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

Source: operation/js/api/Sorting.js

define([
    'entity/js/api/Property',
    'entity/js/api/PropertyType',
    'operation/js/api/FieldPath'
], function(
        Property,
        PropertyType,
        FieldPath
    ) {

    'use strict';

    /**
     * An API object providing methods to create sorting rule which can be applied within the custom code.
     *
     * @AbcsAPI stable
     * @version 17.1.1
     * @exports operation/js/api/Sorting
     *
     * @constructor
     * @private
     *
     * @see {@link module:api/js/Operations.read Abcs.Operations().read(..)} to use <code>Sorting</code> from Application Builder custom code.
     *
     * @param {Sorting.Criterion[]} sortingCriteria
     */
    var Sorting = function(sortingCriteria) {
        AbcsLib.checkThis(this);

        this._sortingCriteria = sortingCriteria ? sortingCriteria : [];
    };

    /**
     * Creates an instance of <code>Sorting</code> in ascending order.
     *
     * @AbcsAPI stable
     * @version 17.1.1
     * @public
     * @static
     *
     * @param {entity/js/api/Property} property - {@link entity/js/api/Property Property} used for sorting.
     * @returns {operation/js/api/Sorting}
     *
     * @see {@link module:api/js/Operations.read Abcs.Operations().read(..)} to use <code>Sorting</code> from Application Builder custom code.
     *
     * @example
     * <caption>
     *  Create an instance of {@link operation/js/api/Sorting Sorting} for the given {@link entity/js/api/Property Property} in ascending order.
     * </caption>
     *
     * var employee = Abcs.Entities().findById('my.custom.bop.Employee');
     * var firstname = employee.getProperty('firstname');
     * var sorting = Sorting.ascending(firstname);
     */
    Sorting.ascending = function(property) {
        AbcsLib.checkDefined(property, 'property');
        AbcsLib.checkParameterCount(arguments, 1);

        var entity = property.getEntity();
        var sortingCriteria = new Sorting.Criterion(entity, property, false);

        return new Sorting([sortingCriteria]);
    };

    /**
     * Creates an instance of <code>Sorting</code> in descending order.
     *
     * @AbcsAPI stable
     * @version 17.1.1
     * @public
     * @static
     *
     * @param {entity/js/api/Property} property - {@link entity/js/api/Property Property} used for sorting.
     * @returns {operation/js/api/Sorting}
     *
     * @see {@link module:api/js/Operations.read Abcs.Operations().read(..)} to use <code>Sorting</code> from Application Builder custom code.
     *
     * @example
     * <caption>
     *  Create an instance of {@link operation/js/api/Sorting Sorting} for the given {@link entity/js/api/Property Property} in descending order.
     * </caption>
     *
     * var employee = Abcs.Entities().findById('my.custom.bop.Employee');
     * var fistname = employee.getProperty('firstname');
     * var sorting = Sorting.descending(firstname);
     */
    Sorting.descending = function(property) {
        AbcsLib.checkDefined(property, 'property');
        AbcsLib.checkParameterCount(arguments, 1);

        var entity = property.getEntity();
        var sortingCriteria = new Sorting.Criterion(entity, property, true);

        return new Sorting([sortingCriteria]);
    };

    /**
     * Gets an array of {@link operation/js/api/Sorting.Criterion Sorting.Criterion} assigned to this <code>Sorting</code>.
     *
     * @AbcsExtension stable
     * @version 17.1.1
     *
     * @returns {operation/js/api/Sorting.Criterion[]}
     */
    Sorting.prototype.getSortingCriteria = function() {
        return this._sortingCriteria;
    };

    /**
     * StaticViewModelGenerator calls JSON.stringify on ArchetypeConfiguration
     * which may contain instance of Sorting. Hence toJSON below is needed.
     */
    Sorting.prototype.toJSON = function() {
        return this.getDefinition();
    };

    Sorting.prototype.getDefinition = function() {
        var self = this;
        var result = [];

        self._sortingCriteria.forEach(function(sortingProperty) {
            result.push(sortingProperty.getDefinition());
        });
        return result;
    };

    Sorting.createFromDefinition = function(sortingJSON) {
        var sortingCriteria = [];
        for (var i = 0; i < sortingJSON.length; i++) {
            var sortingPropertyJSON = sortingJSON[i];
            sortingCriteria.push(Sorting.Criterion.createFromDefinition(sortingPropertyJSON));
        }
        return new Sorting(sortingCriteria);
    };

    /**
     * Represents single {@link operation/js/api/Sorting Sorting} criterion.
     *
     * <p>
     * Single criterion consist of assigned {@link entity/js/api/Property Property} and the order in which the result needs to be sorted (ascending/descending).
     * </p>
     *
     * <p>
     * In the future, Application Builder is going to support multiple criteria.
     * </p>
     *
     * @AbcsExtension stable
     * @version 17.1.1
     * @constructor
     * @private
     *
     * @param {entity/js/api/Entity} entity
     * @param {entity/js/api/Property} property
     * @param {boolean} descending - Flag whether this criterion is descending or ascending
     */
    Sorting.Criterion = function(entity, property, descending) {
        AbcsLib.checkThis(this);

        this.entity = entity;
        if (property && !(property instanceof FieldPath)) {
            AbcsLib.checkDataType(property, Property);
            var prop = property;
            var rels = [];
            // BUFP-10262 Auto add default display name in Field pickers, pending tree implementation
            // For backward compatibility, if a REFERENCE Property is provided,
            // replace this with the Relation and default displayProperty of the
            // referenced BO
            if (property.getType() === PropertyType.REFERENCE) {
                var rel = property.getEntity().getRelation(property);
                if (rel) {
                    var target = rel.getTargetEntity();
                    var dispPropId = rel.getDefaultDisplayProperty();
                    var dispProp = (dispPropId && target && target.isInternal()) ? target.getProperty(dispPropId) : undefined;
                    if (dispProp && !dispProp.getFormula() && dispProp.getType !== PropertyType.REFERENCE) {
                        rels.push(rel);
                        prop = dispProp;
                    }
                }
            }
            this.fieldPath = new FieldPath(prop, rels);
        } else {
            this.fieldPath = property;
        }
        this.descending = descending ? true : false;
    };

    /**
     * Gets the {@link entity/js/api/Property Property} assigned to this criterion.
     *
     * @AbcsExtension stable
     * @version 17.1.1
     * @memberof operation/js/api/Sorting.Criterion
     *
     * @returns {entity/js/api/Property}
     */
    Sorting.Criterion.prototype.getProperty = function() {
        if (this.fieldPath) {
            return this.fieldPath.getProperty();
        }
    };

    Sorting.Criterion.prototype.getPropertyId = function() {
        if (this.fieldPath) {
            return this.fieldPath.getId();
        }
    };

    /**
     * Gets the FieldPath of this criterion.
     *
     * @returns {operation/js/api/FieldPath}
     */
    Sorting.Criterion.prototype.getFieldPath = function() {
        return this.fieldPath;
    };

    /**
     * Checks whether this <code>Sorting.Criterion</code> is ascending.
     *
     * @AbcsExtension stable
     * @version 17.1.1
     * @memberof operation/js/api/Sorting.Criterion
     *
     * @returns {Boolean} - <code>true</code> if this is ascending criterion, <code>false</code> otherwise
     */
    Sorting.Criterion.prototype.isAscending = function() {
        return !this.descending;
    };

    /**
     * Checks whether this <code>Sorting.Criterion</code> is descending.
     *
     * @AbcsExtension stable
     * @version 17.1.1
     * @memberof operation/js/api/Sorting.Criterion
     *
     * @returns {Boolean} - <code>true</code> if this is descending criterion, <code>false</code> otherwise
     */
    Sorting.Criterion.prototype.isDescending = function() {
        return this.descending;
    };

    /**
     * StaticViewModelGenerator calls JSON.stringify on ArchetypeConfiguration
     * which may contain instance of SortingProperty. Hence toJSON below is needed.
     */
    Sorting.Criterion.prototype.toJSON = function () {
        return this.getDefinition();
    };

    Sorting.Criterion.prototype.getDefinition = function() {
        return {
            descending: this.isDescending(),
            fieldPath: this.fieldPath && this.fieldPath.toJSON()
        };
    };

    Sorting.Criterion.createFromDefinition = function(sortingPropertyJSON) {
        var descending = sortingPropertyJSON.descending;
        var fieldPath = FieldPath.createFromDefinition(sortingPropertyJSON.fieldPath);
        var entity;
        if (fieldPath) {
            entity = fieldPath ? fieldPath.getEntity() : undefined;
        } else {
            // Backward compatibility
            entity = Abcs.Entities().findById(sortingPropertyJSON.entityID);
            var property = entity.getProperty(sortingPropertyJSON.propertyID);
            fieldPath = new FieldPath(property);
        }
        return new Sorting.Criterion(entity, fieldPath, descending);
    };

    return Sorting;
});