Manual Reference Source

app/modules/entities/pipeline/pipeline.js

// @flow
const ODM = require('../crud/odm');
const Joi = require('joi');
const Handlebars = require('../../utils/templating');
const Utils = require('../../utils/utils');
const FormatFunctions = require('../../pipeline/formatter/formatfunctions');
const ComplFunctions = require('../../pipeline/completer/complfunctions');
const TransFunctions = require('../../pipeline/transformer/transfunctions');
const MMapping = require('../crud/mapping');

class Pipeline extends ODM {
    static _recover_value(value: string, type: string): ?number | ?boolean | ?string | ?Object {
        if (value === '__null') {
            return null;
        } else if (value === '__undefined') {
            return undefined;
        } else if (value === '{}') {
            return {};
        } else if (value === '__empty_string') {
            return '';
        }

        switch (type) {
        default:
        case 'string':
            return value;
        case 'boolean': {
            if (typeof value === 'boolean') {
                return value;
            }
            const v = value.toLowerCase();
            return (v === 'yes' || v === 'true');
        }
        case 'integer':
            return parseInt(value, 10);
        case 'hexadecimal':
            return parseInt(value, 16);
        case 'double':
            return parseFloat(value);
        }
    }

    static async generate_resetters(source: Object): Promise<Object> {
        if ('resetters' in source) {
            return source.resetters.reduce((obj, d) => {
                if (d.value != null && d.key != null) {
                    const t = Handlebars.compile(d.value)({});
                    let myobj = t;
                    try { myobj = JSON.parse(t); } catch (err) {}

                    const small = Utils.make_nested_object_from_path(d.key.split('.'), myobj);
                    obj = Utils.merge_with_replacement(obj, small);
                }
                return obj;
            }, {});
        }
        return {};
    }

    static async generate_filters(source: Object): Promise<Array<string>> {
        if ('filters' in source) {
            return source.filters
                .filter(f => (f != null && f.value && f.value != null))
                .map(f => f.value);
        }
        return [];
    }

    static async generate_defaults(source: Object): Promise<Object> {
        const info = source;
        if ('defaults' in info) {
            return info.defaults.reduce((obj, d) => {
                if (d.value != null && d.key != null) {
                    const t = Handlebars.compile(d.value)({});
                    const small = Utils.make_nested_object_from_path(d.key, t);
                    obj = Utils.merge_with_replacement(obj, small);
                }
                return obj;
            }, {});
        }
        return {};
    }

    static async generate_formatters(source: Object): Promise<Array<any>> {
        const info = source;
        if ('formatters' in info && info.formatters.length > 0) {
            return info.formatters.map((f) => {
                if (f.function.arguments) {
                    f.function.arguments = f.function.arguments.map((arg) => {
                        arg.value = Pipeline._recover_value(arg.value, arg.type);
                        return arg;
                    });
                }

                const args = f.function.arguments;
                switch (f.function.name) {
                case 'oarray_to_array':
                    return { [f.field]: a => FormatFunctions.oarray_to_array(a) };
                case 'filter_empty_or_null_objects':
                    return { [f.field]: FormatFunctions.filter_empty_or_null_objects };
                case 'format_string':
                    return { [f.field]: a => FormatFunctions.format_string(args[0].value)(a) };
                case 'generic_formatter':
                    return { [f.field]: (a, o, k) => FormatFunctions.generic_formatter(args[0].value)(a, o, k) };
                default:
                    return null;
                }
            }).filter(f => f != null);
        }
        return [];
    }

    static async generate_completers(source: Object): Promise<Array<any>> {
        const info = source;
        if ('completers' in info && info.completers.length > 0) {
            return info.completers.map((f) => {
                if (f.function.arguments) {
                    f.function.arguments = f.function.arguments.map((arg) => {
                        arg.value = Pipeline._recover_value(arg.value, arg.type);
                        return arg;
                    });
                }

                const args = f.function.arguments;
                switch (f.function.name) {
                case 'generic_complete':
                    return { [f.field]: (o, p, i) => ComplFunctions.generic_complete(args[0].value)(o, p, i) };
                case 'key_complete':
                    return { [f.field]: (o, p, i) => ComplFunctions.key_complete(o, p, i) };
                case 'secret_complete':
                    return { [f.field]: (o, p, i) => ComplFunctions.secret_complete(o, p, i) };
                case 'denormalization':
                    return { [f.field]: (o, p, i) =>
                        ComplFunctions.denormalization(args[0].value, args[1].value,
                            args[2].value, args[3].value, args[4].value)(o, p, i),
                    };
                case 'initial':
                    return { [f.field]: (o, p, i) =>
                        ComplFunctions.initial(args[0].value, args[1].value)(o, p, i),
                    };
                default:
                    return null;
                }
            }).filter(f => f != null);
        }
        return [];
    }

    static async generate_transformers(source: Object): Promise<Array<any>> {
        const info = source;
        if (!('transformers' in info)) {
            return [];
        }

        if (info.transformers.length === 0) {
            return [];
        }

        return info.transformers.map((f) => {
            switch (f.function.name) {
            default:
                return null;
            }
        }).filter(f => f != null);
    }

    static async generate_validators(source: Object): Promise<Array<any>> {
        const info = source;
        const validators = [];
        if ('validators' in info && info.validators.length > 0) {
            const partitions = info.validators.reduce((obj, v) => {
                if (v.type === 'function') {
                    obj.functions.push(v);
                } else {
                    obj.joi.push(v);
                }
                return obj;
            }, { joi: [], functions: [] });

            validators.push(Joi.object(partitions.joi.reduce((obj, v) => {
                switch (v.type) {
                default:
                case 'string':
                    obj[v.field] = Joi.string();
                    break;
                }

                if (v.required) {
                    obj[v.field] = obj[v.field].required();
                } else {
                    obj[v.field] = obj[v.field].optional().empty('');
                }
                return obj;
            }, {})));
        }
        return validators;
    }

    static async generate_model(index: string, type: string,
        client: Object, pipelines: Array<Object>): Object {
        // console.log('gen model', index, type);
        const mapping = await Pipeline.fetch_mapping(index, type, client);


        const all_pipelines = [];
        for (const pipeline of pipelines) {
            const defaults = await Pipeline.generate_defaults(pipeline.source);
            const filters = await Pipeline.generate_filters(pipeline.source);
            const resetters = await Pipeline.generate_resetters(pipeline.source);
            const formatters = await Pipeline.generate_formatters(pipeline.source);
            const completers = await Pipeline.generate_completers(pipeline.source);
            const validators = await Pipeline.generate_validators(pipeline.source);
            const transformers = await Pipeline.generate_transformers(pipeline.source);
            all_pipelines.push({
                Validation: validators,
                Formatting: formatters,
                Completion: completers,
                Transforming: transformers,
                Filtering: filters,
                Resetting: resetters,
                Defaults: defaults,
            });
        }

        const pipe = {
            RawMapping: mapping,
            Mapping: new MMapping(mapping),
            Messages: {
                set: `l_message_set_entity_${type}`,
                remove: `l_message_remove_entity_${type}`,
                modify: `l_message_modify_entity_${type}`,
            },
            Pipelines: all_pipelines,
            Name: type,
        };
        return pipe;
    }
}

module.exports = Pipeline;