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

Source: bop/js/api/operation/CompositeCondition.js

define([
    'bop/js/EmptyCondition',
    'bop/js/api/operation/RelationOperator',
    'operation/js/api/Condition'
], function (
        EmptyCondition,
        RelationOperator,
        Condition
        ) {

    'use strict';

    /**
     * Represents a composite filtering rule which can be applied by the client to fetch only records matching the given restrictions.
     *
     * <p>
     * {@link bop/js/api/operation/CompositeCondition CompositeCondition} consist of a single {@link bop/js/api/operation/RelationOperator RelationOperator} and an array of sub-{@link operation/js/api/Condition Condition}s
     * which belongs logically under this composition. Assigned {@link bop/js/api/operation/RelationOperator RelationOperator} is always aplied between all passed sub-{@link operation/js/api/Condition Condition}s.
     * </p>
     *
     * <p>
     * Sub-{@link operation/js/api/Condition Condition} might be again instance of {@link bop/js/api/operation/CompositeCondition CompositeCondition} which results in a deeper tree based structure or if they are rather
     * leafs, they need to be instances of {@link bop/js/api/operation/SimpleCondition SimpleCondition}. That allows Application Builder UI (and also API client when using {@link module:operation/js/api/Conditions Conditions}
     * factory) to potentially build any tree structure including parenthesis logic.
     * </p>
     *
     * @AbcsExtension stable
     * @version 17.1.1
     * @exports bop/js/api/operation/CompositeCondition
     *
     * @constructor
     * @private
     *
     * @see {@link bop/js/api/operation/SimpleCondition SimpleCondition}
     * @see {@link bop/js/api/operation/RelationOperator RelationOperator}
     * @see {@link module:operation/js/api/Conditions.OR Conditions.OR(..)} to create {@link bop/js/api/operation/CompositeCondition CompositeCondition}s with {@link bop/js/api/operation/RelationOperator.OR RelationOperator.OR} set.
     * @see {@link module:operation/js/api/Conditions.AND Conditions.AND(..)} to create {@link bop/js/api/operation/CompositeCondition CompositeCondition}s with {@link bop/js/api/operation/RelationOperator.OR RelationOperator.AND} set.
     * @see {@link bop/js/spi/operation/ConditionVisitor#visitCompositeCondition ConditionVisitor.visitCompositeCondition(..)} to check how {@link bop/js/spi/operation/ConditionVisitor ConditionVisitor} is processed.
     *
     * @param {bop/js/api/operation/RelationOperator} relationOperator
     * @param {Condition[]} conditions
     */
    var CompositeCondition = function(relationOperator, conditions) {
        AbcsLib.checkThis(this);
        Condition.apply(this, conditions);

        this._relationOperator = relationOperator;
        this._conditions = conditions;
    };
    AbcsLib.extend(CompositeCondition, Condition);

    CompositeCondition._RELATION_OPERATOR = 'relationOperator';
    CompositeCondition._CONDITIONS = 'conditions';
    CompositeCondition._LOGGER = Logger.get('CompositeCondition');

    CompositeCondition.prototype.getDefinition = function() {
        var self = this;
        var result = {};
        result[CompositeCondition._RELATION_OPERATOR] = self._relationOperator;
        result[CompositeCondition._CONDITIONS] = [];

        for (var i = 0; i < self._conditions.length; i++) {
            var condition = self._conditions[i];
            result.conditions.push(condition.getDefinition());
        }
        return result;
    };

    CompositeCondition.prototype.clone = function() {
        var self = this;
        var conditions = [];
        self._conditions.forEach(function(condition) {
            conditions.push(condition.clone());
        });

        return new CompositeCondition(self._relationOperator, conditions);
    };

    CompositeCondition.prototype.match = function(recordData) {
        var self = this;
        var operator = self._relationOperator;
        var condition;
        switch (operator) {
            // If at least one Condition is false, return false immediately
            case RelationOperator.AND:
                for (var i = 0; i < self._conditions.length; i++) {
                    condition = self._conditions[i];
                    if (!condition.match(recordData)) {
                        return false;
                    }
                }
                return true;

            // If at least one Condition is true, return true immediately
            case RelationOperator.OR:
                for (var j = 0; j < self._conditions.length; j++) {
                    condition = self._conditions[j];
                    if (condition.match(recordData)) {
                        return true;
                    }
                }
                return false;
            default:
                CompositeCondition._LOGGER.trace('Unknown operator: ' + operator);
        }
    };

    CompositeCondition.prototype.append = function(condition, relationOperator) {
        // If client attempts to append EmptyCondition, simply return this instance
        if (condition === null || condition === undefined || condition instanceof EmptyCondition) {
            return this;
        }

        // If relationOperator is defined, create a purely new CompositeCondition which consist from
        // the original one and passed value
        if (relationOperator) {
            return new CompositeCondition(relationOperator, [this, condition]);
        }

        // No relationOperator means simply appending the given condition into current Composite
        this._conditions.push(condition);
        return this;
    };

    CompositeCondition.prototype.visit = function(conditionVisitor) {
        return conditionVisitor.visitCompositeCondition(this);
    };

    /**
     * Gets an array of sub-{@link operation/js/api/Condition Condition}s belonging under this {@link bop/js/api/operation/CompositeCondition CompositeCondition}.
     *
     * <p>
     * Sub-{@link operation/js/api/Condition Condition} might be either instance of {@link bop/js/api/operation/CompositeCondition CompositeCondition} which means
     * we are dealing with a deeper tree based structure or leafs will be instances of {@link bop/js/api/operation/SimpleCondition SimpleCondition}.
     * </p>
     *
     * @AbcsExtension stable
     * @version 17.1.1
     *
     * @returns {operation/js/api/Condition[]}
     */
    CompositeCondition.prototype.getSubConditions = function() {
        return this._conditions;
    };

    /**
     * Gets the {@link bop/js/api/operation/RelationOperator RelationOperator} assigned to this {@link bop/js/api/operation/CompositeCondition CompositeCondition}.
     *
     * @AbcsExtension stable
     * @version 17.1.1
     *
     * @returns {bop/js/api/operation/RelationOperator}
     */
    CompositeCondition.prototype.getRelationOperator = function() {
        return this._relationOperator;
    };

    return CompositeCondition;
});