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

Source: entity/js/api/Property.js

define([
    'entity/js/api/PropertyClassification',
    'entity/js/api/PropertyType',
    'entity/js/spi/Attributed',
    'translations/js/api/I18n'
], function (
        PropertyClassification,
        PropertyType,
        Attributed,
        I18n
        ) {

    'use strict';

    /**
     * Represents a property of an Entity.
     *
     * @AbcsAPI stable
     * @version 15.4.5
     * @exports entity/js/api/Property
     *
     * @constructor
     * @private
     *
     * @param {Object} model object literal w/ following properties:
     * @param {String} model.id
     * @param {String} model.name
     * @param {entity/js/api/PropertyType} model.type
     * @param {entity/js/api/PropertyClassification} model.classification
     * @param {String} model.initialValue - initial value
     * @param {Boolean} model.required
     * @param {entity/js/api/Entity} entity - An instance of the owning {@link entity/js/api/Entity Entity}.
     * @param {Object} baseModel read only base model (optional)
     */
    var Property = function (model, entity, baseModel) {
        AbcsLib.checkThis(this);

        if (AbcsLib.isString(model)) {
            //the passed parameter is a string, which is interpreted as desired property ID
            //convert to the common notation...
            model = {
                id: model,
                classification: PropertyClassification.BASIC
            };
        }

        if (baseModel) {
            AbcsLib.checkDefined(baseModel.id, 'model.id');
        } else if (AbcsLib.isObject(model)) {
            AbcsLib.checkDefined(model.id, 'model.id');
        }

        if (!entity && model.entity) {
            // Support legacy code passing in entity as part of the model.
            entity = model.entity;
        }
        delete model.entity;

        Attributed.call(this, model, entity, baseModel);
    };

    AbcsLib.extend(Property, Attributed);

    Property._KEY_ID = 'id';
    Property._KEY_NAME = 'name';
    Property._KEY_TYPE = 'type';
    Property._KEY_REQUIRED = 'required';
    Property._KEY_UNIQUE = 'unique';
    Property._KEY_INITIAL_VALUE = 'initialValue';
    Property._KEY_CLASSIFICATION = 'classification';
    Property._KEY_FORMULA = 'formula';
    Property._KEY_AGGREGATION = 'aggregation';
    Property._KEY_VALIDATORS = 'validators';

    Property._ATTRIBUTE_KEY_DESCRIPTION = 'description';
    Property._ATTRIBUTE_KEY_SEARCHABLE = 'searchable';
    Property._ATTRIBUTE_KEY_SORTABLE = 'sortable';

    Property.I18N_SCOPE_PROPERTIES = 'properties';

    /**
     * @returns {Entity}
     */
    Property.prototype.getEntity = function () {
        return this.getParentObject();
    };

    /**
     * Gets a map with the translatable attribute info for Entity.
     * @override
     * @returns {Object} model key -> I18n key.
     */
    Property.prototype.getTranslatableKeys = function() {
        var map = {};
        map[Property._KEY_NAME]
                = I18n.key(I18n.Type.Entity, this.getEntity().getId(), Property.I18N_SCOPE_PROPERTIES, this.getId(), I18n.Suffix.Name);
        return map;
    };

    /**
     * Gets a map with the translatable attribute info for Entity.
     * @override
     * @returns {Object} model key -> I18n key.
     */
    Property.prototype.getTranslatableAttributes = function() {
        var map = {};
        map[Property._ATTRIBUTE_KEY_DESCRIPTION]
                = I18n.key(I18n.Type.Entity, this.getEntity().getId(), Property.I18N_SCOPE_PROPERTIES, this.getId(), I18n.Suffix.Description);
        return map;
    };

    /**
     * Returns ID of this property.
     *
     * @AbcsAPI stable
     * @version 15.4.5
     *
     * @returns {String}
     */
    Property.prototype.getId = function () {
        return this.getModelValue(Property._KEY_ID);
    };

    /**
     * Gets human readable singular name of this property, e.g. 'Address'
     *
     * @AbcsAPI stable
     * @version 15.4.5
     *
     * @returns {String}
     */
    Property.prototype.getSingularName = function () {
        return this.getModelValueAsString(Property._KEY_NAME);
    };

    /**
     * Gets human readable singular name of this property, e.g. 'Address'
     *
     * @deprecated use {@link #getSingularName} instead.
     * @returns {String}
     */
    Property.prototype.getName = Property.prototype.getSingularName;

    /**
     * Gets the human readable description for this property.
     * @returns {String} the property description
     */
    Property.prototype.getDescription = function() {
        return this.getAttributeAsString(Property._ATTRIBUTE_KEY_DESCRIPTION);
    };

    /**
     * Returns type of this property.
     *
     * @AbcsAPI stable
     * @version 15.4.5
     *
     * @returns {entity/js/api/PropertyType}
     */
    Property.prototype.getType = function () {
        return this.getModelValue(Property._KEY_TYPE);
    };

    /**
     * Is this property required?
     *
     * @returns {Boolean}
     */
    Property.prototype.isRequired = function () {
        // return boolean, defaulting to false if undefined or null
        return !!this.getModelValue(Property._KEY_REQUIRED);
    };

    /**
     * Is this property unique?
     *
     * @returns {Boolean}
     */
    Property.prototype.isUnique = function () {
        // return boolean, defaulting to false if undefined or null
        return !!this.getModelValue(Property._KEY_UNIQUE);
    };

    /**
     * Returns initial value of this property.
     *
     * @returns {String}
     */
    Property.prototype.getInitialValue = function () {
        return this.getModelValue(Property._KEY_INITIAL_VALUE);
    };

    /**
     * Returns classification of this property. If the model has no
     * classification value, this method returns BASIC.
     *
     * @returns {PropertyClassification}
     */
    Property.prototype.getClassification = function () {
        var res = this.getModelValue(Property._KEY_CLASSIFICATION);
        if (!res) {
            res = PropertyClassification.BASIC;
        }
        return res;
    };

    /**
     * Finds out if the property is a key or not.
     *
     * @returns {Boolean} true if the property is a key, false otherwise
     */
    Property.prototype.isKey = function () {
        return this.getType() === PropertyType.KEY;
    };

    /**
     * Finds out if the property is a reference or not.
     *
     * @returns {Boolean} true if the property is a reference, false otherwise
     */
    Property.prototype.isReference = function () {
        return this.getType() === PropertyType.REFERENCE;
    };

    /**
     * Checks if this property is sortable or not.
     *
     * @returns {Boolean}
     */
    Property.prototype.isSortable = function () {
        return this.getAttribute(Property._ATTRIBUTE_KEY_SORTABLE, !this.isReference());
    };

    /**
     * Checks if this property is searchable or not.
     *
     * <p>
     * The difference between 'searchable' and 'filterable' is that some properties are allowed to be
     * searched, but doesn't make sense in the context of basic filter working over that single field.
     * </p>
     *
     * <p>
     * Example could be DateTime property which would be hard to use for basic filtering (it would be
     * pretty hard to set exact date-time value into basic filter field). But on the other hand, it could
     * be easily used as part of default query where one wants to see all records with date-time later
     * than included value.
     * </p>
     *
     * @returns {Boolean}
     */
    Property.prototype.isSearchable = function () {
        return this.getAttribute('searchable', true);
    };

    /**
     * Checks if this property is filerable or not.
     *
     * @returns {Boolean}
     */
    Property.prototype.isFilterable = function () {
        switch (this.getType()) {
            case PropertyType.BOOLEAN:
            case PropertyType.DATETIME:
            case PropertyType.TIME:
            case PropertyType.ATTACHMENT:
                return false;
            default:
                return true;
        }
    };

    /**
     * Returns formula to calculate value of this property.
     *
     * @returns {String} a snippet of JavaScript code
     */
    Property.prototype.getFormula = function () {
        return this.getModelValue(Property._KEY_FORMULA);
    };

    /**
     * Gets the declarative aggregation information used to calculate the value
     * of this property from related Entities.
     *
     * <p>
     * The returned object has the following properties:
     * <ul><li>aggregationFunction - AVG, COUNT, MIN, MAX or SUM</li>
     * <li>aggregationPath - an array of objects which each represent a releation
     * and therefore have an entityId and mappingPropertyId</li>
     * <li>aggregatedPropertyId - the id of the property being aggregated</li></ul>
     * </p>
     * <p>
     * Example aggregation object for averaging the "salary" property of child
     * entity "employee": {
     *   aggregationFunction: 'AVG',
     *   aggregationPath: [{entityId: 'employee', mappingPropertyId: 'ref2departments'}],
     *   aggregatedPropertyId: 'salary'
     * }
     * </p>
     * @returns {Object} the declarative aggregate forumla
     */
    Property.prototype.getAggregation = function () {
        // Until there is a child object representing aggregation (which can
        // fire change events) return a clone to force modifiers to call
        // setAggregation.
        return AbcsLib.clone(this.getModelValue(Property._KEY_AGGREGATION));
    };

    /**
     * Return the array of validators assigned to the property
     * @returns {Array} array of validators parameters/descriptors
     */
    Property.prototype.getValidators = function () {
        // Until there is a child object representing a validator (which can
        // fire change events) return a clone to force modifiers to call
        // setValidators.
        return AbcsLib.clone(this.getModelValue(Property._KEY_VALIDATORS));
    };

    return Property;
});