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

Source: operation/js/api/ExpandableReference.js

/* eslint-disable no-use-before-define */

define([
    'entity/js/api/Entity',
    'entity/js/api/Property'
], function(
        Entity,
        Property
    ) {

    'use strict';

    /**
     * An API object representing expandable reference of an {@link entity/js/api/Entity Entity}.
     *
     * <p>
     * <code>ExpandableReference</code> gives client of {@link module:api/js/Operations.read Operations.read(..)} an opportunity to automatically expand some of the references from the fetched
     * {@link entity/js/api/Entity Entity}.
     * </p>
     *
     * @AbcsAPI stable
     * @version 17.1.3
     * @exports operation/js/api/ExpandableReference
     *
     * @constructor
     * @private
     *
     * @param {operation/js/api/ExpandableReference[]} childExpandables
     *
     * @see {@link operation/js/api/ExpandableReference.create ExpandableReference.create(..)} to see how to create instances of <code>ExpandableReference</code>s
     * @see {@link module:api/js/Operations.read Operations.read(..)} to see where and how to use <code>ExpandableReference</code>
     */
    var ExpandableReference = function(childExpandables) {
        this._childExpandables = childExpandables;
    };

    /**
     * Creates an instance of <code>ExpandableReference</code> that could be passed into {@link module:api/js/Operations.read Operations.read(..)} so that except for main data, it fetch
     * also embeded reference {@link entity/js/api/Entity Entity} record (otherwise there would be just the reference ID).
     *
     * You have two options how to create an instance of <code>ExpandableReference</code>:
     * <ul>
     *  <li>
     *      Pass an instance of {@link entity/js/api/Entity Entity} in which case all references between the main and the given {@link entity/js/api/Entity Entity} will be expanded.
     *  </li>
     *  <li>
     *      Pass an instance of {@link entity/js/api/Property Property} which represents one particular mapping property between two entities.
     *  </li>
     * </ul>
     *
     * @AbcsAPI stable
     * @version 17.1.3
     *
     * @param {entity/js/api/Entity | entity/js/api/Property} value - Either an {@link entity/js/api/Entity Entity} that should be embedded or exact mapping {@link entity/js/api/Property Property} that refers to the {@link entity/js/api/Entity Entity} that should be embedded.
     * @param {Object} [optionalParams] - Object literal with following possible parameters.
     * @param {operation/js/api/ExpandableReference | operation/js/api/ExpandableReference[]} [optionalParams.expand] - Either a single instance of {@link operation/js/api/ExpandableReference ExpandableReference} or an array of {@link operation/js/api/ExpandableReference ExpandableReference}s for deeper children expansion.
     *
     * @returns {operation/js/api/ExpandableReference}
     *
     * @see {@link module:api/js/Operations.read Operations.read(..)} to see where and how to use <code>ExpandableReference</code>
     *
     * @example
     * <caption>
     *  Creates an expandable reference that will expand all relations between Employee and Department entities.
     * </caption>
     *
     * require([
     *     'operation/js/api/ExpandableReference'
     * ], function(
     *         ExpandableReference
     * ) {
     *     var department = Abcs.Entities().findById('my.custom.bop.Department');
     *     var departmentRef = ExpandableReference.create(department);
     * });
     *
     * @example
     * <caption>
     *  Creates an expandable reference for just the specific mapping property.
     * </caption>
     *
     * require([
     *     'operation/js/api/ExpandableReference'
     * ], function(
     *         ExpandableReference
     * ) {
     *     var employee = Abcs.Entities().findById('my.custom.bop.Employee');
     *     var ref2Department = employee.getProperty('ref2Department');
     *     var emp2DeptRef = ExpandableReference.create(ref2Department);
     * });
     *
     * @example
     * <caption>
     *  Creates an <code>ExpandableReference</code> object to get an Employee data together with an embedded Department record that recursively contains embedded DepartmentType record.
     * </caption>
     *
     * require([
     *     'operation/js/api/ExpandableReference'
     * ], function(
     *         ExpandableReference
     * ) {
     *     var employee = Abcs.Entities().findById('my.custom.bop.Employee');
     *     var department = Abcs.Entities().findById('my.custom.bop.Department');
     *     var departmentType = Abcs.Entities().findById('my.custom.bop.DepartmentType');
     *
     *     var expandableReference = ExpandableReference.create(department, {
     *         expand: ExpandableReference.create(departmentType)
     *     });
     * });
     */
    ExpandableReference.create = function (value, optionalParams) {
        AbcsLib.checkParameterCount(arguments, 1, 1);
        AbcsLib.checkDataType(value, [Entity, Property]);

        var childExpandables = optionalParams ? optionalParams.expand : undefined;
        if (optionalParams || AbcsLib.isDefined(optionalParams)) {
            AbcsLib.checkDataType(optionalParams, AbcsLib.Type.OBJECT);
            AbcsLib.checkObjectLiteral(optionalParams, ['expand']);

            if (childExpandables || AbcsLib.isDefined(childExpandables)) {
                AbcsLib.checkDataType(childExpandables, [ExpandableReference, AbcsLib.Type.ARRAY]);

                if (AbcsLib.isArray(childExpandables)) {
                    // If this is an array of expandable references, check typ of each of the given items
                    for (var i = 0; i < childExpandables.length; i++) {
                        AbcsLib.checkDataType(childExpandables[i], ExpandableReference);
                    }
                } else {
                    // Otherwise turn the single instance into an array with one item to to simplify processing
                    childExpandables = [childExpandables];
                }
            }
        }

        if (value instanceof Entity) {
            return new ExpandableEntity(value, childExpandables);
        } else if (value instanceof Property) {
            return new ExpandableProperty(value, childExpandables);
        } else {
            throw new Error('ExpandableReference should never be created using different Object than either Entity or Property. The given Object is: ' + JSON.stringify(value));
        }
    };

    /**
     * Gets an array of {@link entity/js/api/Relation Relation}s associated with this <code>ExpandableReference</code> instance.
     *
     * <p>
     * Return value depends on how this <code>ExpandableReference</code> was constructed:
     *
     * <ul>
     *  <li>
     *      If using an instance of {@link entity/js/api/Property Property} representing one particular mapping property, {@link entity/js/api/Relation Relation} associated with that mapping property will be returned.
     *  </li>
     *  <li>
     *      If using an instance of {@link entity/js/api/Entity Entity}, all {@link entity/js/api/Relation Relation}s between the main and the given {@link entity/js/api/Entity Entity} will be returned.
     *  </li>
     * </ul>
     * </p>
     *
     * @param {entity/js/api/Entity} entity - The main BO for which this <code>ExpandableReference</code> instance were created.
     * @returns {entity/js/api/Relation[]}
     */
    ExpandableReference.prototype.getRelations = function(entity) { // eslint-disable-line no-unused-vars
    };

    /**
     * Gets an array of {@link operation/js/api/ExpandableReference ExpandableReference}s for all requested child expansions of this one.
     *
     * @returns {operation/js/api/ExpandableReference[]}
     */
    ExpandableReference.prototype.getChildExpandables = function() {
        return this._childExpandables;
    };

    var ExpandableProperty = function(mappingProperty, childExpandables) {
        ExpandableReference.apply(this, [childExpandables]);

        this._mappingProperty = mappingProperty;
    };
    AbcsLib.extend(ExpandableProperty, ExpandableReference);

    ExpandableProperty.prototype.getRelations = function(entity) {
        return [entity.getRelation(this._mappingProperty)];
    };

    var ExpandableEntity = function(embeddedEntity, childExpandables) {
        ExpandableReference.apply(this, [childExpandables]);

        this._embeddedEntity = embeddedEntity;
    };
    AbcsLib.extend(ExpandableEntity, ExpandableReference);

    ExpandableEntity.prototype.getRelations = function(entity) {
        return entity.getRelationsForEntity(this._embeddedEntity);
    };

    return ExpandableReference;
});