mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-08 18:44:14 +00:00
refactoring
This commit is contained in:
21
src/app/core/cache/builders/bitstream-builder.ts
vendored
21
src/app/core/cache/builders/bitstream-builder.ts
vendored
@@ -1,21 +0,0 @@
|
|||||||
import { Bitstream } from "../../shared/bitstream.model";
|
|
||||||
import { RequestService } from "../../data/request.service";
|
|
||||||
import { hasValue } from "../../../shared/empty.util";
|
|
||||||
import { NormalizedBitstream } from "../models/normalized-bitstream.model";
|
|
||||||
import { RemoteDataBuildService } from "./remote-data-build.service";
|
|
||||||
import { DomainModelBuilder } from "./domain-model-builder";
|
|
||||||
|
|
||||||
export class BitstreamBuilder extends DomainModelBuilder<NormalizedBitstream, Bitstream> {
|
|
||||||
constructor(
|
|
||||||
private requestService: RequestService,
|
|
||||||
private rdbService: RemoteDataBuildService,
|
|
||||||
) {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
build(): Bitstream {
|
|
||||||
let links: any = {};
|
|
||||||
//TODO
|
|
||||||
return Object.assign(new Bitstream(), this.normalized, links);
|
|
||||||
}
|
|
||||||
}
|
|
39
src/app/core/cache/builders/build-decorators.ts
vendored
Normal file
39
src/app/core/cache/builders/build-decorators.ts
vendored
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import { GenericConstructor } from "../../shared/generic-constructor";
|
||||||
|
import { CacheableObject } from "../object-cache.reducer";
|
||||||
|
|
||||||
|
const mapsToMetadataKey = Symbol("mapsTo");
|
||||||
|
const relationshipKey = Symbol("relationship");
|
||||||
|
|
||||||
|
const relationshipMap = new Map();
|
||||||
|
|
||||||
|
export const mapsTo = function(value: GenericConstructor<CacheableObject>) {
|
||||||
|
return Reflect.metadata(mapsToMetadataKey, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getMapsTo = function(target: any) {
|
||||||
|
return Reflect.getOwnMetadata(mapsToMetadataKey, target);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const relationship = function(value: any): any {
|
||||||
|
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
||||||
|
if (!target || !propertyKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let metaDataList : Array<string> = relationshipMap.get(target.constructor) || [];
|
||||||
|
if (metaDataList.indexOf(propertyKey) === -1) {
|
||||||
|
metaDataList.push(propertyKey);
|
||||||
|
}
|
||||||
|
relationshipMap.set(target.constructor, metaDataList);
|
||||||
|
|
||||||
|
return Reflect.metadata(relationshipKey, value).apply(this, arguments);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getResourceType = function(target: any, propertyKey: string) {
|
||||||
|
return Reflect.getMetadata(relationshipKey, target, propertyKey);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getRelationships = function(target: any) {
|
||||||
|
return relationshipMap.get(target);
|
||||||
|
};
|
34
src/app/core/cache/builders/bundle-builder.ts
vendored
34
src/app/core/cache/builders/bundle-builder.ts
vendored
@@ -1,34 +0,0 @@
|
|||||||
import { Bundle } from "../../shared/bundle.model";
|
|
||||||
import { RequestService } from "../../data/request.service";
|
|
||||||
import { NormalizedBundle } from "../models/normalized-bundle.model";
|
|
||||||
import { hasValue } from "../../../shared/empty.util";
|
|
||||||
import { NormalizedBitstream } from "../models/normalized-bitstream.model";
|
|
||||||
import { RemoteDataBuildService } from "./remote-data-build.service";
|
|
||||||
import { DomainModelBuilder } from "./domain-model-builder";
|
|
||||||
import { BitstreamBuilder } from "./bitstream-builder";
|
|
||||||
|
|
||||||
export class BundleBuilder extends DomainModelBuilder<NormalizedBundle, Bundle> {
|
|
||||||
constructor(
|
|
||||||
private requestService: RequestService,
|
|
||||||
private rdbService: RemoteDataBuildService,
|
|
||||||
) {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
build(): Bundle {
|
|
||||||
let links: any = {};
|
|
||||||
|
|
||||||
if (hasValue(this.normalized.bitstreams)) {
|
|
||||||
this.normalized.bitstreams.forEach((href: string) => {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.requestService.configure(href, NormalizedBitstream);
|
|
||||||
},0);
|
|
||||||
});
|
|
||||||
|
|
||||||
links.bitstreams = this.normalized.bitstreams.map((href: string) => {
|
|
||||||
return this.rdbService.buildSingle(href, NormalizedBitstream, new BitstreamBuilder(this.requestService, this.rdbService));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return Object.assign(new Bundle(), this.normalized, links);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,34 +0,0 @@
|
|||||||
import { Collection } from "../../shared/collection.model";
|
|
||||||
import { RequestService } from "../../data/request.service";
|
|
||||||
import { NormalizedCollection } from "../models/normalized-collection.model";
|
|
||||||
import { hasValue } from "../../../shared/empty.util";
|
|
||||||
import { NormalizedItem } from "../models/normalized-item.model";
|
|
||||||
import { RemoteDataBuildService } from "./remote-data-build.service";
|
|
||||||
import { DomainModelBuilder } from "./domain-model-builder";
|
|
||||||
import { ItemBuilder } from "./item-builder";
|
|
||||||
|
|
||||||
export class CollectionBuilder extends DomainModelBuilder<NormalizedCollection, Collection> {
|
|
||||||
constructor(
|
|
||||||
private requestService: RequestService,
|
|
||||||
private rdbService: RemoteDataBuildService,
|
|
||||||
) {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
build(): Collection {
|
|
||||||
let links: any = {};
|
|
||||||
|
|
||||||
if (hasValue(this.normalized.items)) {
|
|
||||||
this.normalized.items.forEach((href: string) => {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.requestService.configure(href, NormalizedItem)
|
|
||||||
},0);
|
|
||||||
});
|
|
||||||
|
|
||||||
links.items = this.normalized.items.map((href: string) => {
|
|
||||||
return this.rdbService.buildSingle(href, NormalizedItem, new ItemBuilder(this.requestService, this.rdbService));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return Object.assign(new Collection(), this.normalized, links);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,21 +0,0 @@
|
|||||||
import { CacheableObject } from "../object-cache.reducer";
|
|
||||||
|
|
||||||
export abstract class DomainModelBuilder<TNormalized extends CacheableObject, TDomain> {
|
|
||||||
protected href: string;
|
|
||||||
protected normalized: TNormalized;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
}
|
|
||||||
|
|
||||||
setHref(href: string): DomainModelBuilder<TNormalized, TDomain> {
|
|
||||||
this.href = href;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
setNormalized(normalized: TNormalized): DomainModelBuilder<TNormalized, TDomain> {
|
|
||||||
this.normalized = normalized;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract build(): TDomain;
|
|
||||||
}
|
|
34
src/app/core/cache/builders/item-builder.ts
vendored
34
src/app/core/cache/builders/item-builder.ts
vendored
@@ -1,34 +0,0 @@
|
|||||||
import { Item } from "../../shared/item.model";
|
|
||||||
import { RequestService } from "../../data/request.service";
|
|
||||||
import { NormalizedItem } from "../models/normalized-item.model";
|
|
||||||
import { hasValue } from "../../../shared/empty.util";
|
|
||||||
import { NormalizedBundle } from "../models/normalized-bundle.model";
|
|
||||||
import { RemoteDataBuildService } from "./remote-data-build.service";
|
|
||||||
import { DomainModelBuilder } from "./domain-model-builder";
|
|
||||||
import { BundleBuilder } from "./bundle-builder";
|
|
||||||
|
|
||||||
export class ItemBuilder extends DomainModelBuilder<NormalizedItem, Item> {
|
|
||||||
constructor(
|
|
||||||
private requestService: RequestService,
|
|
||||||
private rdbService: RemoteDataBuildService,
|
|
||||||
) {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
build(): Item {
|
|
||||||
let links: any = {};
|
|
||||||
|
|
||||||
if (hasValue(this.normalized.bundles)) {
|
|
||||||
this.normalized.bundles.forEach((href: string) => {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.requestService.configure(href, NormalizedBundle)
|
|
||||||
},0);
|
|
||||||
});
|
|
||||||
|
|
||||||
links.bundles = this.normalized.bundles.map((href: string) => {
|
|
||||||
return this.rdbService.buildSingle(href, NormalizedBundle, new BundleBuilder(this.requestService, this.rdbService));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return Object.assign(new Item(), this.normalized, links);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,5 +1,4 @@
|
|||||||
import { Injectable } from "@angular/core";
|
import { Injectable } from "@angular/core";
|
||||||
import { GenericConstructor } from "../../shared/generic-constructor";
|
|
||||||
import { CacheableObject } from "../object-cache.reducer";
|
import { CacheableObject } from "../object-cache.reducer";
|
||||||
import { ObjectCacheService } from "../object-cache.service";
|
import { ObjectCacheService } from "../object-cache.service";
|
||||||
import { RequestService } from "../../data/request.service";
|
import { RequestService } from "../../data/request.service";
|
||||||
@@ -12,7 +11,8 @@ import { ResponseCacheEntry } from "../response-cache.reducer";
|
|||||||
import { ErrorResponse, SuccessResponse } from "../response-cache.models";
|
import { ErrorResponse, SuccessResponse } from "../response-cache.models";
|
||||||
import { Observable } from "rxjs/Observable";
|
import { Observable } from "rxjs/Observable";
|
||||||
import { RemoteData } from "../../data/remote-data";
|
import { RemoteData } from "../../data/remote-data";
|
||||||
import { DomainModelBuilder } from "./domain-model-builder";
|
import { GenericConstructor } from "../../shared/generic-constructor";
|
||||||
|
import { getMapsTo, getResourceType, getRelationships } from "./build-decorators";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class RemoteDataBuildService {
|
export class RemoteDataBuildService {
|
||||||
@@ -26,8 +26,7 @@ export class RemoteDataBuildService {
|
|||||||
|
|
||||||
buildSingle<TNormalized extends CacheableObject, TDomain>(
|
buildSingle<TNormalized extends CacheableObject, TDomain>(
|
||||||
href: string,
|
href: string,
|
||||||
normalizedType: GenericConstructor<TNormalized>,
|
normalizedType: GenericConstructor<TNormalized>
|
||||||
builder: DomainModelBuilder<TNormalized, TDomain>
|
|
||||||
): RemoteData<TDomain> {
|
): RemoteData<TDomain> {
|
||||||
const requestObs = this.store.select<RequestEntry>('core', 'data', 'request', href);
|
const requestObs = this.store.select<RequestEntry>('core', 'data', 'request', href);
|
||||||
const responseCacheObs = this.responseCache.get(href);
|
const responseCacheObs = this.responseCache.get(href);
|
||||||
@@ -46,24 +45,22 @@ export class RemoteDataBuildService {
|
|||||||
|
|
||||||
const payload =
|
const payload =
|
||||||
Observable.race(
|
Observable.race(
|
||||||
this.objectCache.getBySelfLink<TNormalized>(href, normalizedType),
|
this.objectCache.getBySelfLink<TNormalized>(href),
|
||||||
responseCacheObs
|
responseCacheObs
|
||||||
.filter((entry: ResponseCacheEntry) => hasValue(entry) && entry.response.isSuccessful)
|
.filter((entry: ResponseCacheEntry) => hasValue(entry) && entry.response.isSuccessful)
|
||||||
.map((entry: ResponseCacheEntry) => (<SuccessResponse> entry.response).resourceUUIDs)
|
.map((entry: ResponseCacheEntry) => (<SuccessResponse> entry.response).resourceUUIDs)
|
||||||
.flatMap((resourceUUIDs: Array<string>) => {
|
.flatMap((resourceUUIDs: Array<string>) => {
|
||||||
if (isNotEmpty(resourceUUIDs)) {
|
if (isNotEmpty(resourceUUIDs)) {
|
||||||
return this.objectCache.get(resourceUUIDs[0], normalizedType);
|
return this.objectCache.get(resourceUUIDs[0]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return Observable.of(undefined);
|
return Observable.of(undefined);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
).map((normalized: TNormalized) => builder
|
).map((normalized: TNormalized) => {
|
||||||
.setHref(href)
|
return this.build<TNormalized, TDomain>(normalized);
|
||||||
.setNormalized(normalized)
|
});
|
||||||
.build()
|
|
||||||
);
|
|
||||||
|
|
||||||
return new RemoteData(
|
return new RemoteData(
|
||||||
href,
|
href,
|
||||||
@@ -77,8 +74,7 @@ export class RemoteDataBuildService {
|
|||||||
|
|
||||||
buildList<TNormalized extends CacheableObject, TDomain>(
|
buildList<TNormalized extends CacheableObject, TDomain>(
|
||||||
href: string,
|
href: string,
|
||||||
normalizedType: GenericConstructor<TNormalized>,
|
normalizedType: GenericConstructor<TNormalized>
|
||||||
builder: DomainModelBuilder<TNormalized, TDomain>
|
|
||||||
): RemoteData<TDomain[]> {
|
): RemoteData<TDomain[]> {
|
||||||
const requestObs = this.store.select<RequestEntry>('core', 'data', 'request', href);
|
const requestObs = this.store.select<RequestEntry>('core', 'data', 'request', href);
|
||||||
const responseCacheObs = this.responseCache.get(href);
|
const responseCacheObs = this.responseCache.get(href);
|
||||||
@@ -99,13 +95,10 @@ export class RemoteDataBuildService {
|
|||||||
.filter((entry: ResponseCacheEntry) => hasValue(entry) && entry.response.isSuccessful)
|
.filter((entry: ResponseCacheEntry) => hasValue(entry) && entry.response.isSuccessful)
|
||||||
.map((entry: ResponseCacheEntry) => (<SuccessResponse> entry.response).resourceUUIDs)
|
.map((entry: ResponseCacheEntry) => (<SuccessResponse> entry.response).resourceUUIDs)
|
||||||
.flatMap((resourceUUIDs: Array<string>) => {
|
.flatMap((resourceUUIDs: Array<string>) => {
|
||||||
return this.objectCache.getList(resourceUUIDs, normalizedType)
|
return this.objectCache.getList(resourceUUIDs)
|
||||||
.map((normList: TNormalized[]) => {
|
.map((normList: TNormalized[]) => {
|
||||||
return normList.map((normalized: TNormalized) => {
|
return normList.map((normalized: TNormalized) => {
|
||||||
return builder
|
return this.build<TNormalized, TDomain>(normalized);
|
||||||
.setHref(href)
|
|
||||||
.setNormalized(normalized)
|
|
||||||
.build();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -120,4 +113,42 @@ export class RemoteDataBuildService {
|
|||||||
payload
|
payload
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
build<TNormalized extends CacheableObject, TDomain>(normalized: TNormalized): TDomain {
|
||||||
|
let links: any = {};
|
||||||
|
|
||||||
|
const relationships = getRelationships(normalized.constructor) || [];
|
||||||
|
|
||||||
|
relationships.forEach((relationship: string) => {
|
||||||
|
if (hasValue(normalized[relationship])) {
|
||||||
|
const resourceType = getResourceType(normalized, relationship);
|
||||||
|
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, resourceType)
|
||||||
|
});
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
links[relationship] = normalized[relationship].map((href: string) => {
|
||||||
|
return this.buildSingle(href, resourceType);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// 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], resourceType);
|
||||||
|
},0);
|
||||||
|
|
||||||
|
links[relationship] = this.buildSingle(normalized[relationship], resourceType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const constructor = getMapsTo(normalized.constructor);
|
||||||
|
return Object.assign(new constructor(), normalized, links);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,9 @@
|
|||||||
import { inheritSerialization } from "cerialize";
|
import { inheritSerialization } from "cerialize";
|
||||||
import { NormalizedDSpaceObject } from "./normalized-dspace-object.model";
|
import { NormalizedDSpaceObject } from "./normalized-dspace-object.model";
|
||||||
|
import { Bitstream } from "../../shared/bitstream.model";
|
||||||
|
import { mapsTo } from "../builders/build-decorators";
|
||||||
|
|
||||||
|
@mapsTo(Bitstream)
|
||||||
@inheritSerialization(NormalizedDSpaceObject)
|
@inheritSerialization(NormalizedDSpaceObject)
|
||||||
export class NormalizedBitstream extends NormalizedDSpaceObject {
|
export class NormalizedBitstream extends NormalizedDSpaceObject {
|
||||||
|
|
||||||
|
@@ -1,12 +1,17 @@
|
|||||||
import { autoserialize, inheritSerialization } from "cerialize";
|
import { autoserialize, inheritSerialization } from "cerialize";
|
||||||
import { NormalizedDSpaceObject } from "./normalized-dspace-object.model";
|
import { NormalizedDSpaceObject } from "./normalized-dspace-object.model";
|
||||||
|
import { Bundle } from "../../shared/bundle.model";
|
||||||
|
import { mapsTo, relationship } from "../builders/build-decorators";
|
||||||
|
import { NormalizedBitstream } from "./normalized-bitstream.model";
|
||||||
|
|
||||||
|
@mapsTo(Bundle)
|
||||||
@inheritSerialization(NormalizedDSpaceObject)
|
@inheritSerialization(NormalizedDSpaceObject)
|
||||||
export class NormalizedBundle extends NormalizedDSpaceObject {
|
export class NormalizedBundle extends NormalizedDSpaceObject {
|
||||||
/**
|
/**
|
||||||
* The primary bitstream of this Bundle
|
* The primary bitstream of this Bundle
|
||||||
*/
|
*/
|
||||||
@autoserialize
|
@autoserialize
|
||||||
|
@relationship(NormalizedBitstream)
|
||||||
primaryBitstream: string;
|
primaryBitstream: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,5 +25,6 @@ export class NormalizedBundle extends NormalizedDSpaceObject {
|
|||||||
owner: string;
|
owner: string;
|
||||||
|
|
||||||
@autoserialize
|
@autoserialize
|
||||||
|
@relationship(NormalizedBitstream)
|
||||||
bitstreams: Array<string>;
|
bitstreams: Array<string>;
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,10 @@
|
|||||||
import { autoserialize, inheritSerialization, autoserializeAs } from "cerialize";
|
import { autoserialize, inheritSerialization, autoserializeAs } from "cerialize";
|
||||||
import { NormalizedDSpaceObject } from "./normalized-dspace-object.model";
|
import { NormalizedDSpaceObject } from "./normalized-dspace-object.model";
|
||||||
|
import { Collection } from "../../shared/collection.model";
|
||||||
|
import { mapsTo, relationship } from "../builders/build-decorators";
|
||||||
|
import { NormalizedItem } from "./normalized-item.model";
|
||||||
|
|
||||||
|
@mapsTo(Collection)
|
||||||
@inheritSerialization(NormalizedDSpaceObject)
|
@inheritSerialization(NormalizedDSpaceObject)
|
||||||
export class NormalizedCollection extends NormalizedDSpaceObject {
|
export class NormalizedCollection extends NormalizedDSpaceObject {
|
||||||
|
|
||||||
@@ -26,6 +30,7 @@ export class NormalizedCollection extends NormalizedDSpaceObject {
|
|||||||
owner: string;
|
owner: string;
|
||||||
|
|
||||||
@autoserialize
|
@autoserialize
|
||||||
|
@relationship(NormalizedItem)
|
||||||
items: Array<string>;
|
items: Array<string>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,10 @@
|
|||||||
import { inheritSerialization, autoserialize } from "cerialize";
|
import { inheritSerialization, autoserialize } from "cerialize";
|
||||||
import { NormalizedDSpaceObject } from "./normalized-dspace-object.model";
|
import { NormalizedDSpaceObject } from "./normalized-dspace-object.model";
|
||||||
|
import { Item } from "../../shared/item.model";
|
||||||
|
import { mapsTo, relationship } from "../builders/build-decorators";
|
||||||
|
import { NormalizedBundle } from "./normalized-bundle.model";
|
||||||
|
|
||||||
|
@mapsTo(Item)
|
||||||
@inheritSerialization(NormalizedDSpaceObject)
|
@inheritSerialization(NormalizedDSpaceObject)
|
||||||
export class NormalizedItem extends NormalizedDSpaceObject {
|
export class NormalizedItem extends NormalizedDSpaceObject {
|
||||||
|
|
||||||
@@ -36,5 +40,6 @@ export class NormalizedItem extends NormalizedDSpaceObject {
|
|||||||
owner: string;
|
owner: string;
|
||||||
|
|
||||||
@autoserialize
|
@autoserialize
|
||||||
|
@relationship(NormalizedBundle)
|
||||||
bundles: Array<string>;
|
bundles: Array<string>;
|
||||||
}
|
}
|
||||||
|
10
src/app/core/cache/object-cache.service.spec.ts
vendored
10
src/app/core/cache/object-cache.service.spec.ts
vendored
@@ -57,12 +57,12 @@ describe("ObjectCacheService", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("get", () => {
|
describe("get", () => {
|
||||||
it("should return an observable of the cached object with the specified UUID and type", () => {
|
it("should return an observable of the cached object with the specified UUID", () => {
|
||||||
spyOn(store, 'select').and.returnValue(Observable.of(cacheEntry));
|
spyOn(store, 'select').and.returnValue(Observable.of(cacheEntry));
|
||||||
|
|
||||||
let testObj: any;
|
let testObj: any;
|
||||||
//due to the implementation of spyOn above, this subscribe will be synchronous
|
//due to the implementation of spyOn above, this subscribe will be synchronous
|
||||||
service.get(uuid, TestClass).take(1).subscribe(o => testObj = o);
|
service.get(uuid).take(1).subscribe(o => testObj = o);
|
||||||
expect(testObj.uuid).toBe(uuid);
|
expect(testObj.uuid).toBe(uuid);
|
||||||
expect(testObj.foo).toBe("bar");
|
expect(testObj.foo).toBe("bar");
|
||||||
// this only works if testObj is an instance of TestClass
|
// this only works if testObj is an instance of TestClass
|
||||||
@@ -73,18 +73,18 @@ describe("ObjectCacheService", () => {
|
|||||||
spyOn(store, 'select').and.returnValue(Observable.of(invalidCacheEntry));
|
spyOn(store, 'select').and.returnValue(Observable.of(invalidCacheEntry));
|
||||||
|
|
||||||
let getObsHasFired = false;
|
let getObsHasFired = false;
|
||||||
const subscription = service.get(uuid, TestClass).subscribe(o => getObsHasFired = true);
|
const subscription = service.get(uuid).subscribe(o => getObsHasFired = true);
|
||||||
expect(getObsHasFired).toBe(false);
|
expect(getObsHasFired).toBe(false);
|
||||||
subscription.unsubscribe();
|
subscription.unsubscribe();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("getList", () => {
|
describe("getList", () => {
|
||||||
it("should return an observable of the array of cached objects with the specified UUID and type", () => {
|
it("should return an observable of the array of cached objects with the specified UUID", () => {
|
||||||
spyOn(service, 'get').and.returnValue(Observable.of(new TestClass(uuid, "bar")));
|
spyOn(service, 'get').and.returnValue(Observable.of(new TestClass(uuid, "bar")));
|
||||||
|
|
||||||
let testObjs: Array<any>;
|
let testObjs: Array<any>;
|
||||||
service.getList([uuid, uuid], TestClass).take(1).subscribe(arr => testObjs = arr);
|
service.getList([uuid, uuid]).take(1).subscribe(arr => testObjs = arr);
|
||||||
expect(testObjs[0].uuid).toBe(uuid);
|
expect(testObjs[0].uuid).toBe(uuid);
|
||||||
expect(testObjs[0].foo).toBe("bar");
|
expect(testObjs[0].foo).toBe("bar");
|
||||||
expect(testObjs[0].test()).toBe("bar" + uuid);
|
expect(testObjs[0].test()).toBe("bar" + uuid);
|
||||||
|
34
src/app/core/cache/object-cache.service.ts
vendored
34
src/app/core/cache/object-cache.service.ts
vendored
@@ -4,7 +4,6 @@ import { ObjectCacheState, ObjectCacheEntry, CacheableObject } from "./object-ca
|
|||||||
import { AddToObjectCacheAction, RemoveFromObjectCacheAction } from "./object-cache.actions";
|
import { AddToObjectCacheAction, RemoveFromObjectCacheAction } from "./object-cache.actions";
|
||||||
import { Observable } from "rxjs";
|
import { Observable } from "rxjs";
|
||||||
import { hasNoValue } from "../../shared/empty.util";
|
import { hasNoValue } from "../../shared/empty.util";
|
||||||
import { GenericConstructor } from "../shared/generic-constructor";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A service to interact with the object cache
|
* A service to interact with the object cache
|
||||||
@@ -40,53 +39,34 @@ export class ObjectCacheService {
|
|||||||
/**
|
/**
|
||||||
* Get an observable of the object with the specified UUID
|
* Get an observable of the object with the specified UUID
|
||||||
*
|
*
|
||||||
* The type needs to be specified as well, in order to turn
|
|
||||||
* the cached plain javascript object in to an instance of
|
|
||||||
* a class.
|
|
||||||
*
|
|
||||||
* e.g. get('c96588c6-72d3-425d-9d47-fa896255a695', Item)
|
|
||||||
*
|
|
||||||
* @param uuid
|
* @param uuid
|
||||||
* The UUID of the object to get
|
* The UUID of the object to get
|
||||||
* @param type
|
|
||||||
* The type of the object to get
|
|
||||||
* @return Observable<T>
|
* @return Observable<T>
|
||||||
* An observable of the requested object
|
* An observable of the requested object
|
||||||
*/
|
*/
|
||||||
get<T extends CacheableObject>(uuid: string, type: GenericConstructor<T>): Observable<T> {
|
get<T extends CacheableObject>(uuid: string): Observable<T> {
|
||||||
return this.store.select<ObjectCacheEntry>('core', 'cache', 'object', uuid)
|
return this.store.select<ObjectCacheEntry>('core', 'cache', 'object', uuid)
|
||||||
.filter(entry => this.isValid(entry))
|
.filter(entry => this.isValid(entry))
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.map((entry: ObjectCacheEntry) => <T> Object.assign(new type(), entry.data));
|
.map((entry: ObjectCacheEntry) => <T> entry.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
getBySelfLink<T extends CacheableObject>(href: string, type: GenericConstructor<T>): Observable<T> {
|
getBySelfLink<T extends CacheableObject>(href: string): Observable<T> {
|
||||||
return this.store.select<string>('core', 'index', 'href', href)
|
return this.store.select<string>('core', 'index', 'href', href)
|
||||||
.flatMap((uuid: string) => this.get(uuid, type))
|
.flatMap((uuid: string) => this.get<T>(uuid))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an observable for an array of objects of the same type
|
* Get an observable for an array of objects
|
||||||
* with the specified UUIDs
|
* with the specified UUIDs
|
||||||
*
|
*
|
||||||
* The type needs to be specified as well, in order to turn
|
|
||||||
* the cached plain javascript object in to an instance of
|
|
||||||
* a class.
|
|
||||||
*
|
|
||||||
* e.g. getList([
|
|
||||||
* 'c96588c6-72d3-425d-9d47-fa896255a695',
|
|
||||||
* 'cff860da-cf5f-4fda-b8c9-afb7ec0b2d9e'
|
|
||||||
* ], Collection)
|
|
||||||
*
|
|
||||||
* @param uuids
|
* @param uuids
|
||||||
* An array of UUIDs of the objects to get
|
* An array of UUIDs of the objects to get
|
||||||
* @param type
|
|
||||||
* The type of the objects to get
|
|
||||||
* @return Observable<Array<T>>
|
* @return Observable<Array<T>>
|
||||||
*/
|
*/
|
||||||
getList<T extends CacheableObject>(uuids: Array<string>, type: GenericConstructor<T>): Observable<Array<T>> {
|
getList<T extends CacheableObject>(uuids: Array<string>): Observable<Array<T>> {
|
||||||
return Observable.combineLatest(
|
return Observable.combineLatest(
|
||||||
uuids.map((id: string) => this.get<T>(id, type))
|
uuids.map((id: string) => this.get<T>(id))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -8,8 +8,6 @@ import { NormalizedCollection } from "../cache/models/normalized-collection.mode
|
|||||||
import { CoreState } from "../core.reducers";
|
import { CoreState } from "../core.reducers";
|
||||||
import { RequestService } from "./request.service";
|
import { RequestService } from "./request.service";
|
||||||
import { RemoteDataBuildService } from "../cache/builders/remote-data-build.service";
|
import { RemoteDataBuildService } from "../cache/builders/remote-data-build.service";
|
||||||
import { DomainModelBuilder } from "../cache/builders/domain-model-builder";
|
|
||||||
import { CollectionBuilder } from "../cache/builders/collection-builder";
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CollectionDataService extends DataService<NormalizedCollection, Collection> {
|
export class CollectionDataService extends DataService<NormalizedCollection, Collection> {
|
||||||
@@ -25,7 +23,4 @@ export class CollectionDataService extends DataService<NormalizedCollection, Col
|
|||||||
super(NormalizedCollection);
|
super(NormalizedCollection);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getDomainModelBuilder(): CollectionBuilder {
|
|
||||||
return new CollectionBuilder(this.requestService, this.rdbService);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -2,15 +2,14 @@ import { ObjectCacheService } from "../cache/object-cache.service";
|
|||||||
import { ResponseCacheService } from "../cache/response-cache.service";
|
import { ResponseCacheService } from "../cache/response-cache.service";
|
||||||
import { CacheableObject } from "../cache/object-cache.reducer";
|
import { CacheableObject } from "../cache/object-cache.reducer";
|
||||||
import { hasValue } from "../../shared/empty.util";
|
import { hasValue } from "../../shared/empty.util";
|
||||||
import { GenericConstructor } from "../shared/generic-constructor";
|
|
||||||
import { RemoteData } from "./remote-data";
|
import { RemoteData } from "./remote-data";
|
||||||
import { FindAllRequest, FindByIDRequest, Request } from "./request.models";
|
import { FindAllRequest, FindByIDRequest, Request } from "./request.models";
|
||||||
import { Store } from "@ngrx/store";
|
import { Store } from "@ngrx/store";
|
||||||
import { RequestConfigureAction, RequestExecuteAction } from "./request.actions";
|
import { RequestConfigureAction, RequestExecuteAction } from "./request.actions";
|
||||||
import { CoreState } from "../core.reducers";
|
import { CoreState } from "../core.reducers";
|
||||||
import { DomainModelBuilder } from "../cache/builders/domain-model-builder";
|
|
||||||
import { RequestService } from "./request.service";
|
import { RequestService } from "./request.service";
|
||||||
import { RemoteDataBuildService } from "../cache/builders/remote-data-build.service";
|
import { RemoteDataBuildService } from "../cache/builders/remote-data-build.service";
|
||||||
|
import { GenericConstructor } from "../shared/generic-constructor";
|
||||||
|
|
||||||
export abstract class DataService<TNormalized extends CacheableObject, TDomain> {
|
export abstract class DataService<TNormalized extends CacheableObject, TDomain> {
|
||||||
protected abstract objectCache: ObjectCacheService;
|
protected abstract objectCache: ObjectCacheService;
|
||||||
@@ -24,8 +23,6 @@ export abstract class DataService<TNormalized extends CacheableObject, TDomain>
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract getDomainModelBuilder(): DomainModelBuilder<TNormalized, TDomain>;
|
|
||||||
|
|
||||||
protected getFindAllHref(scopeID?): string {
|
protected getFindAllHref(scopeID?): string {
|
||||||
let result = this.endpoint;
|
let result = this.endpoint;
|
||||||
if (hasValue(scopeID)) {
|
if (hasValue(scopeID)) {
|
||||||
@@ -41,7 +38,8 @@ export abstract class DataService<TNormalized extends CacheableObject, TDomain>
|
|||||||
this.store.dispatch(new RequestConfigureAction(request));
|
this.store.dispatch(new RequestConfigureAction(request));
|
||||||
this.store.dispatch(new RequestExecuteAction(href));
|
this.store.dispatch(new RequestExecuteAction(href));
|
||||||
}
|
}
|
||||||
return this.rdbService.buildList(href, this.normalizedResourceType, this.getDomainModelBuilder())
|
return this.rdbService.buildList<TNormalized, TDomain>(href, this.normalizedResourceType);
|
||||||
|
// return this.rdbService.buildList(href);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getFindByIDHref(resourceID): string {
|
protected getFindByIDHref(resourceID): string {
|
||||||
@@ -55,7 +53,8 @@ export abstract class DataService<TNormalized extends CacheableObject, TDomain>
|
|||||||
this.store.dispatch(new RequestConfigureAction(request));
|
this.store.dispatch(new RequestConfigureAction(request));
|
||||||
this.store.dispatch(new RequestExecuteAction(href));
|
this.store.dispatch(new RequestExecuteAction(href));
|
||||||
}
|
}
|
||||||
return this.rdbService.buildSingle(href, this.normalizedResourceType, this.getDomainModelBuilder())
|
return this.rdbService.buildSingle<TNormalized, TDomain>(href, this.normalizedResourceType);
|
||||||
|
// return this.rdbService.buildSingle(href);
|
||||||
}
|
}
|
||||||
|
|
||||||
findByHref(href: string): RemoteData<TDomain> {
|
findByHref(href: string): RemoteData<TDomain> {
|
||||||
@@ -64,7 +63,8 @@ export abstract class DataService<TNormalized extends CacheableObject, TDomain>
|
|||||||
this.store.dispatch(new RequestConfigureAction(request));
|
this.store.dispatch(new RequestConfigureAction(request));
|
||||||
this.store.dispatch(new RequestExecuteAction(href));
|
this.store.dispatch(new RequestExecuteAction(href));
|
||||||
}
|
}
|
||||||
return this.rdbService.buildSingle(href, this.normalizedResourceType, this.getDomainModelBuilder())
|
return this.rdbService.buildSingle<TNormalized, TDomain>(href, this.normalizedResourceType);
|
||||||
|
// return this.rdbService.buildSingle(href));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -8,7 +8,6 @@ import { CoreState } from "../core.reducers";
|
|||||||
import { NormalizedItem } from "../cache/models/normalized-item.model";
|
import { NormalizedItem } from "../cache/models/normalized-item.model";
|
||||||
import { RequestService } from "./request.service";
|
import { RequestService } from "./request.service";
|
||||||
import { RemoteDataBuildService } from "../cache/builders/remote-data-build.service";
|
import { RemoteDataBuildService } from "../cache/builders/remote-data-build.service";
|
||||||
import { ItemBuilder } from "../cache/builders/item-builder";
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ItemDataService extends DataService<NormalizedItem, Item> {
|
export class ItemDataService extends DataService<NormalizedItem, Item> {
|
||||||
@@ -23,8 +22,4 @@ export class ItemDataService extends DataService<NormalizedItem, Item> {
|
|||||||
) {
|
) {
|
||||||
super(NormalizedItem);
|
super(NormalizedItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getDomainModelBuilder(): ItemBuilder {
|
|
||||||
return new ItemBuilder(this.requestService, this.rdbService);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -5,10 +5,10 @@ import { Request } from "./request.models";
|
|||||||
import { hasValue } from "../../shared/empty.util";
|
import { hasValue } from "../../shared/empty.util";
|
||||||
import { Observable } from "rxjs/Observable";
|
import { Observable } from "rxjs/Observable";
|
||||||
import { RequestConfigureAction, RequestExecuteAction } from "./request.actions";
|
import { RequestConfigureAction, RequestExecuteAction } from "./request.actions";
|
||||||
import { GenericConstructor } from "../shared/generic-constructor";
|
|
||||||
import { ResponseCacheService } from "../cache/response-cache.service";
|
import { ResponseCacheService } from "../cache/response-cache.service";
|
||||||
import { ObjectCacheService } from "../cache/object-cache.service";
|
import { ObjectCacheService } from "../cache/object-cache.service";
|
||||||
import { CacheableObject } from "../cache/object-cache.reducer";
|
import { CacheableObject } from "../cache/object-cache.reducer";
|
||||||
|
import { GenericConstructor } from "../shared/generic-constructor";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class RequestService {
|
export class RequestService {
|
||||||
|
@@ -1,8 +1,6 @@
|
|||||||
import { inheritSerialization } from "cerialize";
|
|
||||||
import { DSpaceObject } from "./dspace-object.model";
|
import { DSpaceObject } from "./dspace-object.model";
|
||||||
import { Bundle } from "./bundle.model";
|
import { Bundle } from "./bundle.model";
|
||||||
|
|
||||||
@inheritSerialization(DSpaceObject)
|
|
||||||
export class Bitstream extends DSpaceObject {
|
export class Bitstream extends DSpaceObject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -8,7 +8,7 @@ export const BUNDLES = [
|
|||||||
"bitstreams": [
|
"bitstreams": [
|
||||||
{ "href": "/bitstreams/3678" },
|
{ "href": "/bitstreams/3678" },
|
||||||
],
|
],
|
||||||
"primaryBitstream": { "href": "/bitstreams/43c57c2b-206f-4645-8c8f-5f10c84b09fa" }
|
"primaryBitstream": { "href": "/bitstreams/3678" }
|
||||||
},
|
},
|
||||||
"id": "2355",
|
"id": "2355",
|
||||||
"uuid": "35e0606d-5e18-4f9c-aa61-74fc751cc3f9",
|
"uuid": "35e0606d-5e18-4f9c-aa61-74fc751cc3f9",
|
||||||
@@ -26,7 +26,7 @@ export const BUNDLES = [
|
|||||||
"bitstreams": [
|
"bitstreams": [
|
||||||
{ "href": "/bitstreams/8842" },
|
{ "href": "/bitstreams/8842" },
|
||||||
],
|
],
|
||||||
"primaryBitstream": { "href": "/bitstreams/1a013ecc-fb25-4689-a44f-f1383ad26632" }
|
"primaryBitstream": { "href": "/bitstreams/8842" }
|
||||||
},
|
},
|
||||||
"id": "5687",
|
"id": "5687",
|
||||||
"uuid": "a469c57a-abcf-45c3-83e4-b187ebd708fd",
|
"uuid": "a469c57a-abcf-45c3-83e4-b187ebd708fd",
|
||||||
|
Reference in New Issue
Block a user