@esfaenza/es-diagrams 18.2.2 → 19.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/esfaenza-es-diagrams.mjs +18 -18
- package/fesm2022/esfaenza-es-diagrams.mjs.map +1 -1
- package/package.json +3 -5
- package/esm2022/esfaenza-es-diagrams.mjs +0 -5
- package/esm2022/lib/components/es-diagram.component.mjs +0 -537
- package/esm2022/lib/esdiagram.module.mjs +0 -32
- package/esm2022/lib/extensions/ReactiveExtensions.mjs +0 -36
- package/esm2022/lib/extensions/ResizeSensor.mjs +0 -71
- package/esm2022/lib/models/EsDiagramModuleConfig.mjs +0 -6
- package/esm2022/lib/models/component/contextmenu/ContextMenuCommand.mjs +0 -6
- package/esm2022/lib/models/component/contextmenu/ContextMenuOptions.mjs +0 -7
- package/esm2022/lib/models/component/grouping/ExpandCollapseOptions.mjs +0 -6
- package/esm2022/lib/models/component/nodes/NodeHTMLTemplate.mjs +0 -6
- package/esm2022/lib/models/component/nodes/NodeTemplate.mjs +0 -6
- package/esm2022/lib/models/component/nodes/ZoomLevelBasedTemplate.mjs +0 -6
- package/esm2022/lib/models/layouts/BreadthFirstLayoutOptionsImpl.mjs +0 -35
- package/esm2022/lib/models/layouts/CircleLayoutOptionsImpl.mjs +0 -27
- package/esm2022/lib/models/layouts/ConcentricLayoutOptionsImpl.mjs +0 -64
- package/esm2022/lib/models/layouts/CoseLayoutOptionsImpl.mjs +0 -83
- package/esm2022/lib/models/layouts/DagreLayoutOptionsImpl.mjs +0 -52
- package/esm2022/lib/models/layouts/GridLayoutOptionsImpl.mjs +0 -38
- package/esm2022/lib/models/layouts/NullLayoutOptionsImpl.mjs +0 -15
- package/esm2022/lib/models/layouts/PresetLayoutOptionsImpl.mjs +0 -24
- package/esm2022/lib/models/layouts/RandomLayoutOptionsImpl.mjs +0 -36
- package/esm2022/lib/models/layouts/base/AnimateLayoutOptionsImpl.mjs +0 -42
- package/esm2022/lib/models/layouts/base/BaseLayoutOptionsImpl.mjs +0 -18
- package/esm2022/lib/models/layouts/base/ShapedLayoutOptionsImpl.mjs +0 -48
- package/esm2022/lib/services/es-diagram.dispatcher.mjs +0 -89
- package/esm2022/lib/services/es-diagram.service.mjs +0 -106
- package/esm2022/lib/tokens.mjs +0 -6
- package/esm2022/public-api.mjs +0 -24
|
@@ -1,537 +0,0 @@
|
|
|
1
|
-
import { Component, EventEmitter, Input, Optional, Output, ViewChild } from '@angular/core';
|
|
2
|
-
import { ResizeSensor } from "../extensions/ResizeSensor";
|
|
3
|
-
import * as cy_ from 'cytoscape';
|
|
4
|
-
import * as i0 from "@angular/core";
|
|
5
|
-
import * as i1 from "../services/es-diagram.service";
|
|
6
|
-
import * as i2 from "../services/es-diagram.dispatcher";
|
|
7
|
-
import * as i3 from "../extensions/ReactiveExtensions";
|
|
8
|
-
/** @ignore */ const cytoscape = cy_.default ? cy_.default : cy_;
|
|
9
|
-
/**
|
|
10
|
-
* Componente che si occupa di graficare un diagramma e di gestirne il ciclo di vita
|
|
11
|
-
*/
|
|
12
|
-
export class EsDiagramComponent {
|
|
13
|
-
/**
|
|
14
|
-
* Costruttore
|
|
15
|
-
*
|
|
16
|
-
* @ignore
|
|
17
|
-
*/
|
|
18
|
-
constructor(service, dispatcher, exts) {
|
|
19
|
-
this.service = service;
|
|
20
|
-
this.dispatcher = dispatcher;
|
|
21
|
-
this.exts = exts;
|
|
22
|
-
/**
|
|
23
|
-
* Nome del diagramma, fondamentale assegnarlo per permettere alla libreria di schedularne la creazione
|
|
24
|
-
*/
|
|
25
|
-
this.name = "";
|
|
26
|
-
/**
|
|
27
|
-
* Indica se utilizzare il menù contestuale a ruota attorno ad ogni nodo
|
|
28
|
-
*/
|
|
29
|
-
this.UseContextMenu = false;
|
|
30
|
-
/**
|
|
31
|
-
* Dice al componente se il diagramma deve utilizzare il sistema di estensione per l'expand e collapse dei gruppi
|
|
32
|
-
*/
|
|
33
|
-
this.UseExpandCollapse = false;
|
|
34
|
-
/**
|
|
35
|
-
* Blocco completo delle opzioni, alternativo all'assegnazione di **Elements**, **NodeStyles**, **EdgeStyles**, e **Layout**.
|
|
36
|
-
*
|
|
37
|
-
* Qualora entrambe venissero specificate verrà effettuata un'unione fra queste opzioni e quelle specificate, dando priorità alle specificate
|
|
38
|
-
*/
|
|
39
|
-
this.NativeOptions = {};
|
|
40
|
-
/**
|
|
41
|
-
* Aggiorna automaticamente le dimensioni del diagramma quando cambiano le dimensioni della finestra
|
|
42
|
-
*/
|
|
43
|
-
this.AutoupdateSize = true;
|
|
44
|
-
/**
|
|
45
|
-
* Indica di mantenere la posizione dei nodi qualora venissero cambiati dall'Input **Elements**.
|
|
46
|
-
*
|
|
47
|
-
* Se l'ID di un nodo è uguale all'ID di un nodo presente in precedenza, il nuovo nodo ne erediterà la posizione
|
|
48
|
-
*/
|
|
49
|
-
this.PreserveElementsPosition = true;
|
|
50
|
-
/**
|
|
51
|
-
* Qualora venisse modificato l'Input **Elements**, piuttosto che mettere semplicemente il nuovo Elemento in base al Layout precedente, applica anche un'animazione
|
|
52
|
-
*
|
|
53
|
-
* Funziona solamente se il **Layout** corrente del diagramma supporta le animazioni
|
|
54
|
-
*/
|
|
55
|
-
this.AnimateLayoutChanges = true;
|
|
56
|
-
/**
|
|
57
|
-
* Attiva una modalità di selezione "smart"... o perlomeno "smarter" del default di Cytoscape.
|
|
58
|
-
*
|
|
59
|
-
* - Il click di un elemento non selezionato lo seleziona
|
|
60
|
-
* - Il click di un elemento selezionato lo deseleziona
|
|
61
|
-
* - Lo stato di selezione viene persistito sull'oggetto originale invece di rimanere in un internal
|
|
62
|
-
* - All'assegnazione di oggetti selezionati, questi vengono marcati correttamente con l'overlay di selezione
|
|
63
|
-
*
|
|
64
|
-
* N.B: la chiamata all'evento **onNodeClick** avviene **DOPO** la gestione della selezione
|
|
65
|
-
*/
|
|
66
|
-
this.SmartSelection = false;
|
|
67
|
-
/**
|
|
68
|
-
* Indica di selezionare un elemento per volta qualora **SmartSelection** fosse attivo
|
|
69
|
-
*/
|
|
70
|
-
this.SingleSelection = false;
|
|
71
|
-
/**
|
|
72
|
-
* CSS per la graficazione della selezione dei nodi. Quando un nodo verrà selezionato avrà sopra di se un overlay che 'sborda' di **overlay-padding** pixel,
|
|
73
|
-
* di colore **overlay-color** e con un opacità **overlay-opacity**
|
|
74
|
-
*
|
|
75
|
-
* Assegnando "{}" a questo input, la Smart selection viene gestita ma la gestione grafica è affidata all'utente,
|
|
76
|
-
* ad esempio usando dei **NodeHTMLTemplates** che definiscano selettori su nodi ":selected"
|
|
77
|
-
*
|
|
78
|
-
* @default {'overlay-color':'blue','overlay-opacity':0.5,'overlay-padding':7}
|
|
79
|
-
*/
|
|
80
|
-
this.SmartSelectionStyles = null;
|
|
81
|
-
/**
|
|
82
|
-
* Periodo di throttle da quando viene effettuato un resize a quando ricalcolare le dimensioni del diagramma.
|
|
83
|
-
*
|
|
84
|
-
* Può essere tenuto a 0 (redraw istantaneo) finché non ci sono problemi di prestazioni con eventualmente tanti resize a poca distanza l'uno dall'altro.
|
|
85
|
-
*/
|
|
86
|
-
this.ResizeThrottleTime = 0;
|
|
87
|
-
/**
|
|
88
|
-
* Fornisce il global della libreria (namespace **cytoscape**) e si aspetta che dopo operazioni di importazione
|
|
89
|
-
* lasciate all'utente vengano aggiunti tutti i moduli desiderati.
|
|
90
|
-
*
|
|
91
|
-
* È **fondamentale** che il primo parametro (il nome del modulo) sia uguale a ciò di cui viene fatto il require in modo che la libreria
|
|
92
|
-
* possa controllare che il modulo importato non sia già stato importato in precedenza
|
|
93
|
-
*
|
|
94
|
-
* ## Esempio:
|
|
95
|
-
*
|
|
96
|
-
* ```typescript
|
|
97
|
-
* (global) => {
|
|
98
|
-
* return import("cytoscape-extension-library").then(module => global.use("cytoscape-extension-library", module.default));
|
|
99
|
-
*
|
|
100
|
-
* ...
|
|
101
|
-
* }
|
|
102
|
-
* ```
|
|
103
|
-
*/
|
|
104
|
-
this.ExtensionModulesImporter = null;
|
|
105
|
-
/**
|
|
106
|
-
* Fornisce l'istanza attuale di Cytoscape da cui è possibile prendere le librerie di estensione caricate in **ExtensionModulesImporter**
|
|
107
|
-
* e configurarle in base ai comportamenti specifici
|
|
108
|
-
*
|
|
109
|
-
* ## Esempio:
|
|
110
|
-
*
|
|
111
|
-
* ```typescript
|
|
112
|
-
* (cytoscapeCore) => {
|
|
113
|
-
* // Fare questo lavoro per ogni estensione caricata
|
|
114
|
-
* let extensionConfiguration = { ... };
|
|
115
|
-
* let extensionInstance = cytoscapeCore.extensionLibrary(extensionConfiguration);
|
|
116
|
-
* extensionInstance.doSomethingSpecificToThisExtension();
|
|
117
|
-
*
|
|
118
|
-
* ...
|
|
119
|
-
* }
|
|
120
|
-
* ```
|
|
121
|
-
*/
|
|
122
|
-
this.ExtensionModulesApplyer = null;
|
|
123
|
-
/**
|
|
124
|
-
* Evento lanciato al click di un nodo, contiene l'oggetto **data** del nodo in questione
|
|
125
|
-
*/
|
|
126
|
-
this.onNodeClick = new EventEmitter();
|
|
127
|
-
/**
|
|
128
|
-
* Evento lanciato alla selezione o deselezione di un nodo, contiene l'oggetto **data** del nodo in questione e informazioni sul suo stato di selezione
|
|
129
|
-
*/
|
|
130
|
-
this.onNodeSelection = new EventEmitter();
|
|
131
|
-
/**
|
|
132
|
-
* Evento lanciato al termine del Layouting. Se si vuole eseguire codice dopo che il Layout è fatto e completamente graficato, questo è il punto
|
|
133
|
-
*/
|
|
134
|
-
this.onLayoutDone = new EventEmitter();
|
|
135
|
-
/**
|
|
136
|
-
* Evento lanciato al termine del caricamento del diagramma
|
|
137
|
-
*/
|
|
138
|
-
this.onLoaded = new EventEmitter();
|
|
139
|
-
/**
|
|
140
|
-
* Indica se il rendering del diagramma è terminato
|
|
141
|
-
*/
|
|
142
|
-
this.Rendered = false;
|
|
143
|
-
/**
|
|
144
|
-
* Api dell'estensione expand-collapse per permettere di effettuare operazioni dall'esterno del diagramma. Vengono valorizzate se **UseExpandCollapse** è **true**
|
|
145
|
-
*/
|
|
146
|
-
this.ExpandCollapseApi = null;
|
|
147
|
-
/**
|
|
148
|
-
* Api dell'estensione html-node per permettere di effettuare operazioni dall'esterno del diagramma. Vengono valorizzate se sono impostati dei **NodeHTMLTemplates**
|
|
149
|
-
*/
|
|
150
|
-
this.HtmlNodeApi = null;
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* @ignore
|
|
154
|
-
*
|
|
155
|
-
* Angular Pipeline
|
|
156
|
-
*/
|
|
157
|
-
ngAfterViewInit() {
|
|
158
|
-
if (!this.service || !this.dispatcher)
|
|
159
|
-
throw "Il modulo @esfaenza/diagrams non è stato importato con il forRoot();";
|
|
160
|
-
this.dispatchLoadChart();
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* All'onDestroy ripulisco la memoria dal diagramma
|
|
164
|
-
*/
|
|
165
|
-
ngOnDestroy() {
|
|
166
|
-
if (this.resizeObserver) {
|
|
167
|
-
this.resizeObserver.dispose();
|
|
168
|
-
this.resizeObserver = null;
|
|
169
|
-
}
|
|
170
|
-
if (this.cy) {
|
|
171
|
-
this.service.log("I", "Diagram" + " " + this.name + ": Unloading destroyed diagram", false);
|
|
172
|
-
this.cy.destroy();
|
|
173
|
-
this.dispatcher.deregister(this.name);
|
|
174
|
-
}
|
|
175
|
-
else
|
|
176
|
-
this.service.log("I", "Chart " + this.name + ": Unloading uncreated chart component. It probably was a duplicated", false);
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Registra il diagramma attuale nel Dispatcher in modo che venga caricato appena possibile
|
|
180
|
-
*/
|
|
181
|
-
dispatchLoadChart() {
|
|
182
|
-
this.dispatcher.register(this.name, () => { return this.render(); });
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* @ignore
|
|
186
|
-
*
|
|
187
|
-
* Angular Pipeline: Gestione ri-graficazione del diagramma, se possibile
|
|
188
|
-
*/
|
|
189
|
-
ngOnChanges(changes) {
|
|
190
|
-
let toCheck = ["Templates", "UseContextMenu", "ContextMenuOptions", "UseExpandCollapse", "ExpandCollapseOptions", "NodeStyles", "EdgeStyles", "NativeOptions"];
|
|
191
|
-
if (this.Rendered && toCheck.some(t => changes[t]))
|
|
192
|
-
this.service.log("W", "Redraw based on dynamic Input change is supported only for 'Elements' and 'Layout' inputs, please destroy the component and recreate it with the new settings");
|
|
193
|
-
let elementChanges = changes["Elements"];
|
|
194
|
-
let layoutChanges = changes["Layout"];
|
|
195
|
-
if (elementChanges && !elementChanges.firstChange) {
|
|
196
|
-
this.service.log("I", "Elements have been changed after diagram initialization");
|
|
197
|
-
// Cambiamento agli Elementi: ripulisco gli elementi vecchi, prendo i nuovi, li sistemo e li riassegno.
|
|
198
|
-
// Se il nuovo Input Elements è roba strana mi limito a ripulire il diagramma
|
|
199
|
-
// Se cytoscape aveva già degli elementi precedentemente ne prendo le posizioni in modo da ridisegnarli partendo dallo stesso punto (carino per le animazioni)
|
|
200
|
-
let elements = elementChanges?.currentValue;
|
|
201
|
-
let previous_elements = this.PreserveElementsPosition ? this.cy.nodes() : null;
|
|
202
|
-
this.cy.elements().remove();
|
|
203
|
-
if (elements && elements.length && elements.length > 0) {
|
|
204
|
-
this.reviewCytoscapeElements(elements, previous_elements);
|
|
205
|
-
this.cy.add(elements);
|
|
206
|
-
if (this.SmartSelection)
|
|
207
|
-
this.setupElementsSelectionIfNeeded();
|
|
208
|
-
// Se solo gli elementi cambiano, riapplico il Layout precedente
|
|
209
|
-
if (!layoutChanges && this.LastLayout) {
|
|
210
|
-
// Se devo animare le modifche al layout forzo il parametro relativo
|
|
211
|
-
if (this.AnimateLayoutChanges)
|
|
212
|
-
this.LastLayout.animate = true;
|
|
213
|
-
this.cy.layout(this.LastLayout).run();
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
// Se il layout cambia lo applico e me lo salvo come layout precedente per il futuro
|
|
218
|
-
if (layoutChanges && !layoutChanges.firstChange) {
|
|
219
|
-
this.service.log("I", "Layout have been changed after diagram initialization");
|
|
220
|
-
this.LastLayout = JSON.parse(JSON.stringify(layoutChanges.currentValue));
|
|
221
|
-
this.cy.layout(this.LastLayout).run();
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* Effettua il rendering del diagramma
|
|
226
|
-
*/
|
|
227
|
-
async render() {
|
|
228
|
-
// Tiro fuori le opzioni con cui generare il diagramma
|
|
229
|
-
let cyOptions = this.getCompletedOptions();
|
|
230
|
-
this.NodesHierarchy = cyOptions.elements && cyOptions.elements.some(t => t.data.parent);
|
|
231
|
-
// Carico eventuali classi di estensione che servono
|
|
232
|
-
await this.performModulesLoading();
|
|
233
|
-
// Genero il diagramma
|
|
234
|
-
this.cy = cytoscape(cyOptions);
|
|
235
|
-
// Collego gli eventi al componente
|
|
236
|
-
this.bindCytoscapeEvents();
|
|
237
|
-
// Utilizzo le classi di estensione caricate precedentemente per fare il resto delle mie operazioni
|
|
238
|
-
this.performOperationsWithLoadedModules();
|
|
239
|
-
// Imposto la variabile Rendered a true in modo che se da adesso vengono fatte modifiche che dovrebbero causare un redraw posso accorgermene
|
|
240
|
-
// e mandare a cagare lo stronzo di turno
|
|
241
|
-
this.Rendered = true;
|
|
242
|
-
// Se devo aggiornare in automatico in base alla dimensione del contenitore collego il ResizeObserver
|
|
243
|
-
if (this.AutoupdateSize)
|
|
244
|
-
this.listenOnChanges();
|
|
245
|
-
if (this.SmartSelection) {
|
|
246
|
-
this.setupSelectionStyles();
|
|
247
|
-
this.setupElementsSelectionIfNeeded();
|
|
248
|
-
}
|
|
249
|
-
this.onLoaded.emit();
|
|
250
|
-
}
|
|
251
|
-
/**
|
|
252
|
-
* Prende tutti gli elementi appena assegnati, e se qualcuno era selezionato la situazione viene persistita su cytoscape
|
|
253
|
-
*/
|
|
254
|
-
setupElementsSelectionIfNeeded() {
|
|
255
|
-
for (let i = 0; i < this.Elements.length; i++) {
|
|
256
|
-
let eldata = this.Elements[i].data;
|
|
257
|
-
if (eldata.__selected) {
|
|
258
|
-
let el = this.cy.$id(eldata.id);
|
|
259
|
-
el.select();
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* Carica gli stili per mostrare carina la selezione dei nodi
|
|
265
|
-
*/
|
|
266
|
-
setupSelectionStyles() {
|
|
267
|
-
let cssItem = this.SmartSelectionStyles || {
|
|
268
|
-
'overlay-color': 'blue',
|
|
269
|
-
'overlay-opacity': 0.5,
|
|
270
|
-
'overlay-padding': 7
|
|
271
|
-
};
|
|
272
|
-
// Backdoor per poter assegnare "{}" a SmartSelectionStyles in modo di utilizzare la smart selection ma senza che nessuno stile venga applicato
|
|
273
|
-
// ad esempio qualora si volesse utilizzare l'htmlnode per gestire la grafica degli elementi selezionati
|
|
274
|
-
if (cssItem['overlay-color'] && cssItem['overlay-opacity'] && cssItem['overlay-padding'])
|
|
275
|
-
this.cy.style().selector('node:selected').css(cssItem);
|
|
276
|
-
}
|
|
277
|
-
/**
|
|
278
|
-
* Registra l'ascolto al contenitore del grafico e in caso di modifiche alla dimensione, al massimo una volta ogni 500 millisecondi, lo ridisegna
|
|
279
|
-
*/
|
|
280
|
-
listenOnChanges() {
|
|
281
|
-
this.resizeObserver = new ResizeSensor(this.cyGraph.nativeElement, () => {
|
|
282
|
-
this.exts.throttle(this.name, this.onContainerSizeChanged.bind(this), this.ResizeThrottleTime);
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Funzione che si occupa di gestire il repaint del diagramma
|
|
287
|
-
*/
|
|
288
|
-
onContainerSizeChanged() {
|
|
289
|
-
this.service.log("I", "Diagram container size has changed, redrawing");
|
|
290
|
-
this.cy.resize();
|
|
291
|
-
this.cy.fit();
|
|
292
|
-
}
|
|
293
|
-
/**
|
|
294
|
-
* Collega tutti gli eventi che mi possono servire e li espone in output
|
|
295
|
-
*/
|
|
296
|
-
bindCytoscapeEvents() {
|
|
297
|
-
this.cy.bind('click', 'node', (event) => {
|
|
298
|
-
let targetData = event.target.data();
|
|
299
|
-
if (this.SmartSelection) {
|
|
300
|
-
// In caso di selezione singola ripulisco tutti gli elementi precedentemente selezionati
|
|
301
|
-
if (this.SingleSelection) {
|
|
302
|
-
let selected = this.cy.elements('node:selected');
|
|
303
|
-
selected.forEach(el => {
|
|
304
|
-
el.selectify();
|
|
305
|
-
el.unselect();
|
|
306
|
-
el.unselectify();
|
|
307
|
-
el.data("__selected", false);
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
let id = targetData.id;
|
|
311
|
-
let el = this.cy.$id(id);
|
|
312
|
-
let selected = el.selected();
|
|
313
|
-
el.selectify();
|
|
314
|
-
if (selected)
|
|
315
|
-
el.unselect();
|
|
316
|
-
else
|
|
317
|
-
el.select();
|
|
318
|
-
el.unselectify();
|
|
319
|
-
// Questo va anche nella lista degli elementi originali (this.Elements) dato che cytoscape li prende per riferimento (bbbbbravo cyto-chan)
|
|
320
|
-
el.data("__selected", !selected);
|
|
321
|
-
}
|
|
322
|
-
this.onNodeClick.emit({ data: targetData });
|
|
323
|
-
});
|
|
324
|
-
this.cy.bind('select', 'node', (event) => {
|
|
325
|
-
let targetData = event.target.data();
|
|
326
|
-
this.onNodeSelection.emit({ data: targetData, selected: true });
|
|
327
|
-
});
|
|
328
|
-
this.cy.bind('layoutstop', (event) => {
|
|
329
|
-
this.onLayoutDone.emit();
|
|
330
|
-
});
|
|
331
|
-
this.cy.bind('unselect', 'node', (event) => {
|
|
332
|
-
let targetData = event.target.data();
|
|
333
|
-
this.onNodeSelection.emit({ data: targetData, selected: false });
|
|
334
|
-
});
|
|
335
|
-
// Altri eventi...
|
|
336
|
-
}
|
|
337
|
-
/**
|
|
338
|
-
* Metodo che serve per caricare tutte le estensioni della libreria in base a ciò che viene utilizzato
|
|
339
|
-
*/
|
|
340
|
-
async performModulesLoading() {
|
|
341
|
-
if (this.Layout.name == 'dagre')
|
|
342
|
-
await this.loadInternal("cytoscape-dagre");
|
|
343
|
-
if (this.NodeHTMLTemplates && this.NodeHTMLTemplates.length > 0)
|
|
344
|
-
await this.loadInternal("cytoscape-html-node");
|
|
345
|
-
if (this.UseContextMenu)
|
|
346
|
-
await this.loadInternal("cytoscape-cxtmenu");
|
|
347
|
-
if (this.NodesHierarchy && this.UseExpandCollapse)
|
|
348
|
-
await this.loadInternal("cytoscape-expand-collapse");
|
|
349
|
-
if (this.ExtensionModulesImporter) {
|
|
350
|
-
// Wrappo il namespace in modo che possa dire la mia sul fatto che l'utente aggiunga un modulo o meno :D
|
|
351
|
-
var wrappedCytoscape = {
|
|
352
|
-
use: (moduleName, module) => {
|
|
353
|
-
if (!module)
|
|
354
|
-
this.service.log("E", this.service.loc("Received an undefined module. Make sure you are correctly loading it") + ": " + moduleName, false);
|
|
355
|
-
if (["cytoscape-dagre", "cytoscape-html-node", "cytoscape-cxtmenu", "cytoscape-expand-collapse"].includes(moduleName))
|
|
356
|
-
this.service.log("W", this.service.loc("Module") + " " + moduleName + " " + this.service.loc("is loaded and managed directly by this library. You don't need to import it or use it directly, just be sure to set the relative options"), false);
|
|
357
|
-
else
|
|
358
|
-
cytoscape.use(module);
|
|
359
|
-
}
|
|
360
|
-
};
|
|
361
|
-
await this.ExtensionModulesImporter(wrappedCytoscape);
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
/**
|
|
365
|
-
* Metodo che serve per caricare tutte le estensioni della libreria in base a ciò che viene utilizzato con le opzioni definite dagli Input
|
|
366
|
-
*/
|
|
367
|
-
performOperationsWithLoadedModules() {
|
|
368
|
-
let anyCy = this.cy;
|
|
369
|
-
// Utilizzo del layout, lo salvo per poterlo riutilizzare in futuro
|
|
370
|
-
if (this.Layout) {
|
|
371
|
-
this.LastLayout = JSON.parse(JSON.stringify(this.Layout));
|
|
372
|
-
this.cy.layout(this.LastLayout).run();
|
|
373
|
-
}
|
|
374
|
-
// Utilizzo dell'HTML node
|
|
375
|
-
if (this.NodeHTMLTemplates && this.NodeHTMLTemplates.length > 0) {
|
|
376
|
-
this.HtmlNodeApi = anyCy.htmlnode();
|
|
377
|
-
this.HtmlNodeApi.createHtmlNode(cytoscape, this.cy, this.NodeHTMLTemplates);
|
|
378
|
-
}
|
|
379
|
-
// Utilizzo del Context Menu
|
|
380
|
-
if (this.UseContextMenu)
|
|
381
|
-
this.ContextMenuOptions.forEach(o => { anyCy.cxtmenu(o); });
|
|
382
|
-
// Utilizzo dell'expand collapse solo quando c'è una gerarchia di nodi
|
|
383
|
-
if (this.NodesHierarchy && this.UseExpandCollapse)
|
|
384
|
-
this.ExpandCollapseApi = anyCy.expandCollapse(this.ExpandCollapseOptions);
|
|
385
|
-
// Utilizzo di estensioni extra, implementazione affidata al programmatore
|
|
386
|
-
if (this.ExtensionModulesApplyer)
|
|
387
|
-
this.ExtensionModulesApplyer(this.cy);
|
|
388
|
-
}
|
|
389
|
-
updateCardData() {
|
|
390
|
-
if (!this.HtmlNodeApi) {
|
|
391
|
-
this.service.log("E", "Cannot update NodeHTMLTemplates as they don't seem to be used");
|
|
392
|
-
return;
|
|
393
|
-
}
|
|
394
|
-
this.HtmlNodeApi.update();
|
|
395
|
-
}
|
|
396
|
-
/**
|
|
397
|
-
* Metodo interno per il caricamento dei moduli di estensione
|
|
398
|
-
*
|
|
399
|
-
* @param {'cytoscape-expand-collapse' | 'cytoscape-cxtmenu' | 'cytoscape-html-node' | 'cytoscape-dagre'} moduleId Modulo da caricare
|
|
400
|
-
*/
|
|
401
|
-
async loadInternal(moduleId) {
|
|
402
|
-
let toLoad = await this.service.importIfNeeded(moduleId);
|
|
403
|
-
if (toLoad)
|
|
404
|
-
cytoscape.use(toLoad);
|
|
405
|
-
}
|
|
406
|
-
/**
|
|
407
|
-
* Metodo che basandosi sulle opzioni native eventualmente assegnate le completa con gli Input addizionali
|
|
408
|
-
*
|
|
409
|
-
* @returns {cy_.CytoscapeOptions} Opzioni finali unite da Input ed opzioni native
|
|
410
|
-
*/
|
|
411
|
-
getCompletedOptions() {
|
|
412
|
-
var opts = this.NativeOptions || {};
|
|
413
|
-
opts.container = this.cyGraph.nativeElement;
|
|
414
|
-
opts.style = opts.style || [];
|
|
415
|
-
// Per tutte le cose per cui gli Input hanno priorità sovrascrivo gli originali delle opzioni
|
|
416
|
-
if (this.NodeStyles || this.EdgeStyles) {
|
|
417
|
-
opts.style = [];
|
|
418
|
-
if (this.NodeStyles)
|
|
419
|
-
opts.style.push({ selector: 'node', css: this.NodeStyles });
|
|
420
|
-
if (this.EdgeStyles)
|
|
421
|
-
opts.style.push({ selector: 'edge', css: this.EdgeStyles });
|
|
422
|
-
}
|
|
423
|
-
if (this.Elements)
|
|
424
|
-
opts.elements = this.Elements;
|
|
425
|
-
this.reviewCytoscapeElements(opts.elements);
|
|
426
|
-
if (this.Layout)
|
|
427
|
-
opts.layout = this.Layout;
|
|
428
|
-
if (this.Readonly) {
|
|
429
|
-
// Questo coso fa effetti strani....
|
|
430
|
-
//opts.autolock = true;
|
|
431
|
-
opts.autoungrabify = true;
|
|
432
|
-
opts.autounselectify = false;
|
|
433
|
-
opts.boxSelectionEnabled = true;
|
|
434
|
-
opts.userZoomingEnabled = false;
|
|
435
|
-
opts.userPanningEnabled = false;
|
|
436
|
-
}
|
|
437
|
-
return opts;
|
|
438
|
-
}
|
|
439
|
-
/**
|
|
440
|
-
* Aggiustamenti degli elementi di Cytoscape.
|
|
441
|
-
*
|
|
442
|
-
* I nodi non vengono toccati.
|
|
443
|
-
*
|
|
444
|
-
* Per ogni edge viene controllato se è specificata una sorgente ed una destinazione, in caso contrario si cerca di dedurli dall'ID
|
|
445
|
-
*
|
|
446
|
-
* @param {cytoscape.ElementDefinition[]} elements Elementi da sistemare
|
|
447
|
-
*/
|
|
448
|
-
reviewCytoscapeElements(elements, prevPositions) {
|
|
449
|
-
let hasPreviousPositions = prevPositions && prevPositions.length > 0;
|
|
450
|
-
let positionCache = {};
|
|
451
|
-
if (hasPreviousPositions) {
|
|
452
|
-
for (let i = 0; i < prevPositions.length; i++) {
|
|
453
|
-
let item = prevPositions[i];
|
|
454
|
-
if (!positionCache[item.data().id])
|
|
455
|
-
positionCache[item.data().id] = item.position();
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
for (let i = 0; i < elements.length; i++) {
|
|
459
|
-
let el = elements[i];
|
|
460
|
-
if (el.group == "edges" && (!el.data.source && !el.data.target)) {
|
|
461
|
-
if (!el.data.id.includes("-"))
|
|
462
|
-
this.service.log("E", "If you don't specify a source and a target for an edge you have to write its id in the format {source}-{target}");
|
|
463
|
-
else {
|
|
464
|
-
var sourceTarget = el.data.id.split('-');
|
|
465
|
-
el.data.source = sourceTarget[0].trim();
|
|
466
|
-
el.data.target = sourceTarget[1].trim();
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
if (hasPreviousPositions && el.group == "nodes")
|
|
470
|
-
el.position = positionCache[el.data.id];
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EsDiagramComponent, deps: [{ token: i1.EsDiagramService, optional: true }, { token: i2.EsDiagramDispatcher, optional: true }, { token: i3.ReactiveExtensions }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
474
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: EsDiagramComponent, selector: "es-diagram", inputs: { name: "name", UseContextMenu: "UseContextMenu", ContextMenuOptions: "ContextMenuOptions", UseExpandCollapse: "UseExpandCollapse", ExpandCollapseOptions: "ExpandCollapseOptions", NativeOptions: "NativeOptions", Elements: "Elements", NodeStyles: "NodeStyles", EdgeStyles: "EdgeStyles", Readonly: "Readonly", AutoupdateSize: "AutoupdateSize", PreserveElementsPosition: "PreserveElementsPosition", AnimateLayoutChanges: "AnimateLayoutChanges", SmartSelection: "SmartSelection", SingleSelection: "SingleSelection", SmartSelectionStyles: "SmartSelectionStyles", ResizeThrottleTime: "ResizeThrottleTime", Layout: "Layout", NodeHTMLTemplates: "NodeHTMLTemplates", ExtensionModulesImporter: "ExtensionModulesImporter", ExtensionModulesApplyer: "ExtensionModulesApplyer" }, outputs: { onNodeClick: "onNodeClick", onNodeSelection: "onNodeSelection", onLayoutDone: "onLayoutDone", onLoaded: "onLoaded" }, viewQueries: [{ propertyName: "cyGraph", first: true, predicate: ["graph"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div #graph class=\"graph-wrapper {{name}}\"></div>", styles: [".graph-wrapper{height:100%;width:100%}.html-node-notransition{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;transition:none!important;-o-transform:none!important;-moz-transform:none!important;-ms-transform:none!important;-webkit-transform:none!important;transform:none!important}\n"] }); }
|
|
475
|
-
}
|
|
476
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EsDiagramComponent, decorators: [{
|
|
477
|
-
type: Component,
|
|
478
|
-
args: [{ selector: 'es-diagram', template: "<div #graph class=\"graph-wrapper {{name}}\"></div>", styles: [".graph-wrapper{height:100%;width:100%}.html-node-notransition{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;transition:none!important;-o-transform:none!important;-moz-transform:none!important;-ms-transform:none!important;-webkit-transform:none!important;transform:none!important}\n"] }]
|
|
479
|
-
}], ctorParameters: () => [{ type: i1.EsDiagramService, decorators: [{
|
|
480
|
-
type: Optional
|
|
481
|
-
}] }, { type: i2.EsDiagramDispatcher, decorators: [{
|
|
482
|
-
type: Optional
|
|
483
|
-
}] }, { type: i3.ReactiveExtensions }], propDecorators: { cyGraph: [{
|
|
484
|
-
type: ViewChild,
|
|
485
|
-
args: ['graph']
|
|
486
|
-
}], name: [{
|
|
487
|
-
type: Input
|
|
488
|
-
}], UseContextMenu: [{
|
|
489
|
-
type: Input
|
|
490
|
-
}], ContextMenuOptions: [{
|
|
491
|
-
type: Input
|
|
492
|
-
}], UseExpandCollapse: [{
|
|
493
|
-
type: Input
|
|
494
|
-
}], ExpandCollapseOptions: [{
|
|
495
|
-
type: Input
|
|
496
|
-
}], NativeOptions: [{
|
|
497
|
-
type: Input
|
|
498
|
-
}], Elements: [{
|
|
499
|
-
type: Input
|
|
500
|
-
}], NodeStyles: [{
|
|
501
|
-
type: Input
|
|
502
|
-
}], EdgeStyles: [{
|
|
503
|
-
type: Input
|
|
504
|
-
}], Readonly: [{
|
|
505
|
-
type: Input
|
|
506
|
-
}], AutoupdateSize: [{
|
|
507
|
-
type: Input
|
|
508
|
-
}], PreserveElementsPosition: [{
|
|
509
|
-
type: Input
|
|
510
|
-
}], AnimateLayoutChanges: [{
|
|
511
|
-
type: Input
|
|
512
|
-
}], SmartSelection: [{
|
|
513
|
-
type: Input
|
|
514
|
-
}], SingleSelection: [{
|
|
515
|
-
type: Input
|
|
516
|
-
}], SmartSelectionStyles: [{
|
|
517
|
-
type: Input
|
|
518
|
-
}], ResizeThrottleTime: [{
|
|
519
|
-
type: Input
|
|
520
|
-
}], Layout: [{
|
|
521
|
-
type: Input
|
|
522
|
-
}], NodeHTMLTemplates: [{
|
|
523
|
-
type: Input
|
|
524
|
-
}], ExtensionModulesImporter: [{
|
|
525
|
-
type: Input
|
|
526
|
-
}], ExtensionModulesApplyer: [{
|
|
527
|
-
type: Input
|
|
528
|
-
}], onNodeClick: [{
|
|
529
|
-
type: Output
|
|
530
|
-
}], onNodeSelection: [{
|
|
531
|
-
type: Output
|
|
532
|
-
}], onLayoutDone: [{
|
|
533
|
-
type: Output
|
|
534
|
-
}], onLoaded: [{
|
|
535
|
-
type: Output
|
|
536
|
-
}] } });
|
|
537
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXMtZGlhZ3JhbS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9lcy1kaWFncmFtcy9zcmMvbGliL2NvbXBvbmVudHMvZXMtZGlhZ3JhbS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9lcy1kaWFncmFtcy9zcmMvbGliL2NvbXBvbmVudHMvZXMtZGlhZ3JhbS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFjLFlBQVksRUFBRSxLQUFLLEVBQWEsUUFBUSxFQUFFLE1BQU0sRUFBaUIsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFBO0FBa0JqSSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFJMUQsT0FBTyxLQUFLLEdBQUcsTUFBTSxXQUFXLENBQUM7Ozs7O0FBQ2pDLGNBQWMsQ0FBQSxNQUFNLFNBQVMsR0FBUyxHQUFJLENBQUMsT0FBTyxDQUFBLENBQUMsQ0FBTyxHQUFJLENBQUMsT0FBTyxDQUFBLENBQUMsQ0FBQyxHQUFHLENBQUM7QUFFNUU7O0dBRUc7QUFNSCxNQUFNLE9BQU8sa0JBQWtCO0lBK043Qjs7OztPQUlHO0lBQ0gsWUFBZ0MsT0FBeUIsRUFBc0IsVUFBK0IsRUFBVSxJQUF3QjtRQUFoSCxZQUFPLEdBQVAsT0FBTyxDQUFrQjtRQUFzQixlQUFVLEdBQVYsVUFBVSxDQUFxQjtRQUFVLFNBQUksR0FBSixJQUFJLENBQW9CO1FBN05oSjs7V0FFRztRQUNNLFNBQUksR0FBVyxFQUFFLENBQUM7UUFFM0I7O1dBRUc7UUFDTSxtQkFBYyxHQUFZLEtBQUssQ0FBQztRQVN6Qzs7V0FFRztRQUNNLHNCQUFpQixHQUFZLEtBQUssQ0FBQztRQU81Qzs7OztXQUlHO1FBQ00sa0JBQWEsR0FBK0IsRUFBRSxDQUFDO1FBc0J4RDs7V0FFRztRQUNNLG1CQUFjLEdBQVksSUFBSSxDQUFD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QWhCLEtBQUs7Z0JBS0csY0FBYztzQkFBdEIsS0FBSztnQkFPRyx3QkFBd0I7c0JBQWhDLEtBQUs7Z0JBT0csb0JBQW9CO3NCQUE1QixLQUFLO2dCQVlHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBS0csZUFBZTtzQkFBdkIsS0FBSztnQkFXRyxvQkFBb0I7c0JBQTVCLEtBQUs7Z0JBT0csa0JBQWtCO3NCQUExQixLQUFLO2dCQUtHLE1BQU07c0JBQWQsS0FBSztnQkFPRyxpQkFBaUI7c0JBQXpCLEtBQUs7Z0JBbUJHLHdCQUF3QjtzQkFBaEMsS0FBSztnQkFtQkcsdUJBQXVCO3NCQUEvQixLQUFLO2dCQUtJLFdBQVc7c0JBQXBCLE1BQU07Z0JBS0csZUFBZTtzQkFBeEIsTUFBTTtnQkFLRyxZQUFZO3NCQUFyQixNQUFNO2dCQUtHLFFBQVE7c0JBQWpCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEVsZW1lbnRSZWYsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE9uQ2hhbmdlcywgT3B0aW9uYWwsIE91dHB1dCwgU2ltcGxlQ2hhbmdlcywgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSdcclxuXHJcbmltcG9ydCB7IENvbnRleHRNZW51T3B0aW9ucyB9IGZyb20gJy4uL21vZGVscy9jb21wb25lbnQvY29udGV4dG1lbnUvQ29udGV4dE1lbnVPcHRpb25zJztcclxuaW1wb3J0IHsgRXhwYW5kQ29sbGFwc2VPcHRpb25zIH0gZnJvbSAnLi4vbW9kZWxzL2NvbXBvbmVudC9ncm91cGluZy9FeHBhbmRDb2xsYXBzZU9wdGlvbnMnO1xyXG5pbXBvcnQgeyBOb2RlSFRNTFRlbXBsYXRlIH0gZnJvbSAnLi4vbW9kZWxzL2NvbXBvbmVudC9ub2Rlcy9Ob2RlSFRNTFRlbXBsYXRlJztcclxuXHJcbmltcG9ydCB7IEJyZWFkdGhGaXJzdExheW91dE9wdGlvbnNJbXBsIH0gZnJvbSAnLi4vbW9kZWxzL2xheW91dHMvQnJlYWR0aEZpcnN0TGF5b3V0T3B0aW9uc0ltcGwnO1xyXG5pbXBvcnQgeyBDaXJjbGVMYXlvdXRPcHRpb25zSW1wbCB9IGZyb20gJy4uL21vZGVscy9sYXlvdXRzL0NpcmNsZUxheW91dE9wdGlvbnNJbXBsJztcclxuaW1wb3J0IHsgQ29uY2VudHJpY0xheW91dE9wdGlvbnNJbXBsIH0gZnJvbSAnLi4vbW9kZWxzL2xheW91dHMvQ29uY2VudHJpY0xheW91dE9wdGlvbnNJbXBsJztcclxuaW1wb3J0IHsgQ29zZUxheW91dE9wdGlvbnNJbXBsIH0gZnJvbSAnLi4vbW9kZWxzL2xheW91dHMvQ29zZUxheW91dE9wdGlvbnNJbXBsJztcclxuaW1wb3J0IHsgRGFncmVMYXlvdXRPcHRpb25zSW1wbCB9IGZyb20gJy4uL21vZGVscy9sYXlvdXRzL0RhZ3JlTGF5b3V0T3B0aW9uc0ltcGwnO1xyXG5pbXBvcnQgeyBHcmlkTGF5b3V0T3B0aW9uc0ltcGwgfSBmcm9tICcuLi9tb2RlbHMvbGF5b3V0cy9HcmlkTGF5b3V0T3B0aW9uc0ltcGwnO1xyXG5pbXBvcnQgeyBOdWxsTGF5b3V0T3B0aW9uc0ltcGwgfSBmcm9tICcuLi9tb2RlbHMvbGF5b3V0cy9OdWxsTGF5b3V0T3B0aW9uc0ltcGwnO1xyXG5pbXBvcnQgeyBQcmVzZXRMYXlvdXRPcHRpb25zSW1wbCB9IGZyb20gJy4uL21vZGVscy9sYXlvdXRzL1ByZXNldExheW91dE9wdGlvbnNJbXBsJztcclxuaW1wb3J0IHsgUmFuZG9tTGF5b3V0T3B0aW9uc0ltcGwgfSBmcm9tICcuLi9tb2RlbHMvbGF5b3V0cy9SYW5kb21MYXlvdXRPcHRpb25zSW1wbCc7XHJcblxyXG5pbXBvcnQgeyBFc0RpYWdyYW1TZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvZXMtZGlhZ3JhbS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgRXNEaWFncmFtRGlzcGF0Y2hlciB9IGZyb20gJy4uL3NlcnZpY2VzL2VzLWRpYWdyYW0uZGlzcGF0Y2hlcic7XHJcbmltcG9ydCB7IFJlc2l6ZVNlbnNvciB9IGZyb20gXCIuLi9leHRlbnNpb25zL1Jlc2l6ZVNlbnNvclwiO1xyXG5cclxuaW1wb3J0IHsgUmVhY3RpdmVFeHRlbnNpb25zIH0gZnJvbSAnLi4vZXh0ZW5zaW9ucy9SZWFjdGl2ZUV4dGVuc2lvbnMnO1xyXG5cclxuaW1wb3J0ICogYXMgY3lfIGZyb20gJ2N5dG9zY2FwZSc7XHJcbi8qKiBAaWdub3JlICovY29uc3QgY3l0b3NjYXBlID0gKDxhbnk+Y3lfKS5kZWZhdWx0PyAoPGFueT5jeV8pLmRlZmF1bHQ6IGN5XztcclxuXHJcbi8qKlxyXG4gKiBDb21wb25lbnRlIGNoZSBzaSBvY2N1cGEgZGkgZ3JhZmljYXJlIHVuIGRpYWdyYW1tYSBlIGRpIGdlc3Rpcm5lIGlsIGNpY2xvIGRpIHZpdGFcclxuICovXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnZXMtZGlhZ3JhbScsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL2VzLWRpYWdyYW0uY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL2VzLWRpYWdyYW0uY29tcG9uZW50LnNjc3MnXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgRXNEaWFncmFtQ29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzIHtcclxuXHJcbiAgLyoqXHJcbiAgICogUmlmZXJpbWVudG8gYWxsJ29nZ2V0dG8gSFRNTCBzdSBjdWkgY3JlYXJlIGlsIGRpYWdyYW1tYVxyXG4gICAqL1xyXG4gIEBWaWV3Q2hpbGQoJ2dyYXBoJykgY3lHcmFwaDogRWxlbWVudFJlZjtcclxuXHJcbiAgLyoqXHJcbiAgICogTm9tZSBkZWwgZGlhZ3JhbW1hLCBmb25kYW1lbnRhbGUgYXNzZWduYXJsbyBwZXIgcGVybWV0dGVyZSBhbGxhIGxpYnJlcmlhIGRpIHNjaGVkdWxhcm5lIGxhIGNyZWF6aW9uZVxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIG5hbWU6IHN0cmluZyA9IFwiXCI7XHJcblxyXG4gIC8qKlxyXG4gICAqIEluZGljYSBzZSB1dGlsaXp6YXJlIGlsIG1lbsO5IGNvbnRlc3R1YWxlIGEgcnVvdGEgYXR0b3JubyBhZCBvZ25pIG5vZG9cclxuICAgKi9cclxuICBASW5wdXQoKSBVc2VDb250ZXh0TWVudTogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAvKipcclxuICAgKiBJbmRpY2EgbGUgb3B6aW9uaSBkZWwgbWVuw7kgY29udGVzdHVhbGUgcXVhbG9yYSAqKlVzZUNvbnRleHRNZW51KiogZm9zc2UgKip0cnVlKiouXHJcbiAgICogXHJcbiAgICogT2duaSBlbGVtZW50byBkaSBxdWVzdG8gYXJyYXkgw6ggdW4gc2VsZXR0b3JlIGNvbiBpbCBtZW51IGRhIG1vc3RyYXJlIHBlciBxdWVsbGEgY2FzaXN0aWNhXHJcbiAgICovXHJcbiAgQElucHV0KCkgQ29udGV4dE1lbnVPcHRpb25zOiBDb250ZXh0TWVudU9wdGlvbnNbXTtcclxuXHJcbiAgLyoqXHJcbiAgICogRGljZSBhbCBjb21wb25lbnRlIHNlIGlsIGRpYWdyYW1tYSBkZXZlIHV0aWxpenphcmUgaWwgc2lzdGVtYSBkaSBlc3RlbnNpb25lIHBlciBsJ2V4cGFuZCBlIGNvbGxhcHNlIGRlaSBncnVwcGlcclxuICAgKi9cclxuICBASW5wdXQoKSBVc2VFeHBhbmRDb2xsYXBzZTogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAvKipcclxuICAgKiBPcHppb25pIG5hdGl2ZSBkZWxsJ2VzdGVuc2lvbmUgZXhwYW5kLWNvbGxhcHNlLCB2ZW5nb25vIG92dmlhbWVudGUgdXRpbGl6emF0ZSBzb2xvIHNlICoqVXNlRXhwYW5kQ29sbGFwc2UqKiDDqCAqKnRydWUqKlxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIEV4cGFuZENvbGxhcHNlT3B0aW9uczogRXhwYW5kQ29sbGFwc2VPcHRpb25zO1xyXG5cclxuICAvKipcclxuICAgKiBCbG9jY28gY29tcGxldG8gZGVsbGUgb3B6aW9uaSwgYWx0ZXJuYXRpdm8gYWxsJ2Fzc2VnbmF6aW9uZSBkaSAqKkVsZW1lbnRzKiosICoqTm9kZVN0eWxlcyoqLCAqKkVkZ2VTdHlsZXMqKiwgZSAqKkxheW91dCoqLlxyXG4gICAqIFxyXG4gICAqIFF1YWxvcmEgZW50cmFtYmUgdmVuaXNzZXJvIHNwZWNpZmljYXRlIHZlcnLDoCBlZmZldHR1YXRhIHVuJ3VuaW9uZSBmcmEgcXVlc3RlIG9wemlvbmkgZSBxdWVsbGUgc3BlY2lmaWNhdGUsIGRhbmRvIHByaW9yaXTDoCBhbGxlIHNwZWNpZmljYXRlXHJcbiAgICovXHJcbiAgQElucHV0KCkgTmF0aXZlT3B0aW9uczogY3l0b3NjYXBlLkN5dG9zY2FwZU9wdGlvbnMgPSB7fTtcclxuXHJcbiAgLyoqXHJcbiAgICogRGVmaW5pemlvbmUgZGVnbGkgZWxlbWVudGkgZGEgbW9zdHJhcmUgbmVsIGRpYWdyYW1tYVxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIEVsZW1lbnRzOiBjeXRvc2NhcGUuRWxlbWVudERlZmluaXRpb25bXTtcclxuXHJcbiAgLyoqXHJcbiAgICogRGVmaW5pemlvbmUgZGVnbGkgc3RpbGkgZGVpIG5vZGlcclxuICAgKi9cclxuICBASW5wdXQoKSBOb2RlU3R5bGVzOiBjeXRvc2NhcGUuQ3NzLk5vZGU7XHJcblxyXG4gIC8qKlxyXG4gICAqIERlZmluaXppb25lIGRlZ2xpIHN0aWxpIGRlaSBjb2xsZWdhbWVudGkgZnJhIGkgbm9kaVxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIEVkZ2VTdHlsZXM6IGN5dG9zY2FwZS5Dc3MuRWRnZTtcclxuXHJcbiAgLyoqXHJcbiAgICogSW4gdW4gZGlhZ3JhbW1hIGluIHNvbGEgbGV0dHVyYSB0dXR0ZSBsZSBpbnRlcmF6aW9uaSB1dGVudGUgc29ubyBhbm51bGxhdGVcclxuICAgKi9cclxuICBASW5wdXQoKSBSZWFkb25seTogYm9vbGVhbjtcclxuXHJcbiAgLyoqXHJcbiAgICogQWdnaW9ybmEgYXV0b21hdGljYW1lbnRlIGxlIGRpbWVuc2lvbmkgZGVsIGRpYWdyYW1tYSBxdWFuZG8gY2FtYmlhbm8gbGUgZGltZW5zaW9uaSBkZWxsYSBmaW5lc3RyYVxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIEF1dG91cGRhdGVTaXplOiBib29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgLyoqXHJcbiAgICogSW5kaWNhIGRpIG1hbnRlbmVyZSBsYSBwb3NpemlvbmUgZGVpIG5vZGkgcXVhbG9yYSB2ZW5pc3Nlcm8gY2FtYmlhdGkgZGFsbCdJbnB1dCAqKkVsZW1lbnRzKiouXHJcbiAgICogXHJcbiAgICogU2UgbCdJRCBkaSB1biBub2RvIMOoIHVndWFsZSBhbGwnSUQgZGkgdW4gbm9kbyBwcmVzZW50ZSBpbiBwcmVjZWRlbnphLCBpbCBudW92byBub2RvIG5lIGVyZWRpdGVyw6AgbGEgcG9zaXppb25lXHJcbiAgICovXHJcbiAgQElucHV0KCkgUHJlc2VydmVFbGVtZW50c1Bvc2l0aW9uOiBib29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgLyoqXHJcbiAgICogUXVhbG9yYSB2ZW5pc3NlIG1vZGlmaWNhdG8gbCdJbnB1dCAqKkVsZW1lbnRzKiosIHBpdXR0b3N0byBjaGUgbWV0dGVyZSBzZW1wbGljZW1lbnRlIGlsIG51b3ZvIEVsZW1lbnRvIGluIGJhc2UgYWwgTGF5b3V0IHByZWNlZGVudGUsIGFwcGxpY2EgYW5jaGUgdW4nYW5pbWF6aW9uZSBcclxuICAgKiBcclxuICAgKiBGdW56aW9uYSBzb2xhbWVudGUgc2UgaWwgKipMYXlvdXQqKiBjb3JyZW50ZSBkZWwgZGlhZ3JhbW1hIHN1cHBvcnRhIGxlIGFuaW1hemlvbmlcclxuICAgKi9cclxuICBASW5wdXQoKSBBbmltYXRlTGF5b3V0Q2hhbmdlczogYm9vbGVhbiA9IHRydWU7XHJcblxyXG4gIC8qKlxyXG4gICAqIEF0dGl2YSB1bmEgbW9kYWxpdMOgIGRpIHNlbGV6aW9uZSBcInNtYXJ0XCIuLi4gbyBwZXJsb21lbm8gXCJzbWFydGVyXCIgZGVsIGRlZmF1bHQgZGkgQ3l0b3NjYXBlLlxyXG4gICAqIFxyXG4gICAqIC0gSWwgY2xpY2sgZGkgdW4gZWxlbWVudG8gbm9uIHNlbGV6aW9uYXRvIGxvIHNlbGV6aW9uYVxyXG4gICAqIC0gSWwgY2xpY2sgZGkgdW4gZWxlbWVudG8gc2VsZXppb25hdG8gbG8gZGVzZWxlemlvbmFcclxuICAgKiAtIExvIHN0YXRvIGRpIHNlbGV6aW9uZSB2aWVuZSBwZXJzaXN0aXRvIHN1bGwnb2dnZXR0byBvcmlnaW5hbGUgaW52ZWNlIGRpIHJpbWFuZXJlIGluIHVuIGludGVybmFsXHJcbiAgICogLSBBbGwnYXNzZWduYXppb25lIGRpIG9nZ2V0dGkgc2VsZXppb25hdGksIHF1ZXN0aSB2ZW5nb25vIG1hcmNhdGkgY29ycmV0dGFtZW50ZSBjb24gbCdvdmVybGF5IGRpIHNlbGV6aW9uZVxyXG4gICAqIFxyXG4gICAqIE4uQjogbGEgY2hpYW1hdGEgYWxsJ2V2ZW50byAqKm9uTm9kZUNsaWNrKiogYXZ2aWVuZSAqKkRPUE8qKiBsYSBnZXN0aW9uZSBkZWxsYSBzZWxlemlvbmVcclxuICAgKi9cclxuICBASW5wdXQoKSBTbWFydFNlbGVjdGlvbjogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAvKipcclxuICAgKiBJbmRpY2EgZGkgc2VsZXppb25hcmUgdW4gZWxlbWVudG8gcGVyIHZvbHRhIHF1YWxvcmEgKipTbWFydFNlbGVjdGlvbioqIGZvc3NlIGF0dGl2b1xyXG4gICAqL1xyXG4gIEBJbnB1dCgpIFNpbmdsZVNlbGVjdGlvbjogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAvKipcclxuICAgKiBDU1MgcGVyIGxhIGdyYWZpY2F6aW9uZSBkZWxsYSBzZWxlemlvbmUgZGVpIG5vZGkuIFF1YW5kbyB1biBub2RvIHZlcnLDoCBzZWxlemlvbmF0byBhdnLDoCBzb3ByYSBkaSBzZSB1biBvdmVybGF5IGNoZSAnc2JvcmRhJyBkaSAqKm92ZXJsYXktcGFkZGluZyoqIHBpeGVsLFxyXG4gICAqIGRpIGNvbG9yZSAqKm92ZXJsYXktY29sb3IqKiBlIGNvbiB1biBvcGFjaXTDoCAqKm92ZXJsYXktb3BhY2l0eSoqXHJcbiAgICogXHJcbiAgICogQXNzZWduYW5kbyBcInt9XCIgYSBxdWVzdG8gaW5wdXQsIGxhIFNtYXJ0IHNlbGVjdGlvbiB2aWVuZSBnZXN0aXRhIG1hIGxhIGdlc3Rpb25lIGdyYWZpY2Egw6ggYWZmaWRhdGEgYWxsJ3V0ZW50ZSxcclxuICAgKiBhZCBlc2VtcGlvIHVzYW5kbyBkZWkgKipOb2RlSFRNTFRlbXBsYXRlcyoqIGNoZSBkZWZpbmlzY2FubyBzZWxldHRvcmkgc3Ugbm9kaSBcIjpzZWxlY3RlZFwiXHJcbiAgICogXHJcbiAgICogQGRlZmF1bHQgeydvdmVybGF5LWNvbG9yJzonYmx1ZScsJ292ZXJsYXktb3BhY2l0eSc6MC41LCdvdmVybGF5LXBhZGRpbmcnOjd9XHJcbiAgICovXHJcbiAgQElucHV0KCkgU21hcnRTZWxlY3Rpb25TdHlsZXM6IHsgJ292ZXJsYXktY29sb3InOiBzdHJpbmcsICdvdmVybGF5LW9wYWNpdHknOiBudW1iZXIsICdvdmVybGF5LXBhZGRpbmcnOiBudW1iZXIgfSA9IG51bGxcclxuXHJcbiAgLyoqXHJcbiAgICogUGVyaW9kbyBkaSB0aHJvdHRsZSBkYSBxdWFuZG8gdmllbmUgZWZmZXR0dWF0byB1biByZXNpemUgYSBxdWFuZG8gcmljYWxjb2xhcmUgbGUgZGltZW5zaW9uaSBkZWwgZGlhZ3JhbW1hLlxyXG4gICAqIFxyXG4gICAqIFB1w7IgZXNzZXJlIHRlbnV0byBhIDAgKHJlZHJhdyBpc3RhbnRhbmVvKSBmaW5jaMOpIG5vbiBjaSBzb25vIHByb2JsZW1pIGRpIHByZXN0YXppb25pIGNvbiBldmVudHVhbG1lbnRlIHRhbnRpIHJlc2l6ZSBhIHBvY2EgZGlzdGFuemEgbCd1bm8gZGFsbCdhbHRyby5cclxuICAgKi9cclxuICBASW5wdXQoKSBSZXNpemVUaHJvdHRsZVRpbWU6IG51bWJlciA9IDA7XHJcblxyXG4gIC8qKlxyXG4gICAqIExheW91dCBkaSBvcmRpbmFtZW50byBkZWkgbm9kaVxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIExheW91dDogQnJlYWR0aEZpcnN0TGF5b3V0T3B0aW9uc0ltcGwgfCBDaXJjbGVMYXlvdXRPcHRpb25zSW1wbCB8IENvbmNlbnRyaWNMYXlvdXRPcHRpb25zSW1wbCB8XHJcbiAgICBDb3NlTGF5b3V0T3B0aW9uc0ltcGwgfCBEYWdyZUxheW91dE9wdGlvbnNJbXBsIHwgR3JpZExheW91dE9wdGlvbnNJbXBsIHwgTnVsbExheW91dE9wdGlvbnNJbXBsIHwgUHJlc2V0TGF5b3V0T3B0aW9uc0ltcGwgfFxyXG4gICAgUmFuZG9tTGF5b3V0T3B0aW9uc0ltcGw7XHJcblxyXG4gIC8qKlxyXG4gICAqIFRlbXBsYXRlIEhUTUwgZGEgYXBwbGljYXJlIGFpIG5vZGkgcGVyIGRhcmdsaSBzdGlsaSBwYXJ0aWNvbGFyaSwgZGl2ZXJzaSBkYWxsZSBzaGFwZSBkaSBkZWZhdWx0XHJcbiAgICovXHJcbiAgQElucHV0KCkgTm9kZUhUTUxUZW1wbGF0ZXM6IE5vZGVIVE1MVGVtcGxhdGVbXTtcclxuXHJcbiAgLyoqXHJcbiAgICogRm9ybmlzY2UgaWwgZ2xvYmFsIGRlbGxhIGxpYnJlcmlhIChuYW1lc3BhY2UgKipjeXRvc2NhcGUqKikgZSBzaSBhc3BldHRhIGNoZSBkb3BvIG9wZXJhemlvbmkgZGkgaW1wb3J0YXppb25lIFxyXG4gICAqIGxhc2NpYXRlIGFsbCd1dGVudGUgdmVuZ2FubyBhZ2dpdW50aSB0dXR0aSBpIG1vZHVsaSBkZXNpZGVyYXRpLiBcclxuICAgKiBcclxuICAgKiDDiCAqKmZvbmRhbWVudGFsZSoqIGNoZSBpbCBwcmltbyBwYXJhbWV0cm8gKGlsIG5vbWUgZGVsIG1vZHVsbykgc2lhIHVndWFsZSBhIGNpw7IgZGkgY3VpIHZpZW5lIGZhdHRvIGlsIHJlcXVpcmUgaW4gbW9kbyBjaGUgbGEgbGlicmVyaWFcclxuICAgKiBwb3NzYSBjb250cm9sbGFyZSBjaGUgaWwgbW9kdWxvIGltcG9ydGF0byBub24gc2lhIGdpw6Agc3RhdG8gaW1wb3J0YXRvIGluIHByZWNlZGVuemFcclxuICAgKiBcclxuICAgKiAjIyBFc2VtcGlvOlxyXG4gICAqIFxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiAoZ2xvYmFsKSA9PiB7XHJcbiAgICogICAgcmV0dXJuIGltcG9ydChcImN5dG9zY2FwZS1leHRlbnNpb24tbGlicmFyeVwiKS50aGVuKG1vZHVsZSA9PiBnbG9iYWwudXNlKFwiY3l0b3NjYXBlLWV4dGVuc2lvbi1saWJyYXJ5XCIsIG1vZHVsZS5kZWZhdWx0KSk7XHJcbiAgICogXHJcbiAgICogICAgLi4uXHJcbiAgICogfVxyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIEV4dGVuc2lvbk1vZHVsZXNJbXBvcnRlcjogKGdsb2JhbDogeyB1c2U6IChtb2R1bGVOYW1lOiBzdHJpbmcsIG1vZHVsZTogdm9pZCB8IGN5dG9zY2FwZS5FeHQpID0+IHZvaWQgfSkgPT4gUHJvbWlzZTxhbnk+ID0gbnVsbDtcclxuXHJcbiAgLyoqXHJcbiAgICogRm9ybmlzY2UgbCdpc3RhbnphIGF0dHVhbGUgZGkgQ3l0b3NjYXBlIGRhIGN1aSDDqCBwb3NzaWJpbGUgcHJlbmRlcmUgbGUgbGlicmVyaWUgZGkgZXN0ZW5zaW9uZSBjYXJpY2F0ZSBpbiAqKkV4dGVuc2lvbk1vZHVsZXNJbXBvcnRlcioqXHJcbiAgICogZSBjb25maWd1cmFybGUgaW4gYmFzZSBhaSBjb21wb3J0YW1lbnRpIHNwZWNpZmljaVxyXG4gICAqIFxyXG4gICAqICMjIEVzZW1waW86XHJcbiAgICogXHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIChjeXRvc2NhcGVDb3JlKSA9PiB7XHJcbiAgICogICAgLy8gRmFyZSBxdWVzdG8gbGF2b3JvIHBlciBvZ25pIGVzdGVuc2lvbmUgY2FyaWNhdGFcclxuICAgKiAgICBsZXQgZXh0ZW5zaW9uQ29uZmlndXJhdGlvbiA9IHsgLi4uIH07XHJcbiAgICogICAgbGV0IGV4dGVuc2lvbkluc3RhbmNlID0gY3l0b3NjYXBlQ29yZS5leHRlbnNpb25MaWJyYXJ5KGV4dGVuc2lvbkNvbmZpZ3VyYXRpb24pO1xyXG4gICAqICAgIGV4dGVuc2lvbkluc3RhbmNlLmRvU29tZXRoaW5nU3BlY2lmaWNUb1RoaXNFeHRlbnNpb24oKTtcclxuICAgKiBcclxuICAgKiAgICAuLi5cclxuICAgKiB9XHJcbiAgICogYGBgXHJcbiAgICovXHJcbiAgQElucHV0KCkgRXh0ZW5zaW9uTW9kdWxlc0FwcGx5ZXI6IChjeXRvc2NhcGVDb3JlOiBjeXRvc2NhcGUuQ29yZSkgPT4gdm9pZCA9IG51bGw7XHJcblxyXG4gIC8qKlxyXG4gICAqIEV2ZW50byBsYW5jaWF0byBhbCBjbGljayBkaSB1biBub2RvLCBjb250aWVuZSBsJ29nZ2V0dG8gKipkYXRhKiogZGVsIG5vZG8gaW4gcXVlc3Rpb25lXHJcbiAgICovXHJcbiAgQE91dHB1dCgpIG9uTm9kZUNsaWNrOiBFdmVudEVtaXR0ZXI8eyBkYXRhOiBhbnkgfT4gPSBuZXcgRXZlbnRFbWl0dGVyPHsgZGF0YTogYW55IH0+KCk7XHJcblxyXG4gIC8qKlxyXG4gICAqIEV2ZW50byBsYW5jaWF0byBhbGxhIHNlbGV6aW9uZSBvIGRlc2VsZXppb25lIGRpIHVuIG5vZG8sIGNvbnRpZW5lIGwnb2dnZXR0byAqKmRhdGEqKiBkZWwgbm9kbyBpbiBxdWVzdGlvbmUgZSBpbmZvcm1hemlvbmkgc3VsIHN1byBzdGF0byBkaSBzZWxlemlvbmVcclxuICAgKi9cclxuICBAT3V0cHV0KCkgb25Ob2RlU2VsZWN0aW9uOiBFdmVudEVtaXR0ZXI8eyBkYXRhOiBhbnksIHNlbGVjdGVkOiBib29sZWFuIH0+ID0gbmV3IEV2ZW50RW1pdHRlcjx7IGRhdGE6IGFueSwgc2VsZWN0ZWQ6IGJvb2xlYW4gfT4oKTtcclxuXHJcbiAgLyoqXHJcbiAgICogRXZlbnRvIGxhbmNpYXRvIGFsIHRlcm1pbmUgZGVsIExheW91dGluZy4gU2Ugc2kgdnVvbGUgZXNlZ3VpcmUgY29kaWNlIGRvcG8gY2hlIGlsIExheW91dCDDqCBmYXR0byBlIGNvbXBsZXRhbWVudGUgZ3JhZmljYXRvLCBxdWVzdG8gw6ggaWwgcHVudG9cclxuICAgKi9cclxuICBAT3V0cHV0KCkgb25MYXlvdXREb25lOiBFdmVudEVtaXR0ZXI8dm9pZD4gPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XHJcblxyXG4gIC8qKlxyXG4gICAqIEV2ZW50byBsYW5jaWF0byBhbCB0ZXJtaW5lIGRlbCBjYXJpY2FtZW50byBkZWwgZGlhZ3JhbW1hXHJcbiAgICovXHJcbiAgQE91dHB1dCgpIG9uTG9hZGVkOiBFdmVudEVtaXR0ZXI8dm9pZD4gPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XHJcblxyXG4gIC8qKlxyXG4gICAqIFZhcmlhYmlsZSBzdSBjdWkgc2FsdmFyc2kgc2UgaSBub2RpIGhhbm5vIHVuYSBnZXJhcmNoaWEgYSBncnVwcGkgbyBuby4gU2VydmUgcGVyIHBvaSBjYXJpY2FyZSBsJ2VzdGVuc2lvbmUgZXhwYW5kLWNvbGxhcHNlIHF1YWxvcmEgZm9zc2UgcmljaGllc3RhXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBOb2Rlc0hpZXJhcmNoeTogYm9vbGVhbjtcclxuXHJcbiAgLyoqXHJcbiAgICogSW5kaWNhIHNlIGlsIHJlbmRlcmluZyBkZWwgZGlhZ3JhbW1hIMOoIHRlcm1pbmF0b1xyXG4gICAqL1xyXG4gIHByaXZhdGUgUmVuZGVyZWQ6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgLyoqXHJcbiAgICogSXN0YW56YSBkZWwgZGlhZ3JhbW1hIGF0dHVhbG1lbnRlIGluIHVzb1xyXG4gICAqL1xyXG4gIHB1YmxpYyBjeTogY3l0b3NjYXBlLkNvcmVcclxuXHJcbiAgLyoqXHJcbiAgICogQXBpIGRlbGwnZXN0ZW5zaW9uZSBleHBhbmQtY29sbGFwc2UgcGVyIHBlcm1ldHRlcmUgZGkgZWZmZXR0dWFyZSBvcGVyYXppb25pIGRhbGwnZXN0ZXJubyBkZWwgZGlhZ3JhbW1hLiBWZW5nb25vIHZhbG9yaXp6YXRlIHNlICoqVXNlRXhwYW5kQ29sbGFwc2UqKiDDqCAqKnRydWUqKlxyXG4gICAqL1xyXG4gIHB1YmxpYyBFeHBhbmRDb2xsYXBzZUFwaTogYW55ID0gbnVsbDtcclxuXHJcbiAgLyoqXHJcbiAgICogQXBpIGRlbGwnZXN0ZW5zaW9uZSBodG1sLW5vZGUgcGVyIHBlcm1ldHRlcmUgZGkgZWZmZXR0dWFyZSBvcGVyYXppb25pIGRhbGwnZXN0ZXJubyBkZWwgZGlhZ3JhbW1hLiBWZW5nb25vIHZhbG9yaXp6YXRlIHNlIHNvbm8gaW1wb3N0YXRpIGRlaSAqKk5vZGVIVE1MVGVtcGxhdGVzKipcclxuICAgKi9cclxuICBwcml2YXRlIEh0bWxOb2RlQXBpOiBhbnkgPSBudWxsO1xyXG5cclxuICAvKipcclxuICAgKiBPc3NlcnZhdG9yZSBkZWxsZSBtb2RpZmljaGUgYWwgY29udGVuaXRvcmUgZGVsIGRpYWdyYW1tYVxyXG4gICAqL1xyXG4gIHByaXZhdGUgcmVzaXplT2JzZXJ2ZXI6IFJlc2l6ZVNlbnNvcjtcclxuXHJcbiAgLyoqXHJcbiAgICogUmlmZXJpbWVudG8gYWxsJ3VsdGltbyBsYXlvdXQgdXRpbGl6emF0by4gVmllbmUgcmlhcHBsaWNhdG8gcXVhbG9yYSB2ZW5pc3NlIGNhbWJpYXRvIGwnSW5wdXQgKipFbGVtZW50cyoqLlxyXG4gICAqIFxyXG4gICAqIE5vbiB1dGlsaXp6byBpbCBtYWtlTGF5b3V0cyBwZXJjaMOpIGFsdHJpbWVudGkgcmlzY2hpZXJlaSBkaSBjcmVhcmUgdW4gbGF5b3V0IHJpZmVyaXRvIGEgWCBlbGVtZW50aSwgbmUgYWdnaXVuZ28gMSwgcmlhcHBsaWNvIGlsIExheW91dCBcclxuICAgKiBtYSBtaSB2aWVuZSByaWFwcGxpY2F0byBhIFggZWxlbWVudGkgaW52ZWNlIGNoZSBYICsgMVxyXG4gICAqL1xyXG4gIHByaXZhdGUgTGFzdExheW91dDogY3l0b3NjYXBlLkxheW91dE9wdGlvbnM7XHJcblxyXG4gIC8qKlxyXG4gICAqIENvc3RydXR0b3JlXHJcbiAgICogXHJcbiAgICogQGlnbm9yZVxyXG4gICAqL1xyXG4gIGNvbnN0cnVjdG9yKEBPcHRpb25hbCgpIHByaXZhdGUgc2VydmljZTogRXNEaWFncmFtU2VydmljZSwgQE9wdGlvbmFsKCkgcHJpdmF0ZSBkaXNwYXRjaGVyOiBFc0RpYWdyYW1EaXNwYXRjaGVyLCBwcml2YXRlIGV4dHM6IFJlYWN0aXZlRXh0ZW5zaW9ucykgeyB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEBpZ25vcmUgXHJcbiAgICogXHJcbiAgICogQW5ndWxhciBQaXBlbGluZVxyXG4gICAqL1xyXG4gIHB1YmxpYyBuZ0FmdGVyVmlld0luaXQoKSB7XHJcbiAgICBpZiAoIXRoaXMuc2VydmljZSB8fCAhdGhpcy5kaXNwYXRjaGVyKVxyXG4gICAgICB0aHJvdyBcIklsIG1vZHVsbyBAZXNmYWVuemEvZGlhZ3JhbXMgbm9uIMOoIHN0YXRvIGltcG9ydGF0byBjb24gaWwgZm9yUm9vdCgpO1wiO1xyXG5cclxuICAgIHRoaXMuZGlzcGF0Y2hMb2FkQ2hhcnQoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEFsbCdvbkRlc3Ryb3kgcmlwdWxpc2NvIGxhIG1lbW9yaWEgZGFsIGRpYWdyYW1tYVxyXG4gICAqL1xyXG4gIHB1YmxpYyBuZ09uRGVzdHJveSgpIHtcclxuICAgIGlmICh0aGlzLnJlc2l6ZU9ic2VydmVyKSB7XHJcbiAgICAgIHRoaXMucmVzaXplT2JzZXJ2ZXIuZGlzcG9zZSgpO1xyXG4gICAgICB0aGlzLnJlc2l6ZU9ic2VydmVyID0gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5jeSkge1xyXG4gICAgICB0aGlzLnNlcnZpY2UubG9nKFwiSVwiLCBcIkRpYWdyYW1cIiArIFwiIFwiICsgdGhpcy5uYW1lICsgXCI6IFVubG9hZGluZyBkZXN0cm95ZWQgZGlhZ3JhbVwiLCBmYWxzZSk7XHJcbiAgICAgIHRoaXMuY3kuZGVzdHJveSgpO1xyXG4gICAgICB0aGlzLmRpc3BhdGNoZXIuZGVyZWdpc3Rlcih0aGlzLm5hbWUpO1xyXG4gICAgfVxyXG4gICAgZWxzZVxyXG4gICAgICB0aGlzLnNlcnZpY2UubG9nKFwiSVwiLCBcIkNoYXJ0IFwiICsgdGhpcy5uYW1lICsgXCI6IFVubG9hZGluZyB1bmNyZWF0ZWQgY2hhcnQgY29tcG9uZW50LiBJdCBwcm9iYWJseSB3YXMgYSBkdXBsaWNhdGVkXCIsIGZhbHNlKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJlZ2lzdHJhIGlsIGRpYWdyYW1tYSBhdHR1YWxlIG5lbCBEaXNwYXRjaGVyIGluIG1vZG8gY2hlIHZlbmdhIGNhcmljYXRvIGFwcGVuYSBwb3NzaWJpbGVcclxuICAgKi9cclxuICBwcml2YXRlIGRpc3BhdGNoTG9hZENoYXJ0KCk6IHZvaWQge1xyXG4gICAgdGhpcy5kaXNwYXRjaGVyLnJlZ2lzdGVyKHRoaXMubmFtZSwgKCkgPT4geyByZXR1cm4gdGhpcy5yZW5kZXIoKTsgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBAaWdub3JlIFxyXG4gICAqIFxyXG4gICAqIEFuZ3VsYXIgUGlwZWxpbmU6IEdlc3Rpb25lIHJpLWdyYWZpY2F6aW9uZSBkZWwgZGlhZ3JhbW1hLCBzZSBwb3NzaWJpbGVcclxuICAgKi9cclxuICBwdWJsaWMgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IGFueSB7XHJcbiAgICBsZXQgdG9DaGVjayA9IFtcIlRlbXBsYXRlc1wiLCBcIlVzZUNvbnRleHRNZW51XCIsIFwiQ29udGV4dE1lbnVPcHRpb25zXCIsIFwiVXNlRXhwYW5kQ29sbGFwc2VcIiwgXCJFeHBhbmRDb2xsYXBzZU9wdGlvbnNcIiwgXCJOb2RlU3R5bGVzXCIsIFwiRWRnZVN0eWxlc1wiLCBcIk5hdGl2ZU9wdGlvbnNcIl07XHJcblxyXG4gICAgaWYgKHRoaXMuUmVuZGVyZWQgJiYgdG9DaGVjay5zb21lKHQgPT4gY2hhbmdlc1t0XSkpXHJcbiAgICAgIHRoaXMuc2VydmljZS5sb2coXCJXXCIsIFwiUmVkcmF3IGJhc2VkIG9uIGR5bmFtaWMgSW5wdXQgY2hhbmdlIGlzIHN1cHBvcnRlZCBvbmx5IGZvciAnRWxlbWVudHMnIGFuZCAnTGF5b3V0JyBpbnB1dHMsIHBsZWFzZSBkZXN0cm95IHRoZSBjb21wb25lbnQgYW5kIHJlY3JlYXRlIGl0IHdpdGggdGhlIG5ldyBzZXR0aW5nc1wiKTtcclxuXHJcbiAgICBsZXQgZWxlbWVudENoYW5nZXMgPSBjaGFuZ2VzW1wiRWxlbWVudHNcIl07XHJcbiAgICBsZXQgbGF5b3V0Q2hhbmdlcyA9IGNoYW5nZXNbXCJMYXlvdXRcIl07XHJcbiAgICBpZiAoZWxlbWVudENoYW5nZXMgJiYgIWVsZW1lbnRDaGFuZ2VzLmZpcnN0Q2hhbmdlKSB7XHJcbiAgICAgIHRoaXMuc2VydmljZS5sb2coXCJJXCIsIFwiRWxlbWVudHMgaGF2ZSBiZWVuIGNoYW5nZWQgYWZ0ZXIgZGlhZ3JhbSBpbml0aWFsaXphdGlvblwiKTtcclxuXHJcbiAgICAgIC8vIENhbWJpYW1lbnRvIGFnbGkgRWxlbWVudGk6IHJpcHVsaXNjbyBnbGkgZWxlbWVudGkgdmVjY2hpLCBwcmVuZG8gaSBudW92aSwgbGkgc2lzdGVtbyBlIGxpIHJpYXNzZWduby4gXHJcbiAgICAgIC8vIFNlIGlsIG51b3ZvIElucHV0IEVsZW1lbnRzIMOoIHJvYmEgc3RyYW5hIG1pIGxpbWl0byBhIHJpcHVsaXJlIGlsIGRpYWdyYW1tYVxyXG4gICAgICAvLyBTZSBjeXRvc2NhcGUgYXZldmEgZ2nDoCBkZWdsaSBlbGVtZW50aSBwcmVjZWRlbnRlbWVudGUgbmUgcHJlbmRvIGxlIHBvc2l6aW9uaSBpbiBtb2RvIGRhIHJpZGlzZWduYXJsaSBwYXJ0ZW5kbyBkYWxsbyBzdGVzc28gcHVudG8gKGNhcmlubyBwZXIgbGUgYW5pbWF6aW9uaSlcclxuICAgICAgbGV0IGVsZW1lbnRzID0gZWxlbWVudENoYW5nZXM/LmN1cnJlbnRWYWx1ZTtcclxuICAgICAgbGV0IHByZXZpb3VzX2VsZW1lbnRzID0gdGhpcy5QcmVzZXJ2ZUVsZW1lbnRzUG9zaXRpb24gPyA8YW55PnRoaXMuY3kubm9kZXMoKSA6IG51bGw7XHJcblxyXG4gICAgICB0aGlzLmN5LmVsZW1lbnRzKCkucmVtb3ZlKCk7XHJcbiAgICAgIGlmIChlbGVtZW50cyAmJiBlbGVtZW50cy5sZW5ndGggJiYgZWxlbWVudHMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgIHRoaXMucmV2aWV3Q3l0b3NjYXBlRWxlbWVudHMoZWxlbWVudHMsIHByZXZpb3VzX2VsZW1lbnRzKTtcclxuICAgICAgICB0aGlzLmN5LmFkZChlbGVtZW50cyk7XHJcblxyXG4gICAgICAgIGlmICh0aGlzLlNtYXJ0U2VsZWN0aW9uKVxyXG4gICAgICAgICAgdGhpcy5zZXR1cEVsZW1lbnRzU2VsZWN0aW9uSWZOZWVkZWQoKTtcclxuXHJcbiAgICAgICAgLy8gU2Ugc29sbyBnbGkgZWxlbWVudGkgY2FtYmlhbm8sIHJpYXBwbGljbyBpbCBMYXlvdXQgcHJlY2VkZW50ZVxyXG4gICAgICAgIGlmICghbGF5b3V0Q2hhbmdlcyAmJiB0aGlzLkxhc3RMYXlvdXQpIHtcclxuXHJcbiAgICAgICAgICAvLyBTZSBkZXZvIGFuaW1hcmUgbGUgbW9kaWZjaGUgYWwgbGF5b3V0IGZvcnpvIGlsIHBhcmFtZXRybyByZWxhdGl2b1xyXG4gICAgICAgICAgaWYgKHRoaXMuQW5pbWF0ZUxheW91dENoYW5nZXMpXHJcbiAgICAgICAgICAgICg8YW55PnRoaXMuTGFzdExheW91dCkuYW5pbWF0ZSA9IHRydWU7XHJcblxyXG4gICAgICAgICAgdGhpcy5jeS5sYXlvdXQodGhpcy5MYXN0TGF5b3V0KS5ydW4oKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyBTZSBpbCBsYXlvdXQgY2FtYmlhIGxvIGFwcGxpY28gZSBtZSBsbyBzYWx2byBjb21lIGxheW91dCBwcmVjZWRlbnRlIHBlciBpbCBmdXR1cm9cclxuICAgIGlmIChsYXlvdXRDaGFuZ2VzICYmICFsYXlvdXRDaGFuZ2VzLmZpcnN0Q2hhbmdlKSB7XHJcbiAgICAgIHRoaXMuc2VydmljZS5sb2coXCJJXCIsIFwiTGF5b3V0IGhhdmUgYmVlbiBjaGFuZ2VkIGFmdGVyIGRpYWdyYW0gaW5pdGlhbGl6YXRpb25cIik7XHJcbiAgICAgIHRoaXMuTGFzdExheW91dCA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkobGF5b3V0Q2hhbmdlcy5jdXJyZW50VmFsdWUpKTtcclxuICAgICAgdGhpcy5jeS5sYXlvdXQodGhpcy5MYXN0TGF5b3V0KS5ydW4oKVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRWZmZXR0dWEgaWwgcmVuZGVyaW5nIGRlbCBkaWFncmFtbWFcclxuICAgKi9cclxuICBwcml2YXRlIGFzeW5jIHJlbmRlcigpIHtcclxuXHJcbiAgICAvLyBUaXJvIGZ1b3JpIGxlIG9wemlvbmkgY29uIGN1aSBnZW5lcmFyZSBpbCBkaWFncmFtbWFcclxuICAgIGxldCBjeU9wdGlvbnMgPSB0aGlzLmdldENvbXBsZXRlZE9wdGlvbnMoKTtcclxuICAgIHRoaXMuTm9kZXNIaWVyYXJjaHkgPSBjeU9wdGlvbnMuZWxlbWVudHMgJiYgKDxjeV8uRWxlbWVudERlZmluaXRpb25bXT5jeU9wdGlvbnMuZWxlbWVudHMpLnNvbWUodCA9PiB0LmRhdGEucGFyZW50KTtcclxuXHJcbiAgICAvLyBDYXJpY28gZXZlbnR1YWxpIGNsYXNzaSBkaSBlc3RlbnNpb25lIGNoZSBzZXJ2b25vXHJcbiAgICBhd2FpdCB0aGlzLnBlcmZvcm1Nb2R1bGVzTG9hZGluZygpO1xyXG5cclxuICAgIC8vIEdlbmVybyBpbCBkaWFncmFtbWFcclxuICAgIHRoaXMuY3kgPSBjeXRvc2NhcGUoY3lPcHRpb25zKTtcclxuXHJcbiAgICAvLyBDb2xsZWdvIGdsaSBldmVudGkgYWwgY29tcG9uZW50ZVxyXG4gICAgdGhpcy5iaW5kQ3l0b3NjYXBlRXZlbnRzKCk7XHJcblxyXG4gICAgLy8gVXRpbGl6em8gbGUgY2xhc3NpIGRpIGVzdGVuc2lvbmUgY2FyaWNhdGUgcHJlY2VkZW50ZW1lbnRlIHBlciBmYXJlIGlsIHJlc3RvIGRlbGxlIG1pZSBvcGVyYXppb25pXHJcbiAgICB0aGlzLnBlcmZvcm1PcGVyYXRpb25zV2l0aExvYWRlZE1vZHVsZXMoKTtcclxuXHJcbiAgICAvLyBJbXBvc3RvIGxhIHZhcmlhYmlsZSBSZW5kZXJlZCBhIHRydWUgaW4gbW9kbyBjaGUgc2UgZGEgYWRlc3NvIHZlbmdvbm8gZmF0dGUgbW9kaWZpY2hlIGNoZSBkb3ZyZWJiZXJvIGNhdXNhcmUgdW4gcmVkcmF3IHBvc3NvIGFjY29yZ2VybWVuZVxyXG4gICAgLy8gZSBtYW5kYXJlIGEgY2FnYXJlIGxvIHN0cm9uem8gZGkgdHVybm9cclxuICAgIHRoaXMuUmVuZGVyZWQgPSB0cnVlO1xyXG5cclxuICAgIC8vIFNlIGRldm8gYWdnaW9ybmFyZSBpbiBhdXRvbWF0aWNvIGluIGJhc2UgYWxsYSBkaW1lbnNpb25lIGRlbCBjb250ZW5pdG9yZSBjb2xsZWdvIGlsIFJlc2l6ZU9ic2VydmVyXHJcbiAgICBpZiAodGhpcy5BdXRvdXBkYXRlU2l6ZSlcclxuICAgICAgdGhpcy5saXN0ZW5PbkNoYW5nZXMoKTtcclxuXHJcbiAgICBpZiAodGhpcy5TbWFydFNlbGVjdGlvbikge1xyXG4gICAgICB0aGlzLnNldHVwU2VsZWN0aW9uU3R5bGVzKCk7XHJcbiAgICAgIHRoaXMuc2V0dXBFbGVtZW50c1NlbGVjdGlvbklmTmVlZGVkKCk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5vbkxvYWRlZC5lbWl0KCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBQcmVuZGUgdHV0dGkgZ2xpIGVsZW1lbnRpIGFwcGVuYSBhc3NlZ25hdGksIGUgc2UgcXVhbGN1bm8gZXJhIHNlbGV6aW9uYXRvIGxhIHNpdHVhemlvbmUgdmllbmUgcGVyc2lzdGl0YSBzdSBjeXRvc2NhcGVcclxuICAgKi9cclxuICBwcml2YXRlIHNldHVwRWxlbWVudHNTZWxlY3Rpb25JZk5lZWRlZCgpIHtcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5FbGVtZW50cy5sZW5ndGg7IGkrKykge1xyXG4gICAgICBsZXQgZWxkYXRhID0gPGFueT50aGlzLkVsZW1lbnRzW2ldLmRhdGE7XHJcbiAgICAgIGlmIChlbGRhdGEuX19zZWxlY3RlZCkge1xyXG4gICAgICAgIGxldCBlbCA9IHRoaXMuY3kuJGlkKGVsZGF0YS5pZCk7XHJcbiAgICAgICAgZWwuc2VsZWN0KCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENhcmljYSBnbGkgc3RpbGkgcGVyIG1vc3RyYXJlIGNhcmluYSBsYSBzZWxlemlvbmUgZGVpIG5vZGlcclxuICAgKi9cclxuICBwcml2YXRlIHNldHVwU2VsZWN0aW9uU3R5bGVzKCl7XHJcbiAgICBsZXQgY3NzSXRlbSA9IHRoaXMuU21hcnRTZWxlY3Rpb25TdHlsZXMgfHwge1xyXG4gICAgICAnb3ZlcmxheS1jb2xvcic6ICdibHVlJyxcclxuICAgICAgJ292ZXJsYXktb3BhY2l0eSc6IDAuNSxcclxuICAgICAgJ292ZXJsYXktcGFkZGluZyc6IDdcclxuICAgIH07XHJcblxyXG4gICAgLy8gQmFja2Rvb3IgcGVyIHBvdGVyIGFzc2VnbmFyZSBcInt9XCIgYSBTbWFydFNlbGVjdGlvblN0eWxlcyBpbiBtb2RvIGRpIHV0aWxpenphcmUgbGEgc21hcnQgc2VsZWN0aW9uIG1hIHNlbnphIGNoZSBuZXNzdW5vIHN0aWxlIHZlbmdhIGFwcGxpY2F0b1xyXG4gICAgLy8gYWQgZXNlbXBpbyBxdWFsb3JhIHNpIHZvbGVzc2UgdXRpbGl6emFyZSBsJ2h0bWxub2RlIHBlciBnZXN0aXJlIGxhIGdyYWZpY2EgZGVnbGkgZWxlbWVudGkgc2VsZXppb25hdGlcclxuICAgIGlmKGNzc0l0ZW1bJ292ZXJsYXktY29sb3InXSAmJiBjc3NJdGVtWydvdmVybGF5LW9wYWNpdHknXSAmJiBjc3NJdGVtWydvdmVybGF5LXBhZGRpbmcnXSlcclxuICAgICAgKDxhbnk+dGhpcy5jeS5zdHlsZSgpKS5zZWxlY3Rvcignbm9kZTpzZWxlY3RlZCcpLmNzcyhjc3NJdGVtKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJlZ2lzdHJhIGwnYXNjb2x0byBhbCBjb250ZW5pdG9yZSBkZWwgZ3JhZmljbyBlIGluIGNhc28gZGkgbW9kaWZpY2hlIGFsbGEgZGltZW5zaW9uZSwgYWwgbWFzc2ltbyB1bmEgdm9sdGEgb2duaSA1MDAgbWlsbGlzZWNvbmRpLCBsbyByaWRpc2VnbmFcclxuICAgKi9cclxuICBwcml2YXRlIGxpc3Rlbk9uQ2hhbmdlcygpIHtcclxuICAgIHRoaXMucmVzaXplT2JzZXJ2ZXIgPSBuZXcgUmVzaXplU2Vuc29yKHRoaXMuY3lHcmFwaC5uYXRpdmVFbGVtZW50LCAoKSA9PiB7XHJcbiAgICAgIHRoaXMuZXh0cy50aHJvdHRsZSh0aGlzLm5hbWUsIHRoaXMub25Db250YWluZXJTaXplQ2hhbmdlZC5iaW5kKHRoaXMpLCB0aGlzLlJlc2l6ZVRocm90dGxlVGltZSk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEZ1bnppb25lIGNoZSBzaSBvY2N1cGEgZGkgZ2VzdGlyZSBpbCByZXBhaW50IGRlbCBkaWFncmFtbWFcclxuICAgKi9cclxuICBwcml2YXRlIG9uQ29udGFpbmVyU2l6ZUNoYW5nZWQoKSB7XHJcbiAgICB0aGlzLnNlcnZpY2UubG9nKFwiSVwiLCBcIkRpYWdyYW0gY29udGFpbmVyIHNpemUgaGFzIGNoYW5nZWQsIHJlZHJhd2luZ1wiKTtcclxuICAgIHRoaXMuY3kucmVzaXplKCk7XHJcbiAgICB0aGlzLmN5LmZpdCgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ29sbGVnYSB0dXR0aSBnbGkgZXZlbnRpIGNoZSBtaSBwb3Nzb25vIHNlcnZpcmUgZSBsaSBlc3BvbmUgaW4gb3V0cHV0XHJcbiAgICovXHJcbiAgcHJpdmF0ZSBiaW5kQ3l0b3NjYXBlRXZlbnRzKCkge1xyXG4gICAgdGhpcy5jeS5iaW5kKCdjbGljaycsICdub2RlJywgKGV2ZW50KSA9PiB7XHJcbiAgICAgIGxldCB0YXJnZXREYXRhID0gZXZlbnQudGFyZ2V0LmRhdGEoKVxyXG4gICAgICBpZiAodGhpcy5TbWFydFNlbGVjdGlvbikge1xyXG5cclxuICAgICAgICAvLyBJbiBjYXNvIGRpIHNlbGV6aW9uZSBzaW5nb2xhIHJpcHVsaXNjbyB0dXR0aSBnbGkgZWxlbWVudGkgcHJlY2VkZW50ZW1lbnRlIHNlbGV6aW9uYXRpXHJcbiAgICAgICAgaWYgKHRoaXMuU2luZ2xlU2VsZWN0aW9uKSB7XHJcbiAgICAgICAgICBsZXQgc2VsZWN0ZWQgPSB0aGlzLmN5LmVsZW1lbnRzKCdub2RlOnNlbGVjdGVkJyk7XHJcbiAgICAgICAgICBzZWxlY3RlZC5mb3JFYWNoKGVsID0+IHtcclxuICAgICAgICAgICAgZWwuc2VsZWN0aWZ5KCk7XHJcbiAgICAgICAgICAgIGVsLnVuc2VsZWN0KCk7XHJcbiAgICAgICAgICAgIGVsLnVuc2VsZWN0aWZ5KCk7XHJcbiAgICAgICAgICAgIGVsLmRhdGEoXCJfX3NlbGVjdGVkXCIsIGZhbHNlKTtcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICBsZXQgaWQgPSB0YXJnZXREYXRhLmlkXHJcbiAgICAgICAgbGV0IGVsID0gdGhpcy5jeS4kaWQoaWQpO1xyXG4gICAgICAgIGxldCBzZWxlY3RlZCA9IGVsLnNlbGVjdGVkKCk7XHJcblxyXG4gICAgICAgIGVsLnNlbGVjdGlmeSgpO1xyXG4gICAgICAgIGlmIChzZWxlY3RlZClcclxuICAgICAgICAgIGVsLnVuc2VsZWN0KCk7XHJcbiAgICAgICAgZWxzZVxyXG4gICAgICAgICAgZWwuc2VsZWN0KCk7XHJcbiAgICAgICAgZWwudW5zZWxlY3RpZnkoKTtcclxuXHJcbiAgICAgICAgLy8gUXVlc3RvIHZhIGFuY2hlIG5lbGxhIGxpc3RhIGRlZ2xpIGVsZW1lbnRpIG9yaWdpbmFsaSAodGhpcy5FbGVtZW50cykgZGF0byBjaGUgY3l0b3NjYXBlIGxpIHByZW5kZSBwZXIgcmlmZXJpbWVudG8gKGJiYmJicmF2byBjeXRvLWNoYW4pXHJcbiAgICAgICAgZWwuZGF0YShcIl9fc2VsZWN0ZWRcIiwgIXNlbGVjdGVkKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy5vbk5vZGVDbGljay5lbWl0KHsgZGF0YTogdGFyZ2V0RGF0YSB9KTtcclxuICAgIH0pO1xyXG5cclxuICAgIHRoaXMuY3kuYmluZCgnc2VsZWN0JywgJ25vZGUnLCAoZXZlbnQpID0+IHtcclxuICAgICAgbGV0IHRhcmdldERhdGEgPSBldmVudC50YXJnZXQuZGF0YSgpXHJcblxyXG4gICAgICB0aGlzLm9uTm9kZVNlbGVjdGlvbi5lbWl0KHsgZGF0YTogdGFyZ2V0RGF0YSwgc2VsZWN0ZWQ6IHRydWUgfSk7XHJcbiAgICB9KTtcclxuXHJcbiAgICB0aGlzLmN5LmJpbmQoJ2xheW91dHN0b3AnLCAoZXZlbnQpID0+IHtcclxuICAgICAgdGhpcy5vbkxheW91dERvbmUuZW1pdCgpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgdGhpcy5jeS5iaW5kKCd1bnNlbGVjdCcsICdub2RlJywgKGV2ZW50KSA9PiB7XHJcbiAgICAgIGxldCB0YXJnZXREYXRhID0gZXZlbnQudGFyZ2V0LmRhdGEoKVxyXG5cclxuICAgICAgdGhpcy5vbk5vZGVTZWxlY3Rpb24uZW1pdCh7IGRhdGE6IHRhcmdldERhdGEsIHNlbGVjdGVkOiBmYWxzZSB9KTtcclxuICAgIH0pO1xyXG5cclxuICAgIC8vIEFsdHJpIGV2ZW50aS4uLlxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTWV0b2RvIGNoZSBzZXJ2ZSBwZXIgY2FyaWNhcmUgdHV0dGUgbGUgZXN0ZW5zaW9uaSBkZWxsYSBsaWJyZXJpYSBpbiBiYXNlIGEgY2nDsiBjaGUgdmllbmUgdXRpbGl6emF0b1xyXG4gICAqL1xyXG4gIHByaXZhdGUgYXN5bmMgcGVyZm9ybU1vZHVsZXNMb2FkaW5nKCkge1xyXG4gICAgaWYgKHRoaXMuTGF5b3V0Lm5hbWUgPT0gJ2RhZ3JlJylcclxuICAgICAgYXdhaXQgdGhpcy5sb2FkSW50ZXJuYWwoXCJjeXRvc2NhcGUtZGFncmVcIik7XHJcblxyXG4gICAgaWYgKHRoaXMuTm9kZUhUTUxUZW1wbGF0ZXMgJiYgdGhpcy5Ob2RlSFRNTFRlbXBsYXRlcy5sZW5ndGggPiAwKVxyXG4gICAgICBhd2FpdCB0aGlzLmxvYWRJbnRlcm5hbChcImN5dG9zY2FwZS1odG1sLW5vZGVcIik7XHJcblxyXG4gICAgaWYgKHRoaXMuVXNlQ29udGV4dE1lbnUpXHJcbiAgICAgIGF3YWl0IHRoaXMubG9hZEludGVybmFsKFwiY3l0b3NjYXBlLWN4dG1lbnVcIik7XHJcblxyXG4gICAgaWYgKHRoaXMuTm9kZXNIaWVyYXJjaHkgJiYgdGhpcy5Vc2VFeHBhbmRDb2xsYXBzZSlcclxuICAgICAgYXdhaXQgdGhpcy5sb2FkSW50ZXJuYWwoXCJjeXRvc2NhcGUtZXhwYW5kLWNvbGxhcHNlXCIpO1xyXG5cclxuICAgIGlmICh0aGlzLkV4dGVuc2lvbk1vZHVsZXNJbXBvcnRlcikge1xyXG4gICAgICAvLyBXcmFwcG8gaWwgbmFtZXNwYWNlIGluIG1vZG8gY2hlIHBvc3NhIGRpcmUgbGEgbWlhIHN1bCBmYXR0byBjaGUgbCd1dGVudGUgYWdnaXVuZ2EgdW4gbW9kdWxvIG8gbWVubyA6RFxyXG4gICAgICB2YXIgd3JhcHBlZEN5dG9zY2FwZSA9IHtcclxuICAgICAgICB1c2U6IChtb2R1bGVOYW1lOiBzdHJpbmcsIG1vZHVsZTogY3l0b3NjYXBlLkV4dCkgPT4ge1xyXG4gICAgICAgICAgaWYgKCFtb2R1bGUpXHJcbiAgICAgICAgICAgIHRoaXMuc2VydmljZS5sb2coXCJFXCIsIHRoaXMuc2VydmljZS5sb2MoXCJSZWNlaXZlZCBhbiB1bmRlZmluZWQgbW9kdWxlLiBNYWtlIHN1cmUgeW91IGFyZSBjb3JyZWN0bHkgbG9hZGluZyBpdFwiKSArIFwiOiBcIiArIG1vZHVsZU5hbWUsIGZhbHNlKTtcclxuXHJcbiAgICAgICAgICBpZiAoW1wiY3l0b3NjYXBlLWRhZ3JlXCIsIFwiY3l0b3NjYXBlLWh0bWwtbm9kZVwiLCBcImN5dG9zY2FwZS1jeHRtZW51XCIsIFwiY3l0b3NjYXBlLWV4cGFuZC1jb2xsYXBzZVwiXS5pbmNsdWRlcyhtb2R1bGVOYW1lKSlcclxuICAgICAgICAgICAgdGhpcy5zZXJ2aWNlLmxvZyhcIldcIiwgdGhpcy5zZXJ2aWNlLmxvYyhcIk1vZHVsZVwiKSArIFwiIFwiICsgbW9kdWxlTmFtZSArIFwiIFwiICsgdGhpcy5zZXJ2aWNlLmxvYyhcImlzIGxvYWRlZCBhbmQgbWFuYWdlZCBkaXJlY3RseSBieSB0aGlzIGxpYnJhcnkuIFlvdSBkb24ndCBuZWVkIHRvIGltcG9ydCBpdCBvciB1c2UgaXQgZGlyZWN0bHksIGp1c3QgYmUgc3VyZSB0byBzZXQgdGhlIHJlbGF0aXZlIG9wdGlvbnNcIiksIGZhbHNlKTtcclxuICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgY3l0b3NjYXBlLnVzZShtb2R1bGUpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgYXdhaXQgdGhpcy5FeHRlbnNpb25Nb2R1bGVzSW1wb3J0ZXIod3JhcHBlZEN5dG9zY2FwZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBNZXRvZG8gY2hlIHNlcnZlIHBlciBjYXJpY2FyZSB0dXR0ZSBsZSBlc3RlbnNpb25pIGRlbGxhIGxpYnJlcmlhIGluIGJhc2UgYSBjacOyIGNoZSB2aWVuZSB1dGlsaXp6YXRvIGNvbiBsZSBvcHppb25pIGRlZmluaXRlIGRhZ2xpIElucHV0XHJcbiAgICovXHJcbiAgcHJpdmF0ZSBwZXJmb3JtT3BlcmF0aW9uc1dpdGhMb2FkZWRNb2R1bGVzKCkge1xyXG5cclxuICAgIGxldCBhbnlDeSA9ICg8YW55PnRoaXMuY3kpO1xyXG5cclxuICAgIC8vIFV0aWxpenpvIGRlbCBsYXlvdXQsIGxvIHNhbHZvIHBlciBwb3RlcmxvIHJpdXRpbGl6emFyZSBpbiBmdXR1cm9cclxuICAgIGlmICh0aGlzLkxheW91dCkge1xyXG4gICAgICB0aGlzLkxhc3RMYXlvdXQgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KHRoaXMuTGF5b3V0KSk7XHJcbiAgICAgIHRoaXMuY3kubGF5b3V0KHRoaXMuTGFzdExheW91dCkucnVuKClcclxuICAgIH1cclxuXHJcbiAgICAvLyBVdGlsaXp6byBkZWxsJ0hUTUwgbm9kZVxyXG4gICAgaWYgKHRoaXMuTm9kZUhUTUxUZW1wbGF0ZXMgJiYgdGhpcy5Ob2RlSFRNTFRlbXBsYXRlcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgIHRoaXMuSHRtbE5vZGVBcGkgPSBhbnlDeS5odG1sbm9kZSgpO1xyXG4gICAgICB0aGlzLkh0bWxOb2RlQXBpLmNyZWF0ZUh0bWxOb2RlKGN5dG9zY2FwZSwgdGhpcy5jeSwgdGhpcy5Ob2RlSFRNTFRlbXBsYXRlcyk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gVXRpbGl6em8gZGVsIENvbnRleHQgTWVudVxyXG4gICAgaWYgKHRoaXMuVXNlQ29udGV4dE1lbnUpXHJcbiAgICAgIHRoaXMuQ29udGV4dE1lbnVPcHRpb25zLmZvckVhY2gobyA9PiB7IGFueUN5LmN4dG1lbnUobyk7IH0pO1xyXG5cclxuICAgIC8vIFV0aWxpenpvIGRlbGwnZXhwYW5kIGNvbGxhcHNlIHNvbG8gcXVhbmRvIGMnw6ggdW5hIGdlcmFyY2hpYSBkaSBub2RpXHJcbiAgICBpZiAodGhpcy5Ob2Rlc0hpZXJhcmNoeSAmJiB0aGlzLlVzZUV4cGFuZENvbGxhcHNlKVxyXG4gICAgICB0aGlzLkV4cGFuZENvbGxhcHNlQXBpID0gYW55Q3kuZXhwYW5kQ29sbGFwc2UodGhpcy5FeHBhbmRDb2xsYXBzZU9wdGlvbnMpO1xyXG5cclxuICAgIC8vIFV0aWxpenpvIGRpIGVzdGVuc2lvbmkgZXh0cmEsIGltcGxlbWVudGF6aW9uZSBhZmZpZGF0YSBhbCBwcm9ncmFtbWF0b3JlXHJcbiAgICBpZiAodGhpcy5FeHRlbnNpb25Nb2R1bGVzQXBwbHllcilcclxuICAgICAgdGhpcy5FeHRlbnNpb25Nb2R1bGVzQXBwbHllcih0aGlzLmN5KTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyB1cGRhdGVDYXJkRGF0YSgpIHtcclxuICAgIGlmICghdGhpcy5IdG1sTm9kZUFwaSkge1xyXG4gICAgICB0aGlzLnNlcnZpY2UubG9nKFwiRVwiLCBcIkNhbm5vdCB1cGRhdGUgTm9kZUhUTUxUZW1wbGF0ZXMgYXMgdGhleSBkb24ndCBzZWVtIHRvIGJlIHVzZWRcIik7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIHRoaXMuSHRtbE5vZGVBcGkudXBkYXRlKCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBNZXRvZG8gaW50ZXJubyBwZXIgaWwgY2FyaWNhbWVudG8gZGVpIG1vZHVsaSBkaSBlc3RlbnNpb25lXHJcbiAgICogXHJcbiAgICogQHBhcmFtIHsnY3l0b3NjYXBlLWV4cGFuZC1jb2xsYXBzZScgfCAnY3l0b3NjYXBlLWN4dG1lbnUnIHwgJ2N5dG9zY2FwZS1odG1sLW5vZGUnIHwgJ2N5dG9zY2FwZS1kYWdyZSd9IG1vZHVsZUlkIE1vZHVsbyBkYSBjYXJpY2FyZVxyXG4gICAqL1xyXG4gIHByaXZhdGUgYXN5bmMgbG9hZEludGVybmFsKG1vZHVsZUlkOiAnY3l0b3NjYXBlLWV4cGFuZC1jb2xsYXBzZScgfCAnY3l0b3NjYXBlLWN4dG1lbnUnIHwgJ2N5dG9zY2FwZS1odG1sLW5vZGUnIHwgJ2N5dG9zY2FwZS1kYWdyZScpIHtcclxuICAgIGxldCB0b0xvYWQgPSBhd2FpdCB0aGlzLnNlcnZpY2UuaW1wb3J0SWZOZWVkZWQobW9kdWxlSWQpO1xyXG4gICAgaWYgKHRvTG9hZCkgY3l0b3NjYXBlLnVzZSh0b0xvYWQpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTWV0b2RvIGNoZSBiYXNhbmRvc2kgc3VsbGUgb3B6aW9uaSBuYXRpdmUgZXZlbnR1YWxtZW50ZSBhc3NlZ25hdGUgbGUgY29tcGxldGEgY29uIGdsaSBJbnB1dCBhZGRpemlvbmFsaVxyXG4gICAqIFxyXG4gICAqIEByZXR1cm5zIHtjeV8uQ3l0b3NjYXBlT3B0aW9uc30gT3B6aW9uaSBmaW5hbGkgdW5pdGUgZGEgSW5wdXQgZWQgb3B6aW9uaSBuYXRpdmVcclxuICAgKi9cclxuICBwcml2YXRlIGdldENvbXBsZXRlZE9wdGlvbnMoKTogY3lfLkN5dG9zY2FwZU9wdGlvbnMge1xyXG4gICAgdmFyIG9wdHM6IGN5Xy5DeXRvc2NhcGVPcHRpb25zID0gdGhpcy5OYXRpdmVPcHRpb25zIHx8IHt9O1xyXG4gICAgb3B0cy5jb250YWluZXIgPSB0aGlzLmN5R3JhcGgubmF0aXZlRWxlbWVudDtcclxuICAgIG9wdHMuc3R5bGUgPSBvcHRzLnN0eWxlIHx8IFtdO1xyXG5cclxuICAgIC8vIFBlciB0dXR0ZSBsZSBjb3NlIHBlciBjdWkgZ2xpIElucHV0IGhhbm5vIHByaW9yaXTDoCBzb3ZyYXNjcml2byBnbGkgb3JpZ2luYWxpIGRlbGxlIG9wemlvbmlcclxuXHJcbiAgICBpZiAodGhpcy5Ob2RlU3R5bGVzIHx8IHRoaXMuRWRnZVN0eWxlcykge1xyXG4gICAgICBvcHRzLnN0eWxlID0gW107XHJcbiAgICAgIGlmICh0aGlzLk5vZGVTdHlsZXMpIG9wdHMuc3R5bGUucHVzaCh7IHNlbGVjdG9yOiAnbm9kZScsIGNzczogdGhpcy5Ob2RlU3R5bGVzIH0pO1xyXG4gICAgICBpZiAodGhpcy5FZGdlU3R5bGVzKSBvcHRzLnN0eWxlLnB1c2goeyBzZWxlY3RvcjogJ2VkZ2UnLCBjc3M6IHRoaXMuRWRnZVN0eWxlcyB9KTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5FbGVtZW50cylcclxuICAgICAgb3B0cy5lbGVtZW50cyA9IHRoaXMuRWxlbWVudHM7XHJcblxyXG4gICAgdGhpcy5yZXZpZXdDeXRvc2NhcGVFbGVtZW50cyg8Y3l0b3NjYXBlLkVsZW1lbnREZWZpbml0aW9uW10+b3B0cy5lbGVtZW50cyk7XHJcblxyXG4gICAgaWYgKHRoaXMuTGF5b3V0KVxyXG4gICAgICBvcHRzLmxheW91dCA9IHRoaXMuTGF5b3V0O1xyXG5cclxuICAgIGlmICh0aGlzLlJlYWRvbmx5KSB7XHJcbiAgICAgIC8vIFF1ZXN0byBjb3NvIGZhIGVmZmV0dGkgc3RyYW5pLi4uLlxyXG4gICAgICAvL29wdHMuYXV0b2xvY2sgPSB0cnVlO1xyXG5cclxuICAgICAgb3B0cy5hdXRvdW5ncmFiaWZ5ID0gdHJ1ZTtcclxuICAgICAgb3B0cy5hdXRvdW5zZWxlY3RpZnkgPSBmYWxzZTtcclxuICAgICAgb3B0cy5ib3hTZWxlY3Rpb25FbmFibGVkID0gdHJ1ZTtcclxuICAgICAgb3B0cy51c2VyWm9vbWluZ0VuYWJsZWQgPSBmYWxzZTtcclxuICAgICAgb3B0cy51c2VyUGFubmluZ0VuYWJsZWQgPSBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gb3B0cztcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEFnZ2l1c3RhbWVudGkgZGVnbGkgZWxlbWVudGkgZGkgQ3l0b3NjYXBlLiBcclxuICAgKiBcclxuICAgKiBJIG5vZGkgbm9uIHZlbmdvbm8gdG9jY2F0aS5cclxuICAgKiBcclxuICAgKiBQZXIgb2duaSBlZGdlIHZpZW5lIGNvbnRyb2xsYXRvIHNlIMOoIHNwZWNpZmljYXRhIHVuYSBzb3JnZW50ZSBlZCB1bmEgZGVzdGluYXppb25lLCBpbiBjYXNvIGNvbnRyYXJpbyBzaSBjZXJjYSBkaSBkZWR1cmxpIGRhbGwnSURcclxuICAgKiBcclxuICAgKiBAcGFyYW0ge2N5dG9zY2FwZS5FbGVtZW50RGVmaW5pdGlvbltdfSBlbGVtZW50cyBFbGVtZW50aSBkYSBzaXN0ZW1hcmVcclxuICAgKi9cclxuICBwcml2YXRlIHJldmlld0N5dG9zY2FwZUVsZW1lbnRzKGVsZW1lbnRzOiBjeXRvc2NhcGUuRWxlbWVudERlZmluaXRpb25bXSwgcHJldlBvc2l0aW9ucz86IGFueSkge1xyXG4gICAgbGV0IGhhc1ByZXZpb3VzUG9zaXRpb25zID0gcHJldlBvc2l0aW9ucyAmJiBwcmV2UG9zaXRpb25zLmxlbmd0aCA+IDA7XHJcbiAgICBsZXQgcG9zaXRpb25DYWNoZTogeyBbaW5kZXg6IHN0cmluZ106IGN5dG9zY2FwZS5Qb3NpdGlvbiB9ID0ge307XHJcblxyXG4gICAgaWYgKGhhc1ByZXZpb3VzUG9zaXRpb25zKSB7XHJcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcHJldlBvc2l0aW9ucy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIGxldCBpdGVtID0gcHJldlBvc2l0aW9uc1tpXTtcclxuICAgICAgICBpZiAoIXBvc2l0aW9uQ2FjaGVbaXRlbS5kYXRhKCkuaWRdKVxyXG4gICAgICAgICAgcG9zaXRpb25DYWNoZVtpdGVtLmRhdGEoKS5pZF0gPSBpdGVtLnBvc2l0aW9uKCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIGxldCBlbCA9IGVsZW1lbnRzW2ldO1xyXG4gICAgICBpZiAoZWwuZ3JvdXAgPT0gXCJlZGdlc1wiICYmICghZWwuZGF0YS5zb3VyY2UgJiYgIWVsLmRhdGEudGFyZ2V0KSkge1xyXG4gICAgICAgIGlmICghZWwuZGF0YS5pZC5pbmNsdWRlcyhcIi1cIikpXHJcbiAgICAgICAgICB0aGlzLnNlcnZpY2UubG9nKFwiRVwiLCBcIklmIHlvdSBkb24ndCBzcGVjaWZ5IGEgc291cmNlIGFuZCBhIHRhcmdldCBmb3IgYW4gZWRnZSB5b3UgaGF2ZSB0byB3cml0ZSBpdHMgaWQgaW4gdGhlIGZvcm1hdCB7c291cmNlfS17dGFyZ2V0fVwiKTtcclxuICAgICAgICBlbHNlIHtcclxuICAgICAgICAgIHZhciBzb3VyY2VUYXJnZXQgPSBlbC5kYXRhLmlkLnNwbGl0KCctJyk7XHJcbiAgICAgICAgICBlbC5kYXRhLnNvdXJjZSA9IHNvdXJjZVRhcmdldFswXS50cmltKCk7XHJcbiAgICAgICAgICBlbC5kYXRhLnRhcmdldCA9IHNvdXJjZVRhcmdldFsxXS50cmltKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAoaGFzUHJldmlvdXNQb3NpdGlvbnMgJiYgZWwuZ3JvdXAgPT0gXCJub2Rlc1wiKVxyXG4gICAgICAgIGVsLnBvc2l0aW9uID0gcG9zaXRpb25DYWNoZVtlbC5kYXRhLmlkXVxyXG4gICAgfVxyXG4gIH1cclxufSIsIjxkaXYgI2dyYXBoIGNsYXNzPVwiZ3JhcGgtd3JhcHBlciB7e25hbWV9fVwiPjwvZGl2PiJdfQ==
|