@catull/igniteui-angular
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
403 lines • 48.5 kB
JavaScript
import { __decorate, __extends, __read, __spread, __values } from "tslib";
import { TransactionType } from './transaction';
import { IgxBaseTransactionService } from './base-transaction';
import { EventEmitter, Injectable } from '@angular/core';
import { isObject, mergeObjects, cloneValue } from '../../core/utils';
var IgxTransactionService = /** @class */ (function (_super) {
__extends(IgxTransactionService, _super);
function IgxTransactionService() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this._transactions = [];
_this._redoStack = [];
_this._undoStack = [];
_this._states = new Map();
/**
* @inheritdoc
*/
_this.onStateUpdate = new EventEmitter();
return _this;
}
Object.defineProperty(IgxTransactionService.prototype, "canUndo", {
/**
* @inheritdoc
*/
get: function () {
return this._undoStack.length > 0;
},
enumerable: true,
configurable: true
});
Object.defineProperty(IgxTransactionService.prototype, "canRedo", {
/**
* @inheritdoc
*/
get: function () {
return this._redoStack.length > 0;
},
enumerable: true,
configurable: true
});
/**
* @inheritdoc
*/
IgxTransactionService.prototype.add = function (transaction, recordRef) {
var states = this._isPending ? this._pendingStates : this._states;
this.verifyAddedTransaction(states, transaction, recordRef);
this.addTransaction(transaction, states, recordRef);
};
IgxTransactionService.prototype.addTransaction = function (transaction, states, recordRef) {
this.updateState(states, transaction, recordRef);
var transactions = this._isPending ? this._pendingTransactions : this._transactions;
transactions.push(transaction);
if (!this._isPending) {
this._undoStack.push([{ transaction: transaction, recordRef: recordRef }]);
this._redoStack = [];
this.onStateUpdate.emit();
}
};
/**
* @inheritdoc
*/
IgxTransactionService.prototype.getTransactionLog = function (id) {
if (id !== undefined) {
return this._transactions.filter(function (t) { return t.id === id; });
}
return __spread(this._transactions);
};
/**
* @inheritdoc
*/
IgxTransactionService.prototype.getAggregatedChanges = function (mergeChanges) {
var _this = this;
var result = [];
this._states.forEach(function (state, key) {
var value = mergeChanges ? _this.mergeValues(state.recordRef, state.value) : state.value;
result.push({ id: key, newValue: value, type: state.type });
});
return result;
};
/**
* @inheritdoc
*/
IgxTransactionService.prototype.getState = function (id, pending) {
if (pending === void 0) { pending = false; }
return pending ? this._pendingStates.get(id) : this._states.get(id);
};
Object.defineProperty(IgxTransactionService.prototype, "enabled", {
/**
* @inheritdoc
*/
get: function () {
return true;
},
enumerable: true,
configurable: true
});
/**
* @inheritdoc
*/
IgxTransactionService.prototype.getAggregatedValue = function (id, mergeChanges) {
var state = this._states.get(id);
var pendingState = _super.prototype.getState.call(this, id);
// if there is no state and there is no pending state return null
if (!state && !pendingState) {
return null;
}
var pendingChange = _super.prototype.getAggregatedValue.call(this, id, false);
var change = state && state.value;
var aggregatedValue = this.mergeValues(change, pendingChange);
if (mergeChanges) {
var originalValue = state ? state.recordRef : pendingState.recordRef;
aggregatedValue = this.mergeValues(originalValue, aggregatedValue);
}
return aggregatedValue;
};
/**
* @inheritdoc
*/
IgxTransactionService.prototype.endPending = function (commit) {
var e_1, _a;
this._isPending = false;
if (commit) {
var actions = [];
try {
// don't use addTransaction due to custom undo handling
for (var _b = __values(this._pendingTransactions), _c = _b.next(); !_c.done; _c = _b.next()) {
var transaction = _c.value;
var pendingState = this._pendingStates.get(transaction.id);
this._transactions.push(transaction);
this.updateState(this._states, transaction, pendingState.recordRef);
actions.push({ transaction: transaction, recordRef: pendingState.recordRef });
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_1) throw e_1.error; }
}
this._undoStack.push(actions);
this._redoStack = [];
this.onStateUpdate.emit();
}
_super.prototype.endPending.call(this, commit);
};
/**
* @inheritdoc
*/
IgxTransactionService.prototype.commit = function (data, id) {
var _this = this;
if (id !== undefined) {
var state = this.getState(id);
if (state) {
this.updateRecord(data, state);
}
}
else {
this._states.forEach(function (s) {
_this.updateRecord(data, s);
});
}
this.clear(id);
};
/**
* @inheritdoc
*/
IgxTransactionService.prototype.clear = function (id) {
if (id !== undefined) {
this._transactions = this._transactions.filter(function (t) { return t.id !== id; });
this._states.delete(id);
// Undo stack is an array of actions. Each action is array of transaction like objects
// We are going trough all the actions. For each action we are filtering out transactions
// with provided id. Finally if any action ends up as empty array we are removing it from
// undo stack
this._undoStack = this._undoStack.map(function (a) { return a.filter(function (t) { return t.transaction.id !== id; }); }).filter(function (a) { return a.length > 0; });
}
else {
this._transactions = [];
this._states.clear();
this._undoStack = [];
}
this._redoStack = [];
this.onStateUpdate.emit();
};
/**
* @inheritdoc
*/
IgxTransactionService.prototype.undo = function () {
var e_2, _a, e_3, _b;
if (this._undoStack.length <= 0) {
return;
}
var lastActions = this._undoStack.pop();
this._transactions.splice(this._transactions.length - lastActions.length);
this._redoStack.push(lastActions);
this._states.clear();
try {
for (var _c = __values(this._undoStack), _d = _c.next(); !_d.done; _d = _c.next()) {
var currentActions = _d.value;
try {
for (var currentActions_1 = (e_3 = void 0, __values(currentActions)), currentActions_1_1 = currentActions_1.next(); !currentActions_1_1.done; currentActions_1_1 = currentActions_1.next()) {
var transaction = currentActions_1_1.value;
this.updateState(this._states, transaction.transaction, transaction.recordRef);
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (currentActions_1_1 && !currentActions_1_1.done && (_b = currentActions_1.return)) _b.call(currentActions_1);
}
finally { if (e_3) throw e_3.error; }
}
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
}
finally { if (e_2) throw e_2.error; }
}
this.onStateUpdate.emit();
};
/**
* @inheritdoc
*/
IgxTransactionService.prototype.redo = function () {
var e_4, _a;
if (this._redoStack.length > 0) {
var actions = void 0;
actions = this._redoStack.pop();
try {
for (var actions_1 = __values(actions), actions_1_1 = actions_1.next(); !actions_1_1.done; actions_1_1 = actions_1.next()) {
var action = actions_1_1.value;
this.updateState(this._states, action.transaction, action.recordRef);
this._transactions.push(action.transaction);
}
}
catch (e_4_1) { e_4 = { error: e_4_1 }; }
finally {
try {
if (actions_1_1 && !actions_1_1.done && (_a = actions_1.return)) _a.call(actions_1);
}
finally { if (e_4) throw e_4.error; }
}
this._undoStack.push(actions);
this.onStateUpdate.emit();
}
};
/**
* Verifies if the passed transaction is correct. If not throws an exception.
* @param transaction Transaction to be verified
*/
IgxTransactionService.prototype.verifyAddedTransaction = function (states, transaction, recordRef) {
var state = states.get(transaction.id);
switch (transaction.type) {
case TransactionType.ADD:
if (state) {
// cannot add same item twice
throw new Error("Cannot add this transaction. Transaction with id: " + transaction.id + " has been already added.");
}
break;
case TransactionType.DELETE:
case TransactionType.UPDATE:
if (state && state.type === TransactionType.DELETE) {
// cannot delete or update deleted items
throw new Error("Cannot add this transaction. Transaction with id: " + transaction.id + " has been already deleted.");
}
if (!state && !recordRef && !this._isPending) {
// cannot initially add transaction or delete item with no recordRef
throw new Error("Cannot add this transaction. This is first transaction of type " + transaction.type + " " +
("for id " + transaction.id + ". For first transaction of this type recordRef is mandatory."));
}
break;
}
};
/**
* Updates the provided states collection according to passed transaction and recordRef
* @param states States collection to apply the update to
* @param transaction Transaction to apply to the current state
* @param recordRef Reference to the value of the record in data source, if any, where transaction should be applied
*/
IgxTransactionService.prototype.updateState = function (states, transaction, recordRef) {
var state = states.get(transaction.id);
// if TransactionType is ADD simply add transaction to states;
// if TransactionType is DELETE:
// - if there is state with this id of type ADD remove it from the states;
// - if there is state with this id of type UPDATE change its type to DELETE;
// - if there is no state with this id add transaction to states;
// if TransactionType is UPDATE:
// - if there is state with this id of type ADD merge new value and state recordRef into state new value
// - if there is state with this id of type UPDATE merge new value into state new value
// - if there is state with this id and state type is DELETE change its type to UPDATE
// - if there is no state with this id add transaction to states;
if (state) {
switch (transaction.type) {
case TransactionType.DELETE:
if (state.type === TransactionType.ADD) {
states.delete(transaction.id);
}
else if (state.type === TransactionType.UPDATE) {
state.value = transaction.newValue;
state.type = TransactionType.DELETE;
}
break;
case TransactionType.UPDATE:
if (isObject(state.value)) {
if (state.type === TransactionType.ADD) {
state.value = this.mergeValues(state.value, transaction.newValue);
}
if (state.type === TransactionType.UPDATE) {
mergeObjects(state.value, transaction.newValue);
}
}
else {
state.value = transaction.newValue;
}
}
}
else {
state = { value: cloneValue(transaction.newValue), recordRef: recordRef, type: transaction.type };
states.set(transaction.id, state);
}
// should not clean pending state. This will happen automatically on endPending call
if (!this._isPending) {
this.cleanState(transaction.id, states);
}
};
/**
* Compares the state with recordRef and clears all duplicated values. If any state ends as
* empty object removes it from states.
* @param state State to clean
*/
IgxTransactionService.prototype.cleanState = function (id, states) {
var e_5, _a;
var state = states.get(id);
// do nothing if
// there is no state, or
// there is no state value (e.g. DELETED transaction), or
// there is no recordRef (e.g. ADDED transaction)
if (state && state.value && state.recordRef) {
// if state's value is object compare each key with the ones in recordRef
// if values in any key are the same delete it from state's value
// if state's value is not object, simply compare with recordRef and remove
// the state if they are equal
if (isObject(state.recordRef)) {
try {
for (var _b = __values(Object.keys(state.value)), _c = _b.next(); !_c.done; _c = _b.next()) {
var key = _c.value;
if (JSON.stringify(state.recordRef[key]) === JSON.stringify(state.value[key])) {
delete state.value[key];
}
}
}
catch (e_5_1) { e_5 = { error: e_5_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_5) throw e_5.error; }
}
// if state's value is empty remove the state from the states, only if state is not DELETE type
if (state.type !== TransactionType.DELETE && Object.keys(state.value).length === 0) {
states.delete(id);
}
}
else {
if (state.recordRef === state.value) {
states.delete(id);
}
}
}
};
/**
* Updates state related record in the provided data
* @param data Data source to update
* @param state State to update data from
*/
IgxTransactionService.prototype.updateRecord = function (data, state) {
var index = data.findIndex(function (i) { return JSON.stringify(i) === JSON.stringify(state.recordRef || {}); });
switch (state.type) {
case TransactionType.ADD:
data.push(state.value);
break;
case TransactionType.DELETE:
if (0 <= index && index < data.length) {
data.splice(index, 1);
}
break;
case TransactionType.UPDATE:
if (0 <= index && index < data.length) {
data[index] = this.updateValue(state);
}
break;
}
};
IgxTransactionService = __decorate([
Injectable()
], IgxTransactionService);
return IgxTransactionService;
}(IgxBaseTransactionService));
export { IgxTransactionService };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWd4LXRyYW5zYWN0aW9uLmpzIiwic291cmNlUm9vdCI6Im5nOi8vaWduaXRldWktYW5ndWxhci8iLCJzb3VyY2VzIjpbImxpYi9zZXJ2aWNlcy90cmFuc2FjdGlvbi9pZ3gtdHJhbnNhY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBc0IsZUFBZSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3BFLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQy9ELE9BQU8sRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3pELE9BQU8sRUFBRSxRQUFRLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBR3RFO0lBQW1GLHlDQUErQjtJQUFsSDtRQUFBLHFFQXNWQztRQXJWYSxtQkFBYSxHQUFRLEVBQUUsQ0FBQztRQUN4QixnQkFBVSxHQUEyQyxFQUFFLENBQUM7UUFDeEQsZ0JBQVUsR0FBMkMsRUFBRSxDQUFDO1FBQ3hELGFBQU8sR0FBZ0IsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQWdCM0M7O1dBRUc7UUFDSSxtQkFBYSxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7O0lBK1RwRCxDQUFDO0lBN1VHLHNCQUFJLDBDQUFPO1FBSFg7O1dBRUc7YUFDSDtZQUNJLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ3RDLENBQUM7OztPQUFBO0lBS0Qsc0JBQUksMENBQU87UUFIWDs7V0FFRzthQUNIO1lBQ0ksT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7UUFDdEMsQ0FBQzs7O09BQUE7SUFPRDs7T0FFRztJQUNJLG1DQUFHLEdBQVYsVUFBVyxXQUFjLEVBQUUsU0FBZTtRQUN0QyxJQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFD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O1FBRGpDLFVBQVUsRUFBRTtPQUNBLHFCQUFxQixDQXNWakM7SUFBRCw0QkFBQztDQUFBLEFBdFZELENBQW1GLHlCQUF5QixHQXNWM0c7U0F0VlkscUJBQXFCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgVHJhbnNhY3Rpb24sIFN0YXRlLCBUcmFuc2FjdGlvblR5cGUgfSBmcm9tICcuL3RyYW5zYWN0aW9uJztcbmltcG9ydCB7IElneEJhc2VUcmFuc2FjdGlvblNlcnZpY2UgfSBmcm9tICcuL2Jhc2UtdHJhbnNhY3Rpb24nO1xuaW1wb3J0IHsgRXZlbnRFbWl0dGVyLCBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBpc09iamVjdCwgbWVyZ2VPYmplY3RzLCBjbG9uZVZhbHVlIH0gZnJvbSAnLi4vLi4vY29yZS91dGlscyc7XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBJZ3hUcmFuc2FjdGlvblNlcnZpY2U8VCBleHRlbmRzIFRyYW5zYWN0aW9uLCBTIGV4dGVuZHMgU3RhdGU+IGV4dGVuZHMgSWd4QmFzZVRyYW5zYWN0aW9uU2VydmljZTxULCBTPiB7XG4gICAgcHJvdGVjdGVkIF90cmFuc2FjdGlvbnM6IFRbXSA9IFtdO1xuICAgIHByb3RlY3RlZCBfcmVkb1N0YWNrOiB7IHRyYW5zYWN0aW9uOiBULCByZWNvcmRSZWY6IGFueSB9W11bXSA9IFtdO1xuICAgIHByb3RlY3RlZCBfdW5kb1N0YWNrOiB7IHRyYW5zYWN0aW9uOiBULCByZWNvcmRSZWY6IGFueSB9W11bXSA9IFtdO1xuICAgIHByb3RlY3RlZCBfc3RhdGVzOiBNYXA8YW55LCBTPiA9IG5ldyBNYXAoKTtcblxuICAgIC8qKlxuICAgICAqIEBpbmhlcml0ZG9jXG4gICAgICovXG4gICAgZ2V0IGNhblVuZG8oKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl91bmRvU3RhY2subGVuZ3RoID4gMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaW5oZXJpdGRvY1xuICAgICAqL1xuICAgIGdldCBjYW5SZWRvKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fcmVkb1N0YWNrLmxlbmd0aCA+IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGluaGVyaXRkb2NcbiAgICAgKi9cbiAgICBwdWJsaWMgb25TdGF0ZVVwZGF0ZSA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICAgIC8qKlxuICAgICAqIEBpbmhlcml0ZG9jXG4gICAgICovXG4gICAgcHVibGljIGFkZCh0cmFuc2FjdGlvbjogVCwgcmVjb3JkUmVmPzogYW55KTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHN0YXRlcyA9IHRoaXMuX2lzUGVuZGluZyA/IHRoaXMuX3BlbmRpbmdTdGF0ZXMgOiB0aGlzLl9zdGF0ZXM7XG4gICAgICAgIHRoaXMudmVyaWZ5QWRkZWRUcmFuc2FjdGlvbihzdGF0ZXMsIHRyYW5zYWN0aW9uLCByZWNvcmRSZWYpO1xuICAgICAgICB0aGlzLmFkZFRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uLCBzdGF0ZXMsIHJlY29yZFJlZik7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGFkZFRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uOiBULCBzdGF0ZXM6IE1hcDxhbnksIFM+LCByZWNvcmRSZWY/OiBhbnkpIHtcbiAgICAgICAgdGhpcy51cGRhdGVTdGF0ZShzdGF0ZXMsIHRyYW5zYWN0aW9uLCByZWNvcmRSZWYpO1xuXG4gICAgICAgIGNvbnN0IHRyYW5zYWN0aW9ucyA9IHRoaXMuX2lzUGVuZGluZyA/IHRoaXMuX3BlbmRpbmdUcmFuc2FjdGlvbnMgOiB0aGlzLl90cmFuc2FjdGlvbnM7XG4gICAgICAgIHRyYW5zYWN0aW9ucy5wdXNoKHRyYW5zYWN0aW9uKTtcblxuICAgICAgICBpZiAoIXRoaXMuX2lzUGVuZGluZykge1xuICAgICAgICAgICAgdGhpcy5fdW5kb1N0YWNrLnB1c2goW3sgdHJhbnNhY3Rpb24sIHJlY29yZFJlZiB9XSk7XG4gICAgICAgICAgICB0aGlzLl9yZWRvU3RhY2sgPSBbXTtcbiAgICAgICAgICAgIHRoaXMub25TdGF0ZVVwZGF0ZS5lbWl0KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaW5oZXJpdGRvY1xuICAgICAqL1xuICAgIHB1YmxpYyBnZXRUcmFuc2FjdGlvbkxvZyhpZD86IGFueSk6IFRbXSB7XG4gICAgICAgIGlmIChpZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fdHJhbnNhY3Rpb25zLmZpbHRlcih0ID0+IHQuaWQgPT09IGlkKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gWy4uLnRoaXMuX3RyYW5zYWN0aW9uc107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGluaGVyaXRkb2NcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0QWdncmVnYXRlZENoYW5nZXMobWVyZ2VDaGFuZ2VzOiBib29sZWFuKTogVFtdIHtcbiAgICAgICAgY29uc3QgcmVzdWx0OiBUW10gPSBbXTtcbiAgICAgICAgdGhpcy5fc3RhdGVzLmZvckVhY2goKHN0YXRlOiBTLCBrZXk6IGFueSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBtZXJnZUNoYW5nZXMgPyB0aGlzLm1lcmdlVmFsdWVzKHN0YXRlLnJlY29yZFJlZiwgc3RhdGUudmFsdWUpIDogc3RhdGUudmFsdWU7XG4gICAgICAgICAgICByZXN1bHQucHVzaCh7IGlkOiBrZXksIG5ld1ZhbHVlOiB2YWx1ZSwgdHlwZTogc3RhdGUudHlwZSB9IGFzIFQpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaW5oZXJpdGRvY1xuICAgICAqL1xuICAgIHB1YmxpYyBnZXRTdGF0ZShpZDogYW55LCBwZW5kaW5nOiBib29sZWFuID0gZmFsc2UpOiBTIHtcbiAgICAgICAgcmV0dXJuIHBlbmRpbmcgPyB0aGlzLl9wZW5kaW5nU3RhdGVzLmdldChpZCkgOiB0aGlzLl9zdGF0ZXMuZ2V0KGlkKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaW5oZXJpdGRvY1xuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgZW5hYmxlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGluaGVyaXRkb2NcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0QWdncmVnYXRlZFZhbHVlKGlkOiBhbnksIG1lcmdlQ2hhbmdlczogYm9vbGVhbik6IGFueSB7XG4gICAgICAgIGNvbnN0IHN0YXRlID0gdGhpcy5fc3RhdGVzLmdldChpZCk7XG4gICAgICAgIGNvbnN0IHBlbmRpbmdTdGF0ZSA9IHN1cGVyLmdldFN0YXRlKGlkKTtcblxuICAgICAgICAvLyAgaWYgdGhlcmUgaXMgbm8gc3RhdGUgYW5kIHRoZXJlIGlzIG5vIHBlbmRpbmcgc3RhdGUgcmV0dXJuIG51bGxcbiAgICAgICAgaWYgKCFzdGF0ZSAmJiAhcGVuZGluZ1N0YXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHBlbmRpbmdDaGFuZ2UgPSBzdXBlci5nZXRBZ2dyZWdhdGVkVmFsdWUoaWQsIGZhbHNlKTtcbiAgICAgICAgY29uc3QgY2hhbmdlID0gc3RhdGUgJiYgc3RhdGUudmFsdWU7XG4gICAgICAgIGxldCBhZ2dyZWdhdGVkVmFsdWUgPSB0aGlzLm1lcmdlVmFsdWVzKGNoYW5nZSwgcGVuZGluZ0NoYW5nZSk7XG4gICAgICAgIGlmIChtZXJnZUNoYW5nZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IG9yaWdpbmFsVmFsdWUgPSBzdGF0ZSA/IHN0YXRlLnJlY29yZFJlZiA6IHBlbmRpbmdTdGF0ZS5yZWNvcmRSZWY7XG4gICAgICAgICAgICBhZ2dyZWdhdGVkVmFsdWUgPSB0aGlzLm1lcmdlVmFsdWVzKG9yaWdpbmFsVmFsdWUsIGFnZ3JlZ2F0ZWRWYWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFnZ3JlZ2F0ZWRWYWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaW5oZXJpdGRvY1xuICAgICAqL1xuICAgIHB1YmxpYyBlbmRQZW5kaW5nKGNvbW1pdDogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLl9pc1BlbmRpbmcgPSBmYWxzZTtcbiAgICAgICAgaWYgKGNvbW1pdCkge1xuICAgICAgICAgICAgY29uc3QgYWN0aW9uczogeyB0cmFuc2FjdGlvbjogVCwgcmVjb3JkUmVmOiBhbnkgfVtdID0gW107XG4gICAgICAgICAgICAvLyBkb24ndCB1c2UgYWRkVHJhbnNhY3Rpb24gZHVlIHRvIGN1c3RvbSB1bmRvIGhhbmRsaW5nXG4gICAgICAgICAgICBmb3IgKGNvbnN0IHRyYW5zYWN0aW9uIG9mIHRoaXMuX3BlbmRpbmdUcmFuc2FjdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwZW5kaW5nU3RhdGUgPSB0aGlzLl9wZW5kaW5nU3RhdGVzLmdldCh0cmFuc2FjdGlvbi5pZCk7XG4gICAgICAgICAgICAgICAgdGhpcy5fdHJhbnNhY3Rpb25zLnB1c2godHJhbnNhY3Rpb24pO1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlU3RhdGUodGhpcy5fc3RhdGVzLCB0cmFuc2FjdGlvbiwgcGVuZGluZ1N0YXRlLnJlY29yZFJlZik7XG4gICAgICAgICAgICAgICAgYWN0aW9ucy5wdXNoKHsgdHJhbnNhY3Rpb24sIHJlY29yZFJlZjogcGVuZGluZ1N0YXRlLnJlY29yZFJlZiB9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fdW5kb1N0YWNrLnB1c2goYWN0aW9ucyk7XG4gICAgICAgICAgICB0aGlzLl9yZWRvU3RhY2sgPSBbXTtcblxuICAgICAgICAgICAgdGhpcy5vblN0YXRlVXBkYXRlLmVtaXQoKTtcbiAgICAgICAgfVxuICAgICAgICBzdXBlci5lbmRQZW5kaW5nKGNvbW1pdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGluaGVyaXRkb2NcbiAgICAgKi9cbiAgICBwdWJsaWMgY29tbWl0KGRhdGE6IGFueVtdLCBpZD86IGFueSk6IHZvaWQge1xuICAgICAgICBpZiAoaWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgY29uc3Qgc3RhdGUgPSB0aGlzLmdldFN0YXRlKGlkKTtcbiAgICAgICAgICAgIGlmIChzdGF0ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlUmVjb3JkKGRhdGEsIHN0YXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX3N0YXRlcy5mb3JFYWNoKChzOiBTKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVSZWNvcmQoZGF0YSwgcyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNsZWFyKGlkKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaW5oZXJpdGRvY1xuICAgICAqL1xuICAgIHB1YmxpYyBjbGVhcihpZD86IGFueSk6IHZvaWQge1xuICAgICAgICBpZiAoaWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5fdHJhbnNhY3Rpb25zID0gdGhpcy5fdHJhbnNhY3Rpb25zLmZpbHRlcih0ID0+IHQuaWQgIT09IGlkKTtcbiAgICAgICAgICAgIHRoaXMuX3N0YXRlcy5kZWxldGUoaWQpO1xuICAgICAgICAgICAgLy8gIFVuZG8gc3RhY2sgaXMgYW4gYXJyYXkgb2YgYWN0aW9ucy4gRWFjaCBhY3Rpb24gaXMgYXJyYXkgb2YgdHJhbnNhY3Rpb24gbGlrZSBvYmplY3RzXG4gICAgICAgICAgICAvLyAgV2UgYXJlIGdvaW5nIHRyb3VnaCBhbGwgdGhlIGFjdGlvbnMuIEZvciBlYWNoIGFjdGlvbiB3ZSBhcmUgZmlsdGVyaW5nIG91dCB0cmFuc2FjdGlvbnNcbiAgICAgICAgICAgIC8vICB3aXRoIHByb3ZpZGVkIGlkLiBGaW5hbGx5IGlmIGFueSBhY3Rpb24gZW5kcyB1cCBhcyBlbXB0eSBhcnJheSB3ZSBhcmUgcmVtb3ZpbmcgaXQgZnJvbVxuICAgICAgICAgICAgLy8gIHVuZG8gc3RhY2tcbiAgICAgICAgICAgIHRoaXMuX3VuZG9TdGFjayA9IHRoaXMuX3VuZG9TdGFjay5tYXAoYSA9PiBhLmZpbHRlcih0ID0+IHQudHJhbnNhY3Rpb24uaWQgIT09IGlkKSkuZmlsdGVyKGEgPT4gYS5sZW5ndGggPiAwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX3RyYW5zYWN0aW9ucyA9IFtdO1xuICAgICAgICAgICAgdGhpcy5fc3RhdGVzLmNsZWFyKCk7XG4gICAgICAgICAgICB0aGlzLl91bmRvU3RhY2sgPSBbXTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9yZWRvU3RhY2sgPSBbXTtcbiAgICAgICAgdGhpcy5vblN0YXRlVXBkYXRlLmVtaXQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaW5oZXJpdGRvY1xuICAgICAqL1xuICAgIHB1YmxpYyB1bmRvKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5fdW5kb1N0YWNrLmxlbmd0aCA8PSAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBsYXN0QWN0aW9uczogeyB0cmFuc2FjdGlvbjogVCwgcmVjb3JkUmVmOiBhbnkgfVtdID0gdGhpcy5fdW5kb1N0YWNrLnBvcCgpO1xuICAgICAgICB0aGlzLl90cmFuc2FjdGlvbnMuc3BsaWNlKHRoaXMuX3RyYW5zYWN0aW9ucy5sZW5ndGggLSBsYXN0QWN0aW9ucy5sZW5ndGgpO1xuICAgICAgICB0aGlzLl9yZWRvU3RhY2sucHVzaChsYXN0QWN0aW9ucyk7XG5cbiAgICAgICAgdGhpcy5fc3RhdGVzLmNsZWFyKCk7XG4gICAgICAgIGZvciAoY29uc3QgY3VycmVudEFjdGlvbnMgb2YgdGhpcy5fdW5kb1N0YWNrKSB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHRyYW5zYWN0aW9uIG9mIGN1cnJlbnRBY3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVTdGF0ZSh0aGlzLl9zdGF0ZXMsIHRyYW5zYWN0aW9uLnRyYW5zYWN0aW9uLCB0cmFuc2FjdGlvbi5yZWNvcmRSZWYpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5vblN0YXRlVXBkYXRlLmVtaXQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaW5oZXJpdGRvY1xuICAgICAqL1xuICAgIHB1YmxpYyByZWRvKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5fcmVkb1N0YWNrLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGxldCBhY3Rpb25zOiB7IHRyYW5zYWN0aW9uOiBULCByZWNvcmRSZWY6IGFueSwgdXNlSW5VbmRvPzogYm9vbGVhbiB9W107XG4gICAgICAgICAgICBhY3Rpb25zID0gdGhpcy5fcmVkb1N0YWNrLnBvcCgpO1xuICAgICAgICAgICAgZm9yIChjb25zdCBhY3Rpb24gb2YgYWN0aW9ucykge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlU3RhdGUodGhpcy5fc3RhdGVzLCBhY3Rpb24udHJhbnNhY3Rpb24sIGFjdGlvbi5yZWNvcmRSZWYpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3RyYW5zYWN0aW9ucy5wdXNoKGFjdGlvbi50cmFuc2FjdGlvbik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX3VuZG9TdGFjay5wdXNoKGFjdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy5vblN0YXRlVXBkYXRlLmVtaXQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFZlcmlmaWVzIGlmIHRoZSBwYXNzZWQgdHJhbnNhY3Rpb24gaXMgY29ycmVjdC4gSWYgbm90IHRocm93cyBhbiBleGNlcHRpb24uXG4gICAgICogQHBhcmFtIHRyYW5zYWN0aW9uIFRyYW5zYWN0aW9uIHRvIGJlIHZlcmlmaWVkXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHZlcmlmeUFkZGVkVHJhbnNhY3Rpb24oc3RhdGVzOiBNYXA8YW55LCBTPiwgdHJhbnNhY3Rpb246IFQsIHJlY29yZFJlZj86IGFueSk6IHZvaWQge1xuICAgICAgICBjb25zdCBzdGF0ZSA9IHN0YXRlcy5nZXQodHJhbnNhY3Rpb24uaWQpO1xuICAgICAgICBzd2l0Y2ggKHRyYW5zYWN0aW9uLnR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLkFERDpcbiAgICAgICAgICAgICAgICBpZiAoc3RhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gIGNhbm5vdCBhZGQgc2FtZSBpdGVtIHR3aWNlXG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IGFkZCB0aGlzIHRyYW5zYWN0aW9uLiBUcmFuc2FjdGlvbiB3aXRoIGlkOiAke3RyYW5zYWN0aW9uLmlkfSBoYXMgYmVlbiBhbHJlYWR5IGFkZGVkLmApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLkRFTEVURTpcbiAgICAgICAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlVQREFURTpcbiAgICAgICAgICAgICAgICBpZiAoc3RhdGUgJiYgc3RhdGUudHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLkRFTEVURSkge1xuICAgICAgICAgICAgICAgICAgICAvLyAgY2Fubm90IGRlbGV0ZSBvciB1cGRhdGUgZGVsZXRlZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCBhZGQgdGhpcyB0cmFuc2FjdGlvbi4gVHJhbnNhY3Rpb24gd2l0aCBpZDogJHt0cmFuc2FjdGlvbi5pZH0gaGFzIGJlZW4gYWxyZWFkeSBkZWxldGVkLmApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIXN0YXRlICYmICFyZWNvcmRSZWYgJiYgIXRoaXMuX2lzUGVuZGluZykge1xuICAgICAgICAgICAgICAgICAgICAvLyAgY2Fubm90IGluaXRpYWxseSBhZGQgdHJhbnNhY3Rpb24gb3IgZGVsZXRlIGl0ZW0gd2l0aCBubyByZWNvcmRSZWZcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgYWRkIHRoaXMgdHJhbnNhY3Rpb24uIFRoaXMgaXMgZmlyc3QgdHJhbnNhY3Rpb24gb2YgdHlwZSAke3RyYW5zYWN0aW9uLnR5cGV9IGAgK1xuICAgICAgICAgICAgICAgICAgICAgICAgYGZvciBpZCAke3RyYW5zYWN0aW9uLmlkfS4gRm9yIGZpcnN0IHRyYW5zYWN0aW9uIG9mIHRoaXMgdHlwZSByZWNvcmRSZWYgaXMgbWFuZGF0b3J5LmApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZXMgdGhlIHByb3ZpZGVkIHN0YXRlcyBjb2xsZWN0aW9uIGFjY29yZGluZyB0byBwYXNzZWQgdHJhbnNhY3Rpb24gYW5kIHJlY29yZFJlZlxuICAgICAqIEBwYXJhbSBzdGF0ZXMgU3RhdGVzIGNvbGxlY3Rpb24gdG8gYXBwbHkgdGhlIHVwZGF0ZSB0b1xuICAgICAqIEBwYXJhbSB0cmFuc2FjdGlvbiBUcmFuc2FjdGlvbiB0byBhcHBseSB0byB0aGUgY3VycmVudCBzdGF0ZVxuICAgICAqIEBwYXJhbSByZWNvcmRSZWYgUmVmZXJlbmNlIHRvIHRoZSB2YWx1ZSBvZiB0aGUgcmVjb3JkIGluIGRhdGEgc291cmNlLCBpZiBhbnksIHdoZXJlIHRyYW5zYWN0aW9uIHNob3VsZCBiZSBhcHBsaWVkXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHVwZGF0ZVN0YXRlKHN0YXRlczogTWFwPGFueSwgUz4sIHRyYW5zYWN0aW9uOiBULCByZWNvcmRSZWY/OiBhbnkpOiB2b2lkIHtcbiAgICAgICAgbGV0IHN0YXRlID0gc3RhdGVzLmdldCh0cmFuc2FjdGlvbi5pZCk7XG4gICAgICAgIC8vICBpZiBUcmFuc2FjdGlvblR5cGUgaXMgQUREIHNpbXBseSBhZGQgdHJhbnNhY3Rpb24gdG8gc3RhdGVzO1xuICAgICAgICAvLyAgaWYgVHJhbnNhY3Rpb25UeXBlIGlzIERFTEVURTpcbiAgICAgICAgLy8gICAgLSBpZiB0aGVyZSBpcyBzdGF0ZSB3aXRoIHRoaXMgaWQgb2YgdHlwZSBBREQgcmVtb3ZlIGl0IGZyb20gdGhlIHN0YXRlcztcbiAgICAgICAgLy8gICAgLSBpZiB0aGVyZSBpcyBzdGF0ZSB3aXRoIHRoaXMgaWQgb2YgdHlwZSBVUERBVEUgY2hhbmdlIGl0cyB0eXBlIHRvIERFTEVURTtcbiAgICAgICAgLy8gICAgLSBpZiB0aGVyZSBpcyBubyBzdGF0ZSB3aXRoIHRoaXMgaWQgYWRkIHRyYW5zYWN0aW9uIHRvIHN0YXRlcztcbiAgICAgICAgLy8gIGlmIFRyYW5zYWN0aW9uVHlwZSBpcyBVUERBVEU6XG4gICAgICAgIC8vICAgIC0gaWYgdGhlcmUgaXMgc3RhdGUgd2l0aCB0aGlzIGlkIG9mIHR5cGUgQUREIG1lcmdlIG5ldyB2YWx1ZSBhbmQgc3RhdGUgcmVjb3JkUmVmIGludG8gc3RhdGUgbmV3IHZhbHVlXG4gICAgICAgIC8vICAgIC0gaWYgdGhlcmUgaXMgc3RhdGUgd2l0aCB0aGlzIGlkIG9mIHR5cGUgVVBEQVRFIG1lcmdlIG5ldyB2YWx1ZSBpbnRvIHN0YXRlIG5ldyB2YWx1ZVxuICAgICAgICAvLyAgICAtIGlmIHRoZXJlIGlzIHN0YXRlIHdpdGggdGhpcyBpZCBhbmQgc3RhdGUgdHlwZSBpcyBERUxFVEUgY2hhbmdlIGl0cyB0eXBlIHRvIFVQREFURVxuICAgICAgICAvLyAgICAtIGlmIHRoZXJlIGlzIG5vIHN0YXRlIHdpdGggdGhpcyBpZCBhZGQgdHJhbnNhY3Rpb24gdG8gc3RhdGVzO1xuICAgICAgICBpZiAoc3RhdGUpIHtcbiAgICAgICAgICAgIHN3aXRjaCAodHJhbnNhY3Rpb24udHlwZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLkRFTEVURTpcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXRlLnR5cGUgPT09IFRyYW5zYWN0aW9uVHlwZS5BREQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlcy5kZWxldGUodHJhbnNhY3Rpb24uaWQpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHN0YXRlLnR5cGUgPT09IFRyYW5zYWN0aW9uVHlwZS5VUERBVEUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLnZhbHVlID0gdHJhbnNhY3Rpb24ubmV3VmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS50eXBlID0gVHJhbnNhY3Rpb25UeXBlLkRFTEVURTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5VUERBVEU6XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChzdGF0ZS52YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0ZS50eXBlID09PSBUcmFuc2FjdGlvblR5cGUuQUREKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUudmFsdWUgPSB0aGlzLm1lcmdlVmFsdWVzKHN0YXRlLnZhbHVlLCB0cmFuc2FjdGlvbi5uZXdWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdGUudHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLlVQREFURSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lcmdlT2JqZWN0cyhzdGF0ZS52YWx1ZSwgdHJhbnNhY3Rpb24ubmV3VmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUudmFsdWUgPSB0cmFuc2FjdGlvbi5uZXdWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3RhdGUgPSB7IHZhbHVlOiBjbG9uZVZhbHVlKHRyYW5zYWN0aW9uLm5ld1ZhbHVlKSwgcmVjb3JkUmVmOiByZWNvcmRSZWYsIHR5cGU6IHRyYW5zYWN0aW9uLnR5cGUgfSBhcyBTO1xuICAgICAgICAgICAgc3RhdGVzLnNldCh0cmFuc2FjdGlvbi5pZCwgc3RhdGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gIHNob3VsZCBub3QgY2xlYW4gcGVuZGluZyBzdGF0ZS4gVGhpcyB3aWxsIGhhcHBlbiBhdXRvbWF0aWNhbGx5IG9uIGVuZFBlbmRpbmcgY2FsbFxuICAgICAgICBpZiAoIXRoaXMuX2lzUGVuZGluZykge1xuICAgICAgICAgICAgdGhpcy5jbGVhblN0YXRlKHRyYW5zYWN0aW9uLmlkLCBzdGF0ZXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29tcGFyZXMgdGhlIHN0YXRlIHdpdGggcmVjb3JkUmVmIGFuZCBjbGVhcnMgYWxsIGR1cGxpY2F0ZWQgdmFsdWVzLiBJZiBhbnkgc3RhdGUgZW5kcyBhc1xuICAgICAqIGVtcHR5IG9iamVjdCByZW1vdmVzIGl0IGZyb20gc3RhdGVzLlxuICAgICAqIEBwYXJhbSBzdGF0ZSBTdGF0ZSB0byBjbGVhblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjbGVhblN0YXRlKGlkOiBhbnksIHN0YXRlczogTWFwPGFueSwgUz4pOiB2b2lkIHtcbiAgICAgICAgY29uc3Qgc3RhdGUgPSBzdGF0ZXMuZ2V0KGlkKTtcbiAgICAgICAgLy8gIGRvIG5vdGhpbmcgaWZcbiAgICAgICAgLy8gIHRoZXJlIGlzIG5vIHN0YXRlLCBvclxuICAgICAgICAvLyAgdGhlcmUgaXMgbm8gc3RhdGUgdmFsdWUgKGUuZy4gREVMRVRFRCB0cmFuc2FjdGlvbiksIG9yXG4gICAgICAgIC8vICB0aGVyZSBpcyBubyByZWNvcmRSZWYgKGUuZy4gQURERUQgdHJhbnNhY3Rpb24pXG4gICAgICAgIGlmIChzdGF0ZSAmJiBzdGF0ZS52YWx1ZSAmJiBzdGF0ZS5yZWNvcmRSZWYpIHtcbiAgICAgICAgICAgIC8vICBpZiBzdGF0ZSdzIHZhbHVlIGlzIG9iamVjdCBjb21wYXJlIGVhY2gga2V5IHdpdGggdGhlIG9uZXMgaW4gcmVjb3JkUmVmXG4gICAgICAgICAgICAvLyAgaWYgdmFsdWVzIGluIGFueSBrZXkgYXJlIHRoZSBzYW1lIGRlbGV0ZSBpdCBmcm9tIHN0YXRlJ3MgdmFsdWVcbiAgICAgICAgICAgIC8vICBpZiBzdGF0ZSdzIHZhbHVlIGlzIG5vdCBvYmplY3QsIHNpbXBseSBjb21wYXJlIHdpdGggcmVjb3JkUmVmIGFuZCByZW1vdmVcbiAgICAgICAgICAgIC8vICB0aGUgc3RhdGUgaWYgdGhleSBhcmUgZXF1YWxcbiAgICAgICAgICAgIGlmIChpc09iamVjdChzdGF0ZS5yZWNvcmRSZWYpKSB7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoc3RhdGUudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChKU09OLnN0cmluZ2lmeShzdGF0ZS5yZWNvcmRSZWZba2V5XSkgPT09IEpTT04uc3RyaW5naWZ5KHN0YXRlLnZhbHVlW2tleV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgc3RhdGUudmFsdWVba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vICBpZiBzdGF0ZSdzIHZhbHVlIGlzIGVtcHR5IHJlbW92ZSB0aGUgc3RhdGUgZnJvbSB0aGUgc3RhdGVzLCBvbmx5IGlmIHN0YXRlIGlzIG5vdCBERUxFVEUgdHlwZVxuICAgICAgICAgICAgICAgIGlmIChzdGF0ZS50eXBlICE9PSBUcmFuc2FjdGlvblR5cGUuREVMRVRFICYmIE9iamVjdC5rZXlzKHN0YXRlLnZhbHVlKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgc3RhdGVzLmRlbGV0ZShpZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoc3RhdGUucmVjb3JkUmVmID09PSBzdGF0ZS52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBzdGF0ZXMuZGVsZXRlKGlkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGVzIHN0YXRlIHJlbGF0ZWQgcmVjb3JkIGluIHRoZSBwcm92aWRlZCBkYXRhXG4gICAgICogQHBhcmFtIGRhdGEgRGF0YSBzb3VyY2UgdG8gdXBkYXRlXG4gICAgICogQHBhcmFtIHN0YXRlIFN0YXRlIHRvIHVwZGF0ZSBkYXRhIGZyb21cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgdXBkYXRlUmVjb3JkKGRhdGE6IGFueVtdLCBzdGF0ZTogUykge1xuICAgICAgICBjb25zdCBpbmRleCA9IGRhdGEuZmluZEluZGV4KGkgPT4gSlNPTi5zdHJpbmdpZnkoaSkgPT09IEpTT04uc3RyaW5naWZ5KHN0YXRlLnJlY29yZFJlZiB8fCB7fSkpO1xuICAgICAgICBzd2l0Y2ggKHN0YXRlLnR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLkFERDpcbiAgICAgICAgICAgICAgICBkYXRhLnB1c2goc3RhdGUudmFsdWUpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuREVMRVRFOlxuICAgICAgICAgICAgICAgIGlmICgwIDw9IGluZGV4ICYmIGluZGV4IDwgZGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YS5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlVQREFURTpcbiAgICAgICAgICAgICAgICBpZiAoMCA8PSBpbmRleCAmJiBpbmRleCA8IGRhdGEubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIGRhdGFbaW5kZXhdID0gdGhpcy51cGRhdGVWYWx1ZShzdGF0ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxufVxuIl19