import {Injectable} from '@angular/core';
import {Http} from '@angular/http';
import {ProjectConfiguration} from './project-configuration';
import {MDInternal} from '../messages/md-internal';
import {ConfigurationPreprocessor} from './configuration-preprocessor';
import {ConfigurationValidator} from './configuration-validator';
import {PrePrepprocessConfigurationValidator} from './pre-prepprocess-configuration-validator';
@Injectable()
/**
* Lets clients subscribe for the app
* configuration. In order for this to work, they
* have to call go 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 {
private static defaultFields = [
{
name: 'id',
editable: false,
visible: false
},
{
name: 'type',
visible: false,
editable: false
}
];
private processedAppConfiguration: Promise|undefined = undefined;
private resolveFunction: Function = () => {};
private rejectFunction: Function = () => {};
constructor(private http: Http) {
this.processedAppConfiguration = new Promise((resolve, reject) => {
this.resolveFunction = resolve;
this.rejectFunction = reject;
});
}
/**
* @returns resolves with the ProjectConfiguration or rejects with
* a msgWithParams.
*/
public getProjectConfiguration = (): Promise|undefined => this.processedAppConfiguration;
public async go(
appConfigurationPath: string,
hiddenConfigurationPath: string|undefined,
externallyConfiguredConfigurationPreprocessor: ConfigurationPreprocessor,
postPreprocessConfigurationValidator: ConfigurationValidator) {
let appConfiguration;
try {
appConfiguration = await this.read(this.http, appConfigurationPath);
} catch (msgWithParams) {
if (this.rejectFunction) return this.rejectFunction([msgWithParams]);
}
// PRE PREPROCESS VALIDATION
/*
const prePreprocessValidationErrors = PrePrepprocessConfigurationValidator.go(appConfiguration);
if (prePreprocessValidationErrors.length > 0) {
return this.rejectFunction(prePreprocessValidationErrors);
}
*/
// PREPROCESS
if (hiddenConfigurationPath) {
let hiddenConfiguration;
try {
hiddenConfiguration = await this.read(this.http, hiddenConfigurationPath);
if (hiddenConfiguration) ConfigLoader.hideFields(appConfiguration, hiddenConfiguration);
} catch (_) {}
}
if (externallyConfiguredConfigurationPreprocessor) {
externallyConfiguredConfigurationPreprocessor.go(appConfiguration);
}
new ConfigurationPreprocessor([], ConfigLoader.defaultFields, [])
.go(appConfiguration);
// POST PREPROCESS VALIDATION
let configurationErrors: any = [];
if (postPreprocessConfigurationValidator) configurationErrors = postPreprocessConfigurationValidator.go(appConfiguration);
if (configurationErrors.length > 0) {
this.rejectFunction(configurationErrors);
} else {
this.resolveFunction(new ProjectConfiguration(appConfiguration));
}
}
private read(http: any, path: string): Promise {
return new Promise((resolve, reject) => {
http.get(path).subscribe((data_: any) => {
let data;
try {
data = JSON.parse(data_['_body']);
} catch(e) {
reject([MDInternal.PARSE_ERROR_INVALID_JSON, path]);
}
try {
resolve(data);
} catch(e) {
console.log(e);
}
});
});
}
private static hideFields(appConfiguration: any, hiddenConfiguration: any) {
if (appConfiguration.types) {
for (let type of Object.keys(hiddenConfiguration)) {
for (let fieldToHide of hiddenConfiguration[type]) {
for (let i in appConfiguration.types) {
if (appConfiguration.types[i].type === type
&& appConfiguration.types[i].fields) {
for (let j in appConfiguration.types[i].fields) {
if (appConfiguration.types[i].fields[j].name === fieldToHide) {
appConfiguration.types[i].fields[j].visible = false;
appConfiguration.types[i].fields[j].editable = false;
}
}
}
}
}
}
}
}
}