UNPKG

saij

Version:
323 lines (263 loc) 22.8 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.CollectionEvent = void 0; var _Object = _interopRequireDefault(require("./Object")); var _Event = _interopRequireDefault(require("./Event")); var _AssertionError = _interopRequireDefault(require("./AssertionError")); var _CollectionEventType = _interopRequireDefault(require("./CollectionEventType")); var _Errors = _interopRequireDefault(require("./Errors")); /** * @module saij/core/Collection */ /* eslint max-len: 0 */ /** * @enum {string} * @private */ const Property = { LENGTH: 'length' }; /** * @classdesc * Events emitted by {@link module:saij/core/Collection~Collection} instances are instances of this * type. */ class CollectionEvent extends _Event.default { /** * @param {module:saij/core/CollectionEventType} type Type. * @param {*=} opt_element Element. */ constructor(type, opt_element) { super(type); /** * The element that is added to or removed from the collection. * @type {*} * @api */ this.element = opt_element; } } /** * @typedef {Object} Options * @property {boolean} [unique=false] Disallow the same item from being added to * the collection twice. */ /** * @classdesc * An expanded version of standard JS Array, adding convenience methods for * manipulation. Add and remove changes to the Collection trigger a Collection * event. Note that this does not cover changes to the objects _within_ the * Collection; they trigger events on the appropriate object, not on the * Collection as a whole. * * @template T * @api */ exports.CollectionEvent = CollectionEvent; class Collection extends _Object.default { /** * @param {Array<T>=} opt_array Array. * @param {module:saij/core/Collection~Options=} opt_options Collection options. */ constructor(opt_array, opt_options) { super(); const options = opt_options || {}; /** * @private * @type {boolean} */ this.unique_ = Boolean(options.unique); /** * @private * @type {!Array<T>} */ this.array_ = opt_array ? opt_array : []; if (this.unique_) { for (let i = 0, ii = this.array_.length; i < ii; i += 1) { this.assertUnique_(this.array_[i], i); } } this.updateLength_(); } /** * Remove all elements from the collection. * @api */ clear() { while (this.getLength() > 0) { this.pop(); } } /** * Add elements to the collection. This pushes each item in the provided array * to the end of the collection. * @param {!Array<T>} arr Array. * @return {module:saij/core/Collection<T>} This collection. * @api */ extend(arr) { for (let i = 0, ii = arr.length; i < ii; i += 1) { this.push(arr[i]); } return this; } /** * Iterate over each element, calling the provided callback. * @param {function(T, number, Array<T>): *} func The function to call * for every element. This function takes 3 arguments (the element, the * index and the array). The return value is ignored. * @api */ forEach(func) { const array = this.array_; for (let i = 0, ii = array.length; i < ii; i += 1) { func(array[i], i, array); } } /** * Get a reference to the underlying Array object. Warning: if the array * is mutated, no events will be dispatched by the collection, and the * collection's "length" property won't be in sync with the actual length * of the array. * @return {!Array<T>} Array. * @api */ getArray() { return this.array_; } /** * Get the element at the provided index. * @param {number} index Index. * @return {T} Element. * @api */ item(index) { return this.array_[index]; } /** * Get the length of this collection. * @return {number} The length of the array. * @observable * @api */ getLength() { return ( /** @type {number} */ this.get(Property.LENGTH) ); } /** * Insert an element at the provided index. * @param {number} index Index. * @param {T} elem Element. * @api */ insertAt(index, elem) { if (this.unique_) { this.assertUnique_(elem); } this.array_.splice(index, 0, elem); this.updateLength_(); this.dispatchEvent(new CollectionEvent(_CollectionEventType.default.ADD, elem)); } /** * Remove the last element of the collection and return it. * Return `undefined` if the collection is empty. * @return {T|undefined} Element. * @api */ pop() { return this.removeAt(this.getLength() - 1); } /** * Insert the provided element at the end of the collection. * @param {T} elem Element. * @return {number} New length of the collection. * @api */ push(elem) { if (this.unique_) { this.assertUnique_(elem); } const len = this.getLength(); this.insertAt(len, elem); return this.getLength(); } /** * Remove the first occurrence of an element from the collection. * @param {T} elem Element. * @return {T|undefined} The removed element or undefined if none found. * @api */ remove(elem) { const arr = this.array_; for (let i = 0, ii = arr.length; i < ii; i += 1) { if (arr[i] === elem) { return this.removeAt(i); } } return undefined; } /** * Remove the element at the provided index and return it. * Return `undefined` if the collection does not contain this index. * @param {number} index Index. * @return {T|undefined} Value. * @api */ removeAt(index) { const prev = this.array_[index]; this.array_.splice(index, 1); this.updateLength_(); this.dispatchEvent(new CollectionEvent(_CollectionEventType.default.REMOVE, prev)); return prev; } /** * Set the element at the provided index. * @param {number} index Index. * @param {T} elem Element. * @api */ // eslint-disable-next-line max-statements setAt(index, elem) { const len = this.getLength(); if (index < len) { if (this.unique_) { this.assertUnique_(elem, index); } const prev = this.array_[index]; this.array_[index] = elem; this.dispatchEvent(new CollectionEvent(_CollectionEventType.default.REMOVE, prev)); this.dispatchEvent(new CollectionEvent(_CollectionEventType.default.ADD, elem)); } else { for (let j = len; j < index; j += 1) { this.insertAt(j, undefined); } this.insertAt(index, elem); } } /** * @private */ updateLength_() { this.set(Property.LENGTH, this.array_.length); } /** * @private * @param {T} elem Element. * @param {number=} opt_except Optional index to ignore. */ assertUnique_(elem, opt_except) { for (let i = 0, ii = this.array_.length; i < ii; i += 1) { if (this.array_[i] === elem && i !== opt_except) { throw new _AssertionError.default(_Errors.default.ASSERT_UNIQUE.code); } } } } var _default = Collection; exports.default = _default; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zYWlqL2NvcmUvQ29sbGVjdGlvbi5qcyJdLCJuYW1lcyI6WyJQcm9wZXJ0eSIsIkxFTkdUSCIsIkNvbGxlY3Rpb25FdmVudCIsIkV2ZW50IiwiY29uc3RydWN0b3IiLCJ0eXBlIiwib3B0X2VsZW1lbnQiLCJlbGVtZW50IiwiQ29sbGVjdGlvbiIsIkJhc2VPYmplY3QiLCJvcHRfYXJyYXkiLCJvcHRfb3B0aW9ucyIsIm9wdGlvbnMiLCJ1bmlxdWVfIiwiQm9vbGVhbiIsInVuaXF1ZSIsImFycmF5XyIsImkiLCJpaSIsImxlbmd0aCIsImFzc2VydFVuaXF1ZV8iLCJ1cGRhdGVMZW5ndGhfIiwiY2xlYXIiLCJnZXRMZW5ndGgiLCJwb3AiLCJleHRlbmQiLCJhcnIiLCJwdXNoIiwiZm9yRWFjaCIsImZ1bmMiLCJhcnJheSIsImdldEFycmF5IiwiaXRlbSIsImluZGV4IiwiZ2V0IiwiaW5zZXJ0QXQiLCJlbGVtIiwic3BsaWNlIiwiZGlzcGF0Y2hFdmVudCIsIkNvbGxlY3Rpb25FdmVudFR5cGUiLCJBREQiLCJyZW1vdmVBdCIsImxlbiIsInJlbW92ZSIsInVuZGVmaW5lZCIsInByZXYiLCJSRU1PVkUiLCJzZXRBdCIsImoiLCJzZXQiLCJvcHRfZXhjZXB0IiwiQXNzZXJ0aW9uRXJyb3IiLCJFcnJvcnMiLCJBU1NFUlRfVU5JUVVFIiwiY29kZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBR0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBUEE7Ozs7QUFTQTs7QUFHQTs7OztBQUlBLE1BQU1BLFFBQVEsR0FBRztBQUNmQyxFQUFBQSxNQUFNLEVBQUU7QUFETyxDQUFqQjtBQUtBOzs7Ozs7QUFLTyxNQUFNQyxlQUFOLFNBQThCQyxjQUE5QixDQUFvQztBQUV6Qzs7OztBQUlBQyxFQUFBQSxXQUFXLENBQUNDLElBQUQsRUFBT0MsV0FBUCxFQUFvQjtBQUM3QixVQUFNRCxJQUFOO0FBRUE7Ozs7OztBQUtBLFNBQUtFLE9BQUwsR0FBZUQs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QyxFQUFpRDtBQUMvQyxjQUFNLElBQUlDLHVCQUFKLENBQW1CQyxnQkFBT0MsYUFBUCxDQUFxQkMsSUFBeEMsQ0FBTjtBQUNEO0FBQ0Y7QUFDRjs7QUE3TmlDOztlQWlPckI5QyxVIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbW9kdWxlIHNhaWovY29yZS9Db2xsZWN0aW9uXG4gKi9cbmltcG9ydCBCYXNlT2JqZWN0IGZyb20gJy4vT2JqZWN0JztcbmltcG9ydCBFdmVudCBmcm9tICcuL0V2ZW50JztcbmltcG9ydCBBc3NlcnRpb25FcnJvciBmcm9tICcuL0Fzc2VydGlvbkVycm9yJztcbmltcG9ydCBDb2xsZWN0aW9uRXZlbnRUeXBlIGZyb20gJy4vQ29sbGVjdGlvbkV2ZW50VHlwZSc7XG5pbXBvcnQgRXJyb3JzIGZyb20gJy4vRXJyb3JzJztcblxuLyogZXNsaW50IG1heC1sZW46IDAgKi9cblxuXG4vKipcbiAqIEBlbnVtIHtzdHJpbmd9XG4gKiBAcHJpdmF0ZVxuICovXG5jb25zdCBQcm9wZXJ0eSA9IHtcbiAgTEVOR1RIOiAnbGVuZ3RoJ1xufTtcblxuXG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIEV2ZW50cyBlbWl0dGVkIGJ5IHtAbGluayBtb2R1bGU6c2Fpai9jb3JlL0NvbGxlY3Rpb25+Q29sbGVjdGlvbn0gaW5zdGFuY2VzIGFyZSBpbnN0YW5jZXMgb2YgdGhpc1xuICogdHlwZS5cbiAqL1xuZXhwb3J0IGNsYXNzIENvbGxlY3Rpb25FdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAvKipcbiAgICogQHBhcmFtIHttb2R1bGU6c2Fpai9jb3JlL0NvbGxlY3Rpb25FdmVudFR5cGV9IHR5cGUgVHlwZS5cbiAgICogQHBhcmFtIHsqPX0gb3B0X2VsZW1lbnQgRWxlbWVudC5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9wdF9lbGVtZW50KSB7XG4gICAgc3VwZXIodHlwZSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZWxlbWVudCB0aGF0IGlzIGFkZGVkIHRvIG9yIHJlbW92ZWQgZnJvbSB0aGUgY29sbGVjdGlvbi5cbiAgICAgKiBAdHlwZSB7Kn1cbiAgICAgKiBAYXBpXG4gICAgICovXG4gICAgdGhpcy5lbGVtZW50ID0gb3B0X2VsZW1lbnQ7XG4gIH1cbn1cblxuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW3VuaXF1ZT1mYWxzZV0gRGlzYWxsb3cgdGhlIHNhbWUgaXRlbSBmcm9tIGJlaW5nIGFkZGVkIHRvXG4gKiB0aGUgY29sbGVjdGlvbiB0d2ljZS5cbiAqL1xuXG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIEFuIGV4cGFuZGVkIHZlcnNpb24gb2Ygc3RhbmRhcmQgSlMgQXJyYXksIGFkZGluZyBjb252ZW5pZW5jZSBtZXRob2RzIGZvclxuICogbWFuaXB1bGF0aW9uLiBBZGQgYW5kIHJlbW92ZSBjaGFuZ2VzIHRvIHRoZSBDb2xsZWN0aW9uIHRyaWdnZXIgYSBDb2xsZWN0aW9uXG4gKiBldmVudC4gTm90ZSB0aGF0IHRoaXMgZG9lcyBub3QgY292ZXIgY2hhbmdlcyB0byB0aGUgb2JqZWN0cyBfd2l0aGluXyB0aGVcbiAqIENvbGxlY3Rpb247IHRoZXkgdHJpZ2dlciBldmVudHMgb24gdGhlIGFwcHJvcHJpYXRlIG9iamVjdCwgbm90IG9uIHRoZVxuICogQ29sbGVjdGlvbiBhcyBhIHdob2xlLlxuICpcbiAqIEB0ZW1wbGF0ZSBUXG4gKiBAYXBpXG4gKi9cbmNsYXNzIENvbGxlY3Rpb24gZXh0ZW5kcyBCYXNlT2JqZWN0IHtcblxuICAvKipcbiAgICogQHBhcmFtIHtBcnJheTxUPj19IG9wdF9hcnJheSBBcnJheS5cbiAgICogQHBhcmFtIHttb2R1bGU6c2Fpai9jb3JlL0NvbGxlY3Rpb25+T3B0aW9ucz19IG9wdF9vcHRpb25zIENvbGxlY3Rpb24gb3B0aW9ucy5cbiAgICovXG4gIGNvbnN0cnVjdG9yKG9wdF9hcnJheSwgb3B0X29wdGlvbnMpIHtcblxuICAgIHN1cGVyKCk7XG5cbiAgICBjb25zdCBvcHRpb25zID0gb3B0X29wdGlvbnMgfHwge307XG5cbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuICAgIHRoaXMudW5pcXVlXyA9IEJvb2xlYW4ob3B0aW9ucy51bmlxdWUpO1xuXG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7IUFycmF5PFQ+fVxuICAgICAqL1xuICAgIHRoaXMuYXJyYXlfID0gb3B0X2FycmF5ID8gb3B0X2FycmF5IDogW107XG5cbiAgICBpZiAodGhpcy51bmlxdWVfKSB7XG4gICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSB0aGlzLmFycmF5Xy5sZW5ndGg7IGkgPCBpaTsgaSArPSAxKSB7XG4gICAgICAgIHRoaXMuYXNzZXJ0VW5pcXVlXyh0aGlzLmFycmF5X1tpXSwgaSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy51cGRhdGVMZW5ndGhfKCk7XG5cbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgYWxsIGVsZW1lbnRzIGZyb20gdGhlIGNvbGxlY3Rpb24uXG4gICAqIEBhcGlcbiAgICovXG4gIGNsZWFyKCkge1xuICAgIHdoaWxlICh0aGlzLmdldExlbmd0aCgpID4gMCkge1xuICAgICAgdGhpcy5wb3AoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQWRkIGVsZW1lbnRzIHRvIHRoZSBjb2xsZWN0aW9uLiAgVGhpcyBwdXNoZXMgZWFjaCBpdGVtIGluIHRoZSBwcm92aWRlZCBhcnJheVxuICAgKiB0byB0aGUgZW5kIG9mIHRoZSBjb2xsZWN0aW9uLlxuICAgKiBAcGFyYW0geyFBcnJheTxUPn0gYXJyIEFycmF5LlxuICAgKiBAcmV0dXJuIHttb2R1bGU6c2Fpai9jb3JlL0NvbGxlY3Rpb248VD59IFRoaXMgY29sbGVjdGlvbi5cbiAgICogQGFwaVxuICAgKi9cbiAgZXh0ZW5kKGFycikge1xuICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGFyci5sZW5ndGg7IGkgPCBpaTsgaSArPSAxKSB7XG4gICAgICB0aGlzLnB1c2goYXJyW2ldKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogSXRlcmF0ZSBvdmVyIGVhY2ggZWxlbWVudCwgY2FsbGluZyB0aGUgcHJvdmlkZWQgY2FsbGJhY2suXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oVCwgbnVtYmVyLCBBcnJheTxUPik6ICp9IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGNhbGxcbiAgICogICAgIGZvciBldmVyeSBlbGVtZW50LiBUaGlzIGZ1bmN0aW9uIHRha2VzIDMgYXJndW1lbnRzICh0aGUgZWxlbWVudCwgdGhlXG4gICAqICAgICBpbmRleCBhbmQgdGhlIGFycmF5KS4gVGhlIHJldHVybiB2YWx1ZSBpcyBpZ25vcmVkLlxuICAgKiBAYXBpXG4gICAqL1xuICBmb3JFYWNoKGZ1bmMpIHtcbiAgICBjb25zdCBhcnJheSA9IHRoaXMuYXJyYXlfO1xuICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGFycmF5Lmxlbmd0aDsgaSA8IGlpOyBpICs9IDEpIHtcbiAgICAgIGZ1bmMoYXJyYXlbaV0sIGksIGFycmF5KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0IGEgcmVmZXJlbmNlIHRvIHRoZSB1bmRlcmx5aW5nIEFycmF5IG9iamVjdC4gV2FybmluZzogaWYgdGhlIGFycmF5XG4gICAqIGlzIG11dGF0ZWQsIG5vIGV2ZW50cyB3aWxsIGJlIGRpc3BhdGNoZWQgYnkgdGhlIGNvbGxlY3Rpb24sIGFuZCB0aGVcbiAgICogY29sbGVjdGlvbidzIFwibGVuZ3RoXCIgcHJvcGVydHkgd29uJ3QgYmUgaW4gc3luYyB3aXRoIHRoZSBhY3R1YWwgbGVuZ3RoXG4gICAqIG9mIHRoZSBhcnJheS5cbiAgICogQHJldHVybiB7IUFycmF5PFQ+fSBBcnJheS5cbiAgICogQGFwaVxuICAgKi9cbiAgZ2V0QXJyYXkoKSB7XG4gICAgcmV0dXJuIHRoaXMuYXJyYXlfO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgZWxlbWVudCBhdCB0aGUgcHJvdmlkZWQgaW5kZXguXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBpbmRleCBJbmRleC5cbiAgICogQHJldHVybiB7VH0gRWxlbWVudC5cbiAgICogQGFwaVxuICAgKi9cbiAgaXRlbShpbmRleCkge1xuICAgIHJldHVybiB0aGlzLmFycmF5X1tpbmRleF07XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBsZW5ndGggb2YgdGhpcyBjb2xsZWN0aW9uLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IFRoZSBsZW5ndGggb2YgdGhlIGFycmF5LlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuICBnZXRMZW5ndGgoKSB7XG4gICAgcmV0dXJuIC8qKiBAdHlwZSB7bnVtYmVyfSAqLyAodGhpcy5nZXQoUHJvcGVydHkuTEVOR1RIKSk7XG4gIH1cblxuICAvKipcbiAgICogSW5zZXJ0IGFuIGVsZW1lbnQgYXQgdGhlIHByb3ZpZGVkIGluZGV4LlxuICAgKiBAcGFyYW0ge251bWJlcn0gaW5kZXggSW5kZXguXG4gICAqIEBwYXJhbSB7VH0gZWxlbSBFbGVtZW50LlxuICAgKiBAYXBpXG4gICAqL1xuICBpbnNlcnRBdChpbmRleCwgZWxlbSkge1xuICAgIGlmICh0aGlzLnVuaXF1ZV8pIHtcbiAgICAgIHRoaXMuYXNzZXJ0VW5pcXVlXyhlbGVtKTtcbiAgICB9XG4gICAgdGhpcy5hcnJheV8uc3BsaWNlKGluZGV4LCAwLCBlbGVtKTtcbiAgICB0aGlzLnVwZGF0ZUxlbmd0aF8oKTtcbiAgICB0aGlzLmRpc3BhdGNoRXZlbnQoXG4gICAgICBuZXcgQ29sbGVjdGlvbkV2ZW50KENvbGxlY3Rpb25FdmVudFR5cGUuQURELCBlbGVtKSk7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlIHRoZSBsYXN0IGVsZW1lbnQgb2YgdGhlIGNvbGxlY3Rpb24gYW5kIHJldHVybiBpdC5cbiAgICogUmV0dXJuIGB1bmRlZmluZWRgIGlmIHRoZSBjb2xsZWN0aW9uIGlzIGVtcHR5LlxuICAgKiBAcmV0dXJuIHtUfHVuZGVmaW5lZH0gRWxlbWVudC5cbiAgICogQGFwaVxuICAgKi9cbiAgcG9wKCkge1xuICAgIHJldHVybiB0aGlzLnJlbW92ZUF0KHRoaXMuZ2V0TGVuZ3RoKCkgLSAxKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbnNlcnQgdGhlIHByb3ZpZGVkIGVsZW1lbnQgYXQgdGhlIGVuZCBvZiB0aGUgY29sbGVjdGlvbi5cbiAgICogQHBhcmFtIHtUfSBlbGVtIEVsZW1lbnQuXG4gICAqIEByZXR1cm4ge251bWJlcn0gTmV3IGxlbmd0aCBvZiB0aGUgY29sbGVjdGlvbi5cbiAgICogQGFwaVxuICAgKi9cbiAgcHVzaChlbGVtKSB7XG4gICAgaWYgKHRoaXMudW5pcXVlXykge1xuICAgICAgdGhpcy5hc3NlcnRVbmlxdWVfKGVsZW0pO1xuICAgIH1cbiAgICBjb25zdCBsZW4gPSB0aGlzLmdldExlbmd0aCgpO1xuICAgIHRoaXMuaW5zZXJ0QXQobGVuLCBlbGVtKTtcbiAgICByZXR1cm4gdGhpcy5nZXRMZW5ndGgoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgYW4gZWxlbWVudCBmcm9tIHRoZSBjb2xsZWN0aW9uLlxuICAgKiBAcGFyYW0ge1R9IGVsZW0gRWxlbWVudC5cbiAgICogQHJldHVybiB7VHx1bmRlZmluZWR9IFRoZSByZW1vdmVkIGVsZW1lbnQgb3IgdW5kZWZpbmVkIGlmIG5vbmUgZm91bmQuXG4gICAqIEBhcGlcbiAgICovXG4gIHJlbW92ZShlbGVtKSB7XG4gICAgY29uc3QgYXJyID0gdGhpcy5hcnJheV87XG4gICAgZm9yIChsZXQgaSA9IDAsIGlpID0gYXJyLmxlbmd0aDsgaSA8IGlpOyBpICs9IDEpIHtcbiAgICAgIGlmIChhcnJbaV0gPT09IGVsZW0pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVtb3ZlQXQoaSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlIHRoZSBlbGVtZW50IGF0IHRoZSBwcm92aWRlZCBpbmRleCBhbmQgcmV0dXJuIGl0LlxuICAgKiBSZXR1cm4gYHVuZGVmaW5lZGAgaWYgdGhlIGNvbGxlY3Rpb24gZG9lcyBub3QgY29udGFpbiB0aGlzIGluZGV4LlxuICAgKiBAcGFyYW0ge251bWJlcn0gaW5kZXggSW5kZXguXG4gICAqIEByZXR1cm4ge1R8dW5kZWZpbmVkfSBWYWx1ZS5cbiAgICogQGFwaVxuICAgKi9cbiAgcmVtb3ZlQXQoaW5kZXgpIHtcbiAgICBjb25zdCBwcmV2ID0gdGhpcy5hcnJheV9baW5kZXhdO1xuICAgIHRoaXMuYXJyYXlfLnNwbGljZShpbmRleCwgMSk7XG4gICAgdGhpcy51cGRhdGVMZW5ndGhfKCk7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBDb2xsZWN0aW9uRXZlbnQoQ29sbGVjdGlvbkV2ZW50VHlwZS5SRU1PVkUsIHByZXYpKTtcbiAgICByZXR1cm4gcHJldjtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgdGhlIGVsZW1lbnQgYXQgdGhlIHByb3ZpZGVkIGluZGV4LlxuICAgKiBAcGFyYW0ge251bWJlcn0gaW5kZXggSW5kZXguXG4gICAqIEBwYXJhbSB7VH0gZWxlbSBFbGVtZW50LlxuICAgKiBAYXBpXG4gICAqL1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbWF4LXN0YXRlbWVudHNcbiAgc2V0QXQoaW5kZXgsIGVsZW0pIHtcbiAgICBjb25zdCBsZW4gPSB0aGlzLmdldExlbmd0aCgpO1xuICAgIGlmIChpbmRleCA8IGxlbikge1xuICAgICAgaWYgKHRoaXMudW5pcXVlXykge1xuICAgICAgICB0aGlzLmFzc2VydFVuaXF1ZV8oZWxlbSwgaW5kZXgpO1xuICAgICAgfVxuICAgICAgY29uc3QgcHJldiA9IHRoaXMuYXJyYXlfW2luZGV4XTtcbiAgICAgIHRoaXMuYXJyYXlfW2luZGV4XSA9IGVsZW07XG4gICAgICB0aGlzLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgIG5ldyBDb2xsZWN0aW9uRXZlbnQoQ29sbGVjdGlvbkV2ZW50VHlwZS5SRU1PVkUsIHByZXYpKTtcbiAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgbmV3IENvbGxlY3Rpb25FdmVudChDb2xsZWN0aW9uRXZlbnRUeXBlLkFERCwgZWxlbSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBmb3IgKGxldCBqID0gbGVuOyBqIDwgaW5kZXg7IGogKz0gMSkge1xuICAgICAgICB0aGlzLmluc2VydEF0KGosIHVuZGVmaW5lZCk7XG4gICAgICB9XG4gICAgICB0aGlzLmluc2VydEF0KGluZGV4LCBlbGVtKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHVwZGF0ZUxlbmd0aF8oKSB7XG4gICAgdGhpcy5zZXQoUHJvcGVydHkuTEVOR1RILCB0aGlzLmFycmF5Xy5sZW5ndGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7VH0gZWxlbSBFbGVtZW50LlxuICAgKiBAcGFyYW0ge251bWJlcj19IG9wdF9leGNlcHQgT3B0aW9uYWwgaW5kZXggdG8gaWdub3JlLlxuICAgKi9cbiAgYXNzZXJ0VW5pcXVlXyhlbGVtLCBvcHRfZXhjZXB0KSB7XG4gICAgZm9yIChsZXQgaSA9IDAsIGlpID0gdGhpcy5hcnJheV8ubGVuZ3RoOyBpIDwgaWk7IGkgKz0gMSkge1xuICAgICAgaWYgKHRoaXMuYXJyYXlfW2ldID09PSBlbGVtICYmIGkgIT09IG9wdF9leGNlcHQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEFzc2VydGlvbkVycm9yKEVycm9ycy5BU1NFUlRfVU5JUVVFLmNvZGUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5cbmV4cG9ydCBkZWZhdWx0IENvbGxlY3Rpb247XG4iXX0=