diff --git a/src/app/core/auth/models/auth-status.model.ts b/src/app/core/auth/models/auth-status.model.ts index ab03a00745..022e3d7f26 100644 --- a/src/app/core/auth/models/auth-status.model.ts +++ b/src/app/core/auth/models/auth-status.model.ts @@ -42,7 +42,7 @@ export class AuthStatus implements CacheableObject { /** * The eperson of this auth status */ - @link(EPerson) + @link(EPerson.type) eperson: Observable>; /** diff --git a/src/app/core/cache/builders/build-decorators.ts b/src/app/core/cache/builders/build-decorators.ts index 3a3e402966..7dcaa946b2 100644 --- a/src/app/core/cache/builders/build-decorators.ts +++ b/src/app/core/cache/builders/build-decorators.ts @@ -88,23 +88,23 @@ export function getRelationships(target: any) { return relationshipMap.get(target); } -export function dataService(domainModelConstructor: GenericConstructor): any { +export function dataService(resourceType: ResourceType): any { return (target: any) => { - if (hasNoValue(domainModelConstructor)) { - throw new Error(`Invalid @dataService annotation on ${target}, domainModelConstructor needs to be defined`); + if (hasNoValue(resourceType)) { + throw new Error(`Invalid @dataService annotation on ${target}, resourceType needs to be defined`); } - const existingDataservice = dataServiceMap.get(domainModelConstructor); + const existingDataservice = dataServiceMap.get(resourceType.value); if (hasValue(existingDataservice)) { - throw new Error(`Multiple dataservices for ${domainModelConstructor}: ${existingDataservice} and ${target}`); + throw new Error(`Multiple dataservices for ${resourceType.value}: ${existingDataservice} and ${target}`); } - dataServiceMap.set(domainModelConstructor, target); + dataServiceMap.set(resourceType.value, target); }; } -export function getDataServiceFor(domainModelConstructor: GenericConstructor) { - return dataServiceMap.get(domainModelConstructor); +export function getDataServiceFor(resourceType: ResourceType) { + return dataServiceMap.get(resourceType.value); } export function resolvedLink, K extends keyof T>(provider: GenericConstructor, methodName?: K, ...params: any[]): any { @@ -135,20 +135,18 @@ export function getResolvedLinks(target: any) { } export class LinkDefinition { - targetConstructor: GenericConstructor; + resourceType: ResourceType; isList = false; linkName: keyof T['_links']; propertyName: keyof T; } export const link = ( - targetConstructor: GenericConstructor, + resourceType: ResourceType, isList = false, linkName?: keyof T['_links'], ) => { - console.log('link call', targetConstructor, isList, linkName); return (target: T, propertyName: string) => { - console.log('link return', targetConstructor, isList, linkName, target, propertyName); let targetMap = linkMap.get(target.constructor); if (hasNoValue(targetMap)) { @@ -160,7 +158,7 @@ export const link = ( } targetMap.set(propertyName, { - targetConstructor, + resourceType, isList, linkName, propertyName diff --git a/src/app/core/cache/builders/link.service.ts b/src/app/core/cache/builders/link.service.ts index ad64d03d8e..ea01ac6d3f 100644 --- a/src/app/core/cache/builders/link.service.ts +++ b/src/app/core/cache/builders/link.service.ts @@ -21,10 +21,10 @@ export class LinkService { if (hasNoValue(matchingLinkDef)) { throw new Error(`followLink('${linkToFollow.name}') was used for a ${model.constructor.name}, but there is no property on ${model.constructor.name} models with an @link() for ${linkToFollow.name}`); } else { - const provider = getDataServiceFor(matchingLinkDef.targetConstructor); + const provider = getDataServiceFor(matchingLinkDef.resourceType); if (hasNoValue(provider)) { - throw new Error(`The @link() for ${linkToFollow.name} on ${model.constructor.name} models refers to a ${matchingLinkDef.targetConstructor.name}, but there is no service with an @dataService(${matchingLinkDef.targetConstructor.name}) annotation in order to retrieve it`); + throw new Error(`The @link() for ${linkToFollow.name} on ${model.constructor.name} models uses the resource type ${matchingLinkDef.resourceType.value.toUpperCase()}, but there is no service with an @dataService(${matchingLinkDef.resourceType.value.toUpperCase()}) annotation in order to retrieve it`); } const service = Injector.create({ diff --git a/src/app/core/data/bitstream-data.service.ts b/src/app/core/data/bitstream-data.service.ts index c25d641db3..d9f2a941a3 100644 --- a/src/app/core/data/bitstream-data.service.ts +++ b/src/app/core/data/bitstream-data.service.ts @@ -28,7 +28,7 @@ import { RequestService } from './request.service'; @Injectable({ providedIn: 'root' }) -@dataService(Bitstream) +@dataService(Bitstream.type) export class BitstreamDataService extends DataService { protected linkPath = 'bitstreams'; diff --git a/src/app/core/data/bitstream-format-data.service.ts b/src/app/core/data/bitstream-format-data.service.ts index abf4374d0b..bd9b0d72e9 100644 --- a/src/app/core/data/bitstream-format-data.service.ts +++ b/src/app/core/data/bitstream-format-data.service.ts @@ -41,7 +41,7 @@ const selectedBitstreamFormatSelector = createSelector(bitstreamFormatsStateSele * A service responsible for fetching/sending data from/to the REST API on the bitstreamformats endpoint */ @Injectable() -@dataService(BitstreamFormat) +@dataService(BitstreamFormat.type) export class BitstreamFormatDataService extends DataService { protected linkPath = 'bitstreamformats'; diff --git a/src/app/core/data/bundle-data.service.ts b/src/app/core/data/bundle-data.service.ts index 0fb8605cd5..1d82381463 100644 --- a/src/app/core/data/bundle-data.service.ts +++ b/src/app/core/data/bundle-data.service.ts @@ -27,7 +27,7 @@ import { RequestService } from './request.service'; @Injectable( {providedIn: 'root'} ) -@dataService(Bundle) +@dataService(Bundle.type) export class BundleDataService extends DataService { protected linkPath = 'bundles'; protected forceBypassCache = false; diff --git a/src/app/core/data/collection-data.service.ts b/src/app/core/data/collection-data.service.ts index b8c56d62e3..793c6ea4b0 100644 --- a/src/app/core/data/collection-data.service.ts +++ b/src/app/core/data/collection-data.service.ts @@ -49,7 +49,7 @@ import { INotification } from '../../shared/notifications/models/notification.mo import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; @Injectable() -@dataService(Collection) +@dataService(Collection.type) export class CollectionDataService extends ComColDataService { protected linkPath = 'collections'; protected errorTitle = 'collection.source.update.notifications.error.title'; diff --git a/src/app/core/data/community-data.service.ts b/src/app/core/data/community-data.service.ts index 8526584ef9..a9f3300391 100644 --- a/src/app/core/data/community-data.service.ts +++ b/src/app/core/data/community-data.service.ts @@ -21,7 +21,7 @@ import { NormalizedObjectBuildService } from '../cache/builders/normalized-objec import { DSOChangeAnalyzer } from './dso-change-analyzer.service'; @Injectable() -@dataService(Community) +@dataService(Community.type) export class CommunityDataService extends ComColDataService { protected linkPath = 'communities'; protected topLinkPath = 'communities/search/top'; diff --git a/src/app/core/data/dspace-object-data.service.ts b/src/app/core/data/dspace-object-data.service.ts index c4185d5990..dce218ad13 100644 --- a/src/app/core/data/dspace-object-data.service.ts +++ b/src/app/core/data/dspace-object-data.service.ts @@ -39,7 +39,7 @@ class DataServiceImpl extends DataService { } @Injectable() -@dataService(DSpaceObject) +@dataService(DSpaceObject.type) export class DSpaceObjectDataService { protected linkPath = 'dso'; private dataService: DataServiceImpl; diff --git a/src/app/core/data/item-data.service.ts b/src/app/core/data/item-data.service.ts index 32f964cb86..60d6020f36 100644 --- a/src/app/core/data/item-data.service.ts +++ b/src/app/core/data/item-data.service.ts @@ -41,7 +41,7 @@ import { PaginatedList } from './paginated-list'; import { ExternalSourceEntry } from '../shared/external-source-entry.model'; @Injectable() -@dataService(Item) +@dataService(Item.type) export class ItemDataService extends DataService { protected linkPath = 'items'; diff --git a/src/app/core/data/metadata-schema-data.service.ts b/src/app/core/data/metadata-schema-data.service.ts index 98c1ac06e3..edad9f9a56 100644 --- a/src/app/core/data/metadata-schema-data.service.ts +++ b/src/app/core/data/metadata-schema-data.service.ts @@ -1,6 +1,5 @@ import { Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; -import { Observable } from 'rxjs'; import { dataService } from '../cache/builders/build-decorators'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { CoreState } from '../core.reducers'; @@ -8,7 +7,6 @@ import { CoreState } from '../core.reducers'; import { DataService } from './data.service'; import { RequestService } from './request.service'; import { HALEndpointService } from '../shared/hal-endpoint.service'; -import { FindListOptions } from './request.models'; import { ObjectCacheService } from '../cache/object-cache.service'; import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { HttpClient } from '@angular/common/http'; @@ -40,7 +38,7 @@ class DataServiceImpl extends DataService { * A service responsible for fetching/sending data from/to the REST API on the metadataschemas endpoint */ @Injectable() -@dataService(MetadataSchema) +@dataService(MetadataSchema.type) export class MetadataSchemaDataService { private dataService: DataServiceImpl; diff --git a/src/app/core/data/relationship-type.service.ts b/src/app/core/data/relationship-type.service.ts index 5673e751e2..70714a7d84 100644 --- a/src/app/core/data/relationship-type.service.ts +++ b/src/app/core/data/relationship-type.service.ts @@ -28,7 +28,7 @@ import { FindListOptions, FindListRequest } from './request.models'; * The service handling all relationship type requests */ @Injectable() -@dataService(RelationshipType) +@dataService(RelationshipType.type) export class RelationshipTypeService extends DataService { protected linkPath = 'relationshiptypes'; diff --git a/src/app/core/data/relationship.service.ts b/src/app/core/data/relationship.service.ts index e7ce6b6c9e..341a229cfb 100644 --- a/src/app/core/data/relationship.service.ts +++ b/src/app/core/data/relationship.service.ts @@ -47,7 +47,7 @@ const relationshipStateSelector = (listID: string, itemID: string): MemoizedSele * The service handling all relationship requests */ @Injectable() -@dataService(Relationship) +@dataService(Relationship.type) export class RelationshipService extends DataService { protected linkPath = 'relationships'; diff --git a/src/app/core/data/site-data.service.ts b/src/app/core/data/site-data.service.ts index 2191e9fdac..389ab164be 100644 --- a/src/app/core/data/site-data.service.ts +++ b/src/app/core/data/site-data.service.ts @@ -22,7 +22,7 @@ import { getSucceededRemoteData } from '../shared/operators'; * Service responsible for handling requests related to the Site object */ @Injectable() -@dataService(Site) +@dataService(Site.type) export class SiteDataService extends DataService {​ protected linkPath = 'sites'; diff --git a/src/app/core/eperson/eperson-data.service.ts b/src/app/core/eperson/eperson-data.service.ts index c39611d93e..b6d823164e 100644 --- a/src/app/core/eperson/eperson-data.service.ts +++ b/src/app/core/eperson/eperson-data.service.ts @@ -14,7 +14,7 @@ import { HALEndpointService } from '../shared/hal-endpoint.service'; import { EPerson } from './models/eperson.model'; @Injectable() -@dataService(EPerson) +@dataService(EPerson.type) export class EPersonDataService extends DataService { protected linkPath: 'eperson/epersons'; diff --git a/src/app/core/metadata/metadata-field.model.ts b/src/app/core/metadata/metadata-field.model.ts index e034ded2b5..727477db24 100644 --- a/src/app/core/metadata/metadata-field.model.ts +++ b/src/app/core/metadata/metadata-field.model.ts @@ -41,7 +41,7 @@ export class MetadataField extends ListableObject implements HALResource { /** * The metadata schema object of this metadata field */ - @link(MetadataSchema) + @link(MetadataSchema.type) // TODO the responseparsingservice assumes schemas are always embedded. This should be remotedata instead. schema?: MetadataSchema; diff --git a/src/app/core/shared/bitstream.model.ts b/src/app/core/shared/bitstream.model.ts index b5ef7b9d27..4a78e1e195 100644 --- a/src/app/core/shared/bitstream.model.ts +++ b/src/app/core/shared/bitstream.model.ts @@ -34,17 +34,17 @@ export class Bitstream extends DSpaceObject implements HALResource { /** * The Bitstream Format for this Bitstream */ - @link(BitstreamFormat) + @link(BitstreamFormat.type) format?: Observable>; _links: { - // @link(Bitstream) + // @link(Bitstream.type) self: HALLink; - // @link(Bundle) + // @link(Bundle.type) bundle: HALLink; - // @link(BitstreamFormat) + // @link(BitstreamFormat.type) format: HALLink; content: HALLink; diff --git a/src/app/core/shared/collection.model.ts b/src/app/core/shared/collection.model.ts index a2a1df8b4f..aa16a2edab 100644 --- a/src/app/core/shared/collection.model.ts +++ b/src/app/core/shared/collection.model.ts @@ -66,13 +66,13 @@ export class Collection extends DSpaceObject { /** * The Bitstream that represents the logo of this Collection */ - @link(Bitstream) + @link(Bitstream.type) logo?: Observable>; /** * The default access conditions of this Collection */ - @link(ResourcePolicy, true) + @link(ResourcePolicy.type, true) defaultAccessConditions?: Observable>>; _links: { diff --git a/src/app/core/shared/community.model.ts b/src/app/core/shared/community.model.ts index 40edae1159..ffc50d597d 100644 --- a/src/app/core/shared/community.model.ts +++ b/src/app/core/shared/community.model.ts @@ -51,13 +51,13 @@ export class Community extends DSpaceObject { /** * The Bitstream that represents the logo of this Community */ - @link(Bitstream) + @link(Bitstream.type) logo?: Observable>; - @link(Collection, true) + @link(Collection.type, true) collections?: Observable>>; - @link(Community, true) + @link(Community.type, true) subcommunities?: Observable>>; _links: { diff --git a/src/app/core/shared/item-relationships/relationship-type.model.ts b/src/app/core/shared/item-relationships/relationship-type.model.ts index 7f3011de67..cddc89efed 100644 --- a/src/app/core/shared/item-relationships/relationship-type.model.ts +++ b/src/app/core/shared/item-relationships/relationship-type.model.ts @@ -65,13 +65,13 @@ export class RelationshipType implements CacheableObject { /** * The type of Item found to the left of this RelationshipType */ - @link(ItemType) + @link(ItemType.type) leftType?: Observable>; /** * The type of Item found to the right of this RelationshipType */ - @link(ItemType) + @link(ItemType.type) rightType?: Observable>; _links: { diff --git a/src/app/core/shared/item-relationships/relationship.model.ts b/src/app/core/shared/item-relationships/relationship.model.ts index 4cb11e3114..4c6cda84fd 100644 --- a/src/app/core/shared/item-relationships/relationship.model.ts +++ b/src/app/core/shared/item-relationships/relationship.model.ts @@ -3,15 +3,16 @@ import { link } from '../../cache/builders/build-decorators'; import { CacheableObject } from '../../cache/object-cache.reducer'; import { RemoteData } from '../../data/remote-data'; import { HALLink } from '../hal-link.model'; -import { ResourceType } from '../resource-type'; import { RelationshipType } from './relationship-type.model'; import { Item } from '../item.model'; +import { ITEM } from "../item-resource-type"; +import { RELATIONSHIP } from "../relationship.resource-type"; /** * Describes a Relationship between two Items */ export class Relationship implements CacheableObject { - static type = new ResourceType('relationship'); + static type = RELATIONSHIP; /** * The link to the rest endpoint where this object can be found @@ -32,14 +33,13 @@ export class Relationship implements CacheableObject { * The item to the left of this relationship */ - // TODO it's likely a circular dependency 😒 -> https://stackoverflow.com/questions/35240716/webpack-import-returns-undefined-depending-on-the-order-of-imports - @link(Item) + @link(ITEM) leftItem?: Observable>; /** * The item to the right of this relationship */ - @link(Item) + @link(ITEM) rightItem?: Observable>; /** @@ -65,7 +65,7 @@ export class Relationship implements CacheableObject { /** * The type of Relationship */ - @link(RelationshipType) + @link(RelationshipType.type) relationshipType?: Observable>; _links: { diff --git a/src/app/core/shared/item-resource-type.ts b/src/app/core/shared/item-resource-type.ts new file mode 100644 index 0000000000..c21b83fde9 --- /dev/null +++ b/src/app/core/shared/item-resource-type.ts @@ -0,0 +1,9 @@ +import { ResourceType } from "./resource-type"; + +/** + * The resource type for Item. + * + * Needs to be in a separate file to prevent circular + * dependencies in webpack. + */ +export const ITEM = new ResourceType('item'); diff --git a/src/app/core/shared/item.model.ts b/src/app/core/shared/item.model.ts index 3093afbaff..6a4431a9ad 100644 --- a/src/app/core/shared/item.model.ts +++ b/src/app/core/shared/item.model.ts @@ -12,13 +12,14 @@ import { DSpaceObject } from './dspace-object.model'; import { GenericConstructor } from './generic-constructor'; import { HALLink } from './hal-link.model'; import { Relationship } from './item-relationships/relationship.model'; -import { ResourceType } from './resource-type'; +import { ITEM } from "./item-resource-type"; +import { RELATIONSHIP } from "./relationship.resource-type"; /** * Class representing a DSpace Item */ export class Item extends DSpaceObject { - static type = new ResourceType('item'); + static type = ITEM; /** * A string representing the unique handle of this Item @@ -48,13 +49,13 @@ export class Item extends DSpaceObject { /** * The Collection that owns this Item */ - @link(Collection) + @link(Collection.type) owningCollection: Observable>; - @link(Bundle, true) + @link(Bundle.type, true) bundles: Observable>>; - @link(Relationship, true) + @link(RELATIONSHIP) relationships: Observable>>; _links: { diff --git a/src/app/core/shared/relationship.resource-type.ts b/src/app/core/shared/relationship.resource-type.ts new file mode 100644 index 0000000000..afc5526268 --- /dev/null +++ b/src/app/core/shared/relationship.resource-type.ts @@ -0,0 +1,10 @@ +import { ResourceType } from "./resource-type"; + +/** + * The resource type for Relationship. + * + * Needs to be in a separate file to prevent circular + * dependencies in webpack. + */ +export const RELATIONSHIP = new ResourceType('relationship'); + diff --git a/src/app/core/submission/models/submission-object.model.ts b/src/app/core/submission/models/submission-object.model.ts index 86569def0b..b5a9c2f5ee 100644 --- a/src/app/core/submission/models/submission-object.model.ts +++ b/src/app/core/submission/models/submission-object.model.ts @@ -39,13 +39,13 @@ export abstract class SubmissionObject extends DSpaceObject implements Cacheable /** * The collection this submission applies to */ - @link(Collection) + @link(Collection.type) collection?: Observable> | Collection; /** * The submission item */ - @link(Item) + @link(Item.type) item?: Observable> | Item; /** @@ -56,13 +56,13 @@ export abstract class SubmissionObject extends DSpaceObject implements Cacheable /** * The configuration object that define this submission */ - @link(SubmissionDefinitionsModel) + @link(SubmissionDefinitionsModel.type) submissionDefinition?: Observable> | SubmissionDefinitionsModel; /** * The workspaceitem submitter */ - @link(EPerson) + @link(EPerson.type) submitter?: Observable> | EPerson; /** diff --git a/src/app/core/submission/workflowitem-data.service.ts b/src/app/core/submission/workflowitem-data.service.ts index 97e508f56e..41897aba98 100644 --- a/src/app/core/submission/workflowitem-data.service.ts +++ b/src/app/core/submission/workflowitem-data.service.ts @@ -19,7 +19,7 @@ import { DSOChangeAnalyzer } from '../data/dso-change-analyzer.service'; * A service that provides methods to make REST requests with workflowitems endpoint. */ @Injectable() -@dataService(WorkflowItem) +@dataService(WorkflowItem.type) export class WorkflowItemDataService extends DataService { protected linkPath = 'workflowitems'; protected responseMsToLive = 10 * 1000; diff --git a/src/app/core/submission/workspaceitem-data.service.ts b/src/app/core/submission/workspaceitem-data.service.ts index 9dc090aec5..9114882d73 100644 --- a/src/app/core/submission/workspaceitem-data.service.ts +++ b/src/app/core/submission/workspaceitem-data.service.ts @@ -19,7 +19,7 @@ import { WorkspaceItem } from './models/workspaceitem.model'; * A service that provides methods to make REST requests with workspaceitems endpoint. */ @Injectable() -@dataService(WorkspaceItem) +@dataService(WorkspaceItem.type) export class WorkspaceitemDataService extends DataService { protected linkPath = 'workspaceitems'; protected responseMsToLive = 10 * 1000; diff --git a/src/app/core/tasks/claimed-task-data.service.ts b/src/app/core/tasks/claimed-task-data.service.ts index b1deaa99b5..a1d45e8f25 100644 --- a/src/app/core/tasks/claimed-task-data.service.ts +++ b/src/app/core/tasks/claimed-task-data.service.ts @@ -21,7 +21,7 @@ import { ProcessTaskResponse } from './models/process-task-response'; * The service handling all REST requests for ClaimedTask */ @Injectable() -@dataService(ClaimedTask) +@dataService(ClaimedTask.type) export class ClaimedTaskDataService extends TasksService { protected responseMsToLive = 10 * 1000; diff --git a/src/app/core/tasks/models/task-object.model.ts b/src/app/core/tasks/models/task-object.model.ts index 6a94af224f..286a7cf025 100644 --- a/src/app/core/tasks/models/task-object.model.ts +++ b/src/app/core/tasks/models/task-object.model.ts @@ -34,19 +34,19 @@ export class TaskObject extends DSpaceObject implements CacheableObject { /** * The group of this task */ - @link(EPerson) + @link(EPerson.type) eperson?: Observable>; /** * The group of this task */ - @link(Group) + @link(Group.type) group?: Observable>; /** * The workflowitem object whom this task is related */ - @link(WorkflowItem) + @link(WorkflowItem.type) workflowitem?: Observable> | WorkflowItem; _links: { diff --git a/src/app/core/tasks/pool-task-data.service.ts b/src/app/core/tasks/pool-task-data.service.ts index d27cf96e39..21c2733d07 100644 --- a/src/app/core/tasks/pool-task-data.service.ts +++ b/src/app/core/tasks/pool-task-data.service.ts @@ -21,7 +21,7 @@ import { ProcessTaskResponse } from './models/process-task-response'; * The service handling all REST requests for PoolTask */ @Injectable() -@dataService(PoolTask) +@dataService(PoolTask.type) export class PoolTaskDataService extends TasksService { /**