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;