@catull/igniteui-angular
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
331 lines • 43.8 kB
JavaScript
import { __decorate } from "tslib";
import { TransactionType } from './transaction';
import { IgxBaseTransactionService } from './base-transaction';
import { EventEmitter, Injectable } from '@angular/core';
import { isObject, mergeObjects, cloneValue } from '../../core/utils';
let IgxTransactionService = class IgxTransactionService extends IgxBaseTransactionService {
constructor() {
super(...arguments);
this._transactions = [];
this._redoStack = [];
this._undoStack = [];
this._states = new Map();
/**
* @inheritdoc
*/
this.onStateUpdate = new EventEmitter();
}
/**
* @inheritdoc
*/
get canUndo() {
return this._undoStack.length > 0;
}
/**
* @inheritdoc
*/
get canRedo() {
return this._redoStack.length > 0;
}
/**
* @inheritdoc
*/
add(transaction, recordRef) {
const states = this._isPending ? this._pendingStates : this._states;
this.verifyAddedTransaction(states, transaction, recordRef);
this.addTransaction(transaction, states, recordRef);
}
addTransaction(transaction, states, recordRef) {
this.updateState(states, transaction, recordRef);
const transactions = this._isPending ? this._pendingTransactions : this._transactions;
transactions.push(transaction);
if (!this._isPending) {
this._undoStack.push([{ transaction, recordRef }]);
this._redoStack = [];
this.onStateUpdate.emit();
}
}
/**
* @inheritdoc
*/
getTransactionLog(id) {
if (id !== undefined) {
return this._transactions.filter(t => t.id === id);
}
return [...this._transactions];
}
/**
* @inheritdoc
*/
getAggregatedChanges(mergeChanges) {
const result = [];
this._states.forEach((state, key) => {
const value = mergeChanges ? this.mergeValues(state.recordRef, state.value) : state.value;
result.push({ id: key, newValue: value, type: state.type });
});
return result;
}
/**
* @inheritdoc
*/
getState(id, pending = false) {
return pending ? this._pendingStates.get(id) : this._states.get(id);
}
/**
* @inheritdoc
*/
get enabled() {
return true;
}
/**
* @inheritdoc
*/
getAggregatedValue(id, mergeChanges) {
const state = this._states.get(id);
const pendingState = super.getState(id);
// if there is no state and there is no pending state return null
if (!state && !pendingState) {
return null;
}
const pendingChange = super.getAggregatedValue(id, false);
const change = state && state.value;
let aggregatedValue = this.mergeValues(change, pendingChange);
if (mergeChanges) {
const originalValue = state ? state.recordRef : pendingState.recordRef;
aggregatedValue = this.mergeValues(originalValue, aggregatedValue);
}
return aggregatedValue;
}
/**
* @inheritdoc
*/
endPending(commit) {
this._isPending = false;
if (commit) {
const actions = [];
// don't use addTransaction due to custom undo handling
for (const transaction of this._pendingTransactions) {
const pendingState = this._pendingStates.get(transaction.id);
this._transactions.push(transaction);
this.updateState(this._states, transaction, pendingState.recordRef);
actions.push({ transaction, recordRef: pendingState.recordRef });
}
this._undoStack.push(actions);
this._redoStack = [];
this.onStateUpdate.emit();
}
super.endPending(commit);
}
/**
* @inheritdoc
*/
commit(data, id) {
if (id !== undefined) {
const state = this.getState(id);
if (state) {
this.updateRecord(data, state);
}
}
else {
this._states.forEach((s) => {
this.updateRecord(data, s);
});
}
this.clear(id);
}
/**
* @inheritdoc
*/
clear(id) {
if (id !== undefined) {
this._transactions = this._transactions.filter(t => 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(a => a.filter(t => t.transaction.id !== id)).filter(a => a.length > 0);
}
else {
this._transactions = [];
this._states.clear();
this._undoStack = [];
}
this._redoStack = [];
this.onStateUpdate.emit();
}
/**
* @inheritdoc
*/
undo() {
if (this._undoStack.length <= 0) {
return;
}
const lastActions = this._undoStack.pop();
this._transactions.splice(this._transactions.length - lastActions.length);
this._redoStack.push(lastActions);
this._states.clear();
for (const currentActions of this._undoStack) {
for (const transaction of currentActions) {
this.updateState(this._states, transaction.transaction, transaction.recordRef);
}
}
this.onStateUpdate.emit();
}
/**
* @inheritdoc
*/
redo() {
if (this._redoStack.length > 0) {
let actions;
actions = this._redoStack.pop();
for (const action of actions) {
this.updateState(this._states, action.transaction, action.recordRef);
this._transactions.push(action.transaction);
}
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
*/
verifyAddedTransaction(states, transaction, recordRef) {
const 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
*/
updateState(states, transaction, recordRef) {
let 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
*/
cleanState(id, states) {
const 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)) {
for (const key of Object.keys(state.value)) {
if (JSON.stringify(state.recordRef[key]) === JSON.stringify(state.value[key])) {
delete state.value[key];
}
}
// 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
*/
updateRecord(data, state) {
const index = data.findIndex(i => 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);
export { IgxTransactionService };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWd4LXRyYW5zYWN0aW9uLmpzIiwic291cmNlUm9vdCI6Im5nOi8vaWduaXRldWktYW5ndWxhci8iLCJzb3VyY2VzIjpbImxpYi9zZXJ2aWNlcy90cmFuc2FjdGlvbi9pZ3gtdHJhbnNhY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBc0IsZUFBZSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3BFLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQy9ELE9BQU8sRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3pELE9BQU8sRUFBRSxRQUFRLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBR3RFLElBQWEscUJBQXFCLEdBQWxDLE1BQWEscUJBQThELFNBQVEseUJBQStCO0lBQWxIOztRQUNjLGtCQUFhLEdBQVEsRUFBRSxDQUFDO1FBQ3hCLGVBQVUsR0FBMkMsRUFBRSxDQUFDO1FBQ3hELGVBQVUsR0FBMkMsRUFBRSxDQUFDO1FBQ3hELFlBQU8sR0FBZ0IsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQWdCM0M7O1dBRUc7UUFDSSxrQkFBYSxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7SUErVHBELENBQUM7SUFoVkc7O09BRUc7SUFDSCxJQUFJLE9BQU87UUFDUCxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUN0QyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUFJLE9BQU87UUFDUCxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUN0QyxDQUFDO0lBT0Q7O09BRUc7SUFDSSxHQUFHLENBQUMsV0FBYyxFQUFFLFNBQWU7UUFDdEMsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztRQUNwRSxJQUFJLENBQUMsc0JBQXNCLENBQUMsTUFBTSxFQUFFLFdBQVcsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUM1RCxJQUFJLENBQUMsY0FBYyxDQUFDLFdBQVcsRUFBRSxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDeEQsQ0FBQztJQUVTLGNBQWMsQ0FBQyxXQUFjLEVBQUUsTUFBbUIsRUFBRSxTQUFlO1FBQ3pFLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLFdBQVcsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUVqRCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUM7UUFDdEYsWUFBWSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUUvQixJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRTtZQUNsQixJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUNuRCxJQUFJLENBQUMsVUFBVSxHQUFHLEVBQUUsQ0FBQztZQUNyQixJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRSxDQUFDO1NBQzdCO0lBQ0wsQ0FBQztJQUVEOztPQUVHO0lBQ0ksaUJBQWlCLENBQUMsRUFBUTtRQUM3QixJQUFJLEVBQUUsS0FBSyxTQUFTLEVBQUU7WUFDbEIsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7U0FDdEQ7UUFDRCxPQUFPLENBQUMsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVEOztPQUVHO0lBQ0ksb0JBQW9CLENBQUMsWUFBcUI7UUFDN0MsTUFBTSxNQUFNLEdBQVEsRUFBRSxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBUSxFQUFFLEdBQVEsRUFBRSxFQUFFO1lBQ3hDLE1BQU0sS0FBSyxHQUFHLFlBQVksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQztZQUMxRixNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSSxFQUFPLENBQUMsQ0FBQztRQUNyRSxDQUFDLENBQUMsQ0FBQztRQUNILE9BQU8sTUFBTSxDQUFDO0lBQ2xCLENBQUM7SUFFRDs7T0FFRztJQUNJLFFBQVEsQ0FBQyxFQUFPLEVBQUUsVUFBbUIsS0FBSztRQUM3QyxPQUFPLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3hFLENBQUM7SUFFRDs7T0FFRztJQUNILElBQVcsT0FBTztRQUNkLE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFFRDs7T0FFRztJQUNJLGtCQUFrQixDQUFDLEVBQU8sRUFBRSxZQUFxQjtRQUNwRCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNuQyxNQUFNLFlBQVksR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBRXhDLGtFQUFrRTtRQUNsRSxJQUFJLENBQUMsS0FBSyxJQUFJLENBQUMsWUFBWSxFQUFFO1lBQ3pCLE9BQU8sSUFBSSxDQUFDO1NBQ2Y7UUFFRCxNQUFNLGFBQWEsR0FBRyxLQUFLLENBQUMsa0JBQWtCLENBQUMsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQzFELE1BQU0sTUFBTSxHQUFHLEtBQUssSUFBSSxLQUFLLENBQUMsS0FBSyxDQUFDO1FBQ3BDLElBQUksZUFBZSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLGFBQWEsQ0FBQyxDQUFDO1FBQzlELElBQUksWUFBWSxFQUFFO1lBQ2QsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDO1lBQ3ZFLGVBQWUsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsRUFBRSxlQUFlLENBQUMsQ0FBQztTQUN0RTtRQUNELE9BQU8sZUFBZSxDQUFDO0lBQzNCLENBQUM7SUFFRDs7T0FFRztJQUNJLFVBQVUsQ0FBQyxNQUFlO1FBQzdCLElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDO1FBQ3hCLElBQUksTUFBTSxFQUFFO1lBQ1IsTUFBTSxPQUFPLEdBQXlDLEVBQUUsQ0FBQztZQUN6RCx1REFBdUQ7WUFDdkQsS0FBSyxNQUFNLFdBQVcsSUFBSSxJQUFJLENBQUMsb0JBQW9CLEVBQUU7Z0JBQ2pELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDN0QsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7Z0JBQ3JDLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxXQUFXLEVBQUUsWUFBWSxDQUFDLFNBQVMsQ0FBQyxDQUFDO2dCQUNwRSxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxZQUFZLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQzthQUNwRTtZQUVELElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzlCLElBQUksQ0FBQyxVQUFVLEdBQUcsRUFBRSxDQUFDO1lBRXJCLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLENBQUM7U0FDN0I7UUFDRCxLQUFLLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzdCLENBQUM7SUFFRDs7T0FFRztJQUNJLE1BQU0sQ0FBQyxJQUFXLEVBQUUsRUFBUTtRQUMvQixJQUFJLEVBQUUsS0FBSyxTQUFTLEVBQUU7WUFDbEIsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNoQyxJQUFJLEtBQUssRUFBRTtnQkFDUCxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQzthQUNsQztTQUNKO2FBQU07WUFDSCxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUksRUFBRSxFQUFFO2dCQUMxQixJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztZQUMvQixDQUFDLENBQUMsQ0FBQztTQUNOO1FBQ0QsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNuQixDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsRUFBUTtRQUNqQixJQUFJLEVBQUUsS0FBSyxTQUFTLEVBQUU7WUFDbEIsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7WUFDakUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDeEIsdUZBQXVGO1lBQ3ZGLDBGQUEwRjtZQUMxRiwwRkFBMEY7WUFDMUYsY0FBYztZQUNkLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1NBQ2hIO2FBQU07WUFDSCxJQUFJLENBQUMsYUFBYSxHQUFHLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3JCLElBQUksQ0FBQyxVQUFVLEdBQUcsRUFBRSxDQUFDO1NBQ3hCO1FBQ0QsSUFBSSxDQUFDLFVBQVUsR0FBRyxFQUFFLENBQUM7UUFDckIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUM5QixDQUFDO0lBRUQ7O09BRUc7SUFDSSxJQUFJO1FBQ1AsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sSUFBSSxDQUFDLEVBQUU7WUFDN0IsT0FBTztTQUNWO1FBRUQsTUFBTSxXQUFXLEdBQXlDLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDaEYsSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLEdBQUcsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzFFLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBRWxDLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDckIsS0FBSyxNQUFNLGNBQWMsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQzFDLEtBQUssTUFBTSxXQUFXLElBQUksY0FBYyxFQUFFO2dCQUN0QyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsV0FBVyxDQUFDLFdBQVcsRUFBRSxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUM7YUFDbEY7U0FDSjtRQUVELElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDOUIsQ0FBQztJQUVEOztPQUVHO0lBQ0ksSUFBSTtRQUNQLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1lBQzVCLElBQUksT0FBa0UsQ0FBQztZQUN2RSxPQUFPLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNoQyxLQUFLLE1BQU0sTUFBTSxJQUFJLE9BQU8sRUFBRTtnQkFDMUIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxXQUFXLEVBQUUsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO2dCQUNyRSxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7YUFDL0M7WUFFRCxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUM5QixJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRSxDQUFDO1NBQzdCO0lBQ0wsQ0FBQztJQUVEOzs7T0FHRztJQUNPLHNCQUFzQixDQUFDLE1BQW1CLEVBQUUsV0FBYyxFQUFFLFNBQWU7UUFDakYsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDekMsUUFBUSxXQUFXLENBQUMsSUFBSSxFQUFFO1lBQ3RCLEtBQUssZUFBZSxDQUFDLEdBQUc7Z0JBQ3BCLElBQUksS0FBSyxFQUFFO29CQUNQLDhCQUE4QjtvQkFDOUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxxREFBcUQsV0FBVyxDQUFDLEVBQUUsMEJBQTBCLENBQUMsQ0FBQztpQkFDbEg7Z0JBQ0QsTUFBTTtZQUNWLEtBQUssZUFBZSxDQUFDLE1BQU0sQ0FBQztZQUM1QixLQUFLLGVBQWUsQ0FBQyxNQUFNO2dCQUN2QixJQUFJLEtBQUssSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLGVBQWUsQ0FBQyxNQUFNLEVBQUU7b0JBQ2hELHlDQUF5QztvQkFDekMsTUFBTSxJQUFJLEtBQUssQ0FBQyxxREFBcUQsV0FBVyxDQUFDLEVBQUUsNEJBQTRCLENBQUMsQ0FBQztpQkFDcEg7Z0JBQ0QsSUFBSSxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUU7b0JBQzFDLHFFQUFxRTtvQkFDckUsTUFBTSxJQUFJLEtBQUssQ0FBQyxrRUFBa0UsV0FBVyxDQUFDLElBQUksR0FBRzt3QkFDakcsVUFBVSxXQUFXLENBQUMsRUFBRSw4REFBOEQsQ0FBQyxDQUFDO2lCQUMvRjtnQkFDRCxNQUFNO1NBQ2I7SUFDTCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDTyxXQUFXLENBQUMsTUFBbUIsRUFBRSxXQUFjLEVBQUUsU0FBZTtRQUN0RSxJQUFJLEtBQUssR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN2QywrREFBK0Q7UUFDL0QsaUNBQWlDO1FBQ2pDLDZFQUE2RTtRQUM3RSxnRkFBZ0Y7UUFDaEYsb0VBQW9FO1FBQ3BFLGlDQUFpQztRQUNqQywyR0FBMkc7UUFDM0csMEZBQTBGO1FBQzFGLHlGQUF5RjtRQUN6RixvRUFBb0U7UUFDcEUsSUFBSSxLQUFLLEVBQUU7WUFDUCxRQUFRLFdBQVcsQ0FBQyxJQUFJLEVBQUU7Z0JBQ3RCLEtBQUssZUFBZSxDQUFDLE1BQU07b0JBQ3ZCLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxlQUFlLENBQUMsR0FBRyxFQUFFO3dCQUNwQyxNQUFNLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQztxQkFDakM7eUJBQU0sSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLGVBQWUsQ0FBQyxNQUFNLEVBQUU7d0JBQzlDLEtBQUssQ0FBQyxLQUFLLEdBQUcsV0FBVyxDQUFDLFFBQVEsQ0FBQzt3QkFDbkMsS0FBSyxDQUFDLElBQUksR0FBRyxlQUFlLENBQUMsTUFBTSxDQUFDO3FCQUN2QztvQkFDRCxNQUFNO2dCQUNWLEtBQUssZUFBZSxDQUFDLE1BQU07b0JBQ3ZCLElBQUksUUFBUSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsRUFBRTt3QkFDdkIsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLGVBQWUsQ0FBQyxHQUFHLEVBQUU7NEJBQ3BDLEtBQUssQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQzt5QkFDckU7d0JBQ0QsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLGVBQWUsQ0FBQyxNQUFNLEVBQUU7NEJBQ3ZDLFlBQVksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQzt5QkFDbkQ7cUJBQ0o7eUJBQU07d0JBQ0gsS0FBSyxDQUFDLEtBQUssR0FBRyxXQUFXLENBQUMsUUFBUSxDQUFDO3FCQUN0QzthQUNSO1NBQ0o7YUFBTTtZQUNILEtBQUssR0FBRyxFQUFFLEtBQUssRUFBRSxVQUFVLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLFdBQVcsQ0FBQyxJQUFJLEVBQU8sQ0FBQztZQUN2RyxNQUFNLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7U0FDckM7UUFFRCxxRkFBcUY7UUFDckYsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUU7WUFDbEIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1NBQzNDO0lBQ0wsQ0FBQztJQUVEOzs7O09BSUc7SUFDTyxVQUFVLENBQUMsRUFBTyxFQUFFLE1BQW1CO1FBQzdDLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDN0IsaUJBQWlCO1FBQ2pCLHlCQUF5QjtRQUN6QiwwREFBMEQ7UUFDMUQsa0RBQWtEO1FBQ2xELElBQUksS0FBSyxJQUFJLEtBQUssQ0FBQyxLQUFLLElBQUksS0FBSyxDQUFDLFNBQVMsRUFBRTtZQUN6QywwRUFBMEU7WUFDMUUsa0VBQWtFO1lBQ2xFLDRFQUE0RTtZQUM1RSwrQkFBK0I7WUFDL0IsSUFBSSxRQUFRLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxFQUFFO2dCQUMzQixLQUFLLE1BQU0sR0FBRyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxFQUFFO29CQUN4QyxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFO3dCQUMzRSxPQUFPLEtBQUssQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7cUJBQzNCO2lCQUNKO2dCQUVELGdHQUFnRztnQkFDaEcsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLGVBQWUsQ0FBQyxNQUFNLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtvQkFDaEYsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztpQkFDckI7YUFDSjtpQkFBTTtnQkFDSCxJQUFJLEtBQUssQ0FBQyxTQUFTLEtBQUssS0FBSyxDQUFDLEtBQUssRUFBRTtvQkFDakMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztpQkFDckI7YUFDSjtTQUNKO0lBQ0wsQ0FBQztJQUVEOzs7O09BSUc7SUFDTyxZQUFZLENBQUMsSUFBVyxFQUFFLEtBQVE7UUFDeEMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsU0FBUyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDL0YsUUFBUSxLQUFLLENBQUMsSUFBSSxFQUFFO1lBQ2hCLEtBQUssZUFBZSxDQUFDLEdBQUc7Z0JBQ3BCLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUN2QixNQUFNO1lBQ1YsS0FBSyxlQUFlLENBQUMsTUFBTTtnQkFDdkIsSUFBSSxDQUFDLElBQUksS0FBSyxJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFO29CQUNuQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztpQkFDekI7Z0JBQ0QsTUFBTTtZQUNWLEtBQUssZUFBZSxDQUFDLE1BQU07Z0JBQ3ZCLElBQUksQ0FBQyxJQUFJLEtBQUssSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRTtvQkFDbkMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7aUJBQ3pDO2dCQUNELE1BQU07U0FDYjtJQUNMLENBQUM7Q0FDSixDQUFBO0FBdFZZLHFCQUFxQjtJQURqQyxVQUFVLEVBQUU7R0FDQSxxQkFBcUIsQ0FzVmpDO1NBdFZZLHFCQUFxQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFRyYW5zYWN0aW9uLCBTdGF0ZSwgVHJhbnNhY3Rpb25UeXBlIH0gZnJvbSAnLi90cmFuc2FjdGlvbic7XG5pbXBvcnQgeyBJZ3hCYXNlVHJhbnNhY3Rpb25TZXJ2aWNlIH0gZnJvbSAnLi9iYXNlLXRyYW5zYWN0aW9uJztcbmltcG9ydCB7IEV2ZW50RW1pdHRlciwgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgaXNPYmplY3QsIG1lcmdlT2JqZWN0cywgY2xvbmVWYWx1ZSB9IGZyb20gJy4uLy4uL2NvcmUvdXRpbHMnO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgSWd4VHJhbnNhY3Rpb25TZXJ2aWNlPFQgZXh0ZW5kcyBUcmFuc2FjdGlvbiwgUyBleHRlbmRzIFN0YXRlPiBleHRlbmRzIElneEJhc2VUcmFuc2FjdGlvblNlcnZpY2U8VCwgUz4ge1xuICAgIHByb3RlY3RlZCBfdHJhbnNhY3Rpb25zOiBUW10gPSBbXTtcbiAgICBwcm90ZWN0ZWQgX3JlZG9TdGFjazogeyB0cmFuc2FjdGlvbjogVCwgcmVjb3JkUmVmOiBhbnkgfVtdW10gPSBbXTtcbiAgICBwcm90ZWN0ZWQgX3VuZG9TdGFjazogeyB0cmFuc2FjdGlvbjogVCwgcmVjb3JkUmVmOiBhbnkgfVtdW10gPSBbXTtcbiAgICBwcm90ZWN0ZWQgX3N0YXRlczogTWFwPGFueSwgUz4gPSBuZXcgTWFwKCk7XG5cbiAgICAvKipcbiAgICAgKiBAaW5oZXJpdGRvY1xuICAgICAqL1xuICAgIGdldCBjYW5VbmRvKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fdW5kb1N0YWNrLmxlbmd0aCA+IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGluaGVyaXRkb2NcbiAgICAgKi9cbiAgICBnZXQgY2FuUmVkbygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3JlZG9TdGFjay5sZW5ndGggPiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBpbmhlcml0ZG9jXG4gICAgICovXG4gICAgcHVibGljIG9uU3RhdGVVcGRhdGUgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cbiAgICAvKipcbiAgICAgKiBAaW5oZXJpdGRvY1xuICAgICAqL1xuICAgIHB1YmxpYyBhZGQodHJhbnNhY3Rpb246IFQsIHJlY29yZFJlZj86IGFueSk6IHZvaWQge1xuICAgICAgICBjb25zdCBzdGF0ZXMgPSB0aGlzLl9pc1BlbmRpbmcgPyB0aGlzLl9wZW5kaW5nU3RhdGVzIDogdGhpcy5fc3RhdGVzO1xuICAgICAgICB0aGlzLnZlcmlmeUFkZGVkVHJhbnNhY3Rpb24oc3RhdGVzLCB0cmFuc2FjdGlvbiwgcmVjb3JkUmVmKTtcbiAgICAgICAgdGhpcy5hZGRUcmFuc2FjdGlvbih0cmFuc2FjdGlvbiwgc3RhdGVzLCByZWNvcmRSZWYpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBhZGRUcmFuc2FjdGlvbih0cmFuc2FjdGlvbjogVCwgc3RhdGVzOiBNYXA8YW55LCBTPiwgcmVjb3JkUmVmPzogYW55KSB7XG4gICAgICAgIHRoaXMudXBkYXRlU3RhdGUoc3RhdGVzLCB0cmFuc2FjdGlvbiwgcmVjb3JkUmVmKTtcblxuICAgICAgICBjb25zdCB0cmFuc2FjdGlvbnMgPSB0aGlzLl9pc1BlbmRpbmcgPyB0aGlzLl9wZW5kaW5nVHJhbnNhY3Rpb25zIDogdGhpcy5fdHJhbnNhY3Rpb25zO1xuICAgICAgICB0cmFuc2FjdGlvbnMucHVzaCh0cmFuc2FjdGlvbik7XG5cbiAgICAgICAgaWYgKCF0aGlzLl9pc1BlbmRpbmcpIHtcbiAgICAgICAgICAgIHRoaXMuX3VuZG9TdGFjay5wdXNoKFt7IHRyYW5zYWN0aW9uLCByZWNvcmRSZWYgfV0pO1xuICAgICAgICAgICAgdGhpcy5fcmVkb1N0YWNrID0gW107XG4gICAgICAgICAgICB0aGlzLm9uU3RhdGVVcGRhdGUuZW1pdCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGluaGVyaXRkb2NcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0VHJhbnNhY3Rpb25Mb2coaWQ/OiBhbnkpOiBUW10ge1xuICAgICAgICBpZiAoaWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3RyYW5zYWN0aW9ucy5maWx0ZXIodCA9PiB0LmlkID09PSBpZCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFsuLi50aGlzLl90cmFuc2FjdGlvbnNdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBpbmhlcml0ZG9jXG4gICAgICovXG4gICAgcHVibGljIGdldEFnZ3JlZ2F0ZWRDaGFuZ2VzKG1lcmdlQ2hhbmdlczogYm9vbGVhbik6IFRbXSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdDogVFtdID0gW107XG4gICAgICAgIHRoaXMuX3N0YXRlcy5mb3JFYWNoKChzdGF0ZTogUywga2V5OiBhbnkpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gbWVyZ2VDaGFuZ2VzID8gdGhpcy5tZXJnZVZhbHVlcyhzdGF0ZS5yZWNvcmRSZWYsIHN0YXRlLnZhbHVlKSA6IHN0YXRlLnZhbHVlO1xuICAgICAgICAgICAgcmVzdWx0LnB1c2goeyBpZDoga2V5LCBuZXdWYWx1ZTogdmFsdWUsIHR5cGU6IHN0YXRlLnR5cGUgfSBhcyBUKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGluaGVyaXRkb2NcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0U3RhdGUoaWQ6IGFueSwgcGVuZGluZzogYm9vbGVhbiA9IGZhbHNlKTogUyB7XG4gICAgICAgIHJldHVybiBwZW5kaW5nID8gdGhpcy5fcGVuZGluZ1N0YXRlcy5nZXQoaWQpIDogdGhpcy5fc3RhdGVzLmdldChpZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGluaGVyaXRkb2NcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IGVuYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBpbmhlcml0ZG9jXG4gICAgICovXG4gICAgcHVibGljIGdldEFnZ3JlZ2F0ZWRWYWx1ZShpZDogYW55LCBtZXJnZUNoYW5nZXM6IGJvb2xlYW4pOiBhbnkge1xuICAgICAgICBjb25zdCBzdGF0ZSA9IHRoaXMuX3N0YXRlcy5nZXQoaWQpO1xuICAgICAgICBjb25zdCBwZW5kaW5nU3RhdGUgPSBzdXBlci5nZXRTdGF0ZShpZCk7XG5cbiAgICAgICAgLy8gIGlmIHRoZXJlIGlzIG5vIHN0YXRlIGFuZCB0aGVyZSBpcyBubyBwZW5kaW5nIHN0YXRlIHJldHVybiBudWxsXG4gICAgICAgIGlmICghc3RhdGUgJiYgIXBlbmRpbmdTdGF0ZSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwZW5kaW5nQ2hhbmdlID0gc3VwZXIuZ2V0QWdncmVnYXRlZFZhbHVlKGlkLCBmYWxzZSk7XG4gICAgICAgIGNvbnN0IGNoYW5nZSA9IHN0YXRlICYmIHN0YXRlLnZhbHVlO1xuICAgICAgICBsZXQgYWdncmVnYXRlZFZhbHVlID0gdGhpcy5tZXJnZVZhbHVlcyhjaGFuZ2UsIHBlbmRpbmdDaGFuZ2UpO1xuICAgICAgICBpZiAobWVyZ2VDaGFuZ2VzKSB7XG4gICAgICAgICAgICBjb25zdCBvcmlnaW5hbFZhbHVlID0gc3RhdGUgPyBzdGF0ZS5yZWNvcmRSZWYgOiBwZW5kaW5nU3RhdGUucmVjb3JkUmVmO1xuICAgICAgICAgICAgYWdncmVnYXRlZFZhbHVlID0gdGhpcy5tZXJnZVZhbHVlcyhvcmlnaW5hbFZhbHVlLCBhZ2dyZWdhdGVkVmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhZ2dyZWdhdGVkVmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGluaGVyaXRkb2NcbiAgICAgKi9cbiAgICBwdWJsaWMgZW5kUGVuZGluZyhjb21taXQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5faXNQZW5kaW5nID0gZmFsc2U7XG4gICAgICAgIGlmIChjb21taXQpIHtcbiAgICAgICAgICAgIGNvbnN0IGFjdGlvbnM6IHsgdHJhbnNhY3Rpb246IFQsIHJlY29yZFJlZjogYW55IH1bXSA9IFtdO1xuICAgICAgICAgICAgLy8gZG9uJ3QgdXNlIGFkZFRyYW5zYWN0aW9uIGR1ZSB0byBjdXN0b20gdW5kbyBoYW5kbGluZ1xuICAgICAgICAgICAgZm9yIChjb25zdCB0cmFuc2FjdGlvbiBvZiB0aGlzLl9wZW5kaW5nVHJhbnNhY3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcGVuZGluZ1N0YXRlID0gdGhpcy5fcGVuZGluZ1N0YXRlcy5nZXQodHJhbnNhY3Rpb24uaWQpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3RyYW5zYWN0aW9ucy5wdXNoKHRyYW5zYWN0aW9uKTtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVN0YXRlKHRoaXMuX3N0YXRlcywgdHJhbnNhY3Rpb24sIHBlbmRpbmdTdGF0ZS5yZWNvcmRSZWYpO1xuICAgICAgICAgICAgICAgIGFjdGlvbnMucHVzaCh7IHRyYW5zYWN0aW9uLCByZWNvcmRSZWY6IHBlbmRpbmdTdGF0ZS5yZWNvcmRSZWYgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX3VuZG9TdGFjay5wdXNoKGFjdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy5fcmVkb1N0YWNrID0gW107XG5cbiAgICAgICAgICAgIHRoaXMub25TdGF0ZVVwZGF0ZS5lbWl0KCk7XG4gICAgICAgIH1cbiAgICAgICAgc3VwZXIuZW5kUGVuZGluZyhjb21taXQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBpbmhlcml0ZG9jXG4gICAgICovXG4gICAgcHVibGljIGNvbW1pdChkYXRhOiBhbnlbXSwgaWQ/OiBhbnkpOiB2b2lkIHtcbiAgICAgICAgaWYgKGlkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0YXRlID0gdGhpcy5nZXRTdGF0ZShpZCk7XG4gICAgICAgICAgICBpZiAoc3RhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVJlY29yZChkYXRhLCBzdGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9zdGF0ZXMuZm9yRWFjaCgoczogUykgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlUmVjb3JkKGRhdGEsIHMpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jbGVhcihpZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGluaGVyaXRkb2NcbiAgICAgKi9cbiAgICBwdWJsaWMgY2xlYXIoaWQ/OiBhbnkpOiB2b2lkIHtcbiAgICAgICAgaWYgKGlkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX3RyYW5zYWN0aW9ucyA9IHRoaXMuX3RyYW5zYWN0aW9ucy5maWx0ZXIodCA9PiB0LmlkICE9PSBpZCk7XG4gICAgICAgICAgICB0aGlzLl9zdGF0ZXMuZGVsZXRlKGlkKTtcbiAgICAgICAgICAgIC8vICBVbmRvIHN0YWNrIGlzIGFuIGFycmF5IG9mIGFjdGlvbnMuIEVhY2ggYWN0aW9uIGlzIGFycmF5IG9mIHRyYW5zYWN0aW9uIGxpa2Ugb2JqZWN0c1xuICAgICAgICAgICAgLy8gIFdlIGFyZSBnb2luZyB0cm91Z2ggYWxsIHRoZSBhY3Rpb25zLiBGb3IgZWFjaCBhY3Rpb24gd2UgYXJlIGZpbHRlcmluZyBvdXQgdHJhbnNhY3Rpb25zXG4gICAgICAgICAgICAvLyAgd2l0aCBwcm92aWRlZCBpZC4gRmluYWxseSBpZiBhbnkgYWN0aW9uIGVuZHMgdXAgYXMgZW1wdHkgYXJyYXkgd2UgYXJlIHJlbW92aW5nIGl0IGZyb21cbiAgICAgICAgICAgIC8vICB1bmRvIHN0YWNrXG4gICAgICAgICAgICB0aGlzLl91bmRvU3RhY2sgPSB0aGlzLl91bmRvU3RhY2subWFwKGEgPT4gYS5maWx0ZXIodCA9PiB0LnRyYW5zYWN0aW9uLmlkICE9PSBpZCkpLmZpbHRlcihhID0+IGEubGVuZ3RoID4gMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl90cmFuc2FjdGlvbnMgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX3N0YXRlcy5jbGVhcigpO1xuICAgICAgICAgICAgdGhpcy5fdW5kb1N0YWNrID0gW107XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcmVkb1N0YWNrID0gW107XG4gICAgICAgIHRoaXMub25TdGF0ZVVwZGF0ZS5lbWl0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGluaGVyaXRkb2NcbiAgICAgKi9cbiAgICBwdWJsaWMgdW5kbygpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuX3VuZG9TdGFjay5sZW5ndGggPD0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbGFzdEFjdGlvbnM6IHsgdHJhbnNhY3Rpb246IFQsIHJlY29yZFJlZjogYW55IH1bXSA9IHRoaXMuX3VuZG9TdGFjay5wb3AoKTtcbiAgICAgICAgdGhpcy5fdHJhbnNhY3Rpb25zLnNwbGljZSh0aGlzLl90cmFuc2FjdGlvbnMubGVuZ3RoIC0gbGFzdEFjdGlvbnMubGVuZ3RoKTtcbiAgICAgICAgdGhpcy5fcmVkb1N0YWNrLnB1c2gobGFzdEFjdGlvbnMpO1xuXG4gICAgICAgIHRoaXMuX3N0YXRlcy5jbGVhcigpO1xuICAgICAgICBmb3IgKGNvbnN0IGN1cnJlbnRBY3Rpb25zIG9mIHRoaXMuX3VuZG9TdGFjaykge1xuICAgICAgICAgICAgZm9yIChjb25zdCB0cmFuc2FjdGlvbiBvZiBjdXJyZW50QWN0aW9ucykge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlU3RhdGUodGhpcy5fc3RhdGVzLCB0cmFuc2FjdGlvbi50cmFuc2FjdGlvbiwgdHJhbnNhY3Rpb24ucmVjb3JkUmVmKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMub25TdGF0ZVVwZGF0ZS5lbWl0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGluaGVyaXRkb2NcbiAgICAgKi9cbiAgICBwdWJsaWMgcmVkbygpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuX3JlZG9TdGFjay5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBsZXQgYWN0aW9uczogeyB0cmFuc2FjdGlvbjogVCwgcmVjb3JkUmVmOiBhbnksIHVzZUluVW5kbz86IGJvb2xlYW4gfVtdO1xuICAgICAgICAgICAgYWN0aW9ucyA9IHRoaXMuX3JlZG9TdGFjay5wb3AoKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgYWN0aW9uIG9mIGFjdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVN0YXRlKHRoaXMuX3N0YXRlcywgYWN0aW9uLnRyYW5zYWN0aW9uLCBhY3Rpb24ucmVjb3JkUmVmKTtcbiAgICAgICAgICAgICAgICB0aGlzLl90cmFuc2FjdGlvbnMucHVzaChhY3Rpb24udHJhbnNhY3Rpb24pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl91bmRvU3RhY2sucHVzaChhY3Rpb25zKTtcbiAgICAgICAgICAgIHRoaXMub25TdGF0ZVVwZGF0ZS5lbWl0KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBWZXJpZmllcyBpZiB0aGUgcGFzc2VkIHRyYW5zYWN0aW9uIGlzIGNvcnJlY3QuIElmIG5vdCB0aHJvd3MgYW4gZXhjZXB0aW9uLlxuICAgICAqIEBwYXJhbSB0cmFuc2FjdGlvbiBUcmFuc2FjdGlvbiB0byBiZSB2ZXJpZmllZFxuICAgICAqL1xuICAgIHByb3RlY3RlZCB2ZXJpZnlBZGRlZFRyYW5zYWN0aW9uKHN0YXRlczogTWFwPGFueSwgUz4sIHRyYW5zYWN0aW9uOiBULCByZWNvcmRSZWY/OiBhbnkpOiB2b2lkIHtcbiAgICAgICAgY29uc3Qgc3RhdGUgPSBzdGF0ZXMuZ2V0KHRyYW5zYWN0aW9uLmlkKTtcbiAgICAgICAgc3dpdGNoICh0cmFuc2FjdGlvbi50eXBlKSB7XG4gICAgICAgICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5BREQ6XG4gICAgICAgICAgICAgICAgaWYgKHN0YXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vICBjYW5ub3QgYWRkIHNhbWUgaXRlbSB0d2ljZVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCBhZGQgdGhpcyB0cmFuc2FjdGlvbi4gVHJhbnNhY3Rpb24gd2l0aCBpZDogJHt0cmFuc2FjdGlvbi5pZH0gaGFzIGJlZW4gYWxyZWFkeSBhZGRlZC5gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5ERUxFVEU6XG4gICAgICAgICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5VUERBVEU6XG4gICAgICAgICAgICAgICAgaWYgKHN0YXRlICYmIHN0YXRlLnR5cGUgPT09IFRyYW5zYWN0aW9uVHlwZS5ERUxFVEUpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gIGNhbm5vdCBkZWxldGUgb3IgdXBkYXRlIGRlbGV0ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgYWRkIHRoaXMgdHJhbnNhY3Rpb24uIFRyYW5zYWN0aW9uIHdpdGggaWQ6ICR7dHJhbnNhY3Rpb24uaWR9IGhhcyBiZWVuIGFscmVhZHkgZGVsZXRlZC5gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCFzdGF0ZSAmJiAhcmVjb3JkUmVmICYmICF0aGlzLl9pc1BlbmRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gIGNhbm5vdCBpbml0aWFsbHkgYWRkIHRyYW5zYWN0aW9uIG9yIGRlbGV0ZSBpdGVtIHdpdGggbm8gcmVjb3JkUmVmXG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IGFkZCB0aGlzIHRyYW5zYWN0aW9uLiBUaGlzIGlzIGZpcnN0IHRyYW5zYWN0aW9uIG9mIHR5cGUgJHt0cmFuc2FjdGlvbi50eXBlfSBgICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGBmb3IgaWQgJHt0cmFuc2FjdGlvbi5pZH0uIEZvciBmaXJzdCB0cmFuc2FjdGlvbiBvZiB0aGlzIHR5cGUgcmVjb3JkUmVmIGlzIG1hbmRhdG9yeS5gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGVzIHRoZSBwcm92aWRlZCBzdGF0ZXMgY29sbGVjdGlvbiBhY2NvcmRpbmcgdG8gcGFzc2VkIHRyYW5zYWN0aW9uIGFuZCByZWNvcmRSZWZcbiAgICAgKiBAcGFyYW0gc3RhdGVzIFN0YXRlcyBjb2xsZWN0aW9uIHRvIGFwcGx5IHRoZSB1cGRhdGUgdG9cbiAgICAgKiBAcGFyYW0gdHJhbnNhY3Rpb24gVHJhbnNhY3Rpb24gdG8gYXBwbHkgdG8gdGhlIGN1cnJlbnQgc3RhdGVcbiAgICAgKiBAcGFyYW0gcmVjb3JkUmVmIFJlZmVyZW5jZSB0byB0aGUgdmFsdWUgb2YgdGhlIHJlY29yZCBpbiBkYXRhIHNvdXJjZSwgaWYgYW55LCB3aGVyZSB0cmFuc2FjdGlvbiBzaG91bGQgYmUgYXBwbGllZFxuICAgICAqL1xuICAgIHByb3RlY3RlZCB1cGRhdGVTdGF0ZShzdGF0ZXM6IE1hcDxhbnksIFM+LCB0cmFuc2FjdGlvbjogVCwgcmVjb3JkUmVmPzogYW55KTogdm9pZCB7XG4gICAgICAgIGxldCBzdGF0ZSA9IHN0YXRlcy5nZXQodHJhbnNhY3Rpb24uaWQpO1xuICAgICAgICAvLyAgaWYgVHJhbnNhY3Rpb25UeXBlIGlzIEFERCBzaW1wbHkgYWRkIHRyYW5zYWN0aW9uIHRvIHN0YXRlcztcbiAgICAgICAgLy8gIGlmIFRyYW5zYWN0aW9uVHlwZSBpcyBERUxFVEU6XG4gICAgICAgIC8vICAgIC0gaWYgdGhlcmUgaXMgc3RhdGUgd2l0aCB0aGlzIGlkIG9mIHR5cGUgQUREIHJlbW92ZSBpdCBmcm9tIHRoZSBzdGF0ZXM7XG4gICAgICAgIC8vICAgIC0gaWYgdGhlcmUgaXMgc3RhdGUgd2l0aCB0aGlzIGlkIG9mIHR5cGUgVVBEQVRFIGNoYW5nZSBpdHMgdHlwZSB0byBERUxFVEU7XG4gICAgICAgIC8vICAgIC0gaWYgdGhlcmUgaXMgbm8gc3RhdGUgd2l0aCB0aGlzIGlkIGFkZCB0cmFuc2FjdGlvbiB0byBzdGF0ZXM7XG4gICAgICAgIC8vICBpZiBUcmFuc2FjdGlvblR5cGUgaXMgVVBEQVRFOlxuICAgICAgICAvLyAgICAtIGlmIHRoZXJlIGlzIHN0YXRlIHdpdGggdGhpcyBpZCBvZiB0eXBlIEFERCBtZXJnZSBuZXcgdmFsdWUgYW5kIHN0YXRlIHJlY29yZFJlZiBpbnRvIHN0YXRlIG5ldyB2YWx1ZVxuICAgICAgICAvLyAgICAtIGlmIHRoZXJlIGlzIHN0YXRlIHdpdGggdGhpcyBpZCBvZiB0eXBlIFVQREFURSBtZXJnZSBuZXcgdmFsdWUgaW50byBzdGF0ZSBuZXcgdmFsdWVcbiAgICAgICAgLy8gICAgLSBpZiB0aGVyZSBpcyBzdGF0ZSB3aXRoIHRoaXMgaWQgYW5kIHN0YXRlIHR5cGUgaXMgREVMRVRFIGNoYW5nZSBpdHMgdHlwZSB0byBVUERBVEVcbiAgICAgICAgLy8gICAgLSBpZiB0aGVyZSBpcyBubyBzdGF0ZSB3aXRoIHRoaXMgaWQgYWRkIHRyYW5zYWN0aW9uIHRvIHN0YXRlcztcbiAgICAgICAgaWYgKHN0YXRlKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHRyYW5zYWN0aW9uLnR5cGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5ERUxFVEU6XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdGF0ZS50eXBlID09PSBUcmFuc2FjdGlvblR5cGUuQUREKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZXMuZGVsZXRlKHRyYW5zYWN0aW9uLmlkKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzdGF0ZS50eXBlID09PSBUcmFuc2FjdGlvblR5cGUuVVBEQVRFKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS52YWx1ZSA9IHRyYW5zYWN0aW9uLm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUudHlwZSA9IFRyYW5zYWN0aW9uVHlwZS5ERUxFVEU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuVVBEQVRFOlxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNPYmplY3Qoc3RhdGUudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdGUudHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLkFERCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLnZhbHVlID0gdGhpcy5tZXJnZVZhbHVlcyhzdGF0ZS52YWx1ZSwgdHJhbnNhY3Rpb24ubmV3VmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXRlLnR5cGUgPT09IFRyYW5zYWN0aW9uVHlwZS5VUERBVEUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXJnZU9iamVjdHMoc3RhdGUudmFsdWUsIHRyYW5zYWN0aW9uLm5ld1ZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLnZhbHVlID0gdHJhbnNhY3Rpb24ubmV3VmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHN0YXRlID0geyB2YWx1ZTogY2xvbmVWYWx1ZSh0cmFuc2FjdGlvbi5uZXdWYWx1ZSksIHJlY29yZFJlZjogcmVjb3JkUmVmLCB0eXBlOiB0cmFuc2FjdGlvbi50eXBlIH0gYXMgUztcbiAgICAgICAgICAgIHN0YXRlcy5zZXQodHJhbnNhY3Rpb24uaWQsIHN0YXRlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vICBzaG91bGQgbm90IGNsZWFuIHBlbmRpbmcgc3RhdGUuIFRoaXMgd2lsbCBoYXBwZW4gYXV0b21hdGljYWxseSBvbiBlbmRQZW5kaW5nIGNhbGxcbiAgICAgICAgaWYgKCF0aGlzLl9pc1BlbmRpbmcpIHtcbiAgICAgICAgICAgIHRoaXMuY2xlYW5TdGF0ZSh0cmFuc2FjdGlvbi5pZCwgc3RhdGVzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbXBhcmVzIHRoZSBzdGF0ZSB3aXRoIHJlY29yZFJlZiBhbmQgY2xlYXJzIGFsbCBkdXBsaWNhdGVkIHZhbHVlcy4gSWYgYW55IHN0YXRlIGVuZHMgYXNcbiAgICAgKiBlbXB0eSBvYmplY3QgcmVtb3ZlcyBpdCBmcm9tIHN0YXRlcy5cbiAgICAgKiBAcGFyYW0gc3RhdGUgU3RhdGUgdG8gY2xlYW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgY2xlYW5TdGF0ZShpZDogYW55LCBzdGF0ZXM6IE1hcDxhbnksIFM+KTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHN0YXRlID0gc3RhdGVzLmdldChpZCk7XG4gICAgICAgIC8vICBkbyBub3RoaW5nIGlmXG4gICAgICAgIC8vICB0aGVyZSBpcyBubyBzdGF0ZSwgb3JcbiAgICAgICAgLy8gIHRoZXJlIGlzIG5vIHN0YXRlIHZhbHVlIChlLmcuIERFTEVURUQgdHJhbnNhY3Rpb24pLCBvclxuICAgICAgICAvLyAgdGhlcmUgaXMgbm8gcmVjb3JkUmVmIChlLmcuIEFEREVEIHRyYW5zYWN0aW9uKVxuICAgICAgICBpZiAoc3RhdGUgJiYgc3RhdGUudmFsdWUgJiYgc3RhdGUucmVjb3JkUmVmKSB7XG4gICAgICAgICAgICAvLyAgaWYgc3RhdGUncyB2YWx1ZSBpcyBvYmplY3QgY29tcGFyZSBlYWNoIGtleSB3aXRoIHRoZSBvbmVzIGluIHJlY29yZFJlZlxuICAgICAgICAgICAgLy8gIGlmIHZhbHVlcyBpbiBhbnkga2V5IGFyZSB0aGUgc2FtZSBkZWxldGUgaXQgZnJvbSBzdGF0ZSdzIHZhbHVlXG4gICAgICAgICAgICAvLyAgaWYgc3RhdGUncyB2YWx1ZSBpcyBub3Qgb2JqZWN0LCBzaW1wbHkgY29tcGFyZSB3aXRoIHJlY29yZFJlZiBhbmQgcmVtb3ZlXG4gICAgICAgICAgICAvLyAgdGhlIHN0YXRlIGlmIHRoZXkgYXJlIGVxdWFsXG4gICAgICAgICAgICBpZiAoaXNPYmplY3Qoc3RhdGUucmVjb3JkUmVmKSkge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHN0YXRlLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoSlNPTi5zdHJpbmdpZnkoc3RhdGUucmVjb3JkUmVmW2tleV0pID09PSBKU09OLnN0cmluZ2lmeShzdGF0ZS52YWx1ZVtrZXldKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHN0YXRlLnZhbHVlW2tleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyAgaWYgc3RhdGUncyB2YWx1ZSBpcyBlbXB0eSByZW1vdmUgdGhlIHN0YXRlIGZyb20gdGhlIHN0YXRlcywgb25seSBpZiBzdGF0ZSBpcyBub3QgREVMRVRFIHR5cGVcbiAgICAgICAgICAgICAgICBpZiAoc3RhdGUudHlwZSAhPT0gVHJhbnNhY3Rpb25UeXBlLkRFTEVURSAmJiBPYmplY3Qua2V5cyhzdGF0ZS52YWx1ZSkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0YXRlcy5kZWxldGUoaWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHN0YXRlLnJlY29yZFJlZiA9PT0gc3RhdGUudmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgc3RhdGVzLmRlbGV0ZShpZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlcyBzdGF0ZSByZWxhdGVkIHJlY29yZCBpbiB0aGUgcHJvdmlkZWQgZGF0YVxuICAgICAqIEBwYXJhbSBkYXRhIERhdGEgc291cmNlIHRvIHVwZGF0ZVxuICAgICAqIEBwYXJhbSBzdGF0ZSBTdGF0ZSB0byB1cGRhdGUgZGF0YSBmcm9tXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHVwZGF0ZVJlY29yZChkYXRhOiBhbnlbXSwgc3RhdGU6IFMpIHtcbiAgICAgICAgY29uc3QgaW5kZXggPSBkYXRhLmZpbmRJbmRleChpID0+IEpTT04uc3RyaW5naWZ5KGkpID09PSBKU09OLnN0cmluZ2lmeShzdGF0ZS5yZWNvcmRSZWYgfHwge30pKTtcbiAgICAgICAgc3dpdGNoIChzdGF0ZS50eXBlKSB7XG4gICAgICAgICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5BREQ6XG4gICAgICAgICAgICAgICAgZGF0YS5wdXNoKHN0YXRlLnZhbHVlKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLkRFTEVURTpcbiAgICAgICAgICAgICAgICBpZiAoMCA8PSBpbmRleCAmJiBpbmRleCA8IGRhdGEubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIGRhdGEuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5VUERBVEU6XG4gICAgICAgICAgICAgICAgaWYgKDAgPD0gaW5kZXggJiYgaW5kZXggPCBkYXRhLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBkYXRhW2luZGV4XSA9IHRoaXMudXBkYXRlVmFsdWUoc3RhdGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cbn1cbiJdfQ==