OpenSlides/client/src/app/core/core-services/collection-string-mapper.se...

141 lines
4.6 KiB
TypeScript

import { Injectable } from '@angular/core';
import { BaseRepository } from 'app/core/repositories/base-repository';
import { BaseViewModel, TitleInformation, ViewModelConstructor } from 'app/site/base/base-view-model';
import { BaseModel, ModelConstructor } from '../../shared/models/base/base-model';
/**
* Unifies the ModelConstructor and ViewModelConstructor.
*/
interface UnifiedConstructors {
COLLECTIONSTRING: string;
new (...args: any[]): any;
}
/**
* Every types supported: (View)ModelConstructors, repos and collectionstrings.
*/
type TypeIdentifier = UnifiedConstructors | BaseRepository<any, any, any> | string;
type CollectionStringMappedTypes = [
ModelConstructor<BaseModel>,
ViewModelConstructor<BaseViewModel>,
BaseRepository<BaseViewModel<any>, BaseModel<any>, TitleInformation>
];
/**
* Registeres the mapping between collection strings, models constructors, view
* model constructors and repositories.
* All models need to be registered!
*/
@Injectable({
providedIn: 'root'
})
export class CollectionStringMapperService {
/**
* Maps collection strings to mapping entries
*/
private collectionStringMapping: {
[collectionString: string]: CollectionStringMappedTypes;
} = {};
public constructor() {}
/**
* Registers the combination of a collection string, model, view model and repository
* @param collectionString
* @param model
*/
public registerCollectionElement<V extends BaseViewModel<M>, M extends BaseModel>(
collectionString: string,
model: ModelConstructor<M>,
viewModel: ViewModelConstructor<V>,
repository: BaseRepository<V, M, TitleInformation>
): void {
this.collectionStringMapping[collectionString] = [model, viewModel, repository];
}
/**
* @param obj The object to get the collection string from.
* @returns the collectionstring
*/
public getCollectionString(obj: TypeIdentifier): string {
if (typeof obj === 'string') {
return obj;
} else {
return obj.COLLECTIONSTRING;
}
}
/**
* @returns true, if the given collection is known by this service.
*/
public isCollectionRegistered(collectionString: string): boolean {
return !!this.collectionStringMapping[collectionString];
}
/**
* @param obj The object to get the model constructor from.
* @returns the model constructor
*/
public getModelConstructor<M extends BaseModel>(obj: TypeIdentifier): ModelConstructor<M> | null {
if (this.isCollectionRegistered(this.getCollectionString(obj))) {
return this.collectionStringMapping[this.getCollectionString(obj)][0] as ModelConstructor<M>;
}
}
/**
* @param obj The object to get the view model constructor from.
* @returns the view model constructor
*/
public getViewModelConstructor<M extends BaseViewModel>(obj: TypeIdentifier): ViewModelConstructor<M> | null {
if (this.isCollectionRegistered(this.getCollectionString(obj))) {
return this.collectionStringMapping[this.getCollectionString(obj)][1] as ViewModelConstructor<M>;
}
}
/**
* @param obj The object to get the repository from.
* @returns the repository
*/
public getRepository<V extends BaseViewModel, M extends BaseModel, T extends TitleInformation>(
obj: TypeIdentifier
): BaseRepository<V & T, M, T> | null {
if (this.isCollectionRegistered(this.getCollectionString(obj))) {
return this.collectionStringMapping[this.getCollectionString(obj)][2] as BaseRepository<V & T, M, T>;
}
}
/**
* @returns all registered repositories.
*/
public getAllRepositories(): BaseRepository<any, any, any>[] {
return Object.values(this.collectionStringMapping).map((types: CollectionStringMappedTypes) => types[2]);
}
/**
* Validates the given element id. It must have the form `<collection>:<id>`, with
* <collection> being a registered collection and the id a valid integer greater then 0.
*
* @param elementId The element id.
* @returns true, if the element id is valid.
*/
public isElementIdValid(elementId: any): boolean {
if (!elementId || typeof elementId !== 'string') {
return false;
}
const splitted = elementId.split(':');
if (splitted.length !== 2) {
return false;
}
const id = parseInt(splitted[1], 10);
if (isNaN(id) || id <= 0) {
return false;
}
return Object.keys(this.collectionStringMapping).some(collection => collection === splitted[0]);
}
}