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

Source: operation/js/api/Conditions.js

define([
    'bop/js/EmptyCondition',
    'bop/js/api/operation/CompositeCondition',
    'bop/js/api/operation/RelationOperator',
    'bop/js/api/operation/SimpleCondition',
    'operation/js/api/Operator',
    'operation/js/query/QueryParameterDescription'
], function (
        EmptyCondition,
        CompositeCondition,
        RelationOperator,
        SimpleCondition,
        Operator,
        QueryParameterDescription
    ) {

    'use strict';

    /**
     * An API object providing methods used for building a certain {@link operation/js/api/Condition Condition}.
     *
     * @AbcsAPI stable
     * @version 15.4.5
     * @exports operation/js/api/Conditions
     *
     * @see {@link operation/js/api/Condition Condition}
     * @see {@link module:operation/js/api/Operator Operator}
     */
    var Conditions = function() {
        AbcsLib.throwStaticClassError();
    };

    Conditions._PROPERTY_UNDEFINED = 'Simple condition can\'t be created without passing Property instance';
    Conditions._NO_PARAMETER_PASSED_OR_METHOD = 'There is no parameter passed. Please call QueryBuilder.or() method with appropriate params';
    Conditions._NO_PARAMETER_PASSED_ADD_METHOD = 'There is no parameter passed. Please call QueryBuilder.and() method with appropriate params';

    /**
     * Empty {@link operation/js/api/Condition Condition} without any restriction.
     *
     * @type {operation/js/api/Condition}
     *
     * @public
     * @static
     * @constant
     * @example
     * <caption>
     *  Creates an instance of {@link operation/js/api/Condition Condition} without any restriction.
     * </caption>
     *
     * var condition = Conditions.EMPTY;
     */
    Conditions.EMPTY = new EmptyCondition();

    /**
     * Creates a new instance of {@link operation/js/api/Condition Condition} with a single restriction.
     *
     * @AbcsAPI stable
     * @version 15.4.5
     * @param {entity/js/api/Property} property - property used by this condition
     * @param {module:operation/js/api/Operator} operator - applied operator
     * @param {String} value
     * @returns {operation/js/api/Condition}
     *
     * @public
     * @static
     * @example
     * <caption>
     *  Create an instance of {@link operation/js/api/Condition Condition} with a single restriction.
     * </caption>
     *
     * var condition = Conditions.SIMPLE(firstName, Operator.EQUALS, 'Martin');
     */
    Conditions.SIMPLE = function(property, operator, value) {
        if (!property) {
            throw Conditions._PROPERTY_UNDEFINED;
        }

        var queryOperator = operator ? operator : Operator.EQUALS;
        var queryParamDesc = new QueryParameterDescription(property);

        return new SimpleCondition(queryParamDesc, queryOperator, value ? value : '');
    };

    /**
     * Creates new composite {@link operation/js/api/Condition Condition} which consist of multiple {@link operation/js/api/Condition Condition}s joining
     * them using an AND operator.
     *
     * @AbcsAPI stable
     * @version 15.4.5
     * @param {operation/js/api/Condition[]} arguments - either array of Condition's or simply Condition's separated and passed one by one
     * @returns {operation/js/api/Condition}
     *
     * @public
     * @static
     * @example
     * <caption>
     *  Creates an instance of {@link operation/js/api/Condition Condition} with two sub-restrictions combining them using an AND operator.
     * </caption>
     *
     * // Finds all employees with firstname = 'Martin' and lastname = 'Janicek'.
     *
     * var composite = Conditions.AND(
     *     Conditions.SIMPLE(firstName, Operator.EQUALS, 'Martin'),
     *     Conditions.SIMPLE(lastName, Operator.EQUALS, 'Janicek')
     * );
     *
     * @example
     * <caption>
     *  Creates an instance of {@link operation/js/api/Condition Condition} with two sub-restrictions combining them using an AND operator -
     *  this time using an array of {@link operation/js/api/Condition Condition}s.
     * </caption>
     *
     * // Finds all employees with firstname = 'Martin' and lastname = 'Janicek'.
     *
     * var conditions = [];
     * conditions.push(Conditions.SIMPLE(firstName, Operator.EQUALS, 'Martin'));
     * conditions.push(Conditions.SIMPLE(lastName, Operator.EQUALS, 'Janicek'));
     * var composite = Conditions.AND(conditions);
     *
     * @example
     * <caption>
     *  Creates a more complex {@link operation/js/api/Condition Condition} combining multiple AND and OR operators.
     * </caption>
     *
     * // Finds all employees whose name is either 'Martin Janicek' or 'Ondrej Brejla'
     *
     * var condition = Conditions.OR(
     *     Conditions.AND(
     *         Conditions.SIMPLE(firstName, Operator.EQUALS, 'Martin'),
     *         Conditions.SIMPLE(lastName, Operator.EQUALS, 'Janicek')
     *     ),
     *     Conditions.AND(
     *         Conditions.SIMPLE(firstName, Operator.EQUALS, 'Ondrej'),
     *         Conditions.SIMPLE(lastName, Operator.EQUALS, 'Brejla')
     *     )
     * );
     */
    Conditions.AND = function() {
        if (arguments.length < 1) {
            throw Conditions._NO_PARAMETER_PASSED_ADD_METHOD;
        } else {
            // If an array of elements was passed directly, simply behave as if it was number of individual parameters
            if (AbcsLib.isArray(arguments[0])) {
                return Conditions._createConditon(arguments[0], RelationOperator.AND);
            }
            return Conditions._createConditon(Array.prototype.slice.call(arguments, 0), RelationOperator.AND);
        }
    };

    /**
     * Creates new composite {@link operation/js/api/Condition Condition} which consists of multiple {@link operation/js/api/Condition Condition}s joining
     * them using an OR operator.
     *
     * @AbcsAPI stable
     * @version 15.4.5
     * @param {operation/js/api/Condition[]} arguments - either array of Condition's or simply Condition's separated and passed one by one
     * @returns {operation/js/api/Condition}
     *
     * @public
     * @static
     * @example
     * <caption>
     * Creates an instance of composite {@link operation/js/api/Condition Condition} with two sub-restrictions combining them using an OR operator.
     * </caption>
     *
     * // Finds all employees with firstname = 'Martin' or firstname = 'Ondrej'.
     *
     * var composite = Conditions.OR(
     *     Conditions.SIMPLE(firstName, Operator.EQUALS, 'Martin'),
     *     Conditions.SIMPLE(firstName, Operator.EQUALS, 'Ondrej')
     * );
     *
     * @example
     * <caption>
     *  Creates an instance of composite {@link operation/js/api/Condition Condition} with two sub-restrictions combining them using an OR operator -
     *  this time using an array of {@link operation/js/api/Condition Condition}s.
     * </caption>
     *
     * // Finds all employees with firstname = 'Martin' or firstname = 'Ondrej'.
     *
     * var conditions = [];
     * conditions.push(Conditions.SIMPLE(firstName, Operator.EQUALS, 'Martin'));
     * conditions.push(Conditions.SIMPLE(firstName, Operator.EQUALS, 'Ondrej'));
     * var composite = Conditions.OR(conditions);
     *
     * @example
     * <caption>
     *  Creates a more complex composite {@link operation/js/api/Condition Condition} combining AND and OR operators.
     * </caption>
     *
     * // Finds all employees whose name is either 'Martin Janicek' or 'Ondrej Brejla'
     *
     * var condition = Conditions.OR(
     *     Conditions.AND(
     *         Conditions.SIMPLE(firstName, Operator.EQUALS, 'Martin'),
     *         Conditions.SIMPLE(lastName, Operator.EQUALS, 'Janicek')
     *     ),
     *     Conditions.AND(
     *         Conditions.SIMPLE(firstName, Operator.EQUALS, 'Ondrej'),
     *         Conditions.SIMPLE(lastName, Operator.EQUALS, 'Brejla')
     *     )
     * );
     */
    Conditions.OR = function() {
        if (arguments.length < 1) {
            throw Conditions._NO_PARAMETER_PASSED_OR_METHOD;
        } else {
            // If an array of elements was passed directly, simply behave as if it was number of individual parameters
            if (AbcsLib.isArray(arguments[0])) {
                return Conditions._createConditon(arguments[0], RelationOperator.OR);
            }
            return Conditions._createConditon(Array.prototype.slice.call(arguments, 0), RelationOperator.OR);
        }
    };

    /**
     * Creates a new {@link Condition} instance build using the given JSON definition.
     *
     * <p>
     * This is revert operation to {@link Condition#getDefinition} method. If one invokes:
     *
     * <br/><br/>
     * <code>
     *  var def = condition.getDefinition();<br/>
     *  var recreatedCondition = Conditions.createFromDefinition(def);
     * </code>
     * <br/><br/>
     *
     * It is guaranteed that the structure of 'recretedCondition' will stays the same as was
     * in the original condition.
     * </p>
     *
     * @static
     *
     * @param {Object[]} conditionsJSON - stored JSON definition
     * @param {Object[]} queryDescription
     * @returns {Condition}
     */
    Conditions.createFromDefinition = function(conditionsJSON, queryDescription) {
        // This is a composite condition and thus we need to proceed it recursively
        if (conditionsJSON.relationOperator && conditionsJSON.conditions) {
            var operator = RelationOperator.forName(conditionsJSON.relationOperator);
            var conditions = [];

            for (var i = 0; i < conditionsJSON.conditions.length; i++) {
                var conditionJSON = conditionsJSON.conditions[i];
                var condition = Conditions.createFromDefinition(conditionJSON, queryDescription);
                if (condition) {
                    conditions.push(condition);
                }
            }
            return new CompositeCondition(operator, conditions);
        }
        return SimpleCondition.createFromDefinition(conditionsJSON, queryDescription);
    };

    /**
     * Creates a {@link Condition} based on the given parameter.
     *
     * <p>
     * If just one {@link Condition} was passed to the function, it will return simple {@link SimpleCondition}.
     * If more than one {@link Condition}s were passed to the function, it will build up a {@link CompositeCondition}
     * </p>
     *
     * @static
     *
     * @param {Condition[]} conditions
     * @param {RelationOperator} operator
     * @returns {Condition}
     */
    Conditions._createConditon = function(conditions, operator) {
        if (conditions.length === 1) {
            return conditions[0];
        }
        return new CompositeCondition(operator, conditions);
    };

    return Conditions;
});