@tripsnek/tmf
Version:
TypeScript Modeling Framework - A TypeScript port of the Eclipse Modeling Framework (EMF)
266 lines • 31.1 kB
JavaScript
/**
* 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