import {Injectable} from '@angular/core'; import {isUndefinedOrEmpty, Map, not} from 'tsfun'; import {map} from 'tsfun/associative'; import {ProjectConfiguration} from '../project-configuration'; import {ConfigurationValidation} from './configuration-validation'; import {ConfigReader} from './config-reader'; import {RelationDefinition} from '../model/relation-definition'; import {FieldDefinition} from '../model/field-definition'; import {buildRawProjectConfiguration} from './build-raw-project-configuration'; import {BuiltinCategoryDefinition} from '../model/builtin-category-definition'; import {LibraryCategoryDefinition} from '../model/library-category-definition'; import {addKeyAsProp} from '../../util/transformers'; import {ValuelistDefinition} from '../model/valuelist-definition'; @Injectable() /** * Lets clients subscribe for the app * configuration. In order for this to work, they * have to call validateFieldDefinitions_ and getProjectConfiguration * (the call order does not matter). * * It is recommended to handle a promise rejection of * getProjectConfiguration at a single place in your app. * * @author Daniel de Oliveira * @author Thomas Kleinke * @author Fabian Z. */ export class ConfigLoader { constructor(private configReader: ConfigReader) {} public go(configDirPath: string, commonFields: { [fieldName: string]: any }, builtinCategories: Map, relations: Array, extraFields: {[fieldName: string]: FieldDefinition }, customConfigurationName: string|undefined, languages: string[]): ProjectConfiguration { if (customConfigurationName) console.log('Load custom configuration', customConfigurationName); const libraryCategories: Map = this.readLibraryCategories(configDirPath); const missingRelationCategoryErrors = ConfigurationValidation.findMissingRelationType( relations, Object.keys(builtinCategories as any) ); if (missingRelationCategoryErrors.length > 0) throw missingRelationCategoryErrors; return this.preprocess( configDirPath, libraryCategories, commonFields, builtinCategories, relations, extraFields, customConfigurationName, languages); } private readLibraryCategories(configDirPath: string): any { const appConfigurationPath = configDirPath + '/Library/Categories.json'; try { return addKeyAsProp('libraryId')(this.configReader.read(appConfigurationPath)); } catch (msgWithParams) { throw [msgWithParams]; } } private preprocess(configDirPath: string, libraryCategories: Map, commonFields: any, builtinCategories: Map, relations: Array, extraFields: { [fieldName: string]: FieldDefinition }, customConfigurationName: string|undefined, languages: string[]): ProjectConfiguration { const orderConfigurationPath = configDirPath + '/Order.json'; const searchConfigurationPath = configDirPath + '/Search.json'; const valuelistsConfigurationPath = configDirPath + '/Library/Valuelists.json'; const customConfigPath = configDirPath + '/Config-' + (customConfigurationName ? customConfigurationName : 'Default') + '.json'; let customCategories; let languageConfigurations: any[]; let searchConfiguration: any; let valuelistsConfiguration: any; let orderConfiguration: any; try { languageConfigurations = this.readLanguageConfigurations( configDirPath, languages, customConfigurationName ); customCategories = this.configReader.read(customConfigPath); searchConfiguration = this.configReader.read(searchConfigurationPath); valuelistsConfiguration = this.readValuelistsConfiguration(valuelistsConfigurationPath); orderConfiguration = this.configReader.read(orderConfigurationPath); } catch (msgWithParams) { throw [msgWithParams]; } // unused: Preprocessing.prepareSameMainCategoryResource(appConfiguration); // unused: Preprocessing.setIsRecordedInVisibilities(appConfiguration); See #8992 try { return new ProjectConfiguration( buildRawProjectConfiguration( builtinCategories, libraryCategories, customCategories, commonFields, valuelistsConfiguration, extraFields, relations, languageConfigurations, searchConfiguration, orderConfiguration, (categories: any) => { const fieldValidationErrors = ConfigurationValidation.validateFieldDefinitions(Object.values(categories)); if (fieldValidationErrors.length > 0) throw fieldValidationErrors; return categories; })); } catch (msgWithParams) { throw msgWithParams; } } private readLanguageConfigurations(configDirPath: string, languages: string[], customConfigurationName: string): any[] { const configurations = []; for (const language of languages) { configurations.push( this.readLanguageConfiguration(configDirPath + '/Language-' + (customConfigurationName ? customConfigurationName : 'Custom') + '.' + language + '.json') ); configurations.push( this.readLanguageConfiguration(configDirPath + '/Library/Language.' + language + '.json') ); configurations.push( this.readLanguageConfiguration(configDirPath + '/Core/Language.' + language + '.json') ); } return configurations.filter(not(isUndefinedOrEmpty)); } private readLanguageConfiguration(path: string): any|undefined { if (!this.configReader.exists(path)) return undefined; return this.configReader.read(path); } private readValuelistsConfiguration(path: string): Map { const valuelistsConfiguration = this.configReader.read(path); map((definition: ValuelistDefinition, id: string) => definition.id = id, valuelistsConfiguration); return valuelistsConfiguration; } }