remove normalized models part 1

This commit is contained in:
Art Lowel
2020-02-13 09:53:52 +01:00
parent bffae34fcc
commit 07998a8c08
137 changed files with 1323 additions and 1444 deletions

View File

@@ -135,7 +135,7 @@
"ngx-pagination": "3.0.3", "ngx-pagination": "3.0.3",
"nouislider": "^11.0.0", "nouislider": "^11.0.0",
"pem": "1.13.2", "pem": "1.13.2",
"reflect-metadata": "0.1.12", "reflect-metadata": "^0.1.13",
"rxjs": "6.4.0", "rxjs": "6.4.0",
"rxjs-spy": "^7.5.1", "rxjs-spy": "^7.5.1",
"sass-resources-loader": "^2.0.0", "sass-resources-loader": "^2.0.0",

View File

@@ -22,6 +22,7 @@ import { SEARCH_CONFIG_SERVICE } from '../../+my-dspace-page/my-dspace-page.comp
import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service'; import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service';
import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model';
import { SearchService } from '../../core/shared/search/search.service'; import { SearchService } from '../../core/shared/search/search.service';
import { followLink } from '../../shared/utils/follow-link-config.model';
@Component({ @Component({
selector: 'ds-collection-item-mapper', selector: 'ds-collection-item-mapper',
@@ -122,7 +123,7 @@ export class CollectionItemMapperComponent implements OnInit {
if (shouldUpdate) { if (shouldUpdate) {
return this.collectionDataService.getMappedItems(collectionRD.payload.id, Object.assign(options, { return this.collectionDataService.getMappedItems(collectionRD.payload.id, Object.assign(options, {
sort: this.defaultSortOptions sort: this.defaultSortOptions
})) }),followLink('owningCollection'))
} }
}) })
); );

View File

@@ -10,7 +10,6 @@ import { ObjectCacheService } from '../cache/object-cache.service';
import { ResponseParsingService } from '../data/parsing.service'; import { ResponseParsingService } from '../data/parsing.service';
import { RestRequest } from '../data/request.models'; import { RestRequest } from '../data/request.models';
import { AuthStatus } from './models/auth-status.model'; import { AuthStatus } from './models/auth-status.model';
import { NormalizedAuthStatus } from './models/normalized-auth-status.model';
import { NormalizedObject } from '../cache/models/normalized-object.model'; import { NormalizedObject } from '../cache/models/normalized-object.model';
@Injectable() @Injectable()
@@ -28,7 +27,7 @@ export class AuthResponseParsingService extends BaseResponseParsingService imple
const response = this.process<NormalizedObject<AuthStatus>>(data.payload, request); const response = this.process<NormalizedObject<AuthStatus>>(data.payload, request);
return new AuthStatusResponse(response, data.statusCode, data.statusText); return new AuthStatusResponse(response, data.statusCode, data.statusText);
} else { } else {
return new AuthStatusResponse(data.payload as NormalizedAuthStatus, data.statusCode, data.statusText); return new AuthStatusResponse(data.payload as AuthStatus, data.statusCode, data.statusText);
} }
} }
} }

View File

@@ -1,10 +1,14 @@
import { autoserialize, deserialize, deserializeAs } from 'cerialize';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { link } from '../../cache/builders/build-decorators'; import { link, resourceType } from '../../cache/builders/build-decorators';
import { IDToUUIDSerializer } from '../../cache/id-to-uuid-serializer';
import { CacheableObject } from '../../cache/object-cache.reducer'; import { CacheableObject } from '../../cache/object-cache.reducer';
import { RemoteData } from '../../data/remote-data'; import { RemoteData } from '../../data/remote-data';
import { EPerson } from '../../eperson/models/eperson.model'; import { EPerson } from '../../eperson/models/eperson.model';
import { EPERSON } from '../../eperson/models/eperson.resource-type'; import { EPERSON } from '../../eperson/models/eperson.resource-type';
import { HALLink } from '../../shared/hal-link.model'; import { HALLink } from '../../shared/hal-link.model';
import { ResourceType } from '../../shared/resource-type';
import { excludeFromEquals } from '../../utilities/equals.decorators';
import { AuthError } from './auth-error.model'; import { AuthError } from './auth-error.model';
import { AUTH_STATUS } from './auth-status.resource-type'; import { AUTH_STATUS } from './auth-status.resource-type';
import { AuthTokenInfo } from './auth-token-info.model'; import { AuthTokenInfo } from './auth-token-info.model';
@@ -12,36 +16,55 @@ import { AuthTokenInfo } from './auth-token-info.model';
/** /**
* Object that represents the authenticated status of a user * Object that represents the authenticated status of a user
*/ */
@resourceType(AuthStatus.type)
export class AuthStatus implements CacheableObject { export class AuthStatus implements CacheableObject {
static type = AUTH_STATUS; static type = AUTH_STATUS;
/** /**
* The unique identifier of this auth status * The unique identifier of this auth status
*/ */
@autoserialize
id: string; id: string;
/** /**
* The unique uuid of this auth status * The type for this AuthStatus
*/ */
@excludeFromEquals
@autoserialize
type: ResourceType;
/**
* The UUID of this auth status
* This UUID is generated client-side and isn't used by the backend.
* It is based on the ID, so it will be the same for each refresh.
*/
@deserializeAs(new IDToUUIDSerializer('auth-status'), 'id')
uuid: string; uuid: string;
/** /**
* True if REST API is up and running, should never return false * True if REST API is up and running, should never return false
*/ */
@autoserialize
okay: boolean; okay: boolean;
/** /**
* If the auth status represents an authenticated state * If the auth status represents an authenticated state
*/ */
@autoserialize
authenticated: boolean; authenticated: boolean;
/** /**
* Authentication error if there was one for this status * The HALLinks for this AuthStatus
*/ */
error?: AuthError; @deserialize
_links: {
self: HALLink;
eperson: HALLink;
};
/** /**
* The eperson of this auth status * The EPerson of this auth status
* Will be undefined unless the eperson HALLink has been resolved.
*/ */
@link(EPERSON) @link(EPERSON)
eperson?: Observable<RemoteData<EPerson>>; eperson?: Observable<RemoteData<EPerson>>;
@@ -49,15 +72,12 @@ export class AuthStatus implements CacheableObject {
/** /**
* True if the token is valid, false if there was no token or the token wasn't valid * True if the token is valid, false if there was no token or the token wasn't valid
*/ */
@autoserialize
token?: AuthTokenInfo; token?: AuthTokenInfo;
/** /**
* The self link of this auth status' REST object * Authentication error if there was one for this status
*/ */
self: string; // TODO should be refactored to use the RemoteData error
error?: AuthError;
_links: {
self: HALLink;
eperson: HALLink
}
} }

View File

@@ -1,41 +0,0 @@
import { AuthStatus } from './auth-status.model';
import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize';
import { mapsTo, relationship } from '../../cache/builders/build-decorators';
import { NormalizedObject } from '../../cache/models/normalized-object.model';
import { IDToUUIDSerializer } from '../../cache/id-to-uuid-serializer';
import { EPerson } from '../../eperson/models/eperson.model';
@mapsTo(AuthStatus)
@inheritSerialization(NormalizedObject)
export class NormalizedAuthStatus extends NormalizedObject<AuthStatus> {
/**
* The unique identifier of this auth status
*/
@autoserialize
id: string;
/**
* The unique generated uuid of this auth status
*/
@autoserializeAs(new IDToUUIDSerializer('auth-status'), 'id')
uuid: string;
/**
* True if REST API is up and running, should never return false
*/
@autoserialize
okay: boolean;
/**
* True if the token is valid, false if there was no token or the token wasn't valid
*/
@autoserialize
authenticated: boolean;
/**
* The self link to the eperson of this auth status
*/
@relationship(EPerson, false, false)
@autoserialize
eperson: string;
}

View File

@@ -30,6 +30,21 @@ export function mapsTo(value: GenericConstructor<TypedObject>) {
} }
} }
/**
* Decorator function to map a normalized class to it's not-normalized counter part class
* It will also maps a type to the matching class
* @param value The not-normalized class to map to
*/
// export function resourceType(target: any, key: string) {
// typeMap.set(target.key.value, target.constructor);
// }
export function resourceType(value: ResourceType) {
return function decorator(objectConstructor: GenericConstructor<TypedObject>) {
typeMap.set(value.value, objectConstructor);
}
}
/** /**
* Maps a type to the matching class * Maps a type to the matching class
* @param value The resourse type * @param value The resourse type
@@ -180,3 +195,18 @@ export const getLinkDefinition = <T extends HALResource>(source: GenericConstruc
return undefined; return undefined;
} }
}; };
export const inheritLinkAnnotations = (parent: any): any => {
return (child: any) => {
const parentMap: Map<string, LinkDefinition<any>> = linkMap.get(parent) || new Map();
const childMap: Map<string, LinkDefinition<any>> = linkMap.get(child) || new Map();
parentMap.forEach((value, key) => {
if (!childMap.has(key)) {
childMap.set(key, value);
}
});
linkMap.set(child, childMap);
}
};

View File

@@ -1,5 +1,5 @@
import { Injectable, Injector } from '@angular/core'; import { Injectable, Injector } from '@angular/core';
import { hasNoValue, isNotEmpty } from '../../../shared/empty.util'; import { hasNoValue, hasValue, isNotEmpty } from '../../../shared/empty.util';
import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model'; import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model';
import { GenericConstructor } from '../../shared/generic-constructor'; import { GenericConstructor } from '../../shared/generic-constructor';
import { HALResource } from '../../shared/hal-resource.model'; import { HALResource } from '../../shared/hal-resource.model';
@@ -40,10 +40,14 @@ export class LinkService {
const href = model._links[matchingLinkDef.linkName].href; const href = model._links[matchingLinkDef.linkName].href;
if (matchingLinkDef.isList) { try {
model[linkToFollow.name] = service.findAllByHref(href, linkToFollow.findListOptions, ...linkToFollow.linksToFollow); if (matchingLinkDef.isList) {
} else { model[linkToFollow.name] = service.findAllByHref(href, linkToFollow.findListOptions, ...linkToFollow.linksToFollow);
model[linkToFollow.name] = service.findByHref(href, ...linkToFollow.linksToFollow); } else {
model[linkToFollow.name] = service.findByHref(href, ...linkToFollow.linksToFollow);
}
} catch (e) {
throw new Error(`Something went wrong when using @dataService(${matchingLinkDef.resourceType.value}) ${hasValue(service) ? '' : '(undefined) '}to resolve link ${linkToFollow.name} from ${href}`);
} }
} }
} }

View File

@@ -42,7 +42,7 @@ export class RemoteDataBuildService {
* Creates a single {@link RemoteData} object based on the response of a request to the REST server, with a list of * Creates a single {@link RemoteData} object based on the response of a request to the REST server, with a list of
* {@link FollowLinkConfig} that indicate which embedded info should be added to the object * {@link FollowLinkConfig} that indicate which embedded info should be added to the object
* @param href$ Observable href of object we want to retrieve * @param href$ Observable href of object we want to retrieve
* @param linksToFollow List of {@link FollowLinkConfig} that indicate which embedded info should be added * @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved
*/ */
buildSingle<T extends CacheableObject>(href$: string | Observable<string>, ...linksToFollow: Array<FollowLinkConfig<T>>): Observable<RemoteData<T>> { buildSingle<T extends CacheableObject>(href$: string | Observable<string>, ...linksToFollow: Array<FollowLinkConfig<T>>): Observable<RemoteData<T>> {
if (typeof href$ === 'string') { if (typeof href$ === 'string') {
@@ -126,7 +126,7 @@ export class RemoteDataBuildService {
* Creates a list of {@link RemoteData} objects based on the response of a request to the REST server, with a list of * Creates a list of {@link RemoteData} objects based on the response of a request to the REST server, with a list of
* {@link FollowLinkConfig} that indicate which embedded info should be added to the objects * {@link FollowLinkConfig} that indicate which embedded info should be added to the objects
* @param href$ Observable href of objects we want to retrieve * @param href$ Observable href of objects we want to retrieve
* @param linksToFollow List of {@link FollowLinkConfig} that indicate which embedded info should be added * @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved
*/ */
buildList<T extends CacheableObject>(href$: string | Observable<string>, ...linksToFollow: Array<FollowLinkConfig<T>>): Observable<RemoteData<PaginatedList<T>>> { buildList<T extends CacheableObject>(href$: string | Observable<string>, ...linksToFollow: Array<FollowLinkConfig<T>>): Observable<RemoteData<PaginatedList<T>>> {
if (typeof href$ === 'string') { if (typeof href$ === 'string') {
@@ -229,8 +229,13 @@ export class RemoteDataBuildService {
} }
} }
}); });
let domainModel;
const domainModelConstructor = getMapsTo(normalized.constructor); const domainModelConstructor = getMapsTo(normalized.constructor);
const domainModel = Object.assign(new domainModelConstructor(), normalized, halLinks); if(hasValue(domainModelConstructor) && domainModelConstructor !== normalized.constructor) {
domainModel = Object.assign(new domainModelConstructor(), normalized, halLinks);
} else {
domainModel = normalized;
}
this.linkService.resolveLinks(domainModel, ...linksToFollow); this.linkService.resolveLinks(domainModel, ...linksToFollow);

View File

@@ -1,30 +0,0 @@
import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize';
import { ItemType } from '../../../shared/item-relationships/item-type.model';
import { mapsTo } from '../../builders/build-decorators';
import { NormalizedObject } from '../normalized-object.model';
import { IDToUUIDSerializer } from '../../id-to-uuid-serializer';
/**
* Normalized model class for a DSpace ItemType
*/
@mapsTo(ItemType)
@inheritSerialization(NormalizedObject)
export class NormalizedItemType extends NormalizedObject<ItemType> {
/**
* The label that describes the ResourceType of the Item
*/
@autoserialize
label: string;
/**
* The identifier of this ItemType
*/
@autoserialize
id: string;
/**
* The universally unique identifier of this ItemType
*/
@autoserializeAs(new IDToUUIDSerializer(ItemType.type.value), 'id')
uuid: string;
}

View File

@@ -1,77 +0,0 @@
import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize';
import { RelationshipType } from '../../../shared/item-relationships/relationship-type.model';
import { ResourceType } from '../../../shared/resource-type';
import { mapsTo, relationship } from '../../builders/build-decorators';
import { NormalizedDSpaceObject } from '../normalized-dspace-object.model';
import { NormalizedObject } from '../normalized-object.model';
import { IDToUUIDSerializer } from '../../id-to-uuid-serializer';
import { ItemType } from '../../../shared/item-relationships/item-type.model';
/**
* Normalized model class for a DSpace RelationshipType
*/
@mapsTo(RelationshipType)
@inheritSerialization(NormalizedDSpaceObject)
export class NormalizedRelationshipType extends NormalizedObject<RelationshipType> {
/**
* The identifier of this RelationshipType
*/
@autoserialize
id: string;
/**
* The label that describes the Relation to the left of this RelationshipType
*/
@autoserialize
leftwardType: string;
/**
* The maximum amount of Relationships allowed to the left of this RelationshipType
*/
@autoserialize
leftMaxCardinality: number;
/**
* The minimum amount of Relationships allowed to the left of this RelationshipType
*/
@autoserialize
leftMinCardinality: number;
/**
* The label that describes the Relation to the right of this RelationshipType
*/
@autoserialize
rightwardType: string;
/**
* The maximum amount of Relationships allowed to the right of this RelationshipType
*/
@autoserialize
rightMaxCardinality: number;
/**
* The minimum amount of Relationships allowed to the right of this RelationshipType
*/
@autoserialize
rightMinCardinality: number;
/**
* The type of Item found to the left of this RelationshipType
*/
@autoserialize
@relationship(ItemType, false)
leftType: string;
/**
* The type of Item found to the right of this RelationshipType
*/
@autoserialize
@relationship(ItemType, false)
rightType: string;
/**
* The universally unique identifier of this RelationshipType
*/
@autoserializeAs(new IDToUUIDSerializer(RelationshipType.type.value), 'id')
uuid: string;
}

View File

@@ -1,72 +0,0 @@
import { autoserialize, deserialize, deserializeAs, inheritSerialization } from 'cerialize';
import { Relationship } from '../../../shared/item-relationships/relationship.model';
import { mapsTo, relationship } from '../../builders/build-decorators';
import { NormalizedObject } from '../normalized-object.model';
import { IDToUUIDSerializer } from '../../id-to-uuid-serializer';
import { RelationshipType } from '../../../shared/item-relationships/relationship-type.model';
import { Item } from '../../../shared/item.model';
/**
* Normalized model class for a DSpace Relationship
*/
@mapsTo(Relationship)
@inheritSerialization(NormalizedObject)
export class NormalizedRelationship extends NormalizedObject<Relationship> {
/**
* The identifier of this Relationship
*/
@deserialize
id: string;
/**
* The item to the left of this relationship
*/
@deserialize
@relationship(Item, false, false)
leftItem: string;
/**
* The item to the right of this relationship
*/
@deserialize
@relationship(Item, false, false)
rightItem: string;
/**
* The place of the Item to the left side of this Relationship
*/
@autoserialize
leftPlace: number;
/**
* The place of the Item to the right side of this Relationship
*/
@autoserialize
rightPlace: number;
/**
* The name variant of the Item to the left side of this Relationship
*/
@autoserialize
leftwardValue: string;
/**
* The name variant of the Item to the right side of this Relationship
*/
@autoserialize
rightwardValue: string;
/**
* The type of Relationship
*/
@deserialize
@relationship(RelationshipType, false, false)
relationshipType: string;
/**
* The universally unique identifier of this Relationship
*/
@deserializeAs(new IDToUUIDSerializer(Relationship.type.value), 'id')
uuid: string;
}

View File

@@ -1,65 +0,0 @@
import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize';
import { BitstreamFormat } from '../../shared/bitstream-format.model';
import { mapsTo } from '../builders/build-decorators';
import { IDToUUIDSerializer } from '../id-to-uuid-serializer';
import { NormalizedObject } from './normalized-object.model';
import { BitstreamFormatSupportLevel } from '../../shared/bitstream-format-support-level';
/**
* Normalized model class for a Bitstream Format
*/
@mapsTo(BitstreamFormat)
@inheritSerialization(NormalizedObject)
export class NormalizedBitstreamFormat extends NormalizedObject<BitstreamFormat> {
/**
* Short description of this Bitstream Format
*/
@autoserialize
shortDescription: string;
/**
* Description of this Bitstream Format
*/
@autoserialize
description: string;
/**
* String representing the MIME type of this Bitstream Format
*/
@autoserialize
mimetype: string;
/**
* The level of support the system offers for this Bitstream Format
*/
@autoserialize
supportLevel: BitstreamFormatSupportLevel;
/**
* True if the Bitstream Format is used to store system information, rather than the content of items in the system
*/
@autoserialize
internal: boolean;
/**
* String representing this Bitstream Format's file extension
*/
@autoserialize
extensions: string[];
/**
* Identifier for this Bitstream Format
* Note that this ID is unique for bitstream formats,
* but might not be unique across different object types
*/
@autoserialize
id: string;
/**
* Universally unique identifier for this Bitstream Format
* Consist of a prefix and the id field to ensure the identifier is unique across all object types
*/
@autoserializeAs(new IDToUUIDSerializer('bitstream-format'), 'id')
uuid: string;
}

View File

@@ -1,61 +0,0 @@
import { autoserialize, inheritSerialization } from 'cerialize';
import { NormalizedDSpaceObject } from './normalized-dspace-object.model';
import { Bitstream } from '../../shared/bitstream.model';
import { mapsTo, relationship } from '../builders/build-decorators';
import { Item } from '../../shared/item.model';
import { BitstreamFormat } from '../../shared/bitstream-format.model';
/**
* Normalized model class for a DSpace Bitstream
*/
@mapsTo(Bitstream)
@inheritSerialization(NormalizedDSpaceObject)
export class NormalizedBitstream extends NormalizedDSpaceObject<Bitstream> {
/**
* The size of this bitstream in bytes
*/
@autoserialize
sizeBytes: number;
/**
* The relative path to this Bitstream's file
*/
@autoserialize
@relationship(Bitstream, false, false)
content: string;
/**
* The format of this Bitstream
*/
@autoserialize
@relationship(BitstreamFormat, false, false)
format: string;
/**
* The description of this Bitstream
*/
@autoserialize
description: string;
/**
* An array of Bundles that are direct parents of this Bitstream
*/
@autoserialize
@relationship(Item, true, false)
parents: string[];
/**
* The Bundle that owns this Bitstream
*/
@autoserialize
@relationship(Item, false, false)
owner: string;
/**
* The name of the Bundle this Bitstream is part of
*/
@autoserialize
bundleName: string;
}

View File

@@ -1,35 +0,0 @@
import { autoserialize, inheritSerialization } from 'cerialize';
import { Bitstream } from '../../shared/bitstream.model';
import { Bundle } from '../../shared/bundle.model';
import { mapsTo, relationship } from '../builders/build-decorators';
import { NormalizedDSpaceObject } from './normalized-dspace-object.model';
/**
* Normalized model class for a DSpace Bundle
*/
@mapsTo(Bundle)
@inheritSerialization(NormalizedDSpaceObject)
export class NormalizedBundle extends NormalizedDSpaceObject<Bundle> {
/**
* The bundle's name
*/
@autoserialize
name: string;
/**
* The primary bitstream of this Bundle
*/
@autoserialize
@relationship(Bitstream, false, false)
primaryBitstream: string;
/**
* List of Bitstreams that are part of this Bundle
*/
@autoserialize
@relationship(Bitstream, true, false)
bitstreams: string[];
}

View File

@@ -1,50 +0,0 @@
import { autoserialize, deserialize, inheritSerialization } from 'cerialize';
import { Bitstream } from '../../shared/bitstream.model';
import { Collection } from '../../shared/collection.model';
import { Item } from '../../shared/item.model';
import { ResourcePolicy } from '../../shared/resource-policy.model';
import { mapsTo, relationship } from '../builders/build-decorators';
import { NormalizedDSpaceObject } from './normalized-dspace-object.model';
/**
* Normalized model class for a DSpace Collection
*/
@mapsTo(Collection)
@inheritSerialization(NormalizedDSpaceObject)
export class NormalizedCollection extends NormalizedDSpaceObject<Collection> {
/**
* A string representing the unique handle of this Collection
*/
@autoserialize
handle: string;
/**
* The Bitstream that represents the license of this Collection
*/
@autoserialize
license: string;
/**
* The Bitstream that represents the default Access Conditions of this Collection
*/
@autoserialize
@relationship(ResourcePolicy, false, false)
defaultAccessConditions: string;
/**
* The Bitstream that represents the logo of this Collection
*/
@deserialize
@relationship(Bitstream, false, false)
logo: string;
/**
* List of Items that are part of (not necessarily owned by) this Collection
*/
@deserialize
@relationship(Item, true, false)
items: string[];
}

View File

@@ -1,56 +0,0 @@
import { autoserialize, deserialize, inheritSerialization } from 'cerialize';
import { NormalizedDSpaceObject } from './normalized-dspace-object.model';
import { Community } from '../../shared/community.model';
import { mapsTo, relationship } from '../builders/build-decorators';
import { ResourceType } from '../../shared/resource-type';
import { NormalizedBitstream } from './normalized-bitstream.model';
import { NormalizedCollection } from './normalized-collection.model';
import { Bitstream } from '../../shared/bitstream.model';
import { Collection } from '../../shared/collection.model';
/**
* Normalized model class for a DSpace Community
*/
@mapsTo(Community)
@inheritSerialization(NormalizedDSpaceObject)
export class NormalizedCommunity extends NormalizedDSpaceObject<Community> {
/**
* A string representing the unique handle of this Community
*/
@autoserialize
handle: string;
/**
* The Bitstream that represents the logo of this Community
*/
@deserialize
@relationship(Bitstream, false, false)
logo: string;
/**
* An array of Communities that are direct parents of this Community
*/
@deserialize
@relationship(Community, true, false)
parents: string[];
/**
* The Community that owns this Community
*/
@deserialize
@relationship(Community, false, false)
owner: string;
/**
* List of Collections that are owned by this Community
*/
@deserialize
@relationship(Collection, true, false)
collections: string[];
@deserialize
@relationship(Community, true, false)
subcommunities: string[];
}

View File

@@ -2,14 +2,13 @@ import { autoserializeAs, deserializeAs, autoserialize } from 'cerialize';
import { DSpaceObject } from '../../shared/dspace-object.model'; import { DSpaceObject } from '../../shared/dspace-object.model';
import { HALLink } from '../../shared/hal-link.model'; import { HALLink } from '../../shared/hal-link.model';
import { MetadataMap, MetadataMapSerializer } from '../../shared/metadata.models'; import { MetadataMap, MetadataMapSerializer } from '../../shared/metadata.models';
import { mapsTo } from '../builders/build-decorators'; import { ResourceType } from '../../shared/resource-type';
import { NormalizedObject } from './normalized-object.model'; import { NormalizedObject } from './normalized-object.model';
import { TypedObject } from '../object-cache.reducer'; import { TypedObject } from '../object-cache.reducer';
/** /**
* An model class for a DSpaceObject. * An model class for a DSpaceObject.
*/ */
@mapsTo(DSpaceObject)
export class NormalizedDSpaceObject<T extends DSpaceObject> extends NormalizedObject<T> implements TypedObject { export class NormalizedDSpaceObject<T extends DSpaceObject> extends NormalizedObject<T> implements TypedObject {
/** /**
@@ -37,10 +36,10 @@ export class NormalizedDSpaceObject<T extends DSpaceObject> extends NormalizedOb
uuid: string; uuid: string;
/** /**
* A string representing the kind of DSpaceObject, e.g. community, item, … * The type of the object
*/ */
@autoserialize @autoserialize
type: string; type: ResourceType;
/** /**
* All metadata of this DSpaceObject * All metadata of this DSpaceObject

View File

@@ -1,42 +0,0 @@
import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize';
import { NormalizedObject } from './normalized-object.model';
import { ExternalSourceEntry } from '../../shared/external-source-entry.model';
import { mapsTo } from '../builders/build-decorators';
import { MetadataMap, MetadataMapSerializer } from '../../shared/metadata.models';
/**
* Normalized model class for an external source entry
*/
@mapsTo(ExternalSourceEntry)
@inheritSerialization(NormalizedObject)
export class NormalizedExternalSourceEntry extends NormalizedObject<ExternalSourceEntry> {
/**
* Unique identifier
*/
@autoserialize
id: string;
/**
* The value to display
*/
@autoserialize
display: string;
/**
* The value to store the entry with
*/
@autoserialize
value: string;
/**
* The ID of the external source this entry originates from
*/
@autoserialize
externalSource: string;
/**
* Metadata of the entry
*/
@autoserializeAs(MetadataMapSerializer)
metadata: MetadataMap;
}

View File

@@ -1,29 +0,0 @@
import { autoserialize, inheritSerialization } from 'cerialize';
import { NormalizedObject } from './normalized-object.model';
import { ExternalSource } from '../../shared/external-source.model';
import { mapsTo } from '../builders/build-decorators';
/**
* Normalized model class for an external source
*/
@mapsTo(ExternalSource)
@inheritSerialization(NormalizedObject)
export class NormalizedExternalSource extends NormalizedObject<ExternalSource> {
/**
* Unique identifier
*/
@autoserialize
id: string;
/**
* The name of this external source
*/
@autoserialize
name: string;
/**
* Is the source hierarchical?
*/
@autoserialize
hierarchical: boolean;
}

View File

@@ -1,65 +0,0 @@
import { inheritSerialization, deserialize, autoserialize, autoserializeAs } from 'cerialize';
import { NormalizedDSpaceObject } from './normalized-dspace-object.model';
import { Item } from '../../shared/item.model';
import { mapsTo, relationship } from '../builders/build-decorators';
import { Collection } from '../../shared/collection.model';
import { Relationship } from '../../shared/item-relationships/relationship.model';
import { Bundle } from '../../shared/bundle.model';
/**
* Normalized model class for a DSpace Item
*/
@mapsTo(Item)
@inheritSerialization(NormalizedDSpaceObject)
export class NormalizedItem extends NormalizedDSpaceObject<Item> {
/**
* A string representing the unique handle of this Item
*/
@autoserialize
handle: string;
/**
* The Date of the last modification of this Item
*/
@deserialize
lastModified: Date;
/**
* A boolean representing if this Item is currently archived or not
*/
@autoserializeAs(Boolean, 'inArchive')
isArchived: boolean;
/**
* A boolean representing if this Item is currently discoverable or not
*/
@autoserializeAs(Boolean, 'discoverable')
isDiscoverable: boolean;
/**
* A boolean representing if this Item is currently withdrawn or not
*/
@autoserializeAs(Boolean, 'withdrawn')
isWithdrawn: boolean;
/**
* The Collection that owns this Item
*/
@deserialize
@relationship(Collection, false, false)
owningCollection: string;
/**
* List of Bitstreams that are owned by this Item
*/
@deserialize
@relationship(Bundle, true, false)
bundles: string[];
@deserialize
@relationship(Relationship, true, false)
relationships: string[];
}

View File

@@ -1,24 +0,0 @@
import { autoserialize, inheritSerialization } from 'cerialize';
import { mapsTo } from '../builders/build-decorators';
import { NormalizedDSpaceObject } from './normalized-dspace-object.model';
import { License } from '../../shared/license.model';
/**
* Normalized model class for a Collection License
*/
@mapsTo(License)
@inheritSerialization(NormalizedDSpaceObject)
export class NormalizedLicense extends NormalizedDSpaceObject<License> {
/**
* A boolean representing if this License is custom or not
*/
@autoserialize
custom: boolean;
/**
* The text of the license
*/
@autoserialize
text: string;
}

View File

@@ -22,5 +22,5 @@ export abstract class NormalizedObject<T extends TypedObject> implements Cacheab
* A string representing the kind of object * A string representing the kind of object
*/ */
@deserialize @deserialize
type: string; type: ResourceType;
} }

View File

@@ -1,48 +0,0 @@
import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize';
import { ResourcePolicy } from '../../shared/resource-policy.model';
import { mapsTo } from '../builders/build-decorators';
import { NormalizedObject } from './normalized-object.model';
import { IDToUUIDSerializer } from '../id-to-uuid-serializer';
import { ActionType } from './action-type.model';
/**
* Normalized model class for a Resource Policy
*/
@mapsTo(ResourcePolicy)
@inheritSerialization(NormalizedObject)
export class NormalizedResourcePolicy extends NormalizedObject<ResourcePolicy> {
/**
* The action that is allowed by this Resource Policy
*/
@autoserialize
action: ActionType;
/**
* The name for this Resource Policy
*/
@autoserialize
name: string;
/**
* The uuid of the Group this Resource Policy applies to
*/
@autoserialize
groupUUID: string;
/**
* Identifier for this Resource Policy
* Note that this ID is unique for resource policies,
* but might not be unique across different object types
*/
@autoserialize
id: string;
/**
* The universally unique identifier for this Resource Policy
* Consist of a prefix and the id field to ensure the identifier is unique across all object types
*/
@autoserializeAs(new IDToUUIDSerializer('resource-policy'), 'id')
uuid: string;
}

View File

@@ -1,13 +0,0 @@
import { inheritSerialization } from 'cerialize';
import { NormalizedDSpaceObject } from './normalized-dspace-object.model';
import { mapsTo } from '../builders/build-decorators';
import { Site } from '../../shared/site.model';
/**
* Normalized model class for a Site object
*/
@mapsTo(Site)
@inheritSerialization(NormalizedDSpaceObject)
export class NormalizedSite extends NormalizedDSpaceObject<Site> {
}

View File

@@ -1,5 +1,7 @@
import { autoserialize, deserialize } from 'cerialize';
import { HALLink } from '../shared/hal-link.model'; import { HALLink } from '../shared/hal-link.model';
import { HALResource } from '../shared/hal-resource.model'; import { HALResource } from '../shared/hal-resource.model';
import { excludeFromEquals } from '../utilities/equals.decorators';
import { import {
ObjectCacheAction, ObjectCacheAction,
ObjectCacheActionTypes, ObjectCacheActionTypes,
@@ -36,6 +38,7 @@ export interface Patch {
export abstract class TypedObject { export abstract class TypedObject {
static type: ResourceType; static type: ResourceType;
type: ResourceType;
} }
/* tslint:disable:max-classes-per-file */ /* tslint:disable:max-classes-per-file */
@@ -47,7 +50,6 @@ export abstract class TypedObject {
export class CacheableObject extends TypedObject implements HALResource { export class CacheableObject extends TypedObject implements HALResource {
uuid?: string; uuid?: string;
handle?: string; handle?: string;
self: string;
_links: { _links: {
self: HALLink; self: HALLink;
@@ -135,9 +137,9 @@ export function objectCacheReducer(state = initialState, action: ObjectCacheActi
* the new state, with the object added, or overwritten. * the new state, with the object added, or overwritten.
*/ */
function addToObjectCache(state: ObjectCacheState, action: AddToObjectCacheAction): ObjectCacheState { function addToObjectCache(state: ObjectCacheState, action: AddToObjectCacheAction): ObjectCacheState {
const existing = state[action.payload.objectToCache.self]; const existing = state[action.payload.objectToCache._links.self.href];
return Object.assign({}, state, { return Object.assign({}, state, {
[action.payload.objectToCache.self]: { [action.payload.objectToCache._links.self.href]: {
data: action.payload.objectToCache, data: action.payload.objectToCache,
timeAdded: action.payload.timeAdded, timeAdded: action.payload.timeAdded,
msToLive: action.payload.msToLive, msToLive: action.payload.msToLive,

View File

@@ -6,7 +6,6 @@ import { first } from 'rxjs/operators';
import { CoreState } from '../core.reducers'; import { CoreState } from '../core.reducers';
import { RestRequestMethod } from '../data/rest-request-method'; import { RestRequestMethod } from '../data/rest-request-method';
import { Item } from '../shared/item.model'; import { Item } from '../shared/item.model';
import { NormalizedItem } from './models/normalized-item.model';
import { import {
AddPatchObjectCacheAction, AddPatchObjectCacheAction,
AddToObjectCacheAction, AddToObjectCacheAction,
@@ -95,7 +94,7 @@ describe('ObjectCacheService', () => {
service.getObjectBySelfLink(selfLink).pipe(first()).subscribe((o) => { service.getObjectBySelfLink(selfLink).pipe(first()).subscribe((o) => {
expect(o.self).toBe(selfLink); expect(o.self).toBe(selfLink);
// this only works if testObj is an instance of TestClass // this only works if testObj is an instance of TestClass
expect(o instanceof NormalizedItem).toBeTruthy(); expect(o instanceof Item).toBeTruthy();
} }
); );
}); });

View File

@@ -116,6 +116,9 @@ export class ObjectCacheService {
), ),
map((entry: ObjectCacheEntry) => { map((entry: ObjectCacheEntry) => {
const type: GenericConstructor<NormalizedObject<T>> = getMapsToType((entry.data as any).type); const type: GenericConstructor<NormalizedObject<T>> = getMapsToType((entry.data as any).type);
if (typeof type !== 'function') {
throw new Error(`${type} is not a valid constructor for ${JSON.stringify(entry.data)}`);
}
return Object.assign(new type(), entry.data) as NormalizedObject<T> return Object.assign(new type(), entry.data) as NormalizedObject<T>
}) })
); );
@@ -259,7 +262,7 @@ export class ObjectCacheService {
const timeOutdated = entry.timeAdded + entry.msToLive; const timeOutdated = entry.timeAdded + entry.msToLive;
const isOutDated = new Date().getTime() > timeOutdated; const isOutDated = new Date().getTime() > timeOutdated;
if (isOutDated) { if (isOutDated) {
this.store.dispatch(new RemoveFromObjectCacheAction(entry.data.self)); this.store.dispatch(new RemoveFromObjectCacheAction(entry.data._links.self.href));
} }
return !isOutDated; return !isOutDated;
} }

View File

@@ -1,4 +1,5 @@
import { SearchQueryResponse } from '../../shared/search/search-query-response.model'; import { SearchQueryResponse } from '../../shared/search/search-query-response.model';
import { AuthStatus } from '../auth/models/auth-status.model';
import { RequestError } from '../data/request.models'; import { RequestError } from '../data/request.models';
import { PageInfo } from '../shared/page-info.model'; import { PageInfo } from '../shared/page-info.model';
import { ConfigObject } from '../config/models/config.model'; import { ConfigObject } from '../config/models/config.model';
@@ -11,7 +12,6 @@ import { RegistryBitstreamformatsResponse } from '../registry/registry-bitstream
import { PaginatedList } from '../data/paginated-list'; import { PaginatedList } from '../data/paginated-list';
import { SubmissionObject } from '../submission/models/submission-object.model'; import { SubmissionObject } from '../submission/models/submission-object.model';
import { DSpaceObject } from '../shared/dspace-object.model'; import { DSpaceObject } from '../shared/dspace-object.model';
import { NormalizedAuthStatus } from '../auth/models/normalized-auth-status.model';
import { MetadataSchema } from '../metadata/metadata-schema.model'; import { MetadataSchema } from '../metadata/metadata-schema.model';
import { MetadataField } from '../metadata/metadata-field.model'; import { MetadataField } from '../metadata/metadata-field.model';
import { ContentSource } from '../shared/content-source.model'; import { ContentSource } from '../shared/content-source.model';
@@ -203,7 +203,7 @@ export class AuthStatusResponse extends RestResponse {
public toCache = false; public toCache = false;
constructor( constructor(
public response: NormalizedAuthStatus, public response: AuthStatus,
public statusCode: number, public statusCode: number,
public statusText: string, public statusText: string,
) { ) {

View File

@@ -18,7 +18,7 @@ import { RequestService } from '../data/request.service';
import { PutRequest } from '../data/request.models'; import { PutRequest } from '../data/request.models';
import { ObjectCacheService } from './object-cache.service'; import { ObjectCacheService } from './object-cache.service';
import { ApplyPatchObjectCacheAction } from './object-cache.actions'; import { ApplyPatchObjectCacheAction } from './object-cache.actions';
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer';
import { GenericConstructor } from '../shared/generic-constructor'; import { GenericConstructor } from '../shared/generic-constructor';
import { hasValue, isNotEmpty, isNotUndefined } from '../../shared/empty.util'; import { hasValue, isNotEmpty, isNotUndefined } from '../../shared/empty.util';
import { Observable } from 'rxjs/internal/Observable'; import { Observable } from 'rxjs/internal/Observable';
@@ -100,7 +100,7 @@ export class ServerSyncBufferEffects {
return patchObject.pipe( return patchObject.pipe(
map((object) => { map((object) => {
const serializedObject = new DSpaceRESTv2Serializer(object.constructor as GenericConstructor<{}>).serialize(object); const serializedObject = new NormalizedObjectSerializer(object.constructor as GenericConstructor<{}>).serialize(object);
this.requestService.configure(new PutRequest(this.requestService.generateRequestId(), href, serializedObject)); this.requestService.configure(new PutRequest(this.requestService.generateRequestId(), href, serializedObject));

View File

@@ -1,3 +1,5 @@
import { autoserialize, deserialize } from 'cerialize';
import { resourceType } from '../../cache/builders/build-decorators';
import { PaginatedList } from '../../data/paginated-list'; import { PaginatedList } from '../../data/paginated-list';
import { HALLink } from '../../shared/hal-link.model'; import { HALLink } from '../../shared/hal-link.model';
import { ResourceType } from '../../shared/resource-type'; import { ResourceType } from '../../shared/resource-type';
@@ -7,22 +9,27 @@ import { ConfigObject } from './config.model';
/** /**
* Class for the configuration describing the submission * Class for the configuration describing the submission
*/ */
@resourceType(SubmissionDefinitionModel.type)
export class SubmissionDefinitionModel extends ConfigObject { export class SubmissionDefinitionModel extends ConfigObject {
static type = new ResourceType('submissiondefinition'); static type = new ResourceType('submissiondefinition');
/** /**
* A boolean representing if this submission definition is the default or not * A boolean representing if this submission definition is the default or not
*/ */
@autoserialize
isDefault: boolean; isDefault: boolean;
/** /**
* A list of SubmissionSectionModel that are present in this submission definition * A list of SubmissionSectionModel that are present in this submission definition
*/ */
// TODO refactor using remotedata
@deserialize
sections: PaginatedList<SubmissionSectionModel>; sections: PaginatedList<SubmissionSectionModel>;
/** /**
* The links to all related resources returned by the rest api. * The links to all related resources returned by the rest api.
*/ */
@deserialize
_links: { _links: {
self: HALLink, self: HALLink,
collections: HALLink, collections: HALLink,

View File

@@ -1,6 +1,8 @@
import { resourceType } from '../../cache/builders/build-decorators';
import { SubmissionDefinitionModel } from './config-submission-definition.model'; import { SubmissionDefinitionModel } from './config-submission-definition.model';
import { ResourceType } from '../../shared/resource-type'; import { ResourceType } from '../../shared/resource-type';
@resourceType(SubmissionDefinitionsModel.type)
export class SubmissionDefinitionsModel extends SubmissionDefinitionModel { export class SubmissionDefinitionsModel extends SubmissionDefinitionModel {
static type = new ResourceType('submissiondefinitions'); static type = new ResourceType('submissiondefinitions');

View File

@@ -1,3 +1,5 @@
import { autoserialize, inheritSerialization } from 'cerialize';
import { resourceType } from '../../cache/builders/build-decorators';
import { ConfigObject } from './config.model'; import { ConfigObject } from './config.model';
import { FormFieldModel } from '../../../shared/form/builder/models/form-field.model'; import { FormFieldModel } from '../../../shared/form/builder/models/form-field.model';
import { ResourceType } from '../../shared/resource-type'; import { ResourceType } from '../../shared/resource-type';
@@ -12,11 +14,14 @@ export interface FormRowModel {
/** /**
* A model class for a NormalizedObject. * A model class for a NormalizedObject.
*/ */
@resourceType(SubmissionFormModel.type)
@inheritSerialization(ConfigObject)
export class SubmissionFormModel extends ConfigObject { export class SubmissionFormModel extends ConfigObject {
static type = new ResourceType('submissionform'); static type = new ResourceType('submissionform');
/** /**
* An array of [FormRowModel] that are present in this form * An array of [FormRowModel] that are present in this form
*/ */
@autoserialize
rows: FormRowModel[]; rows: FormRowModel[];
} }

View File

@@ -1,9 +1,11 @@
import { resourceType } from '../../cache/builders/build-decorators';
import { SubmissionFormModel } from './config-submission-form.model'; import { SubmissionFormModel } from './config-submission-form.model';
import { ResourceType } from '../../shared/resource-type'; import { ResourceType } from '../../shared/resource-type';
/** /**
* A model class for a NormalizedObject. * A model class for a NormalizedObject.
*/ */
@resourceType(SubmissionFormsModel.type)
export class SubmissionFormsModel extends SubmissionFormModel { export class SubmissionFormsModel extends SubmissionFormModel {
static type = new ResourceType('submissionforms'); static type = new ResourceType('submissionforms');
} }

View File

@@ -1,3 +1,6 @@
import { autoserialize, deserialize } from 'cerialize';
import { resourceType } from '../../cache/builders/build-decorators';
import { HALLink } from '../../shared/hal-link.model';
import { ConfigObject } from './config.model'; import { ConfigObject } from './config.model';
import { SectionsType } from '../../../submission/sections/sections-type'; import { SectionsType } from '../../../submission/sections/sections-type';
import { ResourceType } from '../../shared/resource-type'; import { ResourceType } from '../../shared/resource-type';
@@ -10,27 +13,40 @@ export interface SubmissionSectionVisibility {
other: any other: any
} }
@resourceType(SubmissionSectionModel.type)
export class SubmissionSectionModel extends ConfigObject { export class SubmissionSectionModel extends ConfigObject {
static type = new ResourceType('submissionsection'); static type = new ResourceType('submissionsection');
/** /**
* The header for this section * The header for this section
*/ */
@autoserialize
header: string; header: string;
/** /**
* A boolean representing if this submission section is the mandatory or not * A boolean representing if this submission section is the mandatory or not
*/ */
@autoserialize
mandatory: boolean; mandatory: boolean;
/** /**
* A string representing the kind of section object * A string representing the kind of section object
*/ */
@autoserialize
sectionType: SectionsType; sectionType: SectionsType;
/** /**
* The [SubmissionSectionVisibility] object for this section * The [SubmissionSectionVisibility] object for this section
*/ */
visibility: SubmissionSectionVisibility @autoserialize
visibility: SubmissionSectionVisibility;
/**
* The HALLinks for this SubmissionSectionModel
*/
@deserialize
_links: {
self: HALLink;
}
} }

View File

@@ -1,6 +1,8 @@
import { resourceType } from '../../cache/builders/build-decorators';
import { SubmissionSectionModel } from './config-submission-section.model'; import { SubmissionSectionModel } from './config-submission-section.model';
import { ResourceType } from '../../shared/resource-type'; import { ResourceType } from '../../shared/resource-type';
@resourceType(SubmissionSectionsModel.type)
export class SubmissionSectionsModel extends SubmissionSectionModel { export class SubmissionSectionsModel extends SubmissionSectionModel {
static type = new ResourceType('submissionsections'); static type = new ResourceType('submissionsections');
} }

View File

@@ -1,8 +1,10 @@
import { resourceType } from '../../cache/builders/build-decorators';
import { ConfigObject } from './config.model'; import { ConfigObject } from './config.model';
import { AccessConditionOption } from './config-access-condition-option.model'; import { AccessConditionOption } from './config-access-condition-option.model';
import { SubmissionFormsModel } from './config-submission-forms.model'; import { SubmissionFormsModel } from './config-submission-forms.model';
import { ResourceType } from '../../shared/resource-type'; import { ResourceType } from '../../shared/resource-type';
@resourceType(SubmissionUploadsModel.type)
export class SubmissionUploadsModel extends ConfigObject { export class SubmissionUploadsModel extends ConfigObject {
static type = new ResourceType('submissionupload'); static type = new ResourceType('submissionupload');
/** /**

View File

@@ -1,5 +1,8 @@
import { autoserialize, deserialize } from 'cerialize';
import { CacheableObject } from '../../cache/object-cache.reducer'; import { CacheableObject } from '../../cache/object-cache.reducer';
import { HALLink } from '../../shared/hal-link.model'; import { HALLink } from '../../shared/hal-link.model';
import { ResourceType } from '../../shared/resource-type';
import { excludeFromEquals } from '../../utilities/equals.decorators';
export abstract class ConfigObject implements CacheableObject { export abstract class ConfigObject implements CacheableObject {
@@ -8,16 +11,19 @@ export abstract class ConfigObject implements CacheableObject {
*/ */
public name: string; public name: string;
/**
* The type of this ConfigObject
*/
@excludeFromEquals
@autoserialize
type: ResourceType;
/** /**
* The links to all related resources returned by the rest api. * The links to all related resources returned by the rest api.
*/ */
@deserialize
_links: { _links: {
self: HALLink, self: HALLink,
[name: string]: HALLink [name: string]: HALLink
}; };
/**
* The link to the rest endpoint where this config object can be found
*/
self: string;
} }

View File

@@ -1,5 +1,4 @@
import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize'; import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize';
import { mapsTo } from '../../cache/builders/build-decorators';
import { PaginatedList } from '../../data/paginated-list'; import { PaginatedList } from '../../data/paginated-list';
import { SubmissionDefinitionModel } from './config-submission-definition.model'; import { SubmissionDefinitionModel } from './config-submission-definition.model';
import { SubmissionSectionModel } from './config-submission-section.model'; import { SubmissionSectionModel } from './config-submission-section.model';
@@ -8,7 +7,6 @@ import { NormalizedConfigObject } from './normalized-config.model';
/** /**
* Normalized class for the configuration describing the submission * Normalized class for the configuration describing the submission
*/ */
@mapsTo(SubmissionDefinitionModel)
@inheritSerialization(NormalizedConfigObject) @inheritSerialization(NormalizedConfigObject)
export class NormalizedSubmissionDefinitionModel extends NormalizedConfigObject<SubmissionDefinitionModel> { export class NormalizedSubmissionDefinitionModel extends NormalizedConfigObject<SubmissionDefinitionModel> {

View File

@@ -1,13 +1,11 @@
import { inheritSerialization } from 'cerialize'; import { inheritSerialization } from 'cerialize';
import { NormalizedConfigObject } from './normalized-config.model'; import { NormalizedConfigObject } from './normalized-config.model';
import { SubmissionDefinitionsModel } from './config-submission-definitions.model'; import { SubmissionDefinitionsModel } from './config-submission-definitions.model';
import { mapsTo } from '../../cache/builders/build-decorators';
import { NormalizedSubmissionDefinitionModel } from './normalized-config-submission-definition.model'; import { NormalizedSubmissionDefinitionModel } from './normalized-config-submission-definition.model';
/** /**
* Normalized class for the configuration describing the submission * Normalized class for the configuration describing the submission
*/ */
@mapsTo(SubmissionDefinitionsModel)
@inheritSerialization(NormalizedConfigObject) @inheritSerialization(NormalizedConfigObject)
export class NormalizedSubmissionDefinitionsModel extends NormalizedSubmissionDefinitionModel { export class NormalizedSubmissionDefinitionsModel extends NormalizedSubmissionDefinitionModel {
} }

View File

@@ -1,12 +1,10 @@
import { autoserialize, inheritSerialization } from 'cerialize'; import { autoserialize, inheritSerialization } from 'cerialize';
import { NormalizedConfigObject } from './normalized-config.model'; import { NormalizedConfigObject } from './normalized-config.model';
import { mapsTo } from '../../cache/builders/build-decorators';
import { FormRowModel, SubmissionFormModel } from './config-submission-form.model'; import { FormRowModel, SubmissionFormModel } from './config-submission-form.model';
/** /**
* Normalized class for the configuration describing the submission form * Normalized class for the configuration describing the submission form
*/ */
@mapsTo(SubmissionFormModel)
@inheritSerialization(NormalizedConfigObject) @inheritSerialization(NormalizedConfigObject)
export class NormalizedSubmissionFormModel extends NormalizedConfigObject<SubmissionFormModel> { export class NormalizedSubmissionFormModel extends NormalizedConfigObject<SubmissionFormModel> {

View File

@@ -1,12 +1,9 @@
import { inheritSerialization } from 'cerialize'; import { inheritSerialization } from 'cerialize';
import { mapsTo } from '../../cache/builders/build-decorators';
import { SubmissionFormsModel } from './config-submission-forms.model';
import { NormalizedSubmissionFormModel } from './normalized-config-submission-form.model'; import { NormalizedSubmissionFormModel } from './normalized-config-submission-form.model';
/** /**
* Normalized class for the configuration describing the submission form * Normalized class for the configuration describing the submission form
*/ */
@mapsTo(SubmissionFormsModel)
@inheritSerialization(NormalizedSubmissionFormModel) @inheritSerialization(NormalizedSubmissionFormModel)
export class NormalizedSubmissionFormsModel extends NormalizedSubmissionFormModel { export class NormalizedSubmissionFormsModel extends NormalizedSubmissionFormModel {
} }

View File

@@ -5,12 +5,9 @@ import {
SubmissionSectionModel, SubmissionSectionModel,
SubmissionSectionVisibility SubmissionSectionVisibility
} from './config-submission-section.model'; } from './config-submission-section.model';
import { mapsTo } from '../../cache/builders/build-decorators';
/** /**
* Normalized class for the configuration describing the submission section * Normalized class for the configuration describing the submission section
*/ */
@mapsTo(SubmissionSectionModel)
@inheritSerialization(NormalizedConfigObject) @inheritSerialization(NormalizedConfigObject)
export class NormalizedSubmissionSectionModel extends NormalizedConfigObject<SubmissionSectionModel> { export class NormalizedSubmissionSectionModel extends NormalizedConfigObject<SubmissionSectionModel> {

View File

@@ -1,12 +1,10 @@
import { inheritSerialization } from 'cerialize'; import { inheritSerialization } from 'cerialize';
import { mapsTo } from '../../cache/builders/build-decorators';
import { SubmissionSectionsModel } from './config-submission-sections.model'; import { SubmissionSectionsModel } from './config-submission-sections.model';
import { NormalizedSubmissionSectionModel } from './normalized-config-submission-section.model'; import { NormalizedSubmissionSectionModel } from './normalized-config-submission-section.model';
/** /**
* Normalized class for the configuration describing the submission section * Normalized class for the configuration describing the submission section
*/ */
@mapsTo(SubmissionSectionsModel)
@inheritSerialization(NormalizedSubmissionSectionModel) @inheritSerialization(NormalizedSubmissionSectionModel)
export class NormalizedSubmissionSectionsModel extends NormalizedSubmissionSectionModel { export class NormalizedSubmissionSectionsModel extends NormalizedSubmissionSectionModel {
} }

View File

@@ -3,12 +3,9 @@ import { AccessConditionOption } from './config-access-condition-option.model';
import { SubmissionFormsModel } from './config-submission-forms.model'; import { SubmissionFormsModel } from './config-submission-forms.model';
import { NormalizedConfigObject } from './normalized-config.model'; import { NormalizedConfigObject } from './normalized-config.model';
import { SubmissionUploadsModel } from './config-submission-uploads.model'; import { SubmissionUploadsModel } from './config-submission-uploads.model';
import { mapsTo } from '../../cache/builders/build-decorators';
/** /**
* Normalized class for the configuration describing the submission upload section * Normalized class for the configuration describing the submission upload section
*/ */
@mapsTo(SubmissionUploadsModel)
@inheritSerialization(NormalizedConfigObject) @inheritSerialization(NormalizedConfigObject)
export class NormalizedSubmissionUploadsModel extends NormalizedConfigObject<SubmissionUploadsModel> { export class NormalizedSubmissionUploadsModel extends NormalizedConfigObject<SubmissionUploadsModel> {

View File

@@ -2,6 +2,8 @@ import { autoserialize, inheritSerialization } from 'cerialize';
import { NormalizedObject } from '../../cache/models/normalized-object.model'; import { NormalizedObject } from '../../cache/models/normalized-object.model';
import { CacheableObject } from '../../cache/object-cache.reducer'; import { CacheableObject } from '../../cache/object-cache.reducer';
import { HALLink } from '../../shared/hal-link.model'; import { HALLink } from '../../shared/hal-link.model';
import { ResourceType } from '../../shared/resource-type';
import { excludeFromEquals } from '../../utilities/equals.decorators';
/** /**
* Normalized abstract class for a configuration object * Normalized abstract class for a configuration object
@@ -15,6 +17,13 @@ export abstract class NormalizedConfigObject<T extends CacheableObject> implemen
@autoserialize @autoserialize
public name: string; public name: string;
/**
* The object type
*/
@excludeFromEquals
@autoserialize
type: ResourceType;
/** /**
* The links to all related resources returned by the rest api. * The links to all related resources returned by the rest api.
*/ */

View File

@@ -1,148 +1,148 @@
import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { HTTP_INTERCEPTORS, HttpClient } from '@angular/common/http';
import { StoreModule } from '@ngrx/store'; import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
import { EffectsModule } from '@ngrx/effects';
import { import {
DynamicFormLayoutService, DynamicFormLayoutService,
DynamicFormService, DynamicFormService,
DynamicFormValidationService DynamicFormValidationService
} from '@ng-dynamic-forms/core'; } from '@ng-dynamic-forms/core';
import { EffectsModule } from '@ngrx/effects';
import { coreEffects } from './core.effects'; import { StoreModule } from '@ngrx/store';
import { coreReducers } from './core.reducers'; import { MyDSpaceGuard } from '../+my-dspace-page/my-dspace.guard';
import { ENV_CONFIG, GLOBAL_CONFIG, GlobalConfig } from '../../config';
import { isNotEmpty } from '../shared/empty.util'; import { isNotEmpty } from '../shared/empty.util';
import { EPersonDataService } from './eperson/eperson-data.service';
import { ApiService } from './services/api.service';
import { BrowseEntriesResponseParsingService } from './data/browse-entries-response-parsing.service';
import { CollectionDataService } from './data/collection-data.service';
import { CommunityDataService } from './data/community-data.service';
import { DebugResponseParsingService } from './data/debug-response-parsing.service';
import { DSOResponseParsingService } from './data/dso-response-parsing.service';
import { SearchResponseParsingService } from './data/search-response-parsing.service';
import { DSpaceRESTv2Service } from './dspace-rest-v2/dspace-rest-v2.service';
import { FormBuilderService } from '../shared/form/builder/form-builder.service'; import { FormBuilderService } from '../shared/form/builder/form-builder.service';
import { SectionFormOperationsService } from '../submission/sections/form/section-form-operations.service';
import { FormService } from '../shared/form/form.service'; import { FormService } from '../shared/form/form.service';
import { HostWindowService } from '../shared/host-window.service'; import { HostWindowService } from '../shared/host-window.service';
import { ItemDataService } from './data/item-data.service';
import { MetadataService } from './metadata/metadata.service';
import { ObjectCacheService } from './cache/object-cache.service';
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
import { RemoteDataBuildService } from './cache/builders/remote-data-build.service';
import { EndpointMapResponseParsingService } from './data/endpoint-map-response-parsing.service';
import { ServerResponseService } from './services/server-response.service';
import { NativeWindowFactory, NativeWindowService } from './services/window.service';
import { BrowseService } from './browse/browse.service';
import { BrowseResponseParsingService } from './data/browse-response-parsing.service';
import { ConfigResponseParsingService } from './config/config-response-parsing.service';
import { RouteService } from './services/route.service';
import { SubmissionDefinitionsConfigService } from './config/submission-definitions-config.service';
import { SubmissionFormsConfigService } from './config/submission-forms-config.service';
import { SubmissionSectionsConfigService } from './config/submission-sections-config.service';
import { Relationship } from './shared/item-relationships/relationship.model';
import { Item } from './shared/item.model';
import { SubmissionResponseParsingService } from './submission/submission-response-parsing.service';
import { EpersonResponseParsingService } from './eperson/eperson-response-parsing.service';
import { JsonPatchOperationsBuilder } from './json-patch/builder/json-patch-operations-builder';
import { AuthorityService } from './integration/authority.service';
import { IntegrationResponseParsingService } from './integration/integration-response-parsing.service';
import { WorkspaceitemDataService } from './submission/workspaceitem-data.service';
import { UUIDService } from './shared/uuid.service';
import { AuthenticatedGuard } from './auth/authenticated.guard';
import { AuthRequestService } from './auth/auth-request.service';
import { AuthResponseParsingService } from './auth/auth-response-parsing.service';
import { HTTP_INTERCEPTORS, HttpClient } from '@angular/common/http';
import { AuthInterceptor } from './auth/auth.interceptor';
import { HALEndpointService } from './shared/hal-endpoint.service';
import { FacetValueResponseParsingService } from './data/facet-value-response-parsing.service';
import { FacetValueMapResponseParsingService } from './data/facet-value-map-response-parsing.service';
import { FacetConfigResponseParsingService } from './data/facet-config-response-parsing.service';
import { ResourcePolicyService } from './data/resource-policy.service';
import { RegistryService } from './registry/registry.service';
import { RegistryMetadataschemasResponseParsingService } from './data/registry-metadataschemas-response-parsing.service';
import { RegistryMetadatafieldsResponseParsingService } from './data/registry-metadatafields-response-parsing.service';
import { RegistryBitstreamformatsResponseParsingService } from './data/registry-bitstreamformats-response-parsing.service';
import { WorkflowItemDataService } from './submission/workflowitem-data.service';
import { NotificationsService } from '../shared/notifications/notifications.service';
import { UploaderService } from '../shared/uploader/uploader.service';
import { FileService } from './shared/file.service';
import { SubmissionRestService } from './submission/submission-rest.service';
import { BrowseItemsResponseParsingService } from './data/browse-items-response-parsing-service';
import { DSpaceObjectDataService } from './data/dspace-object-data.service';
import { MetadataschemaParsingService } from './data/metadataschema-parsing.service';
import { FilteredDiscoveryPageResponseParsingService } from './data/filtered-discovery-page-response-parsing.service';
import { CSSVariableService } from '../shared/sass-helper/sass-helper.service';
import { MenuService } from '../shared/menu/menu.service'; import { MenuService } from '../shared/menu/menu.service';
import { SubmissionJsonPatchOperationsService } from './submission/submission-json-patch-operations.service'; import { EndpointMockingRestService } from '../shared/mocks/dspace-rest-v2/endpoint-mocking-rest.service';
import { NormalizedObjectBuildService } from './cache/builders/normalized-object-build.service';
import { DSOChangeAnalyzer } from './data/dso-change-analyzer.service';
import { ObjectUpdatesService } from './data/object-updates/object-updates.service';
import { DefaultChangeAnalyzer } from './data/default-change-analyzer.service';
import { SearchService } from './shared/search/search.service';
import { RelationshipService } from './data/relationship.service';
import { NormalizedCollection } from './cache/models/normalized-collection.model';
import { NormalizedCommunity } from './cache/models/normalized-community.model';
import { NormalizedDSpaceObject } from './cache/models/normalized-dspace-object.model';
import { NormalizedBitstream } from './cache/models/normalized-bitstream.model';
import { NormalizedBundle } from './cache/models/normalized-bundle.model';
import { NormalizedBitstreamFormat } from './cache/models/normalized-bitstream-format.model';
import { NormalizedItem } from './cache/models/normalized-item.model';
import { NormalizedEPerson } from './eperson/models/normalized-eperson.model';
import { NormalizedGroup } from './eperson/models/normalized-group.model';
import { NormalizedResourcePolicy } from './cache/models/normalized-resource-policy.model';
import { NormalizedMetadataSchema } from './metadata/normalized-metadata-schema.model';
import { NormalizedMetadataField } from './metadata/normalized-metadata-field.model';
import { NormalizedLicense } from './cache/models/normalized-license.model';
import { NormalizedWorkflowItem } from './submission/models/normalized-workflowitem.model';
import { NormalizedWorkspaceItem } from './submission/models/normalized-workspaceitem.model';
import { NormalizedSubmissionDefinitionsModel } from './config/models/normalized-config-submission-definitions.model';
import { NormalizedSubmissionFormsModel } from './config/models/normalized-config-submission-forms.model';
import { NormalizedSubmissionSectionModel } from './config/models/normalized-config-submission-section.model';
import { NormalizedAuthStatus } from './auth/models/normalized-auth-status.model';
import { NormalizedAuthorityValue } from './integration/models/normalized-authority-value.model';
import { RoleService } from './roles/role.service';
import { MyDSpaceGuard } from '../+my-dspace-page/my-dspace.guard';
import { MyDSpaceResponseParsingService } from './data/mydspace-response-parsing.service';
import { ClaimedTaskDataService } from './tasks/claimed-task-data.service';
import { PoolTaskDataService } from './tasks/pool-task-data.service';
import { TaskResponseParsingService } from './tasks/task-response-parsing.service';
import { BitstreamFormatDataService } from './data/bitstream-format-data.service';
import { NormalizedClaimedTask } from './tasks/models/normalized-claimed-task-object.model';
import { NormalizedTaskObject } from './tasks/models/normalized-task-object.model';
import { NormalizedPoolTask } from './tasks/models/normalized-pool-task-object.model';
import { NormalizedRelationship } from './cache/models/items/normalized-relationship.model';
import { NormalizedRelationshipType } from './cache/models/items/normalized-relationship-type.model';
import { NormalizedItemType } from './cache/models/items/normalized-item-type.model';
import { MetadatafieldParsingService } from './data/metadatafield-parsing.service';
import { NormalizedSubmissionUploadsModel } from './config/models/normalized-config-submission-uploads.model';
import { NormalizedBrowseEntry } from './shared/normalized-browse-entry.model';
import { BrowseDefinition } from './shared/browse-definition.model';
import { ContentSourceResponseParsingService } from './data/content-source-response-parsing.service';
import { MappedCollectionsReponseParsingService } from './data/mapped-collections-reponse-parsing.service';
import { ObjectSelectService } from '../shared/object-select/object-select.service';
import {EntityTypeService} from './data/entity-type.service';
import { SiteDataService } from './data/site-data.service';
import { NormalizedSite } from './cache/models/normalized-site.model';
import { import {
MOCK_RESPONSE_MAP, MOCK_RESPONSE_MAP,
MockResponseMap, MockResponseMap,
mockResponseMap mockResponseMap
} from '../shared/mocks/dspace-rest-v2/mocks/mock-response-map'; } from '../shared/mocks/dspace-rest-v2/mocks/mock-response-map';
import { EndpointMockingRestService } from '../shared/mocks/dspace-rest-v2/endpoint-mocking-rest.service'; import { NotificationsService } from '../shared/notifications/notifications.service';
import { ENV_CONFIG, GLOBAL_CONFIG, GlobalConfig } from '../../config';
import { SearchFilterService } from './shared/search/search-filter.service';
import { SearchConfigurationService } from './shared/search/search-configuration.service';
import { SelectableListService } from '../shared/object-list/selectable-list/selectable-list.service'; import { SelectableListService } from '../shared/object-list/selectable-list/selectable-list.service';
import { RelationshipTypeService } from './data/relationship-type.service'; import { ObjectSelectService } from '../shared/object-select/object-select.service';
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
import { CSSVariableService } from '../shared/sass-helper/sass-helper.service';
import { SidebarService } from '../shared/sidebar/sidebar.service'; import { SidebarService } from '../shared/sidebar/sidebar.service';
import { NormalizedExternalSource } from './cache/models/normalized-external-source.model'; import { UploaderService } from '../shared/uploader/uploader.service';
import { NormalizedExternalSourceEntry } from './cache/models/normalized-external-source-entry.model'; import { SectionFormOperationsService } from '../submission/sections/form/section-form-operations.service';
import { AuthRequestService } from './auth/auth-request.service';
import { AuthResponseParsingService } from './auth/auth-response-parsing.service';
import { AuthInterceptor } from './auth/auth.interceptor';
import { AuthenticatedGuard } from './auth/authenticated.guard';
import { AuthStatus } from './auth/models/auth-status.model';
import { BrowseService } from './browse/browse.service';
import { NormalizedObjectBuildService } from './cache/builders/normalized-object-build.service';
import { RemoteDataBuildService } from './cache/builders/remote-data-build.service';
import { ObjectCacheService } from './cache/object-cache.service';
import { ConfigResponseParsingService } from './config/config-response-parsing.service';
import { SubmissionDefinitionsModel } from './config/models/config-submission-definitions.model';
import { SubmissionFormsModel } from './config/models/config-submission-forms.model';
import { SubmissionSectionModel } from './config/models/config-submission-section.model';
import { SubmissionUploadsModel } from './config/models/config-submission-uploads.model';
import { SubmissionDefinitionsConfigService } from './config/submission-definitions-config.service';
import { SubmissionFormsConfigService } from './config/submission-forms-config.service';
import { SubmissionSectionsConfigService } from './config/submission-sections-config.service';
import { coreEffects } from './core.effects';
import { coreReducers } from './core.reducers';
import { BitstreamFormatDataService } from './data/bitstream-format-data.service';
import { BrowseEntriesResponseParsingService } from './data/browse-entries-response-parsing.service';
import { BrowseItemsResponseParsingService } from './data/browse-items-response-parsing-service';
import { BrowseResponseParsingService } from './data/browse-response-parsing.service';
import { CollectionDataService } from './data/collection-data.service';
import { CommunityDataService } from './data/community-data.service';
import { ContentSourceResponseParsingService } from './data/content-source-response-parsing.service';
import { DebugResponseParsingService } from './data/debug-response-parsing.service';
import { DefaultChangeAnalyzer } from './data/default-change-analyzer.service';
import { DSOChangeAnalyzer } from './data/dso-change-analyzer.service';
import { DSOResponseParsingService } from './data/dso-response-parsing.service';
import { DSpaceObjectDataService } from './data/dspace-object-data.service';
import { EndpointMapResponseParsingService } from './data/endpoint-map-response-parsing.service';
import { ItemTypeDataService } from './data/entity-type-data.service';
import { EntityTypeService } from './data/entity-type.service';
import { ExternalSourceService } from './data/external-source.service'; import { ExternalSourceService } from './data/external-source.service';
import { FacetConfigResponseParsingService } from './data/facet-config-response-parsing.service';
import { FacetValueMapResponseParsingService } from './data/facet-value-map-response-parsing.service';
import { FacetValueResponseParsingService } from './data/facet-value-response-parsing.service';
import { FilteredDiscoveryPageResponseParsingService } from './data/filtered-discovery-page-response-parsing.service';
import { ItemDataService } from './data/item-data.service';
import { LicenseDataService } from './data/license-data.service';
import { LookupRelationService } from './data/lookup-relation.service'; import { LookupRelationService } from './data/lookup-relation.service';
import { MappedCollectionsReponseParsingService } from './data/mapped-collections-reponse-parsing.service';
import { MetadatafieldParsingService } from './data/metadatafield-parsing.service';
import { MetadataschemaParsingService } from './data/metadataschema-parsing.service';
import { MyDSpaceResponseParsingService } from './data/mydspace-response-parsing.service';
import { ObjectUpdatesService } from './data/object-updates/object-updates.service';
import { RegistryBitstreamformatsResponseParsingService } from './data/registry-bitstreamformats-response-parsing.service';
import { RegistryMetadatafieldsResponseParsingService } from './data/registry-metadatafields-response-parsing.service';
import { RegistryMetadataschemasResponseParsingService } from './data/registry-metadataschemas-response-parsing.service';
import { RelationshipTypeService } from './data/relationship-type.service';
import { RelationshipService } from './data/relationship.service';
import { ResourcePolicyService } from './data/resource-policy.service';
import { SearchResponseParsingService } from './data/search-response-parsing.service';
import { SiteDataService } from './data/site-data.service';
import { DSpaceRESTv2Service } from './dspace-rest-v2/dspace-rest-v2.service';
import { EPersonDataService } from './eperson/eperson-data.service';
import { EpersonResponseParsingService } from './eperson/eperson-response-parsing.service';
import { EPerson } from './eperson/models/eperson.model';
import { Group } from './eperson/models/group.model';
import { AuthorityService } from './integration/authority.service';
import { IntegrationResponseParsingService } from './integration/integration-response-parsing.service';
import { AuthorityValue } from './integration/models/authority.value';
import { JsonPatchOperationsBuilder } from './json-patch/builder/json-patch-operations-builder';
import { MetadataField } from './metadata/metadata-field.model';
import { MetadataSchema } from './metadata/metadata-schema.model';
import { MetadataService } from './metadata/metadata.service';
import { RegistryService } from './registry/registry.service';
import { RoleService } from './roles/role.service';
import { ApiService } from './services/api.service';
import { RouteService } from './services/route.service';
import { ServerResponseService } from './services/server-response.service';
import { NativeWindowFactory, NativeWindowService } from './services/window.service';
import { BitstreamFormat } from './shared/bitstream-format.model';
import { Bitstream } from './shared/bitstream.model';
import { BrowseDefinition } from './shared/browse-definition.model';
import { BrowseEntry } from './shared/browse-entry.model';
import { Bundle } from './shared/bundle.model';
import { Collection } from './shared/collection.model';
import { Community } from './shared/community.model';
import { DSpaceObject } from './shared/dspace-object.model';
import { ExternalSourceEntry } from './shared/external-source-entry.model';
import { ExternalSource } from './shared/external-source.model';
import { FileService } from './shared/file.service';
import { HALEndpointService } from './shared/hal-endpoint.service';
import { ItemType } from './shared/item-relationships/item-type.model';
import { RelationshipType } from './shared/item-relationships/relationship-type.model';
import { Relationship } from './shared/item-relationships/relationship.model';
import { Item } from './shared/item.model';
import { License } from './shared/license.model';
import { ResourcePolicy } from './shared/resource-policy.model';
import { SearchConfigurationService } from './shared/search/search-configuration.service';
import { SearchFilterService } from './shared/search/search-filter.service';
import { SearchService } from './shared/search/search.service';
import { Site } from './shared/site.model';
import { UUIDService } from './shared/uuid.service';
import { WorkflowItem } from './submission/models/workflowitem.model';
import { WorkspaceItem } from './submission/models/workspaceitem.model';
import { SubmissionJsonPatchOperationsService } from './submission/submission-json-patch-operations.service';
import { SubmissionResponseParsingService } from './submission/submission-response-parsing.service';
import { SubmissionRestService } from './submission/submission-rest.service';
import { WorkflowItemDataService } from './submission/workflowitem-data.service';
import { WorkspaceitemDataService } from './submission/workspaceitem-data.service';
import { ClaimedTaskDataService } from './tasks/claimed-task-data.service';
import { ClaimedTask } from './tasks/models/claimed-task-object.model';
import { PoolTask } from './tasks/models/pool-task-object.model';
import { TaskObject } from './tasks/models/task-object.model';
import { PoolTaskDataService } from './tasks/pool-task-data.service';
import { TaskResponseParsingService } from './tasks/task-response-parsing.service';
/** /**
* When not in production, endpoint responses can be mocked for testing purposes * When not in production, endpoint responses can be mocked for testing purposes
@@ -257,6 +257,8 @@ const PROVIDERS = [
RelationshipTypeService, RelationshipTypeService,
ExternalSourceService, ExternalSourceService,
LookupRelationService, LookupRelationService,
LicenseDataService,
ItemTypeDataService,
// register AuthInterceptor as HttpInterceptor // register AuthInterceptor as HttpInterceptor
{ {
provide: HTTP_INTERCEPTORS, provide: HTTP_INTERCEPTORS,
@@ -271,42 +273,40 @@ const PROVIDERS = [
/** /**
* Declaration needed to make sure all decorator functions are called in time * Declaration needed to make sure all decorator functions are called in time
*/ */
export const normalizedModels = export const models =
[ [
Relationship, DSpaceObject,
Bundle,
Bitstream,
BitstreamFormat,
Item, Item,
NormalizedDSpaceObject, Site,
NormalizedBundle, Collection,
NormalizedBitstream, Community,
NormalizedBitstreamFormat, EPerson,
NormalizedItem, Group,
NormalizedSite, ResourcePolicy,
NormalizedCollection, MetadataSchema,
NormalizedCommunity, MetadataField,
NormalizedEPerson, License,
NormalizedGroup, WorkflowItem,
NormalizedResourcePolicy, WorkspaceItem,
NormalizedMetadataSchema, SubmissionDefinitionsModel,
NormalizedMetadataField, SubmissionFormsModel,
NormalizedLicense, SubmissionSectionModel,
NormalizedWorkflowItem, SubmissionUploadsModel,
NormalizedWorkspaceItem, AuthStatus,
NormalizedSubmissionDefinitionsModel, AuthorityValue,
NormalizedSubmissionFormsModel, BrowseEntry,
NormalizedSubmissionSectionModel,
NormalizedSubmissionUploadsModel,
NormalizedAuthStatus,
NormalizedAuthorityValue,
NormalizedBrowseEntry,
BrowseDefinition, BrowseDefinition,
NormalizedClaimedTask, ClaimedTask,
NormalizedTaskObject, TaskObject,
NormalizedPoolTask, PoolTask,
NormalizedRelationship, Relationship,
NormalizedRelationshipType, RelationshipType,
NormalizedItemType, ItemType,
NormalizedExternalSource, ExternalSource,
NormalizedExternalSourceEntry, ExternalSourceEntry,
]; ];
@NgModule({ @NgModule({

View File

@@ -1,13 +1,14 @@
import { hasNoValue, hasValue, isNotEmpty } from '../../shared/empty.util'; import { hasNoValue, hasValue, isNotEmpty } from '../../shared/empty.util';
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer';
import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer';
import { CacheableObject } from '../cache/object-cache.reducer'; import { CacheableObject } from '../cache/object-cache.reducer';
import { Serializer } from '../serializer';
import { PageInfo } from '../shared/page-info.model'; import { PageInfo } from '../shared/page-info.model';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
import { GlobalConfig } from '../../../config/global-config.interface'; import { GlobalConfig } from '../../../config/global-config.interface';
import { GenericConstructor } from '../shared/generic-constructor'; import { GenericConstructor } from '../shared/generic-constructor';
import { PaginatedList } from './paginated-list'; import { PaginatedList } from './paginated-list';
import { isRestDataObject, isRestPaginatedList } from '../cache/builders/normalized-object-build.service'; import { isRestDataObject, isRestPaginatedList } from '../cache/builders/normalized-object-build.service';
import { ResourceType } from '../shared/resource-type';
import { getMapsToType } from '../cache/builders/build-decorators'; import { getMapsToType } from '../cache/builders/build-decorators';
import { RestRequest } from './request.models'; import { RestRequest } from './request.models';
/* tslint:disable:max-classes-per-file */ /* tslint:disable:max-classes-per-file */
@@ -17,6 +18,7 @@ export abstract class BaseResponseParsingService {
protected abstract objectCache: ObjectCacheService; protected abstract objectCache: ObjectCacheService;
protected abstract toCache: boolean; protected abstract toCache: boolean;
protected shouldDirectlyAttachEmbeds = false; protected shouldDirectlyAttachEmbeds = false;
protected serializerConstructor: GenericConstructor<Serializer<any>> = DSpaceSerializer;
protected process<ObjectDomain>(data: any, request: RestRequest): any { protected process<ObjectDomain>(data: any, request: RestRequest): any {
if (isNotEmpty(data)) { if (isNotEmpty(data)) {
@@ -47,7 +49,7 @@ export abstract class BaseResponseParsingService {
}); });
} }
this.cache(object, request); this.cache(object, request, data);
return object; return object;
} }
const result = {}; const result = {};
@@ -91,30 +93,35 @@ export abstract class BaseResponseParsingService {
const normObjConstructor = getMapsToType(type) as GenericConstructor<ObjectDomain>; const normObjConstructor = getMapsToType(type) as GenericConstructor<ObjectDomain>;
if (hasValue(normObjConstructor)) { if (hasValue(normObjConstructor)) {
const serializer = new DSpaceRESTv2Serializer(normObjConstructor); const serializer = new this.serializerConstructor(normObjConstructor);
return serializer.deserialize(obj); return serializer.deserialize(obj);
} else { } else {
// TODO: move check to Validator?
// throw new Error(`The server returned an object with an unknown a known type: ${type}`);
return null; return null;
} }
} else { } else {
// TODO: move check to Validator
// throw new Error(`The server returned an object without a type: ${JSON.stringify(obj)}`);
return null; return null;
} }
} }
protected cache<ObjectDomain>(obj, request: RestRequest) { protected cache<ObjectDomain>(obj, request: RestRequest, data: any) {
if (this.toCache) { if (this.toCache) {
this.addToObjectCache(obj, request); this.addToObjectCache(obj, request, data);
} }
} }
protected addToObjectCache(co: CacheableObject, request: RestRequest): void { protected addToObjectCache(co: CacheableObject, request: RestRequest, data: any): void {
if (hasNoValue(co) || hasNoValue(co.self)) { if (hasNoValue(co) || hasNoValue(co._links) || hasNoValue(co._links.self) || hasNoValue(co._links.self.href)) {
throw new Error('The server returned an invalid object'); const type = hasValue(data) && hasValue(data.type) ? data.type : 'object';
let dataJSON: string;
if (hasValue(data._embedded)) {
dataJSON = JSON.stringify(Object.assign({}, data, {
_embedded: '...'
}));
} else {
dataJSON = JSON.stringify(data);
}
throw new Error(`Can't cache incomplete ${type}: ${JSON.stringify(co)}, parsed from (partial) response: ${dataJSON}`);
} }
this.objectCache.add(co, hasValue(request.responseMsToLive) ? request.responseMsToLive : this.EnvConfig.cache.msToLive.default, request.uuid); this.objectCache.add(co, hasValue(request.responseMsToLive) ? request.responseMsToLive : this.EnvConfig.cache.msToLive.default, request.uuid);
} }
@@ -122,7 +129,7 @@ export abstract class BaseResponseParsingService {
processPageInfo(payload: any): PageInfo { processPageInfo(payload: any): PageInfo {
if (hasValue(payload.page)) { if (hasValue(payload.page)) {
const pageObj = Object.assign({}, payload.page, { _links: payload._links }); const pageObj = Object.assign({}, payload.page, { _links: payload._links });
const pageInfoObject = new DSpaceRESTv2Serializer(PageInfo).deserialize(pageObj); const pageInfoObject = new NormalizedObjectSerializer(PageInfo).deserialize(pageObj);
if (pageInfoObject.currentPage >= 0) { if (pageInfoObject.currentPage >= 0) {
Object.assign(pageInfoObject, { currentPage: pageInfoObject.currentPage + 1 }); Object.assign(pageInfoObject, { currentPage: pageInfoObject.currentPage + 1 });
} }
@@ -141,7 +148,7 @@ export abstract class BaseResponseParsingService {
} }
protected retrieveObjectOrUrl(obj: any): any { protected retrieveObjectOrUrl(obj: any): any {
return this.toCache ? obj.self : obj; return this.toCache ? obj._links.self.href : obj;
} }
protected isSuccessStatus(statusCode: number) { protected isSuccessStatus(statusCode: number) {

View File

@@ -5,7 +5,7 @@ import { isNotEmpty } from '../../shared/empty.util';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
import { ErrorResponse, GenericSuccessResponse, RestResponse } from '../cache/response.models'; import { ErrorResponse, GenericSuccessResponse, RestResponse } from '../cache/response.models';
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer';
import { BaseResponseParsingService } from './base-response-parsing.service'; import { BaseResponseParsingService } from './base-response-parsing.service';
import { ResponseParsingService } from './parsing.service'; import { ResponseParsingService } from './parsing.service';
import { RestRequest } from './request.models'; import { RestRequest } from './request.models';
@@ -26,7 +26,7 @@ export class BrowseEntriesResponseParsingService extends BaseResponseParsingServ
if (isNotEmpty(data.payload)) { if (isNotEmpty(data.payload)) {
let browseEntries = []; let browseEntries = [];
if (isNotEmpty(data.payload._embedded) && Array.isArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]])) { if (isNotEmpty(data.payload._embedded) && Array.isArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]])) {
const serializer = new DSpaceRESTv2Serializer(NormalizedBrowseEntry); const serializer = new NormalizedObjectSerializer(NormalizedBrowseEntry);
browseEntries = serializer.deserializeArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]]); browseEntries = serializer.deserializeArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]]);
} }
return new GenericSuccessResponse(browseEntries, data.statusCode, data.statusText, this.processPageInfo(data.payload)); return new GenericSuccessResponse(browseEntries, data.statusCode, data.statusText, this.processPageInfo(data.payload));

View File

@@ -6,7 +6,7 @@ import { hasValue, isNotEmpty } from '../../shared/empty.util';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
import { ErrorResponse, GenericSuccessResponse, RestResponse } from '../cache/response.models'; import { ErrorResponse, GenericSuccessResponse, RestResponse } from '../cache/response.models';
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer';
import { BaseResponseParsingService } from './base-response-parsing.service'; import { BaseResponseParsingService } from './base-response-parsing.service';
import { ResponseParsingService } from './parsing.service'; import { ResponseParsingService } from './parsing.service';
import { RestRequest } from './request.models'; import { RestRequest } from './request.models';
@@ -35,7 +35,7 @@ export class BrowseItemsResponseParsingService extends BaseResponseParsingServic
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._embedded) if (isNotEmpty(data.payload) && isNotEmpty(data.payload._embedded)
&& Array.isArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]])) { && Array.isArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]])) {
const serializer = new DSpaceRESTv2Serializer(NormalizedDSpaceObject); const serializer = new NormalizedObjectSerializer(NormalizedDSpaceObject);
const items = serializer.deserializeArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]]); const items = serializer.deserializeArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]]);
return new GenericSuccessResponse(items, data.statusCode, data.statusText, this.processPageInfo(data.payload)); return new GenericSuccessResponse(items, data.statusCode, data.statusText, this.processPageInfo(data.payload));
} else if (hasValue(data.payload) && hasValue(data.payload.page)) { } else if (hasValue(data.payload) && hasValue(data.payload.page)) {

View File

@@ -4,7 +4,7 @@ import { RestRequest } from './request.models';
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
import { GenericSuccessResponse, ErrorResponse, RestResponse } from '../cache/response.models'; import { GenericSuccessResponse, ErrorResponse, RestResponse } from '../cache/response.models';
import { isNotEmpty } from '../../shared/empty.util'; import { isNotEmpty } from '../../shared/empty.util';
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer';
import { BrowseDefinition } from '../shared/browse-definition.model'; import { BrowseDefinition } from '../shared/browse-definition.model';
@Injectable() @Injectable()
@@ -13,7 +13,7 @@ export class BrowseResponseParsingService implements ResponseParsingService {
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._embedded) if (isNotEmpty(data.payload) && isNotEmpty(data.payload._embedded)
&& Array.isArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]])) { && Array.isArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]])) {
const serializer = new DSpaceRESTv2Serializer(BrowseDefinition); const serializer = new NormalizedObjectSerializer(BrowseDefinition);
const browseDefinitions = serializer.deserializeArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]]); const browseDefinitions = serializer.deserializeArray(data.payload._embedded[Object.keys(data.payload._embedded)[0]]);
return new GenericSuccessResponse(browseDefinitions, data.statusCode, data.statusText); return new GenericSuccessResponse(browseDefinitions, data.statusCode, data.statusText);
} else { } else {

View File

@@ -1,4 +1,3 @@
import { NormalizedObject } from '../cache/models/normalized-object.model';
import { Operation } from 'fast-json-patch/lib/core'; import { Operation } from 'fast-json-patch/lib/core';
import { CacheableObject } from '../cache/object-cache.reducer'; import { CacheableObject } from '../cache/object-cache.reducer';
@@ -12,10 +11,10 @@ export interface ChangeAnalyzer<T extends CacheableObject> {
* Compare two objects and return their differences as a * Compare two objects and return their differences as a
* JsonPatch Operation Array * JsonPatch Operation Array
* *
* @param {NormalizedObject} object1 * @param {CacheableObject} object1
* The first object to compare * The first object to compare
* @param {NormalizedObject} object2 * @param {CacheableObject} object2
* The second object to compare * The second object to compare
*/ */
diff(object1: T | NormalizedObject<T>, object2: T | NormalizedObject<T>): Operation[]; diff(object1: T, object2: T): Operation[];
} }

View File

@@ -9,6 +9,7 @@ import { NotificationOptions } from '../../shared/notifications/models/notificat
import { INotification } from '../../shared/notifications/models/notification.model'; import { INotification } from '../../shared/notifications/models/notification.model';
import { NotificationsService } from '../../shared/notifications/notifications.service'; import { NotificationsService } from '../../shared/notifications/notifications.service';
import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model';
import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model';
import { dataService } from '../cache/builders/build-decorators'; import { dataService } from '../cache/builders/build-decorators';
import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
@@ -16,7 +17,7 @@ import { SearchParam } from '../cache/models/search-param.model';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
import { ContentSourceSuccessResponse, RestResponse } from '../cache/response.models'; import { ContentSourceSuccessResponse, RestResponse } from '../cache/response.models';
import { CoreState } from '../core.reducers'; import { CoreState } from '../core.reducers';
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer';
import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service';
import { Collection } from '../shared/collection.model'; import { Collection } from '../shared/collection.model';
import { COLLECTION } from '../shared/collection.resource-type'; import { COLLECTION } from '../shared/collection.resource-type';
@@ -152,7 +153,7 @@ export class CollectionDataService extends ComColDataService<Collection> {
*/ */
updateContentSource(collectionId: string, contentSource: ContentSource): Observable<ContentSource | INotification> { updateContentSource(collectionId: string, contentSource: ContentSource): Observable<ContentSource | INotification> {
const requestId = this.requestService.generateRequestId(); const requestId = this.requestService.generateRequestId();
const serializedContentSource = new DSpaceRESTv2Serializer(ContentSource).serialize(contentSource); const serializedContentSource = new NormalizedObjectSerializer(ContentSource).serialize(contentSource);
const request$ = this.getHarvesterEndpoint(collectionId).pipe( const request$ = this.getHarvesterEndpoint(collectionId).pipe(
take(1), take(1),
map((href: string) => { map((href: string) => {
@@ -210,8 +211,9 @@ export class CollectionDataService extends ComColDataService<Collection> {
* Fetches a list of items that are mapped to a collection * Fetches a list of items that are mapped to a collection
* @param collectionId The id of the collection * @param collectionId The id of the collection
* @param searchOptions Search options to sort or filter out items * @param searchOptions Search options to sort or filter out items
* @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved
*/ */
getMappedItems(collectionId: string, searchOptions?: PaginatedSearchOptions): Observable<RemoteData<PaginatedList<DSpaceObject>>> { getMappedItems(collectionId: string, searchOptions?: PaginatedSearchOptions, ...linksToFollow: Array<FollowLinkConfig<Item>>): Observable<RemoteData<PaginatedList<DSpaceObject>>> {
const requestUuid = this.requestService.generateRequestId(); const requestUuid = this.requestService.generateRequestId();
const href$ = this.getMappedItemsEndpoint(collectionId).pipe( const href$ = this.getMappedItemsEndpoint(collectionId).pipe(
@@ -233,7 +235,7 @@ export class CollectionDataService extends ComColDataService<Collection> {
configureRequest(this.requestService) configureRequest(this.requestService)
).subscribe(); ).subscribe();
return this.rdbService.buildList(href$); return this.rdbService.buildList(href$, ...linksToFollow);
} }
protected getFindByParentHref(parentUUID: string): Observable<string> { protected getFindByParentHref(parentUUID: string): Observable<string> {

View File

@@ -6,9 +6,10 @@ import {
} from 'rxjs/operators'; } from 'rxjs/operators';
import { merge as observableMerge, Observable, throwError as observableThrowError, combineLatest as observableCombineLatest } from 'rxjs'; import { merge as observableMerge, Observable, throwError as observableThrowError, combineLatest as observableCombineLatest } from 'rxjs';
import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util'; import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util';
import { NormalizedCommunity } from '../cache/models/normalized-community.model';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
import { Community } from '../shared/community.model';
import { HALLink } from '../shared/hal-link.model'; import { HALLink } from '../shared/hal-link.model';
import { HALResource } from '../shared/hal-resource.model';
import { CommunityDataService } from './community-data.service'; import { CommunityDataService } from './community-data.service';
import { DataService } from './data.service'; import { DataService } from './data.service';
@@ -71,7 +72,7 @@ export abstract class ComColDataService<T extends CacheableObject> extends DataS
const successResponses = responses.pipe( const successResponses = responses.pipe(
filter((response) => response.isSuccessful), filter((response) => response.isSuccessful),
mergeMap(() => this.objectCache.getObjectByUUID(options.scopeID)), mergeMap(() => this.objectCache.getObjectByUUID(options.scopeID)),
map((nc: NormalizedCommunity) => nc._links[linkPath]), map((hr: HALResource) => hr._links[linkPath]),
filter((halLink: HALLink) => isNotEmpty(halLink)), filter((halLink: HALLink) => isNotEmpty(halLink)),
map((halLink: HALLink) => halLink.href) map((halLink: HALLink) => halLink.href)
); );

View File

@@ -3,7 +3,7 @@ import { ResponseParsingService } from './parsing.service';
import { RestRequest } from './request.models'; import { RestRequest } from './request.models';
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
import { ContentSourceSuccessResponse, RestResponse } from '../cache/response.models'; import { ContentSourceSuccessResponse, RestResponse } from '../cache/response.models';
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer';
import { ContentSource } from '../shared/content-source.model'; import { ContentSource } from '../shared/content-source.model';
import { MetadataConfig } from '../shared/metadata-config.model'; import { MetadataConfig } from '../shared/metadata-config.model';
@@ -17,11 +17,11 @@ export class ContentSourceResponseParsingService implements ResponseParsingServi
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
const payload = data.payload; const payload = data.payload;
const deserialized = new DSpaceRESTv2Serializer(ContentSource).deserialize(payload); const deserialized = new NormalizedObjectSerializer(ContentSource).deserialize(payload);
let metadataConfigs = []; let metadataConfigs = [];
if (payload._embedded && payload._embedded.harvestermetadata && payload._embedded.harvestermetadata.configs) { if (payload._embedded && payload._embedded.harvestermetadata && payload._embedded.harvestermetadata.configs) {
metadataConfigs = new DSpaceRESTv2Serializer(MetadataConfig).serializeArray(payload._embedded.harvestermetadata.configs); metadataConfigs = new NormalizedObjectSerializer(MetadataConfig).serializeArray(payload._embedded.harvestermetadata.configs);
} }
deserialized.metadataConfigs = metadataConfigs; deserialized.metadataConfigs = metadataConfigs;

View File

@@ -27,7 +27,7 @@ import { CacheableObject } from '../cache/object-cache.reducer';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
import { ErrorResponse, RestResponse } from '../cache/response.models'; import { ErrorResponse, RestResponse } from '../cache/response.models';
import { CoreState } from '../core.reducers'; import { CoreState } from '../core.reducers';
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer';
import { DSpaceObject } from '../shared/dspace-object.model'; import { DSpaceObject } from '../shared/dspace-object.model';
import { HALEndpointService } from '../shared/hal-endpoint.service'; import { HALEndpointService } from '../shared/hal-endpoint.service';
import { import {
@@ -155,7 +155,7 @@ export abstract class DataService<T extends CacheableObject> {
/** /**
* Returns {@link RemoteData} of all object with a list of {@link FollowLinkConfig}, to indicate which embedded * Returns {@link RemoteData} of all object with a list of {@link FollowLinkConfig}, to indicate which embedded
* info should be added to the objects * info should be added to the objects
* @param linksToFollow List of {@link FollowLinkConfig} to indicate which embedded info should be retrieved and added * @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved
*/ */
findAll(options: FindListOptions = {}, ...linksToFollow: Array<FollowLinkConfig<T>>): Observable<RemoteData<PaginatedList<T>>> { findAll(options: FindListOptions = {}, ...linksToFollow: Array<FollowLinkConfig<T>>): Observable<RemoteData<PaginatedList<T>>> {
return this.findList(this.getFindAllHref(options), options, ...linksToFollow); return this.findList(this.getFindAllHref(options), options, ...linksToFollow);
@@ -163,9 +163,9 @@ export abstract class DataService<T extends CacheableObject> {
/** /**
* Returns an observable of {@link RemoteData} of an object, based on href observable, * Returns an observable of {@link RemoteData} of an object, based on href observable,
* with a list of {@link FollowLinkConfig}, to add embedded info to the object * with a list of {@link FollowLinkConfig}, to automatically resolve HALLinks of the object
* @param href$ Observable of href of object we want to retrieve * @param href$ Observable of href of object we want to retrieve
* @param linksToFollow List of {@link FollowLinkConfig} to indicate which embedded info should be retrieved and added * @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved
*/ */
protected findList(href$, options: FindListOptions, ...linksToFollow: Array<FollowLinkConfig<T>>) { protected findList(href$, options: FindListOptions, ...linksToFollow: Array<FollowLinkConfig<T>>) {
href$.pipe( href$.pipe(
@@ -192,9 +192,9 @@ export abstract class DataService<T extends CacheableObject> {
/** /**
* Returns an observable of {@link RemoteData} of an object, based on its ID, with a list of {@link FollowLinkConfig}, * Returns an observable of {@link RemoteData} of an object, based on its ID, with a list of {@link FollowLinkConfig},
* to add embedded info to the object * to automatically resolve HALLinks of the object
* @param id ID of object we want to retrieve * @param id ID of object we want to retrieve
* @param linksToFollow List of {@link FollowLinkConfig} to indicate which embedded info should be retrieved and added * @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved
*/ */
findById(id: string, ...linksToFollow: Array<FollowLinkConfig<T>>): Observable<RemoteData<T>> { findById(id: string, ...linksToFollow: Array<FollowLinkConfig<T>>): Observable<RemoteData<T>> {
@@ -216,9 +216,9 @@ export abstract class DataService<T extends CacheableObject> {
/** /**
* Returns an observable of {@link RemoteData} of an object, based on an href, with a list of {@link FollowLinkConfig}, * Returns an observable of {@link RemoteData} of an object, based on an href, with a list of {@link FollowLinkConfig},
* to add embedded info to the object * to automatically resolve HALLinks of the object
* @param href Href of object we want to retrieve * @param href Href of object we want to retrieve
* @param linksToFollow List of {@link FollowLinkConfig} to indicate which embedded info should be retrieved and added * @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved
*/ */
findByHref(href: string, ...linksToFollow: Array<FollowLinkConfig<T>>): Observable<RemoteData<T>> { findByHref(href: string, ...linksToFollow: Array<FollowLinkConfig<T>>): Observable<RemoteData<T>> {
const requestHref = this.buildHrefFromFindOptions(href, {}, []); const requestHref = this.buildHrefFromFindOptions(href, {}, []);
@@ -232,9 +232,9 @@ export abstract class DataService<T extends CacheableObject> {
/** /**
* Returns a list of observables of {@link RemoteData} of objects, based on an href, with a list of {@link FollowLinkConfig}, * Returns a list of observables of {@link RemoteData} of objects, based on an href, with a list of {@link FollowLinkConfig},
* to add embedded info to the object * to automatically resolve HALLinks of the object
* @param id ID of object we want to retrieve * @param id ID of object we want to retrieve
* @param linksToFollow List of {@link FollowLinkConfig} to indicate which embedded info should be retrieved and added * @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved
*/ */
findAllByHref(href: string, findListOptions: FindListOptions = {}, ...linksToFollow: Array<FollowLinkConfig<T>>): Observable<RemoteData<PaginatedList<T>>> { findAllByHref(href: string, findListOptions: FindListOptions = {}, ...linksToFollow: Array<FollowLinkConfig<T>>): Observable<RemoteData<PaginatedList<T>>> {
const requestHref = this.buildHrefFromFindOptions(href, findListOptions, []); const requestHref = this.buildHrefFromFindOptions(href, findListOptions, []);
@@ -302,16 +302,16 @@ export abstract class DataService<T extends CacheableObject> {
* @param {DSpaceObject} object The given object * @param {DSpaceObject} object The given object
*/ */
update(object: T): Observable<RemoteData<T>> { update(object: T): Observable<RemoteData<T>> {
const oldVersion$ = this.findByHref(object.self); const oldVersion$ = this.findByHref(object._links.self.href);
return oldVersion$.pipe( return oldVersion$.pipe(
getSucceededRemoteData(), getSucceededRemoteData(),
getRemoteDataPayload(), getRemoteDataPayload(),
mergeMap((oldVersion: T) => { mergeMap((oldVersion: T) => {
const operations = this.comparator.diff(oldVersion, object); const operations = this.comparator.diff(oldVersion, object);
if (isNotEmpty(operations)) { if (isNotEmpty(operations)) {
this.objectCache.addPatch(object.self, operations); this.objectCache.addPatch(object._links.self.href, operations);
} }
return this.findByHref(object.self); return this.findByHref(object._links.self.href);
} }
)); ));
} }
@@ -334,7 +334,7 @@ export abstract class DataService<T extends CacheableObject> {
); );
const normalizedObject: NormalizedObject<T> = this.dataBuildService.normalize<T>(dso); const normalizedObject: NormalizedObject<T> = this.dataBuildService.normalize<T>(dso);
const serializedDso = new DSpaceRESTv2Serializer(getMapsToType((dso as any).type)).serialize(normalizedObject); const serializedDso = new NormalizedObjectSerializer(getMapsToType((dso as any).type)).serialize(normalizedObject);
const request$ = endpoint$.pipe( const request$ = endpoint$.pipe(
take(1), take(1),

View File

@@ -1,10 +1,11 @@
import { Operation } from 'fast-json-patch/lib/core';
import { compare } from 'fast-json-patch';
import { ChangeAnalyzer } from './change-analyzer';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { CacheableObject } from '../cache/object-cache.reducer'; import { compare } from 'fast-json-patch';
import { Operation } from 'fast-json-patch/lib/core';
import { getMapsToType } from '../cache/builders/build-decorators';
import { NormalizedObject } from '../cache/models/normalized-object.model'; import { NormalizedObject } from '../cache/models/normalized-object.model';
import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { CacheableObject } from '../cache/object-cache.reducer';
import { DSpaceSerializer } from '../dspace-rest-v2/dspace.serializer';
import { ChangeAnalyzer } from './change-analyzer';
/** /**
* A class to determine what differs between two * A class to determine what differs between two
@@ -12,7 +13,7 @@ import { NormalizedObjectBuildService } from '../cache/builders/normalized-objec
*/ */
@Injectable() @Injectable()
export class DefaultChangeAnalyzer<T extends CacheableObject> implements ChangeAnalyzer<T> { export class DefaultChangeAnalyzer<T extends CacheableObject> implements ChangeAnalyzer<T> {
constructor(private normalizeService: NormalizedObjectBuildService) { constructor() {
} }
/** /**
@@ -24,7 +25,9 @@ export class DefaultChangeAnalyzer<T extends CacheableObject> implements ChangeA
* @param {NormalizedObject} object2 * @param {NormalizedObject} object2
* The second object to compare * The second object to compare
*/ */
diff(object1: T | NormalizedObject<T>, object2: T | NormalizedObject<T>): Operation[] { diff(object1: T, object2: T): Operation[] {
return compare(this.normalizeService.normalize(object1), this.normalizeService.normalize(object2)); const serializer1 = new DSpaceSerializer(getMapsToType(object1.type));
const serializer2 = new DSpaceSerializer(getMapsToType(object2.type));
return compare(serializer1.serialize(object1), serializer2.serialize(object2));
} }
} }

View File

@@ -16,12 +16,12 @@ export class DSOChangeAnalyzer<T extends DSpaceObject> implements ChangeAnalyzer
* Compare the metadata of two DSpaceObjects and return the differences as * Compare the metadata of two DSpaceObjects and return the differences as
* a JsonPatch Operation Array * a JsonPatch Operation Array
* *
* @param {NormalizedDSpaceObject} object1 * @param {DSpaceObject} object1
* The first object to compare * The first object to compare
* @param {NormalizedDSpaceObject} object2 * @param {DSpaceObject} object2
* The second object to compare * The second object to compare
*/ */
diff(object1: T | NormalizedDSpaceObject<T>, object2: T | NormalizedDSpaceObject<T>): Operation[] { diff(object1: DSpaceObject, object2: DSpaceObject): Operation[] {
return compare(object1.metadata, object2.metadata).map((operation: Operation) => Object.assign({}, operation, { path: '/metadata' + operation.path })); return compare(object1.metadata, object2.metadata).map((operation: Operation) => Object.assign({}, operation, { path: '/metadata' + operation.path }));
} }
} }

View File

@@ -42,7 +42,7 @@ export class DSOResponseParsingService extends BaseResponseParsingService implem
} else if (!Array.isArray(processRequestDTO)) { } else if (!Array.isArray(processRequestDTO)) {
objectList = [processRequestDTO]; objectList = [processRequestDTO];
} }
const selfLinks = objectList.map((no) => no.self); const selfLinks = objectList.map((no) => no._links.self.href);
return new DSOSuccessResponse(selfLinks, data.statusCode, data.statusText, this.processPageInfo(data.payload)) return new DSOSuccessResponse(selfLinks, data.statusCode, data.statusText, this.processPageInfo(data.payload))
} }

View File

@@ -0,0 +1,76 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { NotificationsService } from '../../shared/notifications/notifications.service';
import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model';
import { dataService } from '../cache/builders/build-decorators';
import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { ObjectCacheService } from '../cache/object-cache.service';
import { CoreState } from '../core.reducers';
import { HALEndpointService } from '../shared/hal-endpoint.service';
import { ItemType } from '../shared/item-relationships/item-type.model';
import { ITEM_TYPE } from '../shared/item-relationships/item-type.resource-type';
import { DataService } from './data.service';
import { DefaultChangeAnalyzer } from './default-change-analyzer.service';
import { PaginatedList } from './paginated-list';
import { RemoteData } from './remote-data';
import { FindListOptions } from './request.models';
import { RequestService } from './request.service';
class DataServiceImpl extends DataService<ItemType> {
protected linkPath = 'entitytypes';
constructor(
protected requestService: RequestService,
protected rdbService: RemoteDataBuildService,
protected dataBuildService: NormalizedObjectBuildService,
protected store: Store<CoreState>,
protected objectCache: ObjectCacheService,
protected halService: HALEndpointService,
protected notificationsService: NotificationsService,
protected http: HttpClient,
protected comparator: DefaultChangeAnalyzer<ItemType>) {
super();
}
}
@Injectable()
@dataService(ITEM_TYPE)
export class ItemTypeDataService {
private dataService: DataServiceImpl;
constructor(
protected requestService: RequestService,
protected rdbService: RemoteDataBuildService,
protected dataBuildService: NormalizedObjectBuildService,
protected store: Store<CoreState>,
protected objectCache: ObjectCacheService,
protected halService: HALEndpointService,
protected notificationsService: NotificationsService,
protected http: HttpClient,
protected comparator: DefaultChangeAnalyzer<ItemType>) {
this.dataService = new DataServiceImpl(requestService, rdbService, dataBuildService, null, objectCache, halService, notificationsService, http, comparator);
}
/**
* Returns an observable of {@link RemoteData} of an object, based on an href, with a list of {@link FollowLinkConfig},
* to automatically resolve HALLinks of the object
* @param href Href of object we want to retrieve
* @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved
*/
findByHref(href: string, ...linksToFollow: Array<FollowLinkConfig<ItemType>>): Observable<RemoteData<ItemType>> {
return this.dataService.findByHref(href, ...linksToFollow);
}
/**
* Returns a list of observables of {@link RemoteData} of objects, based on an href, with a list of {@link FollowLinkConfig},
* to automatically resolve HALLinks of the object
* @param id ID of object we want to retrieve
* @param linksToFollow List of {@link FollowLinkConfig} that indicate which HALLinks should be automatically resolved
*/
findByAllHref(href: string, findListOptions: FindListOptions = {}, ...linksToFollow: Array<FollowLinkConfig<ItemType>>): Observable<RemoteData<PaginatedList<ItemType>>> {
return this.dataService.findAllByHref(href, findListOptions, ...linksToFollow);
}
}

View File

@@ -6,7 +6,7 @@ import {
import { ResponseParsingService } from './parsing.service'; import { ResponseParsingService } from './parsing.service';
import { RestRequest } from './request.models'; import { RestRequest } from './request.models';
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer';
import { SearchFilterConfig } from '../../shared/search/search-filter-config.model'; import { SearchFilterConfig } from '../../shared/search/search-filter-config.model';
import { BaseResponseParsingService } from './base-response-parsing.service'; import { BaseResponseParsingService } from './base-response-parsing.service';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
@@ -24,7 +24,7 @@ export class FacetConfigResponseParsingService extends BaseResponseParsingServic
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
const config = data.payload._embedded.facets; const config = data.payload._embedded.facets;
const serializer = new DSpaceRESTv2Serializer(SearchFilterConfig); const serializer = new NormalizedObjectSerializer(SearchFilterConfig);
const facetConfig = serializer.deserializeArray(config); const facetConfig = serializer.deserializeArray(config);
return new FacetConfigSuccessResponse(facetConfig, data.statusCode, data.statusText); return new FacetConfigSuccessResponse(facetConfig, data.statusCode, data.statusText);
} }

View File

@@ -8,7 +8,7 @@ import {
import { ResponseParsingService } from './parsing.service'; import { ResponseParsingService } from './parsing.service';
import { RestRequest } from './request.models'; import { RestRequest } from './request.models';
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer';
import { FacetValue } from '../../shared/search/facet-value.model'; import { FacetValue } from '../../shared/search/facet-value.model';
import { BaseResponseParsingService } from './base-response-parsing.service'; import { BaseResponseParsingService } from './base-response-parsing.service';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
@@ -30,7 +30,7 @@ export class FacetValueMapResponseParsingService extends BaseResponseParsingServ
const payload = data.payload; const payload = data.payload;
const facetMap: FacetValueMap = new FacetValueMap(); const facetMap: FacetValueMap = new FacetValueMap();
const serializer = new DSpaceRESTv2Serializer(FacetValue); const serializer = new NormalizedObjectSerializer(FacetValue);
payload._embedded.facets.map((facet) => { payload._embedded.facets.map((facet) => {
const values = facet._embedded.values.map((value) => {value.search = value._links.search.href; return value;}); const values = facet._embedded.values.map((value) => {value.search = value._links.search.href; return value;});
const facetValues = serializer.deserializeArray(values); const facetValues = serializer.deserializeArray(values);

View File

@@ -3,8 +3,8 @@ import { FacetValueSuccessResponse, RestResponse } from '../cache/response.model
import { ResponseParsingService } from './parsing.service'; import { ResponseParsingService } from './parsing.service';
import { RestRequest } from './request.models'; import { RestRequest } from './request.models';
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer';
import {FacetValue} from '../../shared/search/facet-value.model'; import { FacetValue } from '../../shared/search/facet-value.model';
import { BaseResponseParsingService } from './base-response-parsing.service'; import { BaseResponseParsingService } from './base-response-parsing.service';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
import { GLOBAL_CONFIG } from '../../../config'; import { GLOBAL_CONFIG } from '../../../config';
@@ -21,7 +21,7 @@ export class FacetValueResponseParsingService extends BaseResponseParsingService
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
const payload = data.payload; const payload = data.payload;
const serializer = new DSpaceRESTv2Serializer(FacetValue); const serializer = new NormalizedObjectSerializer(FacetValue);
// const values = payload._embedded.values.map((value) => {value.search = value._links.search.href; return value;}); // const values = payload._embedded.values.map((value) => {value.search = value._links.search.href; return value;});
const facetValues = serializer.deserializeArray(payload._embedded.values); const facetValues = serializer.deserializeArray(payload._embedded.values);

View File

@@ -271,7 +271,7 @@ export class ItemDataService extends DataService<Item> {
href$.pipe( href$.pipe(
find((href: string) => hasValue(href)), find((href: string) => hasValue(href)),
map((href: string) => { map((href: string) => {
const request = new PostRequest(requestId, href, externalSourceEntry.self, options); const request = new PostRequest(requestId, href, externalSourceEntry._links.self.href, options);
this.requestService.configure(request); this.requestService.configure(request);
}) })
).subscribe(); ).subscribe();

View File

@@ -0,0 +1,64 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { NotificationsService } from '../../shared/notifications/notifications.service';
import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model';
import { dataService } from '../cache/builders/build-decorators';
import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { ObjectCacheService } from '../cache/object-cache.service';
import { CoreState } from '../core.reducers';
import { HALEndpointService } from '../shared/hal-endpoint.service';
import { License } from '../shared/license.model';
import { LICENSE } from '../shared/license.resource-type';
import { DataService } from './data.service';
import { DefaultChangeAnalyzer } from './default-change-analyzer.service';
import { PaginatedList } from './paginated-list';
import { RemoteData } from './remote-data';
import { FindListOptions } from './request.models';
import { RequestService } from './request.service';
class DataServiceImpl extends DataService<License> {
protected linkPath = '';
constructor(
protected requestService: RequestService,
protected rdbService: RemoteDataBuildService,
protected dataBuildService: NormalizedObjectBuildService,
protected store: Store<CoreState>,
protected objectCache: ObjectCacheService,
protected halService: HALEndpointService,
protected notificationsService: NotificationsService,
protected http: HttpClient,
protected comparator: DefaultChangeAnalyzer<License>) {
super();
}
}
@Injectable()
@dataService(LICENSE)
export class LicenseDataService {
private dataService: DataServiceImpl;
constructor(
protected requestService: RequestService,
protected rdbService: RemoteDataBuildService,
protected dataBuildService: NormalizedObjectBuildService,
protected store: Store<CoreState>,
protected objectCache: ObjectCacheService,
protected halService: HALEndpointService,
protected notificationsService: NotificationsService,
protected http: HttpClient,
protected comparator: DefaultChangeAnalyzer<License>) {
this.dataService = new DataServiceImpl(requestService, rdbService, dataBuildService, null, objectCache, halService, notificationsService, http, comparator);
}
findByHref(href: string, ...linksToFollow: Array<FollowLinkConfig<License>>): Observable<RemoteData<License>> {
return this.dataService.findByHref(href, ...linksToFollow);
}
findByAllHref(href: string, findListOptions: FindListOptions = {}, ...linksToFollow: Array<FollowLinkConfig<License>>): Observable<RemoteData<PaginatedList<License>>> {
return this.dataService.findAllByHref(href, findListOptions, ...linksToFollow);
}
}

View File

@@ -1,4 +1,4 @@
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer';
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
import { RestRequest } from './request.models'; import { RestRequest } from './request.models';
import { ResponseParsingService } from './parsing.service'; import { ResponseParsingService } from './parsing.service';
@@ -15,7 +15,7 @@ export class MetadatafieldParsingService implements ResponseParsingService {
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
const payload = data.payload; const payload = data.payload;
const deserialized = new DSpaceRESTv2Serializer(MetadataField).deserialize(payload); const deserialized = new NormalizedObjectSerializer(MetadataField).deserialize(payload);
return new MetadatafieldSuccessResponse(deserialized, data.statusCode, data.statusText); return new MetadatafieldSuccessResponse(deserialized, data.statusCode, data.statusText);
} }

View File

@@ -1,4 +1,4 @@
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer';
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
import { RestRequest } from './request.models'; import { RestRequest } from './request.models';
import { ResponseParsingService } from './parsing.service'; import { ResponseParsingService } from './parsing.service';
@@ -12,7 +12,7 @@ export class MetadataschemaParsingService implements ResponseParsingService {
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
const payload = data.payload; const payload = data.payload;
const deserialized = new DSpaceRESTv2Serializer(MetadataSchema).deserialize(payload); const deserialized = new NormalizedObjectSerializer(MetadataSchema).deserialize(payload);
return new MetadataschemaSuccessResponse(deserialized, data.statusCode, data.statusText); return new MetadataschemaSuccessResponse(deserialized, data.statusCode, data.statusText);
} }

View File

@@ -4,7 +4,7 @@ import { DSOResponseParsingService } from './dso-response-parsing.service';
import { ResponseParsingService } from './parsing.service'; import { ResponseParsingService } from './parsing.service';
import { RestRequest } from './request.models'; import { RestRequest } from './request.models';
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer';
import { hasValue } from '../../shared/empty.util'; import { hasValue } from '../../shared/empty.util';
import { SearchQueryResponse } from '../../shared/search/search-query-response.model'; import { SearchQueryResponse } from '../../shared/search/search-query-response.model';
import { MetadataMap, MetadataValue } from '../shared/metadata.models'; import { MetadataMap, MetadataValue } from '../shared/metadata.models';
@@ -57,7 +57,7 @@ export class MyDSpaceResponseParsingService implements ResponseParsingService {
_embedded: this.filterEmbeddedObjects(object) _embedded: this.filterEmbeddedObjects(object)
})); }));
payload.objects = objects; payload.objects = objects;
const deserialized = new DSpaceRESTv2Serializer(SearchQueryResponse).deserialize(payload); const deserialized = new NormalizedObjectSerializer(SearchQueryResponse).deserialize(payload);
return new SearchSuccessResponse(deserialized, data.statusCode, data.statusText, this.dsoParser.processPageInfo(payload)); return new SearchSuccessResponse(deserialized, data.statusCode, data.statusText, this.dsoParser.processPageInfo(payload));
} }

View File

@@ -1,6 +1,6 @@
import { RegistryBitstreamformatsSuccessResponse, RestResponse } from '../cache/response.models'; import { RegistryBitstreamformatsSuccessResponse, RestResponse } from '../cache/response.models';
import { RegistryBitstreamformatsResponse } from '../registry/registry-bitstreamformats-response.model'; import { RegistryBitstreamformatsResponse } from '../registry/registry-bitstreamformats-response.model';
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer';
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
import { RestRequest } from './request.models'; import { RestRequest } from './request.models';
import { DSOResponseParsingService } from './dso-response-parsing.service'; import { DSOResponseParsingService } from './dso-response-parsing.service';
@@ -18,7 +18,7 @@ export class RegistryBitstreamformatsResponseParsingService implements ResponseP
const bitstreamformats = payload._embedded.bitstreamformats; const bitstreamformats = payload._embedded.bitstreamformats;
payload.bitstreamformats = bitstreamformats; payload.bitstreamformats = bitstreamformats;
const deserialized = new DSpaceRESTv2Serializer(RegistryBitstreamformatsResponse).deserialize(payload); const deserialized = new NormalizedObjectSerializer(RegistryBitstreamformatsResponse).deserialize(payload);
return new RegistryBitstreamformatsSuccessResponse(deserialized, data.statusCode, data.statusText, this.dsoParser.processPageInfo(data.payload.page)); return new RegistryBitstreamformatsSuccessResponse(deserialized, data.statusCode, data.statusText, this.dsoParser.processPageInfo(data.payload.page));
} }

View File

@@ -5,7 +5,7 @@ import {
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
import { RestRequest } from './request.models'; import { RestRequest } from './request.models';
import { ResponseParsingService } from './parsing.service'; import { ResponseParsingService } from './parsing.service';
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer';
import { DSOResponseParsingService } from './dso-response-parsing.service'; import { DSOResponseParsingService } from './dso-response-parsing.service';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { RegistryMetadatafieldsResponse } from '../registry/registry-metadatafields-response.model'; import { RegistryMetadatafieldsResponse } from '../registry/registry-metadatafields-response.model';
@@ -30,7 +30,7 @@ export class RegistryMetadatafieldsResponseParsingService implements ResponsePar
payload.metadatafields = metadatafields; payload.metadatafields = metadatafields;
const deserialized = new DSpaceRESTv2Serializer(RegistryMetadatafieldsResponse).deserialize(payload); const deserialized = new NormalizedObjectSerializer(RegistryMetadatafieldsResponse).deserialize(payload);
return new RegistryMetadatafieldsSuccessResponse(deserialized, data.statusCode, data.statusText, this.dsoParser.processPageInfo(data.payload)); return new RegistryMetadatafieldsSuccessResponse(deserialized, data.statusCode, data.statusText, this.dsoParser.processPageInfo(data.payload));
} }

View File

@@ -3,7 +3,7 @@ import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.
import { RestRequest } from './request.models'; import { RestRequest } from './request.models';
import { ResponseParsingService } from './parsing.service'; import { ResponseParsingService } from './parsing.service';
import { RegistryMetadataschemasResponse } from '../registry/registry-metadataschemas-response.model'; import { RegistryMetadataschemasResponse } from '../registry/registry-metadataschemas-response.model';
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer';
import { DSOResponseParsingService } from './dso-response-parsing.service'; import { DSOResponseParsingService } from './dso-response-parsing.service';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { hasValue } from '../../shared/empty.util'; import { hasValue } from '../../shared/empty.util';
@@ -22,7 +22,7 @@ export class RegistryMetadataschemasResponseParsingService implements ResponsePa
} }
payload.metadataschemas = metadataschemas; payload.metadataschemas = metadataschemas;
const deserialized = new DSpaceRESTv2Serializer(RegistryMetadataschemasResponse).deserialize(payload); const deserialized = new NormalizedObjectSerializer(RegistryMetadataschemasResponse).deserialize(payload);
return new RegistryMetadataschemasSuccessResponse(deserialized, data.statusCode, data.statusText, this.dsoParser.processPageInfo(data.payload)); return new RegistryMetadataschemasSuccessResponse(deserialized, data.statusCode, data.statusText, this.dsoParser.processPageInfo(data.payload));
} }

View File

@@ -64,7 +64,7 @@ export class RelationshipTypeService extends DataService<RelationshipType> {
.pipe( .pipe(
map((endpointURL: string) => new FindListRequest(this.requestService.generateRequestId(), endpointURL, options)), map((endpointURL: string) => new FindListRequest(this.requestService.generateRequestId(), endpointURL, options)),
configureRequest(this.requestService), configureRequest(this.requestService),
switchMap(() => this.rdbService.buildList(link$, followLink('leftType'), followLink('rightType'))) switchMap(() => this.rdbService.buildList<RelationshipType>(link$, followLink('leftType'), followLink('rightType')))
) as Observable<RemoteData<PaginatedList<RelationshipType>>>; ) as Observable<RemoteData<PaginatedList<RelationshipType>>>;
} }

View File

@@ -164,15 +164,15 @@ export class RelationshipService extends DataService<Relationship> {
* @param item The item to remove from the cache * @param item The item to remove from the cache
*/ */
private removeRelationshipItemsFromCache(item) { private removeRelationshipItemsFromCache(item) {
this.objectCache.remove(item.self); this.objectCache.remove(item._links.self.href);
this.requestService.removeByHrefSubstring(item.uuid); this.requestService.removeByHrefSubstring(item.uuid);
combineLatest( combineLatest(
this.objectCache.hasBySelfLinkObservable(item.self), this.objectCache.hasBySelfLinkObservable(item._links.self.href),
this.requestService.hasByHrefObservable(item.uuid) this.requestService.hasByHrefObservable(item.uuid)
).pipe( ).pipe(
filter(([existsInOC, existsInRC]) => !existsInOC && !existsInRC), filter(([existsInOC, existsInRC]) => !existsInOC && !existsInRC),
take(1), take(1),
switchMap(() => this.itemService.findByHref(item.self).pipe(take(1))) switchMap(() => this.itemService.findByHref(item._links.self.href).pipe(take(1)))
).subscribe(); ).subscribe();
} }

View File

@@ -16,7 +16,7 @@ import {
import { RequestError, RestRequest } from './request.models'; import { RequestError, RestRequest } from './request.models';
import { RequestEntry } from './request.reducer'; import { RequestEntry } from './request.reducer';
import { RequestService } from './request.service'; import { RequestService } from './request.service';
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer';
import { catchError, filter, flatMap, map, take, tap } from 'rxjs/operators'; import { catchError, filter, flatMap, map, take, tap } from 'rxjs/operators';
import { ErrorResponse, RestResponse } from '../cache/response.models'; import { ErrorResponse, RestResponse } from '../cache/response.models';
import { StoreActionTypes } from '../../store.actions'; import { StoreActionTypes } from '../../store.actions';
@@ -45,7 +45,7 @@ export class RequestEffects {
flatMap((request: RestRequest) => { flatMap((request: RestRequest) => {
let body; let body;
if (isNotEmpty(request.body)) { if (isNotEmpty(request.body)) {
const serializer = new DSpaceRESTv2Serializer(getMapsToType(request.body.type)); const serializer = new NormalizedObjectSerializer(getMapsToType(request.body.type));
body = serializer.serialize(request.body); body = serializer.serialize(request.body);
} }
return this.restApi.request(request.method, request.href, body, request.options).pipe( return this.restApi.request(request.method, request.href, body, request.options).pipe(

View File

@@ -3,6 +3,8 @@ import { HttpClient } from '@angular/common/http';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model';
import { dataService } from '../cache/builders/build-decorators';
import { DataService } from '../data/data.service'; import { DataService } from '../data/data.service';
import { RequestService } from '../data/request.service'; import { RequestService } from '../data/request.service';
@@ -16,6 +18,7 @@ import { CoreState } from '../core.reducers';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
import { NotificationsService } from '../../shared/notifications/notifications.service'; import { NotificationsService } from '../../shared/notifications/notifications.service';
import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service';
import { RESOURCE_POLICY } from '../shared/resource-policy.resource-type';
import { ChangeAnalyzer } from './change-analyzer'; import { ChangeAnalyzer } from './change-analyzer';
import { DefaultChangeAnalyzer } from '../data/default-change-analyzer.service'; import { DefaultChangeAnalyzer } from '../data/default-change-analyzer.service';
import { PaginatedList } from './paginated-list'; import { PaginatedList } from './paginated-list';
@@ -43,6 +46,7 @@ class DataServiceImpl extends DataService<ResourcePolicy> {
* A service responsible for fetching/sending data from/to the REST API on the resourcepolicies endpoint * A service responsible for fetching/sending data from/to the REST API on the resourcepolicies endpoint
*/ */
@Injectable() @Injectable()
@dataService(RESOURCE_POLICY)
export class ResourcePolicyService { export class ResourcePolicyService {
private dataService: DataServiceImpl; private dataService: DataServiceImpl;
@@ -58,8 +62,12 @@ export class ResourcePolicyService {
this.dataService = new DataServiceImpl(requestService, rdbService, dataBuildService, null, objectCache, halService, notificationsService, http, comparator); this.dataService = new DataServiceImpl(requestService, rdbService, dataBuildService, null, objectCache, halService, notificationsService, http, comparator);
} }
findByHref(href: string): Observable<RemoteData<ResourcePolicy>> { findByHref(href: string, ...linksToFollow: Array<FollowLinkConfig<ResourcePolicy>>): Observable<RemoteData<ResourcePolicy>> {
return this.dataService.findByHref(href); return this.dataService.findByHref(href, ...linksToFollow);
}
findAllByHref(href: string, findListOptions: FindListOptions = {}, ...linksToFollow: Array<FollowLinkConfig<ResourcePolicy>>): Observable<RemoteData<PaginatedList<ResourcePolicy>>> {
return this.dataService.findAllByHref(href, findListOptions, ...linksToFollow);
} }
getDefaultAccessConditionsFor(collection: Collection, findListOptions?: FindListOptions): Observable<RemoteData<PaginatedList<ResourcePolicy>>> { getDefaultAccessConditionsFor(collection: Collection, findListOptions?: FindListOptions): Observable<RemoteData<PaginatedList<ResourcePolicy>>> {

View File

@@ -4,7 +4,7 @@ import { DSOResponseParsingService } from './dso-response-parsing.service';
import { ResponseParsingService } from './parsing.service'; import { ResponseParsingService } from './parsing.service';
import { RestRequest } from './request.models'; import { RestRequest } from './request.models';
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer';
import { hasValue } from '../../shared/empty.util'; import { hasValue } from '../../shared/empty.util';
import { SearchQueryResponse } from '../../shared/search/search-query-response.model'; import { SearchQueryResponse } from '../../shared/search/search-query-response.model';
import { MetadataMap, MetadataValue } from '../shared/metadata.models'; import { MetadataMap, MetadataValue } from '../shared/metadata.models';
@@ -59,13 +59,9 @@ export class SearchResponseParsingService implements ResponseParsingService {
.map((object, index) => Object.assign({}, object, { .map((object, index) => Object.assign({}, object, {
indexableObject: dsoSelfLinks[index], indexableObject: dsoSelfLinks[index],
hitHighlights: hitHighlights[index], hitHighlights: hitHighlights[index],
// we don't need embedded collections, bitstreamformats, etc for search results.
// And parsing them all takes up a lot of time. Throw them away to improve performance
// until objs until partial results are supported by the rest api
_embedded: undefined
})); }));
payload.objects = objects; payload.objects = objects;
const deserialized = new DSpaceRESTv2Serializer(SearchQueryResponse).deserialize(payload); const deserialized = new NormalizedObjectSerializer(SearchQueryResponse).deserialize(payload);
return new SearchSuccessResponse(deserialized, data.statusCode, data.statusText, this.dsoParser.processPageInfo(payload)); return new SearchSuccessResponse(deserialized, data.statusCode, data.statusText, this.dsoParser.processPageInfo(payload));
} }
} }

View File

@@ -0,0 +1,66 @@
import { Deserialize, Serialize } from 'cerialize';
import { Serializer } from '../serializer';
import { GenericConstructor } from '../shared/generic-constructor';
/**
* This Serializer turns responses from v2 of DSpace's REST API
* to models and vice versa
*/
export class DSpaceSerializer<T> implements Serializer<T> {
/**
* Create a new DSpaceSerializer instance
*
* @param modelType a class or interface to indicate
* the kind of model this serializer should work with
*/
constructor(private modelType: GenericConstructor<T>) {
}
/**
* Convert a model in to the format expected by the backend
*
* @param model The model to serialize
* @returns An object to send to the backend
*/
serialize(model: T): any {
return Serialize(model, this.modelType);
}
/**
* Convert an array of models in to the format expected by the backend
*
* @param models The array of models to serialize
* @returns An object to send to the backend
*/
serializeArray(models: T[]): any {
return Serialize(models, this.modelType);
}
/**
* Convert a response from the backend in to a model.
*
* @param response An object returned by the backend
* @returns a model of type T
*/
deserialize(response: any): T {
if (Array.isArray(response)) {
throw new Error('Expected a single model, use deserializeArray() instead');
}
return Deserialize(response, this.modelType) as T;
}
/**
* Convert a response from the backend in to an array of models
*
* @param response An object returned by the backend
* @returns an array of models of type T
*/
deserializeArray(response: any): T[] {
if (!Array.isArray(response)) {
throw new Error('Expected an Array, use deserialize() instead');
}
return Deserialize(response, this.modelType) as T[];
}
}

View File

@@ -1,6 +1,6 @@
import { autoserialize, autoserializeAs } from 'cerialize'; import { autoserialize, autoserializeAs } from 'cerialize';
import { DSpaceRESTv2Serializer } from './dspace-rest-v2.serializer'; import { NormalizedObjectSerializer } from './normalized-object.serializer';
class TestModel { class TestModel {
@autoserialize @autoserialize
@@ -53,12 +53,12 @@ const testResponses = [
const parentHrefRegex = /^\/testmodels\/(.+)$/g; const parentHrefRegex = /^\/testmodels\/(.+)$/g;
describe('DSpaceRESTv2Serializer', () => { describe('NormalizedObjectSerializer', () => {
describe('serialize', () => { describe('serialize', () => {
it('should turn a model in to a valid document', () => { it('should turn a model in to a valid document', () => {
const serializer = new DSpaceRESTv2Serializer(TestModel); const serializer = new NormalizedObjectSerializer(TestModel);
const doc = serializer.serialize(testModels[0]); const doc = serializer.serialize(testModels[0]);
expect(testModels[0].id).toBe(doc.id); expect(testModels[0].id).toBe(doc.id);
expect(testModels[0].name).toBe(doc.name); expect(testModels[0].name).toBe(doc.name);
@@ -69,7 +69,7 @@ describe('DSpaceRESTv2Serializer', () => {
describe('serializeArray', () => { describe('serializeArray', () => {
it('should turn an array of models in to a valid document', () => { it('should turn an array of models in to a valid document', () => {
const serializer = new DSpaceRESTv2Serializer(TestModel); const serializer = new NormalizedObjectSerializer(TestModel);
const doc = serializer.serializeArray(testModels); const doc = serializer.serializeArray(testModels);
expect(testModels[0].id).toBe(doc[0].id); expect(testModels[0].id).toBe(doc[0].id);
@@ -83,7 +83,7 @@ describe('DSpaceRESTv2Serializer', () => {
describe('deserialize', () => { describe('deserialize', () => {
it('should turn a valid document describing a single entity in to a valid model', () => { it('should turn a valid document describing a single entity in to a valid model', () => {
const serializer = new DSpaceRESTv2Serializer(TestModel); const serializer = new NormalizedObjectSerializer(TestModel);
const model = serializer.deserialize(testResponses[0]); const model = serializer.deserialize(testResponses[0]);
expect(model.id).toBe(testResponses[0].id); expect(model.id).toBe(testResponses[0].id);
@@ -93,7 +93,7 @@ describe('DSpaceRESTv2Serializer', () => {
// TODO: cant implement/test this yet - depends on how relationships // TODO: cant implement/test this yet - depends on how relationships
// will be handled in the rest api // will be handled in the rest api
// it('should retain relationship information', () => { // it('should retain relationship information', () => {
// const serializer = new DSpaceRESTv2Serializer(TestModel); // const serializer = new NormalizedObjectSerializer(TestModel);
// const doc = { // const doc = {
// '_embedded': testResponses[0], // '_embedded': testResponses[0],
// }; // };
@@ -113,7 +113,7 @@ describe('DSpaceRESTv2Serializer', () => {
// TODO enable once validation is enabled in the serializer // TODO enable once validation is enabled in the serializer
// it('should throw an error when dealing with an invalid document', () => { // it('should throw an error when dealing with an invalid document', () => {
// const serializer = new DSpaceRESTv2Serializer(TestModel); // const serializer = new NormalizedObjectSerializer(TestModel);
// const doc = testResponses[0]; // const doc = testResponses[0];
// //
// expect(() => { // expect(() => {
@@ -122,7 +122,7 @@ describe('DSpaceRESTv2Serializer', () => {
// }); // });
it('should throw an error when dealing with a document describing an array', () => { it('should throw an error when dealing with a document describing an array', () => {
const serializer = new DSpaceRESTv2Serializer(TestModel); const serializer = new NormalizedObjectSerializer(TestModel);
expect(() => { expect(() => {
serializer.deserialize(testResponses); serializer.deserialize(testResponses);
}).toThrow(); }).toThrow();
@@ -134,7 +134,7 @@ describe('DSpaceRESTv2Serializer', () => {
// TODO: rewrite to incorporate normalisation. // TODO: rewrite to incorporate normalisation.
// it('should turn a valid document describing a collection of objects in to an array of valid models', () => { // it('should turn a valid document describing a collection of objects in to an array of valid models', () => {
// const serializer = new DSpaceRESTv2Serializer(TestModel); // const serializer = new NormalizedObjectSerializer(TestModel);
// const doc = { // const doc = {
// '_embedded': testResponses // '_embedded': testResponses
// }; // };
@@ -150,7 +150,7 @@ describe('DSpaceRESTv2Serializer', () => {
// TODO: cant implement/test this yet - depends on how relationships // TODO: cant implement/test this yet - depends on how relationships
// will be handled in the rest api // will be handled in the rest api
// it('should retain relationship information', () => { // it('should retain relationship information', () => {
// const serializer = new DSpaceRESTv2Serializer(TestModel); // const serializer = new NormalizedObjectSerializer(TestModel);
// const doc = { // const doc = {
// '_embedded': testResponses, // '_embedded': testResponses,
// }; // };
@@ -170,7 +170,7 @@ describe('DSpaceRESTv2Serializer', () => {
// TODO enable once validation is enabled in the serializer // TODO enable once validation is enabled in the serializer
// it('should throw an error when dealing with an invalid document', () => { // it('should throw an error when dealing with an invalid document', () => {
// const serializer = new DSpaceRESTv2Serializer(TestModel); // const serializer = new NormalizedObjectSerializer(TestModel);
// const doc = testResponses[0]; // const doc = testResponses[0];
// //
// expect(() => { // expect(() => {
@@ -179,7 +179,7 @@ describe('DSpaceRESTv2Serializer', () => {
// }); // });
it('should throw an error when dealing with a document describing a single model', () => { it('should throw an error when dealing with a document describing a single model', () => {
const serializer = new DSpaceRESTv2Serializer(TestModel); const serializer = new NormalizedObjectSerializer(TestModel);
const doc = { const doc = {
_embedded: testResponses[0] _embedded: testResponses[0]
}; };

View File

@@ -1,19 +1,19 @@
import { Serialize, Deserialize } from 'cerialize'; import { Deserialize, Serialize } from 'cerialize';
import { deprecate } from 'util';
import { Serializer } from '../serializer'; import { Serializer } from '../serializer';
import { DSpaceRESTV2Response } from './dspace-rest-v2-response.model';
import { DSpaceRESTv2Validator } from './dspace-rest-v2.validator';
import { GenericConstructor } from '../shared/generic-constructor'; import { GenericConstructor } from '../shared/generic-constructor';
import { hasNoValue, hasValue } from '../../shared/empty.util';
/** /**
* This Serializer turns responses from v2 of DSpace's REST API * This Serializer turns responses from v2 of DSpace's REST API
* to models and vice versa * to normalized models and vice versa
*
* @deprecated use DSpaceSerializer instead
*/ */
export class DSpaceRESTv2Serializer<T> implements Serializer<T> { export class NormalizedObjectSerializer<T> implements Serializer<T> {
/** /**
* Create a new DSpaceRESTv2Serializer instance * Create a new NormalizedObjectSerializer instance
* *
* @param modelType a class or interface to indicate * @param modelType a class or interface to indicate
* the kind of model this serializer should work with * the kind of model this serializer should work with

View File

@@ -1,4 +1,6 @@
import { autoserialize, deserialize, inheritSerialization } from 'cerialize';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { link, resourceType } from '../../cache/builders/build-decorators';
import { PaginatedList } from '../../data/paginated-list'; import { PaginatedList } from '../../data/paginated-list';
import { RemoteData } from '../../data/remote-data'; import { RemoteData } from '../../data/remote-data';
@@ -6,48 +8,53 @@ import { DSpaceObject } from '../../shared/dspace-object.model';
import { HALLink } from '../../shared/hal-link.model'; import { HALLink } from '../../shared/hal-link.model';
import { EPERSON } from './eperson.resource-type'; import { EPERSON } from './eperson.resource-type';
import { Group } from './group.model'; import { Group } from './group.model';
import { GROUP } from './group.resource-type';
@resourceType(EPerson.type)
@inheritSerialization(DSpaceObject)
export class EPerson extends DSpaceObject { export class EPerson extends DSpaceObject {
static type = EPERSON; static type = EPERSON;
/** /**
* A string representing the unique handle of this Collection * A string representing the unique handle of this Collection
*/ */
@autoserialize
public handle: string; public handle: string;
/**
* List of Groups that this EPerson belong to
*/
public groups: Observable<RemoteData<PaginatedList<Group>>>;
/** /**
* A string representing the netid of this EPerson * A string representing the netid of this EPerson
*/ */
@autoserialize
public netid: string; public netid: string;
/** /**
* A string representing the last active date for this EPerson * A string representing the last active date for this EPerson
*/ */
@autoserialize
public lastActive: string; public lastActive: string;
/** /**
* A boolean representing if this EPerson can log in * A boolean representing if this EPerson can log in
*/ */
@autoserialize
public canLogIn: boolean; public canLogIn: boolean;
/** /**
* The EPerson email address * The EPerson email address
*/ */
@autoserialize
public email: string; public email: string;
/** /**
* A boolean representing if this EPerson require certificate * A boolean representing if this EPerson require certificate
*/ */
@autoserialize
public requireCertificate: boolean; public requireCertificate: boolean;
/** /**
* A boolean representing if this EPerson registered itself * A boolean representing if this EPerson registered itself
*/ */
@autoserialize
public selfRegistered: boolean; public selfRegistered: boolean;
/** /**
@@ -58,7 +65,15 @@ export class EPerson extends DSpaceObject {
} }
_links: { _links: {
self: HALLink, self: HALLink;
groups: HALLink, groups: HALLink;
} };
/**
* The list of Groups this EPerson is part of
* Will be undefined unless the groups HALLink has been resolved.
*/
@link(GROUP, true)
public groups?: Observable<RemoteData<PaginatedList<Group>>>;
} }

View File

@@ -1,30 +1,44 @@
import { autoserialize, deserialize, inheritSerialization } from 'cerialize';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { link, resourceType } from '../../cache/builders/build-decorators';
import { PaginatedList } from '../../data/paginated-list'; import { PaginatedList } from '../../data/paginated-list';
import { RemoteData } from '../../data/remote-data'; import { RemoteData } from '../../data/remote-data';
import { DSpaceObject } from '../../shared/dspace-object.model'; import { DSpaceObject } from '../../shared/dspace-object.model';
import { HALLink } from '../../shared/hal-link.model';
import { GROUP } from './group.resource-type'; import { GROUP } from './group.resource-type';
@resourceType(Group.type)
@inheritSerialization(DSpaceObject)
export class Group extends DSpaceObject { export class Group extends DSpaceObject {
static type = GROUP; static type = GROUP;
/**
* List of Groups that this Group belong to
*/
public groups: Observable<RemoteData<PaginatedList<Group>>>;
/** /**
* A string representing the unique handle of this Group * A string representing the unique handle of this Group
*/ */
@autoserialize
public handle: string; public handle: string;
/** /**
* A string representing the name of this Group * A boolean denoting whether this Group is permanent
*/ */
public name: string; @autoserialize
public permanent: boolean;
/** /**
* A string representing the name of this Group is permanent * The HALLinks for this Group
*/ */
public permanent: boolean; @deserialize
_links: {
self: HALLink;
groups: HALLink;
};
/**
* The list of Groups this Group is part of
* Will be undefined unless the groups HALLink has been resolved.
*/
@link(GROUP, true)
public groups?: Observable<RemoteData<PaginatedList<Group>>>;
} }

View File

@@ -1,61 +0,0 @@
import { autoserialize, deserialize, inheritSerialization } from 'cerialize';
import { CacheableObject } from '../../cache/object-cache.reducer';
import { NormalizedDSpaceObject } from '../../cache/models/normalized-dspace-object.model';
import { EPerson } from './eperson.model';
import { mapsTo, relationship } from '../../cache/builders/build-decorators';
import { Group } from './group.model';
@mapsTo(EPerson)
@inheritSerialization(NormalizedDSpaceObject)
export class NormalizedEPerson extends NormalizedDSpaceObject<EPerson> implements CacheableObject {
/**
* A string representing the unique handle of this EPerson
*/
@autoserialize
public handle: string;
/**
* List of Groups that this EPerson belong to
*/
@deserialize
@relationship(Group, true)
groups: string[];
/**
* A string representing the netid of this EPerson
*/
@autoserialize
public netid: string;
/**
* A string representing the last active date for this EPerson
*/
@autoserialize
public lastActive: string;
/**
* A boolean representing if this EPerson can log in
*/
@autoserialize
public canLogIn: boolean;
/**
* The EPerson email address
*/
@autoserialize
public email: string;
/**
* A boolean representing if this EPerson require certificate
*/
@autoserialize
public requireCertificate: boolean;
/**
* A boolean representing if this EPerson registered itself
*/
@autoserialize
public selfRegistered: boolean;
}

View File

@@ -1,36 +0,0 @@
import { autoserialize, deserialize, inheritSerialization } from 'cerialize';
import { CacheableObject } from '../../cache/object-cache.reducer';
import { NormalizedDSpaceObject } from '../../cache/models/normalized-dspace-object.model';
import { mapsTo, relationship } from '../../cache/builders/build-decorators';
import { Group } from './group.model';
@mapsTo(Group)
@inheritSerialization(NormalizedDSpaceObject)
export class NormalizedGroup extends NormalizedDSpaceObject<Group> implements CacheableObject {
/**
* List of Groups that this Group belong to
*/
@deserialize
@relationship(Group, true)
groups: string[];
/**
* A string representing the unique handle of this Group
*/
@autoserialize
public handle: string;
/**
* A string representing the name of this Group
*/
@autoserialize
public name: string;
/**
* A string representing the name of this Group is permanent
*/
@autoserialize
public permanent: boolean;
}

View File

@@ -0,0 +1,3 @@
import { ResourceType } from '../../shared/resource-type';
export const WORKFLOWITEM = new ResourceType('workflowitem');

View File

@@ -24,7 +24,7 @@ export class UUIDIndexEffects {
return new AddToIndexAction( return new AddToIndexAction(
IndexName.OBJECT, IndexName.OBJECT,
action.payload.objectToCache.uuid, action.payload.objectToCache.uuid,
action.payload.objectToCache.self action.payload.objectToCache._links.self.href
); );
}) })
); );

View File

@@ -1,6 +1,8 @@
import { autoserialize, deserialize, inheritSerialization } from 'cerialize';
import { isNotEmpty } from '../../../shared/empty.util'; import { isNotEmpty } from '../../../shared/empty.util';
import { PLACEHOLDER_PARENT_METADATA } from '../../../shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.model'; import { PLACEHOLDER_PARENT_METADATA } from '../../../shared/form/builder/ds-dynamic-form-ui/models/relation-group/dynamic-relation-group.model';
import { OtherInformation } from '../../../shared/form/builder/models/form-field-metadata-value.model'; import { OtherInformation } from '../../../shared/form/builder/models/form-field-metadata-value.model';
import { resourceType } from '../../cache/builders/build-decorators';
import { HALLink } from '../../shared/hal-link.model'; import { HALLink } from '../../shared/hal-link.model';
import { MetadataValueInterface } from '../../shared/metadata.models'; import { MetadataValueInterface } from '../../shared/metadata.models';
import { AUTHORITY_VALUE } from './authority.resource-type'; import { AUTHORITY_VALUE } from './authority.resource-type';
@@ -9,34 +11,42 @@ import { IntegrationModel } from './integration.model';
/** /**
* Class representing an authority object * Class representing an authority object
*/ */
@resourceType(AuthorityValue.type)
@inheritSerialization(IntegrationModel)
export class AuthorityValue extends IntegrationModel implements MetadataValueInterface { export class AuthorityValue extends IntegrationModel implements MetadataValueInterface {
static type = AUTHORITY_VALUE; static type = AUTHORITY_VALUE;
/** /**
* The identifier of this authority * The identifier of this authority
*/ */
@autoserialize
id: string; id: string;
/** /**
* The display value of this authority * The display value of this authority
*/ */
@autoserialize
display: string; display: string;
/** /**
* The value of this authority * The value of this authority
*/ */
@autoserialize
value: string; value: string;
/** /**
* An object containing additional information related to this authority * An object containing additional information related to this authority
*/ */
@autoserialize
otherInformation: OtherInformation; otherInformation: OtherInformation;
/** /**
* The language code of this authority value * The language code of this authority value
*/ */
@autoserialize
language: string; language: string;
@deserialize
_links: { _links: {
self: HALLink, self: HALLink,
}; };

View File

@@ -1,4 +1,4 @@
import { autoserialize } from 'cerialize'; import { autoserialize, deserialize } from 'cerialize';
import { CacheableObject } from '../../cache/object-cache.reducer'; import { CacheableObject } from '../../cache/object-cache.reducer';
import { HALLink } from '../../shared/hal-link.model'; import { HALLink } from '../../shared/hal-link.model';
@@ -13,7 +13,7 @@ export abstract class IntegrationModel implements CacheableObject {
@autoserialize @autoserialize
public type: any; public type: any;
@autoserialize @deserialize
public _links: { public _links: {
self: HALLink, self: HALLink,
[name: string]: HALLink [name: string]: HALLink

View File

@@ -1,28 +0,0 @@
import { autoserialize, inheritSerialization } from 'cerialize';
import { IntegrationModel } from './integration.model';
import { mapsTo } from '../../cache/builders/build-decorators';
import { AuthorityValue } from './authority.value';
/**
* Normalized model class for an Authority Value
*/
@mapsTo(AuthorityValue)
@inheritSerialization(IntegrationModel)
export class NormalizedAuthorityValue extends IntegrationModel {
@autoserialize
id: string;
@autoserialize
display: string;
@autoserialize
value: string;
@autoserialize
otherInformation: any;
@autoserialize
language: string;
}

View File

@@ -1,9 +1,12 @@
import { autoserialize } from 'cerialize';
import { isNotEmpty } from '../../shared/empty.util'; import { isNotEmpty } from '../../shared/empty.util';
import { ListableObject } from '../../shared/object-collection/shared/listable-object.model'; import { ListableObject } from '../../shared/object-collection/shared/listable-object.model';
import { link } from '../cache/builders/build-decorators'; import { link, resourceType } from '../cache/builders/build-decorators';
import { GenericConstructor } from '../shared/generic-constructor'; import { GenericConstructor } from '../shared/generic-constructor';
import { HALLink } from '../shared/hal-link.model'; import { HALLink } from '../shared/hal-link.model';
import { HALResource } from '../shared/hal-resource.model'; import { HALResource } from '../shared/hal-resource.model';
import { ResourceType } from '../shared/resource-type';
import { excludeFromEquals } from '../utilities/equals.decorators';
import { METADATA_FIELD } from './metadata-field.resource-type'; import { METADATA_FIELD } from './metadata-field.resource-type';
import { MetadataSchema } from './metadata-schema.model'; import { MetadataSchema } from './metadata-schema.model';
import { METADATA_SCHEMA } from './metadata-schema.resource-type'; import { METADATA_SCHEMA } from './metadata-schema.resource-type';
@@ -11,9 +14,17 @@ import { METADATA_SCHEMA } from './metadata-schema.resource-type';
/** /**
* Class the represents a metadata field * Class the represents a metadata field
*/ */
@resourceType(MetadataField.type)
export class MetadataField extends ListableObject implements HALResource { export class MetadataField extends ListableObject implements HALResource {
static type = METADATA_FIELD; static type = METADATA_FIELD;
/**
* The object type
*/
@excludeFromEquals
@autoserialize
type: ResourceType;
/** /**
* The identifier of this metadata field * The identifier of this metadata field
*/ */
@@ -40,7 +51,8 @@ export class MetadataField extends ListableObject implements HALResource {
scopeNote: string; scopeNote: string;
/** /**
* The metadata schema object of this metadata field * The MetadataSchema for this MetadataField
* Will be undefined unless the schema HALLink has been resolved.
*/ */
@link(METADATA_SCHEMA) @link(METADATA_SCHEMA)
// TODO the responseparsingservice assumes schemas are always embedded. This should be remotedata instead. // TODO the responseparsingservice assumes schemas are always embedded. This should be remotedata instead.

View File

@@ -1,12 +1,17 @@
import { autoserialize } from 'cerialize';
import { ListableObject } from '../../shared/object-collection/shared/listable-object.model'; import { ListableObject } from '../../shared/object-collection/shared/listable-object.model';
import { resourceType } from '../cache/builders/build-decorators';
import { GenericConstructor } from '../shared/generic-constructor'; import { GenericConstructor } from '../shared/generic-constructor';
import { HALLink } from '../shared/hal-link.model'; import { HALLink } from '../shared/hal-link.model';
import { HALResource } from '../shared/hal-resource.model'; import { HALResource } from '../shared/hal-resource.model';
import { ResourceType } from '../shared/resource-type';
import { excludeFromEquals } from '../utilities/equals.decorators';
import { METADATA_SCHEMA } from './metadata-schema.resource-type'; import { METADATA_SCHEMA } from './metadata-schema.resource-type';
/** /**
* Class that represents a metadata schema * Class that represents a metadata schema
*/ */
@resourceType(MetadataSchema.type)
export class MetadataSchema extends ListableObject implements HALResource { export class MetadataSchema extends ListableObject implements HALResource {
static type = METADATA_SCHEMA; static type = METADATA_SCHEMA;
@@ -16,9 +21,11 @@ export class MetadataSchema extends ListableObject implements HALResource {
id: number; id: number;
/** /**
* The REST link to itself * The object type
*/ */
self: string; @excludeFromEquals
@autoserialize
type: ResourceType;
/** /**
* A unique prefix that defines this schema * A unique prefix that defines this schema

View File

@@ -1,5 +1,5 @@
import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; import { autoserialize, deserialize, inheritSerialization } from 'cerialize';
import { mapsTo, relationship } from '../cache/builders/build-decorators'; import { relationship } from '../cache/builders/build-decorators';
import { MetadataField } from './metadata-field.model'; import { MetadataField } from './metadata-field.model';
import { NormalizedObject } from '../cache/models/normalized-object.model'; import { NormalizedObject } from '../cache/models/normalized-object.model';
import { MetadataSchema } from './metadata-schema.model'; import { MetadataSchema } from './metadata-schema.model';
@@ -7,7 +7,6 @@ import { MetadataSchema } from './metadata-schema.model';
/** /**
* Class the represents a normalized metadata field * Class the represents a normalized metadata field
*/ */
@mapsTo(MetadataField)
@inheritSerialization(NormalizedObject) @inheritSerialization(NormalizedObject)
export class NormalizedMetadataField extends NormalizedObject<MetadataField> { export class NormalizedMetadataField extends NormalizedObject<MetadataField> {

View File

@@ -1,12 +1,10 @@
import { autoserialize, inheritSerialization } from 'cerialize'; import { autoserialize, inheritSerialization } from 'cerialize';
import { NormalizedObject } from '../cache/models/normalized-object.model'; import { NormalizedObject } from '../cache/models/normalized-object.model';
import { mapsTo } from '../cache/builders/build-decorators';
import { MetadataSchema } from './metadata-schema.model'; import { MetadataSchema } from './metadata-schema.model';
/** /**
* Normalized class for a DSpace MetadataSchema * Normalized class for a DSpace MetadataSchema
*/ */
@mapsTo(MetadataSchema)
@inheritSerialization(NormalizedObject) @inheritSerialization(NormalizedObject)
export class NormalizedMetadataSchema extends NormalizedObject<MetadataSchema> { export class NormalizedMetadataSchema extends NormalizedObject<MetadataSchema> {
/** /**

View File

@@ -1,15 +1,26 @@
import { autoserialize, deserialize } from 'cerialize'; import { autoserialize, deserialize } from 'cerialize';
import { relationship } from '../cache/builders/build-decorators'; import { relationship, resourceType } from '../cache/builders/build-decorators';
import { MetadataField } from '../metadata/metadata-field.model'; import { MetadataField } from '../metadata/metadata-field.model';
import { METADATA_FIELD } from '../metadata/metadata-field.resource-type'; import { METADATA_FIELD } from '../metadata/metadata-field.resource-type';
import { HALLink } from '../shared/hal-link.model'; import { HALLink } from '../shared/hal-link.model';
import { PageInfo } from '../shared/page-info.model'; import { PageInfo } from '../shared/page-info.model';
import { ResourceType } from '../shared/resource-type';
import { excludeFromEquals } from '../utilities/equals.decorators';
/** /**
* Class that represents a response with a registry's metadata fields * Class that represents a response with a registry's metadata fields
*/ */
@resourceType(RegistryMetadatafieldsResponse.type)
export class RegistryMetadatafieldsResponse { export class RegistryMetadatafieldsResponse {
static type = METADATA_FIELD; static type = METADATA_FIELD;
/**
* The object type
*/
@excludeFromEquals
@autoserialize
type: ResourceType;
/** /**
* List of metadata fields in the response * List of metadata fields in the response
*/ */

View File

@@ -48,7 +48,7 @@ import {
MetadataRegistrySelectSchemaAction MetadataRegistrySelectSchemaAction
} from '../../+admin/admin-registries/metadata-registry/metadata-registry.actions'; } from '../../+admin/admin-registries/metadata-registry/metadata-registry.actions';
import { distinctUntilChanged, flatMap, map, take, tap } from 'rxjs/operators'; import { distinctUntilChanged, flatMap, map, take, tap } from 'rxjs/operators';
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { NormalizedObjectSerializer } from '../dspace-rest-v2/normalized-object.serializer';
import { NormalizedMetadataSchema } from '../metadata/normalized-metadata-schema.model'; import { NormalizedMetadataSchema } from '../metadata/normalized-metadata-schema.model';
import { NotificationsService } from '../../shared/notifications/notifications.service'; import { NotificationsService } from '../../shared/notifications/notifications.service';
import { NotificationOptions } from '../../shared/notifications/models/notification-options.model'; import { NotificationOptions } from '../../shared/notifications/models/notification-options.model';
@@ -400,7 +400,7 @@ export class RegistryService {
distinctUntilChanged() distinctUntilChanged()
); );
const serializedSchema = new DSpaceRESTv2Serializer(getMapsToType(MetadataSchema.type)).serialize(schema); const serializedSchema = new NormalizedObjectSerializer(getMapsToType(MetadataSchema.type)).serialize(schema);
const request$ = endpoint$.pipe( const request$ = endpoint$.pipe(
take(1), take(1),

View File

@@ -1,53 +1,69 @@
import { autoserialize, deserialize, deserializeAs } from 'cerialize';
import { resourceType } from '../cache/builders/build-decorators';
import { IDToUUIDSerializer } from '../cache/id-to-uuid-serializer';
import { CacheableObject } from '../cache/object-cache.reducer'; import { CacheableObject } from '../cache/object-cache.reducer';
import { excludeFromEquals } from '../utilities/equals.decorators';
import { BitstreamFormatSupportLevel } from './bitstream-format-support-level'; import { BitstreamFormatSupportLevel } from './bitstream-format-support-level';
import { BITSTREAM_FORMAT } from './bitstream-format.resource-type'; import { BITSTREAM_FORMAT } from './bitstream-format.resource-type';
import { HALLink } from './hal-link.model'; import { HALLink } from './hal-link.model';
import { ResourceType } from './resource-type';
/** /**
* Model class for a Bitstream Format * Model class for a Bitstream Format
*/ */
@resourceType(BitstreamFormat.type)
export class BitstreamFormat implements CacheableObject { export class BitstreamFormat implements CacheableObject {
static type = BITSTREAM_FORMAT; static type = BITSTREAM_FORMAT;
bitstreamformat /**
* The object type
*/
@excludeFromEquals
@autoserialize
type: ResourceType;
/** /**
* Short description of this Bitstream Format * Short description of this Bitstream Format
*/ */
@autoserialize
shortDescription: string; shortDescription: string;
/** /**
* Description of this Bitstream Format * Description of this Bitstream Format
*/ */
@autoserialize
description: string; description: string;
/** /**
* String representing the MIME type of this Bitstream Format * String representing the MIME type of this Bitstream Format
*/ */
@autoserialize
mimetype: string; mimetype: string;
/** /**
* The level of support the system offers for this Bitstream Format * The level of support the system offers for this Bitstream Format
*/ */
@autoserialize
supportLevel: BitstreamFormatSupportLevel; supportLevel: BitstreamFormatSupportLevel;
/** /**
* True if the Bitstream Format is used to store system information, rather than the content of items in the system * True if the Bitstream Format is used to store system information, rather than the content of items in the system
*/ */
@autoserialize
internal: boolean; internal: boolean;
/** /**
* String representing this Bitstream Format's file extension * String representing this Bitstream Format's file extension
*/ */
@autoserialize
extensions: string[]; extensions: string[];
/**
* The link to the rest endpoint where this Bitstream Format can be found
*/
self: string;
/** /**
* Universally unique identifier for this Bitstream Format * Universally unique identifier for this Bitstream Format
* This UUID is generated client-side and isn't used by the backend.
* It is based on the ID, so it will be the same for each refresh.
*/ */
@deserializeAs(new IDToUUIDSerializer('bitstream-format'), 'id')
uuid: string; uuid: string;
/** /**
@@ -55,8 +71,13 @@ export class BitstreamFormat implements CacheableObject {
* Note that this ID is unique for bitstream formats, * Note that this ID is unique for bitstream formats,
* but might not be unique across different object types * but might not be unique across different object types
*/ */
@autoserialize
id: string; id: string;
/**
* The HALLinks for this BitstreamFormat
*/
@deserialize
_links: { _links: {
self: HALLink; self: HALLink;
} }

View File

@@ -1,5 +1,6 @@
import { autoserialize, deserialize, inheritSerialization } from 'cerialize';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { link } from '../cache/builders/build-decorators'; import { link, resourceType } from '../cache/builders/build-decorators';
import { RemoteData } from '../data/remote-data'; import { RemoteData } from '../data/remote-data';
import { BitstreamFormat } from './bitstream-format.model'; import { BitstreamFormat } from './bitstream-format.model';
import { BITSTREAM_FORMAT } from './bitstream-format.resource-type'; import { BITSTREAM_FORMAT } from './bitstream-format.resource-type';
@@ -8,39 +9,52 @@ import { DSpaceObject } from './dspace-object.model';
import { HALLink } from './hal-link.model'; import { HALLink } from './hal-link.model';
import { HALResource } from './hal-resource.model'; import { HALResource } from './hal-resource.model';
@resourceType(Bitstream.type)
@inheritSerialization(DSpaceObject)
export class Bitstream extends DSpaceObject implements HALResource { export class Bitstream extends DSpaceObject implements HALResource {
static type = BITSTREAM; static type = BITSTREAM;
/** /**
* The size of this bitstream in bytes * The size of this bitstream in bytes
*/ */
@autoserialize
sizeBytes: number; sizeBytes: number;
/** /**
* The description of this Bitstream * The description of this Bitstream
*/ */
@autoserialize
description: string; description: string;
/** /**
* The name of the Bundle this Bitstream is part of * The name of the Bundle this Bitstream is part of
*/ */
@autoserialize
bundleName: string; bundleName: string;
/** /**
* The Thumbnail for this Bitstream * The HALLinks for this Bitstream
*/ */
thumbnail?: Observable<RemoteData<Bitstream>>; @deserialize
/**
* The Bitstream Format for this Bitstream
*/
@link(BITSTREAM_FORMAT)
format?: Observable<RemoteData<BitstreamFormat>>;
_links: { _links: {
self: HALLink; self: HALLink;
bundle: HALLink; bundle: HALLink;
format: HALLink; format: HALLink;
content: HALLink; content: HALLink;
} };
/**
* The thumbnail for this Bitstream
* Needs to be resolved first, but isn't available as a HALLink yet
* Use BitstreamDataService.getThumbnailFor(…) for now.
*/
thumbnail?: Observable<RemoteData<Bitstream>>;
/**
* The BitstreamFormat of this Bitstream
* Will be undefined unless the format HALLink has been resolved.
*/
@link(BITSTREAM_FORMAT)
format?: Observable<RemoteData<BitstreamFormat>>;
} }

View File

@@ -1,12 +1,23 @@
import { autoserialize, autoserializeAs } from 'cerialize'; import { autoserialize, autoserializeAs, deserialize } from 'cerialize';
import { resourceType } from '../cache/builders/build-decorators';
import { TypedObject } from '../cache/object-cache.reducer'; import { TypedObject } from '../cache/object-cache.reducer';
import { excludeFromEquals } from '../utilities/equals.decorators';
import { BROWSE_DEFINITION } from './browse-definition.resource-type'; import { BROWSE_DEFINITION } from './browse-definition.resource-type';
import { HALLink } from './hal-link.model'; import { HALLink } from './hal-link.model';
import { ResourceType } from './resource-type';
import { SortOption } from './sort-option.model'; import { SortOption } from './sort-option.model';
@resourceType(BrowseDefinition.type)
export class BrowseDefinition implements TypedObject { export class BrowseDefinition implements TypedObject {
static type = BROWSE_DEFINITION; static type = BROWSE_DEFINITION;
/**
* The object type
*/
@excludeFromEquals
@autoserialize
type: ResourceType;
@autoserialize @autoserialize
id: string; id: string;
@@ -26,7 +37,7 @@ export class BrowseDefinition implements TypedObject {
return this._links.self.href; return this._links.self.href;
} }
@autoserialize @deserialize
_links: { _links: {
self: HALLink; self: HALLink;
entries: HALLink; entries: HALLink;

View File

@@ -1,17 +1,28 @@
import { autoserialize } from 'cerialize';
import { ListableObject } from '../../shared/object-collection/shared/listable-object.model'; import { ListableObject } from '../../shared/object-collection/shared/listable-object.model';
import { resourceType } from '../cache/builders/build-decorators';
import { TypedObject } from '../cache/object-cache.reducer'; import { TypedObject } from '../cache/object-cache.reducer';
import { excludeFromEquals } from '../utilities/equals.decorators'; import { excludeFromEquals } from '../utilities/equals.decorators';
import { BROWSE_ENTRY } from './browse-entry.resource-type'; import { BROWSE_ENTRY } from './browse-entry.resource-type';
import { GenericConstructor } from './generic-constructor'; import { GenericConstructor } from './generic-constructor';
import { HALLink } from './hal-link.model'; import { HALLink } from './hal-link.model';
import { ResourceType } from './resource-type';
/** /**
* Class object representing a browse entry * Class object representing a browse entry
* This class is not normalized because browse entries do not have self links * This class is not normalized because browse entries do not have self links
*/ */
@resourceType(BrowseEntry.type)
export class BrowseEntry extends ListableObject implements TypedObject { export class BrowseEntry extends ListableObject implements TypedObject {
static type = BROWSE_ENTRY; static type = BROWSE_ENTRY;
/**
* The object type
*/
@excludeFromEquals
@autoserialize
type: ResourceType;
/** /**
* The authority string of this browse entry * The authority string of this browse entry
*/ */

View File

@@ -1,15 +1,18 @@
import { deserialize, inheritSerialization } from 'cerialize';
import { resourceType } from '../cache/builders/build-decorators';
import { BUNDLE } from './bundle.resource-type'; import { BUNDLE } from './bundle.resource-type';
import { DSpaceObject } from './dspace-object.model'; import { DSpaceObject } from './dspace-object.model';
import { HALLink } from './hal-link.model'; import { HALLink } from './hal-link.model';
@resourceType(Bundle.type)
@inheritSerialization(DSpaceObject)
export class Bundle extends DSpaceObject { export class Bundle extends DSpaceObject {
static type = BUNDLE; static type = BUNDLE;
/** /**
* The bundle's name * The HALLinks for this Bundle
*/ */
name: string; @deserialize
_links: { _links: {
self: HALLink; self: HALLink;
primaryBitstream: HALLink; primaryBitstream: HALLink;

View File

@@ -1,5 +1,6 @@
import { autoserialize, deserialize, inheritSerialization } from 'cerialize';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { link } from '../cache/builders/build-decorators'; import { link, resourceType } from '../cache/builders/build-decorators';
import { PaginatedList } from '../data/paginated-list'; import { PaginatedList } from '../data/paginated-list';
import { RemoteData } from '../data/remote-data'; import { RemoteData } from '../data/remote-data';
import { Bitstream } from './bitstream.model'; import { Bitstream } from './bitstream.model';
@@ -12,14 +13,52 @@ import { LICENSE } from './license.resource-type';
import { ResourcePolicy } from './resource-policy.model'; import { ResourcePolicy } from './resource-policy.model';
import { RESOURCE_POLICY } from './resource-policy.resource-type'; import { RESOURCE_POLICY } from './resource-policy.resource-type';
@resourceType(Collection.type)
@inheritSerialization(DSpaceObject)
export class Collection extends DSpaceObject { export class Collection extends DSpaceObject {
static type = COLLECTION; static type = COLLECTION;
/** /**
* A string representing the unique handle of this Collection * A string representing the unique handle of this Collection
*/ */
@autoserialize
handle: string; handle: string;
/**
* The HALLinks for this Collection
*/
@deserialize
_links: {
license: HALLink;
harvester: HALLink;
mappedItems: HALLink;
itemtemplate: HALLink;
defaultAccessConditions: HALLink;
logo: HALLink;
self: HALLink;
};
/**
* The license for this Collection
* Will be undefined unless the license HALLink has been resolved.
*/
@link(LICENSE)
license?: Observable<RemoteData<License>>;
/**
* The logo for this Collection
* Will be undefined unless the logo HALLink has been resolved.
*/
@link(BITSTREAM)
logo?: Observable<RemoteData<Bitstream>>;
/**
* The default access conditions for this Collection
* Will be undefined unless the defaultAccessConditions HALLink has been resolved.
*/
@link(RESOURCE_POLICY, true)
defaultAccessConditions?: Observable<RemoteData<PaginatedList<ResourcePolicy>>>;
/** /**
* The introductory text of this Collection * The introductory text of this Collection
* Corresponds to the metadata field dc.description * Corresponds to the metadata field dc.description
@@ -59,32 +98,4 @@ export class Collection extends DSpaceObject {
get sidebarText(): string { get sidebarText(): string {
return this.firstMetadataValue('dc.description.tableofcontents'); return this.firstMetadataValue('dc.description.tableofcontents');
} }
/**
* The deposit license of this Collection
*/
@link(LICENSE)
license?: Observable<RemoteData<License>>;
/**
* The Bitstream that represents the logo of this Collection
*/
@link(BITSTREAM)
logo?: Observable<RemoteData<Bitstream>>;
/**
* The default access conditions of this Collection
*/
@link(RESOURCE_POLICY, true)
defaultAccessConditions?: Observable<RemoteData<PaginatedList<ResourcePolicy>>>;
_links: {
license: HALLink;
harvester: HALLink;
mappedItems: HALLink;
itemtemplate: HALLink;
defaultAccessConditions: HALLink;
logo: HALLink;
self: HALLink;
}
} }

View File

@@ -1,5 +1,6 @@
import { autoserialize, deserialize, inheritSerialization } from 'cerialize';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { link } from '../cache/builders/build-decorators'; import { link, resourceType } from '../cache/builders/build-decorators';
import { PaginatedList } from '../data/paginated-list'; import { PaginatedList } from '../data/paginated-list';
import { RemoteData } from '../data/remote-data'; import { RemoteData } from '../data/remote-data';
import { Bitstream } from './bitstream.model'; import { Bitstream } from './bitstream.model';
@@ -10,14 +11,49 @@ import { COMMUNITY } from './community.resource-type';
import { DSpaceObject } from './dspace-object.model'; import { DSpaceObject } from './dspace-object.model';
import { HALLink } from './hal-link.model'; import { HALLink } from './hal-link.model';
@resourceType(Community.type)
@inheritSerialization(DSpaceObject)
export class Community extends DSpaceObject { export class Community extends DSpaceObject {
static type = COMMUNITY; static type = COMMUNITY;
/** /**
* A string representing the unique handle of this Community * A string representing the unique handle of this Community
*/ */
@autoserialize
handle: string; handle: string;
/**
* The HALLinks for this Community
*/
@deserialize
_links: {
collections: HALLink;
logo: HALLink;
subcommunities: HALLink;
self: HALLink;
};
/**
* The logo for this Community
* Will be undefined unless the logo HALLink has been resolved.
*/
@link(BITSTREAM)
logo?: Observable<RemoteData<Bitstream>>;
/**
* The list of Collections that are direct children of this Community
* Will be undefined unless the collections HALLink has been resolved.
*/
@link(COLLECTION, true)
collections?: Observable<RemoteData<PaginatedList<Collection>>>;
/**
* The list of Communities that are direct children of this Community
* Will be undefined unless the subcommunities HALLink has been resolved.
*/
@link(COMMUNITY, true)
subcommunities?: Observable<RemoteData<PaginatedList<Community>>>;
/** /**
* The introductory text of this Community * The introductory text of this Community
* Corresponds to the metadata field dc.description * Corresponds to the metadata field dc.description
@@ -49,23 +85,4 @@ export class Community extends DSpaceObject {
get sidebarText(): string { get sidebarText(): string {
return this.firstMetadataValue('dc.description.tableofcontents'); return this.firstMetadataValue('dc.description.tableofcontents');
} }
/**
* The Bitstream that represents the logo of this Community
*/
@link(BITSTREAM)
logo?: Observable<RemoteData<Bitstream>>;
@link(COLLECTION, true)
collections?: Observable<RemoteData<PaginatedList<Collection>>>;
@link(COMMUNITY, true)
subcommunities?: Observable<RemoteData<PaginatedList<Community>>>;
_links: {
collections: HALLink;
logo: HALLink;
subcommunities: HALLink;
self: HALLink;
}
} }

Some files were not shown because too many files have changed in this diff Show More