JavaScript Extension Development API for Oracle Visual Builder Cloud Service - Classic Applications

Source: operation/js/api/OperationResult.js

/* eslint-disable no-use-before-define */

define([
    'core/js/api/utils/StringUtils',
    'operation/js/api/PaginationCursor'
], function(
        StringUtils,
        PaginationCursor
    ) {

    'use strict';

    /**
     * Represents result returned from particular {@link operation/js/api/Operation#perform Operation.perform(..)} method call.
     *
     * <p>
     * Each {@link operation/js/api/Operation#perform Operation.perform(..)} method call returns an instance of {@link operation/js/api/OperationResult OperationResult}.
     * It either:
     * <ul>
     *  <li>
     *      Provides returned data in case {@link operation/js/api/Operation Operation} performed correctly. <br/>
     *      It also can contain any other metadata which Business Object Provider decides to return. For example {@link operation/js/api/PaginationCursor PaginationCursor} can be available if the perfomed
     *      {@link operation/js/api/Operation Operation} has type {@link operation/js/api/Operation.Type.READ_MANY Operation.Type.READ_MANY} set and provider implemented capability to paginate through
     *      the records.
     *  </li>
     *  <li>
     *      Provides error code, message and possibly any other additional error information in case {@link operation/js/api/Operation Operation} performed incorrectly.
     *  </li>
     * </ul>
     *
     * To check the result of {@link operation/js/api/Operation#perform Operation.perform(..)} call, you can use:
     * <ul>
     *  <li>
     *      {@link operation/js/api/OperationResult#isSuccess OperationResult.isSuccess()} to check if the call was performed correctly and resulted in a {@link operation/js/api/OperationResult.Success OperationResult.Success}.
     *  </li>
     *  <li>
     *      {@link operation/js/api/OperationResult#isFailure OperationResult.isFailure()} to check if the call was performed incorrectly and resulted in a {@link operation/js/api/OperationResult.Failure OperationResult.Failure}.
     *  </li>
     * </ul>
     * </p>
     *
     * @AbcsAPI stable
     * @version 17.1.1
     * @exports operation/js/api/OperationResult
     *
     * @constructor
     * @private
     *
     * @see {@link operation/js/api/Operation Operation}
     * @see {@link operation/js/api/Operation#perform Operation.perform(..)}
     */
    var OperationResult = function() {
        AbcsLib.throwStaticClassError();
    };

    /**
     * Creates new instance of {@link operation/js/api/OperationResult.Success OperationResult.Success} result.
     *
     * @AbcsExtension stable
     * @version 17.1.1
     * @public
     * @static
     *
     * @param {Object} [data] - REST data response.
     * @param {operation/js/api/PaginationCursor} [paginationCursor] - Metadata describing data pagination if it was requested.
     * @param {Object} [additionalInfo] - Additional information about the successful operation.
     * @returns {operation/js/api/OperationResult.Success}
     */
    /*
     * @param {String} [etag] - the etag for the http response
     */
    OperationResult.success = function(data, paginationCursor, additionalInfo, etag) {
        AbcsLib.checkThis(this);
        if (paginationCursor) {
            AbcsLib.checkDataType(paginationCursor, PaginationCursor);
        }
        AbcsLib.checkParameterCount(arguments, 0, 4);

        return new Success(data, paginationCursor, additionalInfo, etag);
    };

    /**
     * Creates new instance of {@link operation/js/api/OperationResult.Failure OperationResult.Failure} result.
     *
     * @AbcsExtension stable
     * @version 17.1.1
     * @public
     * @static
     *
     * @param {String} message - Message describing in detail why {@link operation/js/api/Operation#perform Operation.perform(..)} method failed.
     * @param {Number} [code] - Error code for better identification of what type of error caused {@link operation/js/api/Operation#perform Operation.perform(..)} method to fail.
     * @param {Object} [additionalInfo] - Additional information about the failure.
     * @returns {operation/js/api/OperationResult.Failure}
     *
     * @example
     * <caption>
     *  Creates an instance of {@link operation/js/api/OperationResult.Failure OperationResult.Failure} result with only message text set.
     * </caption>
     *
     * var error = OperationResult.failure('This is an example of error message.');
     *
     * @example
     * <caption>
     *  Creates an instance of {@link operation/js/api/OperationResult.Failure OperationResult.Failure} result with message text and error code set.
     * </caption>
     *
     * var error = OperationResult.failure('Not Found.', 404);
     *
     * @example
     * <caption>
     *  Creates an instance of {@link operation/js/api/OperationResult.Failure OperationResult.Failure} result with message text, error code and additional information set.
     * </caption>
     *
     * var error = OperationResult.failure('Not Found.', 404, {
     *     foo: 'You can include anything you want here',
     *     bar: {
     *         barbar: 'You can even structure additional information any way you need'
     *     }
     * });
     */
    OperationResult.failure = function(message, code, additionalInfo) {
        AbcsLib.checkThis(this);
        AbcsLib.checkDefined(message, 'message');
        AbcsLib.checkDataType(message, AbcsLib.Type.STRING);
        if (code) {
            AbcsLib.checkDataType(code, AbcsLib.Type.NUMBER);
        }
        AbcsLib.checkParameterCount(arguments, 1, 2);

        return new Failure(message, code, additionalInfo);
    };

    /**
     * Check whether the given object is an <code>OperationResult.Success</code> instance or not.
     *
     * @param {Object} obj - An arbitrary object to check.
     * @returns {Boolean}
     */
    OperationResult.isSuccessResult = function(obj) {
        return obj instanceof OperationResult && obj.isSuccess();
    };

    /**
     * Check whether the given object is an <code>OperationResult.Failure</code> instance or not.
     *
     * @param {Object} obj - An arbitrary object to check.
     * @returns {Boolean}
     */
    OperationResult.isFailureResult = function(obj) {
        return obj instanceof OperationResult && obj.isFailure();
    };

    /**
     * Checks whether this {@link operation/js/api/OperationResult OperationResult} is {@link operation/js/api/OperationResult.Success OperationResult.Success} or not.
     *
     * @AbcsAPI stable
     * @version 17.1.1
     *
     * @returns {Boolean} true if this {@link operation/js/api/OperationResult OperationResult} is {@link operation/js/api/OperationResult.Success OperationResult.Success}, false otherwise
     *
     * @example
     * <caption>
     *  Performs an existing {@link operation/js/api/Operation Operation} and check the result using {@link operation/js/api/OperationResult#isSuccess OperationResult.isSuccess()} method.
     * </caption>
     *
     * var employee = Abcs.Entities().findById('my.custom.bop.Employee');
     * var operation = Abcs.Operations().create({
     *     entity: employee,
     *     record: {
     *         firstName: 'Martin',
     *         lastName: 'Janicek',
     *         age: 28
     *     }
     * });
     *
     * operation.perform().then(function(operationResult) {
     *      if (operationResult.isSuccess()) {
     *          // Insert code you want to perform after record being created
     *      }
     * });
     */
    OperationResult.prototype.isSuccess = function() {
        return this instanceof Success;
    };

    /**
     * Checks whether this {@link operation/js/api/OperationResult OperationResult} is {@link operation/js/api/OperationResult.Failure OperationResult.Failure} or not.
     *
     * @AbcsAPI stable
     * @version 17.1.1
     *
     * @returns {Boolean} true if this {@link operation/js/api/OperationResult OperationResult} is {@link operation/js/api/OperationResult.Failure OperationResult.Failure}, false otherwise
     *
     * @example
     * <caption>
     *  Performs an existing {@link operation/js/api/Operation Operation} and check the result using {@link operation/js/api/OperationResult#isFailure OperationResult.isFailure()} method.
     * </caption>
     *
     * var employee = Abcs.Entities().findById('my.custom.bop.Employee');
     * var operation = Abcs.Operations().create({
     *     entity: employee,
     *     record: {
     *         firstName: 'Martin',
     *         lastName: 'Janicek',
     *         age: 28
     *     }
     * });
     *
     * operation.perform().then(function(operationResult) {
     *     // Do something when your operation succeed
     * }).catch(function(operationResult) {
     *     if (operationResult.isFailure()) {
     *         // Insert code you want to perform if record creation failed
     *     }
     * });
     */
    OperationResult.prototype.isFailure = function() {
        return this instanceof Failure;
    };

    OperationResult._ENTITY_NOT_FOUND = 'Not Found';
    OperationResult._INSUFFICIENT_PRIVILEGES_EXCEPTION = 'InsufficientPrivilegeException';

    /**
     * Checks whether this <code>OperationResult</code> instance represents failure caused by insufficient privileges or not.
     *
     * @returns {Boolean}
     */
    OperationResult.prototype.isInsufficientPrivileges = function() {
        if (this.isFailure()) {
            var errorMessage = this.getMessage();
            var errorCode = this.getCode();
            if (errorCode === 403 && StringUtils.contains(errorMessage, OperationResult._INSUFFICIENT_PRIVILEGES_EXCEPTION)) {
                return true;
            }
        }
        return false;
    };

    /**
     * Checks whether this <code>OperationResult</code> instance represents failure caused by missing entity.
     *
     * @returns {Boolean}
     */
    OperationResult.prototype.isNotFoundEntity = function() {
        if (this.isFailure()) {
            var errorMessage = this.getMessage();
            var errorCode = this.getCode();
            if (errorCode === 404 && StringUtils.contains(errorMessage, OperationResult._ENTITY_NOT_FOUND)) {
                return true;
            }
        }
        return false;
    };

    /**
     * Represents error result coming from {@link operation/js/api/Operation#perform Operation.perform(..)} method.
     *
     * @AbcsAPI stable
     * @version 17.1.1
     * @memberof operation/js/api/OperationResult
     * @constructor
     * @private
     *
     * @param {String} message
     * @param {Number} [code]
     * @param {Object} [additionalInfo]
     */
    var Failure = function (message, code, additionalInfo) {
        this._code = code;
        this._message = message;
        this._additionalInfo = additionalInfo;
    };
    AbcsLib.extend(Failure, OperationResult);

    /**
     * Gets the message describing why {@link operation/js/api/Operation#perform Operation.perform(..)} method failed.
     *
     * @AbcsAPI stable
     * @version 17.1.1
     * @memberof operation/js/api/OperationResult.Failure
     *
     * @returns {String}
     */
    Failure.prototype.getMessage = function() {
        return this._message;
    };

    /**
     * Gets the {@link operation/js/api/OperationResult.Failure OperationResult.Failure} code for identification of what type of error caused {@link operation/js/api/Operation#perform Operation.perform(..)} method to fail.
     *
     * @AbcsAPI stable
     * @version 17.1.1
     * @memberof operation/js/api/OperationResult.Failure
     *
     * @returns {Number}
     */
    Failure.prototype.getCode = function() {
        return this._code;
    };

    /**
     * Gets additional information which can be used to pass any other proprietary information into client's {@link operation/js/api/OperationResult OperationResult} handler.
     *
     * @AbcsAPI stable
     * @version 17.1.1
     * @memberof operation/js/api/OperationResult.Failure
     *
     * @returns {Object}
     *
     * @example
     * <caption>
     *  Performs an existing {@link operation/js/api/Operation Operation} and use additional information to behave appropriately in {@link operation/js/api/OperationResult OperationResult} handler.
     * </caption>
     *
     * var employee = Abcs.Entities().findById('my.custom.bop.Employee');
     * var operation = Abcs.Operations().create({
     *     entity: employee,
     *     record: {
     *         firstName: 'Martin',
     *         lastName: 'Janicek',
     *         age: 28
     *     }
     * });
     *
     * operation.perform().then(function(operationResult) {
     *     // Do something when your operation succeed
     * }).catch(function(operationResult) {
     *     if (operationResult.isFailure()) {
     *         // Let's assume that Operation implementor included Object literal with 'log' field for better error tracing
     *         var additionalInfo = operationResult.getAdditionalInfo();
     *         var log = additionalInfo.log;
     *         if (log) {
     *             // Insert code you want to perform if record creation failed and 'log' info is available
     *         }
     *     }
     * });
     */
    Failure.prototype.getAdditionalInfo = function() {
        return this._additionalInfo;
    };

    /**
     * Represents success result coming from {@link operation/js/api/Operation#perform Operation.perform(..)} method.
     *
     * @AbcsAPI stable
     * @version 17.1.1
     * @memberof operation/js/api/OperationResult
     * @constructor
     * @private
     *
     * @param {Object} data
     * @param {PaginationCursor} [paginationCursor]
     * @param {Object} [additionalInfo]
     * @param {String} [etag]
     */
    var Success = function (data, paginationCursor, additionalInfo, etag) {
        this._data = data;
        this._paginationCursor = paginationCursor;
        this._additionalInfo = additionalInfo;
        this._etag = etag;
    };
    AbcsLib.extend(Success, OperationResult);

    /**
     * Returns data coming from {@link operation/js/api/Operation#perform Operation.perform(..)} method.
     *
     * <p>
     * This can be anything and it depends on the {@link operation/js/api/Operation Operation} author to decide how the resulted data are structured.
     * Usually in case of {@link operation/js/api/Operation.Type.READ_MANY Operation.Type.READ_MANY}, the {@link operation/js/api/Operation#perform Operation.perform(..)}
     * returns array of {@link module:api/js/Operations~Record Record}s in it's data field, but it's not a rule and different Business Object Provider's can vary in how they
     * process and return their results.
     * </p>
     *
     * @AbcsAPI stable
     * @version 17.1.1
     * @memberof operation/js/api/OperationResult.Success
     *
     * @returns {module:api/js/Operations~Record | module:api/js/Operations~Record[]}
     */
    Success.prototype.getData = function() {
        return this._data;
    };

    /**
     * Sets data records for this result.
     *
     * <p>
     * This should never become public API, it's only required insternally by OperationBuilder doing data mash-ups.
     * </p>
     *
     * @param {Object<String, Object>} data
     */
    Success.prototype.setData = function(data) {
        this._data = data;
    };

    /**
     * Gets the {@link operation/js/api/PaginationCursor PaginationCursor} returned by the performed {@link operation/js/api/Operation Operation}.
     *
     * @AbcsAPI stable
     * @version 17.1.1
     * @memberof operation/js/api/OperationResult.Success
     *
     * @returns {operation/js/api/PaginationCursor}
     */
    Success.prototype.getPaginationCursor = function() {
        return this._paginationCursor;
    };

    /**
     * Gets additional information returned by the performed {@link operation/js/api/Operation Operation}.
     *
     * <p>
     * Additional info has no formal structure defined. It's up to the {@link operation/js/api/Operation Operation} author whether s(he) needs or wants to pass some custom
     * values as part of the {@link operation/js/api/OperationResult OperationResult} and as such, the format is completely up to the author. It can be complex Object
     * literal, plain String value or any other valid JS construct.
     * </p>
     *
     * <p>
     * Consult with BOP author to learn what an {@link operation/js/api/Operation Operation} may return as custom results.
     * </p>
     *
     * @AbcsAPI stable
     * @version 17.1.1
     * @memberof operation/js/api/OperationResult.Success
     *
     * @returns {Object}
     */
    Success.prototype.getAdditionalInfo = function() {
        return this._additionalInfo;
    };

    Success.prototype.getETag = function() {
        return this._etag;
    };

    return OperationResult;
});