refactored getScopeEndpoint method for Collection- and CommunityDataService

This commit is contained in:
Art Lowel
2017-10-18 15:41:00 +02:00
parent 912388c0ab
commit dcea432606
7 changed files with 122 additions and 122 deletions

View File

@@ -41,7 +41,5 @@ export class TopLevelCommunityListComponent {
elementsPerPage: data.pageSize, elementsPerPage: data.pageSize,
sort: { field: data.sortField, direction: data.sortDirection } sort: { field: data.sortField, direction: data.sortDirection }
}); });
this.cds.getScopedEndpoint('7669c72a-3f2a-451f-a3b9-9210e7a4c02f')
.subscribe((c) => console.log('communities', c))
} }
} }

View File

@@ -142,7 +142,7 @@ describe('BrowseService', () => {
expect(result).toBeObservable(expected); expect(result).toBeObservable(expected);
}); });
it('should configure a new BrowseEndpointRequest', (done) => { it('should configure a new BrowseEndpointRequest', (done: DoneFn) => {
const metadatumKey = 'dc.date.issued'; const metadatumKey = 'dc.date.issued';
const linkName = 'items'; const linkName = 'items';
const expected = new BrowseEndpointRequest(browsesEndpointURL); const expected = new BrowseEndpointRequest(browsesEndpointURL);

View File

@@ -1,25 +1,18 @@
import { Inject, Injectable } from '@angular/core'; import { Inject, Injectable } from '@angular/core';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { DataService } from './data.service';
import { Collection } from '../shared/collection.model';
import { ResponseCacheService } from '../cache/response-cache.service';
import { NormalizedCollection } from '../cache/models/normalized-collection.model';
import { CoreState } from '../core.reducers';
import { RequestService } from './request.service';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; import { GLOBAL_CONFIG, GlobalConfig } from '../../../config';
import { Observable } from 'rxjs/Observable'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { CommunityDataService } from './community-data.service'; import { NormalizedCollection } from '../cache/models/normalized-collection.model';
import { FindByIDRequest } from './request.models';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
import { NormalizedCommunity } from '../cache/models/normalized-community.model'; import { ResponseCacheService } from '../cache/response-cache.service';
import { isNotEmpty } from '../../shared/empty.util'; import { CoreState } from '../core.reducers';
import { ResponseCacheEntry } from '../cache/response-cache.reducer'; import { Collection } from '../shared/collection.model';
import { DSOSuccessResponse, RestResponse } from '../cache/response-cache.models'; import { ComColDataService } from './comcol-data.service';
import { CommunityDataService } from './community-data.service';
import { RequestService } from './request.service';
@Injectable() @Injectable()
export class CollectionDataService extends DataService<NormalizedCollection, Collection> { export class CollectionDataService extends ComColDataService<NormalizedCollection, Collection> {
protected linkName = 'collections'; protected linkName = 'collections';
constructor( constructor(
@@ -28,47 +21,9 @@ export class CollectionDataService extends DataService<NormalizedCollection, Col
protected rdbService: RemoteDataBuildService, protected rdbService: RemoteDataBuildService,
protected store: Store<CoreState>, protected store: Store<CoreState>,
@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig, @Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig,
private cds: CommunityDataService, protected cds: CommunityDataService,
protected objectCache: ObjectCacheService protected objectCache: ObjectCacheService
) { ) {
super(NormalizedCollection); super(NormalizedCollection);
} }
/**
* Get the scoped endpoint URL by fetching the object with
* the given scopeID and returning its HAL link with this
* data-service's linkName
*
* @param {string} scopeID
* the id of the scope object
* @return { Observable<string> }
* an Observable<string> containing the scoped URL
*/
public getScopedEndpoint(scopeID: string): Observable<string> {
const scopeCommunityHrefObs = this.cds.getEndpoint()
.flatMap((endpoint: string) => this.cds.getFindByIDHref(endpoint, scopeID))
.filter((href: string) => isNotEmpty(href))
.take(1)
.do((href: string) => {
const request = new FindByIDRequest(href, scopeID);
setTimeout(() => {
this.requestService.configure(request);
}, 0);
});
const [successResponse, errorResponse] = scopeCommunityHrefObs
.flatMap((href: string) => this.responseCache.get(href))
.map((entry: ResponseCacheEntry) => entry.response)
.share()
.partition((response: RestResponse) => response.isSuccessful);
return Observable.merge(
errorResponse.flatMap((response: DSOSuccessResponse) =>
Observable.throw(new Error(`The Community with scope ${scopeID} couldn't be retrieved`))),
successResponse
.flatMap((response: DSOSuccessResponse) => this.objectCache.getByUUID(scopeID, NormalizedCommunity))
.map((nc: NormalizedCommunity) => nc._links[this.linkName])
.filter((href) => isNotEmpty(href))
).distinctUntilChanged();
}
} }

View File

@@ -1,20 +1,45 @@
import { CollectionDataService } from './collection-data.service';
import { ResponseCacheService } from '../cache/response-cache.service';
import { RequestService } from './request.service';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { CoreState } from '../core.reducers';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { GlobalConfig } from '../../../config';
import { CommunityDataService } from './community-data.service';
import { ObjectCacheService } from '../cache/object-cache.service';
import { cold, getTestScheduler, hot } from 'jasmine-marbles'; import { cold, getTestScheduler, hot } from 'jasmine-marbles';
import { FindByIDRequest } from './request.models';
import { NormalizedCommunity } from '../cache/models/normalized-community.model';
import { TestScheduler } from 'rxjs/Rx'; import { TestScheduler } from 'rxjs/Rx';
import { GlobalConfig } from '../../../config';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { NormalizedCommunity } from '../cache/models/normalized-community.model';
import { CacheableObject } from '../cache/object-cache.reducer';
import { ObjectCacheService } from '../cache/object-cache.service';
import { ResponseCacheService } from '../cache/response-cache.service';
import { CoreState } from '../core.reducers';
import { ComColDataService } from './comcol-data.service';
import { CommunityDataService } from './community-data.service';
import { FindByIDRequest } from './request.models';
import { RequestService } from './request.service';
describe('CollectionDataService', () => { const LINK_NAME = 'test';
/* tslint:disable:max-classes-per-file */
class NormalizedTestObject implements CacheableObject {
self: string;
}
class TestService extends ComColDataService<NormalizedTestObject, any> {
protected linkName = LINK_NAME;
constructor(
protected responseCache: ResponseCacheService,
protected requestService: RequestService,
protected rdbService: RemoteDataBuildService,
protected store: Store<CoreState>,
protected EnvConfig: GlobalConfig,
protected cds: CommunityDataService,
protected objectCache: ObjectCacheService
) {
super(NormalizedTestObject);
}
}
/* tslint:enable:max-classes-per-file */
describe('ComColDataService', () => {
let scheduler: TestScheduler; let scheduler: TestScheduler;
let service: CollectionDataService; let service: TestService;
let responseCache: ResponseCacheService; let responseCache: ResponseCacheService;
let requestService: RequestService; let requestService: RequestService;
let cds: CommunityDataService; let cds: CommunityDataService;
@@ -27,7 +52,7 @@ describe('CollectionDataService', () => {
const scopeID = 'd9d30c0c-69b7-4369-8397-ca67c888974d'; const scopeID = 'd9d30c0c-69b7-4369-8397-ca67c888974d';
const communitiesEndpoint = 'https://rest.api/core/communities'; const communitiesEndpoint = 'https://rest.api/core/communities';
const communityEndpoint = `${communitiesEndpoint}/${scopeID}`; const communityEndpoint = `${communitiesEndpoint}/${scopeID}`;
const scopedCollectionsEndpoint = `${communityEndpoint}/collections`; const scopedEndpoint = `${communityEndpoint}/${LINK_NAME}`;
function initMockCommunityDataService(): CommunityDataService { function initMockCommunityDataService(): CommunityDataService {
return jasmine.createSpyObj('responseCache', { return jasmine.createSpyObj('responseCache', {
@@ -53,15 +78,15 @@ describe('CollectionDataService', () => {
getByUUID: cold('d-', { getByUUID: cold('d-', {
d: { d: {
_links: { _links: {
collections: scopedCollectionsEndpoint [LINK_NAME]: scopedEndpoint
} }
} }
}) })
}); });
} }
function initTestCollectionDataService(): CollectionDataService { function initTestService(): TestService {
return new CollectionDataService( return new TestService(
responseCache, responseCache,
requestService, requestService,
rdbService, rdbService,
@@ -77,12 +102,12 @@ describe('CollectionDataService', () => {
scheduler = getTestScheduler(); scheduler = getTestScheduler();
}); });
it('should configure a new FindByIDRequest for the scope Community', (done) => { it('should configure a new FindByIDRequest for the scope Community', (done: DoneFn) => {
cds = initMockCommunityDataService(); cds = initMockCommunityDataService();
requestService = initMockRequestService(); requestService = initMockRequestService();
objectCache = initMockObjectCacheService(); objectCache = initMockObjectCacheService();
responseCache = initMockResponceCacheService(true); responseCache = initMockResponceCacheService(true);
service = initTestCollectionDataService(); service = initTestService();
const expected = new FindByIDRequest(communityEndpoint, scopeID); const expected = new FindByIDRequest(communityEndpoint, scopeID);
@@ -101,7 +126,7 @@ describe('CollectionDataService', () => {
requestService = initMockRequestService(); requestService = initMockRequestService();
objectCache = initMockObjectCacheService(); objectCache = initMockObjectCacheService();
responseCache = initMockResponceCacheService(true); responseCache = initMockResponceCacheService(true);
service = initTestCollectionDataService(); service = initTestService();
}); });
it('should fetch the scope Community from the cache', () => { it('should fetch the scope Community from the cache', () => {
@@ -110,9 +135,9 @@ describe('CollectionDataService', () => {
expect(objectCache.getByUUID).toHaveBeenCalledWith(scopeID, NormalizedCommunity); expect(objectCache.getByUUID).toHaveBeenCalledWith(scopeID, NormalizedCommunity);
}); });
it('should return the endpoint to fetch collections within the given scope', () => { it('should return the endpoint to fetch resources within the given scope', () => {
const result = service.getScopedEndpoint(scopeID); const result = service.getScopedEndpoint(scopeID);
const expected = cold('--e-', { e: scopedCollectionsEndpoint }); const expected = cold('--e-', { e: scopedEndpoint });
expect(result).toBeObservable(expected); expect(result).toBeObservable(expected);
}); });
@@ -124,7 +149,7 @@ describe('CollectionDataService', () => {
requestService = initMockRequestService(); requestService = initMockRequestService();
objectCache = initMockObjectCacheService(); objectCache = initMockObjectCacheService();
responseCache = initMockResponceCacheService(false); responseCache = initMockResponceCacheService(false);
service = initTestCollectionDataService(); service = initTestService();
}); });
it('should throw an error', () => { it('should throw an error', () => {

View File

@@ -0,0 +1,54 @@
import { Observable } from 'rxjs/Observable';
import { isNotEmpty } from '../../shared/empty.util';
import { NormalizedCommunity } from '../cache/models/normalized-community.model';
import { CacheableObject } from '../cache/object-cache.reducer';
import { DSOSuccessResponse, RestResponse } from '../cache/response-cache.models';
import { ResponseCacheEntry } from '../cache/response-cache.reducer';
import { CommunityDataService } from './community-data.service';
import { DataService } from './data.service';
import { FindByIDRequest } from './request.models';
import { ObjectCacheService } from '../cache/object-cache.service';
export abstract class ComColDataService<TNormalized extends CacheableObject, TDomain> extends DataService<TNormalized, TDomain> {
protected abstract cds: CommunityDataService;
protected abstract objectCache: ObjectCacheService;
/**
* Get the scoped endpoint URL by fetching the object with
* the given scopeID and returning its HAL link with this
* data-service's linkName
*
* @param {string} scopeID
* the id of the scope object
* @return { Observable<string> }
* an Observable<string> containing the scoped URL
*/
public getScopedEndpoint(scopeID: string): Observable<string> {
const scopeCommunityHrefObs = this.cds.getEndpoint()
.flatMap((endpoint: string) => this.cds.getFindByIDHref(endpoint, scopeID))
.filter((href: string) => isNotEmpty(href))
.take(1)
.do((href: string) => {
const request = new FindByIDRequest(href, scopeID);
setTimeout(() => {
this.requestService.configure(request);
}, 0);
});
const [successResponse, errorResponse] = scopeCommunityHrefObs
.flatMap((href: string) => this.responseCache.get(href))
.map((entry: ResponseCacheEntry) => entry.response)
.share()
.partition((response: RestResponse) => response.isSuccessful);
return Observable.merge(
errorResponse.flatMap((response: DSOSuccessResponse) =>
Observable.throw(new Error(`The Community with scope ${scopeID} couldn't be retrieved`))),
successResponse
.flatMap((response: DSOSuccessResponse) => this.objectCache.getByUUID(scopeID, NormalizedCommunity))
.map((nc: NormalizedCommunity) => nc._links[this.linkName])
.filter((href) => isNotEmpty(href))
).distinctUntilChanged();
}
}

View File

@@ -1,23 +1,20 @@
import { Inject, Injectable } from '@angular/core'; import { Inject, Injectable } from '@angular/core';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { DataService } from './data.service';
import { Community } from '../shared/community.model';
import { ResponseCacheService } from '../cache/response-cache.service';
import { NormalizedCommunity } from '../cache/models/normalized-community.model';
import { CoreState } from '../core.reducers';
import { RequestService } from './request.service';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; import { GLOBAL_CONFIG, GlobalConfig } from '../../../config';
import { Observable } from 'rxjs/Observable'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { isNotEmpty } from '../../shared/empty.util'; import { NormalizedCommunity } from '../cache/models/normalized-community.model';
import { FindByIDRequest } from './request.models';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
import { ResponseCacheService } from '../cache/response-cache.service';
import { CoreState } from '../core.reducers';
import { Community } from '../shared/community.model';
import { ComColDataService } from './comcol-data.service';
import { RequestService } from './request.service';
@Injectable() @Injectable()
export class CommunityDataService extends DataService<NormalizedCommunity, Community> { export class CommunityDataService extends ComColDataService<NormalizedCommunity, Community> {
protected linkName = 'communities'; protected linkName = 'communities';
protected cds = this;
constructor( constructor(
protected responseCache: ResponseCacheService, protected responseCache: ResponseCacheService,
@@ -29,33 +26,4 @@ export class CommunityDataService extends DataService<NormalizedCommunity, Commu
) { ) {
super(NormalizedCommunity); super(NormalizedCommunity);
} }
/**
* Get the scoped endpoint URL by fetching the object with
* the given scopeID and returning its HAL link with this
* data-service's linkName
*
* @param {string} scopeID
* the id of the scope object
* @return { Observable<string> }
* an Observable<string> containing the scoped URL
*/
public getScopedEndpoint(scopeID: string): Observable<string> {
this.getEndpoint()
.map((endpoint: string) => this.getFindByIDHref(endpoint, scopeID))
.filter((href: string) => isNotEmpty(href))
.take(1)
.subscribe((href: string) => {
const request = new FindByIDRequest(href, scopeID);
setTimeout(() => {
this.requestService.configure(request);
}, 0);
});
return this.objectCache.getByUUID(scopeID, NormalizedCommunity)
.map((nc: NormalizedCommunity) => nc._links[this.linkName])
.filter((href) => isNotEmpty(href))
.distinctUntilChanged();
}
} }

View File

@@ -21,7 +21,7 @@ export abstract class DataService<TNormalized extends CacheableObject, TDomain>
protected abstract EnvConfig: GlobalConfig; protected abstract EnvConfig: GlobalConfig;
constructor( constructor(
private normalizedResourceType: GenericConstructor<TNormalized>, protected normalizedResourceType: GenericConstructor<TNormalized>,
) { ) {
super(); super();
} }