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

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

define([
    'bop/js/EmptyCondition',
    'bop/js/api/operation/CompositeCondition',
    'core/js/api/utils/StringUtils',
    'entity/js/api/PropertyType',
    'operation/js/api/Condition',
    'operation/js/api/FieldPath',
    'operation/js/api/Operator',
    'operation/js/query/QueryType'
], function(
        EmptyCondition,
        CompositeCondition,
        StringUtils,
        PropertyType,
        Condition,
        FieldPath,
        Operator,
        QueryType) {

    'use strict';

    /**
     * Represents a single filtering rule which can be applied by the client to fetch only records matching the given restriction.
     *
     * <p>
     * {@link bop/js/api/operation/SimpleCondition SimpleCondition} is not expected to be created directly by the client. It's only consumed by the {@link bop/js/spi/operation/ConditionVisitor#visitSimpleCondition ConditionVisitor.visitSimpleCondition(..)}
     * method where {@link bop/js/spi/BOP BOP} author is expected to interpret incoming {@link operation/js/api/Condition Condition}s and transform them into proper URL query or generally process them any way (s)he need.
     * </p>
     *
     * @AbcsExtension stable
     * @version 17.1.1
     * @exports bop/js/api/operation/SimpleCondition
     *
     * @constructor
     * @private
     *
     * @see {@link entity/js/api/Property Property}
     * @see {@link module:operation/js/api/Operator Operator}
     * @see {@link bop/js/api/operation/CompositeCondition CompositeCondition}
     * @see {@link module:operation/js/api/Conditions.SIMPLE Conditions.SIMPLE(..)} to create instances of {@link bop/js/api/operation/SimpleCondition SimpleCondition}
     * @see {@link bop/js/spi/operation/ConditionVisitor#visitSimpleCondition ConditionVisitor.visitSimpleCondition(..)} to process instances of {@link bop/js/api/operation/SimpleCondition SimpleCondition}
     *
     * @param {QueryParameterDescription} queryParameterDescription
     * @param {Operator} operator
     * @param {String} value
     * @param {SimpleCondition.Expression} valueExpression - expression which needs to be evaluated to get real live 'value'.
     * You may instantiate an expression with SimpleCondition.createExpression().
     * @param {QueryType} type
     * @param {String} valuePlaceholder
     * @param {boolean} userSpecified
     */
    var SimpleCondition = function(queryParameterDescription, operator, value, valueExpression, type, valuePlaceholder, userSpecified) {
        AbcsLib.checkThis(this);
        Condition.apply(this, arguments);

        var self = this;

        self._value = value;
        self.setValueExpression(valueExpression);
        self._operator = operator;
        self._type = type;
        self._valuePlaceholder = valuePlaceholder;
        self._lookupReplaced = false;
        self._queryParamDescription = queryParameterDescription;
        self._userSpecified = userSpecified;
        self._fieldPath = queryParameterDescription
                ? FieldPath.fromDescription(queryParameterDescription.getFieldPathDescription())
                : undefined;
    };
    AbcsLib.extend(SimpleCondition, Condition);

    SimpleCondition._LOGGER = Logger.get('SimpleCondition');
    SimpleCondition._UNKNOWN_OPERATOR = 'SimpleCondition.match() called with Operator that doesn\'t seem to be implemented yet. \n\
                                         Please file an issue with steps which you\'ve proceed, so it gets fixed correctly';

    /**
     * Checks whether the given recordData matches condition described by this {@link SimpleCondition}.
     *
     * @param {Map<String, String>} recordData - Map[key = PropertyID, value = Record value]
     * @returns {boolean}
     */
    SimpleCondition.prototype.match = function(recordData) {
        var self = this;
        var propertyID = self.getPropertyID();
        var propertyType = self.getProperty().getType();
        var value = recordData[propertyID];

        if (typeof value === 'object' && value !== null) {
            value = value.id;
        }

        var isEmpty = value === null || value === undefined || StringUtils.isEmpty(value);
        switch (self._operator) {
            case Operator.IS_EMPTY:
                return isEmpty;
            case Operator.IS_NOT_EMPTY:
                return !isEmpty;
            case Operator.EQUALS:
                // Special handling for cases where both values are null/undefined/empty
                var isThisEmpty = this._value === null || this._value === undefined || StringUtils.isEmpty(this._value);
                if (isThisEmpty && isEmpty) {
                    return true;
                }
                break;
            default:
                break;
        }

        switch (propertyType) {
            case PropertyType.DATE:
            case PropertyType.TIME:
            case PropertyType.DATETIME:
                return self._matchDates(value);
            case PropertyType.NUMBER:
            case PropertyType.CURRENCY:
            case PropertyType.PERCENTAGE:
                return self._matchNumbers(value);
            default:
                return self._matchStrings(value);
        }
    };

    SimpleCondition.prototype._matchDates = function(value) {
        var self = this;
        switch (self._operator) {
            case Operator.LESS:
                return value < this._value;
            case Operator.LESS_OR_EQUAL:
                return value <= this._value;
            case Operator.MORE:
                return value > this._value;
            case Operator.MORE_OR_EQUAL:
                return value >= this._value;
            default:
                SimpleCondition._LOGGER.error(SimpleCondition._UNKNOWN_OPERATOR);
                return true;
        }
    };

    SimpleCondition.prototype._matchNumbers = function(value) {
        var self = this;
        switch (self._operator) {
            case Operator.EQUALS:
                return value === this._value;
            case Operator.NOT_EQUALS:
                return value !== this._value;
            case Operator.LESS:
                return value < this._value;
            case Operator.LESS_OR_EQUAL:
                return value <= this._value;
            case Operator.MORE:
                return value > this._value;
            case Operator.MORE_OR_EQUAL:
                return value >= this._value;
            default:
                SimpleCondition._LOGGER.error(SimpleCondition._UNKNOWN_OPERATOR);
                return true;
        }
    };

    SimpleCondition.prototype._matchStrings = function(value) {
        var self = this;
        switch (self._operator) {
            case Operator.EQUALS:
                return StringUtils.equalsIgnoreCase(value, this._value);
            case Operator.NOT_EQUALS:
                return !StringUtils.equalsIgnoreCase(value, this._value);
            case Operator.STARTS_WITH:
                return StringUtils.startsWithIgnoreCase(value, this._value);
            case Operator.ENDS_WITH:
                return StringUtils.endsWithIgnoreCase(value, this._value);
            case Operator.CONTAINS:
                return StringUtils.containsIgnoreCase(value, this._value);
            default:
                SimpleCondition._LOGGER.error(SimpleCondition._UNKNOWN_OPERATOR);
                return true;
        }
    };

    /**
     * Gets the {@link module:operation/js/api/Operator Operator} assigned to this {@link bop/js/api/operation/SimpleCondition SimpleCondition}.
     *
     * @AbcsExtension stable
     * @version 17.1.1
     *
     * @returns {module:operation/js/api/Operator}
     */
    SimpleCondition.prototype.getOperator = function() {
        return this._operator;
    };

    SimpleCondition.prototype.hasValueExpression = function() {
        if (this._valueExpression && this._valueExpression.getValue()) {
            return true;
        }
        return false;
    };

    SimpleCondition.prototype.setValueExpression = function(valueExpression) {
        if (valueExpression) {
            valueExpression = SimpleCondition.createExpression(valueExpression);
        }
        this._valueExpression = valueExpression;
    };

    SimpleCondition.prototype.getValueExpression = function() {
        return this._valueExpression;
    };

    SimpleCondition.prototype.getValuePlaceholder = function() {
        return this._valuePlaceholder;
    };

    SimpleCondition.prototype.setValue = function(value) {
        this._value = value;
    };

    /**
     * Gets the value assigned to this {@link bop/js/api/operation/SimpleCondition SimpleCondition}.
     *
     * @AbcsExtension stable
     * @version 17.1.1
     *
     * @returns {String}
     */
    SimpleCondition.prototype.getValue = function() {
        return this._value;
    };

    SimpleCondition.prototype.setUserSpecified = function (userSpecified) {
        this._userSpecified = userSpecified;
    };

    SimpleCondition.prototype.isUserSpecified = function () {
        return this._userSpecified;
    };

    SimpleCondition.prototype.getType = function() {
        return this._type;
    };

    SimpleCondition.prototype.isLookupReplaced = function() {
        return this._lookupReplaced;
    };

    SimpleCondition.prototype.setLookupReplaced = function() {
        this._lookupReplaced = true;
    };

    /**
     * Gets the {@link entity/js/api/Property Property} assigned to this {@link bop/js/api/operation/SimpleCondition SimpleCondition}.
     *
     * @AbcsExtension stable
     * @version 17.1.1
     *
     * @returns {entity/js/api/Property}
     */
    SimpleCondition.prototype.getProperty = function() {
        return this._queryParamDescription.getProperty();
    };

    SimpleCondition.prototype.getFieldPath = function() {
        return this._fieldPath;
    };

    /**
     * Gets the custom information defined for the parameter descriptor assigned to this {@link bop/js/api/operation/SimpleCondition SimpleCondition}.
     *
     * @AbcsExtension stable
     * @version 17.1.1
     *
     * @returns {Object}
     *
     * @see {@link bop/js/api/operation/OperationInput#parameter OperationInput.parameter(..)} to understand where is additional info defined.
     */
    SimpleCondition.prototype.getAdditionalInfo = function() {
        return this._queryParamDescription.getAdditionalInfo();
    };

    SimpleCondition.prototype.getParameterType = function() {
        return this._queryParamDescription.getParameterType();
    };

    SimpleCondition.prototype.getPropertyID = function() {
        return this.getProperty().getId();
    };

    /**
     * Checks wheather this query parameter is required or not.
     * @returns {boolean}
     */
    SimpleCondition.prototype.isRequired = function() {
        return this._queryParamDescription.isRequired();
    };

    SimpleCondition.prototype.clone = function() {
        return new SimpleCondition(
            this._queryParamDescription,
            this._operator,
            this._value,
            this._valueExpression,
            this._type,
            this._valuePlaceholder,
            this._userSpecified,
            this._fieldPath
        );
    };

    SimpleCondition.prototype.getDefinition = function() {
        var res = {
            //name: this.getProperty().getId(),
            fieldPath: this._fieldPath && this._fieldPath.toJSON(),
            operator: this.getOperator(),
            value: this.getValue(),
            valueExpression: this._valueExpression && this._valueExpression.getDefinition(),
            valuePlaceholder: this.getValuePlaceholder(),
            type: this.getType()
        };
        var userSpec = this.isUserSpecified();
        if (AbcsLib.isDefined(userSpec)) {
            res.userSpecified = userSpec;
        }
        return res;
    };

    SimpleCondition.createFromDefinition = function(queryParamJSON, queryDescription) {
        var name;
        if (queryParamJSON.fieldPath) {
            var fp = FieldPath.createFromDefinition(queryParamJSON.fieldPath);
            name = fp.getId();
        } else if (queryParamJSON.name) {
            // Backward compatibility
            name = queryParamJSON.name;
        }
        var paramDesc = name ? queryDescription.getQueryParameter(name) : undefined;
        if (paramDesc) {
            return new SimpleCondition(
                paramDesc,
                queryParamJSON.operator,
                queryParamJSON.value,
                queryParamJSON.valueExpression && SimpleCondition.createExpression(queryParamJSON.valueExpression),
                QueryType.forValue(queryParamJSON.type),
                queryParamJSON.valuePlaceholder,
                queryParamJSON.userSpecified);
        }
    };

    SimpleCondition.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;
        }
        return new CompositeCondition(relationOperator, [this, condition]);
    };

    SimpleCondition.prototype.visit = function(conditionVisitor) {
        return conditionVisitor.visitSimpleCondition(this);
    };

    SimpleCondition.prototype.getSubConditions = function() {
        return [];
    };

    SimpleCondition.Expression = function (value, displayName) {
        AbcsLib.checkThis(this);
        this._value = value;
        this._displayName = displayName || value;
    };

    SimpleCondition.Expression.prototype.getValue = function () {
        return this._value || '';
    };

    SimpleCondition.Expression.prototype.getDisplayName = function () {
        return this._displayName || '';
    };

    SimpleCondition.Expression.prototype.getDefinition = function () {
        return {
            value: this.getValue(),
            displayName: this.getDisplayName()
        };
    };

    SimpleCondition.createExpression = function (value, displayName) {
        if (value && typeof value === 'object') {
            displayName = value.displayName || value._displayName;
            value = value.value || value._value;
        }
        return new SimpleCondition.Expression(value, displayName);
    };

    return SimpleCondition;
});