Changed EpersonService to extend DataService

This commit is contained in:
Giuseppe
2018-09-14 15:01:32 +02:00
parent 49f37e8ad7
commit 6da159b763
11 changed files with 80 additions and 165 deletions

View File

@@ -0,0 +1,6 @@
export class SearchParam {
constructor(public fieldName: string, public fieldValue: any) {
}
}

View File

@@ -12,6 +12,7 @@ import { FindAllOptions, FindAllRequest, FindByIDRequest, GetRequest } from './r
import { RequestService } from './request.service'; import { RequestService } from './request.service';
import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service';
import { NormalizedObject } from '../cache/models/normalized-object.model'; import { NormalizedObject } from '../cache/models/normalized-object.model';
import { SearchParam } from '../cache/models/search-param.model';
export abstract class DataService<TNormalized extends NormalizedObject, TDomain> { export abstract class DataService<TNormalized extends NormalizedObject, TDomain> {
protected abstract responseCache: ResponseCacheService; protected abstract responseCache: ResponseCacheService;
@@ -58,10 +59,16 @@ export abstract class DataService<TNormalized extends NormalizedObject, TDomain>
let result: Observable<string>; let result: Observable<string>;
const args = []; const args = [];
result = Observable.of(`${endpoint}/search/${searchByLink}`);
if (hasValue(options.searchParams)) {
options.searchParams.forEach((param: SearchParam) => {
args.push(`${param.fieldName}=${param.fieldValue}`);
})
}
if (hasValue(options.scopeID)) { if (hasValue(options.scopeID)) {
result = Observable.of(`${endpoint}/${searchByLink}?uuid=${options.scopeID}`); args.push(`uuid=${options.scopeID}`);
} else {
result = Observable.of(endpoint);
} }
if (hasValue(options.currentPage) && typeof options.currentPage === 'number') { if (hasValue(options.currentPage) && typeof options.currentPage === 'number') {
@@ -123,38 +130,17 @@ export abstract class DataService<TNormalized extends NormalizedObject, TDomain>
return this.rdbService.buildSingle<TNormalized, TDomain>(href); return this.rdbService.buildSingle<TNormalized, TDomain>(href);
} }
// TODO remove when search will be completed protected searchBy(searchMethod: string, options: FindAllOptions = {}): Observable<RemoteData<PaginatedList<TDomain>>> {
public searchBySubmitter(options: FindAllOptions = {}): Observable<RemoteData<PaginatedList<TDomain>>> {
return this.searchBy('submitter', options);
}
// TODO remove when search will be completed
searchByUser(options: FindAllOptions = {}): Observable<RemoteData<PaginatedList<TDomain>>> {
return this.searchBy('user', options);
}
// TODO remove when search will be completed
protected searchBy(searchBy: string, options: FindAllOptions = {}): Observable<RemoteData<PaginatedList<TDomain>>> {
let url = null;
switch (searchBy) {
case 'user': {
url = 'search/findByUser';
break;
}
case 'submitter': {
url = 'search/findBySubmitter';
break;
}
}
const hrefObs = this.halService.getEndpoint(this.linkPath).filter((href: string) => isNotEmpty(href)) const hrefObs = this.halService.getEndpoint(this.linkPath).filter((href: string) => isNotEmpty(href))
.flatMap((endpoint: string) => this.getSearchByHref(endpoint, url, options)); .flatMap((endpoint: string) => this.getSearchByHref(endpoint, searchMethod, options));
hrefObs hrefObs
.filter((href: string) => hasValue(href)) .filter((href: string) => hasValue(href))
.take(1) .take(1)
.subscribe((href: string) => { .subscribe((href: string) => {
console.log(href);
const request = new FindAllRequest(this.requestService.generateRequestId(), href, options); const request = new FindAllRequest(this.requestService.generateRequestId(), href, options);
this.requestService.configure(request, this.forceBypassCache); this.requestService.configure(request, true);
}); });
return this.rdbService.buildList<TNormalized, TDomain>(hrefObs) as Observable<RemoteData<PaginatedList<TDomain>>>; return this.rdbService.buildList<TNormalized, TDomain>(hrefObs) as Observable<RemoteData<PaginatedList<TDomain>>>;

View File

@@ -1,7 +1,5 @@
import { SortOptions } from '../cache/models/sort-options.model'; import { SortOptions } from '../cache/models/sort-options.model';
import { GenericConstructor } from '../shared/generic-constructor'; import { GenericConstructor } from '../shared/generic-constructor';
import { GlobalConfig } from '../../../config/global-config.interface';
import { RESTURLCombiner } from '../url-combiner/rest-url-combiner';
import { BrowseEntriesResponseParsingService } from './browse-entries-response-parsing.service'; import { BrowseEntriesResponseParsingService } from './browse-entries-response-parsing.service';
import { DSOResponseParsingService } from './dso-response-parsing.service'; import { DSOResponseParsingService } from './dso-response-parsing.service';
import { ResponseParsingService } from './parsing.service'; import { ResponseParsingService } from './parsing.service';
@@ -10,10 +8,9 @@ import { BrowseResponseParsingService } from './browse-response-parsing.service'
import { ConfigResponseParsingService } from './config-response-parsing.service'; import { ConfigResponseParsingService } from './config-response-parsing.service';
import { AuthResponseParsingService } from '../auth/auth-response-parsing.service'; import { AuthResponseParsingService } from '../auth/auth-response-parsing.service';
import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service';
import { HttpHeaders } from '@angular/common/http';
import { SubmissionResponseParsingService } from '../submission/submission-response-parsing.service'; import { SubmissionResponseParsingService } from '../submission/submission-response-parsing.service';
import { EpersonResponseParsingService } from '../eperson/eperson-response-parsing.service';
import { IntegrationResponseParsingService } from '../integration/integration-response-parsing.service'; import { IntegrationResponseParsingService } from '../integration/integration-response-parsing.service';
import { SearchParam } from '../cache/models/search-param.model';
/* tslint:disable:max-classes-per-file */ /* tslint:disable:max-classes-per-file */
@@ -143,6 +140,7 @@ export class FindAllOptions {
elementsPerPage?: number; elementsPerPage?: number;
currentPage?: number; currentPage?: number;
sort?: SortOptions; sort?: SortOptions;
searchParams?: SearchParam[];
} }
export class FindAllRequest extends GetRequest { export class FindAllRequest extends GetRequest {
@@ -299,7 +297,7 @@ export class EpersonRequest extends GetRequest {
} }
getResponseParser(): GenericConstructor<ResponseParsingService> { getResponseParser(): GenericConstructor<ResponseParsingService> {
return EpersonResponseParsingService; return DSOResponseParsingService;
} }
} }

View File

@@ -1,12 +0,0 @@
import { PageInfo } from '../shared/page-info.model';
import { NormalizedObject } from '../cache/models/normalized-object.model';
/**
* A class to represent the data retrieved by a Eperson service
*/
export class EpersonData {
constructor(
public pageInfo: PageInfo,
public payload: NormalizedObject[]
) { }
}

View File

@@ -1,21 +0,0 @@
import { EpersonType } from './eperson-type';
import { GenericConstructor } from '../shared/generic-constructor';
import { NormalizedEpersonModel } from './models/NormalizedEperson.model';
import { NormalizedGroupModel } from './models/NormalizedGroup.model';
import { NormalizedObject } from '../cache/models/normalized-object.model';
export class EpersonObjectFactory {
public static getConstructor(type): GenericConstructor<NormalizedObject> {
switch (type) {
case EpersonType.EpersonsModel: {
return NormalizedEpersonModel
}
case EpersonType.GroupsModel: {
return NormalizedGroupModel
}
default: {
return undefined;
}
}
}
}

View File

@@ -1,26 +1,22 @@
import { Inject, Injectable } from '@angular/core'; import { Inject, Injectable } from '@angular/core';
import { RestRequest } from '../data/request.models'; import { RestRequest } from '../data/request.models';
import { ResponseParsingService } from '../data/parsing.service'; import { ResponseParsingService } from '../data/parsing.service';
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
import { import { EpersonSuccessResponse, ErrorResponse, RestResponse } from '../cache/response-cache.models';
EpersonSuccessResponse, ErrorResponse,
RestResponse
} from '../cache/response-cache.models';
import { isNotEmpty } from '../../shared/empty.util'; import { isNotEmpty } from '../../shared/empty.util';
import { EpersonObjectFactory } from './eperson-object-factory';
import { EpersonType } from './eperson-type';
import { BaseResponseParsingService } from '../data/base-response-parsing.service'; import { BaseResponseParsingService } from '../data/base-response-parsing.service';
import { GLOBAL_CONFIG } from '../../../config'; import { GLOBAL_CONFIG } from '../../../config';
import { GlobalConfig } from '../../../config/global-config.interface'; import { GlobalConfig } from '../../../config/global-config.interface';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
import { DSpaceObject } from '../shared/dspace-object.model';
import { NormalizedObject } from '../cache/models/normalized-object.model'; import { NormalizedObject } from '../cache/models/normalized-object.model';
import { NormalizedObjectFactory } from '../cache/models/normalized-object-factory';
import { ResourceType } from '../shared/resource-type';
@Injectable() @Injectable()
export class EpersonResponseParsingService extends BaseResponseParsingService implements ResponseParsingService { export class EpersonResponseParsingService extends BaseResponseParsingService implements ResponseParsingService {
protected objectFactory = EpersonObjectFactory; protected objectFactory = NormalizedObjectFactory;
protected toCache = false; protected toCache = false;
constructor( constructor(
@@ -32,7 +28,7 @@ export class EpersonResponseParsingService extends BaseResponseParsingService im
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links)) { if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links)) {
const epersonDefinition = this.process<NormalizedObject,EpersonType>(data.payload, request.href); const epersonDefinition = this.process<NormalizedObject,ResourceType>(data.payload, request.href);
return new EpersonSuccessResponse(epersonDefinition[Object.keys(epersonDefinition)[0]], data.statusCode, this.processPageInfo(data.payload)); return new EpersonSuccessResponse(epersonDefinition[Object.keys(epersonDefinition)[0]], data.statusCode, this.processPageInfo(data.payload));
} else { } else {
return new ErrorResponse( return new ErrorResponse(

View File

@@ -1,5 +0,0 @@
export enum EpersonType {
EpersonsModel = 'eperson',
GroupsModel = 'group',
}

View File

@@ -1,14 +1,12 @@
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
import { RequestService } from '../data/request.service'; import { RequestService } from '../data/request.service';
import { ResponseCacheService } from '../cache/response-cache.service'; import { ResponseCacheService } from '../cache/response-cache.service';
import { EpersonSuccessResponse, ErrorResponse, RestResponse } from '../cache/response-cache.models'; import { EpersonRequest } from '../data/request.models';
import { EpersonRequest, GetRequest } from '../data/request.models';
import { ResponseCacheEntry } from '../cache/response-cache.reducer';
import { isNotEmpty } from '../../shared/empty.util';
import { HALEndpointService } from '../shared/hal-endpoint.service'; import { HALEndpointService } from '../shared/hal-endpoint.service';
import { EpersonData } from './eperson-data'; import { NormalizedObject } from '../cache/models/normalized-object.model';
import { DataService } from '../data/data.service';
export abstract class EpersonService { export abstract class EpersonService<TNormalized extends NormalizedObject, TDomain> extends DataService<TNormalized, TDomain> {
protected request: EpersonRequest; protected request: EpersonRequest;
protected abstract responseCache: ResponseCacheService; protected abstract responseCache: ResponseCacheService;
protected abstract requestService: RequestService; protected abstract requestService: RequestService;
@@ -16,38 +14,7 @@ export abstract class EpersonService {
protected abstract browseEndpoint: string; protected abstract browseEndpoint: string;
protected abstract halService: HALEndpointService; protected abstract halService: HALEndpointService;
protected getEperson(request: GetRequest): Observable<EpersonData> { public getScopedEndpoint(scopeID: string): Observable<string> {
const [successResponse, errorResponse] = this.responseCache.get(request.href) return this.halService.getEndpoint(this.linkPath);
.map((entry: ResponseCacheEntry) => entry.response)
.partition((response: RestResponse) => response.isSuccessful);
return Observable.merge(
errorResponse.flatMap((response: ErrorResponse) =>
Observable.throw(new Error(`Couldn't retrieve the EPerson`))),
successResponse
.filter((response: EpersonSuccessResponse) => isNotEmpty(response))
.map((response: EpersonSuccessResponse) => new EpersonData(response.pageInfo, response.epersonDefinition))
.distinctUntilChanged());
}
public getDataByHref(href: string): Observable<EpersonData> {
const request = new EpersonRequest(this.requestService.generateRequestId(), href);
this.requestService.configure(request);
return this.getEperson(request);
}
public getDataByUuid(uuid: string): Observable<EpersonData> {
return this.halService.getEndpoint(this.linkPath)
.map((endpoint: string) => this.getDataByIDHref(endpoint, uuid))
.filter((href: string) => isNotEmpty(href))
.distinctUntilChanged()
.map((endpointURL: string) => new EpersonRequest(this.requestService.generateRequestId(), endpointURL))
.do((request: GetRequest) => this.requestService.configure(request))
.flatMap((request: GetRequest) => this.getEperson(request))
.distinctUntilChanged();
}
protected getDataByIDHref(endpoint, resourceID): string {
return `${endpoint}/${resourceID}`;
} }
} }

View File

@@ -1,55 +1,49 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { filter, map, take } from 'rxjs/operators';
import { EpersonService } from './eperson.service'; import { EpersonService } from './eperson.service';
import { ResponseCacheService } from '../cache/response-cache.service'; import { ResponseCacheService } from '../cache/response-cache.service';
import { RequestService } from '../data/request.service'; import { RequestService } from '../data/request.service';
import { isNotEmpty } from '../../shared/empty.util'; import { FindAllOptions } from '../data/request.models';
import { EpersonRequest, GetRequest } from '../data/request.models';
import { EpersonData } from './eperson-data';
import { EpersonSuccessResponse, ErrorResponse, RestResponse } from '../cache/response-cache.models';
import { Observable } from 'rxjs/Observable';
import { ResponseCacheEntry } from '../cache/response-cache.reducer';
import { HALEndpointService } from '../shared/hal-endpoint.service'; import { HALEndpointService } from '../shared/hal-endpoint.service';
import { BrowseService } from '../browse/browse.service'; import { NormalizedGroupModel } from './models/NormalizedGroup.model';
import { Group } from './models/group.model';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { Store } from '@ngrx/store';
import { CoreState } from '../core.reducers';
import { ObjectCacheService } from '../cache/object-cache.service';
import { SearchParam } from '../cache/models/search-param.model';
import { RemoteData } from '../data/remote-data';
import { PaginatedList } from '../data/paginated-list';
@Injectable() @Injectable()
export class GroupEpersonService extends EpersonService { export class GroupEpersonService extends EpersonService<NormalizedGroupModel, Group> {
protected linkPath = 'groups'; protected linkPath = 'groups';
protected browseEndpoint = ''; protected browseEndpoint = '';
protected forceBypassCache = false;
constructor( constructor(
protected responseCache: ResponseCacheService, protected responseCache: ResponseCacheService,
protected requestService: RequestService, protected requestService: RequestService,
protected bs: BrowseService, protected rdbService: RemoteDataBuildService,
protected halService: HALEndpointService) { protected store: Store<CoreState>,
protected objectCache: ObjectCacheService,
protected halService: HALEndpointService
) {
super(); super();
} }
protected getSearchHref(endpoint, groupName): string { isMemberOf(groupName: string): Observable<boolean> {
return `${endpoint}/search/isMemberOf?groupName=${groupName}`; const searchHref = 'isMemberOf';
} const options = new FindAllOptions();
options.searchParams = [new SearchParam('groupName', groupName)];
isMemberOf(groupName: string) { return this.searchBy(searchHref, options).pipe(
return this.halService.getEndpoint(this.linkPath) filter((groups: RemoteData<PaginatedList<Group>>) => !groups.isResponsePending),
.map((endpoint: string) => this.getSearchHref(endpoint, groupName)) take(1),
.filter((href: string) => isNotEmpty(href)) map((groups: RemoteData<PaginatedList<Group>>) => groups.payload.totalElements > 0)
.distinctUntilChanged() );
.map((endpointURL: string) => new EpersonRequest(this.requestService.generateRequestId(), endpointURL))
.do((request: GetRequest) => this.requestService.configure(request))
.flatMap((request: GetRequest) => this.getSearch(request))
.distinctUntilChanged();
}
protected getSearch(request: GetRequest): Observable<EpersonData> {
const [successResponse, errorResponse] = this.responseCache.get(request.href)
.map((entry: ResponseCacheEntry) => entry.response)
.partition((response: RestResponse) => response.isSuccessful);
return Observable.merge(
errorResponse.flatMap((response: ErrorResponse) =>
Observable.of(new EpersonData(undefined, undefined))),
successResponse
.filter((response: EpersonSuccessResponse) => isNotEmpty(response))
.map((response: EpersonSuccessResponse) => new EpersonData(response.pageInfo, response.epersonDefinition))
.distinctUntilChanged());
} }
} }

View File

@@ -2,8 +2,8 @@ import { Component, Input, OnInit } from '@angular/core';
import { GroupEpersonService } from '../../../../core/eperson/group-eperson.service'; import { GroupEpersonService } from '../../../../core/eperson/group-eperson.service';
import { ResourcePolicy } from '../../../../core/shared/resource-policy.model'; import { ResourcePolicy } from '../../../../core/shared/resource-policy.model';
import { isEmpty } from '../../../../shared/empty.util'; import { isEmpty } from '../../../../shared/empty.util';
import { EpersonData } from '../../../../core/eperson/eperson-data';
import { Group } from '../../../../core/eperson/models/group.model'; import { Group } from '../../../../core/eperson/models/group.model';
import { RemoteData } from '../../../../core/data/remote-data';
@Component({ @Component({
selector: 'ds-access-conditions', selector: 'ds-access-conditions',
@@ -20,9 +20,11 @@ export class AccessConditionsComponent implements OnInit {
ngOnInit() { ngOnInit() {
this.accessConditions.forEach((accessCondition: ResourcePolicy) => { this.accessConditions.forEach((accessCondition: ResourcePolicy) => {
if (isEmpty(accessCondition.name)) { if (isEmpty(accessCondition.name)) {
this.groupService.getDataByUuid(accessCondition.groupUUID) this.groupService.findById(accessCondition.groupUUID)
.subscribe((data: EpersonData) => { .filter((rd: RemoteData<Group>) => !rd.isResponsePending && rd.hasSucceeded)
const group = data.payload[0] as any; .take(1)
.subscribe((rd: RemoteData<Group>) => {
const group: Group = rd.payload;
const accessConditionEntry = Object.assign({}, accessCondition); const accessConditionEntry = Object.assign({}, accessCondition);
accessConditionEntry.name = group.name; accessConditionEntry.name = group.name;
this.accessConditionsList.push(accessConditionEntry); this.accessConditionsList.push(accessConditionEntry);

View File

@@ -10,7 +10,6 @@ import { GroupEpersonService } from '../../../core/eperson/group-eperson.service
import { SubmissionUploadsConfigService } from '../../../core/config/submission-uploads-config.service'; import { SubmissionUploadsConfigService } from '../../../core/config/submission-uploads-config.service';
import { SubmissionUploadsModel } from '../../../core/shared/config/config-submission-uploads.model'; import { SubmissionUploadsModel } from '../../../core/shared/config/config-submission-uploads.model';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
import { EpersonData } from '../../../core/eperson/eperson-data';
import { SubmissionFormsModel } from '../../../core/shared/config/config-submission-forms.model'; import { SubmissionFormsModel } from '../../../core/shared/config/config-submission-forms.model';
import { SectionsType } from '../sections-type'; import { SectionsType } from '../sections-type';
import { renderSectionFor } from '../sections-decorator'; import { renderSectionFor } from '../sections-decorator';
@@ -18,6 +17,8 @@ import { SectionDataObject } from '../models/section-data.model';
import { submissionObjectFromIdSelector } from '../../selectors'; import { submissionObjectFromIdSelector } from '../../selectors';
import { SubmissionObjectEntry } from '../../objects/submission-objects.reducer'; import { SubmissionObjectEntry } from '../../objects/submission-objects.reducer';
import { AlertType } from '../../../shared/alerts/aletrs-type'; import { AlertType } from '../../../shared/alerts/aletrs-type';
import { RemoteData } from '../../../core/data/remote-data';
import { Group } from '../../../core/eperson/models/group.model';
export const POLICY_DEFAULT_NO_LIST = 1; // Banner1 export const POLICY_DEFAULT_NO_LIST = 1; // Banner1
export const POLICY_DEFAULT_WITH_LIST = 2; // Banner2 export const POLICY_DEFAULT_WITH_LIST = 2; // Banner2
@@ -113,16 +114,19 @@ export class UploadSectionComponent extends SectionModelComponent implements OnI
// Retrieve Groups for accessConditionPolicies // Retrieve Groups for accessConditionPolicies
this.availableAccessConditionOptions.forEach((accessCondition) => { this.availableAccessConditionOptions.forEach((accessCondition) => {
if (accessCondition.hasEndDate === true || accessCondition.hasStartDate === true) { if (accessCondition.hasEndDate === true || accessCondition.hasStartDate === true) {
groupsObs.push(this.groupService.getDataByUuid(accessCondition.groupUUID) groupsObs.push(
this.groupService.findById(accessCondition.groupUUID)
.filter((rd: RemoteData<Group>) => !rd.isResponsePending && rd.hasSucceeded)
.take(1)
); );
} }
}); });
let obsCounter = 1; let obsCounter = 1;
Observable.merge(groupsObs) Observable.forkJoin(groupsObs)
.flatMap((group) => group) .flatMap((group) => group)
.take(groupsObs.length) .take(groupsObs.length)
.subscribe((data: EpersonData) => { .subscribe((rd: RemoteData<Group>) => {
const group = data.payload[0] as any; const group: Group = rd.payload;
if (isUndefined(this.availableGroups.get(group.uuid))) { if (isUndefined(this.availableGroups.get(group.uuid))) {
if (Array.isArray(group.groups)) { if (Array.isArray(group.groups)) {
const groupArrayData = []; const groupArrayData = [];
@@ -156,7 +160,7 @@ export class UploadSectionComponent extends SectionModelComponent implements OnI
this.fileNames = []; this.fileNames = [];
this.changeDetectorRef.detectChanges(); this.changeDetectorRef.detectChanges();
if (isNotUndefined(fileList) && fileList.length > 0) { if (isNotUndefined(fileList) && fileList.length > 0) {
fileList.forEach((file, index) => { fileList.forEach((file) => {
this.fileList.push(file); this.fileList.push(file);
this.fileIndexes.push(file.uuid); this.fileIndexes.push(file.uuid);
const fileName = file.metadata['dc.title'][0].display || file.uuid; const fileName = file.metadata['dc.title'][0].display || file.uuid;