define([], function() {
'use strict';
/**
* This API module allows authors of ABCS extensions to define their behaviour.
*
* <p>The infrastructure calls its methods {@link extensions.dt/js/spi/ExtensionManager#initialise ExtensionManager.initialise}
* and {@link extensions.dt/js/spi/ExtensionManager#destroy ExtensionManager.destroy} when the application
* which holds the extension is opened or closed.
* </p>
*
* <p>
* It's guranteed that the infrastructure will never call {@link extensions.dt/js/spi/ExtensionManager#initialise ExtensionManager.initialise}
* or {@link extensions.dt/js/spi/extensions.dt/js/spi/ExtensionManager#destroy ExtensionManager.destroy} method twice in row.
* They can be called N times, but always altering.
* </p>
*
* <p>A composite operation consisting from calls to the {@link extensions.dt/js/spi/ExtensionManager#initialise ExtensionManager.initialise}
* or {@link extensions.dt/js/spi/ExtensionManager#destroy ExtensionManager.destroy}
* methods must be idempotent. Which means that when the two methods are
* called in sequence, the state of the system must be exactly the same as before the calls.</p>
*
* The module path is specified in the extension manifest under the "extensionManager" key.
*
* @AbcsExtension stable
* @exports extensions.dt/js/spi/ExtensionManager
* @constructor
* @private
* @version 16.3.1
* @example <caption>Simple shared object extension</caption>
* define([
* 'core/js/api/SharedObjectRegistry'
* ], function (sharedObjectRegistry) {
* 'use strict';
* function MyExtensionManager() {
* }
* MyExtensionManager._OBJECT_ID = 'com.mycompany.extensions.myExtension.message';
* MyExtensionManager.prototype.initialise = function () {
* sharedObjectRegistry.register(MyExtensionManager._OBJECT_ID, 'Ahoy!');
* return Promise.resolve();
* };
* MyExtensionManager.prototype.destroy = function () {
* sharedObjectRegistry.unregister(MyExtensionManager._OBJECT_ID);
* return Promise.resolve();
* };
* MyExtensionManager.prototype.generateRuntimeCode = function () {
* return Promise.resolve('function() {\n\
* return new Promise(function(f,r) {\n\
* require([\'core/js/api/SharedObjectRegistry\'], function(sharedObjectRegistry) {\n\
* sharedObjectRegistry.register(\'com.mycompany.extensions.myExtension.message\', \'Ahoy!\');\n\
* f();\n\
* }, r);\n\
* });\n\
* }\n');
* };
* return new MyExtensionManager();
* });
*/
var ExtensionManager = function () {};
/**
* This method is responsible for initialisation of the extension.
*
* <p>Extension author may call any ABCS stable APIs here to "install" the extension
* to the VM. For example {@link bop/js/spi/BOP BOP} extension typically registers its {@link bop/js/spi/entity/EntityProvider EntityProvider}
* and {@link bop/js/spi/operation/OperationProvider OperationProvider} in this method. Custom UI component register its
* creator, PIs, view generators etc. here.</p>
*
* <p>The method is called by the infrastructure when the application which owns
* or refers the extension is initialised (opened).</p>
*
* <p>An array of {@link module:extensions.dt/js/spi/ExtensionManager.Dependency ExtensionManager.Dependency} objects is passed to the method.
* Each of them represents one dependency to the extension from a dependent object.</p>
*
* <p>It is guaranteed that this method is called only after all dependencies which
* this extension has have been resolved which means the corresponding dependency targets
* (extensions or more generic shareable objects) are initialised.</p>
*
* <p>It's the responsibility of the extension itself to understand any dependencies parameters
* and adjust its behaviour accordingly.</p>
*
* @AbcsExtension stable
* @version 16.3.1
* @param {module:extensions.dt/js/spi/ExtensionManager.Dependency[]} dependencies - array of Dependency
* objects which the extension is target of.
* @return {Promise} promise of the extension being initialised.
*
* @example <caption>Registration of a shared object</caption>
* CurrentTimeExtensionManager.prototype.initialise = function (dependencies) {
* sharedObjectRegistry.register('com.company.abcs.extensions.currentTime', CurrentTime);
* return Promise.resolve();
* };
*/
ExtensionManager.prototype.initialise = function(dependencies) { //eslint-disable-line no-unused-vars
AbcsLib.throwMustBeOverriddenError();
};
/**
* This method is responsible for destroying of the extension.
*
* <p>Extension author may call any ABCS stable APIs here to remove any changes
* which were previously done in the {@link extensions.dt/js/spi/ExtensionManager#initialise ExtensionManager.initialise}
* method from the system.</p>
*
* <p>{@link bop/js/spi/BOP BOP} extension typically un-registers its {@link bop/js/spi/entity/EntityProvider EntityProvider}
* and {@link bop/js/spi/operation/OperationProvider OperationProvider} here. Custom UI component un-register its
* creator, PIs, view generators etc.</p>
*
* <p>The method is called by the infrastructure when the application which owns
* or refers the extension is destroyed (closed).</p>
*
* <p>An array of {@link module:extensions.dt/js/spi/ExtensionManager.Dependency ExtensionManager.Dependency} objects is passed to the method.
* Each of them represents one dependency to the extension from a dependent object.
* The passed dependencies are identical to those which were previously passed
* to the {@link extensions.dt/js/spi/ExtensionManager#initialise ExtensionManager.initialise}
* method.</p>
*
* <p>This method is called only after all dependents which depends on this
* extension were destroyed (the destroy sequence is reverse to the initialisation sequence).</p>
*
* <p>It's the responsibility of the extension itself to understand any dependencies parameters
* and adjust its behaviour accordingly.</p>
*
* @AbcsExtension stable
* @version 16.3.1
* @param {module:extensions.dt/js/spi/ExtensionManager.Dependency[]} dependencies - array of Dependency
* objects which the extension is target of.
* @return {Promise} promise of the extension being destroyed.
*
* @example <caption>De-registration of a shared object</caption>
* CurrentTimeExtensionManager.prototype.destroy = function (dependencies) {
* sharedObjectRegistry.unregister('com.company.abcs.extensions.currentTime');
* return Promise.resolve();
* };
*/
ExtensionManager.prototype.destroy = function(dependencies) { //eslint-disable-line no-unused-vars
AbcsLib.throwMustBeOverriddenError();
};
/**
* Generates a body of javascript function responsible for initialisation
* of the extension in runtime.
*
* <p>The javascript code is placed to a global extensions/shareable objects initialiser
* which runs when the ABCS application is initialised in runtime.</p>
*
* <p>If this extension has dependencies to other shareable objects,
* these shareable objects will be initialised before the code returned
* from this method runs.</p>
*
* <p>The returned code must contain a function body and the function
* must return a Promise object. The promise must only be resolved when the
* code finishes its work which means the extension is initialised
* in the runtime environment.</p>
*
* <p>During the runtime application artefact generation, the extensions
* are initialised according to the applications dependencies in
* similar manner as in design time.</p>
*
* <p>Note: You may use several techniques to built the code in text form:
* <ul>
* <li>return the code as a string - simple variant, allows to easily generate
* the code based on the input parameters passed via the dependencies, however
* it's bit more error prone as you need to properly escape the content of the string.
* <li>alternatively if your code is long and complex enough, you can keep it
* as a separate file in the sources of the extension and then load that module
* using the the requirejs text plugin. This way you can also easily make
* the file a template and use some templating mechanism to resolve
* templating variables. This method spares you the painful escaping
* of the previous simple method.
* <li>use Function.toString() - you can simply declare the required function
* in code form (not as string) and then use the Function.toString() method
* to convert the code to the required textual form.
* </ul>
*
* @AbcsExtension stable
* @version 16.3.1
* @param {module:extensions.dt/js/spi/ExtensionManager.Dependency[]} dependencies - array of Dependency
* objects which the extension is target of.
* @returns {Promise<String>} promise of javascript code in text form
*
* @example <caption>Trivial synchronous initialisation code</caption>
* ExtensionManager.prototype.generateRuntimeCode = function() {
* return 'function () {\n\
* return Promise.resolve();\n\
* }\n';
* }
* @example <caption>Trivial synchronous initialisation code using the Function.toString() method of producing the code</caption>
* ExtensionManager.prototype.generateRuntimeCode = function() {
* return function () {
* return Promise.resolve();
* }.toString();
* }
* @example <caption>More complex asynchronous initialisation code</caption>
* ExtensionManager.prototype.generateRuntimeCode = function() {
* return 'function () {\n\
* return new Promise(function (f, r) {\n\
* require([\'yourPackage/js/YourModule\'], function (YourModule) {\n\
* //if the initialisation itself is asynchronous don\'t forget the resolve the promise\n\
* //when the initialisation finishes, e.g.:\n\
* YourModule.getPromiseOfSomethingAsync().then(f).catch(r);\n\
* }, r);\n\
* });\n\
* }\n';
* }
* @example <caption>Using the separate runtime code template</caption>
* define([
* 'core/js/api/SharedObjectRegistry',
* 'text!com.mycompany.extensions.myExtension/templates/RuntimeInitialiser.js'
* ], function (
* sharedObjectRegistry,
* runtimeInitialiserTemplate
* ) {
* 'use strict';
* function MyExtensionManager() {
* }
* MyExtensionManager._OBJECT_ID = 'com.mycompany.extensions.myExtension.message';
* ...
* MyExtensionManager.prototype.generateRuntimeCode = function () {
* //possibly resolve templating variables used in the templates/RuntimeInitialiser.js file here
* return runtimeInitialiserTemplate;
* };
* return new MyExtensionManager();
* });
*/
ExtensionManager.prototype.generateRuntimeCode = function(dependencies) { //eslint-disable-line no-unused-vars
AbcsLib.throwMustBeOverriddenError();
};
/**
* Defines a dependency between a dependent and an extension object.
*
* <p>An array of objects of this type is passed to the ExtensionManager's
* methods by the infrastructure during the extension lifecycle.</p>
*
* <p>The basic format of the dependency is defined by the
* {@link extensions.dt/js/spi/ExtensionManager~ExtensionDependencyFormat ExtensionDependencyFormat}
* module.</p>
*
* <p>However the keys defined and described there are only the mandatory
* keys which every dependency to an extension must possess.
* Each individual extension can define its own "API" -- e.g. set of keys
* in the dependency definition it understands. The implementation of
* the corresponding ExtensionManager is then responsible for reading those
* keys from the passed dependency object and adapt its behaviour accordingly.</p>
*
* @AbcsExtension stable
* @version 16.3.1
* @memberof module:extensions.dt/js/spi/ExtensionManager
* @objectLiteral
* @example <caption>Usage of the Dependency passed objects</caption>
* CurrentTimeExtensionManager.prototype.initialise = function (dependencies) {
* var timeZones = ['utc']; //default timezone (if noone specifies time zone explicitly in the dependency).
* (dependencies || []).forEach(function(dependency) {
* var timeZone = dependency.getDefinition().timeZone;
* if(timeZone) {
* timeZones.push(timeZone);
* }
* });
* timeZones.forEach(function(timeZone) {
* sharedObjectRegistry.unregister('com.company.abcs.extensions.currentTime.' + timeZone, new CurrentTime(timeZone));
* });
* return Promise.resolve();
* };
*/
var Dependency = function() {
};
/**
* Gets definition of a dependency to an extension.
*
* <p>The keys of the dependency description are defined in {@link extensions.dt/js/spi/ExtensionManager~ExtensionDependencyFormat ExtensionDependencyFormat}</p>
*
* @AbcsExtension stable
* @version 16.3.1
* @returns {Object}
*
* @example <caption>Sample dependency to an ABCS extension</caption>
* {
* sourceType: 'application',
* sourceId: 'myApplication-1.0',
* extensionId: 'com.mycompany.abcs.extensions.myTwitterBOP'
* }
* @see {@link bop.dt/js/spi/BOPExtensionManager~BOPExtensionDependencyFormat BOP dependency definition format}
*/
Dependency.prototype.getDefinition = function(){
};
return ExtensionManager;
});