# Source: data/sources.js

    import {RegistryBase} from '../registry/base';
    import { ADAPTERS } from '../registry';

    /**
     * Create and coordinate an ensemble of (namespaced) data adapter instances.
     * This is the mechanism by which users tell a plot how to retrieve data for a specific plot: adapters are created
     *  through this object rather than instantiating directly.
     *
     * @public
     * @alias module:LocusZoom~DataSources
     * @extends module:registry/base~RegistryBase
     * @inheritDoc
     */
    class DataSources extends RegistryBase {
        /**
         * @param {RegistryBase} [registry] Primarily used for unit testing. When creating sources by name, specify where to
         *  find the registry of known sources.
         */
        constructor(registry) {
            super();
            // This both acts as a registry (of the instantiated sources for this plot), and references a registry
            //   (to locate adapter classes by name, when creating from config)
            this._registry = registry || ADAPTERS;
        }

        /**
         * For data sources, there is a special behavior of "create item from config, then add"
         * @param {String} namespace Uniquely identify this datasource
         * @param {BaseAdapter|Array} item An instantiated datasource, or an array of arguments that can be used to
         *   create a known datasource type.
         * @param [override=false] Whether to allow existing sources to be redefined
         * @return {DataSources} Most registries return the created instance, but this registry returns a reference to
         *  itself (to support chaining)
         */
        add(namespace, item, override = false) {
            if (this._registry.has(namespace)) {
                throw new Error(`The namespace ${namespace} is already in use by another source`);
            }

            if (namespace.match(/[^A-Za-z0-9_]/)) {
                throw new Error(`Data source namespace names can only contain alphanumeric characters or underscores. Invalid name: ${namespace}`);
            }
            if (Array.isArray(item)) {
                const [type, options] = item;
                item = this._registry.create(type, options);
            }
            // Each datasource in the chain should be aware of its assigned namespace
            item.source_id = namespace;

            super.add(namespace, item, override);
            return this;
        }
    }

    export default DataSources;