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

Source: bop.dt/js/api/SimpleBOPExtensionManager.js

define([
    'module',
    'bop/js/BOPSelectionInterceptor',
    'bop/js/api/BOPInterceptors',
    'bop/js/api/BOPRegistry',
    'core/js/api/utils/StringUtils',
    'extensions.dt/js/api/ExtensionOperations',
    'text!bop/templates/BOPInitializer.js'
], function (
        module,
        BOPSelectionInterceptor,
        BOPInterceptors,
        BOPRegistry,
        StringUtils,
        ExtensionOperations,
        BOPInitializerTemplate
    ) {

    'use strict';

    /**
     * Wraps an instance of {@link bop/js/spi/SimpleBOP SimpleBOP} as an implementation of {@link extensions.dt/js/spi/ExtensionManager ExtensionManager}.
     *
     * <p>
     * It takes care of few aspects that you would have to do manually otherwise (resp. if implemented as pure {@link bop/js/spi/BOP BOP}). In summary:
     *
     * <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 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>
     * </p>
     *
     * @AbcsExtension stable
     * @version 17.1.1
     * @exports bop.dt/js/api/SimpleBOPExtensionManager
     *
     * @constructor
     * @public
     *
     * @see {@link bop/js/spi/SimpleBOP SimpleBOP}
     * @see {@link extensions.dt/js/spi/ExtensionManager ExtensionManager}
     *
     * @param {bop/js/spi/SimpleBOP} simpleBOP
     *
     * @example
     * <caption>
     *  Typical implementation creating <code>SimpleBOPExtensionManager<code> and passing custom {@link bop/js/spi/SimpleBOP SimpleBOP} into it.
     * </caption>
     *
     * define([
     *     'bop.dt/js/api/SimpleBOPExtensionManager'
     * ], function (
     *         SimpleBOPExtensionManager
     *     ) {
     *
     *     var CustomBOP = function () {
     *     };
     *
     *     CustomBOP.prototype.getEntityProviderPath = function () {
     *         return '{{package}}/js/CustomEntityProvider';
     *     };
     *
     *     CustomBOP.prototype.getOperationProviderPath = function () {
     *         return '{{package}}/js/CustomOperationProvider';
     *     };
     *
     *     return new SimpleBOPExtensionManager(new CustomBOP());
     * });
     */
    var SimpleBOPExtensionManager = function (simpleBOP) {
        AbcsLib.checkThis(this);

        this._simpleBOP = simpleBOP;
    };

    SimpleBOPExtensionManager._LOGGER = Logger.get(module.id);

    SimpleBOPExtensionManager.prototype.initialise = function (dependencies) {
        var self = this;
        return new Promise(function (fulfil, reject) {
            var entityProviderPath = self._getEntityProviderPath();
            var operationProviderPath = self._getOperationProviderPath();
            var shareable = ExtensionOperations._findShareableForEM(self);

            require([
                entityProviderPath,
                operationProviderPath
            ], function (
                    EntityProviderImpl,
                    OperationProviderImpl
            ) {
                var BOPImpl = function() {
                    this._entityProvider = undefined;
                    this._operationProvider = undefined;
                };

                BOPImpl.prototype.getEntityProvider = function() {
                    try {
                        if (!this._entityProvider) {
                            this._entityProvider = new EntityProviderImpl();
                        }
                    } catch (error) {
                        SimpleBOPExtensionManager._LOGGER.error('Couldn\'t initialize EntityProvider with path: "' + entityProviderPath + '".');
                        if (error) {
                            SimpleBOPExtensionManager._LOGGER.error(error.stack ? error.stack : error);
                        }
                    }
                    return this._entityProvider;
                };

                BOPImpl.prototype.getOperationProvider = function() {
                    try {
                        if (!this._operationProvider) {
                            this._operationProvider = new OperationProviderImpl(dependencies);
                        }
                    } catch (error) {
                        SimpleBOPExtensionManager._LOGGER.error('Couldn\'t initialize OperationProvider with path: "' + operationProviderPath + '"');
                        if (error) {
                            SimpleBOPExtensionManager._LOGGER.error(error.stack ? error.stack : error);
                        }
                    }
                    return this._operationProvider;
                };

                BOPImpl.prototype.getId = function() {
                    return shareable.getId();
                };

                self._bop = new BOPImpl();

                var selectionInterceptor = new BOPSelectionInterceptor(dependencies);
                BOPInterceptors.addInterceptor(selectionInterceptor);
                try {
                    BOPRegistry.register(self._bop, self).then(function() {
                        SimpleBOPExtensionManager._LOGGER.info('SimpleBOP initialised');
                        BOPInterceptors.removeInterceptor(selectionInterceptor);

                        fulfil();
                    }).catch(function(error) {
                        SimpleBOPExtensionManager._LOGGER.warn('SimpleBOP NOT properly initialised.');
                        BOPInterceptors.removeInterceptor(selectionInterceptor);

                        reject(error);
                    });
                } catch (exception) {
                    reject(exception);
                }
            }, function(error) {
                var unloadedModules = error.requireModules;
                if (unloadedModules) {
                    reject(new Error(AbcsLib.i18n('bopDt.unloadedModules', {
                        unloadedModules: unloadedModules
                    })));
                } else {
                    reject(error);
                }
            });
        });
    };

    SimpleBOPExtensionManager.prototype.destroy = function () {
        var self = this;
        return BOPRegistry.deregister(self._bop, self).then(function() {
            self._bop = undefined;
        });
    };

    SimpleBOPExtensionManager.prototype.generateRuntimeCode = function(dependencies, extension) {
        var self = this;
        var map = {
            entityProviderPath: self._getEntityProviderPath(),
            operationProviderPath: self._getOperationProviderPath(),
            shareableID: extension.getId(),
            dependencies : AbcsLib.stringify(dependencies.map(function(dependency) {
                        return dependency.getDefinition();
                    }))
        };
        return StringUtils.resolveTemplate(BOPInitializerTemplate, map, ['$', '$']);
    };

    /**
     * If the path is not defined as a String, don't even attempt to require it.
     *
     * @returns {String}
     */
    SimpleBOPExtensionManager.prototype._getEntityProviderPath = function() {
        var self = this;
        var entityProviderPath = self._simpleBOP.getEntityProviderPath();

        AbcsLib.checkDefined(entityProviderPath, 'entityProviderPath');
        AbcsLib.checkDataType(entityProviderPath, AbcsLib.Type.STRING);

        return entityProviderPath;
    };

    /**
     * If the path is not defined as a String, don't even attempt to require it.
     *
     * @returns {String}
     */
    SimpleBOPExtensionManager.prototype._getOperationProviderPath = function() {
        var self = this;
        var operationProviderPath = self._simpleBOP.getOperationProviderPath();

        AbcsLib.checkDefined(operationProviderPath, 'operationProviderPath');
        AbcsLib.checkDataType(operationProviderPath, AbcsLib.Type.STRING);

        return operationProviderPath;
    };

    return SimpleBOPExtensionManager;
});