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 { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service';
import { NormalizedObject } from '../cache/models/normalized-object.model';
import { SearchParam } from '../cache/models/search-param.model';
export abstract class DataService<TNormalized extends NormalizedObject, TDomain> {
protected abstract responseCache: ResponseCacheService;
@@ -58,10 +59,16 @@ export abstract class DataService<TNormalized extends NormalizedObject, TDomain>
let result: Observable<string>;
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)) {
result = Observable.of(`${endpoint}/${searchByLink}?uuid=${options.scopeID}`);
} else {
result = Observable.of(endpoint);
args.push(`uuid=${options.scopeID}`);
}
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);
}
// TODO remove when search will be completed
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;
}
}
protected searchBy(searchMethod: string, options: FindAllOptions = {}): Observable<RemoteData<PaginatedList<TDomain>>> {
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
.filter((href: string) => hasValue(href))
.take(1)
.subscribe((href: string) => {
console.log(href);
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>>>;

View File

@@ -1,7 +1,5 @@
import { SortOptions } from '../cache/models/sort-options.model';
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 { DSOResponseParsingService } from './dso-response-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 { AuthResponseParsingService } from '../auth/auth-response-parsing.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 { EpersonResponseParsingService } from '../eperson/eperson-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 */
@@ -143,6 +140,7 @@ export class FindAllOptions {
elementsPerPage?: number;
currentPage?: number;
sort?: SortOptions;
searchParams?: SearchParam[];
}
export class FindAllRequest extends GetRequest {
@@ -299,7 +297,7 @@ export class EpersonRequest extends GetRequest {
}
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 { RestRequest } from '../data/request.models';
import { ResponseParsingService } from '../data/parsing.service';
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
import {
EpersonSuccessResponse, ErrorResponse,
RestResponse
} from '../cache/response-cache.models';
import { EpersonSuccessResponse, ErrorResponse, RestResponse } from '../cache/response-cache.models';
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 { GLOBAL_CONFIG } from '../../../config';
import { GlobalConfig } from '../../../config/global-config.interface';
import { ObjectCacheService } from '../cache/object-cache.service';
import { DSpaceObject } from '../shared/dspace-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()
export class EpersonResponseParsingService extends BaseResponseParsingService implements ResponseParsingService {
protected objectFactory = EpersonObjectFactory;
protected objectFactory = NormalizedObjectFactory;
protected toCache = false;
constructor(
@@ -32,7 +28,7 @@ export class EpersonResponseParsingService extends BaseResponseParsingService im
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
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));
} else {
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 { RequestService } from '../data/request.service';
import { ResponseCacheService } from '../cache/response-cache.service';
import { EpersonSuccessResponse, ErrorResponse, RestResponse } from '../cache/response-cache.models';
import { EpersonRequest, GetRequest } from '../data/request.models';
import { ResponseCacheEntry } from '../cache/response-cache.reducer';
import { isNotEmpty } from '../../shared/empty.util';
import { EpersonRequest } from '../data/request.models';
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 abstract responseCache: ResponseCacheService;
protected abstract requestService: RequestService;
@@ -16,38 +14,7 @@ export abstract class EpersonService {
protected abstract browseEndpoint: string;
protected abstract halService: HALEndpointService;
protected getEperson(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.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}`;
public getScopedEndpoint(scopeID: string): Observable<string> {
return this.halService.getEndpoint(this.linkPath);
}
}

View File

@@ -1,55 +1,49 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { filter, map, take } from 'rxjs/operators';
import { EpersonService } from './eperson.service';
import { ResponseCacheService } from '../cache/response-cache.service';
import { RequestService } from '../data/request.service';
import { isNotEmpty } from '../../shared/empty.util';
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 { FindAllOptions } from '../data/request.models';
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()
export class GroupEpersonService extends EpersonService {
export class GroupEpersonService extends EpersonService<NormalizedGroupModel, Group> {
protected linkPath = 'groups';
protected browseEndpoint = '';
protected forceBypassCache = false;
constructor(
protected responseCache: ResponseCacheService,
protected requestService: RequestService,
protected bs: BrowseService,
protected halService: HALEndpointService) {
protected rdbService: RemoteDataBuildService,
protected store: Store<CoreState>,
protected objectCache: ObjectCacheService,
protected halService: HALEndpointService
) {
super();
}
protected getSearchHref(endpoint, groupName): string {
return `${endpoint}/search/isMemberOf?groupName=${groupName}`;
}
isMemberOf(groupName: string): Observable<boolean> {
const searchHref = 'isMemberOf';
const options = new FindAllOptions();
options.searchParams = [new SearchParam('groupName', groupName)];
isMemberOf(groupName: string) {
return this.halService.getEndpoint(this.linkPath)
.map((endpoint: string) => this.getSearchHref(endpoint, groupName))
.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.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());
return this.searchBy(searchHref, options).pipe(
filter((groups: RemoteData<PaginatedList<Group>>) => !groups.isResponsePending),
take(1),
map((groups: RemoteData<PaginatedList<Group>>) => groups.payload.totalElements > 0)
);
}
}

View File

@@ -2,8 +2,8 @@ import { Component, Input, OnInit } from '@angular/core';
import { GroupEpersonService } from '../../../../core/eperson/group-eperson.service';
import { ResourcePolicy } from '../../../../core/shared/resource-policy.model';
import { isEmpty } from '../../../../shared/empty.util';
import { EpersonData } from '../../../../core/eperson/eperson-data';
import { Group } from '../../../../core/eperson/models/group.model';
import { RemoteData } from '../../../../core/data/remote-data';
@Component({
selector: 'ds-access-conditions',
@@ -20,9 +20,11 @@ export class AccessConditionsComponent implements OnInit {
ngOnInit() {
this.accessConditions.forEach((accessCondition: ResourcePolicy) => {
if (isEmpty(accessCondition.name)) {
this.groupService.getDataByUuid(accessCondition.groupUUID)
.subscribe((data: EpersonData) => {
const group = data.payload[0] as any;
this.groupService.findById(accessCondition.groupUUID)
.filter((rd: RemoteData<Group>) => !rd.isResponsePending && rd.hasSucceeded)
.take(1)
.subscribe((rd: RemoteData<Group>) => {
const group: Group = rd.payload;
const accessConditionEntry = Object.assign({}, accessCondition);
accessConditionEntry.name = group.name;
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 { SubmissionUploadsModel } from '../../../core/shared/config/config-submission-uploads.model';
import { Observable } from 'rxjs/Observable';
import { EpersonData } from '../../../core/eperson/eperson-data';
import { SubmissionFormsModel } from '../../../core/shared/config/config-submission-forms.model';
import { SectionsType } from '../sections-type';
import { renderSectionFor } from '../sections-decorator';
@@ -18,6 +17,8 @@ import { SectionDataObject } from '../models/section-data.model';
import { submissionObjectFromIdSelector } from '../../selectors';
import { SubmissionObjectEntry } from '../../objects/submission-objects.reducer';
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_WITH_LIST = 2; // Banner2
@@ -113,16 +114,19 @@ export class UploadSectionComponent extends SectionModelComponent implements OnI
// Retrieve Groups for accessConditionPolicies
this.availableAccessConditionOptions.forEach((accessCondition) => {
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;
Observable.merge(groupsObs)
Observable.forkJoin(groupsObs)
.flatMap((group) => group)
.take(groupsObs.length)
.subscribe((data: EpersonData) => {
const group = data.payload[0] as any;
.subscribe((rd: RemoteData<Group>) => {
const group: Group = rd.payload;
if (isUndefined(this.availableGroups.get(group.uuid))) {
if (Array.isArray(group.groups)) {
const groupArrayData = [];
@@ -156,7 +160,7 @@ export class UploadSectionComponent extends SectionModelComponent implements OnI
this.fileNames = [];
this.changeDetectorRef.detectChanges();
if (isNotUndefined(fileList) && fileList.length > 0) {
fileList.forEach((file, index) => {
fileList.forEach((file) => {
this.fileList.push(file);
this.fileIndexes.push(file.uuid);
const fileName = file.metadata['dc.title'][0].display || file.uuid;