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

Source: layout.dt/js/api/ThemeProviderRegistry.js

define([
    'core/js/api/Listenable',
    'layout.dt/js/spi/ThemeProvider',
    'layout.dt/layouts.builtin/alta/js/AltaThemeProvider',
    'layout.dt/layouts.builtin/fuse/js/FuseThemeProvider',
    'layout.dt/layouts.builtin/fuse-r13/js/FuseThemeProviderR13'
], function(
        Listenable,
        ThemeProvider,
        AltaThemeProvider,
        FuseThemeProvider,
        FuseThemeProviderR13) {

    'use strict';

    /**
     * Registry of all ThemeProviders available to the system. New themes should
     * include an {@Link extensions.dt/js/spi/ExtensionManager ExtensionManager
     * SPI} implementation which will register and unregister them here.
     *
     * @AbcsExtension stable
     * @version 17.1.5
     *
     * @private
     * @singleton
     * @exports layout.dt/js/api/ThemeProviderRegistry
     * @constructor
     *
     * @example <caption>An example of a theme extension manager with methods to
     * register (initialise) and unregister (destroy) theme providers.</caption>
     * define([
     *   'layout.dt/js/api/ThemeProviderRegistry',
     *   'API.Example/js/SimpleThemeProvider'
     * ], function(
     *   ThemeProviderRegistry,
     *   SimpleThemeProvider
     * ) {
     *
     *   'use strict';
     *
     *   var ThemeExtensionManager = function () {
     *   };
     *
     *   ThemeExtensionManager.prototype.initialise = function (dependencies) {
     *     ThemeProviderRegistry.registerThemeProvider(SimpleThemeProvider);
     *   };
     *
     *   ThemeExtensionManager.prototype.destroy = function (dependencies) {
     *     ThemeProviderRegistry.unregisterThemeProvider(SimpleThemeProvider);
     *   };
     *
     *   ThemeExtensionManager.prototype.generateRuntimeCode = function(dependencies) {
     *   };
     *
     *   return new ThemeExtensionManager();
     * });
     * @see {@Link extensions.dt/js/spi/ExtensionManager SPI providing hook
     * points for extensions (e.g. a theme) initialization and destruction}
     */
    var ThemeProviderRegistry = function() {
        AbcsLib.checkThis(this);
        AbcsLib.checkSingleton(ThemeProviderRegistry);

        Listenable.apply(this);

        var self = this;

        self._initialize();
    };
    AbcsLib.mixin(ThemeProviderRegistry, Listenable);

    ThemeProviderRegistry._LOGGER = Logger.get('ThemeProviderRegistry');

    /**
     * Theme provider registered event.
     *
     * @event layout.dt/js/api/ThemeProviderRegistry#EVENT_THEME_PROVIDER_REGISTERED
     * @property {String} theme ID of the registered provider
     */
    ThemeProviderRegistry.EVENT_THEME_PROVIDER_REGISTERED = 'themeProviderRegistered';

    /**
     * Theme provider unregistered event.
     *
     * @event layout.dt/js/api/ThemeProviderRegistry#EVENT_THEME_PROVIDER_UNREGISTERED
     * @property {String} theme ID of the unregistered provider
     */
    ThemeProviderRegistry.EVENT_THEME_PROVIDER_UNREGISTERED = 'themeProviderUnregistered';

    // Bundled internal themes. The intention is to move these out to be
    // bundled extensions.
    ThemeProviderRegistry._BUNDLED_THEME_PROVIDERS = [AltaThemeProvider, FuseThemeProviderR13, FuseThemeProvider];

    /**
     * Gets all registered theme providers
     *
     * @returns {layout.dt/js/api/ThemeProvider[]} array of available theme providers
     */
    ThemeProviderRegistry.prototype.getThemeProviders = function() {
        return this._registry;
    };

    /**
     * Gets array of descriptors for all registered theme providers
     *
     * @param filter value to filter by, or undefined
     * @returns {layout.dt/js/api/ThemeDescriptor[]} array of available descriptors
     */
    ThemeProviderRegistry.prototype.getThemeDescriptors = function(filter) {
        var themeDescriptors = [];
        for (var i = 0; i < this._registry.length; i++) {
            var descriptor = this._registry[i].getDescriptor();
            if (filter) {
                filter = filter.toLowerCase();
                if (descriptor.getId().toLowerCase().indexOf(filter) > -1 ||
                    descriptor.getTitle().toLowerCase().indexOf(filter) > -1 ||
                    (descriptor.getDescription() && descriptor.getDescription().toLowerCase().indexOf(filter) > -1)) {

                    themeDescriptors.push(descriptor);
                }
            } else {
                themeDescriptors.push(descriptor);
            }
        }

        return themeDescriptors;
    };

    /**
     * Returns the provider for the requested theme ID
     *
     * @param {String} themeId Theme ID to check
     * @returns {ThemeDescriptor} the descriptor for the themeId, if registered,
     * otherwise null
     */
    ThemeProviderRegistry.prototype.getThemeDescriptorForTheme = function(themeId) {
        var i;
        for (i = 0; i < this.getThemeProviders().length; i++) {
            if (this._registry[i].getDescriptor().getId() === themeId) {
                return this._registry[i].getDescriptor();
            }
        }
        return null;
    };

    /**
     * Determines whether a theme with the supplied ID is registered.
     *
     * @param {String} themeId Theme ID to check
     * @returns {Boolean} true if the theme is supported, false otherwise
     */
    ThemeProviderRegistry.prototype.isSupportedThemeId = function(themeId) {
        var i;
        for (i = 0; i < this.getThemeProviders().length; i++) {
            if (this._registry[i].getDescriptor().getId() === themeId) {
                return true;
            }
        }
        return false;
    };

    /**
     * Returns the provider for the requested theme ID
     *
     * @param {String} themeId Theme ID to check
     * @returns {ThemeProvider} the provider for the themeId, if registered, otherwise null
     */
    ThemeProviderRegistry.prototype.getThemeProviderForTheme = function(themeId) {
        var i;
        for (i = 0; i < this.getThemeProviders().length; i++) {
            if (this._registry[i].getDescriptor().getId() === themeId) {
                return this._registry[i];
            }
        }
        return null;
    };

    /**
     * Registers the given theme provider.
     *
     * @AbcsExtension stable
     * @version 17.1.5
     *
     * @param {layout.dt/js/spi/ThemeProvider} themeProvider The theme provider
     *         to register
     */
    ThemeProviderRegistry.prototype.registerThemeProvider = function(themeProvider) {
        AbcsLib.checkParameterCount(arguments, 1);
        AbcsLib.checkDataType(themeProvider, AbcsLib.Type.OBJECT);
        // Temporary fix until BUFP-10314 is solved ----------------------------
        // to allow use of theme providers including public fields
//        AbcsLib.checkSPIImpl(themeProvider, ThemeProvider); // Commented out

        if (!(themeProvider instanceof ThemeProvider)) {
            var themeSpiFunctionKeys = Object.keys(ThemeProvider.prototype);
            AbcsLib._checkSPIFunctions(themeProvider, themeSpiFunctionKeys);
        }
        // Temporary fix until BUFP-10314 is solved - END ----------------------

        var self = this;

        var themeId = themeProvider.getDescriptor().getId();
        var existingProvider = self.getThemeProviderForTheme(themeId);

        if (existingProvider) {
            ThemeProviderRegistry._LOGGER.debug('Replacing existing theme provider: ' + themeId);
            self.unregisterThemeProvider(existingProvider);
        }

        self._registry.push(themeProvider);
        ThemeProviderRegistry._LOGGER.debug('Registered theme provider: ' + themeProvider.getDescriptor().getId());

        self.fireEvent(ThemeProviderRegistry.EVENT_THEME_PROVIDER_REGISTERED, themeId);
    };

    /**
     * Unregister the supplied theme provider, if it's registered.
     *
     * @AbcsExtension stable
     * @version 17.1.5
     *
     * @param {layout.dt/js/spi/ThemeProvider} themeProvider the theme provider
     *         to unregister
     */
    ThemeProviderRegistry.prototype.unregisterThemeProvider = function(themeProvider) {
        AbcsLib.checkParameterCount(arguments, 1);
        AbcsLib.checkDataType(themeProvider, AbcsLib.Type.OBJECT);
        // Temporary fix until BUFP-10314 is solved ----------------------------
        // to allow use of theme providers including public fields
//        AbcsLib.checkSPIImpl(themeProvider, ThemeProvider); // Commented out

        if (!(themeProvider instanceof ThemeProvider)) {
            var themeSpiFunctionKeys = Object.keys(ThemeProvider.prototype);
            AbcsLib._checkSPIFunctions(themeProvider, themeSpiFunctionKeys);
        }
        // Temporary fix until BUFP-10314 is solved - END ----------------------

        var themeId = themeProvider.getDescriptor().getId();

        var self = this;
        var i, nextDescriptor;
        var location = -1;
        for (i = 0; i < self._registry.length; i++) {
            nextDescriptor = self._registry[i].getDescriptor();
            if (nextDescriptor && nextDescriptor.getId() === themeId) {
                location = i;
            }
        }

        if (location !== -1) {
            self._registry.splice(location, 1);
            ThemeProviderRegistry._LOGGER.debug('Unregistered theme provider: ' + themeProvider.getDescriptor().getId());
            self.fireEvent(ThemeProviderRegistry.EVENT_THEME_PROVIDER_UNREGISTERED, themeId);
        } else {
            ThemeProviderRegistry._LOGGER.debug('Couldn\'t unregister unexisting theme provider: ' + themeProvider.getDescriptor().getId());
        }
    };

    /**
     * Initialize the registry.
     * @returns {undefined}
     */
    ThemeProviderRegistry.prototype._initialize = function() {
        this._registry = [];
        this._loadBundledThemes();
    };

    /**
     * Register any themes bundled with ABCS.
     *
     * @returns {undefined}
     */
    ThemeProviderRegistry.prototype._loadBundledThemes = function() {
        var self = this;
        ThemeProviderRegistry._BUNDLED_THEME_PROVIDERS.forEach(function(provider) {
            self.registerThemeProvider(provider);
            ThemeProviderRegistry._LOGGER.debug('Added bundled theme provider: ' + provider.getDescriptor().getId());
        });
    };

    return AbcsLib.initSingleton(ThemeProviderRegistry);
});