Home Manual Reference Source Test Repository

src/provision/entities/EntityBuilder.js

'use strict';

import q, {
    timeout
} from 'q';
import jp from 'jsonpath';

import Ajv from 'ajv';
import AssetBuilder from './AssetBuilder';
import DeviceBuilder from './DeviceBuilder';
import TicketBuilder from './TicketBuilder';
import SubscriberBuilder from './SubscriberBuilder';
import SubscriptionBuilder from './SubscriptionBuilder';
import CsvBulkBuilder from './CsvBulkBuilder';
import JsonFlattenedBulkBuilder from './JsonFlattenedBulkBuilder';
import JsonBulkBuilder from './JsonBulkBuilder';

const jsonSchemaValidator = new Ajv();
const ERROR_ORGANIZATION = 'Parameters organization must be defined';
const ERROR_BULK_RESOURCE = 'The parameters resources must be defined and must be some of these values: entities or tickets';
const BULK_RESOURCES = ['entities', 'tickets'];
const schema_base = '/og_basic_types.json';

/**
 * This is a base object that contains all you can do about Devices.
 */
export default class EntityBuilder {

    /**
     * Constructor
     * @param {InternalOpenGateAPI} Reference to the API object.
     */
    constructor(ogapi) {
        const _this = this;
        this._ogapi = ogapi;
    }

    _loadAllowedDatastreams(filterElement, organization, resourceType) {
        let _this = this;
        let defered = q.defer();
        let promise = defered.promise;
        let f = _this._ogapi.newFilterBuilder();
        f.and({
            "like": {
                'datamodels.categories.datastreams.identifier': 'provision'
            }
        }).and({
            "eq": {
                "datamodels.organizationName": organization
            }
        }).and({
            "eq": {
                "datamodels.allowedResourceTypes": resourceType
            }
        });

        let allowedDatastreamsBuilder = this._ogapi.datamodelsSearchBuilder().filter(f).build();

        allowedDatastreamsBuilder.execute().then(function (okh) {
            _this.schema = {};
            return okh;
        }).then(function (data) {
            if (data.statusCode !== 200) {
                defered.reject({
                    data: 'OGAPI_DATASTREAM_NOT_FOUND',
                    statusCode: 204
                });
            }
            _this._getJsonPathElements().then(function () {
                data.data = _this._setDevicesProperties(data.data, filterElement);
                defered.resolve(data);
            }).catch(function (err) {
                defered.reject(err);
            });
        }).catch(function (err) {
            defered.reject(err);
        });
        return promise;
    }

    _getJsonPathElements() {
        let defered = q.defer();
        let promise = defered.promise;

        let basicTypesSearchBuilder = this._ogapi.basicTypesSearchBuilder();

        basicTypesSearchBuilder.withPath('$').build().execute().then(function (res) {
            if (jsonSchemaValidator.getSchema(schema_base)) {
                jsonSchemaValidator.removeSchema(schema_base);
            }

            jsonSchemaValidator.addSchema(res.data, schema_base);
            defered.resolve();
        }).catch(function (err) {
            defered.reject(err);
        });
        return promise;
    }

    _setDevicesProperties(data, filter) {
        let _this = this;
        //http://jekyll.amplia.es/OpenGateDoc/LATEST/opengate-doc-api/api-north/opengate-api-north.html#iotDatastreamTemplate - field calculated (OUW-1679)
        let allowedDatastreams = jp.query(data, "$.datamodels[*].categories[*].datastreams[?(@.calculated === false)]");
        let response = {
            allowedDatastreams: [],
            schemas: {}
        };
        _this.complexFunctions = [];
        _this.simpleFunctions = [];

        allowedDatastreams.forEach(function (element, index) {
            let _id = element.identifier;
            if (_id.startsWith('provision.administration') || _id.startsWith(filter)) {
                response.allowedDatastreams.push(element);
                if (_id.includes('communicationModules')) {
                    var includeSubscriberOrSubscription = filter.includes('subscriber') || filter.includes('subscription');
                    _this.schema[_id] = {
                        value: element.schema,
                        complex: includeSubscriberOrSubscription ? false : true,
                        function: includeSubscriberOrSubscription ? 'with' : 'withComplex'
                    };
                } else {
                    _this.schema[_id] = {
                        value: element.schema,
                        complex: false,
                        function: 'with'
                    };

                }
            }
        });
        response.schemas = _this.schema;

        return response;

    }

    /**
     * Get a DeviceBuilder for operate with entities of type device
     * @example
     * ogapi.devicesBuilder('orgname').then(function(deviceBuilder){//...}).catch()
     * @param {string} organization - required field
     * @param {!number} [timeout] - timeout on request
     * @return {Promise}
     */
    devicesBuilder(organization, timeout) {
        return this._genericBuilder(organization, 'entity.device', 'provision', function (allowedDatastreams, definedSchemas) {
            return new DeviceBuilder(this._ogapi, organization, allowedDatastreams, definedSchemas, jsonSchemaValidator, timeout);
        });
    }

    /**
     * Get a AssetBuilder for operate with entities of type asset
     * @example
     * ogapi.assetsBuilder('orgname').then(function(assetBuilder){//...}).catch()
     * @param {string} organization - required field
     * @param {!number} [timeout] - timeout on request
     * @return {Promise}
     */
    assetsBuilder(organization, timeout) {
        return this._genericBuilder(organization, 'entity.asset', 'provision', function (allowedDatastreams, definedSchemas) {
            return new AssetBuilder(this._ogapi, organization, allowedDatastreams, definedSchemas, jsonSchemaValidator, timeout);
        });
    }

    /**
     * Get a TicketBuilder for operate with entities of type ticket
     * @example
     * ogapi.ticketsBuilder('orgname').then(function(ticketBuilder){//...}).catch()
     * @param {string} organization - required field
     * @param {!number} [timeout] - timeout on request
     * @return {Promise}
     */
    ticketsBuilder(organization, timeout) {
        return this._genericBuilder(organization, 'ticket', 'provision', function (allowedDatastreams, definedSchemas) {
            return new TicketBuilder(this._ogapi, organization, allowedDatastreams, definedSchemas, jsonSchemaValidator, timeout);
        });
    }

    /**
     * Get a SubscriberBuilder for operate with entities of type subscriber
     * @example
     * ogapi.subscribersBuilder('orgname').then(function(subscriberBuilder){//...}).catch()
     * @param {string} organization - required field
     * @param {!number} [timeout] - timeout on request
     * @return {Promise}
     */
    subscribersBuilder(organization, timeout) {
        return this._genericBuilder(organization, 'entity.subscriber', 'provision', function (allowedDatastreams, definedSchemas) {
            return new SubscriberBuilder(this._ogapi, organization, allowedDatastreams, definedSchemas, jsonSchemaValidator, timeout);
        });
    }

    /**
     * Get a SubscriptionBuilder for operate with entities of type subscription
     * @example
     * ogapi.subscriptionsBuilder('orgname').then(function(subscriptionBuilder){//...}).catch()
     * @param {string} organization - required field
     * @param {!number} [timeout] - timeout on request
     * @return {Promise}
     */
    subscriptionsBuilder(organization, timeout) {
        return this._genericBuilder(organization, 'entity.subscription', 'provision', function (allowedDatastreams, definedSchemas) {
            return new SubscriptionBuilder(this._ogapi, organization, allowedDatastreams, definedSchemas, jsonSchemaValidator, timeout);
        });
    }

    /**
     * Get a new CsvBulkBuilder 
     * @example 
     *  ogapi.newCsvBulkBuilder('orgname', 'entities', 10000, false)
     *  ogapi.newCsvBulkBuilder('orgname', 'entities', 10000, true)
     * @param {string} organization - required field. 
     * @param {string} resource - required field. Type of resource: entities or tickets
     * @param {number} [timeout] - timeout in millisecons. The request will have a specific time out if it will be exceeded then the promise throw an exception
     * @param {boolean} [async] - forces async execution for the bulk operation
     * @return {CsvBulkBuilder}
     */
    newCsvBulkBuilder(organization, resource, timeout, async) {
        this._validateBulk(organization, resource);
        return new CsvBulkBuilder(this._ogapi, organization, resource, timeout, async);
    }

    /**
     * Get a new JsonBulkBuilder 
     * @example 
     *  ogapi.newJsonBulkBuilder('orgname', 'entities', 10000)
     * @param {string} organization - required field. 
     * @param {string} resource - required field. Type of resource: entities or tickets
     * @param {number} [timeout] - timeout in millisecons. The request will have a specific time out if it will be exceeded then the promise throw an exception
     * @param {boolean} [async] - forces async execution for the bulk operation
     * @return {JsonBulkBuilder}
     */
    newJsonBulkBuilder(organization, resource, timeout, async) {
        this._validateBulk(organization, resource);
        return new JsonBulkBuilder(this._ogapi, organization, resource, timeout, async);
    }

    /**
     * Get a new JsonFlattenedBulkBuilder 
     * @example 
     *  ogapi.newJsonFlattenedBulkBuilder('orgname', 'entities', 10000)
     * @param {string} organization - required field. 
     * @param {string} resource - required field. Type of resource: entities or tickets
     * @param {number} [timeout] - timeout in millisecons. The request will have a specific time out if it will be exceeded then the promise throw an exception
     * @param {boolean} [async] - forces async execution for the bulk operation
     * @return {JsonFlattenedBulkBuilder}
     */
    newJsonFlattenedBulkBuilder(organization, resource, timeout, async) {
        this._validateBulk(organization, resource);
        return new JsonFlattenedBulkBuilder(this._ogapi, organization, resource, timeout, async);
    }

    _validateBulk(organization, resource) {
        if (!organization) {
            throw new Error(ERROR_ORGANIZATION);
        }
        if (!resource || BULK_RESOURCES.indexOf(resource) === -1) {
            throw new Error(ERROR_BULK_RESOURCE);
        }
    }

    _genericBuilder(organization, resourceType, field, onFindAllowedDatastreams) {
        let _this = this;
        let defered = q.defer();
        if (!organization) {
            throw new Error(ERROR_ORGANIZATION);
        }
        this._loadAllowedDatastreams(field, organization, resourceType)
            .then(function (data) {
                if (data.statusCode === 200) {
                    defered.resolve(onFindAllowedDatastreams.call(_this, data.data.allowedDatastreams, data.data.schemas));
                } else {
                    defered.reject('OGAPI_DATASTREAM_NOT_FOUND');
                }
            }).catch(function (err) {
                defered.reject(err);
            });
        return defered.promise;
    }
}