util_enum.js

/**
 * An enumerated object base class.
 *
 * This class is essentially abstract, and must be extended by another
 * class that overrides the {@link module:util~Enum.enumValues} method.
 *
 * @abstract
 * @alias module:util~Enum
 */
class Enum {
	/**
	 * Constructor.
	 *
	 * @param {string} name the name
	 */
	constructor(name) {
		this._name = name;
		if (this.constructor === Enum) {
			Object.freeze(this);
		}
	}

	/**
	 * Get the enum name.
	 *
	 * @returns {string} the  name
	 */
	get name() {
		return this._name;
	}

	/**
	 * Test if a string is equal to this enum's name.
	 *
	 * As long as enum values are consistently obtained from the {@link module:util~Enum.enumValues}
	 * array then enum instances can be compared with `===`. If unsure, this method can be used
	 * to compare string values instead.
	 *
	 * If `value` is passed as an actual Enum instance, then if that enum is the same class
	 * as this enum it's `name` is compared to this instance's `name`.
	 *
	 * @param {string|Enum} value the value to test
	 * @returns {boolean} `true` if `value` is the same as this instance's `name` value
	 */
	equals(value) {
		if (this.constructor === value.constructor) {
			return value.name === this.name;
		}
		return value === this.name;
	}

	/**
	 * Get all enum values.
	 *
	 * This method must be overridden by subclasses to return something meaningful.
	 * This implementation returns an empty array.
	 *
	 * @abstract
	 * @returns {module:util~Enum[]} get all enum values
	 */
	static enumValues() {
		return [];
	}

	/**
	 * This method takes an array of enums and turns them into a mapped object, using the enum
	 * `name` as object property names.
	 *
	 * @param {module:util~Enum[]} enums the enum list to turn into a value object
	 * @returns {object} an object with enum `name` properties with associated enum values
	 */
	static enumsValue(enums) {
		return Object.freeze(
			enums.reduce((obj, e) => {
				obj[e.name] = e;
				return obj;
			}, {}),
		);
	}

	/**
	 * Get an enum instance from its name.
	 *
	 * This method searches the {@link module:util~Enum#enumVvalues} array for a matching value.
	 *
	 * @param {string} name the enum name to get an instnace for
	 * @returns {module:util~Enum} the instance, or `undefined` if no instance exists for the given `name`
	 */
	static valueOf(name) {
		const enums = this.enumValues();
		if (!Array.isArray(enums)) {
			return undefined;
		}
		for (let i = 0, len = enums.length; i < len; i += 1) {
			if (name === enums[i].name) {
				return enums[i];
			}
		}
		return undefined;
	}

	/**
	 * Get the names of a set of `Enum` instances.
	 * @param {Enum[]} set the set of `Enum` instances to get the names of
	 * @returns {string[]} array of `Enum` name values
	 */
	static namesFor(set) {
		const result = [];
		if (set) {
			for (const e of set) {
				result.push(e.name);
			}
		}
		return result;
	}
}

export default Enum;