mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-10 11:33:04 +00:00
added support for embedded resources
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import "reflect-metadata";
|
||||
import { GenericConstructor } from "../../shared/generic-constructor";
|
||||
import { CacheableObject } from "../object-cache.reducer";
|
||||
import { NormalizedDSOType } from "../models/normalized-dspace-object-type";
|
||||
import { ResourceType } from "../../shared/resource-type";
|
||||
|
||||
const mapsToMetadataKey = Symbol("mapsTo");
|
||||
const relationshipKey = Symbol("relationship");
|
||||
@@ -16,7 +16,7 @@ export const getMapsTo = function(target: any) {
|
||||
return Reflect.getOwnMetadata(mapsToMetadataKey, target);
|
||||
};
|
||||
|
||||
export const relationship = function(value: NormalizedDSOType): any {
|
||||
export const relationship = function(value: ResourceType): any {
|
||||
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
||||
if (!target || !propertyKey) {
|
||||
return;
|
||||
|
@@ -13,7 +13,8 @@ import { Observable } from "rxjs/Observable";
|
||||
import { RemoteData } from "../../data/remote-data";
|
||||
import { GenericConstructor } from "../../shared/generic-constructor";
|
||||
import { getMapsTo, getResourceType, getRelationships } from "./build-decorators";
|
||||
import { NormalizedDSOFactory } from "../models/normalized-dspace-object-factory";
|
||||
import { NormalizedObjectFactory } from "../models/normalized-object-factory";
|
||||
import { Request } from "../../data/request.models";
|
||||
|
||||
@Injectable()
|
||||
export class RemoteDataBuildService {
|
||||
@@ -124,13 +125,13 @@ export class RemoteDataBuildService {
|
||||
relationships.forEach((relationship: string) => {
|
||||
if (hasValue(normalized[relationship])) {
|
||||
const resourceType = getResourceType(normalized, relationship);
|
||||
const resourceConstructor = NormalizedDSOFactory.getConstructor(resourceType);
|
||||
const resourceConstructor = NormalizedObjectFactory.getConstructor(resourceType);
|
||||
if (Array.isArray(normalized[relationship])) {
|
||||
// without the setTimeout, the actions inside requestService.configure
|
||||
// are dispatched, but sometimes don't arrive. I'm unsure why atm.
|
||||
setTimeout(() => {
|
||||
normalized[relationship].forEach((href: string) => {
|
||||
this.requestService.configure(href, resourceConstructor)
|
||||
this.requestService.configure(new Request(href))
|
||||
});
|
||||
}, 0);
|
||||
|
||||
@@ -142,7 +143,7 @@ export class RemoteDataBuildService {
|
||||
// without the setTimeout, the actions inside requestService.configure
|
||||
// are dispatched, but sometimes don't arrive. I'm unsure why atm.
|
||||
setTimeout(() => {
|
||||
this.requestService.configure(normalized[relationship], resourceConstructor);
|
||||
this.requestService.configure(new Request(normalized[relationship]));
|
||||
},0);
|
||||
|
||||
links[relationship] = this.buildSingle(normalized[relationship], resourceConstructor);
|
||||
|
@@ -2,7 +2,7 @@ import { autoserialize, inheritSerialization } from "cerialize";
|
||||
import { NormalizedDSpaceObject } from "./normalized-dspace-object.model";
|
||||
import { Bundle } from "../../shared/bundle.model";
|
||||
import { mapsTo, relationship } from "../builders/build-decorators";
|
||||
import { NormalizedDSOType } from "./normalized-dspace-object-type";
|
||||
import { ResourceType } from "../../shared/resource-type";
|
||||
|
||||
@mapsTo(Bundle)
|
||||
@inheritSerialization(NormalizedDSpaceObject)
|
||||
@@ -11,7 +11,7 @@ export class NormalizedBundle extends NormalizedDSpaceObject {
|
||||
* The primary bitstream of this Bundle
|
||||
*/
|
||||
@autoserialize
|
||||
@relationship(NormalizedDSOType.NormalizedBitstream)
|
||||
@relationship(ResourceType.Bitstream)
|
||||
primaryBitstream: string;
|
||||
|
||||
/**
|
||||
@@ -25,6 +25,6 @@ export class NormalizedBundle extends NormalizedDSpaceObject {
|
||||
owner: string;
|
||||
|
||||
@autoserialize
|
||||
@relationship(NormalizedDSOType.NormalizedBitstream)
|
||||
@relationship(ResourceType.Bitstream)
|
||||
bitstreams: Array<string>;
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@ import { autoserialize, inheritSerialization, autoserializeAs } from "cerialize"
|
||||
import { NormalizedDSpaceObject } from "./normalized-dspace-object.model";
|
||||
import { Collection } from "../../shared/collection.model";
|
||||
import { mapsTo, relationship } from "../builders/build-decorators";
|
||||
import { NormalizedDSOType } from "./normalized-dspace-object-type";
|
||||
import { ResourceType } from "../../shared/resource-type";
|
||||
|
||||
@mapsTo(Collection)
|
||||
@inheritSerialization(NormalizedDSpaceObject)
|
||||
@@ -30,7 +30,7 @@ export class NormalizedCollection extends NormalizedDSpaceObject {
|
||||
owner: string;
|
||||
|
||||
@autoserialize
|
||||
@relationship(NormalizedDSOType.NormalizedItem)
|
||||
@relationship(ResourceType.Item)
|
||||
items: Array<string>;
|
||||
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@ import { autoserialize, inheritSerialization, autoserializeAs } from "cerialize"
|
||||
import { NormalizedDSpaceObject } from "./normalized-dspace-object.model";
|
||||
import { Community } from "../../shared/community.model";
|
||||
import { mapsTo, relationship } from "../builders/build-decorators";
|
||||
import { NormalizedDSOType } from "./normalized-dspace-object-type";
|
||||
import { ResourceType } from "../../shared/resource-type";
|
||||
|
||||
@mapsTo(Community)
|
||||
@inheritSerialization(NormalizedDSpaceObject)
|
||||
@@ -30,7 +30,7 @@ export class NormalizedCommunity extends NormalizedDSpaceObject {
|
||||
owner: string;
|
||||
|
||||
@autoserialize
|
||||
@relationship(NormalizedDSOType.NormalizedCollection)
|
||||
@relationship(ResourceType.Collection)
|
||||
collections: Array<string>;
|
||||
|
||||
}
|
||||
|
@@ -1,7 +0,0 @@
|
||||
export enum NormalizedDSOType {
|
||||
NormalizedBitstream,
|
||||
NormalizedBundle,
|
||||
NormalizedItem,
|
||||
NormalizedCollection,
|
||||
NormalizedCommunity
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
import { autoserialize, autoserializeAs } from "cerialize";
|
||||
import { CacheableObject } from "../object-cache.reducer";
|
||||
import { Metadatum } from "../../shared/metadatum.model";
|
||||
import { ResourceType } from "../../shared/resource-type";
|
||||
|
||||
/**
|
||||
* An abstract model class for a DSpaceObject.
|
||||
@@ -26,7 +27,7 @@ export abstract class NormalizedDSpaceObject implements CacheableObject {
|
||||
* A string representing the kind of DSpaceObject, e.g. community, item, …
|
||||
*/
|
||||
@autoserialize
|
||||
type: string;
|
||||
type: ResourceType;
|
||||
|
||||
/**
|
||||
* The name for this DSpaceObject
|
||||
@@ -49,5 +50,6 @@ export abstract class NormalizedDSpaceObject implements CacheableObject {
|
||||
/**
|
||||
* The DSpaceObject that owns this DSpaceObject
|
||||
*/
|
||||
@autoserialize
|
||||
owner: string;
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@ import { inheritSerialization, autoserialize } from "cerialize";
|
||||
import { NormalizedDSpaceObject } from "./normalized-dspace-object.model";
|
||||
import { Item } from "../../shared/item.model";
|
||||
import { mapsTo, relationship } from "../builders/build-decorators";
|
||||
import { NormalizedDSOType } from "./normalized-dspace-object-type";
|
||||
import { ResourceType } from "../../shared/resource-type";
|
||||
|
||||
@mapsTo(Item)
|
||||
@inheritSerialization(NormalizedDSpaceObject)
|
||||
@@ -33,7 +33,7 @@ export class NormalizedItem extends NormalizedDSpaceObject {
|
||||
* An array of Collections that are direct parents of this Item
|
||||
*/
|
||||
@autoserialize
|
||||
@relationship(NormalizedDSOType.NormalizedCollection)
|
||||
@relationship(ResourceType.Collection)
|
||||
parents: Array<string>;
|
||||
|
||||
/**
|
||||
@@ -42,6 +42,6 @@ export class NormalizedItem extends NormalizedDSpaceObject {
|
||||
owner: string;
|
||||
|
||||
@autoserialize
|
||||
@relationship(NormalizedDSOType.NormalizedBundle)
|
||||
@relationship(ResourceType.Bundle)
|
||||
bundles: Array<string>;
|
||||
}
|
||||
|
@@ -4,25 +4,25 @@ import { NormalizedBundle } from "./normalized-bundle.model";
|
||||
import { NormalizedItem } from "./normalized-item.model";
|
||||
import { NormalizedCollection } from "./normalized-collection.model";
|
||||
import { GenericConstructor } from "../../shared/generic-constructor";
|
||||
import { NormalizedDSOType } from "./normalized-dspace-object-type";
|
||||
import { NormalizedCommunity } from "./normalized-community.model";
|
||||
import { ResourceType } from "../../shared/resource-type";
|
||||
|
||||
export class NormalizedDSOFactory {
|
||||
public static getConstructor(type: NormalizedDSOType): GenericConstructor<NormalizedDSpaceObject> {
|
||||
export class NormalizedObjectFactory {
|
||||
public static getConstructor(type: ResourceType): GenericConstructor<NormalizedDSpaceObject> {
|
||||
switch (type) {
|
||||
case NormalizedDSOType.NormalizedBitstream: {
|
||||
case ResourceType.Bitstream: {
|
||||
return NormalizedBitstream
|
||||
}
|
||||
case NormalizedDSOType.NormalizedBundle: {
|
||||
case ResourceType.Bundle: {
|
||||
return NormalizedBundle
|
||||
}
|
||||
case NormalizedDSOType.NormalizedItem: {
|
||||
case ResourceType.Item: {
|
||||
return NormalizedItem
|
||||
}
|
||||
case NormalizedDSOType.NormalizedCollection: {
|
||||
case ResourceType.Collection: {
|
||||
return NormalizedCollection
|
||||
}
|
||||
case NormalizedDSOType.NormalizedCommunity: {
|
||||
case ResourceType.Community: {
|
||||
return NormalizedCommunity
|
||||
}
|
||||
default: {
|
6
src/app/core/cache/response-cache.models.ts
vendored
6
src/app/core/cache/response-cache.models.ts
vendored
@@ -9,8 +9,12 @@ export class SuccessResponse extends Response {
|
||||
}
|
||||
|
||||
export class ErrorResponse extends Response {
|
||||
constructor(public errorMessage: string) {
|
||||
errorMessage: string;
|
||||
|
||||
constructor(error: Error) {
|
||||
super(false);
|
||||
console.error(error);
|
||||
this.errorMessage = error.message;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -33,11 +33,8 @@ export abstract class DataService<TNormalized extends CacheableObject, TDomain>
|
||||
|
||||
findAll(scopeID?: string): RemoteData<Array<TDomain>> {
|
||||
const href = this.getFindAllHref(scopeID);
|
||||
if (!this.responseCache.has(href) && !this.requestService.isPending(href)) {
|
||||
const request = new FindAllRequest(href, this.normalizedResourceType, scopeID);
|
||||
this.store.dispatch(new RequestConfigureAction(request));
|
||||
this.store.dispatch(new RequestExecuteAction(href));
|
||||
}
|
||||
const request = new FindAllRequest(href, scopeID);
|
||||
this.requestService.configure(request);
|
||||
return this.rdbService.buildList<TNormalized, TDomain>(href, this.normalizedResourceType);
|
||||
// return this.rdbService.buildList(href);
|
||||
}
|
||||
@@ -48,21 +45,14 @@ export abstract class DataService<TNormalized extends CacheableObject, TDomain>
|
||||
|
||||
findById(id: string): RemoteData<TDomain> {
|
||||
const href = this.getFindByIDHref(id);
|
||||
if (!this.objectCache.hasBySelfLink(href) && !this.requestService.isPending(href)) {
|
||||
const request = new FindByIDRequest(href, this.normalizedResourceType, id);
|
||||
this.store.dispatch(new RequestConfigureAction(request));
|
||||
this.store.dispatch(new RequestExecuteAction(href));
|
||||
}
|
||||
const request = new FindByIDRequest(href, id);
|
||||
this.requestService.configure(request);
|
||||
return this.rdbService.buildSingle<TNormalized, TDomain>(href, this.normalizedResourceType);
|
||||
// return this.rdbService.buildSingle(href);
|
||||
}
|
||||
|
||||
findByHref(href: string): RemoteData<TDomain> {
|
||||
if (!this.objectCache.hasBySelfLink(href) && !this.requestService.isPending(href)) {
|
||||
const request = new Request(href, this.normalizedResourceType);
|
||||
this.store.dispatch(new RequestConfigureAction(request));
|
||||
this.store.dispatch(new RequestExecuteAction(href));
|
||||
}
|
||||
this.requestService.configure(new Request(href));
|
||||
return this.rdbService.buildSingle<TNormalized, TDomain>(href, this.normalizedResourceType);
|
||||
// return this.rdbService.buildSingle(href));
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@ import { DSpaceRESTv2Serializer } from "../dspace-rest-v2/dspace-rest-v2.seriali
|
||||
import { CacheableObject } from "../cache/object-cache.reducer";
|
||||
import { Observable } from "rxjs";
|
||||
import { Response, SuccessResponse, ErrorResponse } from "../cache/response-cache.models";
|
||||
import { hasNoValue } from "../../shared/empty.util";
|
||||
import { hasNoValue, hasValue, isEmpty, isNotEmpty } from "../../shared/empty.util";
|
||||
import { GlobalConfig, GLOBAL_CONFIG } from "../../../config";
|
||||
import { RequestState, RequestEntry } from "./request.reducer";
|
||||
import {
|
||||
@@ -17,6 +17,12 @@ import {
|
||||
} from "./request.actions";
|
||||
import { ResponseCacheService } from "../cache/response-cache.service";
|
||||
import { RequestService } from "./request.service";
|
||||
import { NormalizedObjectFactory } from "../cache/models/normalized-object-factory";
|
||||
import { ResourceType } from "../shared/resource-type";
|
||||
|
||||
function isObjectLevel(halObj: any) {
|
||||
return isNotEmpty(halObj._links) && hasValue(halObj._links.self);
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class RequestEffects {
|
||||
@@ -38,30 +44,87 @@ export class RequestEffects {
|
||||
.take(1);
|
||||
})
|
||||
.flatMap((entry: RequestEntry) => {
|
||||
const [ifArray, ifNotArray] = this.restApi.get(entry.request.href)
|
||||
.share() // share ensures restApi.get() doesn't get called twice when the partitions are used below
|
||||
.partition((data: DSpaceRESTV2Response) => Array.isArray(data._embedded));
|
||||
|
||||
return Observable.merge(
|
||||
|
||||
ifArray.map((data: DSpaceRESTV2Response) => {
|
||||
return new DSpaceRESTv2Serializer(entry.request.resourceType).deserializeArray(data);
|
||||
}).do((cos: CacheableObject[]) => cos.forEach((t) => this.addToObjectCache(t)))
|
||||
.map((cos: Array<CacheableObject>): Array<string> => cos.map(t => t.uuid)),
|
||||
|
||||
ifNotArray.map((data: DSpaceRESTV2Response) => {
|
||||
return new DSpaceRESTv2Serializer(entry.request.resourceType).deserialize(data);
|
||||
}).do((co: CacheableObject) => this.addToObjectCache(co))
|
||||
.map((co: CacheableObject): Array<string> => [co.uuid])
|
||||
|
||||
).map((ids: Array<string>) => new SuccessResponse(ids))
|
||||
return this.restApi.get(entry.request.href)
|
||||
.map((data: DSpaceRESTV2Response) => this.processEmbedded(data._embedded))
|
||||
.map((ids: Array<string>) => new SuccessResponse(ids))
|
||||
.do((response: Response) => this.responseCache.add(entry.request.href, response, this.EnvConfig.cache.msToLive))
|
||||
.map((response: Response) => new RequestCompleteAction(entry.request.href))
|
||||
.catch((error: Error) => Observable.of(new ErrorResponse(error.message))
|
||||
.catch((error: Error) => Observable.of(new ErrorResponse(error))
|
||||
.do((response: Response) => this.responseCache.add(entry.request.href, response, this.EnvConfig.cache.msToLive))
|
||||
.map((response: Response) => new RequestCompleteAction(entry.request.href)));
|
||||
});
|
||||
|
||||
protected processEmbedded(_embedded: any): Array<string> {
|
||||
|
||||
if (isNotEmpty(_embedded)) {
|
||||
if (isObjectLevel(_embedded)) {
|
||||
return this.deserializeAndCache(_embedded);
|
||||
}
|
||||
else {
|
||||
let uuids = [];
|
||||
Object.keys(_embedded)
|
||||
.filter(property => _embedded.hasOwnProperty(property))
|
||||
.forEach(property => {
|
||||
uuids = [...uuids, ...this.deserializeAndCache(_embedded[property])];
|
||||
});
|
||||
return uuids;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected deserializeAndCache(obj): Array<string> {
|
||||
let type: ResourceType;
|
||||
const isArray = Array.isArray(obj);
|
||||
|
||||
if (isArray && isEmpty(obj)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (isArray) {
|
||||
type = obj[0]["type"];
|
||||
}
|
||||
else {
|
||||
type = obj["type"];
|
||||
}
|
||||
|
||||
if (hasValue(type)) {
|
||||
const normObjConstructor = NormalizedObjectFactory.getConstructor(type);
|
||||
|
||||
if (hasValue(normObjConstructor)) {
|
||||
const serializer = new DSpaceRESTv2Serializer(normObjConstructor);
|
||||
|
||||
if (isArray) {
|
||||
obj.forEach(o => {
|
||||
if (isNotEmpty(o._embedded)) {
|
||||
this.processEmbedded(o._embedded);
|
||||
}
|
||||
});
|
||||
const normalizedObjArr = serializer.deserializeArray(obj);
|
||||
normalizedObjArr.forEach(t => this.addToObjectCache(t));
|
||||
return normalizedObjArr.map(t => t.uuid);
|
||||
}
|
||||
else {
|
||||
if (isNotEmpty(obj._embedded)) {
|
||||
this.processEmbedded(obj._embedded);
|
||||
}
|
||||
const normalizedObj = serializer.deserialize(obj);
|
||||
this.addToObjectCache(normalizedObj);
|
||||
return [normalizedObj.uuid];
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
//TODO move check to Validator?
|
||||
throw new Error(`The server returned an object with an unknown a known type: ${type}`);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
//TODO move check to Validator
|
||||
throw new Error(`The server returned an object without a type: ${JSON.stringify(obj)}`);
|
||||
}
|
||||
}
|
||||
|
||||
protected addToObjectCache(co: CacheableObject): void {
|
||||
if (hasNoValue(co) || hasNoValue(co.uuid)) {
|
||||
throw new Error('The server returned an invalid object');
|
||||
|
@@ -5,28 +5,25 @@ import { GenericConstructor } from "../shared/generic-constructor";
|
||||
export class Request<T> {
|
||||
constructor(
|
||||
public href: string,
|
||||
public resourceType: GenericConstructor<T>
|
||||
) {}
|
||||
}
|
||||
|
||||
export class FindByIDRequest<T> extends Request<T> {
|
||||
constructor(
|
||||
href: string,
|
||||
resourceType: GenericConstructor<T>,
|
||||
public resourceID: string
|
||||
) {
|
||||
super(href, resourceType);
|
||||
super(href);
|
||||
}
|
||||
}
|
||||
|
||||
export class FindAllRequest<T> extends Request<T> {
|
||||
constructor(
|
||||
href: string,
|
||||
resourceType: GenericConstructor<T>,
|
||||
public scopeID?: string,
|
||||
public paginationOptions?: PaginationOptions,
|
||||
public sortOptions?: SortOptions
|
||||
) {
|
||||
super(href, resourceType);
|
||||
super(href);
|
||||
}
|
||||
}
|
||||
|
@@ -8,7 +8,6 @@ import { RequestConfigureAction, RequestExecuteAction } from "./request.actions"
|
||||
import { ResponseCacheService } from "../cache/response-cache.service";
|
||||
import { ObjectCacheService } from "../cache/object-cache.service";
|
||||
import { CacheableObject } from "../cache/object-cache.reducer";
|
||||
import { GenericConstructor } from "../shared/generic-constructor";
|
||||
|
||||
@Injectable()
|
||||
export class RequestService {
|
||||
@@ -35,14 +34,13 @@ export class RequestService {
|
||||
return this.store.select<RequestEntry>('core', 'data', 'request', href);
|
||||
}
|
||||
|
||||
configure<T extends CacheableObject>(href: string, normalizedType: GenericConstructor<T>): void {
|
||||
const isCached = this.objectCache.hasBySelfLink(href);
|
||||
const isPending = this.isPending(href);
|
||||
configure<T extends CacheableObject>(request: Request<T>): void {
|
||||
const isCached = this.objectCache.hasBySelfLink(request.href);
|
||||
const isPending = this.isPending(request.href);
|
||||
|
||||
if (!(isCached || isPending)) {
|
||||
const request = new Request(href, normalizedType);
|
||||
this.store.dispatch(new RequestConfigureAction(request));
|
||||
this.store.dispatch(new RequestExecuteAction(href));
|
||||
this.store.dispatch(new RequestExecuteAction(request.href));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -84,14 +84,10 @@ describe("DSpaceRESTv2Serializer", () => {
|
||||
|
||||
it("should turn a valid document describing a single entity in to a valid model", () => {
|
||||
const serializer = new DSpaceRESTv2Serializer(TestModel);
|
||||
const doc = {
|
||||
"_embedded": testResponses[0],
|
||||
};
|
||||
const model = serializer.deserialize(testResponses[0]);
|
||||
|
||||
const model = serializer.deserialize(doc);
|
||||
|
||||
expect(model.id).toBe(doc._embedded.id);
|
||||
expect(model.name).toBe(doc._embedded.name);
|
||||
expect(model.id).toBe(testResponses[0].id);
|
||||
expect(model.name).toBe(testResponses[0].name);
|
||||
});
|
||||
|
||||
//TODO cant implement/test this yet - depends on how relationships
|
||||
@@ -127,12 +123,8 @@ describe("DSpaceRESTv2Serializer", () => {
|
||||
|
||||
it("should throw an error when dealing with a document describing an array", () => {
|
||||
const serializer = new DSpaceRESTv2Serializer(TestModel);
|
||||
const doc = {
|
||||
"_embedded": testResponses
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
serializer.deserialize(doc);
|
||||
serializer.deserialize(testResponses);
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
|
@@ -3,6 +3,7 @@ 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 { hasNoValue, hasValue } from "../../shared/empty.util";
|
||||
|
||||
/**
|
||||
* This Serializer turns responses from v2 of DSpace's REST API
|
||||
@@ -49,13 +50,13 @@ export class DSpaceRESTv2Serializer<T> implements Serializer<T> {
|
||||
* @param response An object returned by the backend
|
||||
* @returns a model of type T
|
||||
*/
|
||||
deserialize(response: DSpaceRESTV2Response): T {
|
||||
deserialize(response: any): T {
|
||||
// TODO enable validation, once rest data stabilizes
|
||||
// new DSpaceRESTv2Validator(response).validate();
|
||||
if (Array.isArray(response._embedded)) {
|
||||
if (Array.isArray(response)) {
|
||||
throw new Error('Expected a single model, use deserializeArray() instead');
|
||||
}
|
||||
let normalized = Object.assign({}, response._embedded, this.normalizeLinks(response._embedded._links));
|
||||
let normalized = Object.assign({}, response, this.normalizeLinks(response._links));
|
||||
return <T> Deserialize(normalized, this.modelType);
|
||||
}
|
||||
|
||||
@@ -65,13 +66,13 @@ export class DSpaceRESTv2Serializer<T> implements Serializer<T> {
|
||||
* @param response An object returned by the backend
|
||||
* @returns an array of models of type T
|
||||
*/
|
||||
deserializeArray(response: DSpaceRESTV2Response): Array<T> {
|
||||
deserializeArray(response: any): Array<T> {
|
||||
//TODO enable validation, once rest data stabilizes
|
||||
// new DSpaceRESTv2Validator(response).validate();
|
||||
if (!Array.isArray(response._embedded)) {
|
||||
if (!Array.isArray(response)) {
|
||||
throw new Error('Expected an Array, use deserialize() instead');
|
||||
}
|
||||
let normalized = response._embedded.map((resource) => {
|
||||
let normalized = response.map((resource) => {
|
||||
return Object.assign({}, resource, this.normalizeLinks(resource._links));
|
||||
});
|
||||
|
||||
|
@@ -2,6 +2,7 @@ import { Metadatum } from "./metadatum.model"
|
||||
import { isEmpty, isNotEmpty } from "../../shared/empty.util";
|
||||
import { CacheableObject } from "../cache/object-cache.reducer";
|
||||
import { RemoteData } from "../data/remote-data";
|
||||
import { ResourceType } from "./resource-type";
|
||||
|
||||
/**
|
||||
* An abstract model class for a DSpaceObject.
|
||||
@@ -23,7 +24,7 @@ export abstract class DSpaceObject implements CacheableObject {
|
||||
/**
|
||||
* A string representing the kind of DSpaceObject, e.g. community, item, …
|
||||
*/
|
||||
type: string;
|
||||
type: ResourceType;
|
||||
|
||||
/**
|
||||
* The name for this DSpaceObject
|
||||
|
11
src/app/core/shared/resource-type.ts
Normal file
11
src/app/core/shared/resource-type.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* TODO replace with actual string enum after upgrade to TypeScript 2.4:
|
||||
* https://github.com/Microsoft/TypeScript/pull/15486
|
||||
*/
|
||||
export enum ResourceType {
|
||||
Bundle = <any> "bundle",
|
||||
Bitstream = <any> "bitstream",
|
||||
Item = <any> "item",
|
||||
Collection = <any> "collection",
|
||||
Community = <any> "community"
|
||||
}
|
@@ -82,7 +82,7 @@ export function createMockApi() {
|
||||
let id = req.params.community_id;
|
||||
try {
|
||||
req.community_id = id;
|
||||
req.community = COMMUNITIES.find((community) => {
|
||||
req.community = COMMUNITIES["communities"].find((community) => {
|
||||
return community.id === id;
|
||||
});
|
||||
next();
|
||||
@@ -143,7 +143,7 @@ export function createMockApi() {
|
||||
let id = req.params.collection_id;
|
||||
try {
|
||||
req.collection_id = id;
|
||||
req.collection = COLLECTIONS.find((collection) => {
|
||||
req.collection = COLLECTIONS["collections"].find((collection) => {
|
||||
return collection.id === id;
|
||||
});
|
||||
next();
|
||||
@@ -205,7 +205,7 @@ export function createMockApi() {
|
||||
let id = req.params.item_id;
|
||||
try {
|
||||
req.item_id = id;
|
||||
req.item = ITEMS.find((item) => {
|
||||
req.item = ITEMS["items"].find((item) => {
|
||||
return item.id === id;
|
||||
});
|
||||
next();
|
||||
@@ -250,7 +250,7 @@ export function createMockApi() {
|
||||
let id = req.params.bundle_id;
|
||||
try {
|
||||
req.bundle_id = id;
|
||||
req.bundle = BUNDLES.find((bundle) => {
|
||||
req.bundle = BUNDLES["bundles"].find((bundle) => {
|
||||
return bundle.id === id;
|
||||
});
|
||||
next();
|
||||
@@ -280,7 +280,7 @@ export function createMockApi() {
|
||||
let id = req.params.bitstream_id;
|
||||
try {
|
||||
req.bitstream_id = id;
|
||||
req.bitstream = BITSTREAMS.find((bitstream) => {
|
||||
req.bitstream = BITSTREAMS["bitstreams"].find((bitstream) => {
|
||||
return bitstream.id === id;
|
||||
});
|
||||
next();
|
||||
|
@@ -1,4 +1,5 @@
|
||||
export const BITSTREAMS = [
|
||||
export const BITSTREAMS = {
|
||||
"bitstreams": [
|
||||
{
|
||||
"_links": {
|
||||
"self": { "href": "/bitstreams/3678" },
|
||||
@@ -43,4 +44,5 @@ export const BITSTREAMS = [
|
||||
"format": "JPEG",
|
||||
"mimetype": "image/jpeg"
|
||||
}
|
||||
];
|
||||
]
|
||||
};
|
||||
|
@@ -1,4 +1,5 @@
|
||||
export const BUNDLES = [
|
||||
export const BUNDLES = {
|
||||
"bundles": [
|
||||
{
|
||||
"_links": {
|
||||
"self": { "href": "/bundles/2355" },
|
||||
@@ -37,4 +38,5 @@ export const BUNDLES = [
|
||||
{ "key": "dc.title", "value": "THUMBNAIL", "language": "en" }
|
||||
]
|
||||
}
|
||||
];
|
||||
]
|
||||
};
|
||||
|
@@ -1,4 +1,5 @@
|
||||
export const COLLECTIONS = [
|
||||
export const COLLECTIONS = {
|
||||
"collections": [
|
||||
{
|
||||
"_links": {
|
||||
"self": { "href": "/collections/5179" },
|
||||
@@ -71,4 +72,5 @@ export const COLLECTIONS = [
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
]
|
||||
};
|
||||
|
@@ -1,4 +1,5 @@
|
||||
export const COMMUNITIES = [
|
||||
export const COMMUNITIES = {
|
||||
"communities": [
|
||||
{
|
||||
"name": "Community 1",
|
||||
"handle": "10673/1",
|
||||
@@ -83,4 +84,5 @@ export const COMMUNITIES = [
|
||||
]
|
||||
}
|
||||
}
|
||||
];
|
||||
]
|
||||
};
|
||||
|
@@ -1,4 +1,5 @@
|
||||
export const ITEMS = [
|
||||
export const ITEMS = {
|
||||
"items": [
|
||||
{
|
||||
"_links": {
|
||||
"self": {
|
||||
@@ -90,8 +91,87 @@ export const ITEMS = [
|
||||
"value": "(not specified)",
|
||||
"language": "en"
|
||||
}
|
||||
],
|
||||
"_embedded": {
|
||||
"parents": [
|
||||
{
|
||||
"_links": {
|
||||
"self": { "href": "/collections/5179" },
|
||||
"items": [
|
||||
{ "href": "/items/8871" },
|
||||
{ "href": "/items/9978" }
|
||||
]
|
||||
},
|
||||
"id": "5179",
|
||||
"uuid": "9e32a2e2-6b91-4236-a361-995ccdc14c60",
|
||||
"type": "collection",
|
||||
"name": "A Test Collection",
|
||||
"handle": "123456789/5179",
|
||||
},
|
||||
{
|
||||
"_links": {
|
||||
"self": { "href": "/collections/6547" },
|
||||
"items": [
|
||||
{ "href": "/items/8871" },
|
||||
{ "href": "/items/9978" }
|
||||
]
|
||||
},
|
||||
"id": "6547",
|
||||
"uuid": "598ce822-c357-46f3-ab70-63724d02d6ad",
|
||||
"type": "collection",
|
||||
"name": "Another Test Collection",
|
||||
"handle": "123456789/6547",
|
||||
}
|
||||
],
|
||||
"bundles": [
|
||||
{
|
||||
"_links": {
|
||||
"self": { "href": "/bundles/2355" },
|
||||
"items": [
|
||||
{ "href": "/items/8871" }
|
||||
],
|
||||
"bitstreams": [
|
||||
{ "href": "/bitstreams/3678" },
|
||||
],
|
||||
"primaryBitstream": { "href": "/bitstreams/3678" }
|
||||
},
|
||||
"id": "2355",
|
||||
"uuid": "35e0606d-5e18-4f9c-aa61-74fc751cc3f9",
|
||||
"type": "bundle",
|
||||
"name": "ORIGINAL",
|
||||
"metadata": [
|
||||
{ "key": "dc.title", "value": "ORIGINAL", "language": "en" }
|
||||
],
|
||||
"_embedded": {
|
||||
"bitstreams": [
|
||||
{
|
||||
"_links": {
|
||||
"self": { "href": "/bitstreams/3678" },
|
||||
"bundle": { "href": "/bundles/35e0606d-5e18-4f9c-aa61-74fc751cc3f9" },
|
||||
"retrieve": { "href": "/bitstreams/43c57c2b-206f-4645-8c8f-5f10c84b09fa/retrieve" }
|
||||
},
|
||||
"id": "3678",
|
||||
"uuid": "43c57c2b-206f-4645-8c8f-5f10c84b09fa",
|
||||
"type": "bitstream",
|
||||
"name": "do_open_access_CRL.pdf",
|
||||
"size": 636626,
|
||||
"checksum": {
|
||||
"value": "063dfbbbac873aa3fca479b878eccff3",
|
||||
"algorithm": "MD5"
|
||||
},
|
||||
"metadata": [
|
||||
{ "key": "dc.title", "value": "do_open_access_CRL.pdf", "language": null },
|
||||
{ "key": "dc.description", "value": "Conference Paper", "language": "en" }
|
||||
],
|
||||
"format": "Adobe PDF",
|
||||
"mimetype": "application/pdf"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"_links": {
|
||||
"self": {
|
||||
@@ -163,6 +243,39 @@ export const ITEMS = [
|
||||
"value": "(not specified)",
|
||||
"language": "en"
|
||||
}
|
||||
],
|
||||
"_embedded": {
|
||||
"parents": [
|
||||
{
|
||||
"_links": {
|
||||
"self": { "href": "/collections/5179" },
|
||||
"items": [
|
||||
{ "href": "/items/8871" },
|
||||
{ "href": "/items/9978" }
|
||||
]
|
||||
},
|
||||
"id": "5179",
|
||||
"uuid": "9e32a2e2-6b91-4236-a361-995ccdc14c60",
|
||||
"type": "collection",
|
||||
"name": "A Test Collection",
|
||||
"handle": "123456789/5179",
|
||||
},
|
||||
{
|
||||
"_links": {
|
||||
"self": { "href": "/collections/6547" },
|
||||
"items": [
|
||||
{ "href": "/items/8871" },
|
||||
{ "href": "/items/9978" }
|
||||
]
|
||||
},
|
||||
"id": "6547",
|
||||
"uuid": "598ce822-c357-46f3-ab70-63724d02d6ad",
|
||||
"type": "collection",
|
||||
"name": "Another Test Collection",
|
||||
"handle": "123456789/6547",
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@@ -1,4 +1,5 @@
|
||||
export const METADATA = [
|
||||
export const METADATA = {
|
||||
"metadata": [
|
||||
{
|
||||
"type": "metadata",
|
||||
"id": "d58a3098-b390-4cd6-8f52-b088b3daa637",
|
||||
@@ -179,4 +180,5 @@ export const METADATA = [
|
||||
"language": "en"
|
||||
}
|
||||
}
|
||||
];
|
||||
]
|
||||
};
|
||||
|
Reference in New Issue
Block a user