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

Source: bop/js/spi/SimpleBOP.js

define([], function () {

    'use strict';

    /**
     * SPI object for creating simplified {@link bop/js/spi/BOP BOP} implementations.
     *
     * <p>
     * By implementing {@link bop/js/spi/SimpleBOP SimpleBOP}, you're choosing more restricted SPI which on the other don't require that much effort to be written properly.
     * If you're looking for pure, fully-customizable BOP with no restrictions write your own {@link extensions.dt/js/spi/ExtensionManager ExtensionManager} and use {@link bop/js/spi/BOP BOP}
     * interface with {@link bop/js/api/BOPRegistry BOPRegistry} API object to register it into Application Builder data model.
     * </p>
     *
     * <p>
     * Obviously both options ({@link bop/js/spi/SimpleBOP SimpleBOP} and {@link bop/js/spi/BOP BOP}) has some pros and cons. Here is short list:<br/><br/>
     *
     * {@link bop/js/spi/SimpleBOP SimpleBOP} - Pros:
     * <ul>
     *  <li>
     *      No need to take care of {@link extensions.dt/js/spi/ExtensionManager ExtensionManager} lifecycle manually.
     *  </li>
     *  <li>
     *      No need to write method generating RT code manually.
     *  </li>
     *  <li>
     *      No need to manually define {@link bop/js/spi/BOP BOP}s ID as it's taken automatically based on the extension ID.
     *  </li>
     *  <li>
     *      No need to take care of {@link bop.dt/js/spi/BOPExtensionManager~BOPExtensionDependencyFormat BOPExtensionDependencyFormat} to register only selected
     *      {@link entity/js/api/Entity Entities} and {@link entity/js/api/Property Properties} into the Application Builder data model.
     *  </li>
     * </ul>
     *
     * {@link bop/js/spi/SimpleBOP SimpleBOP} - Cons:
     * <ul>
     *  <li>
     *      You can't apply {@link extensions.dt/js/api/CustomParameter CustomParameter}s as you're out of control over the {@link extensions.dt/js/spi/ExtensionManager ExtensionManager}
     *      lifecycle and thus you can't process them anyhow.
     *  </li>
     *  <li>
     *      Generally, you're restricted only to the simplied expectations and you can't define more custom behavior.
     *  </li>
     * </ul>
     *
     * {@link bop/js/spi/BOP BOP} - Pros & Cons:
     * <ul>
     *  <li>
     *      Opposite of Pros & Cons from {@link bop/js/spi/SimpleBOP SimpleBOP}.
     *  </li>
     * </ul>
     * </p>
     *
     * @AbcsExtension stable
     * @version 17.1.1
     * @exports bop/js/spi/SimpleBOP
     *
     * @constructor
     * @private
     *
     * @see {@link bop/js/spi/BOP BOP}
     * @see {@link bop/js/spi/entity/EntityProvider EntityProvider}
     * @see {@link bop/js/spi/operation/OperationProvider OperationProvider}
     * @see {@link bop.dt/js/api/SimpleBOPExtensionManager SimpleBOPExtensionManager}
     * @see {@link extensions.dt/js/spi/ExtensionManager ExtensionManager}
     *
     * @example
     * <caption>
     *  Example of typical implementation of custom {@link bop/js/spi/SimpleBOP SimpleBOP} with paths to your hand-written {@link bop/js/spi/entity/EntityProvider EntityProvider} and {@link bop/js/spi/operation/OperationProvider OperationProvider}.
     * </caption>
     *
     * define([], function () {
     *
     *     var CustomBOP = function () {
     *     };
     *
     *     CustomBOP.prototype.getEntityProviderPath = function () {
     *         return '{{package}}/js/CustomEntityProvider';
     *     };
     *
     *     CustomBOP.prototype.getOperationProviderPath = function () {
     *         return '{{package}}/js/CustomOperationProvider';
     *     };
     *
     *     return CustomBOP;
     * });
     */
    var SimpleBOP = function () {
        AbcsLib.checkThis(this);
    };

    /**
     * Gets relative path to the corresponding {@link bop/js/spi/entity/EntityProvider EntityProvider}.
     *
     * <p>
     * Returned string can contain special <code>{{package}}</code> identifier which will be automatically transformed into the path that correspond to your extension top-level package.
     * </p>
     *
     * @AbcsExtension stable
     * @version 17.1.1
     *
     * @returns {String}
     *
     * @example
     * <caption>
     *  Typical implementation returning path to your hand-written {@link bop/js/spi/entity/EntityProvider EntityProvider}.
     * </caption>
     *
     * CustomBOP.prototype.getEntityProviderPath = function () {
     *     return '{{package}}/js/CustomEntityProvider';
     * };
     *
     * @example
     * <caption>
     *  Example of typical implementation of custom {@link bop/js/spi/entity/EntityProvider EntityProvider} which is used inside {@link bop/js/spi/SimpleBOP SimpleBOP}.
     * </caption>
     *
     * define([
     *     'bop/js/api/entity/DataModelFactory',
     *     'entity/js/api/PropertyType'
     * ], function (
     *     DataModelFactory,
     *     PropertyType
     * ) {
     *
     *     var CustomEntityProvider = function () {
     *         var firstname = DataModelFactory.createProperty({
     *             id: 'my.custom.bop.Employee.Firstname',
     *             name: 'Firstname',
     *             type: PropertyType.TEXT
     *         });
     *         var lastname = DataModelFactory.createProperty({
     *             id: 'my.custom.bop.Employee.Lastname',
     *             name: 'Lastname',
     *             type: PropertyType.TEXT
     *         });
     *         var age = DataModelFactory.createProperty({
     *             id: 'my.custom.bop.Employee.Age',
     *             name: 'Age',
     *             type: PropertyType.NUMBER
     *         });
     *         var employee = DataModelFactory.createEntity({
     *             id: 'my.custom.bop.Employee',
     *             singularName: 'Employee',
     *             pluralName: 'Employees',
     *             properties: [firstname, lastname, age]
     *         });
     *
     *         this._entities = [employee];
     *     };
     *
     *     CustomEntityProvider.prototype.getEntities = function() {
     *         return this._entities;
     *     };
     *
     *     return CustomEntityProvider;
     * });
     */
    SimpleBOP.prototype.getEntityProviderPath = function () {
        AbcsLib.throwMustBeOverriddenError();
    };

    /**
     * Gets relative path to the corresponding {@link bop/js/spi/operation/OperationProvider OperationProvider}.
     *
     * <p>
     * Returned string can contain special <code>{{package}}</code> identifier which will be automatically transformed into the path that correspond to your extension top-level package.
     * </p>
     *
     * <p>
     * The constructor will be passed an representation of the dependencies that can be used to access
     * configuration parameters and configure {@link bop/js/spi/operation/BOPAuthenticator BOPAuthenticator}
     * </p>
     *
     * @AbcsExtension stable
     * @version 17.1.1
     *
     * @returns {String}
     *
     * @example
     * <caption>
     *  Typical implementation returning path to your hand-written {@link bop/js/spi/operation/OperationProvider OperationProvider}.
     * </caption>
     *
     * CustomBOP.prototype.getOperationProviderPath = function () {
     *     return '{{package}}/js/CustomOperationProvider';
     * };
     *
     * @example
     * <caption>
     *  Example of typical implementation of custom {@link bop/js/spi/operation/OperationProvider OperationProvider} used inside of the custom {@link bop/js/spi/SimpleBOP SimpleBOP}.
     * </caption>
     *
     * define([
     *     'bop/js/api/operation/OperationBuilder',
     *     'bop/js/api/operation/OperationInput',
     *     'bop/js/api/operation/OperationOutput',
     *     'operation/js/api/Operation',
     *     'operation/js/api/Operator',
     *     '{{package}}/js/Employee'
     * ], function (
     *     OperationBuilder,
     *     OperationInput,
     *     OperationOutput,
     *     Operation,
     *     Operator,
     *     Employee
     * ) {
     *
     *     var CustomOperationProvider = function () {
     *         this._operations = [];
     *
     *         var employee = Abcs.Entities().findById('my.custom.bop.Employee');
     *         var id = employee.getProperty('my.custom.bop.Employee.ID');
     *         var firstname = employee.getProperty('my.custom.bop.Employee.Firstname');
     *         var lastname = employee.getProperty('my.custom.bop.Employee.Lastname');
     *         var age = employee.getProperty('my.custom.bop.Employee.Age');
     *
     *         var partialOutput = new OperationOutput({
     *             entity: employee
     *         }).property(firstname).
     *             property(lastname);
     *
     *         var idInput = new OperationInput({
     *             entity: employee
     *         }).parameter({
     *             property: id,
     *             required: true
     *         });
     *
     *         var firstnameLastnameInput = new OperationInput({
     *             entity: employee
     *         }).parameter(firstname).
     *             parameter(lastname).
     *             operators([
     *                 Operator.EQUALS,
     *                 Operator.NOT_EQUALS,
     *                 Operator.STARTS_WITH,
     *                 Operator.ENDS_WITH,
     *                 Operator.CONTAINS,
     *                 Operator.NOT_CONTAINS
     *             ]);
     *
     *         var getAllEmployees = new OperationBuilder({
     *             name: 'Find all Employees',
     *             type: Operation.Type.READ_MANY,
     *             performs: function() {
     *                 // Lets assume there is an Employee object as part of our BOP extension implementation which builds the URL based
     *                 // on the "operationInputData" values, makes the real REST call and returns relevant OperationResult instance
     *                 return Promise.resolve(Employee.getAll());
     *             }
     *         }).description('Longer description of what this Operation does').
     *             returns(partialOutput).
     *             takes(firstnameLastnameInput).
     *             build();
     *
     *         var getEmployeeByID = new OperationBuilder({
     *             name: 'Find Employee by ID',
     *             type: Operation.Type.READ_ONE,
     *             performs: function(operationInputData) {
     *                 // Lets assume there is an Employee object as part of our BOP extension implementation which builds the URL based
     *                 // on the "operationInputData" values, makes the real REST call and returns relevant OperationResult instance
     *                 return Promise.resolve(Employee.findByID(operationInputData));
     *             }
     *         }).specialType(Operation.SpecialType.QUERY_BY_ID).
     *             takes(idInput).
     *             returns(employee).
     *             build();
     *
     *         // Register all relevant operations
     *         this._operations.push(getAllEmployees);
     *         this._operations.push(getEmployeeByID);
     *
     *         // ..include the same for all other REST calls
     *     };
     *
     *     CustomOperationProvider.prototype.getOperations = function() {
     *         return this._operations;
     *     };
     *
     *     return CustomOperationProvider;
     * });
     */
    SimpleBOP.prototype.getOperationProviderPath = function () {
        AbcsLib.throwMustBeOverriddenError();
    };

    return SimpleBOP;
});