const {EventBase, EventBusBase} = require("./EventBase");
const {checkType, checkInstance} = require("./Utility");
/**
* A component that implements some functionality and communicates with other components. Used as a base class for various
* parts of the system that will interact through events.
*
* @property {string} name - The name of the component
* @property {type} string - The type of the component
* @property {EventBase} eventClass - A constructor function for the class of events used by the component
*/
class Component {
/**
* constructor
*
* @param {string} name - The name of the module.
* @param {string} type - The type of the module
* @param {EventBase} eventClass - The class to use for events for this component
*
* @returns {Component} The Object that was created
*/
constructor(name, type, eventClass) {
checkType("Component.constructor", "name", name, "string");
checkType("Component.constructor", "type", type, "string");
checkType("Component.constructor", "eventClass", eventClass, "class");
checkInstance("Component.constructor", "eventClass", eventClass.prototype, EventBase);
this.name = name;
this.type = type;
this.eventClass = eventClass;
Component.register(this);
this.eventBus = this.eventClass.prototype.eventBus;
checkInstance("Component.constructor", "eventBus", this.eventBus, EventBusBase);
}
/**
* Emits an event using the specified eventClass
*
* @param {string} type - The event type to emit
* @param {*} data - The data to emit
*/
sendEvent(type, data) {
checkType("sendEvent", "type", type, "string");
let e = new this.eventClass(this.name, this.type);
return e.emit(type, data);
}
/**
* Registers a component on the global component list
*
* @param {Component} comp The component to be registered
*/
static register(comp) {
checkInstance("Component.register", "comp", comp, Component);
if (componentMap.has(comp.name) && componentMap.get(comp.name) !== comp) {
throw new Error("can't register a module with a duplicate name and a different object");
}
componentMap.set(comp.name, comp);
}
/**
* Look up a Component using its name
*
* @param {string} name The name of the Component passed in at registration time
* @returns {Component} The Component with the corresponding name or `undefined` if none was found
*/
static get(name) {
return componentMap.get(name);
}
/**
* A global list of all components that have been registered. Value is a `Map` of {@link Component|Components}.
* Map keys are the component name.
*/
static get list() {
return componentMap;
}
/**
* Clears the global list of registered Components. Mostly used for testing.
*/
static clearList() {
componentMap.clear();
}
}
const componentMap = new Map();
module.exports = {Component};