UNPKG

@tripsnek/tmf

Version:

TypeScript Modeling Framework - A TypeScript port of the Eclipse Modeling Framework (EMF)

266 lines 31.1 kB
/** * Default implementation for all TMF Lists, and hence all * multi-valued fields. * * This implementation wraps around a simple Javascript Array. */ export class BasicEList { //set when the list belongs to an EObject owner; eFeatureId; //set when a feature on objects in the list points back to the list owningEObject inverseEFeatureID; //the underlying array containing all List elements _elements = []; constructor(elems, owner, featID, inverseFeatID) { this.owner = owner; this.eFeatureId = featID; this.inverseEFeatureID = inverseFeatID; if (elems) this._elements = [...elems]; } add(item, index) { //if there is an inverse reference (container or eopposite), the list must be unique if (!this.hasInverseFeature() || !this.contains(item)) { this.basicAdd(item, index); if (this.hasInverseFeature()) { this.inverseAdd(item); } } } //should only be used for new objects with no existing container (optimization) //may provide modest performance boost in certain cases fastContainmentAddHack(item) { this._elements.push(item); item['_eContainer'] = this.owner; item['_eContainingFeature'] = this.eFeatureId; } basicAdd(item, index) { if (!index && index !== 0) this._elements.push(item); else this._elements.splice(index, 0, item); } inverseAdd(item) { //handle containment inverse references (TODO: Should this be handled by the item's eInverseAdd?) if (this.isContainment()) { item.setEContainer(this.owner, this.eFeatureId); } //handle inverse references (which may also be explicit references to the container) if (this.inverseEFeatureID) { //Remove from existing EOpposite, if it is single-valued (many-many eopposites do not need to be removed) const inverseFeature = item .eClass() .getEStructuralFeature(this.inverseEFeatureID); if (!inverseFeature?.isMany()) { const curOpposite = item.eGet(inverseFeature); if (curOpposite) { curOpposite.eInverseRemove(item, this.eFeatureId); } } item.eInverseAdd(this.owner, this.inverseEFeatureID); } } remove(item) { if (item) { //remove item from the array const removed = this.basicRemove(item); //only proceed with inverse removal if removal was successful if (removed && this.hasInverseFeature()) { this.inverseRemove(item); } } } basicRemove(item) { let removed = false; this._elements.forEach((arrItem, index) => { if (item === arrItem) { this._elements.splice(index, 1); removed = true; } }); return removed; } inverseRemove(item) { //only directly set container to null if there is no inverse feature if (this.isContainment() && !this.inverseEFeatureID) { item.setEContainer(undefined, undefined); } //otherwise, do an inverse remove on the field (whether it is a container or not) else { item.eInverseRemove(this.owner, this.inverseEFeatureID); } } containsAll(c) { throw new Error('Method not implemented.'); } addAll(list) { if (Array.isArray(list)) { for (let i = 0; i < list.length; i++) { this.add(list[i]); } } else { // For other iterables, convert to array first const items = Array.from(list); for (let i = 0; i < items.length; i++) { this.add(items[i]); } } } equals(o) { throw new Error('Method not implemented.'); } size() { return this._elements.length; } isEmpty() { return this._elements.length === 0; } contains(o) { for (const obj of this._elements) { if (o === obj) return true; } return false; } get(index) { return this._elements[index]; } set(index, element) { if (!this.hasInverseFeature() && !this.isContainment()) { this._elements[index] = element; return element; } //TODO: This method MUST handle inverse references else { throw new Error('BasicEList.set(index,element) not implemented for EReferences with containment or inverses.'); } } /** * Indicate whether this list represents a containment relationship * between the list owningEObject and the list contents. */ isContainment() { if (!this.eFeatureId || !this.owner) return false; else { const feature = this.owner .eClass() .getEStructuralFeature(this.eFeatureId); if (!feature) { return false; } //return feature instanceof EReferenceImpl && feature.isContainment(); return feature.isContainment(); } } indexOf(o) { let idx = 0; for (const element of this._elements) { if (element === o) return idx; idx++; } return -1; } lastIndexOf(o) { throw new Error('Method not implemented.'); } removeAll(list) { const startSize = this.size(); if (Array.isArray(list)) { for (let i = 0; i < list.length; i++) { this.remove(list[i]); } } else { // For other iterables, convert to array first const items = Array.from(list); for (let i = 0; i < items.length; i++) { this.remove(items[i]); } } return startSize !== this.size(); } clear() { this.removeAll(Object.assign([], this._elements)); } //implementation of Iterable interface - simply returns the iterator for the wrapped array [Symbol.iterator]() { return this._elements[Symbol.iterator](); } /** * Indicates whether objects in the list have a feature which refers * back to this list's owningEObject. */ hasInverseFeature() { if (this.inverseEFeatureID || this.isContainment()) return true; return false; } //====================================================================== // TMF-specific methods (to work better with TypeScript) /** * Swaps the elements at the given positions, if they exist. * @param idx1 * @param idx2 */ swap(idx1, idx2) { if (this._elements.length > idx1 && this._elements.length > idx2) { const temp = this._elements[idx1]; this._elements[idx1] = this._elements[idx2]; this._elements[idx2] = temp; } } /** * Returns a new native TypeScript Array of the EList's elements */ elements() { const size = this.size(); const result = new Array(size); for (let i = 0; i < size; i++) { result[i] = this.get(i); } return result; } filter(predicate, thisArg) { const result = new BasicEList(); for (const element of this._elements.filter(predicate)) { result.add(element); } return result; } forEach(callbackfn, thisArg) { return this._elements.forEach(callbackfn, thisArg); } find(predicate, thisArg) { return this._elements.find(predicate); } some(arg0) { return this._elements.some(arg0); } map(func, thisArg) { const result = new BasicEList(); for (const element of this._elements.map(func)) { result.add(element); } return result; } last() { if (this._elements.length == 0) return undefined; return this._elements.slice(-1)[0]; } /** * Removes the last element of the List and returns it. */ pop() { if (this.size() === 0) return undefined; const popped = this.get(this.size() - 1); this.remove(popped); return popped; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzaWNlbGlzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvbWV0YW1vZGVsL2Jhc2ljZWxpc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBR0E7Ozs7O0dBS0c7QUFDSCxNQUFNLE9BQU8sVUFBVTtJQUNyQix5Q0FBeUM7SUFDakMsS0FBSyxDQUFXO0lBQ2hCLFVBQVUsQ0FBUztJQUUzQixpRkFBaUY7SUFDekUsaUJBQWlCLENBQVM7SUFFbEMsbURBQW1EO0lBQzNDLFNBQVMsR0FBUSxFQUFFLENBQUM7SUFFNUIsWUFDRSxLQUFXLEVBQ1gsS0FBZSxFQUNmLE1BQWUsRUFDZixhQUFzQjtRQUV0QixJQUFJLENBQUMsS0FBSyxHQUFHLEtBQU0sQ0FBQztRQUNwQixJQUFJLENBQUMsVUFBVSxHQUFHLE1BQU8sQ0FBQztRQUMxQixJQUFJLENBQUMsaUJBQWlCLEdBQUcsYUFBYyxDQUFDO1FBQ3hDLElBQUksS0FBSztZQUFFLElBQUksQ0FBQyxTQUFTLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDO0lBQ3pDLENBQUM7SUFFTSxHQUFHLENBQUMsSUFBTyxFQUFFLEtBQWM7UUFDaEMsb0ZBQW9GO1FBQ3BGLElBQUksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUN0RCxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztZQUMzQixJQUFJLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxFQUFFLENBQUM7Z0JBQzdCLElBQUksQ0FBQyxVQUFVLENBQW9CLElBQUssQ0FBQyxDQUFDO1lBQzVDLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVELCtFQUErRTtJQUMvRSx1REFBdUQ7SUFDaEQsc0JBQXNCLENBQUMsSUFBTztRQUNuQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJ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QUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDekMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNwQixPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBFTGlzdCB9IGZyb20gJy4vYXBpL2VsaXN0LmpzJztcclxuaW1wb3J0IHsgRU9iamVjdCB9IGZyb20gJy4vYXBpL2VvYmplY3QuanMnO1xyXG5cclxuLyoqXHJcbiAqIERlZmF1bHQgaW1wbGVtZW50YXRpb24gZm9yIGFsbCBUTUYgTGlzdHMsIGFuZCBoZW5jZSBhbGxcclxuICogbXVsdGktdmFsdWVkIGZpZWxkcy5cclxuICpcclxuICogVGhpcyBpbXBsZW1lbnRhdGlvbiB3cmFwcyBhcm91bmQgYSBzaW1wbGUgSmF2YXNjcmlwdCBBcnJheS5cclxuICovXHJcbmV4cG9ydCBjbGFzcyBCYXNpY0VMaXN0PFQ+IGltcGxlbWVudHMgRUxpc3Q8VD4ge1xyXG4gIC8vc2V0IHdoZW4gdGhlIGxpc3QgYmVsb25ncyB0byBhbiBFT2JqZWN0XHJcbiAgcHJpdmF0ZSBvd25lciE6IEVPYmplY3Q7XHJcbiAgcHJpdmF0ZSBlRmVhdHVyZUlkOiBudW1iZXI7XHJcblxyXG4gIC8vc2V0IHdoZW4gYSBmZWF0dXJlIG9uIG9iamVjdHMgaW4gdGhlIGxpc3QgcG9pbnRzIGJhY2sgdG8gdGhlIGxpc3Qgb3duaW5nRU9iamVjdFxyXG4gIHByaXZhdGUgaW52ZXJzZUVGZWF0dXJlSUQ6IG51bWJlcjtcclxuXHJcbiAgLy90aGUgdW5kZXJseWluZyBhcnJheSBjb250YWluaW5nIGFsbCBMaXN0IGVsZW1lbnRzXHJcbiAgcHJpdmF0ZSBfZWxlbWVudHM6IFRbXSA9IFtdO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIGVsZW1zPzogVFtdLFxyXG4gICAgb3duZXI/OiBFT2JqZWN0LFxyXG4gICAgZmVhdElEPzogbnVtYmVyLFxyXG4gICAgaW52ZXJzZUZlYXRJRD86IG51bWJlclxyXG4gICkge1xyXG4gICAgdGhpcy5vd25lciA9IG93bmVyITtcclxuICAgIHRoaXMuZUZlYXR1cmVJZCA9IGZlYXRJRCE7XHJcbiAgICB0aGlzLmludmVyc2VFRmVhdHVyZUlEID0gaW52ZXJzZUZlYXRJRCE7XHJcbiAgICBpZiAoZWxlbXMpIHRoaXMuX2VsZW1lbnRzID0gWy4uLmVsZW1zXTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBhZGQoaXRlbTogVCwgaW5kZXg/OiBudW1iZXIpOiB2b2lkIHtcclxuICAgIC8vaWYgdGhlcmUgaXMgYW4gaW52ZXJzZSByZWZlcmVuY2UgKGNvbnRhaW5lciBvciBlb3Bwb3NpdGUpLCB0aGUgbGlzdCBtdXN0IGJlIHVuaXF1ZVxyXG4gICAgaWYgKCF0aGlzLmhhc0ludmVyc2VGZWF0dXJlKCkgfHwgIXRoaXMuY29udGFpbnMoaXRlbSkpIHtcclxuICAgICAgdGhpcy5iYXNpY0FkZChpdGVtLCBpbmRleCk7XHJcbiAgICAgIGlmICh0aGlzLmhhc0ludmVyc2VGZWF0dXJlKCkpIHtcclxuICAgICAgICB0aGlzLmludmVyc2VBZGQoPEVPYmplY3Q+KDx1bmtub3duPml0ZW0pKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy9zaG91bGQgb25seSBiZSB1c2VkIGZvciBuZXcgb2JqZWN0cyB3aXRoIG5vIGV4aXN0aW5nIGNvbnRhaW5lciAob3B0aW1pemF0aW9uKVxyXG4gIC8vbWF5IHByb3ZpZGUgbW9kZXN0IHBlcmZvcm1hbmNlIGJvb3N0IGluIGNlcnRhaW4gY2FzZXNcclxuICBwdWJsaWMgZmFzdENvbnRhaW5tZW50QWRkSGFjayhpdGVtOiBUKTogdm9pZCB7XHJcbiAgICB0aGlzLl9lbGVtZW50cy5wdXNoKGl0ZW0pO1xyXG4gICAgKGl0ZW0gYXMgYW55KVsnX2VDb250YWluZXInXSA9IHRoaXMub3duZXI7XHJcbiAgICAoaXRlbSBhcyBhbnkpWydfZUNvbnRhaW5pbmdGZWF0dXJlJ10gPSB0aGlzLmVGZWF0dXJlSWQ7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYmFzaWNBZGQoaXRlbTogVCwgaW5kZXg/OiBudW1iZXIpOiB2b2lkIHtcclxuICAgIGlmICghaW5kZXggJiYgaW5kZXggIT09IDApIHRoaXMuX2VsZW1lbnRzLnB1c2goaXRlbSk7XHJcbiAgICBlbHNlIHRoaXMuX2VsZW1lbnRzLnNwbGljZShpbmRleCwgMCwgaXRlbSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGludmVyc2VBZGQoaXRlbTogRU9iamVjdCk6IHZvaWQge1xyXG4gICAgLy9oYW5kbGUgY29udGFpbm1lbnQgaW52ZXJzZSByZWZlcmVuY2VzIChUT0RPOiBTaG91bGQgdGhpcyBiZSBoYW5kbGVkIGJ5IHRoZSBpdGVtJ3MgZUludmVyc2VBZGQ/KVxyXG4gICAgaWYgKHRoaXMuaXNDb250YWlubWVudCgpKSB7XHJcbiAgICAgIGl0ZW0uc2V0RUNvbnRhaW5lcih0aGlzLm93bmVyLCB0aGlzLmVGZWF0dXJlSWQpO1xyXG4gICAgfVxyXG4gICAgLy9oYW5kbGUgaW52ZXJzZSByZWZlcmVuY2VzICh3aGljaCBtYXkgYWxzbyBiZSBleHBsaWNpdCByZWZlcmVuY2VzIHRvIHRoZSBjb250YWluZXIpXHJcbiAgICBpZiAodGhpcy5pbnZlcnNlRUZlYXR1cmVJRCkge1xyXG4gICAgICAvL1JlbW92ZSBmcm9tIGV4aXN0aW5nIEVPcHBvc2l0ZSwgaWYgaXQgaXMgc2luZ2xlLXZhbHVlZCAobWFueS1tYW55IGVvcHBvc2l0ZXMgZG8gbm90IG5lZWQgdG8gYmUgcmVtb3ZlZClcclxuICAgICAgY29uc3QgaW52ZXJzZUZlYXR1cmUgPSBpdGVtXHJcbiAgICAgICAgLmVDbGFzcygpXHJcbiAgICAgICAgLmdldEVTdHJ1Y3R1cmFsRmVhdHVyZSh0aGlzLmludmVyc2VFRmVhdHVyZUlEKTtcclxuICAgICAgaWYgKCFpbnZlcnNlRmVhdHVyZT8uaXNNYW55KCkpIHtcclxuICAgICAgICBjb25zdCBjdXJPcHBvc2l0ZSA9IGl0ZW0uZUdldChpbnZlcnNlRmVhdHVyZSEpO1xyXG4gICAgICAgIGlmIChjdXJPcHBvc2l0ZSkge1xyXG4gICAgICAgICAgY3VyT3Bwb3NpdGUuZUludmVyc2VSZW1vdmUoaXRlbSwgdGhpcy5lRmVhdHVyZUlkKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgaXRlbS5lSW52ZXJzZUFkZCh0aGlzLm93bmVyLCB0aGlzLmludmVyc2VFRmVhdHVyZUlEKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHB1YmxpYyByZW1vdmUoaXRlbT86IFQpIHtcclxuICAgIGlmIChpdGVtKSB7XHJcbiAgICAgIC8vcmVtb3ZlIGl0ZW0gZnJvbSB0aGUgYXJyYXlcclxuICAgICAgY29uc3QgcmVtb3ZlZCA9IHRoaXMuYmFzaWNSZW1vdmUoaXRlbSk7XHJcbiAgICAgIC8vb25seSBwcm9jZWVkIHdpdGggaW52ZXJzZSByZW1vdmFsIGlmIHJlbW92YWwgd2FzIHN1Y2Nlc3NmdWxcclxuICAgICAgaWYgKHJlbW92ZWQgJiYgdGhpcy5oYXNJbnZlcnNlRmVhdHVyZSgpKSB7XHJcbiAgICAgICAgdGhpcy5pbnZlcnNlUmVtb3ZlKDxFT2JqZWN0Pig8dW5rbm93bj5pdGVtKSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIHB1YmxpYyBiYXNpY1JlbW92ZShpdGVtOiBUKSB7XHJcbiAgICBsZXQgcmVtb3ZlZCA9IGZhbHNlO1xyXG4gICAgdGhpcy5fZWxlbWVudHMuZm9yRWFjaCgoYXJySXRlbSwgaW5kZXgpID0+IHtcclxuICAgICAgaWYgKGl0ZW0gPT09IGFyckl0ZW0pIHtcclxuICAgICAgICB0aGlzLl9lbGVtZW50cy5zcGxpY2UoaW5kZXgsIDEpO1xyXG4gICAgICAgIHJlbW92ZWQgPSB0cnVlO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICAgIHJldHVybiByZW1vdmVkO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBpbnZlcnNlUmVtb3ZlKGl0ZW06IEVPYmplY3QpOiB2b2lkIHtcclxuICAgIC8vb25seSBkaXJlY3RseSBzZXQgY29udGFpbmVyIHRvIG51bGwgaWYgdGhlcmUgaXMgbm8gaW52ZXJzZSBmZWF0dXJlXHJcbiAgICBpZiAodGhpcy5pc0NvbnRhaW5tZW50KCkgJiYgIXRoaXMuaW52ZXJzZUVGZWF0dXJlSUQpIHtcclxuICAgICAgaXRlbS5zZXRFQ29udGFpbmVyKHVuZGVmaW5lZCwgdW5kZWZpbmVkKTtcclxuICAgIH1cclxuICAgIC8vb3RoZXJ3aXNlLCBkbyBhbiBpbnZlcnNlIHJlbW92ZSBvbiB0aGUgZmllbGQgKHdoZXRoZXIgaXQgaXMgYSBjb250YWluZXIgb3Igbm90KVxyXG4gICAgZWxzZSB7XHJcbiAgICAgIGl0ZW0uZUludmVyc2VSZW1vdmUodGhpcy5vd25lciwgdGhpcy5pbnZlcnNlRUZlYXR1cmVJRCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgY29udGFpbnNBbGwoYzogRUxpc3Q8YW55Pik6IGJvb2xlYW4ge1xyXG4gICAgdGhyb3cgbmV3IEVycm9yKCdNZXRob2Qgbm90IGltcGxlbWVudGVkLicpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGFkZEFsbChsaXN0OiBJdGVyYWJsZTxUPikge1xyXG4gICAgaWYgKEFycmF5LmlzQXJyYXkobGlzdCkpIHtcclxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgdGhpcy5hZGQobGlzdFtpXSk7XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIEZvciBvdGhlciBpdGVyYWJsZXMsIGNvbnZlcnQgdG8gYXJyYXkgZmlyc3RcclxuICAgICAgY29uc3QgaXRlbXMgPSBBcnJheS5mcm9tKGxpc3QpO1xyXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGl0ZW1zLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgdGhpcy5hZGQoaXRlbXNbaV0gYXMgVCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIHB1YmxpYyBlcXVhbHMobzogT2JqZWN0KTogYm9vbGVhbiB7XHJcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01ldGhvZCBub3QgaW1wbGVtZW50ZWQuJyk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgc2l6ZSgpOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIHRoaXMuX2VsZW1lbnRzLmxlbmd0aDtcclxuICB9XHJcbiAgcHVibGljIGlzRW1wdHkoKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdGhpcy5fZWxlbWVudHMubGVuZ3RoID09PSAwO1xyXG4gIH1cclxuICBwdWJsaWMgY29udGFpbnMobzogVCk6IGJvb2xlYW4ge1xyXG4gICAgZm9yIChjb25zdCBvYmogb2YgdGhpcy5fZWxlbWVudHMpIHtcclxuICAgICAgaWYgKG8gPT09IG9iaikgcmV0dXJuIHRydWU7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgZ2V0KGluZGV4OiBudW1iZXIpOiBUIHtcclxuICAgIHJldHVybiB0aGlzLl9lbGVtZW50c1tpbmRleF0gYXMgVDtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBzZXQoaW5kZXg6IG51bWJlciwgZWxlbWVudDogVCk6IFQge1xyXG4gICAgaWYgKCF0aGlzLmhhc0ludmVyc2VGZWF0dXJlKCkgJiYgIXRoaXMuaXNDb250YWlubWVudCgpKSB7XHJcbiAgICAgIHRoaXMuX2VsZW1lbnRzW2luZGV4XSA9IGVsZW1lbnQ7XHJcbiAgICAgIHJldHVybiBlbGVtZW50O1xyXG4gICAgfVxyXG4gICAgLy9UT0RPOiBUaGlzIG1ldGhvZCBNVVNUIGhhbmRsZSBpbnZlcnNlIHJlZmVyZW5jZXNcclxuICAgIGVsc2Uge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXHJcbiAgICAgICAgJ0Jhc2ljRUxpc3Quc2V0KGluZGV4LGVsZW1lbnQpIG5vdCBpbXBsZW1lbnRlZCBmb3IgRVJlZmVyZW5jZXMgd2l0aCBjb250YWlubWVudCBvciBpbnZlcnNlcy4nXHJcbiAgICAgICk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBJbmRpY2F0ZSB3aGV0aGVyIHRoaXMgbGlzdCByZXByZXNlbnRzIGEgY29udGFpbm1lbnQgcmVsYXRpb25zaGlwXHJcbiAgICogYmV0d2VlbiB0aGUgbGlzdCBvd25pbmdFT2JqZWN0IGFuZCB0aGUgbGlzdCBjb250ZW50cy5cclxuICAgKi9cclxuICBwcml2YXRlIGlzQ29udGFpbm1lbnQoKTogYm9vbGVhbiB7XHJcbiAgICBpZiAoIXRoaXMuZUZlYXR1cmVJZCB8fCAhdGhpcy5vd25lcikgcmV0dXJuIGZhbHNlO1xyXG4gICAgZWxzZSB7XHJcbiAgICAgIGNvbnN0IGZlYXR1cmUgPSB0aGlzLm93bmVyXHJcbiAgICAgICAgLmVDbGFzcygpXHJcbiAgICAgICAgLmdldEVTdHJ1Y3R1cmFsRmVhdHVyZSh0aGlzLmVGZWF0dXJlSWQpO1xyXG4gICAgICBpZiAoIWZlYXR1cmUpIHtcclxuICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgIH1cclxuICAgICAgLy9yZXR1cm4gZmVhdHVyZSBpbnN0YW5jZW9mIEVSZWZlcmVuY2VJbXBsICYmIGZlYXR1cmUuaXNDb250YWlubWVudCgpO1xyXG4gICAgICByZXR1cm4gZmVhdHVyZS5pc0NvbnRhaW5tZW50KCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgaW5kZXhPZihvOiBUKTogbnVtYmVyIHtcclxuICAgIGxldCBpZHggPSAwO1xyXG4gICAgZm9yIChjb25zdCBlbGVtZW50IG9mIHRoaXMuX2VsZW1lbnRzKSB7XHJcbiAgICAgIGlmIChlbGVtZW50ID09PSBvKSByZXR1cm4gaWR4O1xyXG4gICAgICBpZHgrKztcclxuICAgIH1cclxuICAgIHJldHVybiAtMTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBsYXN0SW5kZXhPZihvOiBPYmplY3QpOiBudW1iZXIge1xyXG4gICAgdGhyb3cgbmV3IEVycm9yKCdNZXRob2Qgbm90IGltcGxlbWVudGVkLicpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHJlbW92ZUFsbChsaXN0OiBJdGVyYWJsZTxUPik6IGJvb2xlYW4ge1xyXG4gICAgY29uc3Qgc3RhcnRTaXplID0gdGhpcy5zaXplKCk7XHJcbiAgICBpZiAoQXJyYXkuaXNBcnJheShsaXN0KSkge1xyXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICB0aGlzLnJlbW92ZShsaXN0W2ldKTtcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gRm9yIG90aGVyIGl0ZXJhYmxlcywgY29udmVydCB0byBhcnJheSBmaXJzdFxyXG4gICAgICBjb25zdCBpdGVtcyA9IEFycmF5LmZyb20obGlzdCk7XHJcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaXRlbXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICB0aGlzLnJlbW92ZShpdGVtc1tpXSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBzdGFydFNpemUgIT09IHRoaXMuc2l6ZSgpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGNsZWFyKCkge1xyXG4gICAgdGhpcy5yZW1vdmVBbGwoT2JqZWN0LmFzc2lnbihbXSwgdGhpcy5fZWxlbWVudHMpKTtcclxuICB9XHJcblxyXG4gIC8vaW1wbGVtZW50YXRpb24gb2YgSXRlcmFibGUgaW50ZXJmYWNlIC0gc2ltcGx5IHJldHVybnMgdGhlIGl0ZXJhdG9yIGZvciB0aGUgd3JhcHBlZCBhcnJheVxyXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCk6IEl0ZXJhdG9yPFQ+IHtcclxuICAgIHJldHVybiB0aGlzLl9lbGVtZW50c1tTeW1ib2wuaXRlcmF0b3JdKCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBJbmRpY2F0ZXMgd2hldGhlciBvYmplY3RzIGluIHRoZSBsaXN0IGhhdmUgYSBmZWF0dXJlIHdoaWNoIHJlZmVyc1xyXG4gICAqIGJhY2sgdG8gdGhpcyBsaXN0J3Mgb3duaW5nRU9iamVjdC5cclxuICAgKi9cclxuICBwcml2YXRlIGhhc0ludmVyc2VGZWF0dXJlKCk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKHRoaXMuaW52ZXJzZUVGZWF0dXJlSUQgfHwgdGhpcy5pc0NvbnRhaW5tZW50KCkpIHJldHVybiB0cnVlO1xyXG4gICAgcmV0dXJuIGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XHJcbiAgLy8gVE1GLXNwZWNpZmljIG1ldGhvZHMgKHRvIHdvcmsgYmV0dGVyIHdpdGggVHlwZVNjcmlwdClcclxuXHJcbiAgLyoqXHJcbiAgICogU3dhcHMgdGhlIGVsZW1lbnRzIGF0IHRoZSBnaXZlbiBwb3NpdGlvbnMsIGlmIHRoZXkgZXhpc3QuXHJcbiAgICogQHBhcmFtIGlkeDFcclxuICAgKiBAcGFyYW0gaWR4MlxyXG4gICAqL1xyXG4gIHB1YmxpYyBzd2FwKGlkeDE6IG51bWJlciwgaWR4MjogbnVtYmVyKSB7XHJcbiAgICBpZiAodGhpcy5fZWxlbWVudHMubGVuZ3RoID4gaWR4MSAmJiB0aGlzLl9lbGVtZW50cy5sZW5ndGggPiBpZHgyKSB7XHJcbiAgICAgIGNvbnN0IHRlbXAgPSB0aGlzLl9lbGVtZW50c1tpZHgxXTtcclxuICAgICAgdGhpcy5fZWxlbWVudHNbaWR4MV0gPSB0aGlzLl9lbGVtZW50c1tpZHgyXSBhcyBUO1xyXG4gICAgICB0aGlzLl9lbGVtZW50c1tpZHgyXSA9IHRlbXAgYXMgVDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJldHVybnMgYSBuZXcgbmF0aXZlIFR5cGVTY3JpcHQgQXJyYXkgb2YgdGhlIEVMaXN0J3MgZWxlbWVudHNcclxuICAgKi9cclxuICBwdWJsaWMgZWxlbWVudHMoKTogVFtdIHtcclxuICAgIGNvbnN0IHNpemUgPSB0aGlzLnNpemUoKTtcclxuICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBBcnJheTxUPihzaXplKTtcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7XHJcbiAgICAgIHJlc3VsdFtpXSA9IHRoaXMuZ2V0KGkpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBmaWx0ZXIoXHJcbiAgICBwcmVkaWNhdGU6ICh2YWx1ZTogVCwgaW5kZXg6IG51bWJlciwgb2JqOiBUW10pID0+IGJvb2xlYW4sXHJcbiAgICB0aGlzQXJnPzogYW55XHJcbiAgKTogRUxpc3Q8VD4ge1xyXG4gICAgY29uc3QgcmVzdWx0ID0gbmV3IEJhc2ljRUxpc3Q8VD4oKTtcclxuICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiB0aGlzLl9lbGVtZW50cy5maWx0ZXIocHJlZGljYXRlKSkge1xyXG4gICAgICByZXN1bHQuYWRkKGVsZW1lbnQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBmb3JFYWNoKFxyXG4gICAgY2FsbGJhY2tmbjogKHZhbHVlOiBULCBpbmRleDogbnVtYmVyLCBhcnJheTogVFtdKSA9PiB2b2lkLFxyXG4gICAgdGhpc0FyZz86IGFueVxyXG4gICk6IHZvaWQge1xyXG4gICAgcmV0dXJuIHRoaXMuX2VsZW1lbnRzLmZvckVhY2goY2FsbGJhY2tmbiwgdGhpc0FyZyk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgZmluZChcclxuICAgIHByZWRpY2F0ZTogKHZhbHVlOiBULCBpbmRleDogbnVtYmVyLCBvYmo6IFRbXSkgPT4gdW5rbm93bixcclxuICAgIHRoaXNBcmc/OiBhbnlcclxuICApOiBUIHwgdW5kZWZpbmVke1xyXG4gICAgcmV0dXJuIHRoaXMuX2VsZW1lbnRzLmZpbmQocHJlZGljYXRlKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBzb21lKGFyZzA6IChlOiBhbnkpID0+IGJvb2xlYW4pOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLl9lbGVtZW50cy5zb21lKGFyZzApO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIG1hcChcclxuICAgIGZ1bmM6ICh2YWx1ZTogVCwgaW5kZXg6IG51bWJlciwgb2JqOiBUW10pID0+IGFueSxcclxuICAgIHRoaXNBcmc/OiBhbnlcclxuICApOiBFTGlzdDxhbnk+IHtcclxuICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBCYXNpY0VMaXN0PFQ+KCk7XHJcbiAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgdGhpcy5fZWxlbWVudHMubWFwKGZ1bmMpKSB7XHJcbiAgICAgIHJlc3VsdC5hZGQoZWxlbWVudCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGxhc3QoKTogVCB8IHVuZGVmaW5lZCB7XHJcbiAgICBpZiAodGhpcy5fZWxlbWVudHMubGVuZ3RoID09IDApIHJldHVybiB1bmRlZmluZWQ7XHJcbiAgICByZXR1cm4gdGhpcy5fZWxlbWVudHMuc2xpY2UoLTEpWzBdIGFzIFQ7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZW1vdmVzIHRoZSBsYXN0IGVsZW1lbnQgb2YgdGhlIExpc3QgYW5kIHJldHVybnMgaXQuXHJcbiAgICovXHJcbiAgcHVibGljIHBvcCgpOiBUIHwgdW5kZWZpbmVkIHtcclxuICAgIGlmICh0aGlzLnNpemUoKSA9PT0gMCkgcmV0dXJuIHVuZGVmaW5lZDtcclxuICAgIGNvbnN0IHBvcHBlZCA9IHRoaXMuZ2V0KHRoaXMuc2l6ZSgpIC0gMSk7XHJcbiAgICB0aGlzLnJlbW92ZShwb3BwZWQpO1xyXG4gICAgcmV0dXJuIHBvcHBlZDtcclxuICB9XHJcbn1cclxuIl19