@edugouvfr/ngx-dsfr-ext
Version:
NgxDsfrExt est une extension au package @edugouvfr/ngx-dsfr (portage Angular des éléments DSFR)
306 lines (305 loc) • 42.5 kB
JavaScript
import { newUniqueId } from '@edugouvfr/ngx-dsfr';
import { DsfrSelectionModeConst } from '../../models/selection-mode.type';
/**
* TreeSelectManager implémente les fonctionnalités de sélection des nœuds d'une arborescence.
* - Gère le mode de sélection
* - Gère les checkbox
* - Ne gère pas l'apparence des libellés sélectionnés
*/
export class TreeSelectManager {
constructor(treeSelectable) {
/**
* Mode de sélection géré par le manager. Accessible par les composants utilisant ce manager.
*/
this.selectionMode = undefined;
/** Stratégie de sélection : pouvoir sélectionner tous les noeuds ou uniquement les feuilles */
this.selectionStrategy = 'leaf';
/** Liste des nœuds sélectionnés. Si le mode de sélection est 'checkbox', seul les noeuds feuilles sont sélectionnables. */
this.selectedNodes = [];
/** Les noeuds feuilles doivent posséder un id défini à l'initialisation si compareWith n'est pas renseigné */
this.noGenericId = false;
/** Nombre total de feuilles de l'arbre */
this.countLeaves = 0;
/**
* Attribut permettant de notifier qu'un noeud sélectionné à déjà été rencontré en mode single, permettant d'ignorer
* l'état sélectionné de tous les noeuds subséquents.
*/
this.singleModeSelectedSkip = false;
this.treeSelectable = treeSelectable;
}
/**
* À appeler à chaque modification de l'arborescence.
*
* @param nodes Nœuds à initialiser
*/
init(nodes) {
// Initialisation de selected et checkboxId
const nodesClone = this.initNodes(nodes, 1);
this.singleModeSelectedSkip = false;
// Dans le cas d'utilisation des checkboxes, on met à jour la valeur de `selected` en fonction des enfants.
if (this.isCheckboxMode())
this.updateBranches(nodesClone);
return nodesClone;
}
/**
* Sélection / désélection du nœud suite à un clic.
* - Le nœud devient le nœud courant en mettant tabIndex=0
* - Gestion des différents modes de sélection
* - Envoie d'une notification sur le changement d'état de node.selected
* Dans le cas du mode checkbox, il n'y a pas de modification suite aux changements d'états des enfants
*/
doSelectNode(node, nodeElt) {
// Le nœud qui reçoit l'événement devient focusable
nodeElt.tabIndex = 0;
if (!this.isSelectable())
return;
if (this.isSingleMode())
this.handleSingleModeSelection(node);
else if (this.isMultipleMode())
this.handleMultipleModeSelection(node);
else if (this.isCheckboxMode())
this.handleCheckboxModeSelection(node);
}
isSelectable() {
return this.selectionMode !== undefined;
}
isCheckboxMode() {
return this.selectionMode === DsfrSelectionModeConst.CHECKBOX;
}
isSingleMode() {
return this.selectionMode === DsfrSelectionModeConst.SINGLE;
}
isMultipleMode() {
return this.selectionMode === DsfrSelectionModeConst.MULTIPLE;
}
/**
* Initialisation par défaut des propriétés d'un nœud : 'selected', 'id'.
*
* @param nodes Les noeuds à initialiser
* @param level Le niveau du noeud dans la hiérarchie
*/
initNodes(nodes, level) {
const size = nodes.length;
return nodes.map((n) => {
const nodeView = {
...n,
id: n.id || newUniqueId(),
ariaLevel: level,
ariaSize: size,
children: n.children ? this.initNodes(n.children, level + 1) : undefined,
};
if (!n.children && !n.disabled) {
this.countLeaves++;
}
if (!n.children && !n.id && this.noGenericId) {
console.warn(`La fonction compareWith doit être définie: "${n.label}" n'a pas d'attribut 'id'.`);
}
if (this.isSelectable()) {
this.handleNodeSelectedInitialization(n, nodeView);
}
return nodeView;
});
}
/**
* Mise à jour des propriétés des nœuds (label, data, id) sans modifier l'état (select, expand) et ajouts éventuels.
* @param nodes Nœuds d'entrée à mettre à jour.
* @param viewNodes Nœuds clonés représentant l'état actuel de l'arbre.
*/
updateNodesContent(nodes, viewNodes, level) {
const size = nodes.length;
return nodes.map((node) => {
// noeud correspondant dans l'arbre cloné
const matchingNodeView = viewNodes.find((n) => n.id === node.id);
if (matchingNodeView) {
return {
...node, // on récupère les nouvelles valeurs transmises par l'utilisateur du composant
id: node.id || matchingNodeView.id, // si l'id n'a pas été positionné, on récupère celui qui a été généré
selected: matchingNodeView.selected, // on restaure l'état de sélection courant
expanded: matchingNodeView.expanded, // on restaure l'état d'expansion courant
ariaLevel: matchingNodeView.ariaLevel, // on restaure le niveau de hiérarchie
ariaSize: size, // on restaure la taille, car elle a pu changer
children: node.children
? this.updateNodesContent(node.children, matchingNodeView.children || [], level + 1)
: matchingNodeView.children,
};
}
else {
// aucun noeud correspondant, ajouter la nouvelle structure
const nodeView = {
...node,
id: node.id || newUniqueId(),
ariaLevel: level,
ariaSize: size,
children: node.children ? this.initNodes(node.children, level + 1) : undefined,
};
return nodeView;
}
});
}
selectAllNodes(nodes, select = true) {
const isMultiple = this.selectionMode === DsfrSelectionModeConst.MULTIPLE || this.selectionMode === DsfrSelectionModeConst.CHECKBOX;
if (isMultiple || (this.isSingleMode() && !select))
this.toggleNodesState(nodes, select);
}
/**
* Mise à jour liste des feuilles sélectionnées
* (suppression des nœuds non sélectionnés)
*/
updateSelectedNodes() {
this.selectedNodes = this.selectedNodes.filter((n) => n.selected);
return this.selectedNodes;
}
/**
* Détermine l'état de l'attribut selected d'un noeud en fonction du mode courant et du model fournit.
*
* @param node Nœud du model fournit.
* @param viewNode Nœud cloné représentant l'état actuel de l'arbre.
*/
handleNodeSelectedInitialization(node, viewNode) {
if (this.singleModeSelectedSkip) {
viewNode.selected = false;
return;
}
if (!this.isCheckboxMode() || !node.children) {
viewNode.selected = node.selected || false;
}
if ((!viewNode.children || this.selectionStrategy === 'all') && viewNode.selected) {
// update list of selected nodes
this.selectedNodes.push(viewNode);
}
if (node.selected && this.isSingleMode()) {
this.singleModeSelectedSkip = true;
}
}
toggleNodeSelectedState(node) {
node.selected = !node.selected;
if (!node.selected) {
this.treeSelectable.isAllSelected = false;
}
}
handleSingleModeSelection(node) {
const prevSingleNode = this.findFirstNodeSelected(this.treeSelectable.nodes);
if (prevSingleNode && prevSingleNode !== node) {
prevSingleNode.selected = false;
// envoi de l'évènement notifiant la déselection du noeud précédant
this.treeSelectable.notifySelectEvent(prevSingleNode);
}
// ajout de l'unique nœud sélectionnable
if (!node.children || this.selectionStrategy !== 'leaf')
this.selectedNodes = [node];
this.toggleNodeSelectedState(node);
this.treeSelectable.notifySelectEvent(node);
}
handleMultipleModeSelection(node) {
this.selectedNodes.push(node);
this.updateSelectedNodes();
this.toggleNodeSelectedState(node);
this.treeSelectable.notifySelectEvent(node);
}
handleCheckboxModeSelection(node) {
this.toggleNodeSelectedState(node);
// Propagation de la sélection
this.updateChildren(node, node.selected);
// Mise à jour des parents pour tout le model
this.updateBranches(this.treeSelectable.nodes);
this.updateSelectedNodes();
this.treeSelectable.notifySelectEvent(node);
}
/**
* Met à jour, récursivement, l'état de chaque nœud en parcourant l'arborescence de haut en bas.
*/
updateChildren(node, selected) {
if (node.disabled || node.hidden)
return;
node.selected = selected;
// Dans le cas d'utilisation des checkboxes, on propage l'état aux enfants
if (this.isCheckboxMode()) {
node.children?.forEach((n) => this.updateChildren(n, selected));
if (!node.children && node.selected && !this.selectedNodes.find((n) => n.id === node.id)) {
// Ajout du nœud (feuille) sélectionné dans la liste
this.selectedNodes.push(node);
}
}
}
/**
* Met à jour l'état `selected` d'une branche en fonction de ses nœuds enfants ('true', 'false' ou 'undefined').
* Émet un événement si l'état du nœud change.
* Met à jour la propriété indeterminate de la checkbox
* @param node Nœud de l'arbre
*/
updateBranchState(node) {
if (!node.children)
return;
/**
* Partie recursive de l'algorythme. La suite de cette méthode n'est prise en compte qu'après la mise à jour
* de tous les descendants de la branche en cours.
*/
node.children.forEach((n) => this.updateBranchState(n));
const allSelected = !node.children.some((n) => !n.selected);
const noneSelected = !allSelected && !node.children.some((n) => n.selected || n.selected === undefined);
const newState = allSelected ? true : noneSelected ? false : undefined;
if (node.selected !== newState) {
node.selected = newState;
this.treeSelectable.updateIndeterminate(node);
}
}
/**
* Lance la mise à jour de l'état de sélection de chaque banche en parcourant l'arborescence de bas en haut de manière recursive.
*
* ex: Pour un model tel que le suivant:
* B1
* / \
* B2 B3
* | |
* F1 F2
*
* La méthode updateBranches(B1) tentera de mettre à jour le noeud B2 qui recursivement mettra à jour la
* feuille F1 avant de se mettre elle même (B2) à jour. Ensuite, la méthode mettra à jour les noeuds suivants de
* la même façon, d'abord F2, puis B3. Enfin, une fois tous ses descendants à jour, B1 se mettra lui même à jour.
*/
updateBranches(nodes) {
nodes?.forEach((n) => this.updateBranchState(n));
}
/**
* Retourne le 1er nœud sélectionné dans l'arborescence.
* @param nodes arborescence
* @return 1er nœud sélectionné ou undefined
*/
findFirstNodeSelected(nodes) {
let node = undefined;
nodes.find((n) => {
if (node)
return;
node = n.selected ? n : !n.children ? undefined : this.findFirstNodeSelected(n.children);
});
return node;
}
/**
* Sélectionne / déselectionne récursivement tous les nœuds nodes et leurs descendants
* @param nodes Liste de nœuds à sélectionner
* @param select true : selection des noeuds, false : fermeture
*/
toggleNodesState(nodes, select) {
nodes.forEach((node) => {
if (node.hidden)
return;
node.selected = select;
if (node.children) {
this.toggleNodesState(node.children, select);
}
else {
// Mise a jour liste des noeuds sélectionnés
if (select && !this.selectedNodes.find((n) => n === node) && !node.disabled && !node.hidden) {
this.selectedNodes.push(node);
}
else if (!select && !node.disabled && !node.hidden) {
// suppression des noeuds déselectionnés (on ne supprime pas toute la liste au cas ou un filtre est actif)
const i = this.selectedNodes.findIndex((n) => n === node);
if (i !== -1)
this.selectedNodes.splice(i, 1);
}
}
});
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJlZS1zZWxlY3QtbWFuYWdlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1kc2ZyLWV4dC9zcmMvbGliL3NoYXJlZC91dGlscy90cmVlL3RyZWUtc2VsZWN0LW1hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ2xELE9BQU8sRUFBcUIsc0JBQXNCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQXdCN0Y7Ozs7OztHQU1HO0FBQ0gsTUFBTSxPQUFPLGlCQUFpQjtJQTJCNUIsWUFBWSxjQUE4QjtRQTFCMUM7O1dBRUc7UUFDSCxrQkFBYSxHQUFzQixTQUFTLENBQUM7UUFFN0MsZ0dBQWdHO1FBQ2hHLHNCQUFpQixHQUFtQixNQUFNLENBQUM7UUFFM0MsMkhBQTJIO1FBQzNILGtCQUFhLEdBQWUsRUFBRSxDQUFDO1FBRS9CLDhHQUE4RztRQUM5RyxnQkFBVyxHQUFZLEtBQUssQ0FBQztRQUU3QiwwQ0FBMEM7UUFDMUMsZ0JBQVcsR0FBRyxDQUFDLENBQUM7UUFLaEI7OztXQUdHO1FBQ0ssMkJBQXNCLEdBQUcsS0FBSyxDQUFDO1FBR3JDLElBQUksQ0FBQyxjQUFjLEdBQUcsY0FBYyxDQUFDO0lBQ3ZDLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsSUFBSSxDQUFDLEtBQWlCO1FBQ3BCLDJDQUEyQztRQUMzQyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztRQUM1QyxJQUFJLENBQUMsc0JBQXNCLEdBQUcsS0FBSyxDQUFDO1FBRXBDLDJHQUEyRztRQUMzRyxJQUFJLElBQUksQ0FBQyxjQUFjLEVBQUU7WUFBRSxJQUFJLENBQUMsY0FBYyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRTNELE9BQU8sVUFBVSxDQUFDO0lBQ3BCLENBQUM7SUFFRDs7Ozs7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QyxNQUFNLEVBQUUsQ0FBQztvQkFDckQsMEdBQTBHO29CQUMxRyxNQUFNLENBQUMsR0FBVyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDO29CQUNsRSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7d0JBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO2dCQUNoRCxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgbmV3VW5pcXVlSWQgfSBmcm9tICdAZWR1Z291dmZyL25neC1kc2ZyJztcbmltcG9ydCB7IERzZnJTZWxlY3Rpb25Nb2RlLCBEc2ZyU2VsZWN0aW9uTW9kZUNvbnN0IH0gZnJvbSAnLi4vLi4vbW9kZWxzL3NlbGVjdGlvbi1tb2RlLnR5cGUnO1xuaW1wb3J0IHsgRHNmck5vZGUsIERzZnJWaWV3Tm9kZSB9IGZyb20gJy4vdHJlZS5tb2RlbCc7XG5cbi8qKlxuICogSW50ZXJmYWNlIHV0aWxpc8OpZSBwYXIgVHJlZVNlbGVjdE1hbmFnZXJcbiAqL1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxuZXhwb3J0IGludGVyZmFjZSBUcmVlU2VsZWN0YWJsZSB7XG4gIC8qKiBJbmRpcXVlIHNpIHRvdXRlcyBsZXMgb3B0aW9ucyBzb250IHPDqWxlY3Rpb25uw6llcyBvdSBub24uICovXG4gIGlzQWxsU2VsZWN0ZWQ6IGJvb2xlYW47XG5cbiAgLyoqIFJldG91cm5lIGxhIHN0cnVjdHVyZSBhcmJvcmVzY2VudGUgZHUgY29tcG9zYW50LiAgKi9cbiAgZ2V0IG5vZGVzKCk6IERzZnJOb2RlW107XG5cbiAgLyoqIFPDqWxlY3Rpb25uZSAvIGTDqXPDqWxlY3Rpb25uZSB0b3VzIGxlcyBuxZN1ZHMgZW4gbW9kZSBtdWx0aXBsZSBvdSBjaGVja2JveC4gKi9cbiAgc2VsZWN0QWxsKHNlbGVjdDogYm9vbGVhbik6IHZvaWQ7XG5cbiAgLyoqIE5vdGlmaWUgbGUgY29tcG9zYW50IHF1ZSBub2RlIGEgY2hhbmfDqSBkJ8OpdGF0LiAqL1xuICBub3RpZnlTZWxlY3RFdmVudChub2RlOiBEc2ZyTm9kZSk6IHZvaWQ7XG5cbiAgLyoqIE1pc2Ugw6Agam91ciwgZ3JhcGhpcXVlLCBkdSBzdGF0dXQgaW5kZXRlcm1pbmF0ZS4gKi9cbiAgdXBkYXRlSW5kZXRlcm1pbmF0ZShub2RlOiBEc2ZyTm9kZSk6IHZvaWQ7XG59XG5cbi8qKlxuXG4gKiBUcmVlU2VsZWN0TWFuYWdlciBpbXBsw6ltZW50ZSBsZXMgZm9uY3Rpb25uYWxpdMOpcyBkZSBzw6lsZWN0aW9uIGRlcyBuxZN1ZHMgZCd1bmUgYXJib3Jlc2NlbmNlLlxuICogLSBHw6hyZSBsZSBtb2RlIGRlIHPDqWxlY3Rpb25cbiAqIC0gR8OocmUgbGVzIGNoZWNrYm94XG4gKiAtIE5lIGfDqHJlIHBhcyBsJ2FwcGFyZW5jZSBkZXMgbGliZWxsw6lzIHPDqWxlY3Rpb25uw6lzXG4gKi9cbmV4cG9ydCBjbGFzcyBUcmVlU2VsZWN0TWFuYWdlciB7XG4gIC8qKlxuICAgKiBNb2RlIGRlIHPDqWxlY3Rpb24gZ8OpcsOpIHBhciBsZSBtYW5hZ2VyLiBBY2Nlc3NpYmxlIHBhciBsZXMgY29tcG9zYW50cyB1dGlsaXNhbnQgY2UgbWFuYWdlci5cbiAgICovXG4gIHNlbGVjdGlvbk1vZGU6IERzZnJTZWxlY3Rpb25Nb2RlID0gdW5kZWZpbmVkO1xuXG4gIC8qKiBTdHJhdMOpZ2llIGRlIHPDqWxlY3Rpb24gOiBwb3V2b2lyIHPDqWxlY3Rpb25uZXIgdG91cyBsZXMgbm9ldWRzIG91IHVuaXF1ZW1lbnQgbGVzIGZldWlsbGVzICAqL1xuICBzZWxlY3Rpb25TdHJhdGVneTogJ2xlYWYnIHwgJ2FsbCcgPSAnbGVhZic7XG5cbiAgLyoqIExpc3RlIGRlcyBuxZN1ZHMgc8OpbGVjdGlvbm7DqXMuIFNpIGxlIG1vZGUgZGUgc8OpbGVjdGlvbiBlc3QgJ2NoZWNrYm94Jywgc2V1bCBsZXMgbm9ldWRzIGZldWlsbGVzIHNvbnQgc8OpbGVjdGlvbm5hYmxlcy4gKi9cbiAgc2VsZWN0ZWROb2RlczogRHNmck5vZGVbXSA9IFtdO1xuXG4gIC8qKiBMZXMgbm9ldWRzIGZldWlsbGVzIGRvaXZlbnQgcG9zc8OpZGVyIHVuIGlkIGTDqWZpbmkgw6AgbCdpbml0aWFsaXNhdGlvbiBzaSBjb21wYXJlV2l0aCBuJ2VzdCBwYXMgcmVuc2VpZ27DqSAqL1xuICBub0dlbmVyaWNJZDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIC8qKiBOb21icmUgdG90YWwgZGUgZmV1aWxsZXMgZGUgbCdhcmJyZSAqL1xuICBjb3VudExlYXZlcyA9IDA7XG5cbiAgLyoqIENvbXBvc2FudCBnw6lyw6kgcGFyIGxlIG1hbmFnZXIuICovXG4gIHByaXZhdGUgdHJlZVNlbGVjdGFibGU6IFRyZWVTZWxlY3RhYmxlO1xuXG4gIC8qKlxuICAgKiBBdHRyaWJ1dCBwZXJtZXR0YW50IGRlIG5vdGlmaWVyIHF1J3VuIG5vZXVkIHPDqWxlY3Rpb25uw6kgw6AgZMOpasOgIMOpdMOpIHJlbmNvbnRyw6kgZW4gbW9kZSBzaW5nbGUsIHBlcm1ldHRhbnQgZCdpZ25vcmVyXG4gICAqIGwnw6l0YXQgc8OpbGVjdGlvbm7DqSBkZSB0b3VzIGxlcyBub2V1ZHMgc3Vic8OpcXVlbnRzLlxuICAgKi9cbiAgcHJpdmF0ZSBzaW5nbGVNb2RlU2VsZWN0ZWRTa2lwID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IodHJlZVNlbGVjdGFibGU6IFRyZWVTZWxlY3RhYmxlKSB7XG4gICAgdGhpcy50cmVlU2VsZWN0YWJsZSA9IHRyZWVTZWxlY3RhYmxlO1xuICB9XG5cbiAgLyoqXG4gICAqIMOAIGFwcGVsZXIgw6AgY2hhcXVlIG1vZGlmaWNhdGlvbiBkZSBsJ2FyYm9yZXNjZW5jZS5cbiAgICpcbiAgICogQHBhcmFtIG5vZGVzIE7Fk3VkcyDDoCBpbml0aWFsaXNlclxuICAgKi9cbiAgaW5pdChub2RlczogRHNmck5vZGVbXSk6IERzZnJWaWV3Tm9kZVtdIHtcbiAgICAvLyBJbml0aWFsaXNhdGlvbiBkZSBzZWxlY3RlZCBldCBjaGVja2JveElkXG4gICAgY29uc3Qgbm9kZXNDbG9uZSA9IHRoaXMuaW5pdE5vZGVzKG5vZGVzLCAxKTtcbiAgICB0aGlzLnNpbmdsZU1vZGVTZWxlY3RlZFNraXAgPSBmYWxzZTtcblxuICAgIC8vIERhbnMgbGUgY2FzIGQndXRpbGlzYXRpb24gZGVzIGNoZWNrYm94ZXMsIG9uIG1ldCDDoCBqb3VyIGxhIHZhbGV1ciBkZSBgc2VsZWN0ZWRgIGVuIGZvbmN0aW9uIGRlcyBlbmZhbnRzLlxuICAgIGlmICh0aGlzLmlzQ2hlY2tib3hNb2RlKCkpIHRoaXMudXBkYXRlQnJhbmNoZXMobm9kZXNDbG9uZSk7XG5cbiAgICByZXR1cm4gbm9kZXNDbG9uZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTw6lsZWN0aW9uIC8gZMOpc8OpbGVjdGlvbiBkdSBuxZN1ZCBzdWl0ZSDDoCB1biBjbGljLlxuICAgKiAtIExlIG7Fk3VkIGRldmllbnQgbGUgbsWTdWQgY291cmFudCBlbiBtZXR0YW50IHRhYkluZGV4PTBcbiAgICogLSBHZXN0aW9uIGRlcyBkaWZmw6lyZW50cyBtb2RlcyBkZSBzw6lsZWN0aW9uXG4gICAqIC0gRW52b2llIGQndW5lIG5vdGlmaWNhdGlvbiBzdXIgbGUgY2hhbmdlbWVudCBkJ8OpdGF0IGRlIG5vZGUuc2VsZWN0ZWRcbiAgICogRGFucyBsZSBjYXMgZHUgbW9kZSBjaGVja2JveCwgaWwgbid5IGEgcGFzIGRlIG1vZGlmaWNhdGlvbiBzdWl0ZSBhdXggY2hhbmdlbWVudHMgZCfDqXRhdHMgZGVzIGVuZmFudHNcbiAgICovXG4gIHB1YmxpYyBkb1NlbGVjdE5vZGUobm9kZTogRHNmck5vZGUsIG5vZGVFbHQ6IEhUTUxFbGVtZW50KTogdm9pZCB7XG4gICAgLy8gTGUgbsWTdWQgcXVpIHJlw6dvaXQgbCfDqXbDqW5lbWVudCBkZXZpZW50IGZvY3VzYWJsZVxuICAgIG5vZGVFbHQudGFiSW5kZXggPSAwO1xuXG4gICAgaWYgKCF0aGlzLmlzU2VsZWN0YWJsZSgpKSByZXR1cm47XG5cbiAgICBpZiAodGhpcy5pc1NpbmdsZU1vZGUoKSkgdGhpcy5oYW5kbGVTaW5nbGVNb2RlU2VsZWN0aW9uKG5vZGUpO1xuICAgIGVsc2UgaWYgKHRoaXMuaXNNdWx0aXBsZU1vZGUoKSkgdGhpcy5oYW5kbGVNdWx0aXBsZU1vZGVTZWxlY3Rpb24obm9kZSk7XG4gICAgZWxzZSBpZiAodGhpcy5pc0NoZWNrYm94TW9kZSgpKSB0aGlzLmhhbmRsZUNoZWNrYm94TW9kZVNlbGVjdGlvbihub2RlKTtcbiAgfVxuXG4gIHB1YmxpYyBpc1NlbGVjdGFibGUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0aW9uTW9kZSAhPT0gdW5kZWZpbmVkO1xuICB9XG5cbiAgcHVibGljIGlzQ2hlY2tib3hNb2RlKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnNlbGVjdGlvbk1vZGUgPT09IERzZnJTZWxlY3Rpb25Nb2RlQ29uc3QuQ0hFQ0tCT1g7XG4gIH1cblxuICBwdWJsaWMgaXNTaW5nbGVNb2RlKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnNlbGVjdGlvbk1vZGUgPT09IERzZnJTZWxlY3Rpb25Nb2RlQ29uc3QuU0lOR0xFO1xuICB9XG5cbiAgcHVibGljIGlzTXVsdGlwbGVNb2RlKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnNlbGVjdGlvbk1vZGUgPT09IERzZnJTZWxlY3Rpb25Nb2RlQ29uc3QuTVVMVElQTEU7XG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhbGlzYXRpb24gcGFyIGTDqWZhdXQgZGVzIHByb3ByacOpdMOpcyBkJ3VuIG7Fk3VkIDogJ3NlbGVjdGVkJywgJ2lkJy5cbiAgICpcbiAgICogQHBhcmFtIG5vZGVzIExlcyBub2V1ZHMgw6AgaW5pdGlhbGlzZXJcbiAgICogQHBhcmFtIGxldmVsIExlIG5pdmVhdSBkdSBub2V1ZCBkYW5zIGxhIGhpw6lyYXJjaGllXG4gICAqL1xuICBwdWJsaWMgaW5pdE5vZGVzKG5vZGVzOiBEc2ZyTm9kZVtdLCBsZXZlbDogbnVtYmVyKTogRHNmclZpZXdOb2RlW10ge1xuICAgIGNvbnN0IHNpemUgPSBub2Rlcy5sZW5ndGg7XG5cbiAgICByZXR1cm4gbm9kZXMubWFwKChuKSA9PiB7XG4gICAgICBjb25zdCBub2RlVmlldzogRHNmclZpZXdOb2RlID0ge1xuICAgICAgICAuLi5uLFxuICAgICAgICBpZDogbi5pZCB8fCBuZXdVbmlxdWVJZCgpLFxuICAgICAgICBhcmlhTGV2ZWw6IGxldmVsLFxuICAgICAgICBhcmlhU2l6ZTogc2l6ZSxcbiAgICAgICAgY2hpbGRyZW46IG4uY2hpbGRyZW4gPyB0aGlzLmluaXROb2RlcyhuLmNoaWxkcmVuLCBsZXZlbCArIDEpIDogdW5kZWZpbmVkLFxuICAgICAgfTtcblxuICAgICAgaWYgKCFuLmNoaWxkcmVuICYmICFuLmRpc2FibGVkKSB7XG4gICAgICAgIHRoaXMuY291bnRMZWF2ZXMrKztcbiAgICAgIH1cblxuICAgICAgaWYgKCFuLmNoaWxkcmVuICYmICFuLmlkICYmIHRoaXMubm9HZW5lcmljSWQpIHtcbiAgICAgICAgY29uc29sZS53YXJuKGBMYSBmb25jdGlvbiBjb21wYXJlV2l0aCBkb2l0IMOqdHJlIGTDqWZpbmllOiBcIiR7bi5sYWJlbH1cIiBuJ2EgcGFzIGQnYXR0cmlidXQgJ2lkJy5gKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuaXNTZWxlY3RhYmxlKCkpIHtcbiAgICAgICAgdGhpcy5oYW5kbGVOb2RlU2VsZWN0ZWRJbml0aWFsaXphdGlvbihuLCBub2RlVmlldyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBub2RlVmlldztcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNaXNlIMOgIGpvdXIgZGVzIHByb3ByacOpdMOpcyBkZXMgbsWTdWRzIChsYWJlbCwgZGF0YSwgaWQpIHNhbnMgbW9kaWZpZXIgbCfDqXRhdCAoc2VsZWN0LCBleHBhbmQpIGV0IGFqb3V0cyDDqXZlbnR1ZWxzLlxuICAgKiBAcGFyYW0gbm9kZXMgTsWTdWRzIGQnZW50csOpZSDDoCBtZXR0cmUgw6Agam91ci5cbiAgICogQHBhcmFtIHZpZXdOb2RlcyBOxZN1ZHMgY2xvbsOpcyByZXByw6lzZW50YW50IGwnw6l0YXQgYWN0dWVsIGRlIGwnYXJicmUuXG4gICAqL1xuICBwdWJsaWMgdXBkYXRlTm9kZXNDb250ZW50KG5vZGVzOiBEc2ZyTm9kZVtdLCB2aWV3Tm9kZXM6IERzZnJWaWV3Tm9kZVtdLCBsZXZlbDogbnVtYmVyKTogRHNmck5vZGVbXSB7XG4gICAgY29uc3Qgc2l6ZSA9IG5vZGVzLmxlbmd0aDtcblxuICAgIHJldHVybiBub2Rlcy5tYXAoKG5vZGUpID0+IHtcbiAgICAgIC8vIG5vZXVkIGNvcnJlc3BvbmRhbnQgZGFucyBsJ2FyYnJlIGNsb27DqVxuICAgICAgY29uc3QgbWF0Y2hpbmdOb2RlVmlldyA9IHZpZXdOb2Rlcy5maW5kKChuKSA9PiBuLmlkID09PSBub2RlLmlkKTtcblxuICAgICAgaWYgKG1hdGNoaW5nTm9kZVZpZXcpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAuLi5ub2RlLCAvLyBvbiByw6ljdXDDqHJlIGxlcyBub3V2ZWxsZXMgdmFsZXVycyB0cmFuc21pc2VzIHBhciBsJ3V0aWxpc2F0ZXVyIGR1IGNvbXBvc2FudFxuICAgICAgICAgIGlkOiBub2RlLmlkIHx8IG1hdGNoaW5nTm9kZVZpZXcuaWQsIC8vIHNpIGwnaWQgbidhIHBhcyDDqXTDqSBwb3NpdGlvbm7DqSwgb24gcsOpY3Vww6hyZSBjZWx1aSBxdWkgYSDDqXTDqSBnw6luw6lyw6lcbiAgICAgICAgICBzZWxlY3RlZDogbWF0Y2hpbmdOb2RlVmlldy5zZWxlY3RlZCwgLy8gb24gcmVzdGF1cmUgbCfDqXRhdCBkZSBzw6lsZWN0aW9uIGNvdXJhbnRcbiAgICAgICAgICBleHBhbmRlZDogbWF0Y2hpbmdOb2RlVmlldy5leHBhbmRlZCwgLy8gb24gcmVzdGF1cmUgbCfDqXRhdCBkJ2V4cGFuc2lvbiBjb3VyYW50XG4gICAgICAgICAgYXJpYUxldmVsOiBtYXRjaGluZ05vZGVWaWV3LmFyaWFMZXZlbCwgLy8gb24gcmVzdGF1cmUgbGUgbml2ZWF1IGRlIGhpw6lyYXJjaGllXG4gICAgICAgICAgYXJpYVNpemU6IHNpemUsIC8vIG9uIHJlc3RhdXJlIGxhIHRhaWxsZSwgY2FyIGVsbGUgYSBwdSBjaGFuZ2VyXG4gICAgICAgICAgY2hpbGRyZW46IG5vZGUuY2hpbGRyZW5cbiAgICAgICAgICAgID8gdGhpcy51cGRhdGVOb2Rlc0NvbnRlbnQobm9kZS5jaGlsZHJlbiwgbWF0Y2hpbmdOb2RlVmlldy5jaGlsZHJlbiB8fCBbXSwgbGV2ZWwgKyAxKVxuICAgICAgICAgICAgOiBtYXRjaGluZ05vZGVWaWV3LmNoaWxkcmVuLFxuICAgICAgICB9O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gIGF1Y3VuIG5vZXVkIGNvcnJlc3BvbmRhbnQsIGFqb3V0ZXIgbGEgbm91dmVsbGUgc3RydWN0dXJlXG4gICAgICAgIGNvbnN0IG5vZGVWaWV3OiBEc2ZyVmlld05vZGUgPSB7XG4gICAgICAgICAgLi4ubm9kZSxcbiAgICAgICAgICBpZDogbm9kZS5pZCB8fCBuZXdVbmlxdWVJZCgpLFxuICAgICAgICAgIGFyaWFMZXZlbDogbGV2ZWwsXG4gICAgICAgICAgYXJpYVNpemU6IHNpemUsXG4gICAgICAgICAgY2hpbGRyZW46IG5vZGUuY2hpbGRyZW4gPyB0aGlzLmluaXROb2Rlcyhub2RlLmNoaWxkcmVuLCBsZXZlbCArIDEpIDogdW5kZWZpbmVkLFxuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiBub2RlVmlldztcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBzZWxlY3RBbGxOb2Rlcyhub2RlczogRHNmck5vZGVbXSwgc2VsZWN0ID0gdHJ1ZSkge1xuICAgIGNvbnN0IGlzTXVsdGlwbGUgPVxuICAgICAgdGhpcy5zZWxlY3Rpb25Nb2RlID09PSBEc2ZyU2VsZWN0aW9uTW9kZUNvbnN0Lk1VTFRJUExFIHx8IHRoaXMuc2VsZWN0aW9uTW9kZSA9PT0gRHNmclNlbGVjdGlvbk1vZGVDb25zdC5DSEVDS0JPWDtcbiAgICBpZiAoaXNNdWx0aXBsZSB8fCAodGhpcy5pc1NpbmdsZU1vZGUoKSAmJiAhc2VsZWN0KSkgdGhpcy50b2dnbGVOb2Rlc1N0YXRlKG5vZGVzLCBzZWxlY3QpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1pc2Ugw6Agam91ciBsaXN0ZSBkZXMgZmV1aWxsZXMgc8OpbGVjdGlvbm7DqWVzXG4gICAqIChzdXBwcmVzc2lvbiBkZXMgbsWTdWRzIG5vbiBzw6lsZWN0aW9ubsOpcylcbiAgICovXG4gIHB1YmxpYyB1cGRhdGVTZWxlY3RlZE5vZGVzKCk6IERzZnJOb2RlW10ge1xuICAgIHRoaXMuc2VsZWN0ZWROb2RlcyA9IHRoaXMuc2VsZWN0ZWROb2Rlcy5maWx0ZXIoKG4pID0+IG4uc2VsZWN0ZWQpO1xuICAgIHJldHVybiB0aGlzLnNlbGVjdGVkTm9kZXM7XG4gIH1cblxuICAvKipcbiAgICogRMOpdGVybWluZSBsJ8OpdGF0IGRlIGwnYXR0cmlidXQgc2VsZWN0ZWQgZCd1biBub2V1ZCBlbiBmb25jdGlvbiBkdSBtb2RlIGNvdXJhbnQgZXQgZHUgbW9kZWwgZm91cm5pdC5cbiAgICpcbiAgICogQHBhcmFtIG5vZGUgTsWTdWQgZHUgbW9kZWwgZm91cm5pdC5cbiAgICogQHBhcmFtIHZpZXdOb2RlIE7Fk3VkIGNsb27DqSByZXByw6lzZW50YW50IGwnw6l0YXQgYWN0dWVsIGRlIGwnYXJicmUuXG4gICAqL1xuICBwcml2YXRlIGhhbmRsZU5vZGVTZWxlY3RlZEluaXRpYWxpemF0aW9uKG5vZGU6IERzZnJOb2RlLCB2aWV3Tm9kZTogRHNmclZpZXdOb2RlKSB7XG4gICAgaWYgKHRoaXMuc2luZ2xlTW9kZVNlbGVjdGVkU2tpcCkge1xuICAgICAgdmlld05vZGUuc2VsZWN0ZWQgPSBmYWxzZTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuaXNDaGVja2JveE1vZGUoKSB8fCAhbm9kZS5jaGlsZHJlbikge1xuICAgICAgdmlld05vZGUuc2VsZWN0ZWQgPSBub2RlLnNlbGVjdGVkIHx8IGZhbHNlO1xuICAgIH1cbiAgICBpZiAoKCF2aWV3Tm9kZS5jaGlsZHJlbiB8fCB0aGlzLnNlbGVjdGlvblN0cmF0ZWd5ID09PSAnYWxsJykgJiYgdmlld05vZGUuc2VsZWN0ZWQpIHtcbiAgICAgIC8vIHVwZGF0ZSBsaXN0IG9mIHNlbGVjdGVkIG5vZGVzXG4gICAgICB0aGlzLnNlbGVjdGVkTm9kZXMucHVzaCh2aWV3Tm9kZSk7XG4gICAgfVxuXG4gICAgaWYgKG5vZGUuc2VsZWN0ZWQgJiYgdGhpcy5pc1NpbmdsZU1vZGUoKSkge1xuICAgICAgdGhpcy5zaW5nbGVNb2RlU2VsZWN0ZWRTa2lwID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHRvZ2dsZU5vZGVTZWxlY3RlZFN0YXRlKG5vZGU6IERzZnJOb2RlKSB7XG4gICAgbm9kZS5zZWxlY3RlZCA9ICFub2RlLnNlbGVjdGVkO1xuXG4gICAgaWYgKCFub2RlLnNlbGVjdGVkKSB7XG4gICAgICB0aGlzLnRyZWVTZWxlY3RhYmxlLmlzQWxsU2VsZWN0ZWQgPSBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZVNpbmdsZU1vZGVTZWxlY3Rpb24obm9kZTogRHNmck5vZGUpIHtcbiAgICBjb25zdCBwcmV2U2luZ2xlTm9kZSA9IHRoaXMuZmluZEZpcnN0Tm9kZVNlbGVjdGVkKHRoaXMudHJlZVNlbGVjdGFibGUubm9kZXMpO1xuXG4gICAgaWYgKHByZXZTaW5nbGVOb2RlICYmIHByZXZTaW5nbGVOb2RlICE9PSBub2RlKSB7XG4gICAgICBwcmV2U2luZ2xlTm9kZS5zZWxlY3RlZCA9IGZhbHNlO1xuICAgICAgLy8gZW52b2kgZGUgbCfDqXbDqG5lbWVudCBub3RpZmlhbnQgbGEgZMOpc2VsZWN0aW9uIGR1IG5vZXVkIHByw6ljw6lkYW50XG4gICAgICB0aGlzLnRyZWVTZWxlY3RhYmxlLm5vdGlmeVNlbGVjdEV2ZW50KHByZXZTaW5nbGVOb2RlKTtcbiAgICB9XG5cbiAgICAvLyBham91dCBkZSBsJ3VuaXF1ZSBuxZN1ZCBzw6lsZWN0aW9ubmFibGVcbiAgICBpZiAoIW5vZGUuY2hpbGRyZW4gfHwgdGhpcy5zZWxlY3Rpb25TdHJhdGVneSAhPT0gJ2xlYWYnKSB0aGlzLnNlbGVjdGVkTm9kZXMgPSBbbm9kZV07XG5cbiAgICB0aGlzLnRvZ2dsZU5vZGVTZWxlY3RlZFN0YXRlKG5vZGUpO1xuICAgIHRoaXMudHJlZVNlbGVjdGFibGUubm90aWZ5U2VsZWN0RXZlbnQobm9kZSk7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZU11bHRpcGxlTW9kZVNlbGVjdGlvbihub2RlOiBEc2ZyTm9kZSkge1xuICAgIHRoaXMuc2VsZWN0ZWROb2Rlcy5wdXNoKG5vZGUpO1xuICAgIHRoaXMudXBkYXRlU2VsZWN0ZWROb2RlcygpO1xuICAgIHRoaXMudG9nZ2xlTm9kZVNlbGVjdGVkU3RhdGUobm9kZSk7XG4gICAgdGhpcy50cmVlU2VsZWN0YWJsZS5ub3RpZnlTZWxlY3RFdmVudChub2RlKTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlQ2hlY2tib3hNb2RlU2VsZWN0aW9uKG5vZGU6IERzZnJOb2RlKSB7XG4gICAgdGhpcy50b2dnbGVOb2RlU2VsZWN0ZWRTdGF0ZShub2RlKTtcblxuICAgIC8vIFByb3BhZ2F0aW9uIGRlIGxhIHPDqWxlY3Rpb25cbiAgICB0aGlzLnVwZGF0ZUNoaWxkcmVuKG5vZGUsIDxib29sZWFuPm5vZGUuc2VsZWN0ZWQpO1xuICAgIC8vIE1pc2Ugw6Agam91ciBkZXMgcGFyZW50cyBwb3VyIHRvdXQgbGUgbW9kZWxcbiAgICB0aGlzLnVwZGF0ZUJyYW5jaGVzKHRoaXMudHJlZVNlbGVjdGFibGUubm9kZXMpO1xuXG4gICAgdGhpcy51cGRhdGVTZWxlY3RlZE5vZGVzKCk7XG4gICAgdGhpcy50cmVlU2VsZWN0YWJsZS5ub3RpZnlTZWxlY3RFdmVudChub2RlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXQgw6Agam91ciwgcsOpY3Vyc2l2ZW1lbnQsIGwnw6l0YXQgZGUgY2hhcXVlIG7Fk3VkIGVuIHBhcmNvdXJhbnQgbCdhcmJvcmVzY2VuY2UgZGUgaGF1dCBlbiBiYXMuXG4gICAqL1xuICBwcml2YXRlIHVwZGF0ZUNoaWxkcmVuKG5vZGU6IERzZnJOb2RlLCBzZWxlY3RlZDogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmIChub2RlLmRpc2FibGVkIHx8IG5vZGUuaGlkZGVuKSByZXR1cm47XG5cbiAgICBub2RlLnNlbGVjdGVkID0gc2VsZWN0ZWQ7XG5cbiAgICAvLyBEYW5zIGxlIGNhcyBkJ3V0aWxpc2F0aW9uIGRlcyBjaGVja2JveGVzLCBvbiBwcm9wYWdlIGwnw6l0YXQgYXV4IGVuZmFudHNcbiAgICBpZiAodGhpcy5pc0NoZWNrYm94TW9kZSgpKSB7XG4gICAgICBub2RlLmNoaWxkcmVuPy5mb3JFYWNoKChuKSA9PiB0aGlzLnVwZGF0ZUNoaWxkcmVuKG4sIHNlbGVjdGVkKSk7XG5cbiAgICAgIGlmICghbm9kZS5jaGlsZHJlbiAmJiBub2RlLnNlbGVjdGVkICYmICF0aGlzLnNlbGVjdGVkTm9kZXMuZmluZCgobikgPT4gbi5pZCA9PT0gbm9kZS5pZCkpIHtcbiAgICAgICAgLy8gQWpvdXQgZHUgbsWTdWQgKGZldWlsbGUpIHPDqWxlY3Rpb25uw6kgZGFucyBsYSBsaXN0ZVxuICAgICAgICB0aGlzLnNlbGVjdGVkTm9kZXMucHVzaChub2RlKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWV0IMOgIGpvdXIgbCfDqXRhdCBgc2VsZWN0ZWRgIGQndW5lIGJyYW5jaGUgZW4gZm9uY3Rpb24gZGUgc2VzIG7Fk3VkcyBlbmZhbnRzICgndHJ1ZScsICdmYWxzZScgb3UgJ3VuZGVmaW5lZCcpLlxuICAgKiDDiW1ldCB1biDDqXbDqW5lbWVudCBzaSBsJ8OpdGF0IGR1IG7Fk3VkIGNoYW5nZS5cbiAgICogTWV0IMOgIGpvdXIgbGEgcHJvcHJpw6l0w6kgaW5kZXRlcm1pbmF0ZSBkZSBsYSBjaGVja2JveFxuICAgKiBAcGFyYW0gbm9kZSBOxZN1ZCBkZSBsJ2FyYnJlXG4gICAqL1xuICBwcml2YXRlIHVwZGF0ZUJyYW5jaFN0YXRlKG5vZGU6IERzZnJOb2RlKTogdm9pZCB7XG4gICAgaWYgKCFub2RlLmNoaWxkcmVuKSByZXR1cm47XG5cbiAgICAvKipcbiAgICAgKiBQYXJ0aWUgcmVjdXJzaXZlIGRlIGwnYWxnb3J5dGhtZS4gTGEgc3VpdGUgZGUgY2V0dGUgbcOpdGhvZGUgbidlc3QgcHJpc2UgZW4gY29tcHRlIHF1J2FwcsOocyBsYSBtaXNlIMOgIGpvdXJcbiAgICAgKiBkZSB0b3VzIGxlcyBkZXNjZW5kYW50cyBkZSBsYSBicmFuY2hlIGVuIGNvdXJzLlxuICAgICAqL1xuICAgIG5vZGUuY2hpbGRyZW4uZm9yRWFjaCgobikgPT4gdGhpcy51cGRhdGVCcmFuY2hTdGF0ZShuKSk7XG5cbiAgICBjb25zdCBhbGxTZWxlY3RlZCA9ICFub2RlLmNoaWxkcmVuLnNvbWUoKG4pID0+ICFuLnNlbGVjdGVkKTtcbiAgICBjb25zdCBub25lU2VsZWN0ZWQgPSAhYWxsU2VsZWN0ZWQgJiYgIW5vZGUuY2hpbGRyZW4uc29tZSgobikgPT4gbi5zZWxlY3RlZCB8fCBuLnNlbGVjdGVkID09PSB1bmRlZmluZWQpO1xuICAgIGNvbnN0IG5ld1N0YXRlID0gYWxsU2VsZWN0ZWQgPyB0cnVlIDogbm9uZVNlbGVjdGVkID8gZmFsc2UgOiB1bmRlZmluZWQ7XG5cbiAgICBpZiAobm9kZS5zZWxlY3RlZCAhPT0gbmV3U3RhdGUpIHtcbiAgICAgIG5vZGUuc2VsZWN0ZWQgPSBuZXdTdGF0ZTtcbiAgICAgIHRoaXMudHJlZVNlbGVjdGFibGUudXBkYXRlSW5kZXRlcm1pbmF0ZShub2RlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTGFuY2UgbGEgbWlzZSDDoCBqb3VyIGRlIGwnw6l0YXQgZGUgc8OpbGVjdGlvbiBkZSBjaGFxdWUgYmFuY2hlIGVuIHBhcmNvdXJhbnQgbCdhcmJvcmVzY2VuY2UgZGUgYmFzIGVuIGhhdXQgZGUgbWFuacOocmUgcmVjdXJzaXZlLlxuICAgKlxuICAgKiBleDogUG91ciB1biBtb2RlbCB0ZWwgcXVlIGxlIHN1aXZhbnQ6XG4gICAqICAgIEIxXG4gICAqICAgLyBcXFxuICAgKiAgQjIgIEIzXG4gICAqICB8ICAgfFxuICAgKiAgRjEgIEYyXG4gICAqXG4gICAqIExhIG3DqXRob2RlIHVwZGF0ZUJyYW5jaGVzKEIxKSB0ZW50ZXJhIGRlIG1ldHRyZSDDoCBqb3VyIGxlIG5vZXVkIEIyIHF1aSByZWN1cnNpdmVtZW50IG1ldHRyYSDDoCBqb3VyIGxhXG4gICAqIGZldWlsbGUgRjEgYXZhbnQgZGUgc2UgbWV0dHJlIGVsbGUgbcOqbWUgKEIyKSDDoCBqb3VyLiBFbnN1aXRlLCBsYSBtw6l0aG9kZSBtZXR0cmEgw6Agam91ciBsZXMgbm9ldWRzIHN1aXZhbnRzIGRlXG4gICAqIGxhIG3Dqm1lIGZhw6dvbiwgZCdhYm9yZCBGMiwgcHVpcyBCMy4gRW5maW4sIHVuZSBmb2lzIHRvdXMgc2VzIGRlc2NlbmRhbnRzIMOgIGpvdXIsIEIxIHNlIG1ldHRyYSBsdWkgbcOqbWUgw6Agam91ci5cbiAgICovXG4gIHByaXZhdGUgdXBkYXRlQnJhbmNoZXMobm9kZXM6IERzZnJOb2RlW10pIHtcbiAgICBub2Rlcz8uZm9yRWFjaCgobikgPT4gdGhpcy51cGRhdGVCcmFuY2hTdGF0ZShuKSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0b3VybmUgbGUgMWVyIG7Fk3VkIHPDqWxlY3Rpb25uw6kgZGFucyBsJ2FyYm9yZXNjZW5jZS5cbiAgICogQHBhcmFtIG5vZGVzIGFyYm9yZXNjZW5jZVxuICAgKiBAcmV0dXJuIDFlciBuxZN1ZCBzw6lsZWN0aW9ubsOpIG91IHVuZGVmaW5lZFxuICAgKi9cbiAgcHJpdmF0ZSBmaW5kRmlyc3ROb2RlU2VsZWN0ZWQobm9kZXM6IERzZnJOb2RlW10pOiBEc2ZyTm9kZSB8IHVuZGVmaW5lZCB7XG4gICAgbGV0IG5vZGU6IERzZnJOb2RlIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuICAgIG5vZGVzLmZpbmQoKG4pID0+IHtcbiAgICAgIGlmIChub2RlKSByZXR1cm47XG4gICAgICBub2RlID0gbi5zZWxlY3RlZCA/IG4gOiAhbi5jaGlsZHJlbiA/IHVuZGVmaW5lZCA6IHRoaXMuZmluZEZpcnN0Tm9kZVNlbGVjdGVkKG4uY2hpbGRyZW4pO1xuICAgIH0pO1xuICAgIHJldHVybiBub2RlO1xuICB9XG5cbiAgLyoqXG4gICAqIFPDqWxlY3Rpb25uZSAvIGTDqXNlbGVjdGlvbm5lIHLDqWN1cnNpdmVtZW50IHRvdXMgbGVzIG7Fk3VkcyBub2RlcyBldCBsZXVycyBkZXNjZW5kYW50c1xuICAgKiBAcGFyYW0gbm9kZXMgTGlzdGUgZGUgbsWTdWRzIMOgIHPDqWxlY3Rpb25uZXJcbiAgICogQHBhcmFtIHNlbGVjdCB0cnVlIDogc2VsZWN0aW9uIGRlcyBub2V1ZHMsIGZhbHNlIDogZmVybWV0dXJlXG4gICAqL1xuICBwcml2YXRlIHRvZ2dsZU5vZGVzU3RhdGUobm9kZXM6IERzZnJOb2RlW10sIHNlbGVjdDogYm9vbGVhbikge1xuICAgIG5vZGVzLmZvckVhY2goKG5vZGUpID0+IHtcbiAgICAgIGlmIChub2RlLmhpZGRlbikgcmV0dXJuO1xuICAgICAgbm9kZS5zZWxlY3RlZCA9IHNlbGVjdDtcbiAgICAgIGlmIChub2RlLmNoaWxkcmVuKSB7XG4gICAgICAgIHRoaXMudG9nZ2xlTm9kZXNTdGF0ZShub2RlLmNoaWxkcmVuLCBzZWxlY3QpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gTWlzZSBhIGpvdXIgbGlzdGUgZGVzIG5vZXVkcyBzw6lsZWN0aW9ubsOpc1xuICAgICAgICBpZiAoc2VsZWN0ICYmICF0aGlzLnNlbGVjdGVkTm9kZXMuZmluZCgobikgPT4gbiA9PT0gbm9kZSkgJiYgIW5vZGUuZGlzYWJsZWQgJiYgIW5vZGUuaGlkZGVuKSB7XG4gICAgICAgICAgdGhpcy5zZWxlY3RlZE5vZGVzLnB1c2gobm9kZSk7XG4gICAgICAgIH0gZWxzZSBpZiAoIXNlbGVjdCAmJiAhbm9kZS5kaXNhYmxlZCAmJiAhbm9kZS5oaWRkZW4pIHtcbiAgICAgICAgICAvLyBzdXBwcmVzc2lvbiBkZXMgbm9ldWRzIGTDqXNlbGVjdGlvbm7DqXMgKG9uIG5lIHN1cHByaW1lIHBhcyB0b3V0ZSBsYSBsaXN0ZSBhdSBjYXMgb3UgdW4gZmlsdHJlIGVzdCBhY3RpZilcbiAgICAgICAgICBjb25zdCBpOiBudW1iZXIgPSB0aGlzLnNlbGVjdGVkTm9kZXMuZmluZEluZGV4KChuKSA9PiBuID09PSBub2RlKTtcbiAgICAgICAgICBpZiAoaSAhPT0gLTEpIHRoaXMuc2VsZWN0ZWROb2Rlcy5zcGxpY2UoaSwgMSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufVxuIl19