Home Manual Reference Source Test Repository

src/operations/OperationActions.js

'use strict';

import q from 'q';
import moment from 'moment';

const JOB_RESOURCE = "/jobs/";
const TASK_RESOURCE = "/tasks/";
const LIMIT_SIZE_DEF_VALUE = 10;

export default class OperationActions {

    /**
     * Constructor
     * @param {InternalOpenGateAPI} ogapi - this is configuration about Opengate North API.
     * @param {string} operationId - Identifier of the operation on which the action will be carried out
     */
    constructor(ogapi, operationId) {
        if (typeof operationId !== 'string')
            throw new Error('Parameter operationId must be a string');
        this._ogapi = ogapi;
        this._resource = 'operation';
        this._operationId = operationId;
    }

    /**
     * This invoke a request to OpenGate North API and the callback is managed by promises
     * This function active an operation
     * @example 
     * ogapi.newOperationActions("xxxxx-xxx-xxxx-xxxxx").active()
     * @return {Promise} 
     * @property {function (statusCode:number)} then - When request it is OK
     * @property {function (errors:array, statusCode:number)} then - When request it is NOK
     * @property {function (errors:array)} catch - When request it is NOK
     */
    active() {
        let config = {
            request: {
                active: true
            }
        };
        this._key = "job";
        this._resource = this._resource + JOB_RESOURCE + this._operationId;
        return this._update(config);
    }

    /**
     * This invoke a request to OpenGate North API and the callback is managed by promises
     * This function pause an operation
     * @example 
     * ogapi.OperationActions("xxxxx-xxx-xxxx-xxxxx").pause()
     * @return {Promise} 
     * @property {function (statusCode:number)} then - When request it is OK
     * @property {function (errors:array, statusCode:number)} then - When request it is NOK
     * @property {function (errors:array)} catch - When request it is NOK
     */
    pause() {
        let config = {
            request: {
                active: false
            }
        };
        this._key = "job";
        this._resource = this._resource + JOB_RESOURCE + this._operationId;
        return this._update(config);
    }

    /**
     * This invoke a request to OpenGate North API and the callback is managed by promises
     * This function cancela operation
     * @return {Promise}
     * @property {function (result:object, statusCode:number)} then - When request it is OK
     * @property {function (errors:array, statusCode:number)} then - When request it is NOK
     * @property {function (errors:array)} catch - When request it is NOK
     * @example
     * Actions("xxxxx-xxx-xxxx-xxxxx").cancel();
     */
    cancel() {
        this._id = this._operationId;
        this._resource = this._resource + JOB_RESOURCE + this._id;
        return this._cancel(this._resource);
    }

    /**
     * This invoke a request to OpenGate North API and the callback is managed by promises
     * This function active periodicity of an operation
     * @example 
     * ogapi.newOperationActions("xxxxx-xxx-xxxx-xxxxx").activePeriodicity()
     * @return {Promise} 
     * @property {function (statusCode:number)} then - When request it is OK
     * @property {function (errors:array, statusCode:number)} then - When request it is NOK
     * @property {function (errors:array)} catch - When request it is NOK
     */
    activePeriodicity() {
        let config = {
            active: true
        };

        this._key = "task";
        this._resource = this._resource + TASK_RESOURCE;
        return this._periodicityActions("ACTIVE", config);
    }

    /**
     * This invoke a request to OpenGate North API and the callback is managed by promises
     * This function pause periodicity of an operation
     * @example 
     * ogapi.OperationActions("xxxxx-xxx-xxxx-xxxxx").pausePeriodicity()
     * @return {Promise} 
     * @property {function (statusCode:number)} then - When request it is OK
     * @property {function (errors:array, statusCode:number)} then - When request it is NOK
     * @property {function (errors:array)} catch - When request it is NOK
     */
    pausePeriodicity() {
        let config = {
            active: false
        };
        this._key = "task";
        this._resource = this._resource + TASK_RESOURCE;
        return this._periodicityActions("PAUSE", config);
    }

    /**
     * This invoke a request to OpenGate North API and the callback is managed by promises
     * This function cancel the periodicity of an operation
     * @return {Promise}
     * @property {function (result:object, statusCode:number)} then - When request it is OK
     * @property {function (errors:array, statusCode:number)} then - When request it is NOK
     * @property {function (errors:array)} catch - When request it is NOK
     * @example
     * ogapi.OperationActions("xxxxx-xxx-xxxx-xxxxx").cancelPeriodicity();
     */
    cancelPeriodicity() {
        this._resource = this._resource + TASK_RESOURCE;
        return this._periodicityActions("CANCEL");
    }

    /**
     * This invoke a request to OpenGate North API and the callback is managed by promises
     * This function pause, update its delay and active an operation for execute immediately
     * @example 
     * ogapi.OperationActions("xxxxx-xxx-xxxx-xxxxx").executeNow()
     * @return {Promise} 
     * @property {function (statusCode:number)} then - When request it is OK
     * @property {function (errors:array, statusCode:number)} then - When request it is NOK
     * @property {function (errors:array)} catch - When request it is NOK
     */
    executeNow() {
        let config = {
            request: {
                schedule: {
                    start: {}
                }
            }
        };
        this._key = "job";
        return this._readAndUpdate(config, true);
    }

    /**
     * This invoke a request to OpenGate North API and the callback is managed by promises
     * This function pauses (if it was active), updates the delay and passes the operation to the initial state (if activated, activated again)
     * @example 
     * ogapi.OperationActions("xxxxx-xxx-xxxx-xxxxx").executeLater(10)
     * @param {!number} minutes 
     * @return {promise} 
     * @property {function (statusCode:number)} then - When request it is OK
     * @property {function (errors:array, statusCode:number)} then - When request it is NOK
     * @property {function (errors:array)} catch - When request it is NOK
     */
    executeLater(minutes) {
        if (typeof minutes !== "number") {
            throw new Error("Parameter minutes must be typeof number");
        }
        let config = {
            request: {
                schedule: {
                    start: {
                        delayed: moment.duration(minutes, 'minutes').asMilliseconds()
                    }
                }
            }
        };
        this._key = "job";
        return this._readAndUpdate(config);
    }

    /**
     * This invoke a request to OpenGate North API and the callback is managed by promises
     * This function pauses (if it was active), updates the callback and passes the operation to the initial state (if activated, activated again)
     * @example 
     * ogapi.OperationActions("xxxxx-xxx-xxxx-xxxxx").changeCallback("http://[your_application_address]/[your_URI]")
     * @param {!string} url 
     * @return {promise} 
     * @property {function (statusCode:number)} then - When request it is OK
     * @property {function (errors:array, statusCode:number)} then - When request it is NOK
     * @property {function (errors:array)} catch - When request it is NOK
     */
    changeCallback(url) {
        if (typeof url !== "string")
            throw new Error('Parameter url must be a string');
        let config = {
            request: {
                callback: url
            }
        };
        return this._readAndUpdate(config);
    }

    _cancel() {
        var defered = q.defer();
        var promise = defered.promise;
        this._ogapi.Napi.delete(this._resource)
            .then((response) => {
                if (response.statusCode === 200) {
                    defered.resolve({
                        statusCode: response.statusCode,
                        data: {
                            id: this._id
                        }
                    });
                } else {
                    defered.reject({
                        errors: response.errors,
                        statusCode: response.statusCode
                    });
                }
            })
            .catch((error) => {
                defered.reject(this._formatError(error));
            });
        return promise;
    }

    _periodicityActions(action, config) {
        var _this = this;
        var defered = q.defer();
        var promise = defered.promise;
        _this._ogapi.newOperationFinder().findById(_this._operationId)
            .then(function (response) {
                var data = response.data;
                if (!data || Object.keys(data).length == 0) {
                    //BUG http://cm.amplia.es/jira/browse/ODMQA-1057
                    defered.reject({
                        errors: "Operation with id " + _this._operationId + " not exists"
                    });
                } else {
                    let periodicityId = data.taskId;
                    if (!periodicityId) {
                        defered.reject({
                            errors: "Operation is not periodic!"
                        });
                    } else {
                        _this._resource = _this._resource + periodicityId;
                        switch (action) {
                            case "PAUSE":
                            case "ACTIVE":
                                _this._update(config)
                                    .then(function (response) {
                                        defered.resolve(response);
                                    }).catch(function (error) {
                                        defered.reject(error);
                                    });
                                break;
                            case "CANCEL":
                                _this._id = periodicityId;
                                _this._cancel()
                                    .then(function (response) {
                                        defered.resolve(response);
                                    }).catch(function (error) {
                                        defered.reject(error);
                                    });
                                break;
                            default:
                                defered.reject({
                                    errors: "Not implemented action: " + action
                                });
                        }
                    }
                }
            })
            .catch(function (error) {
                defered.reject(error);
            });
        return promise;
    }

    /**
     * This invoke a request to OpenGate North API and the callback is managed by promises
     * This function read and update an operation
     * @example 
     * ogapi.OperationActions("xxxxx-xxx-xxxx-xxxxx")._readAndUpdate({})
     * @param {object} - config 
     * @param {boolean} - forceToActivate
     * @return {Promise} 
     * @property {function (statusCode:number)} then - When request it is OK
     * @property {function (errors:array, statusCode:number)} then - When request it is NOK
     * @property {function (error:string)} catch - When request it is NOK
     */
    _readAndUpdate(config, forceToActivate) {
        let defered = q.defer();
        let promise = defered.promise;
        var _this = this;
        _this._ogapi.newOperationFinder().findById(_this._operationId).then(
            function (response) {
                var data = response.data;
                if (!data) {
                    //BUG http://cm.amplia.es/jira/browse/ODMQA-1057
                    defered.reject("Operation with id " + _this._operationId + " not exists");
                } else {
                    let active = data.operation ? data.operation.active : false;
                    if (active) {
                        _this.pause().then(
                            function (response) {
                                _this._update(config, forceToActivate || active).then(
                                    function (response) {
                                        defered.resolve(response);
                                    }
                                ).catch(
                                    function (error) {
                                        defered.reject(_this._formatError(error));
                                    }
                                );
                            }
                        ).catch(
                            function (error) {
                                defered.reject(_this._formatError(error));
                            }
                        );

                    } else {
                        _this._update(config, forceToActivate || active).then(
                            function (response) {
                                defered.resolve(response);
                            }
                        ).catch(
                            function (error) {
                                defered.reject(_this._formatError(error));
                            }
                        );
                    }
                }
            }
        ).catch(
            function (error) {
                defered.reject(_this._formatError(error));
            }
        );

        return promise;
    }

    /**
     * This invoke a request to OpenGate North API and the callback is managed by promises
     * This function update an operation
     * @example 
     * ogapi.OperationActions("xxxxx-xxx-xxxx-xxxxx")._update({})
     * ogapi.OperationActions("xxxxx-xxx-xxxx-xxxxx")._update({}, _defered, _promise)
     * @return {Promise} 
     * @property {function (statusCode:number)} then - When request it is OK
     * @property {function (errors:array, statusCode:number)} then - When request it is NOK
     * @property {function (error:string)} catch - When request it is NOK
     */
    _update(config, forceToActivate) {
        var _this = this;
        let defered = q.defer();
        let promise = defered.promise;
        let obj = {};
        obj[_this._key] = config;
        this._ogapi.Napi
            .put(this._resource, obj)
            .then((response) => {
                if (forceToActivate) {
                    _this.active().then(
                        function (response) {
                            defered.resolve(response);
                        }
                    ).catch(
                        function (error) {
                            defered.reject(this._formatError(error));
                        }
                    );
                } else {
                    if (response.status === 200) {
                        let data = response.text != "" ? JSON.parse(response.text) : {};
                        let _response = {
                            statusCode: response.status,
                            data: data
                        };
                        defered.resolve(response);
                    } else {
                        defered.reject({
                            errors: response.errors,
                            statusCode: response.status
                        });
                    }
                }
            })
            .catch((error) => {
                defered.reject(this._formatError(error));
            });
        return promise;
    }

    _formatError(error) {
        if (!error.data) {
            error.data = {};
        }
        if (!error.data.errors) {
            error.data.errors = [(typeof (error) === "string") ? {
                message: error
            } : error];
        }
        return error;
    }


}