Home Reference Source

src/users/UserCollection.js

/** @private */
export const USER_ADDRESS_PREFIX = 'wac-user:';
/** @private */
export const USER_ADDRESS_PATTERN = RegExp(`^(${USER_ADDRESS_PREFIX})(\\w*)$`);

/**
 * A local collection of resolved addresses and subscribed addresses.
 * @private
 */
export class UserCollection {

	/**
	 * Constructs an users collection
	 * @param {String} userDomain User's session domain
	 * @protected
	 */
	constructor(userDomain) {

		/**
		 * Users indexed by id field.
		 * @private
		 * @type {Object}
		 */
		this._usersById = {};

		/**
		 * Users indexed by complete username (user@domain).
		 * @private
		 * @type {Object}
		 */
		this._usersByCompleteUsername = {};

		/**
		 * Users indexed by alias field.
		 * @private
		 * @type {Object}
		 */
		this._usersByAlias = {};

		/**
		 * Users indexed by landLineNumber field.
		 * @private
		 * @type {Object}
		 */
		this._usersByLandLineNumber = {};

		/**
		 * Users indexed by phone.
		 * @private
		 * @type {Object}
		 */
		this._usersByMobilePhone = {};

		/**
		 * Users indexed by gatewayUsername
		 * @private
		 * @type {Object}
		 */
		this._usersByGatewayUsername = {};

		/**
		 * The user's session domain
		 * @private
		 * @type {String}
		 */
		this._userDomain = userDomain;

		/**
		 * List of requested addresses.
		 * @private
		 * @type {Array<String>}
		 */
		this._subscribed = [];
	}

	/**
	 * Check if we are subscribed to an address.
	 * @param {String} address the address to query.
	 * @return {Boolean} true if subscribed.
	 */
	isSubscribedTo(address) {
		return this._subscribed.includes(address);
	}

	/**
	 * Update the list of subscribed address.
	 * @param {Array<String>} addresses new subscribed addresses that will
	 * replace existing one.
	 */
	updateSubscribed(addresses) {
		this._subscribed = addresses;
	}

	/**
	 * Add a user to the indexes.
	 * @protected
	 * @param {User} user the user to add.
	 */
	addUser(user) {
		user.getAddress = () => {
			return USER_ADDRESS_PREFIX + user.id;
		};
		this._usersById[user.id] = user;
		this._usersByCompleteUsername[`${user.username}@${user.domain}`.toLowerCase()] = user;
		if (user.alias) {
			this._usersByAlias[user.alias] = user;
		}
		if (user.landLineNumber) {
			this._usersByLandLineNumber[user.landLineNumber] = user;
		}
		if (user.gatewayUsername) {
			this._usersByGatewayUsername[user.gatewayUsername] = user;
		}
		user.mobilePhone.forEach((mobilePhone) => {
			this._usersByMobilePhone[mobilePhone] = user;
		});
	}

	/**
	 * Updates all resolved users and subscribed elements.
	 * @protected
	 * @param {Array<User>} users The new resolved users.
	 * @param {Array<String>} subscribed the new subscribed list.
	 */
	updateUsers(users, subscribed) {
		let newUsers = [];
		users.forEach((user) => {
			if (this._usersById[user.id]) {
				user = Object.assign(this._usersById[user.id], user);
			}
			newUsers.push(user);
		});
		this._usersById = {};
		this._usersByCompleteUsername = {};
		this._usersByAlias = {};
		this._usersByLandLineNumber = {};
		this._usersByGatewayUsername = {};
		this._usersByMobilePhone = {};
		this._subscribed = subscribed;
		newUsers.forEach(this.addUser.bind(this));
	}

	/**
	 * Resolve an address searching in local collection.
	 * @protected
	 * @param {String} address the requested address to resolve
	 * @return {User|undefined} If resolution success, the found User, undefined otherwise.
	 */
	resolve(address) {
		if (USER_ADDRESS_PATTERN.test(address)) {
			let id = USER_ADDRESS_PATTERN.exec(address)[2];
			return this._usersById[id];
		}
		return this._usersById[address]
			|| this._usersByCompleteUsername[address.toLowerCase()]
			|| this._usersByCompleteUsername[`${address}@${this._userDomain}`.toLowerCase()]
			|| this._usersByAlias[address]
			|| this._usersByLandLineNumber[address]
			|| this._usersByMobilePhone[address]
			|| this._usersByGatewayUsername[address];
	}
}