@esfaenza/es-table 11.2.22-beta2 → 11.2.22-beta23

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.
Files changed (67) hide show
  1. package/bundles/esfaenza-es-table.umd.js +3166 -3007
  2. package/bundles/esfaenza-es-table.umd.js.map +1 -1
  3. package/bundles/esfaenza-es-table.umd.min.js +1 -15
  4. package/bundles/esfaenza-es-table.umd.min.js.map +1 -1
  5. package/esfaenza-es-table.d.ts +6 -5
  6. package/esfaenza-es-table.metadata.json +1 -1
  7. package/esm2015/esfaenza-es-table.js +7 -6
  8. package/esm2015/lib/components/es-table/es_table.component.js +1300 -0
  9. package/esm2015/lib/components/es-table/es_table.component.loc.js +36 -0
  10. package/esm2015/lib/components/es-td/es_td.component.js +106 -0
  11. package/esm2015/lib/components/es-th/es_th.component.js +160 -0
  12. package/esm2015/lib/components/pager/table_pager.component.js +106 -0
  13. package/esm2015/lib/components/pager/table_pager.component.loc.js +22 -0
  14. package/esm2015/lib/core/handlers/classes/ColumnMetadataHandler.js +667 -0
  15. package/esm2015/lib/core/handlers/classes/DynamicModeHandler.js +64 -0
  16. package/esm2015/lib/core/handlers/classes/ExportHandler.js +43 -0
  17. package/esm2015/lib/core/handlers/classes/HierarchyModeHandler.js +136 -0
  18. package/esm2015/lib/core/handlers/classes/ItemsHandler.js +121 -0
  19. package/esm2015/lib/core/handlers/classes/ReportModeHandler.js +70 -0
  20. package/esm2015/lib/core/handlers/classes/RowGroupingHandler.js +475 -0
  21. package/esm2015/lib/core/handlers/classes/SelectionHandler.js +527 -0
  22. package/esm2015/lib/core/handlers/classes/UtilitiesHandler.js +169 -0
  23. package/esm2015/lib/core/handlers/index.js +10 -0
  24. package/esm2015/lib/domain/configuration/EsTableDefaultable.js +4 -0
  25. package/esm2015/lib/domain/configuration/EsTableModuleConfig.js +4 -0
  26. package/esm2015/lib/domain/internals/classes/EsTableColumn.js +1 -1
  27. package/esm2015/lib/domain/internals/classes/ThElement.js +2 -0
  28. package/esm2015/lib/domain/internals/index.js +2 -1
  29. package/esm2015/lib/es-table.module.js +6 -6
  30. package/esm2015/lib/tokens.js +1 -1
  31. package/esm2015/public-api.js +6 -6
  32. package/fesm2015/esfaenza-es-table.js +2836 -2700
  33. package/fesm2015/esfaenza-es-table.js.map +1 -1
  34. package/lib/components/es-table/es_table.component.d.ts +628 -0
  35. package/lib/{es_table.component.loc.d.ts → components/es-table/es_table.component.loc.d.ts} +0 -0
  36. package/lib/{es_td.component.d.ts → components/es-td/es_td.component.d.ts} +0 -0
  37. package/lib/{es_th.component.d.ts → components/es-th/es_th.component.d.ts} +6 -0
  38. package/lib/{pager → components/pager}/table_pager.component.d.ts +8 -1
  39. package/lib/{pager → components/pager}/table_pager.component.loc.d.ts +0 -0
  40. package/lib/core/handlers/classes/ColumnMetadataHandler.d.ts +159 -0
  41. package/lib/core/handlers/classes/DynamicModeHandler.d.ts +32 -0
  42. package/lib/core/handlers/classes/ExportHandler.d.ts +22 -0
  43. package/lib/core/handlers/classes/HierarchyModeHandler.d.ts +40 -0
  44. package/lib/core/handlers/classes/ItemsHandler.d.ts +41 -0
  45. package/lib/core/handlers/classes/ReportModeHandler.d.ts +21 -0
  46. package/lib/core/handlers/classes/RowGroupingHandler.d.ts +114 -0
  47. package/lib/core/handlers/classes/SelectionHandler.d.ts +149 -0
  48. package/lib/core/handlers/classes/UtilitiesHandler.d.ts +67 -0
  49. package/lib/core/handlers/index.d.ts +9 -0
  50. package/lib/{models → domain/configuration}/EsTableDefaultable.d.ts +0 -0
  51. package/lib/{models → domain/configuration}/EsTableModuleConfig.d.ts +0 -0
  52. package/lib/domain/internals/classes/EsTableColumn.d.ts +2 -0
  53. package/lib/domain/internals/classes/ThElement.d.ts +13 -0
  54. package/lib/domain/internals/index.d.ts +1 -0
  55. package/lib/es-table.module.d.ts +1 -1
  56. package/lib/tokens.d.ts +1 -1
  57. package/package.json +1 -1
  58. package/public-api.d.ts +5 -5
  59. package/esm2015/lib/es_table.component.js +0 -3453
  60. package/esm2015/lib/es_table.component.loc.js +0 -35
  61. package/esm2015/lib/es_td.component.js +0 -106
  62. package/esm2015/lib/es_th.component.js +0 -150
  63. package/esm2015/lib/models/EsTableDefaultable.js +0 -4
  64. package/esm2015/lib/models/EsTableModuleConfig.js +0 -4
  65. package/esm2015/lib/pager/table_pager.component.js +0 -92
  66. package/esm2015/lib/pager/table_pager.component.loc.js +0 -22
  67. package/lib/es_table.component.d.ts +0 -1192
@@ -1,3453 +0,0 @@
1
- import { __awaiter } from "tslib";
2
- // Angular
3
- import { Component, forwardRef, ContentChildren, ChangeDetectorRef, ChangeDetectionStrategy, Input, EventEmitter, Output, ContentChild, ViewChild, ViewEncapsulation, Optional, Self, Inject } from '@angular/core';
4
- import { NgControl } from '@angular/forms';
5
- // Configurazioni
6
- import { HashingService, UtilityService, ExportService, MessageService, DateService } from '@esfaenza/extensions';
7
- import { LocalizationService } from '@esfaenza/localizations';
8
- import { PreferencesService } from '@esfaenza/preferences';
9
- // Modelli
10
- import { AppSearch, AppOrdering, EsTableColumnsDefinition, ReportDefinition, ReportOrder, EsTableColumn, GroupAggregation, GroupPager, GroupRouteFragment, CacheTriptic } from './domain';
11
- // Componenti e Localizzazione
12
- import { EsTd } from './es_td.component';
13
- import { EsTh } from './es_th.component';
14
- import { EsTdDirective } from './directives/es_td.directive';
15
- import { EsThDirective } from './directives/es_th.directive';
16
- import { EsTableLoc } from './es_table.component.loc';
17
- import { ItemsSelection } from './domain/externals/classes/appsearch/ItemsSelection';
18
- import { GroupOrAggregation } from "./domain/externals/classes/appsearch/GroupOrAggregation";
19
- import { GroupFilter } from "./domain/externals/classes/appsearch/GroupFilter";
20
- import { Group } from "./domain/externals/classes/appsearch/Group";
21
- import { EsTableDefaultable } from './models/EsTableDefaultable';
22
- import { EST_DEFAULTS, EST_LOCALE } from './tokens';
23
- /** Componente che permette di rappresentare una griglia di valori */
24
- export class EsTableComponent {
25
- /** @ignore */
26
- constructor(ngControl, prefService, deafults, locale, lc, cdr, hashExts, utiExts, expExts, dateExts, msgExts) {
27
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
28
- this.ngControl = ngControl;
29
- this.prefService = prefService;
30
- this.deafults = deafults;
31
- this.locale = locale;
32
- this.lc = lc;
33
- this.cdr = cdr;
34
- this.hashExts = hashExts;
35
- this.utiExts = utiExts;
36
- this.expExts = expExts;
37
- this.dateExts = dateExts;
38
- this.msgExts = msgExts;
39
- /** View finale su cui bindarsi lato Frontend, il tipo può essere IAppSearch<any> (per la **viewMode**), any[] (per l'**arrayMode**) e ReportDefinition per la **reportMode** */
40
- this.View = null;
41
- /** Indica se l'es-table deve mostrare il check globale nell'header per fare il "seleziona tutto" */
42
- this.globalCheck = false;
43
- /** Tiene da conto l'ultimo elemento selezionato in modo da poter effettuare il SHIFT+CLICK */
44
- this.lastSelected = null;
45
- /** Conteggio interno per il numero di elementi selezionati */
46
- this.selectedObjects = 0;
47
- /** Indica se è possibile effettuare una selezione massiva */
48
- this.canSelectAll = false;
49
- /** Indica se il componente sta gestendo un IAppSearch<any> */
50
- this.viewMode = false;
51
- /** Indica se il componente sta gestendo un any[] */
52
- this.arrayMode = false;
53
- /** Indica se il componente sta gestendo un ReportDefinition */
54
- this.reportMode = false;
55
- /**
56
- * Contenitore degli elementi da listare lato interfaccia dopo tutte le elaborazioni del caso,
57
- * generalmente non sono altro che tutti gli oggetti da presentare con in più l'hash calcolato per identificare 1 oggetto con la propria riga
58
- */
59
- this.boundSource = [];
60
- /** Stessa cosa della **boundSource**, utilizzata come appoggio temporaneo interno */
61
- this.TMPBoundSource = [];
62
- /** "Fetta" di oggetti utilizzata nell'endless scroll, ogni elemento di questo array è un blocchetto di 100 elementi */
63
- this.boundSubSources = [];
64
- /** Questa funge da indicatore per gli slice inseriti, la lunghezza dovrebbe essere corrispondente a **boundSubSources** */
65
- this.addedSlices = [];
66
- /** Variabile che identifica il valore del "seleziona Tutto" nella paginazione */
67
- this.defaultAllPageOverride = 999999;
68
- /** Indica se utilizzare il sistema di autoupdate, cioè un trigger time-izzato in alto a destra della tabella che ripete le ricerche ogni X **seconds** */
69
- this.autoUpdate = false;
70
- /** Numero di secondi da fare trascorrere fra una ricerca e l'altra */
71
- this.seconds = '10';
72
- /** Impostata a true ogni volta che viene avviata una ricerca, e a false ogni volta che un nuovo valore viene ricevuto */
73
- this.researchInProgress = false;
74
- /** Modello rappresentante un singolo td della tabella, generato in base alle configurazioni e agli oggetti ricevuti */
75
- this.RowTDs = null;
76
- /** Modello di appoggio temporaneo per i **RowTDs** */
77
- this.TMPRowTDs = null;
78
- /** Modello rappresentante un singolo th della tabella, generato in base alle configurazioni e agli oggetti ricevuti */
79
- this.RowTHs = null;
80
- /** Modello di appoggio temporaneo per i **RowTHs** */
81
- this.TMPRowTHs = null;
82
- /** Modello di appoggio temporaneo per i **RowThGroups** */
83
- this.TMPRowThGroups = null;
84
- /** Modello rappresentante un singolo header group della tabella. Questa lista è già ordinata e pronta per essere utilizzata in ngFor */
85
- this.RowThGroups = null;
86
- /** Cache per i routerLink generati nelle tabelle dinamiche */
87
- this.DynamicTableRouterLinkCache = {};
88
- /**
89
- * Lista dei contesti. Un contesto non è altro che un hash particolare calcolato su un oggetto che identifica univocamente tale oggetto.
90
- *
91
- * Ognuno di questi contesti rappresenterà a sua volta, univocamente, una riga all'interno della tabella
92
- */
93
- this.RowContexts = [];
94
- /** Direttive di ordinamento delle colonne (non ordinamento dei dati ma delle colonne in se) */
95
- this.OrderDirectives = [];
96
- /** Codice dell'ultimo oggetto solezionato */
97
- this.lastSelectedItemID = null;
98
- /**
99
- * Indica se oltre alle colonne dinamiche specifiche di un tipo di oggetto ci sono anche colonne dinamiche aggiunte dall'utente
100
- *
101
- * Es. una colonna in cui mostrare sempre un iconcina
102
- */
103
- this.UserDefinedDynamicCols = false;
104
- /** Indica che questo è il primo Bind della tabella, viene settato a false non appena il primo bind viene terminato con successo */
105
- this.FirstBind = true;
106
- /** Lista di colonne che si possono visualizzare/ordinare fra di loro */
107
- this.ColumnsList = [];
108
- /** Variabile d'appoggio usata dalla dialog di selezione/nascondimento, per evitare di danneggiare **ColumnsList** in caso di modifiche poi annullate */
109
- this.TMPColumnsList = [];
110
- /** Valore del check globale di visibilità valido per tutte le colonne in **ColumnsList** */
111
- this.globalColVisCheck = false;
112
- /** Opzioni extra che devono apparire nel Menù contestuale in alto a destra, richiamato dai 3 pallini verticali */
113
- this.CornerMenuOptions = null;
114
- /** Indica se dev'essere possibile effettuare il resize delle colonne */
115
- this.ColumnsResizable = null;
116
- /** Indica se dev'essere disponibile il sistema di aggiornamento automatico */
117
- this.AutoUpdate = null;
118
- /** Indica se la tabella (configurata con **UseCustomCells**) deve mettersi in ascolto per i click sulle celle desiderate
119
- *
120
- * @deprecated Utilizzare l'Input **Template** delle es-td e assegnare un template con tutti i binding che si vuole ai click
121
- */
122
- this.UseCustomCellActions = null;
123
- /**
124
- * Indica le celle desiderate su cui intercettare i click. Attiva solo quando **UseCustomCellActions** è true.
125
- * Ogni cella dev'essere separata dalla successiva dal carattere del Simoleon:
126
- *
127
- * Es, "MiaCella1§MiaCella2"
128
- *
129
- * @deprecated Utilizzare l'Input **Template** delle es-td e assegnare un template con tutti i binding che si vuole ai click
130
- */
131
- this.CustomCellActionsOn = '';
132
- /**
133
- * Serve per decidere di lanciare o meno il **event.stopPropagation()** al termine della gestione dell'evento
134
- *
135
- * @deprecated Utilizzare l'Input **Template** delle es-td e assegnare un template con tutti i binding che si vuole ai click
136
- */
137
- this.CellActionPropagates = true;
138
- /**
139
- * Decide se utilizzare o meno le CustomCells. Impostandolo a **true** l'es-table diventa in grado di gestire nativamente:
140
- *
141
- * 1) Ordinamento e visibilità delle colonne
142
- *
143
- * 2) Ordinamento dei dati
144
- *
145
- * 3) Modalità Gerarchica
146
- *
147
- * ecc...
148
- */
149
- this.UseCustomCells = null;
150
- /** Permette di impostare l'altezza massima della tabella. Se null la dimensione si adatta al numero di elementi attualmente in visualizzazione */
151
- this.MaxHeight = null;
152
- /** Classi da applicare al contenitore della tabella */
153
- this.ContainerClass = null;
154
- /** Permette o meno l'export in formato XLSX */
155
- this.XLSXExport = null;
156
- /** Permette o meno l'export in formato CSV */
157
- this.CSVExport = true;
158
- /** Permette di visualizzare o meno l'opzione di paginazione "Tutti" */
159
- this.AllSearch = null;
160
- /** Diminuisce gli spazi fra una cella e l'altra, e internamente il padding del font in modo da presentare molti più dati in un'unica pagina */
161
- this.HighCellDensity = null;
162
- /** Abilita o meno la possibilità di selezionare oggetti */
163
- this.Selection = null;
164
- /** Mostra o meno un messaggio di Loading al primo caricamento della tabella */
165
- this.ShowLoadingOnBootstrap = null;
166
- /** Se impostato a **true** aggiunge una colonna con pulsante di eliminazione per effettuare l'elimina dell'oggetto relativo */
167
- this.Removal = null;
168
- /**
169
- * Condizione che nasconde l'icona di eliminazione inserita impostando **Removal** a true qualora la condizione non venisse rispettata
170
- *
171
- * Come condizione si considera un semplice campo su cui effettuare un controllo booleano, come ad esempio "canremove"
172
- */
173
- this.RemovalCondition = '';
174
- /** Indica se abilitare la possibilità di esportare la vista dati attuale */
175
- this.Export = null;
176
- /** Indica se permettere la selezione multipla Windows-like cliccando un oggetto e facendo poi Shift + click su un oggetto successivo */
177
- this.ShiftClick = null;
178
- /** Indica se nascondere o mostrare il componente di paginazione */
179
- this.HidePaging = null;
180
- /** Indica se nascondere o mostrare il conteggio degli elementi trovati */
181
- this.HidePagingCount = null;
182
- /** Indica se nascondere o mostrare i pulsanti di paginazione */
183
- this.HidePagingButtons = null;
184
- /** Riferimento al ContextMenu (ngx-contextmenu) associato al click destro di uno o più elementi selezionati nella tabella */
185
- this.ContextMenu = null;
186
- /** Nome dell'esportazione generata da questa tabella */
187
- this.ExportFileName = 'Export.csv';
188
- /** Classe (HTML) di default della tabella */
189
- this.TableClass = null;
190
- /** @deprecated Indica la presenza di raggruppamenti a livello di header */
191
- this.HasHeaderGroup = null;
192
- /** @deprecated Indica la presenza di raggruppamenti a livello del raggruppamento precedentemente esistente, chiaramente è insensata senza **HasHeaderGroup** */
193
- this.HasSecondaryHeaderGroup = null;
194
- /** Utilizzato per dividere la sorgente in modalità EndlessScroll */
195
- this.SliceSize = 100;
196
- /** Decide se utilizzare la modalità di EndlessScroll */
197
- this.EndlessScroll = null;
198
- /** Qualora **EndlessScroll** fosse true, indica se utilizzare questa modalità solo quando si cerca per "Tutti" o in generale */
199
- this.EndlessScrollOnlyForAll = true;
200
- /** Indica se nascondere gli Header della tabella */
201
- this.HeaderHidden = null;
202
- /** Indica se nascondere il Body della tabella */
203
- this.BodyHidden = null;
204
- /**
205
- * Indica se la selezione è temporaneamente disabilitata. Rispetto all'Input **Selection** che visivamente gestisce se ci sono o no gli input di selezione,
206
- * questo Input gestisce se questi input sono abilitati o meno
207
- */
208
- this.SelectionDisabled = null;
209
- /**
210
- * Indica se forzare il sistema di selezione a gestire un elemento per volta.
211
- * Selezionare un'altra riga con una già selezionata applicherà la selezione alla nuova riga, rimuovendola dall'attuale
212
- */
213
- this.SingleSelection = null;
214
- /** Callback che dato un oggetto resituisce l'eventuale classe da applicare alla riga collegata all'oggetto */
215
- this.RowClassAssigner = null;
216
- /** Permette di ordinare i dati in maniera discendente o ascendente */
217
- this.OrderByColumn = null;
218
- /** Permette di avere più direttive di ordinamento dei dati */
219
- this.MultipleOrderingDirectives = true;
220
- /** Permette di nascondere le colonne in base alle selezioni effettuate dal Menù contestuale in alto a destra */
221
- this.HiddenColumns = null;
222
- /** Permette di riordinare le colonne in base alle impostazioni effettuate dal Menù contestuale in alto a destra */
223
- this.ColumnsOrdering = null;
224
- /** Eventuale supporto alle ricerche applicate alla modalità Array */
225
- this.SearchView = null;
226
- /** Abilita o disabilita il sistema che permette di selezionare tutti gli elementi nella vista */
227
- this.SelectAll = null;
228
- /** Simula la paginazione anche per le tabelle che funzionano in modalità Array */
229
- this.UseArrayModePaging = true;
230
- /** Definizione di colonne dinamche per la modalità, appunto, dinamica */
231
- this.DynamicRowColumnsDefinition = null;
232
- /** Indica operazioni dinamiche generiche che possono essere effettuate per riga. Appaiono come colonne extra sul lato sinistro della tabella */
233
- this.DynamicOperations = [];
234
- /** Indica se visualizzare i dati in maniera gerarchica */
235
- this.Hierarchy = null;
236
- /** Nome della proprietà che contiene l'ID del padre. Da utilizzare se **Hierarchy** è impostato */
237
- this.ParentKey = '';
238
- /** Nome della proprietà che contiene l'ID dell'oggetto attuale. Da utilizzare se **Hierarchy** è impostato */
239
- this.OwnKey = '';
240
- /** Indica se partire con un albero espanso. Da utilizzare se **Hierarchy** è impostato */
241
- this.StartsExpanded = true;
242
- /** Indica se effettuare il salvataggio delle preferenze di ricerca */
243
- this.SavePreferences = null;
244
- /** Indica dove visualizzare le informazioni di paginazione, se sopra, sotto o in entrambi */
245
- this.PagingStyle = null;
246
- /** Indica dove visualizzare le informazioni di paginazione, se sopra, sotto o in entrambi */
247
- this.RowGroupingPagingStyle = null;
248
- /**
249
- * Sorgente dati secondaria
250
- *
251
- * @deprecated Utilizzato solo per un caso particolare del Metering
252
- */
253
- this.SecondarySource = null;
254
- /**
255
- * Sorgente dati secondaria
256
- *
257
- * @deprecated Utilizzato solo per un caso particolare del Metering
258
- */
259
- this.TertiarySource = null;
260
- /** Indica se utilizzare la cache di selezione che permette di mantenere gli stati di selezione dei vari oggetti navigando da una pagina all'altra */
261
- this.UseSelectionCache = null;
262
- /** Permette di decidere se, in modalità raggruppamento, mostrare o meno il valore delle colonne di gruppo negli oggetti finali. Di default sono nascosti */
263
- this.ShowItemGroupsColumns = null;
264
- /** Evento che viene richiamato al cambio di oridnamento di una colonna */
265
- this.onOrderChanged = new EventEmitter();
266
- /**
267
- * Evento che viene richiamato quando l'es-table ritiene sia necessario ri-effettuare la ricerca.
268
- * Il booleano dell'evento indica se viene suggerito di resettare la pagina o meno.
269
- *
270
- * Solo in caso venga utilizzata la modalità a raggruppamenti di righe può succedere che l'es-table passi un intero AppSearch come parametro di ricerca,
271
- * in quel caso l'applicazione ricevente dovrà onorare la richiesta spedendo al backand l'oggetto di ricerca AS-IS
272
- *
273
- * il tipo dell'Emitter invece di essere [boolean | AppSearch<any>] è stato impostato a "any" per evitare problemi di retrocompatibilità
274
- */
275
- this.onSearchRequest = new EventEmitter();
276
- /** Evento che parte ad ogni modifica di "checkaggio" in forma di comodo array. Espone l'oggetto con lo stato di check attuale */
277
- this.onSelectionChanged = new EventEmitter();
278
- /** Evento richiamato all'eliminazione di un oggetto */
279
- this.onRemoval = new EventEmitter();
280
- /** Evento richiamato all'annullamento di un'eliminazione */
281
- this.onAbortRemoval = new EventEmitter();
282
- /** Evento richiamato al click su una cella quando **UseCustomCellActions** è attivo
283
- *
284
- * @deprecated Utilizzare l'Input **Template** delle es-td e assegnare un template con tutti i binding che si vuole ai click
285
- */
286
- this.onCellClick = new EventEmitter();
287
- /** Evento richiamato quando si clicca su un opzione definita nelle **CornerMenuOptions** */
288
- this.onCornerAction = new EventEmitter();
289
- /** Evento richiamato quando si clicca su un opzione definita nelle **DynamicOperations** */
290
- this.onDynamicOperation = new EventEmitter();
291
- /** Pagina in visualizzazione (durante la paginazione in modalità Array) */
292
- this.arraymodePage = 1;
293
- /** Numero di pagine (durante la paginazione in modalità Array) */
294
- this.arraymodePages = 1;
295
- /** Oggetti per ogni pagina (durante la paginazione in modalità Array) */
296
- this.ArraymodeItemsPerPage = null;
297
- /** Colonne da visualizzare in modalità array */
298
- this.arrayColumns = [];
299
- /** Ordine delle colonne da visualizzare in modalità array */
300
- this.arrayColumnOrdering = [];
301
- /** Ordinamenti ASC-DESC sulle colonne in modalità array */
302
- this.arrayOrders = [];
303
- /**
304
- * Variabile che serve a gestire il momento in cui l'es-table aggiorna la paginazione (pulsanti ecc).
305
- * Essendo operazioni comunque costose le effettuo solo su binding esterni, non su rewrite generati internamente
306
- */
307
- this.internalWriteCall = false;
308
- /**
309
- * Cache che conterrà tutte le ricerche effettuate su gruppi diversi dal primo e su elementi contenuti nei gruppi.
310
- * In caso di cambi di ordinamento delle colonne diverse dalla prima tutte le chiamate fatte dal secondo livello in poi devono essere rieseguite secondo la seguente logica:
311
- *
312
- *
313
- * **Cambio ordinamento sul primo gruppo**: reload completo, non mi occupo di ripulire gli elementi bindati in alcun modo
314
- *
315
- * **Cambio ordinamento sulla colonna relativa all'N-esimo gruppo**: reload completo del contenuto dei gruppi precedenti, ripulendo precedentemente
316
- * tutti gli elementi con **_grouplevel** = N
317
- *
318
- * **Cambio ordinamento su una colonna non raggruppata**: reload completo per tutti i gruppi finali aperti, devo precedentemente ripulire tutti gli elementi con **_item** = true
319
- *
320
- * Altri eventi non dovrebbero rappresentare problemi:
321
- * - Selezione: non cambia nulla
322
- * - Paginazione: cambia a livello root quindi viene ricaricato tutto comunque, stesso vale per le paginazioni interne
323
- */
324
- this.groupSearchRequestsCache = [];
325
- /** Variabile d'appoggio per capire se c'è bisogno di ri-effettuare una ricerca o meno */
326
- this.ResearchNeeded = false;
327
- /** Colonne visibili della vista attuale. Valorizzato di default al numero massimo di colonne supportate dalla tabella per le casistiche in assenza di custom cells */
328
- this.Columns = { Visibile: 100, VisibleUnpinned: 100, Global: 100 };
329
- /** In caso di Row Grouping qui viene salvata la vista principale dei gruppi base */
330
- this.MainGroupView = null;
331
- /** Conteggio base degli oggetti. In modalità normale viene resettato ad ogni nuova View inserita, in modalità RowGrouping viene resettato solo ad una nuova View di livello "0" */
332
- this.BaseItemsCount = null;
333
- /** Cache per salvare per ogni chiave di ogni gruppo chi è il gruppo rappresentato */
334
- this.rgGroupCache = new Map();
335
- /** Cache per salvare per ogni chiave di ogni gruppo chi sono gli oggetti sottostanti, non dei sottogruppi */
336
- this.rgItemCache = new Map();
337
- /** Cache per salvare per ogni chiave di ogni gruppo chi sono gli oggetti sottostanti, non dei sottogruppi */
338
- this.rgChildGroupsCache = new Map();
339
- /** Cache di selezione Hash - Oggetto per la variabile **items** dell'itemSelector. Facilita le operazioni di lookup via hash*/
340
- this.itemsCache = new Map();
341
- /** Cache di selezione Hash - Oggetto per la variabile **groups** dell'itemSelector. Facilita le operazioni di lookup via hash */
342
- this.groupsCache = new Map();
343
- /** Cache di selezione Hash - Oggetto per la variabile **exclusions** dell'itemSelector. Facilita le operazioni di lookup via hash */
344
- this.exclusionsCache = new Map();
345
- /** Cache di selezione Hash - Oggetto per la variabile **group_exclusions** dell'itemSelector. Facilita le operazioni di lookup via hash */
346
- this.group_exclusionsCache = new Map();
347
- /** Cache di selezione Hash - Oggetto per la variabile **items** dell'itemSelector. Facilita le operazioni di lookup via indice*/
348
- this.i_itemsCache = new Map();
349
- /** Cache di selezione Hash - Oggetto per la variabile **groups** dell'itemSelector. Facilita le operazioni di lookup via indice */
350
- this.i_groupsCache = new Map();
351
- /** Cache di selezione Hash - Oggetto per la variabile **exclusions** dell'itemSelector. Facilita le operazioni di lookup via indice */
352
- this.i_exclusionsCache = new Map();
353
- /** Cache di selezione Hash - Oggetto per la variabile **group_exclusions** dell'itemSelector. Facilita le operazioni di lookup via indice */
354
- this.i_group_exclusionsCache = new Map();
355
- /** Indica se nonostante siamo in modalità array sono stati individuati dei gruppi. In tal caso es-table si comporta da pseudo backend ed effettua le aggregazioni e raggruppamenti completamente lato client */
356
- this.ArrayGrouping = false;
357
- this.PagerOptions = { PagerCount: null, ShowCount: true, ShowPaging: true, UsesView: true, View: null, Ready: false, Searches: 'items' };
358
- /** @ignore */
359
- this.propagateChange = (_) => { };
360
- if (ngControl)
361
- ngControl.valueAccessor = this;
362
- // Assegnazione per tutti gli Input di default
363
- this.ColumnsResizable = this.InputOrDefault(this.ColumnsResizable, (_a = this.deafults) === null || _a === void 0 ? void 0 : _a.ColumnsResizable);
364
- this.AutoUpdate = this.InputOrDefault(this.AutoUpdate, (_b = this.deafults) === null || _b === void 0 ? void 0 : _b.AutoUpdate);
365
- this.AllSearch = this.InputOrDefault(this.AllSearch, (_c = this.deafults) === null || _c === void 0 ? void 0 : _c.AllSearch, true);
366
- this.Export = this.InputOrDefault(this.Export, (_d = this.deafults) === null || _d === void 0 ? void 0 : _d.Export);
367
- this.HidePaging = this.InputOrDefault(this.HidePaging, (_e = this.deafults) === null || _e === void 0 ? void 0 : _e.HidePaging, false);
368
- this.HidePagingCount = this.InputOrDefault(this.HidePagingCount, (_f = this.deafults) === null || _f === void 0 ? void 0 : _f.HidePagingCount);
369
- this.HidePagingButtons = this.InputOrDefault(this.HidePagingButtons, (_g = this.deafults) === null || _g === void 0 ? void 0 : _g.HidePagingButtons);
370
- this.ContainerClass = this.InputOrDefault(this.ContainerClass, (_h = this.deafults) === null || _h === void 0 ? void 0 : _h.ContainerClass, '');
371
- this.TableClass = this.InputOrDefault(this.TableClass, (_j = this.deafults) === null || _j === void 0 ? void 0 : _j.TableClass, 'table table-striped table-hover table-sm');
372
- this.Selection = this.InputOrDefault(this.Selection, (_k = this.deafults) === null || _k === void 0 ? void 0 : _k.Selection);
373
- this.SavePreferences = this.InputOrDefault(this.SavePreferences, (_l = this.deafults) === null || _l === void 0 ? void 0 : _l.SavePreferences);
374
- this.PagingStyle = this.InputOrDefault(this.PagingStyle, (_m = this.deafults) === null || _m === void 0 ? void 0 : _m.PagingStyle, 'bottom');
375
- this.RowGroupingPagingStyle = this.InputOrDefault(this.RowGroupingPagingStyle, (_o = this.deafults) === null || _o === void 0 ? void 0 : _o.RowGroupingPagingStyle, 'left');
376
- this.UseSelectionCache = this.InputOrDefault(this.UseSelectionCache, (_p = this.deafults) === null || _p === void 0 ? void 0 : _p.UseSelectionCache, true);
377
- this.ShowItemGroupsColumns = this.InputOrDefault(this.ShowItemGroupsColumns, (_q = this.deafults) === null || _q === void 0 ? void 0 : _q.ShowItemGroupsColumns, false);
378
- this.ArraymodeItemsPerPage = this.InputOrDefault(this.ArraymodeItemsPerPage, (_r = this.deafults) === null || _r === void 0 ? void 0 : _r.ArraymodeItemsPerPage, 15);
379
- }
380
- // #region Ciclo di vita ES-Table - Inizializzazioni
381
- /** @ignore */
382
- ngOnInit() {
383
- //Per poter cambiare il layout in base al livello gerarchico il componente deva avere il pieno controllo di ogni cella,
384
- //che con solo la proiezione (senza celle cusotm) non è disponibile
385
- if (this.Hierarchy && !this.UseCustomCells)
386
- throw "Es-table error: Per poter utilizzare l'es-table con [Hierarchy]=\"true\" è richiesto anche [UseCustomCells]=\"true\"";
387
- // click destro su una riga con selezione attiva: Tiro fuori il context menu e selezione l'elemento corrente
388
- this.ctxMenuSubscription = (this.ContextMenu || this.tableEmptyMenu).open.subscribe(t => {
389
- // Gruppi va bene, oggetti pure, ma separatori fra gruppi proprio no...
390
- if (t.item._sep)
391
- return;
392
- let shouldEmit = !t.item._selected;
393
- t.item._selected = true;
394
- var itemSelection = this.handleItemsSelection([t.item]);
395
- this.changed();
396
- if (shouldEmit)
397
- this.onSelectionChanged.emit(itemSelection);
398
- });
399
- }
400
- /** @ignore */
401
- ngAfterViewInit() {
402
- // Se utilizzo la new spicy mode deduco tutti i parametri di lavoro possibili al caricamento della tabella
403
- // Vengono sovrascritte solo le proprietà non impostate dall'utente
404
- if (this.EsTdsDirective && this.EsTdsDirective.length > 0 && this.EsThsDirective && this.EsThsDirective.length > 0) {
405
- if (this.UseCustomCells == null)
406
- this.UseCustomCells = true;
407
- if (this.HiddenColumns == null && this.UseCustomCells)
408
- this.HiddenColumns = true;
409
- if (this.ColumnsOrdering == null && this.UseCustomCells)
410
- this.ColumnsOrdering = true;
411
- if (this.OrderByColumn == null && this.UseCustomCells)
412
- this.OrderByColumn = true;
413
- if (this.SelectAll == null && this.Selection)
414
- this.SelectAll = true;
415
- if (this.ShiftClick == null && this.Selection)
416
- this.ShiftClick = true;
417
- }
418
- }
419
- /**
420
- * Se l'Input è null (valore non settato) vede se c'è un default con cui valorizzarlo. Se non c'è utilizza il valore di fallback (qualora fornito)
421
- *
422
- * @param {T} inputValue Valore dell'Input
423
- * @param {T} defaultValue Valore di default impostato da configurazione
424
- * @param {T} fallbackValue Valore dell'Input per quando non è stato assegnato dal programmatore e non ha un default
425
- */
426
- InputOrDefault(inputValue, defaultValue, fallbackValue) {
427
- // Input valorizzato dal programmatore
428
- if (inputValue != null && inputValue != undefined)
429
- return inputValue;
430
- // Input valorizzato da configurazione globale
431
- if (defaultValue != null && defaultValue != undefined)
432
- return defaultValue;
433
- //Input non valorizzato da niente e da nessuno
434
- if (fallbackValue != null && fallbackValue != undefined)
435
- return fallbackValue;
436
- // I casi in cui si arriva qui sono i casi di Input che di default va bene che siano nulli e che nessuno si caga
437
- return null;
438
- }
439
- /** @ignore */
440
- ngOnDestroy() {
441
- if (this.ctxMenuSubscription)
442
- this.ctxMenuSubscription.unsubscribe();
443
- }
444
- /** @ignore */
445
- ngOnChanges(changes) {
446
- return __awaiter(this, void 0, void 0, function* () {
447
- let newSearchView = changes['SearchView'];
448
- if (newSearchView && this.SearchView)
449
- this.arrayPulsanti = this.getPagesArray(6, this.SearchView.page, this.SearchView.pages || 1);
450
- });
451
- }
452
- // #endregion
453
- // #region Implementazione ControlValueAccessor ignorabile
454
- /** @ignore */
455
- registerOnChange(fn) { this.propagateChange = fn; }
456
- /** @ignore */
457
- registerOnTouched(fn) { }
458
- /** @ignore */
459
- changed() { this.propagateChange(this.View); }
460
- // #endregion
461
- /** @ignore */
462
- writeValue(obj) {
463
- var _a;
464
- this.View = obj ? obj : null;
465
- // Mi è arrivata l'AppSearch quindi di sicuro non ho una ricerca in progress
466
- this.researchInProgress = false;
467
- if (!this.View && !this.SearchView) {
468
- // Su view nulla evito di fare pressoché qualsiasi cosa. Se arriva un null devo anche assicurarmi di non mostrare nulla
469
- this.boundSource = this.TMPBoundSource || [];
470
- // Per essere sicuro che dopo un bind di oggetti la es-table aggiorni la grafica
471
- this.cdr.markForCheck();
472
- return;
473
- }
474
- // Se per sbaglio l'oggetto che mi arriva non è tipizzato (instanceof AppSearch restituisce false anche se è del tipo giusto)
475
- // lo correggo--------------------------------------------------------------------------------------------------------------
476
- if (this.View && typeof this.View.result != 'undefined' && !(this.View instanceof ReportDefinition)) {
477
- this.View.__proto__ = new ReportDefinition();
478
- }
479
- else if (this.View && typeof this.View.itemsperpageoverride != 'undefined' && !(this.View instanceof AppSearch)) {
480
- this.View.__proto__ = new AppSearch();
481
- }
482
- else if (this.SearchView && typeof this.SearchView.itemsperpageoverride != 'undefined' && !(this.SearchView instanceof AppSearch)) {
483
- this.SearchView.__proto__ = new AppSearch();
484
- }
485
- // -------------------------------------------------------------------------------------------------------------------------
486
- if (this.View && this.View instanceof ReportDefinition) {
487
- // Se mi arriva una report definition vuol dire che potrei avere dei risultati da visualizzare
488
- this.setMode('report');
489
- this.ReportValues = this.View.result;
490
- if (this.ReportValues)
491
- this.reviewReportBindings();
492
- }
493
- else if (this.View && this.View instanceof AppSearch) {
494
- // Se cambia l'oggetto intero significa che ho rimandato la ricerca
495
- this.setMode('view');
496
- let firstItemGroupOrNoGrouping = (((_a = this.View.requestedgroups) === null || _a === void 0 ? void 0 : _a.length) || 0) == 0;
497
- // Se vengo da una ricerca interna mantengo lo stato di selezione precedente (quindi su cambio pagina, cambio ipp, ecc...)
498
- // se invece l'utente ha fatto una ricerca lui (quindi cambiando filtri), secco le info di selezione
499
- if (!this.View.selection || (!this.View.internalsearchrequest && firstItemGroupOrNoGrouping) || !this.UseSelectionCache) {
500
- this.clearSelectionCaches();
501
- this.View.selection = new ItemsSelection([]);
502
- this.onSelectionChanged.emit(this.View.selection);
503
- }
504
- this.View.internalsearchrequest = false;
505
- // Recupero Preference
506
- if (this.SavePreferences) {
507
- if (!this.ngControl.name)
508
- console.error("Non posso utilizzare le preference senza avere un 'name' per questa tabella");
509
- else if (!this.prefService)
510
- console.error("Non posso utilizzare le preference senza che il pacchetto @esfaenza/preferences sia installato");
511
- else {
512
- var prefs = this.prefService.retrieve(this.ngControl.name);
513
- if (prefs) {
514
- this.View.columns = prefs.columns;
515
- this.View.column_ordering = prefs.column_ordering;
516
- }
517
- }
518
- }
519
- // La paginazione devo farla solamente quando richiedo o un gruppo principale (se sono in row grouping) o se non richiedo gruppi (in tutti lgi altri casi)
520
- if (firstItemGroupOrNoGrouping)
521
- this.arrayPulsanti = this.getPagesArray(6, this.View.page, this.View.pages || 1);
522
- }
523
- else if (this.View && (this.View.length != null && this.View.length != undefined)) {
524
- this.setMode('array');
525
- if (!this.UseSelectionCache || !this.arraymodeSelection) {
526
- this.clearSelectionCaches();
527
- this.arraymodeSelection = new ItemsSelection([]);
528
- ;
529
- this.onSelectionChanged.emit(this.arraymodeSelection);
530
- }
531
- // Recupero Preference
532
- if (this.SavePreferences) {
533
- if (!this.ngControl.name)
534
- console.error("Non posso utilizzare le preference senza avere un 'name' per questa tabella");
535
- else if (!this.prefService)
536
- console.error("Non posso utilizzare le preference senza che il pacchetto @esfaenza/preferences sia installato");
537
- else {
538
- var prefs = this.prefService.retrieve(this.ngControl.name);
539
- if (prefs) {
540
- this.arrayColumns = prefs.columns;
541
- this.arrayColumnOrdering = prefs.column_ordering;
542
- }
543
- }
544
- }
545
- if (this.SearchView)
546
- this.arrayPulsanti = this.getPagesArray(6, this.SearchView.page, this.SearchView.pages || 1);
547
- }
548
- if (this.View && !(this.View instanceof ReportDefinition))
549
- this.finalizeContext();
550
- this.postBoundSourceCalculation();
551
- }
552
- /**
553
- * Successivamente al bind del nuovo input questa funzione si occupa di finalizzare tutti i parametri di funzionamento dell'es-table
554
- * in base a Input - Modello, e qualsiasi altra cosa possa servire
555
- */
556
- finalizeContext() {
557
- let viewCasted = this.View;
558
- /*
559
- *Uso la tecnica di EndlessScroll se la variabile relativa è attiva e se
560
- * 1) Ho un Array, oppure
561
- * 2) Ho un AppSearch che sta cercando con paginazione "Tutto", oppure
562
- * 3) Ho un AppSearch che sta cercando con paginazione diversa da "Tutto" ma con la variabile EndlessScrollOnlyForAll a false
563
- */
564
- let isAppSearchWithIppMax = this.viewMode && viewCasted.itemsperpageoverride == this.defaultAllPageOverride;
565
- let isAppSearchNoMaxIpp = this.viewMode && viewCasted.itemsperpageoverride != this.defaultAllPageOverride;
566
- this.UseEndlessscroll = this.EndlessScroll && (this.arrayMode || isAppSearchWithIppMax || (isAppSearchNoMaxIpp && !this.EndlessScrollOnlyForAll));
567
- let hasRowGroups = (viewCasted.groupings && viewCasted.groupings.filter(t => !t.aggregation).length > 0) || (this.arrayMode && this.EsThsDirective.some(t => t.thGroup));
568
- // Se ho dei gruppi in modalità array devo sistemare un po' di variabili che diventano insensate
569
- if (this.arrayMode) {
570
- if (hasRowGroups)
571
- this.UseArrayModePaging = false;
572
- }
573
- // Riempimento della TMPBoundSource con gli oggetti che verranno poi mostrati ad interfaccia
574
- if (this.UseEndlessscroll && !hasRowGroups) {
575
- this.addedSlices = [];
576
- this.boundSubSources = this.getItemSlices();
577
- let firstSub = this.boundSubSources[0];
578
- this.TMPBoundSource = firstSub ? firstSub : [];
579
- if (firstSub)
580
- this.addedSlices.push(0);
581
- }
582
- else
583
- this.TMPBoundSource = this.getItemsByMode(false, !this.internalWriteCall);
584
- // Se ho una gerarchia, assegno i livelli gerarchici alla TMPBoundSource
585
- if (this.Hierarchy && !hasRowGroups)
586
- this.assignHierarchyLevels(this.TMPBoundSource);
587
- // L'hashing degli oggetti lo faccio a prescindere
588
- this.calculateHash(this.TMPBoundSource);
589
- // Assegno a una variabile mia l'eventuale override per la classe della riga
590
- // Se poi sono in modalità gerarchica inietto anche la classe per la configurazione del livello della riga
591
- if ((this.TMPBoundSource && this.RowClassAssigner) || this.Hierarchy) {
592
- for (let i = 0; i < this.TMPBoundSource.length; i++) {
593
- let item = this.TMPBoundSource[i];
594
- item._rowClass = this.RowClassAssigner ? this.RowClassAssigner(item) : "";
595
- item._rowClass += this.Hierarchy ? " est-row-lvl-" + item._level : "";
596
- }
597
- }
598
- }
599
- /** Genera le informzioni di paginazione per la vista globale dell'es-table */
600
- setupPagingInformations() {
601
- this.PagerOptions.ShowCount = !this.HidePagingCount;
602
- if (this.arrayMode && this.UseArrayModePaging && !this.SearchView) {
603
- this.PagerOptions.PagerCount = this.View.length || 0;
604
- this.PagerOptions.ShowPaging = !this.HidePaging && this.View.length > 10;
605
- this.PagerOptions.View = this.View;
606
- this.PagerOptions.UsesView = false;
607
- }
608
- else if (this.arrayMode && (!this.UseArrayModePaging || this.SearchView)) {
609
- if (this.SearchView) {
610
- this.PagerOptions.View = this.SearchView;
611
- this.PagerOptions.PagerCount = this.SearchView.objectcount || 0;
612
- }
613
- else
614
- this.PagerOptions.PagerCount = this.View.length || 0;
615
- this.PagerOptions.ShowCount = this.PagerOptions.ShowCount || (this.View && this.View.length) || (this.SearchView && this.SearchView.objectcount && this.SearchView.objectcount != -1);
616
- }
617
- else if (this.viewMode) {
618
- let tmpView = this.MainGroupView || this.View;
619
- let count = (tmpView === null || tmpView === void 0 ? void 0 : tmpView.groupcount) || (tmpView === null || tmpView === void 0 ? void 0 : tmpView.objectcount);
620
- this.PagerOptions.Searches = (tmpView === null || tmpView === void 0 ? void 0 : tmpView.groupcount) != null && (tmpView === null || tmpView === void 0 ? void 0 : tmpView.groupcount) != undefined ? 'groups' : 'items';
621
- this.PagerOptions.PagerCount = count || 0;
622
- this.PagerOptions.View = tmpView;
623
- this.PagerOptions.ShowCount = this.PagerOptions.ShowCount || (tmpView && count && count != -1);
624
- this.PagerOptions.ShowPaging = !this.HidePaging;
625
- }
626
- else if (this.reportMode) {
627
- let rvc = this.ReportValues.count;
628
- this.PagerOptions.View = this.View;
629
- this.PagerOptions.PagerCount = rvc && rvc == -1 ? this.ReportValues.rows.length : rvc && rvc > 0 ? this.ReportValues.count : 0;
630
- this.PagerOptions.ShowCount = this.PagerOptions.ShowCount || (this.View && this.View.objectcount && this.View.objectcount != -1);
631
- this.PagerOptions.ShowPaging = !this.HidePaging && this.View.pagingavailable;
632
- }
633
- }
634
- /**
635
- * Ripulisce le cache di selezione
636
- *
637
- * @todo: SELECTION
638
- */
639
- clearSelectionCaches() {
640
- this.itemsCache.clear();
641
- this.groupsCache.clear();
642
- this.exclusionsCache.clear();
643
- this.group_exclusionsCache.clear();
644
- this.i_itemsCache.clear();
645
- this.i_groupsCache.clear();
646
- this.i_exclusionsCache.clear();
647
- this.i_group_exclusionsCache.clear();
648
- }
649
- /**
650
- * In base alla modalità specificata (ArrayMode, ViewMode, ecc...) questo metodo recupera l'array di oggetti da bindare ad interfaccia
651
- *
652
- * @param {boolean} onlyselected [false] Indica di prendere solo gli oggetti selezionati
653
- * @param {boolean} refreshPaging [false] Indica se aggiornare le informazioni di paginazione o meno
654
- * @param {boolean} allIfPossible [false] Indica se prendere tutti gli oggetti quaora possibile, usato solo in ArrayMode
655
- *
656
- * @returns {any[]} Lista degli oggetti su cui effettuare il bind lato interfaccia
657
- *
658
- * @todo: ITEMS
659
- */
660
- getItemsByMode(onlyselected = false, refreshPaging = false, allIfPossible = false) {
661
- let items = [];
662
- if ((this.viewMode && this.View instanceof AppSearch)) {
663
- items = this.getViewItemsBySource();
664
- }
665
- else if (this.arrayMode) {
666
- this.View.forEach(itm => { itm._item = true; });
667
- // Se faccio dei raggruppamenti ignoro la paginazione
668
- if (this.UseArrayModePaging && !allIfPossible) {
669
- // Se sono in modalità array ma la ricerca dipende da una view devo riallineare gli itemperpage
670
- if (this.SearchView)
671
- this.ArraymodeItemsPerPage = this.SearchView.itemsperpageoverride;
672
- // Devo chiamare il refresh page solo se vengo richiamato da un binding esterno
673
- if (refreshPaging)
674
- this.refreshPaging(this.ArraymodeItemsPerPage);
675
- items = this.adaptViewToPaging();
676
- }
677
- else {
678
- items = this.View;
679
- }
680
- }
681
- // Se voglio solo i selezionati filtro
682
- if (onlyselected)
683
- return items.filter(t => t._selected);
684
- return items;
685
- }
686
- /**
687
- * @ignore
688
- *
689
- * @todo: ITEMS
690
- */
691
- getViewItemsBySource() {
692
- var _a, _b;
693
- let castedView = this.View;
694
- let groupKeys = castedView.groupings ? castedView.groupings.filter(t => !t.aggregation).length : 0;
695
- //Gruppi intermedi
696
- if ((((_a = castedView.requestedgroups) === null || _a === void 0 ? void 0 : _a.length) != groupKeys || ((_b = castedView.requestedgroups) === null || _b === void 0 ? void 0 : _b.length) == 0) && groupKeys > 0) {
697
- let ret = castedView.groups;
698
- ret.forEach(itm => {
699
- // Setto variabile interna per capire che questo è in realtà un gruppo
700
- itm._group = true;
701
- // Le informazioni passate come lista le metto dentro a una cache per velocizzarne l'accesso quando devo tirare fuori il display della proprietà
702
- this.cacheAggregations(itm);
703
- });
704
- return ret;
705
- }
706
- else {
707
- let ret = this.SecondarySource ? this.View.items2 : this.TertiarySource ? this.View.items3 : this.View.items;
708
- // Setto variabile interna per specificare che questo è un elemento normale, non un gruppo o altro
709
- ret.forEach(itm => { itm._item = true; });
710
- return ret;
711
- }
712
- }
713
- /**
714
- * Helper per effettuare il caching delle aggregazioni. Le sposta da una lista di **GroupAggregation** a una **<Map<string, Map<string, string>>**
715
- *
716
- * @todo: ROWGROUPING
717
- */
718
- cacheAggregations(group) {
719
- group._aggregationsCache = new Map();
720
- let castedAgCache = group._aggregationsCache;
721
- for (let i = 0; i < group.aggregations.length; i++) {
722
- let agg = group.aggregations[i];
723
- if (castedAgCache.has(agg.column))
724
- castedAgCache.get(agg.column).set(agg.aggregation, agg.value);
725
- else {
726
- let tmp = new Map();
727
- tmp.set(agg.aggregation, agg.value);
728
- castedAgCache.set(agg.column, tmp);
729
- }
730
- }
731
- }
732
- /**
733
- * Metodo che prende tutti gli oggetti di cui dispone divisi in bucket da 100 elementi
734
- *
735
- * @returns {any[][]} Matrice di array Nx100
736
- *
737
- * @todo: ITEMS
738
- */
739
- getItemSlices() {
740
- // Se sono qui di sicuro non ho rowgrouping
741
- let items = this.getItemsByMode();
742
- if (!items)
743
- return [];
744
- let arrayBy100 = [];
745
- let slices = Math.ceil(items.length / this.SliceSize);
746
- for (let i = 0; i < slices; i++) {
747
- let arraySlice = items.slice(i * this.SliceSize, i * this.SliceSize + this.SliceSize);
748
- arrayBy100.push(arraySlice);
749
- }
750
- return arrayBy100;
751
- }
752
- /**
753
- * Metodo che gestisce l'endless scroll e in base a quanto la tabella è stata scrollata aggiunge degli elementi extra a **TMPBoundSource**
754
- *
755
- * @param {any} e Evento di scroll del browser
756
- */
757
- onScroll(e) {
758
- let tableViewHeight = e.target.offsetHeight;
759
- let tableScrollHeight = e.target.scrollHeight;
760
- let scrollLocation = e.target.scrollTop;
761
- let buffer = 200;
762
- let limit = tableScrollHeight - tableViewHeight - buffer;
763
- if (scrollLocation > limit) {
764
- let indexToAdd = Math.floor(this.TMPBoundSource.length / 100);
765
- if (this.boundSubSources[indexToAdd] && this.addedSlices.indexOf(indexToAdd) == -1) {
766
- // Devo ricordarmi di fare l'hash del nuovo pezzo
767
- this.calculateHash(this.boundSubSources[indexToAdd]);
768
- this.TMPBoundSource = this.TMPBoundSource.concat(this.boundSubSources[indexToAdd]);
769
- this.addedSlices.push(indexToAdd);
770
- setTimeout(() => { this.postBoundSourceCalculation(); });
771
- }
772
- }
773
- }
774
- /**
775
- * Metodo lanciato dopo che la sorgente dati è stata correttamente bindata, si occupa di ricalcolare tutto ciò che serve
776
- * all'es-table per renderizzare i valori da mostrare
777
- */
778
- postBoundSourceCalculation() {
779
- // Resetto tutto tranne RowTDs e RowTHs per evitare flickering. RowTDs e RowTHs saranno modificate all'interno del prossimo ciclo di CD
780
- this.RowContexts = [];
781
- this.OrderDirectives = [];
782
- this.lastSelectedItemID = null;
783
- if (this.EsThsDirective && this.EsThsDirective.length > 0 && this.EsTdsDirective && this.EsTdsDirective.length > 0)
784
- this.internalPostBoundSource();
785
- else {
786
- this.cdr.detectChanges();
787
- setTimeout(() => { this.internalPostBoundSource(); });
788
- }
789
- }
790
- /**
791
- * Per poter distinguere le chiamate a questo metodo: Dopo il setTimeout se uso gli EsTd/EsTh vecchi, senza il setTimeout se uso le nuove direttive
792
- */
793
- internalPostBoundSource() {
794
- let View = this.View;
795
- let ths = this.EsThs && this.EsThs.length > 0 ? this.EsThs.toArray() : this.EsThsDirective && this.EsThsDirective.length > 0 ? this.EsThsDirective.toArray() : [];
796
- let tds = this.EsTds && this.EsTds.length > 0 ? this.EsTds.toArray() : this.EsTdsDirective && this.EsTdsDirective.length > 0 ? this.EsTdsDirective.toArray() : [];
797
- // Se non ho colonne dinamiche ma sono in modalità dinamica (lo capisco perché c'è una view piena di genericitem) metto il default delle colonne
798
- this.eventuallyReviewDynamicColumns();
799
- this.bindDisplayToLoadedItemsOrGroups(View);
800
- // Questo dev'essere per forza lanciato dopo **bindDisplayToLoadedItemsOrGroups** dato che è lì che alcune cose vengono valorizzate
801
- this.setupPagingInformations();
802
- // Molte cose sono ovviamente disponibili solo in modalità View
803
- if ((this.viewMode || this.arrayMode) && this.UseCustomCells) {
804
- let view = this.viewMode ? View : null;
805
- let itemsAndGroups = this.viewMode ? [...(view.items || []), ...(view.groups || [])] : View;
806
- let si = this.viewMode ? view.selection : this.arraymodeSelection;
807
- // N.B: Rispettare l'ordine di queste 3 macrocategorie è VITALE
808
- // ************************************* Sistemazioni di TH, TD, e visibilità varie *************************************
809
- let hI = this.evaluateHeadersGroupingInfos(ths); // Prepassaggio per tirare fuori tutte le info utili sugli headers in modo da non ricacolarseli sempre dopo
810
- if (this.arrayMode) { // In modalità array non ho un backend...
811
- this.arrayModeReviewOrderings(); // ... quindi gli ordinamenti li devo fare lato client, e ...
812
- this.arrayModeReviewGroupings(hI.leafs); // ... i raggruppamenti li devo fare lato client
813
- }
814
- this.reviewColumnsList(hI.leafs); // Aggiorna la lista delle colonne da mostrare nella dialog per ordinamento ecc
815
- this.moveFixedColumnsAtTheBeginning(hI.leafs, tds); // Sposto tutte le cose fixed all'inizio in modo che la creazione di th e td sia più snella (Utilizza le ColumnsList, quindi dev'essere richiamata PIRMA di reviewColumnsList)
816
- this.alignHeadersOrdering(hI.leafs, view); // Allineo gli ordinamenti agli header
817
- this.alignColumnsIfLoadedView(view); // Se sto caricando una View da hotpotato (quindi con savedstate = true) riallineo la visibilità delle colonne e il loro ordine.
818
- this.refreshColumnsVisibility(hI.leafs, tds, view); // Lavoro sui TH ed eventualmente modifico la visibilità anche dei TD.
819
- this.evaluatePinnedColumnsWidth(); // Se sono presenti colonne pinnate valuta la dimensione del contenitore
820
- this.generateDefaultOrder(hI.leafs, view); // Genero le direttive di ordinamento, che siano default o derivanti dalla AppSearch
821
- this.evaluateHeaderGroups(hI); // Valuto i raggruppamenti degli header se presenti
822
- // ************************************* Generazione binding per righe e colonne *************************************
823
- this.evaluateRowThs(hI.leafs); // Raccolgo i TH
824
- this.evaluateRowTds(hI.leafs, tds); // Raccolgo i TD in contesti separati, un contesto per ogni item o gruppo
825
- // ************************************* Ultimi aggiustmaenti dei binding *************************************
826
- this.applyOrdering(view, true); // Applico l'ordinamento sulle colonne (non ASC DESC, ma "prima questa o quella colonna")
827
- this.MoveTemporaryVariablesToRealOnes(); // Collego TH e TD aggiustati fino ad ora alle variabili di Binding HTML
828
- this.evaluateSelection(itemsAndGroups, si); // Riallineo le info di selezione degli elementi della View
829
- if (this.ResearchNeeded) {
830
- this.changed();
831
- this.emitSearchRequest(false);
832
- this.ResearchNeeded = false;
833
- }
834
- }
835
- else if ((this.viewMode || this.arrayMode) && !this.UseCustomCells) {
836
- // Riallineo le info di selezione degli elementi della View
837
- let items = this.viewMode ? View.items : View;
838
- let si = this.viewMode ? View.selection : this.arraymodeSelection;
839
- this.evaluateSelection(items, si);
840
- }
841
- // Per essere sicuro che dopo un bind di oggetti la es-table aggiorni la grafica
842
- this.cdr.markForCheck();
843
- this.FirstBind = false;
844
- }
845
- /**
846
- * Se in modalità array applica gli ordinamenti ASC-DESC delle colonne
847
- *
848
- * @todo: INTERNALDB
849
- */
850
- arrayModeReviewOrderings() {
851
- if (this.arrayOrders.length > 0)
852
- this.arrayOrders.forEach(t => {
853
- this.boundSource = this.boundSource.sort((a, b) => (a[t.id] > b[t.id] ? 1 : -1) * (t.order == 'DESC' ? -1 : 1));
854
- });
855
- }
856
- /**
857
- * Se in modalità array applica i raggruppamenti definiti lato row-grouping
858
- *
859
- * @param {ths: EsTh[] | EsThDirective[]} ths Header
860
- *
861
- * @todo: ROW GROUPING
862
- */
863
- arrayModeReviewGroupings(ths) {
864
- if (ths.length == 0)
865
- return;
866
- if (this.isEsTh(ths[0]))
867
- return;
868
- let headerGroups = [];
869
- let headerAggregations = [];
870
- for (let i = 0; i < ths.length; i++) {
871
- let th = ths[i];
872
- if (th.thGroup)
873
- headerGroups.push(new Group(th.th, 0, ""));
874
- else if (th.thAggregation)
875
- headerAggregations = [...headerAggregations, ...this.getGroupAggregations(th)];
876
- }
877
- if (headerGroups.length > 0) {
878
- // Pulizia delle cache
879
- this.rgGroupCache.clear();
880
- this.rgItemCache.clear();
881
- this.rgChildGroupsCache.clear();
882
- this.ArrayGrouping = true;
883
- this.boundSource = this.getGroupsRecursive(headerGroups, 0, this.boundSource, headerAggregations, null);
884
- }
885
- }
886
- /**
887
- * Data la definizione dei gruppi da generare da una lista di oggetti, suddivide gli oggetti passati in gruppi e sottogruppi
888
- *
889
- * @param {Group[]} grps Definizione dei gruppi
890
- * @param {number} currentIndex Indice di elaborazione. Al livello 0 ho tutti gli oggetti e devo generare i primi gruppi, a livello 1 ho tutti i gruppi principali e devo
891
- * elaborare i sottogruppi, e così via ricorsivamente...
892
- * @param {any[]} items Oggetti da raggruppare
893
- * @param {GroupOrAggregation[]} aggregations Info di aggregazione
894
- * @param {any} parent Riferimento al gruppo padre
895
- *
896
- * @todo: INTERNALDB
897
- */
898
- getGroupsRecursive(grps, currentIndex, items, aggregations, parent) {
899
- // Se l'indice è 0 devo sicuramente nascondere tutti gli oggetti. Solo i gruppi saranno visualizzati
900
- if (currentIndex == 0)
901
- items.forEach(i => i._visible = false);
902
- let grp = grps[currentIndex];
903
- let ret = [];
904
- let last = grps.length == currentIndex + 1;
905
- let groups = this.groupBy(items, grp.column);
906
- for (let prop in groups) {
907
- let itms = groups[prop];
908
- let gp = new Group(grp.column, itms.length, prop);
909
- gp.aggregations = this.generateAggregations(itms, aggregations);
910
- let anygp = gp;
911
- anygp._group = true;
912
- anygp._expanded = false;
913
- if (!parent) {
914
- anygp._thisRoute = [{ column: gp.column, value: gp.value }];
915
- anygp._thisKey = gp.value;
916
- anygp._grouplevel = 0;
917
- }
918
- else {
919
- anygp._parent = parent._thisKey;
920
- anygp._parentRoute = parent._thisRoute;
921
- anygp._thisRoute = [...parent._thisRoute, { column: gp.column, value: gp.value }];
922
- anygp._thisKey = parent._thisKey + gp.value;
923
- anygp._grouplevel = parent._grouplevel + 1;
924
- }
925
- // Pusho il gruppo, tutti i gruppi del livello sotto, o gli item se io sono l'ultimo gruppo.
926
- // La visibilità è solo per il gruppo a livello 0, tutti gli altri gruppi saranno mostrati o nascosti di conseguenza
927
- if (currentIndex == 0)
928
- anygp._visible = true;
929
- this.calculateHash([anygp]);
930
- this.cacheAggregations(anygp);
931
- // Aggiungo il gruppo padre
932
- ret.push(anygp);
933
- this.rgGroupCache.set(anygp._thisKey, anygp);
934
- if (!last) {
935
- //Dal gruppo padre, se non è l'ultimo gruppo della catena, calcolo ricorsivamente tutta la catena sotto
936
- let subGroupsAndItems = this.getGroupsRecursive(grps, currentIndex + 1, itms, aggregations, anygp);
937
- let childgroups = subGroupsAndItems.filter(t => t._group && t._parent == anygp._thisKey);
938
- anygp._groupscount = childgroups.length;
939
- // Aggiungo la catena del gruppo sotto, aggiungendo alla cache solo i gruppi padre
940
- ret.push(...subGroupsAndItems);
941
- this.rgChildGroupsCache.set(anygp._thisKey, childgroups);
942
- }
943
- else {
944
- // Al gruppo padre, se è l'ultimo assegno tutte le foglie assegnandogli anche la chiave del gruppo
945
- itms.forEach(i => i._thisKey = anygp._thisKey);
946
- ret.push(...itms);
947
- this.rgItemCache.set(anygp._thisKey, itms);
948
- }
949
- }
950
- return ret;
951
- }
952
- /**
953
- * Data una lista di oggetti genera le aggregazioni specificate. Si considera di avere tutti gli oggetti
954
- *
955
- * @param {any[]} items Oggetti di cui calcolare le aggregazione
956
- * @param {GroupOrAggregation[]} aggregations Aggergazioni da generare
957
- *
958
- * @todo: INTERNALDB
959
- */
960
- generateAggregations(items, aggregations) {
961
- let rets = [];
962
- let aggregationValue = "", feField = null, stringAgg = null, dateAgg = null, numberAgg = null;
963
- for (let i = 0; i < aggregations.length; i++) {
964
- let agg = aggregations[i];
965
- feField = agg.column;
966
- if (!feField)
967
- continue;
968
- switch (agg.datatype) {
969
- case 'string':
970
- stringAgg = items.map(i => i[feField].toString());
971
- break;
972
- case 'date':
973
- dateAgg = items.map(i => new Date(i[feField]).getTime());
974
- break;
975
- case 'number':
976
- numberAgg = items.map(i => parseFloat(i[feField]));
977
- break;
978
- }
979
- switch (agg.aggregation) {
980
- case 'max':
981
- switch (agg.datatype) {
982
- case 'string':
983
- aggregationValue = stringAgg.sort().reverse()[0];
984
- break;
985
- case 'date':
986
- aggregationValue = new Date(Math.max(...dateAgg)).toString();
987
- break;
988
- case 'number':
989
- aggregationValue = Math.max(...numberAgg).toString();
990
- break;
991
- }
992
- break;
993
- case 'min':
994
- switch (agg.datatype) {
995
- case 'string':
996
- aggregationValue = stringAgg.sort()[0];
997
- break;
998
- case 'date':
999
- aggregationValue = new Date(Math.min(...dateAgg)).toString();
1000
- break;
1001
- case 'number':
1002
- aggregationValue = Math.min(...numberAgg).toString();
1003
- break;
1004
- }
1005
- break;
1006
- case 'sum':
1007
- switch (agg.datatype) {
1008
- case 'string':
1009
- aggregationValue = stringAgg.join(", ");
1010
- break;
1011
- case 'date':
1012
- aggregationValue = "";
1013
- break;
1014
- case 'number':
1015
- aggregationValue = numberAgg.reduce((pre, curr) => pre + curr, 0).toString();
1016
- break;
1017
- }
1018
- break;
1019
- }
1020
- rets.push(new GroupAggregation(agg.column, agg.aggregation, aggregationValue));
1021
- }
1022
- return rets;
1023
- }
1024
- /**
1025
- * Data una lista di oggetti effettua dei raggruppamenti in base alla proprietà **field**, restituendo un oggetto del tipo { Gruppo1: oggetti[], Gruppo2: oggetti[], ecc... }
1026
- *
1027
- * @param {any[]} array Lista degli oggetti da raggruppare
1028
- * @param {string} field Campo su cui effettuare i raggruppamenti
1029
- *
1030
- * @returns {{ [id: string]: any[] }} Dizionario dei gruppi
1031
- *
1032
- * @todo: INTERNALDB
1033
- */
1034
- groupBy(array, field) {
1035
- let ret = {};
1036
- for (let i = 0; i < array.length; i++) {
1037
- let x = array[i];
1038
- (ret[x[field]] = ret[x[field]] || []).push(x);
1039
- }
1040
- return ret;
1041
- }
1042
- ;
1043
- /**
1044
- * Effettua il binding degli oggetti pervenuti da questa chiamata con gli oggetti effettivamente da graficare
1045
- *
1046
- * @param {any} view View da cui sono arrivati gli oggetti. Può essere o un array se sono in **arrayMode** o una AppSearch<T> se sono in **viewMode**
1047
- */
1048
- bindDisplayToLoadedItemsOrGroups(view) {
1049
- var _a, _b;
1050
- if (this.TMPBoundSource.length == 0) {
1051
- this.BaseItemsCount = 0;
1052
- return;
1053
- }
1054
- if (this.arrayMode || !this.UseCustomCells) {
1055
- this.boundSource = this.TMPBoundSource;
1056
- this.BaseItemsCount = (view === null || view === void 0 ? void 0 : view.objectcount) || view.length;
1057
- return;
1058
- }
1059
- let groupingKeys = ((_b = (_a = view.groupings) === null || _a === void 0 ? void 0 : _a.filter(t => !t.aggregation)) === null || _b === void 0 ? void 0 : _b.length) || 0;
1060
- if (groupingKeys == 0) {
1061
- this.boundSource = this.TMPBoundSource;
1062
- this.BaseItemsCount = view.objectcount;
1063
- return;
1064
- }
1065
- this.handleNewDataOnRowGrouping(view, groupingKeys);
1066
- }
1067
- /**
1068
- * In modalità rowgrouping quando mi arriva un nuovo blocco di oggetti devo aggiungerlo alla vista attuale:
1069
- *
1070
- * 1) Se non viene richiesto il dettaglio di alcun gruppo significa che devo considerare mi siano arrivati tutti i gruppi principali
1071
- * 2) Se viene richiesto il dettaglio di un gruppo diverso dall'ultimo devo aggiungere dopo al gruppo cliccato la lista dei sottogruppi
1072
- * 2) Se viene richiesto il dettaglio dell'ultimo gruppo devo aggiungere dopo al gruppo cliccato la lista degli oggetti
1073
- *
1074
- * @param {any} view AppSearch<T> da cui sono arrivati gli oggetti
1075
- * @param {number} groupingKeys Livelli di raggruppamento da aspettarsi sui dati
1076
- *
1077
- * @todo: ROWGROUPING
1078
- */
1079
- handleNewDataOnRowGrouping(view, groupingKeys) {
1080
- var _a, _b;
1081
- // 1) Se non viene richiesto il dettaglio di alcun gruppo significa che la chiamata restituisce la lista paginata dei gruppi principali.
1082
- // Li tratto come se fosse una qualsiasi altra query paginata su N elementi
1083
- if ((((_a = view.requestedgroups) === null || _a === void 0 ? void 0 : _a.length) || 0) == 0) {
1084
- this.boundSource = this.TMPBoundSource;
1085
- this.rgGroupCache = new Map();
1086
- this.rgItemCache = new Map();
1087
- this.rgChildGroupsCache = new Map();
1088
- this.TMPBoundSource.forEach(itm => {
1089
- itm._thisRoute = itm._group ? [{ column: itm.column, value: itm.value }] : [];
1090
- itm._thisKey = itm._group ? itm.value : null;
1091
- itm._grouplevel = 0;
1092
- this.rgGroupCache.set(itm._thisKey, itm);
1093
- });
1094
- // Resetto la ricerca alla cache di questa "sessione"
1095
- let firstItem = this.TMPBoundSource[0];
1096
- this.MainGroupView = Object.assign({}, view);
1097
- this.groupSearchRequestsCache = [{ path: '', route: [{ column: firstItem.column, value: firstItem.value }], view: this.MainGroupView, group_column: this.TMPBoundSource[0].column }];
1098
- this.BaseItemsCount = view.objectcount;
1099
- }
1100
- else {
1101
- // 2) Se viene richiesto il dettaglio di un qualsiasi gruppo diverso dall'ultimo vuol dire che devo aggiungere
1102
- // dopo al gruppo che ho cliccato la lista dei gruppi tirata fuori questa volta (intermediateGroup = true)
1103
- /*
1104
- * GruppoA GruppoA
1105
- * GruppoB GruppoB
1106
- * GruppoC <- Clicco qui GruppoC
1107
- * GruppoD GruppoC1
1108
- * GruppoE GruppoC2
1109
- * GruppoD
1110
- * GruppoE
1111
- */
1112
- // 3) se i gruppi richiesti dalla view sono uguali ai gruppi presenti vuol dire che sto prendendo gli oggetti veri e propri, sono in
1113
- // view.items e quindi in TMPBoundSource, ho inoltre le informazioni di paginazione **per il singolo sottogruppo** (intermediateGroup = false)
1114
- /*
1115
- * GruppoA GruppoA
1116
- * GruppoC1 GruppoC1
1117
- * GruppoB GruppoB
1118
- * GruppoC GruppoC
1119
- * GruppoC1 <-- Clicco qui GruppoC1
1120
- * Oggetto1
1121
- * Oggetto2
1122
- * Oggetto3
1123
- * GruppoC2 GruppoC2
1124
- * GruppoD GruppoD
1125
- * GruppoE GruppoE
1126
- */
1127
- let intermediateGroup = view.requestedgroups.length != groupingKeys;
1128
- let items = this.boundSource;
1129
- let insertIndex = 0;
1130
- let groupKey = "";
1131
- let groupRoute = [];
1132
- // Navigo la stuttura dei gruppi ignorando ricorsivamente tutti gli indici fino ai gruppi che mi interessano in modo da non beccare il primo "GruppoC1" del caso sopra
1133
- for (let i = 0; i < view.requestedgroups.length; i++) {
1134
- let rg = view.requestedgroups[i];
1135
- groupKey += rg.value;
1136
- groupRoute.push({ column: rg.column, value: rg.value });
1137
- insertIndex = items.findIndex((t, i) => i >= insertIndex && t._group && t.column == rg.column && t.value == rg.value);
1138
- }
1139
- let itemsCacheReference;
1140
- let childGroupsCacheReference;
1141
- // Se non è un gruppo intermedio devo ripulire la cache del gruppo su cui ho attualmente cliccato. Gli oggetti saranno riaggiunti dopo
1142
- if (!intermediateGroup) {
1143
- this.rgItemCache.set(groupKey, []);
1144
- itemsCacheReference = this.rgItemCache.get(groupKey);
1145
- }
1146
- else {
1147
- // Se invece è un gruppo intermedio devo ripulire sia tutti i child group ricorsivamente, sia tutti gli item
1148
- for (let key of this.rgChildGroupsCache.keys())
1149
- if (key.startsWith(groupKey))
1150
- this.rgChildGroupsCache.delete(key);
1151
- for (let key of this.rgItemCache.keys())
1152
- if (key.startsWith(groupKey))
1153
- this.rgItemCache.delete(key);
1154
- this.rgChildGroupsCache.set(groupKey, []);
1155
- childGroupsCacheReference = this.rgChildGroupsCache.get(groupKey);
1156
- }
1157
- // Assegno un livello ai valori che arrivano da usare per formattare la parte grafica. Il primo gruppo cliccato sarà a livello 1,
1158
- // il secondo sarà a livello 2 e così via...
1159
- // Li marco inoltre con il parent in modo da poter eliminare i vecchi qualora servisse
1160
- this.TMPBoundSource.forEach(itm => {
1161
- itm._parent = groupKey;
1162
- itm._parentRoute = groupRoute;
1163
- itm._thisRoute = itm._group ? [...groupRoute, new GroupRouteFragment(itm.column, itm.value)] : [];
1164
- itm._thisKey = itm._group ? groupKey + itm.value : groupKey;
1165
- // Per le ricerca intermedie metto i gruppi nella cache dei gruppi
1166
- if (intermediateGroup) {
1167
- itm._grouplevel = view.requestedgroups.length;
1168
- this.rgGroupCache.set(itm._thisKey, itm);
1169
- childGroupsCacheReference.push(itm);
1170
- }
1171
- else {
1172
- // Metto anche gli oggetti nella cache non ricorsiva
1173
- itemsCacheReference.push(itm);
1174
- }
1175
- });
1176
- // Elimino gli oggetti vecchi
1177
- // 1) Ricerca intermedia, stato salvato - Elimino tutti gli item e tutti i gruppi la cui route è più lunga della corrente, tutti gli item relativi alla path corrente, e tutte
1178
- // le cache di ricerca effettuate su una path più profonda dell'attuale
1179
- // 2) Ricerca finale o ricerca intermedia senza stato salvato - Elimino tutti gli item relativi alla path corrente
1180
- // Per "stato salvato" si intendono ricerche vecchie salvate per poter essere rieffettuate in caso di ordinamenti su colonne di interesse
1181
- if (intermediateGroup && view.savedstate) {
1182
- this.boundSource = this.boundSource.filter(t => !(t._item || t._thisRoute.length > groupRoute.length));
1183
- this.groupSearchRequestsCache = this.groupSearchRequestsCache.filter(t => !(t.route.length > groupRoute.length));
1184
- }
1185
- this.boundSource = this.boundSource.filter(t => !(t._parent == groupKey));
1186
- let thisGroup = this.boundSource[insertIndex];
1187
- if (intermediateGroup)
1188
- thisGroup._groupscount = (_b = this.View) === null || _b === void 0 ? void 0 : _b.groupcount;
1189
- // Li sostituisco coi nuovi di questa ricerca
1190
- this.boundSource.splice(insertIndex + 1, 0, ...this.TMPBoundSource);
1191
- // Aggiungo un separatore alla fine o all'inizio di questi gruppi che dovrà occuparsi di caricare ALTRI gruppi o oggetti (se sono all'ultimo gruppo)
1192
- let addLast = false;
1193
- this.boundSource.splice(insertIndex + 1 + (addLast ? this.TMPBoundSource.length : 0), 0, this.getGroupSeparator(view, groupKey, groupRoute, view.requestedgroups.length, intermediateGroup ? 'groups' : 'items'));
1194
- // Aggiungo la ricerca alla cache di questa "sessione"
1195
- let toAdd = { path: groupKey, route: groupRoute, view: Object.assign({}, view), group_column: intermediateGroup ? this.TMPBoundSource[0].column : '' };
1196
- let prev = this.groupSearchRequestsCache.findIndex(t => t.path == toAdd.path && t.group_column == toAdd.group_column);
1197
- if (prev == -1)
1198
- this.groupSearchRequestsCache.push(toAdd);
1199
- else
1200
- this.groupSearchRequestsCache.splice(prev, 1, toAdd);
1201
- }
1202
- }
1203
- /**
1204
- * Metodo richiamato solo quando **TMPRowTDs** e **TMPRowTHs** sono completamente generati ed aggiustati. Serve per collegarli alle variabili usate lato binding HTML
1205
- */
1206
- MoveTemporaryVariablesToRealOnes() {
1207
- this.RowTDs = this.TMPRowTDs;
1208
- this.RowTHs = this.TMPRowTHs;
1209
- this.RowThGroups = this.TMPRowThGroups ? this.TMPRowThGroups.reverse() : null;
1210
- this.Columns.Visibile = this.RowTHs.filter(t => t.Visible).length;
1211
- this.Columns.VisibleUnpinned = this.RowTHs.filter(t => t.Visible && !t.Pinned).length;
1212
- this.Columns.Global = this.Columns.VisibleUnpinned + (this.HasPinnedColumns ? 1 : 0) + (this.Selection ? 1 : 0) + (this.Removal ? 1 : 0) + (this.Export || this.HiddenColumns || this.ColumnsOrdering || this.CornerMenuOptions ? 1 : 0);
1213
- }
1214
- /**
1215
- * Permette di selezionare o deselezionare in maniera arbitraria degli oggetti
1216
- *
1217
- * @param {any[]} items Oggetti da selezionare o deselezionare
1218
- * @param {boolean} select **true** per selezionarli, **false** per non toccarli
1219
- *
1220
- * @todo: SELECTION
1221
- */
1222
- setSelectionStatus(items, select) {
1223
- this.handleItemsSelection(items, select);
1224
- this.cdr.markForCheck();
1225
- }
1226
- /**
1227
- * Se non ho l'Input **DynamicRowColumnsDefinition** in modalità dinamica lo riempio con il default nome della colonna = testo della colonna
1228
- */
1229
- eventuallyReviewDynamicColumns() {
1230
- // Senza oggetti esco
1231
- if (!this.TMPBoundSource || this.TMPBoundSource.length == 0)
1232
- return;
1233
- var useGenericItems = !!this.TMPBoundSource[0]["properties"];
1234
- if (!useGenericItems || (!this.FirstBind && this.DynamicRowColumnsDefinition && this.DynamicRowColumnsDefinition.length > 0))
1235
- return;
1236
- if ((!this.DynamicRowColumnsDefinition || this.DynamicRowColumnsDefinition.length == 0)) {
1237
- var props = this.TMPBoundSource[0]["properties"];
1238
- this.DynamicRowColumnsDefinition = [];
1239
- for (let key in props)
1240
- this.DynamicRowColumnsDefinition.push(new EsTableColumnsDefinition(key, key));
1241
- this.UserDefinedDynamicCols = false;
1242
- }
1243
- else
1244
- this.UserDefinedDynamicCols = true;
1245
- }
1246
- /**
1247
- * Partendo dagli **EsThs** estrappolo la lista di **EsTableColumn** che questa tabella dovrà eventualmente gestire per Visibilità e Ordine
1248
- *
1249
- * Costo: 1 scan EsThs
1250
- *
1251
- * @param {EsTh[] | EsThDirective[]} ths Colonne della tabella
1252
- */
1253
- reviewColumnsList(ths) {
1254
- this.TMPColumnsList = [];
1255
- if (ths.length == 0)
1256
- return;
1257
- // Appena il contentChildren è valorizzato scorro tutti gli header
1258
- for (let i = 0; i < ths.length; i++) {
1259
- let th = ths[i];
1260
- if (this.isEsTh(th)) {
1261
- // Se non ho un id il th è considerato inerte
1262
- if (!th.ID)
1263
- continue;
1264
- th.OrderBy = this.OrderByColumn;
1265
- // Salvo le informazioni dell'header per far parte della lista da cui scegliere quali colonne visualizzare/nascondere
1266
- // Di default la visibilità è quella impostata nel componente
1267
- if (this.HiddenColumns || th.Visible)
1268
- this.TMPColumnsList.push(new EsTableColumn(th.ID, th.Description, th.Visible, th.Fixed, null, null, null));
1269
- }
1270
- else {
1271
- let column = th.th;
1272
- // Se non ho un id il th è considerato inerte
1273
- if (!column)
1274
- continue;
1275
- // Salvo le informazioni dell'header per far parte della lista da cui scegliere quali colonne visualizzare/nascondere
1276
- // Di default la visibilità è quella impostata nel componente
1277
- if (this.HiddenColumns || th.thVisible) {
1278
- let previouslyPinned = !this.ColumnsList || this.ColumnsList.length == 0 || !this.ColumnsList.find(t => t.id == column) ? null : this.ColumnsList.find(t => t.id == column).pinned;
1279
- this.TMPColumnsList.push(new EsTableColumn(column, null, th.thVisible, (th.thFixed || th.thGroup), previouslyPinned == null ? th.thPinned : previouslyPinned, th.thPinnedWidth, th.Template));
1280
- }
1281
- }
1282
- }
1283
- this.ColumnsList = [];
1284
- this.TMPColumnsList.forEach(c => { this.ColumnsList.push(Object.assign({}, c)); });
1285
- }
1286
- /**
1287
- * Prende i th e i td in modalità diretive e li ordina in base a se ci sono colonne fixed o meno
1288
- */
1289
- moveFixedColumnsAtTheBeginning(ths, tds) {
1290
- let thsCache = {};
1291
- let fixeds = 0, pinneds = 0;
1292
- let columnsCache = {};
1293
- let columnsIndexCache = {};
1294
- // Creo la cache delle colonne
1295
- for (let coli = 0; coli < this.ColumnsList.length; coli++) {
1296
- let col = this.ColumnsList[coli];
1297
- columnsCache[col.id] = col;
1298
- }
1299
- // Sposto tutti gli header fixed o pinned all'inizio
1300
- for (let i = 0; i < ths.length; i++) {
1301
- let th = ths[i];
1302
- if (this.isEsTh(th)) {
1303
- thsCache[th.ID] = th;
1304
- if (th.Fixed) {
1305
- if (i != pinneds + fixeds)
1306
- this.arrayMove(ths, i, pinneds + fixeds);
1307
- fixeds++;
1308
- }
1309
- }
1310
- else {
1311
- thsCache[th.th] = th;
1312
- // Riassegno sempre per ripulire valori di partenza o per aggiornarli in caso di modifiche utente
1313
- th.thPinned = (!columnsCache[th.th] && th.thPinned) || (columnsCache[th.th] && columnsCache[th.th].pinned);
1314
- if (th.thPinned) {
1315
- if (i != pinneds)
1316
- this.arrayMove(ths, i, pinneds);
1317
- pinneds++;
1318
- }
1319
- //In questo caso sono informazioni statiche invece, non modificabili dall'utente, quindi non mi dò preoccupazioni
1320
- if (th.thFixed || th.thGroup) {
1321
- if (i != pinneds + fixeds)
1322
- this.arrayMove(ths, i, pinneds + fixeds);
1323
- fixeds++;
1324
- }
1325
- }
1326
- }
1327
- if (this.isEsTh(ths[0]) || this.isEsTd(tds[0]))
1328
- return;
1329
- // Cache degli indici per riposizionare i td come i th
1330
- for (let i = 0; i < ths.length; i++)
1331
- columnsIndexCache[ths[i].th] = i;
1332
- // Riordino le celle per fargli mantenere la stessa struttura dei th
1333
- let newTds = new Array(ths.length);
1334
- for (let i = 0; i < tds.length; i++) {
1335
- let item = tds[i];
1336
- newTds[columnsIndexCache[item.td]] = item;
1337
- }
1338
- this.HasPinnedColumns = pinneds > 0;
1339
- }
1340
- /**
1341
- * In base alla configurazione delle colonne calcola le dimenioni delle colonne pinnate
1342
- */
1343
- evaluatePinnedColumnsWidth() {
1344
- if (!this.HasPinnedColumns)
1345
- return;
1346
- this.PinnedContainerWidth = 0;
1347
- for (let i = 0; i < this.ColumnsList.length; i++) {
1348
- let col = this.ColumnsList[i];
1349
- if (col.pinned && col.visible)
1350
- this.PinnedContainerWidth += col.pinnedWidth;
1351
- }
1352
- this.PinnedContainerWidth += this.Selection ? 25 : 0;
1353
- }
1354
- /**
1355
- * Helper per spostare un oggetto di un array da un indice all'altro, in place
1356
- */
1357
- arrayMove(array, oldI, newI) {
1358
- if (newI > array.length - 1 || oldI > array.length - 1 || newI < 0 || oldI < 0)
1359
- throw "Gli indici passati non fanno riferimento a una posizione dell'array. Length: " + array.length + " Old:" + oldI + " New: " + newI;
1360
- array.splice(newI, 0, array.splice(oldI, 1)[0]);
1361
- }
1362
- /**
1363
- * Terminato il binding delle colonne da **reviewColumnsList** e della **View** dal **writeValue** questo metodo si occupa
1364
- * dell'allineamento delle informazioni fra le colonne calcolate internamente e le informazioni sulle colonne che arrivano dall'AppSearch
1365
- *
1366
- * @param {AppSearch<any>} view AppSearch da utilizzare per questa operazione
1367
- */
1368
- alignColumnsIfLoadedView(view) {
1369
- let emitChanged = this.viewMode && view.savedstate;
1370
- let newColset = [];
1371
- if (!this.ColumnsList || this.ColumnsList.length == 0)
1372
- return;
1373
- let columns = this.viewMode ? view.columns : this.arrayColumns;
1374
- this.ColumnsList.forEach(c => {
1375
- // Se la colonna è pinnata mi arriva col simoleon
1376
- let exCl = columns.filter(cc => cc.replace('§', '') == c.id);
1377
- // Se la colonna è pinnata aggiorno l'informazione nella view
1378
- if (exCl.length == 1)
1379
- c.pinned = exCl[0].startsWith('§');
1380
- // Se l'appsearch viene da uno stato precedente, uso le informazioni sulle colonne che ha dentro, altrimenti sovrascrivo tutto **
1381
- if (c.visible && columns.length == 0)
1382
- newColset.push(c.id);
1383
- // Se ho una colonna lato AppSearch e nella ColumnList non è visibile, allineo all'AppSearch
1384
- else if (exCl.length == 1 && !c.visible)
1385
- c.visible = true;
1386
- // Allineamento sull'AppSearch per casistiche inverse al di sopra
1387
- else if (exCl.length == 0 && c.visible)
1388
- c.visible = false;
1389
- });
1390
- // Non ho colonne nella appsearch, vuol dire che sono al primo binding
1391
- if (columns.length == 0) {
1392
- if (this.viewMode)
1393
- view.columns = newColset;
1394
- else
1395
- this.arrayColumns = newColset;
1396
- }
1397
- if ((this.viewMode && view.savedstate) && this.ColumnsOrdering && view.column_ordering.length > 0) {
1398
- // Scorro gli ordinamenti che avevo salvato e ricreo la ColumnsList in base a loro
1399
- let newColList = [];
1400
- view.column_ordering.forEach(co => { this.ColumnsList.forEach(c => { if (c.id == co)
1401
- newColList.push(c); }); });
1402
- this.ColumnsList = newColList;
1403
- }
1404
- // In ogni caso questo non mi serve più, lo resetto **
1405
- if (this.viewMode)
1406
- view.savedstate = false;
1407
- if (emitChanged)
1408
- this.changed();
1409
- }
1410
- /**
1411
- * Metodo che gestisce il cambio di Ordinamento di una colonna
1412
- *
1413
- * @param {string} id ID della colonna il cui oridnamento è cambiato
1414
- * @param {'DESC' | 'ASC'} order Nuovo ordine selezionato per la colonna
1415
- */
1416
- thOrderChanged(id, order) {
1417
- if (!this.viewMode && !this.arrayMode) {
1418
- console.warn('Order changed on a table not in viewMode or Array mode. Operation not supported');
1419
- return;
1420
- }
1421
- if (!this.OrderByColumn)
1422
- return;
1423
- let orders = this.viewMode ? this.View.orders : this.arrayOrders;
1424
- let orderToAdd = true;
1425
- let orderToRemove = null;
1426
- // Se per qualche motivo il costruttore non è passato (cache tarpate o simila) fixo
1427
- if (!orders && this.viewMode)
1428
- this.View.orders = [];
1429
- else if (!orders && this.arrayMode)
1430
- this.arrayOrders = [];
1431
- for (let i = 0; i < orders.length; i++) {
1432
- let t = orders[i];
1433
- if (t.id == id) {
1434
- if (order) {
1435
- t.order = order;
1436
- orderToAdd = false;
1437
- }
1438
- else
1439
- orderToRemove = i;
1440
- }
1441
- }
1442
- if (orderToRemove != null) {
1443
- orders.splice(orderToRemove, 1);
1444
- }
1445
- else if (orderToAdd) {
1446
- if (this.MultipleOrderingDirectives)
1447
- orders.push(new AppOrdering(id, order));
1448
- else {
1449
- if (this.viewMode)
1450
- this.View.orders = [new AppOrdering(id, order)];
1451
- else if (this.arrayMode)
1452
- this.arrayOrders = [new AppOrdering(id, order)];
1453
- }
1454
- }
1455
- this.onOrderChanged.emit({ id, order });
1456
- if (this.viewMode) {
1457
- if (this.groupSearchRequestsCache.length > 0)
1458
- this.emitRowGroupingSearches(id, orders);
1459
- else
1460
- this.emitSearchRequest(false);
1461
- }
1462
- else if (this.arrayMode)
1463
- this.internalWriteValue();
1464
- }
1465
- /**
1466
- * Metodo da chiamare ogni volta che si vuole dare evidenza all'esterno del bisogno di rieffettuare la ricerca
1467
- *
1468
- * @param {boolean} resetsPage Indica al listener che deve resettare il numero di pagina
1469
- * @param {AppSearch<any>} viewOverride Override della view da emettere per questa ricerca
1470
- */
1471
- emitSearchRequest(resetsPage, viewOverride) {
1472
- if (this.viewMode && !viewOverride) {
1473
- this.View.internalsearchrequest = true;
1474
- this.changed();
1475
- }
1476
- if (viewOverride) {
1477
- if (resetsPage)
1478
- viewOverride.page = 1;
1479
- viewOverride.internalsearchrequest = true;
1480
- }
1481
- this.researchInProgress = true;
1482
- this.onSearchRequest.emit(viewOverride ? viewOverride : resetsPage);
1483
- }
1484
- /**
1485
- * In base alla visibilità registrata nelle **ColumnsList** questo metodo si occupa di prendere tutti i **EsThs** ed **EsTds** relativi e nasonderli/mostrarli
1486
- *
1487
- * Costo: 1 scan ColumnsList, 1 scan EsThs, 1 scan EsTds
1488
- *
1489
- * @param {EsTh[] | EsThDirective[]} ths Header della tabella
1490
- * @param {EsTd[] | EsTdDirective[]} tds Celle della tabella
1491
- * @param {AppSearch<any>} view AppSearch da utilizzare per questa operazione
1492
- */
1493
- refreshColumnsVisibility(ths, tds, view) {
1494
- let newColset = [];
1495
- let fixedThs = {};
1496
- let columnsCache = {};
1497
- for (let coli = 0; coli < this.ColumnsList.length; coli++) {
1498
- let col = this.ColumnsList[coli];
1499
- columnsCache[col.id] = col;
1500
- if (col.visible)
1501
- newColset.push((col.pinned ? "§" : "") + col.id);
1502
- }
1503
- if (view)
1504
- view.columns = newColset;
1505
- else
1506
- this.arrayColumns = newColset;
1507
- // Da qui in poi devono essere eseguiti SOLO in fase di writeValue quindi devo assicurarmi di passarli null in tutti i passaggi diversi da quello
1508
- if (ths) {
1509
- // Definisco se la colonna è visibile in base alla sua rappresentazione locale in ColumnsList
1510
- for (let i = 0; i < ths.length; i++) {
1511
- let th = ths[i];
1512
- if (this.isEsTh(th)) {
1513
- th.Visible = th.Fixed || (columnsCache[th.ID] ? columnsCache[th.ID].visible : th.Visible);
1514
- if (th.Fixed)
1515
- fixedThs[th.ID] = true;
1516
- }
1517
- else {
1518
- th.thVisible = th.thFixed || (columnsCache[th.th] ? columnsCache[th.th].visible : th.thVisible);
1519
- if (th.thFixed || th.thGroup)
1520
- fixedThs[th.th] = true;
1521
- }
1522
- }
1523
- }
1524
- if (tds) {
1525
- // Definisco se la cella è visibile in base alla sua rappresentazione locale in ColumnsList
1526
- for (let i = 0; i < tds.length; i++) {
1527
- let td = tds[i];
1528
- if (this.isEsTd(td))
1529
- td.Visible = fixedThs[td.ID] || (columnsCache[td.ID] ? columnsCache[td.ID].visible : td.Visible);
1530
- else
1531
- td.tdVisible = fixedThs[td.td] || (columnsCache[td.td] ? columnsCache[td.td].visible : td.tdVisible);
1532
- }
1533
- }
1534
- this.changed();
1535
- }
1536
- /**
1537
- * Allinea gli ordinamenti dati fra le **EsThs** e le informazioni all'interno della View bindata
1538
- *
1539
- * @param {AppSearch<any>} view AppSearch da utilizzare per questa operazione
1540
- * @param {EsTh[] | EsThDirective[]} ths Colonne della tabella
1541
- */
1542
- alignHeadersOrdering(ths, view) {
1543
- let orders = view ? view.orders : this.arrayOrders;
1544
- for (let i = 0; i < ths.length; i++) {
1545
- let th = ths[i];
1546
- if (this.isEsTh(th)) {
1547
- th.Order = null;
1548
- // Assegno tutti gli ordinamenti che mi vengono da AppSearch. Sono i più importanti. Non faccio cache o cose strano perché tanto questa
1549
- // variabile sarà sempre massimo 3 elementi
1550
- for (let i = 0; i < orders.length; i++) {
1551
- let or = orders[i];
1552
- if (or.id == th.ID)
1553
- th.Order = or.order;
1554
- }
1555
- }
1556
- else {
1557
- th.thOrder = null;
1558
- for (let i = 0; i < orders.length; i++) {
1559
- let or = orders[i];
1560
- if (or.id == th.th)
1561
- th.thOrder = or.order;
1562
- }
1563
- }
1564
- }
1565
- }
1566
- /**
1567
- * Partendo dagli **EsTds** bindati genera, all'interno del dizionario **TMPRowTDs** tutti i contesti dei vari oggetti.
1568
- *
1569
- * Vengono esclusi i TD "Interni" in quanto vengono generati dagli originali quindi includerli vorrebbe dire rieffettuare le operazioni due volte
1570
- *
1571
- * Costo: 2 scan EsThs, 1 scan EsTds
1572
- *
1573
- * @param {EsTh[] | EsThDirective[]} ths Colonne della tabella
1574
- * @param {EsTd[] | EsTdDirective[]} tds Celle della tabella
1575
- */
1576
- evaluateRowTds(ths, tds) {
1577
- if (tds.length == 0)
1578
- return;
1579
- let thsCache = {};
1580
- let columnsCache = {};
1581
- for (let coli = 0; coli < this.ColumnsList.length; coli++) {
1582
- let col = this.ColumnsList[coli];
1583
- columnsCache[col.id] = col;
1584
- }
1585
- for (let i = 0; i < ths.length; i++) {
1586
- let th = ths[i];
1587
- thsCache[this.isEsTh(th) ? th.ID : th.th] = th;
1588
- }
1589
- this.TMPRowTDs = {};
1590
- // Variabile d'appoggio per permettermi di inserire tutte le colonne "Fixed" davanti
1591
- let contextFixeds = {};
1592
- for (let i = 0; i < tds.length; i++) {
1593
- let td = tds[i];
1594
- if (this.isEsTd(td)) {
1595
- let th = thsCache[td.ID];
1596
- if (!!th)
1597
- th._referenced = true;
1598
- else
1599
- throw "ID dell'oggeto EsTd non compatibile con gli ID dicharati negli EsTh: " + td.ID;
1600
- let isFixed = (this.isEsTh(th) && th.Fixed) || (!this.isEsTh(th) && (th.thFixed || th.thGroup));
1601
- let itemToAdd = { GroupAggregation: false, GroupHeader: false, Wraps: true, ID: td.ID, Visible: td.Visible, Class: td.Class, Content: td.Content, RouterLink: td.RouterLink, Template: td.Template };
1602
- let ctx = td.Context;
1603
- if (this.TMPRowTDs[ctx]) {
1604
- if (isFixed)
1605
- this.TMPRowTDs[ctx].splice(0 + (contextFixeds[ctx]++), 0, itemToAdd);
1606
- else
1607
- this.TMPRowTDs[ctx].push(itemToAdd);
1608
- }
1609
- else {
1610
- this.RowContexts.push(ctx);
1611
- this.TMPRowTDs[ctx] = [itemToAdd];
1612
- contextFixeds[ctx] = isFixed ? 1 : 0;
1613
- }
1614
- }
1615
- else {
1616
- for (let i = 0; i < this.boundSource.length; i++) {
1617
- let item = this.boundSource[i];
1618
- let ctx = item._hash;
1619
- let key = td.td;
1620
- let th = thsCache[td.td];
1621
- if (!!th)
1622
- th._referenced = true;
1623
- else
1624
- throw "ID dell'oggeto EsTd non compatibile con gli ID dicharati negli EsTh: " + td.td;
1625
- if (td.tdIf || (!this.isEsTh(th) && th.thGroup)) {
1626
- let thCasted = th;
1627
- let isFixed = (this.isEsTh(th) && th.Fixed) || (!this.isEsTh(th) && (th.thFixed || th.thGroup || th.thPinned));
1628
- let itemToAdd = item._item ?
1629
- { LeftBorder: thCasted._lbord, RightBorder: thCasted._rbord, ID: key, Pinned: columnsCache[td.td].pinned, PinnedWidth: thCasted.thPinnedWidth, GroupHeader: false, GroupAggregation: false, Visible: columnsCache[td.td].visible, Wraps: false, Class: td.tdClass, Template: thCasted.thGroup && !this.ShowItemGroupsColumns ? null : td.Template } :
1630
- { LeftBorder: thCasted._lbord, RightBorder: thCasted._rbord, ID: key, Pinned: columnsCache[td.td].pinned, PinnedWidth: thCasted.thPinnedWidth, GroupHeader: thCasted.thGroup, GroupAggregation: !!thCasted.thAggregation, Visible: columnsCache[td.td].visible, Wraps: false, Class: thCasted.thGroupClass || '', Content: this.getGroupCellDisplay(item, key, th) };
1631
- if (this.TMPRowTDs[ctx]) {
1632
- // Non serve più grazie al metodo **oveFixedColumnsAtTheBeginning**
1633
- //if (isFixed)
1634
- // this.TMPRowTDs[ctx].splice(0 + (contextFixeds[ctx]++), 0, itemToAdd);
1635
- //else
1636
- this.TMPRowTDs[ctx].push(itemToAdd);
1637
- }
1638
- else {
1639
- this.RowContexts.push(ctx);
1640
- this.TMPRowTDs[ctx] = [itemToAdd];
1641
- contextFixeds[ctx] = isFixed ? 1 : 0;
1642
- }
1643
- }
1644
- }
1645
- }
1646
- }
1647
- // Se non ho oggetti è inutile che controllo gli errori, dato che gli es-td non esisteranno di certo e di conseguenza gli es-th non saranno referenziati
1648
- if (this.TMPBoundSource.length == 0)
1649
- return;
1650
- var errs = [];
1651
- for (let i = 0; i < ths.length; i++) {
1652
- let th = ths[i];
1653
- if (!th._referenced)
1654
- errs.push(this.isEsTh(th) ? th.ID : th.th);
1655
- }
1656
- if (errs.length > 0) {
1657
- var errIds = errs.join(', ');
1658
- throw "L'ID di uno o più EsTh non hanno alcun EsTd associato: " + errIds;
1659
- }
1660
- }
1661
- /**
1662
- * Partendo dagli **EsThs** bindati genera, all'interno del dizionario **TMPRowTHs** tutti i contesti dei vari oggetti.
1663
- *
1664
- * Vengono esclusi i TH "Interni" in quanto vengono generati dagli originali quindi includerli vorrebbe dire rieffettuare le operazioni due volte
1665
- *
1666
- * Costo: 1 scan EsThs
1667
- *
1668
- * @param {EsTh[] | EsThDirective[]} ths Colonne della tabella
1669
- */
1670
- evaluateRowThs(ths) {
1671
- if (ths.length == 0)
1672
- return;
1673
- let columnsListCache = {};
1674
- let castedView = this.View;
1675
- let groupingsUndefined = this.viewMode && (castedView && !castedView.groupings || castedView.groupings.length == 0);
1676
- for (let i = 0; i < this.ColumnsList.length; i++) {
1677
- let itm = this.ColumnsList[i];
1678
- columnsListCache[itm.id] = itm;
1679
- }
1680
- this.TMPRowTHs = [];
1681
- let fixed = 0;
1682
- for (let i = 0; i < ths.length; i++) {
1683
- let th = ths[i];
1684
- let toAdd;
1685
- if (this.isEsTh(th)) {
1686
- toAdd = { Pinned: false, ID: th.ID, Visible: th.Visible, Class: th.Class, Order: th.Order, Orderable: th.Orderable, Template: null, Content: th.Description, Wrap: false };
1687
- if (th.Fixed)
1688
- this.TMPRowTHs.splice(0 + (fixed++), 0, toAdd);
1689
- else
1690
- this.TMPRowTHs.push(toAdd);
1691
- }
1692
- else if (th.thIf || th.thGroup) {
1693
- let thClass = (th.thClass || '') + (th.thGroup ? " est-col-min" : "");
1694
- toAdd = { Pinned: columnsListCache[th.th].pinned, PinnedWidth: th.thPinnedWidth, ID: th.th, Visible: th.thVisible, Class: thClass, Order: th.thOrder, Orderable: th.thOrderable, Template: th.Template, Content: null, Wrap: false, LeftBorder: th._lbord, RightBorder: th._rbord };
1695
- this.TMPRowTHs.push(toAdd);
1696
- // Se ho un modello che deve funzionare a rowgrouping ma non è ancora stata effettuata nessuna ricerca sui gruppi principali (groupingsUndefined)
1697
- // li genero e mando la prima ricerca che dev'essere spedita al backend per il primo caricamento dei gruppi
1698
- if (groupingsUndefined && (th.thAggregation || th.thGroup)) {
1699
- let groupAggregations = this.getGroupAggregations(th);
1700
- if (!castedView.groupings)
1701
- castedView.groupings = groupAggregations;
1702
- else
1703
- castedView.groupings.push(...groupAggregations);
1704
- this.ResearchNeeded = true;
1705
- }
1706
- }
1707
- }
1708
- }
1709
- evaluateHeadersGroupingInfos(ths) {
1710
- // Pregiro per trovare i parent
1711
- let parentsCache = {};
1712
- let thsCache = {};
1713
- for (let i = 0; i < ths.length; i++) {
1714
- let th = ths[i];
1715
- if (this.isEsTh(th))
1716
- continue;
1717
- thsCache[th.th] = th;
1718
- if (th.thParent && !parentsCache[th.thParent])
1719
- parentsCache[th.thParent] = true;
1720
- }
1721
- // Secondo giro per beccare il livello massimo e la lista di foglie (th senza parent)
1722
- let hMaxLevel = 0;
1723
- let leafs = [];
1724
- for (let i = 0; i < ths.length; i++) {
1725
- let th = ths[i];
1726
- if (this.isEsTh(th)) {
1727
- leafs.push(th);
1728
- continue;
1729
- }
1730
- // Se sono una foglia vedo quanti livelli ci sono sopra
1731
- if (!parentsCache[th.th]) {
1732
- leafs.push(th);
1733
- let tmp = this.jumpsToFinalParent(th, thsCache);
1734
- hMaxLevel = tmp > hMaxLevel ? tmp : hMaxLevel;
1735
- }
1736
- }
1737
- return { leafs: leafs, groupingLevel: hMaxLevel, parentsCache: parentsCache, thsCache: thsCache };
1738
- }
1739
- /**
1740
- * Genera gli header groups da una lista di info sui th all'interno della variabile **TMPRowThGroups**
1741
- */
1742
- evaluateHeaderGroups(infos) {
1743
- if (infos.groupingLevel == 0)
1744
- return;
1745
- // Giro 2.5, creo l'output dei raggruppamenti per header in modo da non dovermi preoccupare di celle non inizializzate
1746
- let expandedGroups = [];
1747
- let visibleUnpinnedLeafs = infos.leafs.filter((t) => t.thVisible && !t.thPinned);
1748
- for (let l = 0; l < infos.groupingLevel; l++) {
1749
- expandedGroups.push([]);
1750
- for (let i = 0; i < visibleUnpinnedLeafs.length; i++)
1751
- expandedGroups[l].push("");
1752
- }
1753
- // Ordino le foglie in base agli ordinamenti delle colonne
1754
- let orderedLeafs = [];
1755
- for (let i = 0; i < this.OrderDirectives.length; i++) {
1756
- let leaf = infos.thsCache[this.OrderDirectives[i]];
1757
- if (leaf.thVisible && !leaf.thPinned)
1758
- orderedLeafs.push(leaf);
1759
- }
1760
- // Terzo giro per creare l'array group con tutti i riferimenti del caso
1761
- let currentParent = "";
1762
- for (let i = 0; i < orderedLeafs.length; i++) {
1763
- let refTh = orderedLeafs[i];
1764
- let prevTh = i - 1 >= 0 ? orderedLeafs[i - 1] : null;
1765
- // Parent diverso da prima, metto il bordo a sinistra e a destra della cella precedente (se c'è)
1766
- // All'ultimo giro metto il bordo a destra. Tutto questo lo rieseguo per ogni cella in modo da ripulire eventuali a cui avevo assegnato tag precedentemente
1767
- refTh._lbord = refTh.thParent != currentParent;
1768
- refTh._rbord = visibleUnpinnedLeafs.length == i + 1;
1769
- if (prevTh)
1770
- prevTh._rbord = refTh.thParent != currentParent;
1771
- currentParent = refTh.thParent;
1772
- // Per ogni gruppo srotolo il parent nella matrice dei raggruppamenti
1773
- for (let l = 0; l < infos.groupingLevel; l++) {
1774
- let parent = refTh.thParent;
1775
- if (parent && !refTh.thPinned) {
1776
- expandedGroups[l][i] = parent;
1777
- refTh = infos.thsCache[parent];
1778
- }
1779
- }
1780
- }
1781
- // Quarto giro per compattarlo nell'elemento finale su cui bindarmi
1782
- currentParent = "";
1783
- let currentSpan = 0;
1784
- this.TMPRowThGroups = [];
1785
- for (let l = 0; l < expandedGroups.length; l++) {
1786
- let levelArray = [];
1787
- this.TMPRowThGroups.push(levelArray);
1788
- if (this.Selection || this.HasPinnedColumns)
1789
- levelArray.push({ Span: 1, Template: null, Pinned: this.HasPinnedColumns });
1790
- for (let h = 0; h < expandedGroups[l].length; h++) {
1791
- let item = expandedGroups[l][h];
1792
- if (item == currentParent)
1793
- currentSpan++;
1794
- else {
1795
- if (currentSpan > 0)
1796
- levelArray.push({ Span: currentSpan, Template: (currentParent ? infos.thsCache[currentParent].Template : null), Borders: !!currentParent });
1797
- currentSpan = 1;
1798
- currentParent = item;
1799
- }
1800
- }
1801
- // Ultima aggiunta che altrimenti mi rimarrebbe in cache
1802
- levelArray.push({ Span: currentSpan, Template: (currentParent ? infos.thsCache[currentParent].Template : null), Borders: !!currentParent });
1803
- if (this.Removal)
1804
- levelArray.push({ Span: 1, Template: null });
1805
- if (this.Export || this.HiddenColumns || this.ColumnsOrdering || this.CornerMenuOptions)
1806
- levelArray.push({ Span: 1, Template: null });
1807
- currentSpan = 0;
1808
- currentParent = "";
1809
- }
1810
- }
1811
- /**
1812
- * Calcola il numero di salti da un header foglia all'ultimo parent della catena
1813
- */
1814
- jumpsToFinalParent(th, thsCache) {
1815
- let jumps = 0;
1816
- let parent = null;
1817
- do {
1818
- parent = th.thParent;
1819
- if (parent)
1820
- jumps++;
1821
- th = thsCache[parent];
1822
- } while (parent);
1823
- return jumps;
1824
- }
1825
- /**
1826
- * Data una direttiva EsTh restituisce la lista delle aggregazioni richiesta per questa colonna o il gruppo che rappresenta
1827
- *
1828
- * @param {EsThDirective} th Direttiva
1829
- *
1830
- * @returns {GroupOrAggregation[]} Lista dei gruppi o aggregazioni relativi alla Direttiva passata
1831
- */
1832
- getGroupAggregations(th) {
1833
- let ret = [];
1834
- // Es: '{min:dd/MM/yyyy} - {max:dd/MM/yyyy}'
1835
- if (th.thAggregation) {
1836
- this.getEsThDirectiveListOfAggregations(th).forEach((agg) => {
1837
- let isdate = agg.format && ['small', 'long', 'verylong'].includes(agg.format);
1838
- let isnumber = agg.format && agg.format.startsWith("F") && !Number.isNaN(agg.format.charAt(1)) && agg.format.length == 2;
1839
- if (!isdate && !isnumber && agg.format)
1840
- throw "Le aggergazioni supportate dall'es-table sono solo 'small', 'long', 'verylong' per le date e 'F0-9' per i numeri";
1841
- ret.push(new GroupOrAggregation(th.th, agg.func, isdate ? 'date' : isnumber ? 'number' : 'string'));
1842
- });
1843
- }
1844
- else if (th.thGroup)
1845
- ret.push(new GroupOrAggregation(th.th, null));
1846
- return ret;
1847
- }
1848
- /**
1849
- * Data una direttiva con un formato restituisce tutte le coppie Funzione di Aggregazione - Formato
1850
- *
1851
- * @param {EsThDirective} th Direttiva EsTh di cui calcolare le funzioni di aggregazione usate
1852
- *
1853
- * @returns {{ func: string, format: string }[]} Lista delle funzioni di aggregazione rilevate
1854
- */
1855
- getEsThDirectiveListOfAggregations(th) {
1856
- if (!th.thAggregation)
1857
- return [];
1858
- // Se ho già effettuato questo calcolo per questo th restituisco la versione in cache
1859
- if (th._thAggregations)
1860
- return th._thAggregations;
1861
- let ret = [];
1862
- let display = th.thAggregation;
1863
- var matches = display.match(/{[a-zA-Z0-9\/:]*}/gi);
1864
- if (!matches)
1865
- return [];
1866
- matches.forEach(m => {
1867
- let split = m.split(":");
1868
- let func = m, format = "";
1869
- if (split.length > 0) {
1870
- // Escludo primo e ultimo carattere (le graffe)
1871
- func = split[0].substr(1);
1872
- format = split[1].substr(0, split[1].length - 1);
1873
- }
1874
- ret.push({ func: func, format: format, match: m });
1875
- });
1876
- th._thAggregations = ret;
1877
- return ret;
1878
- }
1879
- /**
1880
- * Metodo che genera l'ordine di default delle colonne
1881
- *
1882
- * @param {AppSearch<any>} view AppSearch da utilizzare per questa operazione
1883
- */
1884
- generateDefaultOrder(ths, view) {
1885
- if (ths.length == 0)
1886
- return;
1887
- let orderings = this.viewMode ? view.column_ordering : this.arrayColumnOrdering;
1888
- // Genero ordinamento di default da 0 fino a dove deve arrivare. Situazione attuale senza hotpotato
1889
- if (!orderings || orderings.length == 0) {
1890
- for (let i = 0; i < ths.length; i++) {
1891
- let th = ths[i];
1892
- let order = this.isEsTh(th) ? th.ID : th.th;
1893
- this.OrderDirectives.push(order);
1894
- }
1895
- }
1896
- else
1897
- this.OrderDirectives = orderings;
1898
- }
1899
- /**
1900
- * Applica l'ordine specificato alle varie colonne
1901
- *
1902
- * @param {AppSearch<any>} view AppSearch da utilizzare per questa operazione
1903
- * @param {boolean} finalize Se **true** significa che non mi aspetto di dover effettuare altre operazioni e posso renderizzare la situazione in base ai RowContext
1904
- * Senza finalize significa che mi aspetto altre operazioni che prima o poi richiameranno questa funzione col finalize.
1905
- *
1906
- * Ad esempio, una volta selezionato ordinamento fisico/logico delle colonne so che parte un altra ricerca che mi rivalorizzerà da "writeValue", che già chiama questa funzione.
1907
- * Mettendo solo la chiamata da "writeValue" come "finalizzante" mi assicuro che smanattamenti a frontend non causino flickering fino a quando non servono
1908
- */
1909
- applyOrdering(view, finalize) {
1910
- // Genero ordinamento per gli header
1911
- let newHeaders = [];
1912
- // Se devo finalizzare aggancio tutte le variabili di bind
1913
- if (finalize) {
1914
- this.OrderDirectives.forEach(o => {
1915
- let heaedrItem = this.TMPRowTHs.filter(t => t.ID == o)[0];
1916
- newHeaders.push(heaedrItem);
1917
- });
1918
- this.TMPRowTHs = newHeaders;
1919
- // Genero ordinamento per le celle
1920
- for (let i = 0; i < this.RowContexts.length; i++) {
1921
- let context = this.TMPRowTDs[this.RowContexts[i]];
1922
- let newContext = [];
1923
- this.OrderDirectives.forEach(o => {
1924
- let contextItem = context.filter(t => t.ID == o)[0];
1925
- newContext.push(contextItem);
1926
- });
1927
- this.TMPRowTDs[this.RowContexts[i]] = newContext;
1928
- }
1929
- }
1930
- if (this.viewMode)
1931
- view.column_ordering = this.OrderDirectives;
1932
- else
1933
- this.arrayColumnOrdering = this.OrderDirectives;
1934
- this.changed();
1935
- }
1936
- // #endregion
1937
- // #region Gestione raggruppamenti per riga
1938
- /**
1939
- * Ottiene un elemento di separazione fra Gruppi che serve per paginare le ricerche all'interno di ogni singolo gruppo
1940
- *
1941
- * @param {AppSearch<any>} view View utilizzata per la ricerca. Me ne salvo i parametri nel separatore attuale dato che ne ho bisogno per caricare altri elementi
1942
- * facenti riferimento allo stesso contesto
1943
- * @param {string} parent Parent path che rappresenta a quale gruppo è affibbiato questo separatore
1944
- * @param {GroupRouteFragment[]} route Route path che rappresenta a quale gruppo è affibbiato questo separatore
1945
- * @param {number} level Livello del gruppo di cui questo elemento è separatore, viene usato per applicare la classe "est-lvl-{{level}}"
1946
- *
1947
- * @returns {any} Elemento di separazione contenente tutti i bind per presentare una paginazione sotto questo gruppo lato interfaccia
1948
- */
1949
- getGroupSeparator(view, parent, route, level, searches) {
1950
- let item = new GroupPager(level, route, parent, Object.assign({}, view), searches);
1951
- item.buttons = this.getPagesArray(6, view.page, view.pages);
1952
- this.calculateHash([item]);
1953
- return item;
1954
- }
1955
- /**
1956
- * Sposta la ricerca di una pagina in avanti (o indietro)
1957
- *
1958
- * @param {number} page Numero di pagine da aggiungere (o sottrarre, se negativo) alla pagina attuale
1959
- * @param {any} pager Elemento di separazione su cui è effettuata la ricerca
1960
- */
1961
- addToPageGroup(page, pager) {
1962
- this.goToPageGroup(pager.view.page + page, pager);
1963
- }
1964
- /**
1965
- * Sposta la ricerca alla pagina specificata
1966
- *
1967
- * @param {number} page Pagina a cui navigare
1968
- * @param {any} pager Elemento di separazione su cui è effettuata la ricerca
1969
- */
1970
- goToPageGroup(page, pager) {
1971
- let appSearchElement = pager.view;
1972
- if (page === 0 || page > appSearchElement.pages)
1973
- return;
1974
- appSearchElement.page = page;
1975
- pager.buttons = this.getPagesArray(6, appSearchElement.page, appSearchElement.pages);
1976
- this.emitSearchRequest(false, appSearchElement);
1977
- }
1978
- /**
1979
- * Data una colonna effettua la riemissione di tutte le ricerche relative.
1980
- *
1981
- * Es. Ho 2 campi di gruppo e ho espanso fino a vedere i valori fino ad un livello qualsiasi.
1982
- * Clicco l'ordinamento sul secondo gruppo.
1983
- * Tutte le ricerche relative ai primi gruppi devono essere rieseguite. Quando i risultati arriveranno ci penserà il metodo **bindDisplayToLoadedItemsOrGroups**
1984
- * a tagliare via gli oggetti non più visualizzati
1985
- *
1986
- * @param {string} column Colonna su cui si è effettuata un'operazione di ordinamento
1987
- * @param {AppOrdering[]} orderings Direttive di ordinamento da applicare alle varie sottoricerche
1988
- *
1989
- * @todo: Testare
1990
- */
1991
- emitRowGroupingSearches(column, orderings) {
1992
- // Per tutte le ricerche intermedie che devo rivalutare le re-emitto in modo da aggiornargli i dati
1993
- var meaningfulAppSearches = this.groupSearchRequestsCache.filter(t => t.group_column == column).map(t => t.view);
1994
- // Se non ne trovo significa che ho fatto l'ordinamento o sugli item, o su colonne relative a un sottogruppo non caricato
1995
- if (!meaningfulAppSearches || meaningfulAppSearches.length == 0)
1996
- meaningfulAppSearches = this.groupSearchRequestsCache.filter(t => !t.group_column).map(t => t.view);
1997
- // Se non ne trovo qui significa che sto ordinando su colonne relative a un sottogruppo non caricato
1998
- if (!meaningfulAppSearches || meaningfulAppSearches.length == 0)
1999
- return;
2000
- meaningfulAppSearches.forEach(as => {
2001
- // Ovviamente gli oridnamenti devono essere quelli appena generati
2002
- as.orders = orderings;
2003
- as.savedstate = true;
2004
- this.emitSearchRequest(false, as);
2005
- });
2006
- }
2007
- /**
2008
- * Helper che calcola il contenuto di una cella relativa a un gruppo riga, tenendo conto del formato delle eventuali aggregazioni
2009
- *
2010
- * @param {Group} grp Gruppo di cui mostrare le celle
2011
- * @param {string} cell Cella attuale di cui calcolare il testo
2012
- * @param {EsThDirective} header Header relativo alla cella attuale, utilizzata per identificare le informazioni di aggregazione
2013
- *
2014
- * @returns {string} Testo finale calcolato per la **cell** corrente, in base alle aggregazioni di **header**
2015
- */
2016
- getGroupCellDisplay(grp, cell, header) {
2017
- if (grp._sep)
2018
- return "";
2019
- let display = header.thAggregation;
2020
- if (grp.column == cell) {
2021
- let groupsPart = grp._groupscount ? " - " + grp._groupscount + " " + this.lc.loc("Groups") : "";
2022
- return grp.value + " (" + grp.count + groupsPart + ")";
2023
- }
2024
- else {
2025
- let agg = grp._aggregationsCache.get(cell);
2026
- if (!agg)
2027
- return "";
2028
- this.getEsThDirectiveListOfAggregations(header).forEach((itm) => {
2029
- display = display.replace(itm.match, this.formatAggregationValue(agg.get(itm.func), itm.format));
2030
- });
2031
- return display;
2032
- }
2033
- }
2034
- /**
2035
- * Gestisce i click sulla tabella solo per le righe a gruppo.
2036
- * O rimuove gli elementi attualmente presenti o carica il contenuto del gruppo
2037
- *
2038
- * @param {any} group Gruppo bindato su cui si è effettuato il click
2039
- *
2040
- * @returns {boolean} **true** se l'operaizone è andata a buon fine, **false** altrimenti
2041
- */
2042
- handleGroupClick(group) {
2043
- let casted = this.View;
2044
- let anyG = group;
2045
- anyG._expanded = !anyG._expanded;
2046
- // Sono in modalità raggruppamento virtuale da array: Espandere significa rendere visibili tutti gli oggetti relativi a questo gruppo, viceversa il contrarre
2047
- if (this.ArrayGrouping) {
2048
- let allRelatives = this.boundSource.filter(t => (t._group && ((anyG._expanded && t._parent == anyG._thisKey) || (!anyG._expanded && t._parent && t._parent.startsWith(anyG._thisKey)))) ||
2049
- (t._item && ((anyG._expanded && t._thisKey == anyG._thisKey) || (!anyG._expanded && t._thisKey.startsWith(anyG._thisKey)))));
2050
- allRelatives.forEach(t => { t._visible = anyG._expanded; if (t._group)
2051
- t._expanded = false; });
2052
- return;
2053
- }
2054
- if (anyG._expanded) {
2055
- // Resetto ipp
2056
- casted.itemsperpageoverride = 15;
2057
- if (!casted.requestedgroups)
2058
- casted.requestedgroups = [new GroupFilter(group.column, group.value)];
2059
- else {
2060
- let level = anyG._grouplevel;
2061
- // se il gruppo cliccato non ha un livello è il primo gruppo, quindi ordinamento unico
2062
- // altrimenti devo rimuovere tutti i filtri su livelli superiori al level cliccato e aggiungere il level cliccato
2063
- if (!level)
2064
- casted.requestedgroups = [new GroupFilter(group.column, group.value)];
2065
- else {
2066
- casted.requestedgroups = [];
2067
- anyG._parentRoute.forEach((step) => {
2068
- casted.requestedgroups.push(new GroupFilter(step.column, step.value));
2069
- });
2070
- casted.requestedgroups.push(new GroupFilter(group.column, group.value));
2071
- }
2072
- }
2073
- this.changed();
2074
- this.emitSearchRequest(true);
2075
- }
2076
- else {
2077
- let path = (anyG._parent || '') + group.value;
2078
- // Se ho chiuso un gruppo non mi serve rieffettuare ricerce, mi basta eliminare dagli oggetti bindati tutti gli elementi sottostanti a quel gruppo
2079
- this.boundSource = this.boundSource.filter(t => !t._parent || !t._parent.startsWith(path));
2080
- // devo però anche rimuovere eventuali cache relative
2081
- this.groupSearchRequestsCache = this.groupSearchRequestsCache.filter(t => t.path != path);
2082
- }
2083
- return true;
2084
- }
2085
- /**
2086
- * Funzione che dato un valore lo formatta in base al tipo
2087
- *
2088
- * @param {string} value Valore che generalemnte può essere una data o un numero
2089
- * @param {string} fromat Formato su cui formattare il valore. Può essere ad esempio "small", "long" "verylong" per le date o F{0-9} per i numeri decimali
2090
- *
2091
- * @returns {string} Valore dell'aggregazione formattato come si deve
2092
- */
2093
- formatAggregationValue(value, format) {
2094
- if (!format)
2095
- return value;
2096
- let isNumber = !Number.isNaN(value) && (!format || format.startsWith("F"));
2097
- if (isNumber && format.startsWith("F") && !Number.isNaN(format.substr(1)))
2098
- return parseFloat(value).toFixed(parseInt(format.substr(1)));
2099
- let date = null;
2100
- // Alcune versione di extensions rischiano di crashare con cose non date... è stato risolto dopo quindi questo try - catch in realtà
2101
- // torna utile solo con versioni vecchie/deprecate della libreria @esfaenza/extensions
2102
- try {
2103
- date = this.dateExts.getDateConvertion(value);
2104
- }
2105
- catch (_a) { }
2106
- if (date)
2107
- return this.dateExts.getFormatted(date, format == 'small', format == 'verylong');
2108
- // Qui ci finisco sia per input che non sono né date né numeri, sia per formati non riconosciuti
2109
- return value;
2110
- }
2111
- // #endregion
2112
- // #region Gestione Operaizoni dialog ordinamento/visibilità colonne
2113
- /**
2114
- * All'interno della dialog "Ordinamento e Visibilità Colonne" mette la colonna specificata prima della colonna precedente
2115
- *
2116
- * @param {EsTableColumn} columnItem Colonna da spostare
2117
- */
2118
- sendUp(columnItem) {
2119
- let itemIndex = this.TMPColumnsList.indexOf(columnItem);
2120
- if (this.TMPColumnsList[itemIndex - 1].fixed || this.TMPColumnsList[itemIndex - 1].pinned)
2121
- return;
2122
- this.utiExts.swap(this.TMPColumnsList, itemIndex, itemIndex - 1);
2123
- // Non posso fare JSON.parse(JSON.stringify(this.ColumnsList)) perché contiene riferimenti a TemplateRef
2124
- let tmp = [];
2125
- this.TMPColumnsList.forEach(c => { tmp.push(Object.assign({}, c)); });
2126
- this.TMPColumnsList = tmp;
2127
- }
2128
- /**
2129
- * All'interno della dialog "Ordinamento e Visibilità Colonne" mette la colonna specificata dopo la colonna successiva
2130
- *
2131
- * @param {EsTableColumn} columnItem Colonna da spostare
2132
- */
2133
- sendDown(columnItem) {
2134
- let itemIndex = this.TMPColumnsList.indexOf(columnItem);
2135
- this.utiExts.swap(this.TMPColumnsList, itemIndex, itemIndex + 1);
2136
- // Non posso fare JSON.parse(JSON.stringify(this.ColumnsList)) perché contiene riferimenti a TemplateRef
2137
- let tmp = [];
2138
- this.TMPColumnsList.forEach(c => { tmp.push(Object.assign({}, c)); });
2139
- this.TMPColumnsList = tmp;
2140
- }
2141
- /**
2142
- * All'interno della dialog "Ordinamento e Visibilità Colonne" pinna la colonna specificata
2143
- *
2144
- * @param {EsTableColumn} columnItem Colonna da spostare
2145
- */
2146
- pinOrUnpinColumn(columnItem) {
2147
- let itemIndex = this.TMPColumnsList.indexOf(columnItem);
2148
- // Sposto la colonna alla fine di tutte quelle pinnate. La cosa funziona in entrambi sensi:
2149
- // 1) Se sto pinnando, devo metterla come ultima pinnata
2150
- // 2) Se sto spinnando devo metterla come prima non pinnata
2151
- // Coincidenza vuole che il punto 1 e 2 siano equivalenti
2152
- for (let i = 0; i < this.TMPColumnsList.length; i++) {
2153
- if (!this.TMPColumnsList[i].pinned) {
2154
- this.arrayMove(this.TMPColumnsList, itemIndex, i);
2155
- break;
2156
- }
2157
- }
2158
- columnItem.pinned = !columnItem.pinned;
2159
- }
2160
- /**
2161
- * All'interno della dialog "Ordinamento e Visibilità Colonne" inverte le impostazioni di visibilità della colonna
2162
- *
2163
- * @param {EsTableColumn} columnItem Colonna da spostare
2164
- */
2165
- columnClicked(item) {
2166
- this.lastSelectedItemID = item.id;
2167
- if (!this.HiddenColumns || item.fixed)
2168
- return;
2169
- item.visible = !item.visible;
2170
- this.updateGlobalColVisCheck();
2171
- }
2172
- /**
2173
- * All'apertura della dialog "Ordinamento e Visibilità Colonne" ricarica le informazioni attuali per permettere la modifica
2174
- */
2175
- resetColumnVisSelection() {
2176
- this.TMPColumnsList = [];
2177
- // Non posso fare JSON.parse(JSON.stringify(this.ColumnsList)) perché contiene riferimenti a TemplateRef
2178
- this.TMPColumnsList = [];
2179
- this.ColumnsList.forEach(c => { this.TMPColumnsList.push(Object.assign({}, c)); });
2180
- let reorderedColList = [];
2181
- if (this.ColumnsOrdering) {
2182
- this.OrderDirectives.forEach(o => {
2183
- let column = this.TMPColumnsList.filter(t => t.id == o)[0];
2184
- // Potrei non averne nel caso ci sia il flag HiddenColumns a false, evito di inserire degli undefined
2185
- if (column)
2186
- reorderedColList.push(column);
2187
- });
2188
- this.TMPColumnsList = reorderedColList;
2189
- }
2190
- this.updateGlobalColVisCheck();
2191
- }
2192
- /**
2193
- * Riaggiorna le **OrderDirectives** con le informazioni in **ColumnsList**
2194
- */
2195
- refreshColumnOrdering() {
2196
- this.OrderDirectives = [];
2197
- for (let c = 0; c < this.ColumnsList.length; c++)
2198
- this.OrderDirectives.push(this.ColumnsList[c].id);
2199
- }
2200
- /**
2201
- * Effettua la selezione o meno del check globale (**globalColVisCheck**) di visibilità in base a se tutte le **TMPColumnsList** sono visibili o no
2202
- */
2203
- updateGlobalColVisCheck() {
2204
- // TMPColList viene riempita di undefined nel caso in cui sia disattivata la selezione delle colonne nascoste
2205
- this.globalColVisCheck = this.TMPColumnsList.every(t => t.visible);
2206
- }
2207
- /**
2208
- * Funzione che effettua la conferma della visibilità e dell'ordine delle colonne.
2209
- *
2210
- * Questa selezione viene inoltre salvata nelle preferenze (**@esfaenza/preferences**), qualora l'Input **SavePreferences** fosse valorizzato
2211
- *
2212
- * @returns {boolean} **true** se non ci sono problemi, **false** altrimenti
2213
- */
2214
- confirmColumnVisibilitySelection() {
2215
- // Non permetto di non selezionare nulla
2216
- if (this.TMPColumnsList.every(t => !t.visible))
2217
- return false;
2218
- let castedView = this.viewMode ? this.View : null;
2219
- this.ColumnsList = [];
2220
- this.TMPColumnsList.forEach(c => { this.ColumnsList.push(Object.assign({}, c)); });
2221
- this.refreshColumnOrdering();
2222
- this.applyOrdering(castedView, false);
2223
- this.refreshColumnsVisibility(null, null, castedView);
2224
- //Salvo le preferences di questa view
2225
- //Di default registro ordinamento e visibilità delle colonne nella vista. Solo le cose di UI
2226
- if (this.SavePreferences) {
2227
- if (!this.ngControl.name) {
2228
- console.error("Non posso utilizzare le preference senza avere un 'name' per la tabella");
2229
- return false;
2230
- }
2231
- if (!this.prefService) {
2232
- console.error("Non posso utilizzare le preference senza che il pacchetto @esfaenza/preferences sia installato");
2233
- return false;
2234
- }
2235
- let columns = this.arrayMode ? this.arrayColumns : castedView.columns;
2236
- let columnsOrderings = this.arrayMode ? this.arrayColumnOrdering : castedView.column_ordering;
2237
- var toStore = { columns: JSON.parse(JSON.stringify(columns)), column_ordering: JSON.parse(JSON.stringify(columnsOrderings)) };
2238
- this.prefService.store(this.ngControl.name, toStore);
2239
- }
2240
- // Rieseguo l'ultima ricerca bindata alla tabella
2241
- // Mi assicuro di farlo dopo l'espansione del changed o rischio che la ricerca mi ridia colonne che in realtà non esistono
2242
- if (this.viewMode)
2243
- setTimeout(() => { this.emitSearchRequest(false); });
2244
- else if (this.arrayMode)
2245
- setTimeout(() => { this.internalWriteValue(); });
2246
- // Lo vorrei mettere lato template ma no
2247
- this.lastSelectedItemID = null;
2248
- return true;
2249
- }
2250
- /**
2251
- * Sul click nella checkbox di selezione globale si scorrono tutte le colonne e si impostano al valore della check globale
2252
- */
2253
- globalColVisCheckChanged() {
2254
- this.TMPColumnsList.forEach(t => { if (!t.fixed)
2255
- t.visible = this.globalColVisCheck; });
2256
- }
2257
- // #endregion
2258
- // #region Gestione data source gerarchici
2259
- /**
2260
- * Data una lista di oggetti assegno il livello gerarchico rispetto alla lista di oggetti passata
2261
- *
2262
- * @param {any[]} objs Lista di oggetti a cui aggiungere l'informazione del livello gerarchico
2263
- */
2264
- assignHierarchyLevels(objs) {
2265
- // Casistica input nullo
2266
- if (!objs || !objs.length)
2267
- return;
2268
- //Se mancano entrambe le info le cerco di valorizzare in automatico coi default "parentid" e "id" (posto che le props esistano nell'oggetto)
2269
- if (!this.ParentKey && !this.OwnKey) {
2270
- if (objs[0]['parentid'] !== undefined)
2271
- this.ParentKey = 'parentid';
2272
- if (objs[0]['id'] !== undefined)
2273
- this.OwnKey = 'id';
2274
- }
2275
- //Check finale per assicurarmi che le props ci siano
2276
- if (!this.ParentKey || !this.OwnKey) {
2277
- console.error('Per utilizzare il sistema in modalità gerarchica è obbligatorio specificare sia ParentKey che OwnKey. Fallback a sistema non gerarchico');
2278
- return;
2279
- }
2280
- // Valorizzazione campi level, expanded, e visible per ogni item
2281
- let currentLevel = 1;
2282
- let assigned = 0;
2283
- do {
2284
- assigned = this.assignLevel(objs, currentLevel);
2285
- currentLevel++;
2286
- } while (assigned > 0);
2287
- // butto su lato html e poi me la gioco là con padding = 20 * (level - 1) per far capire il diverso livello
2288
- }
2289
- /**
2290
- * Per ognuno degli oggetti passati gli assegna un livello di gerarchia in base a **ParentKey** e **OwnKey**
2291
- *
2292
- * @param {any[]} objs Oggetti a cui assegnare il livello di gerarchia
2293
- * @param {number} levelToAssign Livello che sta assegnando attualmente questa iterazione (dato che è ricorsiva)
2294
- *
2295
- * @returns {number} Numero di oggetti a cui è stato assegnato un livello gerarchico
2296
- */
2297
- assignLevel(objs, levelToAssign) {
2298
- let assigned = 0;
2299
- for (let i = 0; i < objs.length; i++) {
2300
- let obj = objs[i];
2301
- // Se la parentKey non è valorizzata, questo è il livello 0 (1... perché gli 0 son perciolosi)
2302
- if (!obj[this.ParentKey] && levelToAssign == 1) {
2303
- obj._level = 1;
2304
- obj._visible = true;
2305
- obj._expanded = this.StartsExpanded;
2306
- assigned++;
2307
- continue;
2308
- }
2309
- // Per i livelli superiore al primo
2310
- if (obj[this.ParentKey] && levelToAssign > 1) {
2311
- // trovo il parent
2312
- for (let p = 0; p < objs.length; p++) {
2313
- let possibleParent = objs[p];
2314
- // Trovato il parent dell'item, assegno all'item il livello giusto
2315
- if (possibleParent[this.OwnKey] == obj[this.ParentKey] && possibleParent._level == levelToAssign - 1) {
2316
- obj._level = levelToAssign;
2317
- // So che questo item ha un parent. Ribadisco che il parent è espanso in base alle impostazione e stessa logica
2318
- // per la visibilità del figlio
2319
- possibleParent._expanded = this.StartsExpanded;
2320
- possibleParent.parent = true;
2321
- obj._visible = this.StartsExpanded;
2322
- assigned++;
2323
- break;
2324
- }
2325
- }
2326
- }
2327
- }
2328
- return assigned;
2329
- }
2330
- /**
2331
- * Funzione che permette di effettuare l'espansione di un parent quando la tabella funziona in modalità gerarchica
2332
- *
2333
- * @param {string} key Chiave del parent da espandere
2334
- */
2335
- expandParent(key) {
2336
- for (let i = 0; i < this.boundSource.length; i++) {
2337
- let obj = this.boundSource[i];
2338
- // Trovo il parent con quell'id e lo espando
2339
- if (obj[this.OwnKey] == key) {
2340
- obj._expanded = true;
2341
- for (let ic = 0; ic < this.boundSource.length; ic++) {
2342
- let child = this.boundSource[ic];
2343
- // Trovo tutti i child di quel parent e li rendo visibili
2344
- if (child[this.ParentKey] == key)
2345
- child._visible = true;
2346
- }
2347
- return;
2348
- }
2349
- }
2350
- }
2351
- /**
2352
- * Funzione che permette di effettuare il collapse di un parent quando la tabella funziona in modalità gerarchica
2353
- *
2354
- * @param {string} key Chiave del parent da collassare
2355
- */
2356
- collapseParent(key) {
2357
- for (let i = 0; i < this.boundSource.length; i++) {
2358
- let obj = this.boundSource[i];
2359
- // Trovo il parent con quell'id e lo collasso
2360
- if (obj[this.OwnKey] == key) {
2361
- obj._expanded = false;
2362
- // Collasso/nascondo tutti i child del parent
2363
- this.collapseChildOfParent(key);
2364
- return;
2365
- }
2366
- }
2367
- }
2368
- /**
2369
- * Collassa ricorsivamente tutti i figli di un parent identificato dalla **parentKey**
2370
- *
2371
- * @param {string} parentKey Chiave del parent di cui collassare i figli
2372
- */
2373
- collapseChildOfParent(parentKey) {
2374
- for (let ic = 0; ic < this.boundSource.length; ic++) {
2375
- let child = this.boundSource[ic];
2376
- // Trovo tutti i child di quel parent e li rendo invisibili. Se il child trovato è a sua volta un parent,
2377
- // lo collasso e vado in ricorsione sui figli
2378
- if (child[this.ParentKey] == parentKey && !child.parent)
2379
- child._visible = false;
2380
- else if (child[this.ParentKey] == parentKey && child.parent) {
2381
- child._expanded = false;
2382
- child._visible = false;
2383
- this.collapseChildOfParent(child[this.OwnKey]);
2384
- }
2385
- }
2386
- }
2387
- // #endregion
2388
- // #region Gestione Selezione
2389
- /**
2390
- * Valuta quali elementi devono essere marcati come selezionati nella vista attuale. Si basa sull'oggetto **selection** interno all'AppSearch
2391
- *
2392
- * @param {any[]} items Oggetti di cui valutare la selezione
2393
- * @param {ItemsSelection<any>} selectionItem Oggetti di selezione derivante dalla view o dall'oggetto per Array
2394
- */
2395
- evaluateSelection(items, selectionItem) {
2396
- if (!selectionItem)
2397
- return;
2398
- this.handleSelectionEvaluation(items, selectionItem);
2399
- }
2400
- /**
2401
- * Valuta quali elementi devono essere marcati come selezionati nella vista attuale. Si basa sull'oggetto **arraymodeSelection** dell'es-table
2402
- *
2403
- * @param {any[]} array Lista di oggetti di cui valutare la selezione in modalità array
2404
- */
2405
- arrayModeEvaluateSelection(array) {
2406
- if (array.length == 0)
2407
- return;
2408
- this.handleSelectionEvaluation(array, this.arraymodeSelection);
2409
- }
2410
- /**
2411
- * Implementazione agnostica della valutazione delle selezioni degli oggetti. Richiede gli oggetti della vista attuale e l'itemSelector
2412
- *
2413
- * @param {any[]} items Oggetti di cui aggiornare lo stato di selezione
2414
- * @param {ItemsSelection<any>} selectionItem Oggetto contenente lo stato attuale di selezione
2415
- */
2416
- handleSelectionEvaluation(items, selectionItem) {
2417
- for (let i = 0; i < items.length; i++) {
2418
- let itm = items[i];
2419
- let hash = itm._hash;
2420
- let itemGroup = itm._group ? null : this.getItemGroup(itm);
2421
- // Reidrato la cache di selezione coi nuovi oggetti altrimenti non riuscirei a beccare gli indici giusti
2422
- // Dopodiché la uso per calcolare istantaneamente se gli oggetti sono selezionati o no
2423
- this.rehidrateCache(itm);
2424
- if (itm._item) {
2425
- if (selectionItem.all)
2426
- itm._selected = !this.exclusionsCache.has(hash) && ((!this.groupsCache.has(itemGroup === null || itemGroup === void 0 ? void 0 : itemGroup._hash) && this.itemsCache.has(hash)) || !this.group_exclusionsCache.has(itemGroup === null || itemGroup === void 0 ? void 0 : itemGroup._hash));
2427
- else
2428
- itm._selected = !this.exclusionsCache.has(hash) && (this.groupsCache.has(itemGroup === null || itemGroup === void 0 ? void 0 : itemGroup._hash) || this.itemsCache.has(hash) || (this.parentTreeStatus(itemGroup) == 'included' && !this.group_exclusionsCache.has(itemGroup === null || itemGroup === void 0 ? void 0 : itemGroup._hash)));
2429
- }
2430
- else if (itm._group) {
2431
- if (selectionItem.all)
2432
- itm._selected = !this.group_exclusionsCache.has(hash) && this.parentTreeStatus(itm) != 'excluded';
2433
- else
2434
- itm._selected = this.groupsCache.has(hash) || (this.parentTreeStatus(itm) == 'included' && !this.group_exclusionsCache.has(hash));
2435
- }
2436
- }
2437
- // Se tutti gli oggetti di questa pagina sono solezionati allora posso mettere il global check a true
2438
- // Se sono in situazione di all-select anche metto la global checkbox, nonostante ci possano essere delle esclusioni
2439
- this.globalCheck = this.boundSource.filter(t => t._group || t._item).every(t => t._selected);
2440
- this.canSelectAll = selectionItem.count > 0 && this.SelectAll;
2441
- // Potrebbe cambiare qualora qualcuno inserisse dati a manazza in modalità Array e desse il refresh manuale alla tabella
2442
- // Comunque costa 0 quindi mi permetto di refreshare
2443
- if (this.arrayMode) {
2444
- let prevSelected = this.selectedObjects;
2445
- this.finalizeSelectionInformations(selectionItem);
2446
- if (this.selectedObjects != prevSelected)
2447
- this.onSelectionChanged.emit(selectionItem);
2448
- }
2449
- }
2450
- /**
2451
- * Dato un oggetto trova la cella di cache in cui è registrato e aggiorna il contenuto
2452
- *
2453
- * @param {any} item Oggetto da aggiornare
2454
- */
2455
- rehidrateCache(item) {
2456
- let ctx = item._hash;
2457
- if (this.itemsCache.has(ctx))
2458
- this.itemsCache.set(ctx, item);
2459
- if (this.group_exclusionsCache.has(ctx))
2460
- this.group_exclusionsCache.set(ctx, item);
2461
- if (this.groupsCache.has(ctx))
2462
- this.groupsCache.set(ctx, item);
2463
- if (this.exclusionsCache.has(ctx))
2464
- this.exclusionsCache.set(ctx, item);
2465
- }
2466
- /**
2467
- * Dato un gruppo controlla ricorsivamente l'albero di cui fa parte se c'è stata una inclusione o esclusione diretta
2468
- *
2469
- * @param {any} grp Gruppo da controllare
2470
- *
2471
- * @returns {'none' | 'excluded' | 'included'}
2472
- * 'none' se non ci sono informazioni su inclusioni o esclusioni
2473
- * 'included' se il gruppo controllato è stato incluso in maniera esplicita dall'albero dei gruppi padri
2474
- * 'excluded' se il gruppo controllato è stato escluso in maniera esplicita dall'albero dei gruppi padri
2475
- */
2476
- parentTreeStatus(grp) {
2477
- if (!grp)
2478
- return 'none';
2479
- let parentGroup = this.rgGroupCache.get(grp._parent);
2480
- if (!parentGroup)
2481
- return 'none';
2482
- if (this.group_exclusionsCache.has(parentGroup._hash))
2483
- return 'excluded';
2484
- if (this.groupsCache.has(parentGroup._hash))
2485
- return 'included';
2486
- return this.parentTreeStatus(parentGroup);
2487
- }
2488
- /**
2489
- * Gestisce la selezione globale degli oggetti, sia per pagina che a livello di **SelectAll**
2490
- *
2491
- * @param {boolean} forcedVal Valore forzato di check da assegnare agli oggetti
2492
- */
2493
- globalCheckChanged(forcedVal = null) {
2494
- // Prendo tutti gli elementi presenti in questa vista. Se ho gruppi prendo solo i gruppi a livello 0, altrimenti prendo tutti gli oggetti per selezionarli
2495
- let items = this.boundSource.find(t => t._group) ? this.boundSource.filter(t => t._group && !t._parent) : this.boundSource;
2496
- var itemSelection = this.handleItemsSelection(items, forcedVal, this.globalCheck);
2497
- this.changed();
2498
- this.onSelectionChanged.emit(itemSelection);
2499
- }
2500
- /**
2501
- * Helper per gestire la selezione di N elementi utilizzando la Cache di selezione ed eventualmente aggiornando il concetto di "all selection"
2502
- *
2503
- * Vunziona sia in modalità Array che in modalità View Semplice o View Avanzata (con le Custom Cells)
2504
- *
2505
- * @param {any[]} items Oggetti da selezionare o deselezionare
2506
- * @param {boolean} forcedVal Valore forzato di check da assegnare agli oggetti
2507
- * @param {boolean} globalCheck Valore del check globale
2508
- *
2509
- * @returns {ItemsSelection<any>} Oggetto di selezione aggiornato con le informazioni sull'ultima operazione effettuata
2510
- */
2511
- handleItemsSelection(items, forcedVal = null, globalCheck = null) {
2512
- var _a, _b, _c;
2513
- let si = ((_a = this.View) === null || _a === void 0 ? void 0 : _a.selection) || this.arraymodeSelection;
2514
- // Se sono in modalità di selezione singola e devo selezionare un'oggetto, per prima cosa devo deselezionare tutti gli altri
2515
- if (this.SingleSelection && ((_b = items[0]) === null || _b === void 0 ? void 0 : _b._selected) && !((_c = items[0]) === null || _c === void 0 ? void 0 : _c._group)) {
2516
- if (items.length > 1 && forcedVal == null)
2517
- throw "Tentativo di selezionare o deselezionare più di un elemento con SingleSelection attivo";
2518
- if (items.length == 1 && forcedVal == null) {
2519
- si = this.handleItemsSelection(this.boundSource.filter(t => !t._group), false, null);
2520
- items[0]._selected = true;
2521
- }
2522
- }
2523
- for (let i = 0; i < items.length; i++) {
2524
- let item = items[i];
2525
- let toChange = forcedVal != null ? item._selected != forcedVal : globalCheck != null ? item._selected != this.globalCheck : false;
2526
- // Se dev'essere overridato il valore di check effettuo l'override o col valore forzato o col valore globale
2527
- if (toChange && !item.locked)
2528
- item._selected = forcedVal != null ? forcedVal : this.globalCheck;
2529
- // Se il valore non dev'essere variato e vengo da una selezione globale semplicemente evito di effettuare operaizoni inutili. L'item/gruppo è già nello stato giusto
2530
- if (!toChange && globalCheck != null)
2531
- continue;
2532
- let allSelection = si.all;
2533
- let isGroup = item._group;
2534
- let isSelection = item._selected;
2535
- let itemGroup = null, allItems = null, selectedItems = null, unselectedItems = null, allGroups = null, selectedGroups = null, unselectedGroups = null, parentGroupSelected = null, parentGroupUnselected = null;
2536
- if (isGroup) {
2537
- let pts = this.parentTreeStatus(item);
2538
- parentGroupSelected = pts == 'included';
2539
- parentGroupUnselected = pts == 'excluded';
2540
- allItems = this.getGroupItems(si, item, null, true);
2541
- selectedItems = this.getGroupItems(si, item, 'selected', true, allItems);
2542
- unselectedItems = this.getGroupItems(si, item, 'unselected', true, allItems);
2543
- allGroups = this.getGroupChildGroups(si, item, null, true);
2544
- selectedGroups = this.getGroupChildGroups(si, item, 'selected', true, allGroups);
2545
- unselectedGroups = this.getGroupChildGroups(si, item, 'unselected', true, allGroups);
2546
- }
2547
- else {
2548
- itemGroup = this.getItemGroup(item);
2549
- parentGroupSelected = itemGroup == null ? null : itemGroup._selected;
2550
- parentGroupUnselected = itemGroup == null ? null : !itemGroup._selected;
2551
- }
2552
- if (!this.ArrayGrouping)
2553
- this.performSelectionOperations(si, item, allSelection, isGroup, isSelection, selectedItems, selectedGroups, unselectedItems, unselectedGroups, allItems, allGroups, parentGroupSelected, parentGroupUnselected);
2554
- else
2555
- this.performSimpleSelectionOperations(si, item, isGroup, isSelection, itemGroup, selectedItems, unselectedItems, allItems, allGroups);
2556
- }
2557
- // Imposto il check globale in base a se tutti gli elementi sono selezionati o meno.
2558
- // Evito di fare queste operazioni se la selezione deriva proprio dal global Check
2559
- if (globalCheck == null)
2560
- this.globalCheck = !this.boundSource.some(t => !t._selected && !t._sep);
2561
- this.finalizeSelectionInformations(si);
2562
- return si;
2563
- }
2564
- /**
2565
- * Dato L'oggetto di selezione, l'oggetto da selezionare/deselezionare e tutti i parametri del caso effettua le operazioni che servono.
2566
- *
2567
- * Logica semplificata rispetto all'originale **performSelectionOperations** per lavorare in una modalità in cui tutti gli elementi sono caricati (**ArrayGrouping** = true)
2568
- */
2569
- performSimpleSelectionOperations(base, item, group, sel, itm_group, sel_itm, desel_itm, all_itms, all_grps) {
2570
- let tripticItem = this.getTriptic('item', base);
2571
- if (group) {
2572
- if (sel) {
2573
- all_grps.forEach(gr => { gr._selected = true; });
2574
- if (desel_itm)
2575
- desel_itm.forEach(el => { el._selected = true; this.addItem(el, tripticItem); });
2576
- }
2577
- else {
2578
- all_grps.forEach(gr => { gr._selected = false; });
2579
- if (sel_itm)
2580
- sel_itm.forEach(el => { el._selected = false; this.removeItem(el, tripticItem); });
2581
- }
2582
- }
2583
- else {
2584
- if (sel) {
2585
- this.addItem(item, tripticItem);
2586
- if (itm_group && all_itms && all_itms.every(t => t._selected))
2587
- this.selectGroup(itm_group);
2588
- }
2589
- else {
2590
- this.removeItem(item, tripticItem);
2591
- if (itm_group)
2592
- itm_group._selected = false;
2593
- }
2594
- }
2595
- }
2596
- /**
2597
- * Helper per selezionare un gruppo e, ricorsivamente, se tutti i gruppi sottostanti al parent sono selezionati, selezionare i gruppi padri
2598
- *
2599
- * @param {any} group Gruppo da selezionare
2600
- */
2601
- selectGroup(group) {
2602
- group._selected = true;
2603
- let parent = this.getGroupParent(group);
2604
- if (parent && this.getGroupChildGroups(null, parent, null, true).every(t => t._selected))
2605
- this.selectGroup(parent);
2606
- }
2607
- /**
2608
- * Dato L'oggetto di selezione, l'oggetto da selezionare/deselezionare e tutti i parametri del caso effettua le operazioni che servono.
2609
- *
2610
- * La logica di questa funzione è nata essenzialmente da spam di trial & error ed è stata testata solo fino a due livelli di raggruppamento,
2611
- * qualsiasi cosa vada oltre non è 100% detto che funzioni...
2612
- */
2613
- performSelectionOperations(base, item, all, group, sel, sel_itm, sel_grp, desel_itm, desel_grp, all_itms, all_grps, parent_incl, parent_excl) {
2614
- let tripticGroup = this.getTriptic('group', base);
2615
- let tripticItem = this.getTriptic('item', base);
2616
- let tripticExcl = this.getTriptic('exclusion', base);
2617
- let tripticgrpExcl = this.getTriptic('group_exclusion', base);
2618
- if (group) {
2619
- if (sel) {
2620
- if (all || parent_incl)
2621
- this.removeItem(item, tripticgrpExcl);
2622
- else
2623
- this.addItem(item, tripticGroup);
2624
- if (sel_itm)
2625
- sel_itm.forEach(el => this.removeItem(el, tripticItem));
2626
- if (sel_grp)
2627
- sel_grp.forEach(gr => this.removeItem(gr, tripticGroup));
2628
- if (all_itms)
2629
- all_itms.forEach(el => { el._selected = true; this.removeItem(el, tripticExcl); });
2630
- if (all_grps)
2631
- all_grps.forEach(gr => { gr._selected = true; this.removeItem(gr, tripticgrpExcl); });
2632
- }
2633
- else {
2634
- if (all || parent_incl)
2635
- this.addItem(item, tripticgrpExcl);
2636
- else
2637
- this.removeItem(item, tripticGroup);
2638
- if (desel_itm)
2639
- desel_itm.forEach(el => this.removeItem(el, tripticExcl));
2640
- if (desel_grp)
2641
- desel_grp.forEach(gr => this.removeItem(gr, tripticExcl));
2642
- if (all_itms)
2643
- all_itms.forEach(el => { el._selected = false; this.removeItem(el, tripticItem); });
2644
- if (all_grps)
2645
- all_grps.forEach(gr => { gr._selected = false; this.removeItem(gr, tripticGroup); });
2646
- }
2647
- }
2648
- else {
2649
- if (sel) {
2650
- if ((parent_excl == null && all) || parent_incl)
2651
- this.removeItem(item, tripticExcl);
2652
- else
2653
- this.addItem(item, tripticItem);
2654
- }
2655
- else {
2656
- if (parent_excl || (!all && parent_excl == null))
2657
- this.removeItem(item, tripticItem);
2658
- else
2659
- this.addItem(item, tripticExcl);
2660
- }
2661
- }
2662
- }
2663
- /**
2664
- * Helper per evitare di riscrivere ogni santa volta array.splice(array.indexof(item), 1);
2665
- */
2666
- removeItem(item, triptic) {
2667
- let index = triptic.index_cache.get(item._hash);
2668
- if (index != null) {
2669
- triptic.cache.delete(item._hash);
2670
- triptic.index_cache.delete(item._hash);
2671
- triptic.array[index] = null;
2672
- }
2673
- return !!index;
2674
- }
2675
- /**
2676
- * Helper per evitare di riscrivere ogni santa volta array.push(item); e la gestione della
2677
- */
2678
- addItem(item, triptic) {
2679
- if (triptic.index_cache.get(item._hash) == null) {
2680
- let i = triptic.array.push(item) - 1;
2681
- triptic.cache.set(item._hash, item);
2682
- triptic.index_cache.set(item._hash, i);
2683
- return true;
2684
- }
2685
- return false;
2686
- }
2687
- /**
2688
- * Ottiene il trittico di selezione: L'array degli oggetti e le due cache
2689
- */
2690
- getTriptic(subject, base) {
2691
- switch (subject) {
2692
- case 'group':
2693
- return new CacheTriptic(this.groupsCache, this.i_groupsCache, base.groups);
2694
- case 'item':
2695
- return new CacheTriptic(this.itemsCache, this.i_itemsCache, base.items);
2696
- case 'group_exclusion':
2697
- return new CacheTriptic(this.group_exclusionsCache, this.i_group_exclusionsCache, base.group_exclusions);
2698
- case 'exclusion':
2699
- return new CacheTriptic(this.exclusionsCache, this.i_exclusionsCache, base.exclusions);
2700
- }
2701
- }
2702
- /**
2703
- * Dato un oggetto restituisce il gruppo di cui fa parte, se esiste
2704
- *
2705
- * @param {any} item Oggetto di cui trovare il gruppo
2706
- */
2707
- getItemGroup(item) {
2708
- let parent = this.rgGroupCache.get(item._thisKey);
2709
- if (parent)
2710
- return parent;
2711
- return null;
2712
- }
2713
- /**
2714
- * Data la chiave di un gruppo restituisce tutti gli oggetti con quella chiave
2715
- *
2716
- * @param {any} group Chiave da cercare
2717
- * @param {'selected' | 'unselected'} status Stato degli elementi, selezionati o no
2718
- * @param {boolean} recursive Indica se cercare solo gli elementi direttamente collegati o se prendere anche quelli dei gruppi figli
2719
- *
2720
- * @returns {any[]} Oggetti di tipo **_item** facenti capo alla chiave **groupKey**
2721
- */
2722
- getGroupItems(sel, group, status, recursive = false, allbase = null) {
2723
- let items = [];
2724
- if (allbase)
2725
- items = allbase;
2726
- else {
2727
- if (recursive) {
2728
- // In modalità ricorsiva prendo gli oggetti di tutte le chiavi simili che trovo
2729
- for (let key of this.rgItemCache.keys())
2730
- if (key.startsWith(group._thisKey))
2731
- items.push(...this.rgItemCache.get(key));
2732
- }
2733
- else
2734
- items = this.rgItemCache.get(group._thisKey);
2735
- }
2736
- items = items.filter(t => !status || (t._selected && status == 'selected') || (!t._selected && status == 'unselected'));
2737
- // Non trovo nessun oggetto, però magari di oggetti ne ho all'interno dell'oggetto di selezione.
2738
- // Questo può essere vero solo se NON sono in modalità array, in caso contrario gli oggetti li devo per forza avere tutti
2739
- if (items.length != 0 || !sel || this.arrayMode)
2740
- return items;
2741
- if (status == 'unselected')
2742
- items = sel.exclusions.filter(t => t != null &&
2743
- (!recursive && t._thisKey == group._thisKey) ||
2744
- (recursive && t._thisKey.startsWith(group._thisKey)));
2745
- else if (status == 'selected')
2746
- items = sel.items.filter(t => t != null &&
2747
- (!recursive && t._thisKey == group._thisKey) ||
2748
- (recursive && t._thisKey.startsWith(group._thisKey)));
2749
- return items;
2750
- }
2751
- /**
2752
- * Data la chiave di un gruppo restituisce tutti gli oggetti con quella chiave
2753
- *
2754
- * @param {any} group Gruppo di cui cercare il parent
2755
- *
2756
- * @returns {any} Oggetto di tipo **_group** rappresentante il parent del **group** attuale
2757
- */
2758
- getGroupParent(group) {
2759
- let parent = this.rgGroupCache.get(group._parent);
2760
- if (parent)
2761
- return parent;
2762
- return null;
2763
- }
2764
- /**
2765
- * Data la chiave di un gruppo restituisce tutti i gruppi figli
2766
- *
2767
- * @param {string} group Gruppo che rappresenta il padre di cui cercare i figli
2768
- * @param {'selected' | 'unselected'} status Stato dei gruppi, selezionati o no
2769
- * @param {boolean} recursive Indica se cercare solo i gruppi direttamente collegati o se prendere anche quelli dei gruppi figli
2770
- *
2771
- * @returns {any[]} Oggetti di tipo **_group** facenti capo alla chiave **groupKey**
2772
- */
2773
- getGroupChildGroups(sel, group, status, recursive = false, allbase = null) {
2774
- let thisGroup = this.rgGroupCache.get(group._thisKey);
2775
- let items = [];
2776
- if (allbase)
2777
- items = allbase;
2778
- else {
2779
- if (recursive) {
2780
- // In modalità ricorsiva prendo gli oggetti di tutte le chiavi simili che trovo
2781
- for (let key of this.rgChildGroupsCache.keys())
2782
- if (key.startsWith(group._thisKey))
2783
- items.push(...this.rgChildGroupsCache.get(key));
2784
- }
2785
- else
2786
- items = this.rgChildGroupsCache.get(group._thisKey);
2787
- }
2788
- items = items.filter(t => !status || (t._selected && status == 'selected') || (!t._selected && status == 'unselected'));
2789
- // Non trovo nessun oggetto, però magari di oggetti ne ho all'interno dell'oggetto di selezione
2790
- if (items.length != 0 || !sel)
2791
- return items;
2792
- if (status == 'unselected')
2793
- items = sel.group_exclusions.filter((t) => t != null && ((!recursive && t._thisRoute.length == thisGroup._thisRoute.length + 1 && t._thisRoute.startsWith(group._thisKey)) ||
2794
- (recursive && t._thisKey.startsWith(group._thisKey))));
2795
- else
2796
- items = sel.groups.filter((t) => t != null && ((!recursive && t._thisRoute.length == thisGroup._thisRoute.length + 1 && t._thisRoute.startsWith(group._thisKey)) ||
2797
- (recursive && t._thisKey.startsWith(group._thisKey))));
2798
- return items;
2799
- }
2800
- /**
2801
- * Finalizza le informazioni di selezione del **ItemsSelection** corrente
2802
- */
2803
- finalizeSelectionInformations(selectionItem) {
2804
- // Dato che le delete sono logiche dato che tengo la cache degli indici devo renderle fisiche
2805
- let tmpGrp = [], tmpItems = [], tmpExcl = [], tmpGrpExcl = [];
2806
- let grpRemoved = false, itemsRemoved = false, exclRemoved = false, grpExclRemoved = false;
2807
- for (let i = 0; i < selectionItem.items.length; i++)
2808
- if (selectionItem.items[i] != null)
2809
- tmpItems.push(selectionItem.items[i]);
2810
- else
2811
- itemsRemoved = true;
2812
- for (let i = 0; i < selectionItem.groups.length; i++)
2813
- if (selectionItem.groups[i] != null)
2814
- tmpGrp.push(selectionItem.groups[i]);
2815
- else
2816
- grpRemoved = true;
2817
- for (let i = 0; i < selectionItem.exclusions.length; i++)
2818
- if (selectionItem.exclusions[i] != null)
2819
- tmpExcl.push(selectionItem.exclusions[i]);
2820
- else
2821
- exclRemoved = true;
2822
- for (let i = 0; i < selectionItem.group_exclusions.length; i++)
2823
- if (selectionItem.group_exclusions[i] != null)
2824
- tmpGrpExcl.push(selectionItem.group_exclusions[i]);
2825
- else
2826
- grpExclRemoved = true;
2827
- selectionItem.items = tmpItems;
2828
- selectionItem.group_exclusions = tmpGrpExcl;
2829
- selectionItem.exclusions = tmpExcl;
2830
- selectionItem.groups = tmpGrp;
2831
- // Le cache degli indici potrebbero avere buchi, risolvo
2832
- if (grpRemoved)
2833
- this.i_groupsCache = this.compactIndexMap(this.i_groupsCache);
2834
- if (itemsRemoved)
2835
- this.i_itemsCache = this.compactIndexMap(this.i_itemsCache);
2836
- if (exclRemoved)
2837
- this.i_exclusionsCache = this.compactIndexMap(this.i_exclusionsCache);
2838
- if (grpExclRemoved)
2839
- this.i_group_exclusionsCache = this.compactIndexMap(this.i_group_exclusionsCache);
2840
- // Poi riprendo a fare tutto in normalità
2841
- selectionItem.count = this.evaluateSelected();
2842
- // Se ho fatto selezione "all" ma poi mi sono messo a togliere tutti gli elementi fino a rimanerne 0 resetto l'oggetto di selezione
2843
- if (selectionItem.count == 0) {
2844
- this.boundSource.forEach(t => t._selected = false);
2845
- selectionItem.all = false;
2846
- selectionItem.exclusions = [];
2847
- selectionItem.items = [];
2848
- selectionItem.groups = [];
2849
- selectionItem.group_exclusions = [];
2850
- // Ripulisco la cache altrimenti mi rimane piena di tutte le esclusioni
2851
- this.clearSelectionCaches();
2852
- }
2853
- // Se la possibilità di fare "Seleziona tutto" è abilitata allora la considero appena mi viene selezionato qualcosa
2854
- this.canSelectAll = selectionItem.count > 0 && this.SelectAll;
2855
- }
2856
- /**
2857
- * Compatta una cache di indici
2858
- */
2859
- compactIndexMap(map) {
2860
- let index = 0;
2861
- let ret = new Map();
2862
- for (let key of map.keys())
2863
- ret.set(key, index++);
2864
- return ret;
2865
- }
2866
- /**
2867
- * Gestisce i click sulla tabella, gestendo eventualmente anche gli Shift + Click per selezionare un range di oggetti
2868
- *
2869
- * @param {any} event Evento nativo HTML del click
2870
- * @param {any} item Oggetto bindato su cui si è effettuato il click
2871
- *
2872
- * @returns {boolean} **true** se l'operaizone è andata a buon fine, **false** altrimenti
2873
- */
2874
- handleClick(event, item) {
2875
- // Seleziono del testo ma non ho shift premuto -> ignoro la selezione
2876
- if ((event.view.getSelection().type == 'Range' || event.view.getSelection().toString().length > 0) && !event.shiftKey)
2877
- return false;
2878
- // Seleziono del testo e ho shift premuto -> annullo la selezione del testo
2879
- if ((event.view.getSelection().type == 'Range' || event.view.getSelection().toString().length > 0) && event.shiftKey)
2880
- this.utiExts.clearTextSelection();
2881
- let selecteditems = [];
2882
- if (event.shiftKey && this.ShiftClick && !this.SingleSelection) {
2883
- let startSelecting = false;
2884
- let items = this.boundSource.filter(t => !t._group && !t._sep);
2885
- for (let i = 0; i < items.length; i++) {
2886
- let t = items[i];
2887
- if (startSelecting) {
2888
- t._selected = true;
2889
- selecteditems.push(t);
2890
- }
2891
- if ((t == item || t == this.lastSelected) && !startSelecting) {
2892
- startSelecting = true;
2893
- t._selected = true;
2894
- selecteditems.push(t);
2895
- }
2896
- else if ((t == item || t == this.lastSelected) && startSelecting)
2897
- startSelecting = false;
2898
- }
2899
- }
2900
- else {
2901
- item._selected = !item._selected;
2902
- this.lastSelected = item;
2903
- selecteditems.push(item);
2904
- }
2905
- var itemSelection = this.handleItemsSelection(selecteditems);
2906
- this.changed();
2907
- this.onSelectionChanged.emit(itemSelection);
2908
- return true;
2909
- }
2910
- /**
2911
- * Valuta la quantità di oggetti che sono stati selezionati al termine di un evento di selezione
2912
- *
2913
- * @returns {number} Numero di oggetti selezionati
2914
- */
2915
- evaluateSelected() {
2916
- var _a;
2917
- let si = ((_a = this.View) === null || _a === void 0 ? void 0 : _a.selection) || this.arraymodeSelection;
2918
- let excByGroup = si.group_exclusions.reduce((prev, curr) => prev + curr.count, 0);
2919
- let incByGroup = si.groups.reduce((prev, curr) => prev + curr.count, 0);
2920
- this.selectedObjects = (si.all ? this.BaseItemsCount : incByGroup) - excByGroup + si.items.length - si.exclusions.length;
2921
- return this.selectedObjects;
2922
- }
2923
- /**
2924
- * Gestisce il comando di "Seleziona tutto in tutte le pagine" o il suo contrario, cioè "Reimposta selezione"
2925
- */
2926
- selectAllOrResetSelection() {
2927
- let selectionItem = this.View.selection || this.arraymodeSelection;
2928
- this.clearSelectionCaches();
2929
- selectionItem.all = !selectionItem.all;
2930
- selectionItem.exclusions = [];
2931
- selectionItem.groups = [];
2932
- selectionItem.group_exclusions = [];
2933
- selectionItem.items = [];
2934
- // Ripulisco gli stati UI di selezione globale se l'ho disattivata
2935
- if (!selectionItem.all) {
2936
- this.canSelectAll = false;
2937
- this.globalCheck = false;
2938
- }
2939
- this.finalizeSelectionInformations(selectionItem);
2940
- this.onSelectionChanged.emit(selectionItem);
2941
- // Dopo aver resettato direttamente il solo oggetto this.View.selection devo anche riallineare a tutti gli oggetti bindati
2942
- this.evaluateSelection(this.boundSource, selectionItem);
2943
- }
2944
- // #endregion
2945
- // #region Gestione Paginazione
2946
- /**
2947
- * Sposta la ricerca di una pagina in avanti (o indeitro)
2948
- *
2949
- * @param {number} page Numero di pagine da aggiungere (o sottrarre, se negativo) alla pagina attuale
2950
- */
2951
- addToPage(page) {
2952
- var _a;
2953
- let view = this.MainGroupView ? this.MainGroupView : this.View;
2954
- this.goToPage((((_a = (this.SearchView || view)) === null || _a === void 0 ? void 0 : _a.page) || 0) + page);
2955
- }
2956
- /**
2957
- * Sposta la ricerca alla pagina specificata
2958
- *
2959
- * @param {number} page Pagina a cui navigare
2960
- */
2961
- goToPage(page) {
2962
- let view = this.MainGroupView ? this.MainGroupView : this.View;
2963
- if (!view.page || !view.pages)
2964
- return;
2965
- let appSearchElement = this.SearchView || view;
2966
- if (page === 0 || page > appSearchElement.pages)
2967
- return;
2968
- appSearchElement.page = page;
2969
- this.arrayPulsanti = this.getPagesArray(6, appSearchElement.page, appSearchElement.pages);
2970
- let hasGroupings = !!this.MainGroupView;
2971
- this.emitSearchRequest(false, hasGroupings ? view : null);
2972
- }
2973
- /**
2974
- * Evento richiamato sul cambio della paginazione. Verrà richiamato l'evento **emitSearchRequest**
2975
- * per comunicare al componente che utilizza questa tabella che i dati sono da aggiornare
2976
- */
2977
- onItemsPerPageChanged(newIpp) {
2978
- this.PagerOptions.View.itemsperpageoverride = newIpp;
2979
- this.changed();
2980
- if (this.MainGroupView)
2981
- this.emitSearchRequest(true, this.MainGroupView);
2982
- else
2983
- this.emitSearchRequest(true);
2984
- }
2985
- /**
2986
- * Evento richiamato sul cambio della paginazione. Verrà richiamato l'evento **emitSearchRequest** con la vista del separatore
2987
- */
2988
- onGroupItemsPerPageChanged(pager, newIpp) {
2989
- pager.view.itemsperpageoverride = newIpp;
2990
- this.emitSearchRequest(true, pager.view);
2991
- }
2992
- // #endregion
2993
- // #region Gestione Export
2994
- /**
2995
- * Effettua l'esportazione dei dati
2996
- *
2997
- * @param {string} format Formato di esportazione. Letto solo in modalità Report della tabella
2998
- */
2999
- tryExport(format) {
3000
- if (!this.ExportFunction)
3001
- return;
3002
- if (this.reportMode)
3003
- this.ExportFunction(format);
3004
- else
3005
- this.ExportFunction((data, cancel = false) => {
3006
- if (cancel)
3007
- return;
3008
- if (data.length == 0) {
3009
- this.msgExts.simpleWarning(this.lc.loc("Cannot export an empty dataset"));
3010
- return;
3011
- }
3012
- this.setupExport(data);
3013
- this.cdr.detectChanges();
3014
- setTimeout(() => { this.exportDownloader.nativeElement.click(); });
3015
- });
3016
- }
3017
- /**
3018
- * Metodo che effettivamente genera gli header e i dati per l'esportazione con **ngx-csv**
3019
- *
3020
- * @param {any[]} items Oggetti da esportare
3021
- */
3022
- setupExport(items) {
3023
- let drcd = this.DynamicRowColumnsDefinition;
3024
- this.headers = drcd && drcd.length > 0 ? this.expExts.setupForGenericExport(items, drcd.map(t => { return { label: t.description, key: t.propertyName, order: t.columnOrder }; })) : this.expExts.setupForExport(items);
3025
- this.data = items;
3026
- }
3027
- // #endregion
3028
- // #region Gestione Modalità Report
3029
- /**
3030
- * Sul click dell'Header di una colonna questo metodo si occupa di applicare l'ordinamento successivo e di notificare con **emitSearchRequest**
3031
- * il bisogno di aggiornare i dati da parte del componente che utilizza la tabella
3032
- *
3033
- * Utilizzato solo in modalità REport
3034
- *
3035
- * @param {ReportColumn} clm Colonna del report per cui ordinare
3036
- */
3037
- setupNextOrderAndSearch(clm) {
3038
- if (!(this.View instanceof ReportDefinition)) {
3039
- console.error('View diversa da reportdefinition entrata nel metodo setupNextOrderAndSearch');
3040
- return;
3041
- }
3042
- let orderNext = { NONE: 'DESC', DESC: 'ASC', ASC: null };
3043
- let nextOrder = orderNext[clm.order || 'NONE'];
3044
- clm.order = nextOrder;
3045
- let order;
3046
- let clmOrder = this.View.orders ? this.View.orders.filter(t => t.column == clm.id) : [];
3047
- if (clmOrder.length == 0 && clm.order) {
3048
- order = new ReportOrder();
3049
- order.column = clm.id;
3050
- order.order = clm.order;
3051
- if (!this.View.orders)
3052
- this.View.orders = [];
3053
- this.View.orders.push(order);
3054
- }
3055
- else if (clmOrder.length == 1) {
3056
- // Rimuovo l'ordinamento o aggiorno quello già esistente
3057
- if (!clm.order)
3058
- clmOrder = [];
3059
- else
3060
- clmOrder[0].order = clm.order;
3061
- }
3062
- else
3063
- console.warn('Impossibile settare ordinamento. Colonna ' + clm.id + ' direttive di ordinamento ' + clmOrder.length + ' ordinamento scelto ' + clm.order);
3064
- // Dopo aver aggiornato l'ordinamento rilancio la ricerca
3065
- this.emitSearchRequest(false);
3066
- }
3067
- /**
3068
- * Metodo che si occupa di gestire la grafica della tabella in base alle informazioni di ordinamento colonne e paginazione contenuti nel modello
3069
- */
3070
- reviewReportBindings() {
3071
- if (!(this.View instanceof ReportDefinition)) {
3072
- console.error('View diversa da reportdefinition entrata nel metodo reviewReportBindings');
3073
- return;
3074
- }
3075
- // Allineo le informazioni su eventuali ordinamenti fatti precedentemente
3076
- if (this.View.orders && this.View.orders.length > 0) {
3077
- this.View.orders.forEach(t => {
3078
- this.ReportValues.columns.filter(c => c.id == t.column)[0].order = t.order;
3079
- });
3080
- }
3081
- // Recupero il count precedente se serve
3082
- if (this.ReportValues.count != -2)
3083
- this.previousCount = this.ReportValues.count;
3084
- else if (this.ReportValues.count == -2)
3085
- this.ReportValues.count = this.previousCount;
3086
- let ipp = (this.View.itemsperpageoverride || 15);
3087
- this.View.pages = Math.ceil(this.ReportValues.count / ipp);
3088
- this.arrayPulsanti = this.getPagesArray(6, this.View.page, this.View.pages);
3089
- }
3090
- // #endregion
3091
- // #region Gestione update automatico
3092
- /**
3093
- * Metodo che gestisce la modifica del tempo specificato per l'aggiornamento automatico
3094
- */
3095
- autoUpdateChanged() {
3096
- if (!/^[1-9]\d*$/.test(this.seconds))
3097
- this.seconds = '10';
3098
- let secondsInMs = parseInt(this.seconds, null) * 1000;
3099
- if (this.autoUpdate)
3100
- this.updateTimer = setInterval(() => { this.emitSearchRequest(false); }, secondsInMs);
3101
- else
3102
- clearInterval(this.updateTimer);
3103
- }
3104
- // #endregion
3105
- // #region Gestione tabella dinamica
3106
- /**
3107
- * Metodo chiamato dal click su una delle colonne generate dall'Input **DynamicOperations**
3108
- *
3109
- * @param {any} item L'oggetto su cui va effettuata l'operazione
3110
- * @param {string} opid Codice identificativo dell'operazione da effettuarsi
3111
- */
3112
- dynamicOperation(item, opid) {
3113
- this.onDynamicOperation.emit({ id: opid, item: item });
3114
- }
3115
- /**
3116
- * Ottiene il contenuto dell'EsTd da utilizzare per la colonna specificata
3117
- *
3118
- * @param {string} column Colonna per cui cercare la cella
3119
- *
3120
- * @returns {TemplateRef<any>} Template da usare per la colonna
3121
- */
3122
- findEsTd(column) {
3123
- var EsTd = this.EsTdsDirective.find((item) => item.td === column);
3124
- return EsTd ? EsTd.Template : null;
3125
- }
3126
- /**
3127
- * Metodo di supporto alla creazione di un router link parametrizzato all'oggetto corrente utilizzato nella modalità dinamica
3128
- *
3129
- * @param {string} path Path su cui navigare con eventuali parametri riferiti all'oggetto cotnestuale come {0}, {1}, ecc...
3130
- * @param {string[]} parameterProps Lista posizionale delle proprietà a cui bindare i riferimenti del parametro **path**
3131
- * Es. Il valore dela proprietà all'indice 0 di questo array verrà sostituita al valore {0} del parametro **path**
3132
- * @param {GenericItem} item Oggetto generico collegato a questo contesto
3133
- *
3134
- * @returns {any} Router link generato in base al parametri
3135
- */
3136
- generateRouterLink(path, parameterProps, item) {
3137
- if (this.DynamicTableRouterLinkCache[item._hash + path]) {
3138
- return this.DynamicTableRouterLinkCache[item._hash + path];
3139
- }
3140
- else {
3141
- let link = this.getRouterLink(path, parameterProps, item);
3142
- this.DynamicTableRouterLinkCache[item._hash + path] = link;
3143
- return link;
3144
- }
3145
- }
3146
- /**
3147
- * Crea un router link
3148
- *
3149
- * @param {string} path Path su cui navigare con eventuali parametri riferiti all'oggetto cotnestuale come {0}, {1}, ecc...
3150
- * @param {string[]} pars Lista posizionale delle proprietà a cui bindare i riferimenti del parametro **path**
3151
- * Es. Il valore dela proprietà all'indice 0 di questo array verrà sostituita al valore {0} del parametro **path**
3152
- * @param {GenericItem} item Oggetto generico collegato a questo contesto
3153
- *
3154
- * @returns {any} Router link generato in base al parametri
3155
- */
3156
- getRouterLink(path, pars, item) {
3157
- for (let i = 0; i < pars.length; i++)
3158
- path = path.replace('{' + i + '}', item.properties[pars[i]]);
3159
- path = path.replace(/'/g, '"').replace(/ /g, '');
3160
- return JSON.parse(path);
3161
- }
3162
- // #endregion
3163
- // #region Paginazione in modalità Array
3164
- /**
3165
- * Equivalente del metodo **addToPage** riadattato per la modalità array
3166
- *
3167
- * @param {number} page Numero di pagine da aggiungere (o sottrarre, se negativo) alla pagina attuale
3168
- */
3169
- arrayAddToPage(page) {
3170
- this.arrayGoToPage(this.arraymodePage + page);
3171
- }
3172
- /**
3173
- * Equivalente del metodo **goToPage** riadattato per la modalità array
3174
- *
3175
- * @param {number} page Pagina a cui navigare
3176
- */
3177
- arrayGoToPage(page) {
3178
- if (page === 0 || page > this.arraymodePages)
3179
- return;
3180
- this.arraymodePage = page;
3181
- // Riforzo il writevalue in modo che il codice passi dalla gestione come se fosse fatta ripartire una ricerca
3182
- this.internalWriteValue();
3183
- }
3184
- /**
3185
- * Metodo per effettuare il refresh della paginazione sul cambiamento degli oggetti da visualizzare in una singola pagina.
3186
- *
3187
- * Vale solo per la modalità Array
3188
- *
3189
- * @param {number} pageSize Dimensione della pagina
3190
- */
3191
- refreshPaging(pageSize) {
3192
- this.ArraymodeItemsPerPage = pageSize;
3193
- this.arraymodePages = Math.ceil(this.View.length / this.ArraymodeItemsPerPage);
3194
- this.arraymodePage = 1;
3195
- // Riforzo il writevalue in modo che il codice passi dalla gestione come se fosse fatta ripartire una ricerca
3196
- this.internalWriteValue();
3197
- }
3198
- /**
3199
- * Genera le informazioni di paginazione e taglia la View in modalità array per mostrare solo gli oggetti della pagina specificata
3200
- */
3201
- adaptViewToPaging() {
3202
- let tmpItems = [];
3203
- // Se ho una search view l'array pulsanti viene calcolato da lei, non devo prendere quello della modalità array
3204
- if (!this.SearchView)
3205
- this.arrayPulsanti = this.getPagesArray(6, this.arraymodePage, this.arraymodePages);
3206
- // Poi per tutti i valori dopo compresi fra la pagina - 1 e la pagina
3207
- for (let i = ((this.arraymodePage - 1) * this.ArraymodeItemsPerPage); i < this.arraymodePage * this.ArraymodeItemsPerPage; i++) {
3208
- if (i <= this.View.length - 1)
3209
- tmpItems.push(this.View[i]);
3210
- }
3211
- return tmpItems;
3212
- }
3213
- // #endregion
3214
- // #region Gestione click sulle celle dinamiche e opzioni nel Corner Menu
3215
- /**
3216
- * Gestore dei click sulle celle per le quali era impostata una azione custom da **CustomCellActionsOn**
3217
- *
3218
- * @param {string} name Nome della cella su cui si è fatto click
3219
- * @param {any} model Modello relativo alla cella cliccata
3220
- *
3221
- * @returns {boolean} **true** se il click è stato fatto su una cella cliccabile, **false** altrimenti
3222
- */
3223
- cellClicked(name, model) {
3224
- if (this.UseCustomCellActions && this.CustomCellActionsOn.split('$').indexOf(name) != -1) {
3225
- this.onCellClick.emit({ column: name, model: model });
3226
- return true;
3227
- }
3228
- return false;
3229
- }
3230
- /**
3231
- * Gestione dei click sulle opzioni del menù contestuale in alto a destra generato dall'Input **CornerMenuOptions**
3232
- *
3233
- * @param {string} cornerid Codice dell'operazione selezionata
3234
- */
3235
- cornerActionClicked(cornerid) {
3236
- this.onCornerAction.emit({ id: cornerid, estable: this });
3237
- }
3238
- // #endregion
3239
- // #region Metodi di utilità
3240
- /** Helper che identifica se il td attuale è di tipo **EsTd**. In caso contrario è da considerarsi **EsTdDirective** */
3241
- isEsTd(td) {
3242
- return !td._directive;
3243
- }
3244
- /** Helper che identifica se il th attuale è di tipo **EsTh**. In caso contrario è da considerarsi **EsThDirective** */
3245
- isEsTh(th) {
3246
- return !th._directive;
3247
- }
3248
- /** Impostazione modalità dell'EsTable */
3249
- setMode(mode) {
3250
- this.viewMode = mode == 'view';
3251
- this.arrayMode = mode == 'array';
3252
- this.reportMode = mode == 'report';
3253
- if (this.reportMode) {
3254
- // In modalità report ho di sicuro queste due
3255
- this.XLSXExport = true;
3256
- this.CSVExport = false;
3257
- }
3258
- }
3259
- /**
3260
- * Helper per effettuare chiamate interne di allineamento alla funzione **writeValue**,
3261
- * impostando prima **internalWriteCall** in modo da non effettuare operazioni inutili
3262
- */
3263
- internalWriteValue() {
3264
- this.internalWriteCall = true;
3265
- this.writeValue(this.View);
3266
- this.internalWriteCall = false;
3267
- }
3268
- /**
3269
- * Date le informazioni di paginazione ottiene l'array dei pulsanti
3270
- *
3271
- * @param {number} maxBtns Numero massimo di pulsanti da visualizzare
3272
- * @param {number} page Pagina corrente
3273
- * @param {number} lastPage Ultima pagina disponibile
3274
- *
3275
- * @returns {any[]} Pseudo-array di pulsanti a cui ci si può bindare lato HTML
3276
- */
3277
- getPagesArray(maxBtns, page, lastPage) {
3278
- let result = [];
3279
- if (lastPage == -1)
3280
- lastPage = page + 1;
3281
- let min, max;
3282
- if (lastPage <= maxBtns) {
3283
- min = 1;
3284
- max = lastPage - 1;
3285
- }
3286
- else {
3287
- // tolgo la pagina selected è l'ultima pagina che è quella delle pagine totali
3288
- let rangeOutside = (maxBtns - 2) / 2;
3289
- min = page - rangeOutside;
3290
- max = page + rangeOutside;
3291
- if (min < 1) {
3292
- min = 1;
3293
- max = maxBtns - 1;
3294
- }
3295
- else if (max >= lastPage) {
3296
- min = lastPage - maxBtns + 1;
3297
- max = lastPage - 1;
3298
- }
3299
- }
3300
- result.push({ val: 1, cssClass: (1 === page ? 'btn-main app-white-text' : 'app-white-button') });
3301
- if (max >= min) {
3302
- for (let i = min; i <= max; i++)
3303
- if (i !== 1)
3304
- result.push({ val: i, cssClass: (i === page ? 'btn-main app-white-text' : 'app-white-button') });
3305
- result.push({
3306
- val: lastPage,
3307
- cssClass: (lastPage === page ? 'btn-main app-white-text' : 'app-white-button')
3308
- });
3309
- }
3310
- return result;
3311
- }
3312
- /**
3313
- * Calcola l'hash di un oggetto qualsiasi
3314
- *
3315
- * @param {any[]} items Oggetti per cui calcolare l'hash
3316
- */
3317
- calculateHash(items) {
3318
- if (!items)
3319
- return;
3320
- // Supporto a hash duplicati di oggetti uguali
3321
- let usedHashesCache = {};
3322
- for (let i = 0; i < items.length; i++) {
3323
- let item = items[i];
3324
- // Prima di calcolare l'hash rimuovo le proprietà interne prima che mi scompensino i calcoli successivi
3325
- let tmp = Object.assign({}, items[i]);
3326
- delete tmp._selected;
3327
- delete tmp._visible;
3328
- delete tmp._hash;
3329
- let hash = this.hashExts.hashObject(tmp);
3330
- usedHashesCache[hash] = usedHashesCache[hash] ? usedHashesCache[hash] + 1 : 1;
3331
- item._hash = hash + (usedHashesCache[hash] > 1 ? "_" + usedHashesCache[hash] : "");
3332
- }
3333
- }
3334
- /**
3335
- * Metodo eventualmente richiamabile anche dal componente esterno che permette di forzare un refresh della tabella
3336
- */
3337
- forceRefresh() {
3338
- // Se sono in modalità View viene mantenuto in automatico il numero di pagina, ma per la modalità array devo prendere le info di paginazione prima e riapplicarle dopo
3339
- let arrayPage;
3340
- let arrayIpp;
3341
- if (this.arrayMode) {
3342
- arrayPage = this.arraymodePage;
3343
- arrayIpp = this.ArraymodeItemsPerPage;
3344
- }
3345
- this.writeValue(this.View);
3346
- this.cdr.detectChanges();
3347
- if (this.arrayMode) {
3348
- this.ArraymodeItemsPerPage = arrayIpp;
3349
- this.arrayGoToPage(arrayPage);
3350
- }
3351
- }
3352
- }
3353
- EsTableComponent.decorators = [
3354
- { type: Component, args: [{
3355
- selector: 'es-table',
3356
- viewProviders: [{ provide: LocalizationService, useClass: EsTableLoc }],
3357
- changeDetection: ChangeDetectionStrategy.OnPush,
3358
- encapsulation: ViewEncapsulation.None,
3359
- template: "<!-- Patacchino di autoaggiornamento -->\r\n<div class=\"w-100\" *ngIf=\"AutoUpdate\">\r\n <div class=\"pull-right\">\r\n {{'Update every' | localize : lc}}&nbsp;<input [readonly]=\"autoUpdate\" maxlength=\"3\" class=\"form-control est-custom-input\" type=\"text\" [(ngModel)]=\"seconds\" />&nbsp;{{'second/s' | localize : lc}}\r\n </div>\r\n <div class=\"pull-right m-t-2\">\r\n <label class=\"est-switch\">\r\n <input type=\"checkbox\" [(ngModel)]=\"autoUpdate\" (ngModelChange)=\"autoUpdateChanged();\" />\r\n <div class=\"est-slider round\"></div>\r\n </label>\r\n </div>\r\n</div>\r\n\r\n<!--\r\nI TH sono contenuto statico, questo significa che senza condizione per RowTHs arriverebbero sia qui sia nell ng-container dell'header in fase non inizializzata, duplicando fisicamente le colonne.\r\nPer ovviare al problema, questo pezzo lo faccio apparire solo se ci sono gi\u00E0 dei RowTHs, quindi su valorizzazione della View succeder\u00E0:\r\n1) appaiono i th nell' ng-container dell'header, e NON qui\r\n2) i TH vengono presi, elaborati e trasformati in RowTHs\r\n3) l'ng-container dell'header sparisce (per la condizione !UseCustomCells || !RowTHs) e qui appaiono i nuovi TH (che poi sono gli stessi di prima che girano)\r\n4) Vengono presi i nuovi TH da qui e trasformati a loro volta in RowTHs\r\n-->\r\n<div hidden *ngIf=\"UseCustomCells && RowTHs\">\r\n <ng-container *ngIf=\"View\">\r\n <!--Qui invece ci sono tutti i TH-->\r\n <ng-container *ngTemplateOutlet=\"headerRef\"></ng-container>\r\n </ng-container>\r\n</div>\r\n\r\n<!--\r\nQuesta parte \u00E8 un po' pi\u00F9 semplice del sopra. Infatti i TD vengono s\u00EC bindati in entrambi i punti (qui e nell'ng-container del body), ma avr\u00F2 le TD statiche prima di generare la TMPBoundSource.\r\nQuesto significa che il workflow di binding sar\u00E0:\r\n1) Appaiono i TD statici nel body e NON qui, perch\u00E9 i TMPBoundSource non sono ancora stati emessi\r\n2) Contemporaneamente all'emissione dei TMPBoundSource vengono anche emessi i RowTds\r\n3) Considerando il punto 2, al giro dopo appariranno i TD qui, perch\u00E9 \u00E8 stata generata la TMPBoundSource, e spariranno contemporaneamente dall'ng-container del body (per la condizione !UseCustomCells || !RowTDs)\r\n-->\r\n<div hidden *ngIf=\"UseCustomCells && bodyRef\">\r\n <ng-container *ngIf=\"View\">\r\n <!--Tutti i TD che dopo verranno presi ed elaborati internamente-->\r\n <ng-container *ngFor=\"let item of TMPBoundSource\">\r\n <ng-container *ngTemplateOutlet=\"bodyRef; context : {$implicit: item}\"></ng-container>\r\n </ng-container>\r\n </ng-container>\r\n</div>\r\n\r\n<ng-container *ngIf=\"View\">\r\n <div *ngIf=\"FirstBind && ShowLoadingOnBootstrap\" class=\"est-loading-box\">\r\n <div class=\"est-loading-content\">\r\n <span class=\"fa fa-spinner fa-spin\"></span>&nbsp;{{'Performing Table bootstrap' | localize: lc}}...\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"PagingStyle == 'both' || PagingStyle == 'top'\">\r\n <ng-container *ngTemplateOutlet=\"pagingElement\"></ng-container>\r\n </div>\r\n\r\n <div class=\"table-responsive datatable {{ContainerClass}}\" [class.est-scrollable]=\"UseEndlessscroll\" (scroll)=\"UseEndlessscroll && onScroll($event)\" [style.max-height.px]=\"MaxHeight\">\r\n <table class=\"{{ TableClass }} est-margin-bottom-10\" [class.est-high-density]=\"HighCellDensity\">\r\n <thead [hidden]=\"HeaderHidden || FirstBind\">\r\n <!-- Aggiungo il pezzo che gestisce la selezione di tutto se attivo da config -->\r\n <tr *ngIf=\"SelectAll\">\r\n <th class=\"est-no-selection\" [attr.colspan]=\"Columns.Global\" [class.est-hidden]=\"!canSelectAll && !(View?.selection || arraymodeSelection).all\">\r\n <span>{{ ((selectedObjects || 0) | number : '0.0-0' : locale) + ' ' + ((selectedObjects == 1 ? 'Object Selected' : 'Objects Selected') | localize : lc) }}</span>&nbsp;\r\n <span class=\"est-link est-inline\" (click)=\"selectAllOrResetSelection()\">{{ (View?.selection || arraymodeSelection).all ? ('Reset Selection' | localize : lc) : ('Select Everything' | localize : lc)}}</span>\r\n </th>\r\n </tr>\r\n\r\n <!-- Blocco header group -->\r\n <ng-container *ngIf=\"RowThGroups\">\r\n <tr *ngFor=\"let level of RowThGroups\">\r\n <th *ngFor=\"let cell of level\" [attr.colspan]=\"cell.Span\" \r\n [class.est-pinned-header]=\"cell.Pinned\" [class.est-col-min]=\"cell.Pinned\"\r\n [class.est-ltab-border]=\"cell.Borders\" [class.est-rtab-border]=\"cell.Borders\"\r\n class=\"est-text-center\">\r\n <ng-container *ngIf=\"cell.Pinned; Else: cell.Template\">\r\n <div class=\"est-pinned-border est-cell-group-padding\"></div>\r\n </ng-container>\r\n </th>\r\n </tr>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"!RowThGroups\">\r\n <tr *ngIf=\"headerGroupRef\">\r\n <ng-container *ngTemplateOutlet=\"headerGroupRef\"></ng-container>\r\n <th *ngIf=\"Export\"></th>\r\n </tr>\r\n \r\n <!-- Blocco header group secondario -->\r\n <tr *ngIf=\"secondaryHeaderGroupRef\">\r\n <ng-container *ngTemplateOutlet=\"secondaryHeaderGroupRef\"></ng-container>\r\n <th *ngIf=\"Export\"></th>\r\n </tr>\r\n </ng-container>\r\n\r\n <!-- Blocco effettivo degli header -->\r\n <tr>\r\n <!-- Aggiungo una checkbox se la selezione \u00E8 attiva -->\r\n <th class=\"est-col-min\" *ngIf=\"Selection && !HasPinnedColumns\">\r\n <input *ngIf=\"!SingleSelection\" class=\"est-pointer\" type=\"checkbox\" [disabled]=\"SelectionDisabled\" [(ngModel)]=\"globalCheck\" [ngModelOptions]=\"{'standalone': true}\" (ngModelChange)=\"globalCheckChanged();\">\r\n </th>\r\n\r\n <!-- Header che valgono per view mode e array mode -->\r\n <ng-container *ngIf=\"(viewMode || arrayMode)\">\r\n\r\n <!-- In una tabella base prendo semplicemente i th scritti dall'utente nell'HTML -->\r\n <ng-container *ngIf=\"(!UseCustomCells || !RowTHs) && !DynamicRowColumnsDefinition\">\r\n <ng-container *ngTemplateOutlet=\"headerRef\"></ng-container>\r\n </ng-container>\r\n\r\n <!-- Se ho un modello dinamico dell'oggetto creo le colonne in base alle propriet\u00E0 -->\r\n <ng-container *ngIf=\"(!UseCustomCells || !RowTHs) && DynamicRowColumnsDefinition\">\r\n <th *ngFor=\"let operation of DynamicOperations\" class=\"est-col-min est-no-side-padding\"></th>\r\n \r\n <ng-container *ngFor=\"let rowHeader of DynamicRowColumnsDefinition\">\r\n <ng-container *ngIf=\"rowHeader.visible\">\r\n <th *ngIf=\"OrderByColumn\" es-th=\"{{rowHeader.propertyName}}\" class=\"{{UserDefinedDynamicCols ? ((rowHeader.clss || '') + (rowHeader.headerWraps ? '' : ' est-nowrap')) : ' est-nowrap'}}\" [Order]=\"rowHeader.dataOrder\" [Resizable]=\"ColumnsResizable\" [Orderable]=\"rowHeader.orderable\" [OrderBy]=\"OrderByColumn\" [SearchInProgress]=\"!!researchInProgress\" (onOrderChange)=\"thOrderChanged(rowHeader.propertyName, $event)\">{{rowHeader.description}}</th>\r\n <th *ngIf=\"!OrderByColumn\" es-th=\"{{rowHeader.propertyName}}\" class=\"{{UserDefinedDynamicCols ? ((rowHeader.clss || '') + (rowHeader.headerWraps ? '' : ' est-nowrap')) : ' est-nowrap'}}\" [Order]=\"rowHeader.dataOrder\" [Resizable]=\"ColumnsResizable\" [Orderable]=\"rowHeader.orderable\" [OrderBy]=\"OrderByColumn\">{{rowHeader.description}}</th>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <!-- Se non ho un modello dinamico ma invece delle celle custom, genero gli header in base ai row th -->\r\n <ng-container *ngIf=\"UseCustomCells && RowTHs\">\r\n <th *ngIf=\"HasPinnedColumns\" class=\"est-pinned-header est-col-min\">\r\n <div [style.width.px]=\"PinnedContainerWidth\" class=\"est-pinned-border\">\r\n <th class=\"est-col-min est-no-border\" *ngIf=\"Selection\">\r\n <input *ngIf=\"!SingleSelection\" class=\"est-pointer\" type=\"checkbox\" [disabled]=\"SelectionDisabled\" [(ngModel)]=\"globalCheck\" [ngModelOptions]=\"{'standalone': true}\" (ngModelChange)=\"globalCheckChanged();\">\r\n </th>\r\n <ng-container *ngFor=\"let rowHeader of RowTHs\">\r\n <th *ngIf=\"rowHeader && rowHeader.Visible && rowHeader.Pinned\" [style.width.px]=\"rowHeader.PinnedWidth\" es-th=\"{{rowHeader.ID}}\" [class.est-no-border]=\"true\" [class.est-nowrap]=\"!rowHeader.Wrap\" class=\"{{rowHeader.Class || ''}}\" [Order]=\"rowHeader.Order\" [Resizable]=\"ColumnsResizable\" [Orderable]=\"rowHeader.Orderable\" [OrderBy]=\"OrderByColumn\" [SearchInProgress]=\"!!researchInProgress\" (onOrderChange)=\"OrderByColumn && thOrderChanged(rowHeader.ID, $event)\">\r\n <ng-container *ngIf=\"rowHeader.Template\"><ng-container *ngTemplateOutlet=\"rowHeader.Template;\"></ng-container></ng-container>\r\n <span *ngIf=\"!rowHeader.Template\">{{rowHeader.Content}}</span>\r\n </th>\r\n </ng-container>\r\n </div>\r\n </th>\r\n <ng-container *ngFor=\"let rowHeader of RowTHs\">\r\n <th *ngIf=\"rowHeader && rowHeader.Visible && !rowHeader.Pinned\" es-th=\"{{rowHeader.ID}}\" [class.est-ltab-border]=\"rowHeader.LeftBorder\" [class.est-rtab-border]=\"rowHeader.RightBorder\" [class.est-nowrap]=\"!rowHeader.Wrap\" class=\"{{rowHeader.Class || ''}}\" [Order]=\"rowHeader.Order\" [Resizable]=\"ColumnsResizable\" [Orderable]=\"rowHeader.Orderable\" [OrderBy]=\"OrderByColumn\" [SearchInProgress]=\"!!researchInProgress\" (onOrderChange)=\"OrderByColumn && thOrderChanged(rowHeader.ID, $event)\">\r\n <ng-container *ngIf=\"rowHeader.Template\"><ng-container *ngTemplateOutlet=\"rowHeader.Template;\"></ng-container></ng-container>\r\n <span *ngIf=\"!rowHeader.Template\">{{rowHeader.Content}}</span>\r\n </th>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <!--Casistica in cui ho il setup proveniente da un report. Gli header sono definiti da come \u00E8 fatto il report-->\r\n <ng-container *ngIf=\"reportMode\">\r\n <th [style.color]=\"clm.color\" *ngFor=\"let clm of ReportValues.columns\" class=\"est-no-selection est-pointer est-nowrap\" (click)=\"setupNextOrderAndSearch(clm)\">\r\n {{clm.description}}<span class=\"fa\" [class.fa-chevron-down]=\"clm.order == 'DESC'\" [class.fa-chevron-up]=\"clm.order == 'ASC'\"></span>\r\n </th>\r\n </ng-container>\r\n\r\n <!--Per l'eliminazione mi serve un header aggiuntivo-->\r\n <th *ngIf=\"Removal\" [class.est-right-10]=\"Export || HiddenColumns\" class=\"est-col-min est-sticky-last-column\"><span class=\"fa fa-trash\"></span></th>\r\n\r\n <!--Per l'esportazione mi serve l'header extra da cui faccio uscire i 3 pallocchi-->\r\n <th *ngIf=\"Export || HiddenColumns || ColumnsOrdering || CornerMenuOptions\" class=\"est-table-dotted-menu est-sticky-last-column est-col-min text-sm-center\">\r\n \r\n <!-- Link nascosto che serve a scaricare il file -->\r\n <a *ngIf=\"headers\" hidden #exportDownloader csvLink [data]=\"data\" [headers]=\"headers\" [delimiter]=\"';'\" [filename]=\"ExportFileName\"></a>\r\n\r\n <!-- Blocco con i 3 pallocchi che tira fuori il context menu delle operazioni -->\r\n <div class=\"btn-group\" container=\"body\" placement=\"bottom right\" dropdown #dropdown=\"bs-dropdown\" [autoClose]=\"true\">\r\n <span dropdownToggle class=\"fa fa-ellipsis-v est-fs-18 est-pointer est-padding-3\"></span>\r\n\r\n <div *dropdownMenu class=\"dropdown-menu dropdown-menu-right est-bring-to-front-strong\">\r\n <div class=\"est-pointer\">\r\n <a class=\"dropdown-item\" *ngIf=\"HiddenColumns || ColumnsOrdering\" (click)=\"resetColumnVisSelection(); changeColumnVisibilityModal.show();\">\r\n <ng-container *ngIf=\"!HiddenColumns && ColumnsOrdering\">\r\n {{'Columns Order' | localize : lc}}\r\n </ng-container>\r\n <ng-container *ngIf=\"HiddenColumns && !ColumnsOrdering\">\r\n {{'Columns Visibility' | localize : lc}}\r\n </ng-container>\r\n <ng-container *ngIf=\"HiddenColumns && ColumnsOrdering\">\r\n {{'Columns Visibility and Order' | localize : lc}}\r\n </ng-container>\r\n </a>\r\n <a class=\"dropdown-item\" *ngIf=\"Export && CSVExport\" (click)=\"tryExport('CSV')\">{{'Export View' | localize : lc}} (CSV)</a>\r\n <a class=\"dropdown-item\" *ngIf=\"Export && XLSXExport\" (click)=\"tryExport('XLSX')\">{{'Export View' | localize : lc}} (XLSX)</a>\r\n <a class=\"dropdown-item\" *ngFor=\"let option of CornerMenuOptions\" (click)=\"cornerActionClicked(option.id)\">{{option.description}}</a>\r\n </div>\r\n </div>\r\n </div>\r\n </th>\r\n </tr>\r\n </thead>\r\n \r\n <!-- Valido per modalit\u00E0 View o Array. Se sono in report mode il body \u00E8 creato in altro modo -->\r\n <tbody [hidden]=\"BodyHidden || FirstBind\" *ngIf=\"(arrayMode || viewMode)\">\r\n <!--Con selection attiva richiamo il template che gestisce il context menu-->\r\n <ng-container *ngIf=\"Selection\">\r\n <ng-container *ngTemplateOutlet=\"TBodySelection; context: { $implicit: { selDisabled: arrayMode ? false : SelectionDisabled, sel: Selection }}\"></ng-container>\r\n </ng-container>\r\n\r\n <!--Senza selection richiamo il template che NON gestisce il context menu-->\r\n <ng-container *ngIf=\"!Selection\">\r\n <ng-container *ngTemplateOutlet=\"TBody\"></ng-container>\r\n </ng-container>\r\n </tbody>\r\n\r\n <!-- Per la modalit\u00E0 a report c'\u00E8 un body particolare semi-dinamico -->\r\n <tbody [hidden]=\"BodyHidden\" *ngIf=\"reportMode\">\r\n <tr *ngFor=\"let row of ReportValues.rows; let even = even;\">\r\n <td class=\"est-nowrap\" *ngFor=\"let val of row.values\">{{val}}</td>\r\n <td class=\"est-sticky-last-column{{even && !Hierarchy ? '-alt' : ''}}\"></td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <div *ngIf=\"PagingStyle == 'both' || PagingStyle == 'bottom'\">\r\n <ng-container *ngTemplateOutlet=\"pagingElement\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<!-- Template che contiene tutte le info di paginazione in modo da poterlo replicare anche sopra -->\r\n<ng-template #pagingElement>\r\n <ng-container *ngIf=\"!FirstBind\">\r\n <!-- Pulsanti avanti-indietro di paginazione -->\r\n <div *ngIf=\"PagerOptions.ShowPaging && !HidePagingButtons\" class=\"pull-right btn-toolbar\">\r\n <ng-container *ngIf=\"(!reportMode || View?.pagingavailable) && (!arrayMode || SearchView)\">\r\n <ng-container *ngTemplateOutlet=\"pagingButtons; context: { $implicit: { ATP: addToPage.bind(this), GTP: goToPage.bind(this), Array: arrayPulsanti }}\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"arrayMode && UseArrayModePaging && !SearchView\">\r\n <ng-container *ngTemplateOutlet=\"pagingButtons; context: { $implicit: { ATP: arrayAddToPage.bind(this), GTP: arrayGoToPage.bind(this), Array: arrayPulsanti }}\"></ng-container>\r\n </ng-container>\r\n </div>\r\n <!-- Paginatore dove appare la count e le opzioni di paginazione -->\r\n <div class=\"pull-right m-t-min-3 est-margin-right-50\">\r\n <div *ngIf=\"PagerOptions.ShowPaging && (PagerOptions.PagerCount > 10 || reportMode && View.pagingavailable)\">\r\n <app-paging *ngIf=\"!PagerOptions.UsesView\" [ShowCount]=\"PagerOptions.ShowCount\" [PagerCount]=\"PagerOptions.PagerCount\" [WarnOnAll]=\"false\" [CurrentPageSize]=\"ArraymodeItemsPerPage\" (pagingSelected)=\"refreshPaging($event)\"></app-paging>\r\n <app-paging *ngIf=\"PagerOptions.UsesView\" [ShowCount]=\"PagerOptions.ShowCount\" [PagerCount]=\"PagerOptions.PagerCount\" [GroupMode]=\"PagerOptions.Searches == 'groups'\" [AllSearch]=\"AllSearch\" [View]=\"PagerOptions.View\" (pagingSelected)=\"onItemsPerPageChanged($event);\"></app-paging>\r\n </div>\r\n <div *ngIf=\"reportMode && !PagerOptions.ShowPaging\"><em>{{'Paging options are not available for this report' | localize: lc}}</em></div>\r\n </div>\r\n <div class=\"clearfix\"></div>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<!-- Template che contiene i pulsanti per cambiare pagina -->\r\n<ng-template #pagingButtons let-options>\r\n <a class=\"btn\" class=\"est-page-prev app-pointer\" (click)=\"options.ATP(-1, options.separator)\">\r\n <span class=\"fa fa-chevron-left\"></span>\r\n </a>\r\n <div *ngIf=\"options.Array\" class=\"est-inline\">\r\n <a *ngFor=\"let p of options.Array\" class=\"est-page-sel\" class=\"btn {{p.cssClass}}\"\r\n (click)=\"options.GTP(p.val, options.separator)\">{{p.val}}</a>\r\n </div>\r\n <a class=\"btn\" class=\"est-page-next app-pointer\" (click)=\"options.ATP(1, options.separator)\">\r\n <span class=\"fa fa-chevron-right\"></span>\r\n </a>\r\n</ng-template>\r\n\r\n<!-- Questi due template rappresentano effettivamente il body della tabella. essendo il tr l'unica cosa che davvero cambia, il resto \u00E8 templatizzato -->\r\n<ng-template #TBodySelection let-templateOptions>\r\n <ng-container *ngFor=\"let item of boundSource; let even = even; let i=index;\">\r\n <tr *ngIf=\"item._visible || (!Hierarchy && !ArrayGrouping)\" \r\n [class]=\"item._rowClass ? item._rowClass : ''\" \r\n [class.est-line-through]=\"item.removed || item.deleted\" \r\n [class.est-pointer]=\"!item.locked\" \r\n [class.est-white-selected]=\"item._selected && !item.locked\"\r\n [class.est-rg]=\"item._group\"\r\n [class.est-rg-sep]=\"item._sep\"\r\n [contextMenu]=\"!item.locked ? (ContextMenu || emptyMenu) : emptyMenu\" [contextMenuSubject]=\"item\"\r\n (click)=\"(!item.locked && !item._sep && !item._group && handleClick($event, item)) || item._group && handleGroupClick(item)\">\r\n\r\n <td *ngIf=\"!item.locked && !item._sep && !HasPinnedColumns\">\r\n <input type=\"checkbox\" \r\n [disabled]=\"templateOptions.selDisabled\" \r\n [class.est-pointer]=\"!item.locked\"\r\n [(ngModel)]=\"item._selected\" name=\"check{{i}}\" \r\n (click)=\"$event.stopPropagation(); handleClick($event, item);\">\r\n </td>\r\n <td *ngIf=\"(item.locked || item._sep) && !HasPinnedColumns\"></td>\r\n\r\n <ng-container *ngIf=\"item._sep\"><ng-container *ngTemplateOutlet=\"groupPager; context: { $implicit: item }\"></ng-container> </ng-container>\r\n\r\n <ng-container *ngIf=\"!item._sep\">\r\n <ng-container *ngTemplateOutlet=\"basicColumns; context: { $implicit: item }\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"dynamicColumns; context: { $implicit: item }\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"customCells; context: { $implicit: item, templateOptions: templateOptions }\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngTemplateOutlet=\"bodyDeleteAndExport; context: { $implicit: { even: even, item: item }}\"></ng-container>\r\n </tr>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<ng-template #TBody>\r\n <ng-container *ngFor=\"let item of boundSource; let even = even;\">\r\n <tr *ngIf=\"item._visible || !Hierarchy\" \r\n [class]=\"item._rowClass ? item._rowClass : ''\" \r\n [class.est-line-through]=\"item.removed || item.deleted\"\r\n [class.est-rg]=\"item._group\"\r\n [class.est-rg-sep]=\"item._sep\"\r\n (click)=\"item._group && handleGroupClick(item)\">\r\n\r\n <ng-container *ngIf=\"item._sep\"><ng-container *ngTemplateOutlet=\"groupPager; context: { $implicit: item }\"></ng-container></ng-container>\r\n\r\n <ng-container *ngIf=\"!item._sep\">\r\n <ng-container *ngTemplateOutlet=\"basicColumns; context: { $implicit: item }\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"dynamicColumns; context: { $implicit: item }\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"customCells; context: { $implicit: item }\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngTemplateOutlet=\"bodyDeleteAndExport; context: { $implicit: { even: even, item: item }}\"></ng-container>\r\n </tr>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<ng-template #groupPager let-item>\r\n <td *ngIf=\"HasPinnedColumns\"></td>\r\n <td *ngIf=\"item._grouplevel > 1\" [attr.colspan]=\"item._grouplevel-1\"></td>\r\n <td [attr.colspan]=\"Columns.VisibleUnpinned - (item._grouplevel > 0 ? item._grouplevel - 1 : 0)\">\r\n <div class=\"est-rg-sep-flex-right\" *ngIf=\"RowGroupingPagingStyle == 'right'\">\r\n <div class=\"est-rg-page\"><ng-container *ngTemplateOutlet=\"pagingButtons; context: { $implicit: { separator: item, ATP: addToPageGroup.bind(this), GTP: goToPageGroup.bind(this), Array: item.buttons }}\"></ng-container></div>\r\n <div class=\"est-rg-ipp\"><app-paging [AllSearch]=\"AllSearch\" [GroupMode]=\"item.searches == 'groups'\" [PagerCount]=\"item.searches == 'groups' ? item.view.groupcount : item.view.objectcount\" [View]=\"item.view\" (pagingSelected)=\"onGroupItemsPerPageChanged(item, $event);\"></app-paging></div>\r\n </div>\r\n\r\n <div class=\"est-rg-sep-flex-left\" *ngIf=\"RowGroupingPagingStyle == 'left'\">\r\n <div class=\"est-rg-ipp\"><app-paging [AllSearch]=\"AllSearch\" [GroupMode]=\"item.searches == 'groups'\" [PagerCount]=\"item.searches == 'groups' ? item.view.groupcount : item.view.objectcount\" [View]=\"item.view\" (pagingSelected)=\"onGroupItemsPerPageChanged(item, $event);\"></app-paging></div>\r\n <div class=\"est-rg-page\"><ng-container *ngTemplateOutlet=\"pagingButtons; context: { $implicit: { separator: item, ATP: addToPageGroup.bind(this), GTP: goToPageGroup.bind(this), Array: item.buttons }}\"></ng-container></div>\r\n </div>\r\n </td>\r\n</ng-template>\r\n\r\n<!-- Questo template contiene la print condizionale su tabelle semplici, con header e body scritti a manazza -->\r\n<ng-template #basicColumns let-item>\r\n <ng-container *ngIf=\"(!UseCustomCells || !RowTDs) && !DynamicRowColumnsDefinition\">\r\n <ng-container *ngTemplateOutlet=\"bodyRef; context : {$implicit: item}\"></ng-container>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<!-- Questo template contiene la print condizionale su tabelle definite in maniera dinamica dal modello -->\r\n<ng-template #dynamicColumns let-item>\r\n <ng-container *ngIf=\"(!UseCustomCells || !RowTDs) && DynamicRowColumnsDefinition\">\r\n <ng-container *ngFor=\"let operation of DynamicOperations; let first = first; let last = last;\">\r\n <ng-container *ngIf=\"!operation.conditionField || (item.properties[operation.conditionField] == operation.conditionValue)\">\r\n <td [class.est-no-right-padding]=\"last\" [class.est-no-left-padding]=\"!first\" class=\"est-col-min\"><span title=\"{{operation.title}}\" class=\"{{operation.iconClass}} est-pointer\" (click)=\"dynamicOperation(item, operation.id)\">{{operation.text}}</span></td>\r\n </ng-container>\r\n <ng-container *ngIf=\"operation.conditionField && (item.properties[operation.conditionField] != operation.conditionValue)\">\r\n <td class=\"est-col-min est-no-side-padding\"></td>\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngFor=\"let rowItem of DynamicRowColumnsDefinition\">\r\n <ng-container *ngIf=\"rowItem.routePath && rowItem.visible\">\r\n <td es-td=\"{{rowItem.propertyName}}\" class=\"{{UserDefinedDynamicCols ? rowItem.clss : 'est-nowrap'}}\" [Internal]=\"false\" [Context]=\"item._hash\">\r\n <a [routerLink]=\"generateRouterLink(rowItem.routePath, rowItem.routeParameterProperties, item)\" class=\"est-link\" [innerHTML]=\"item.properties[rowItem.propertyName]\"></a>\r\n </td>\r\n </ng-container>\r\n <ng-container *ngIf=\"!rowItem.routePath && rowItem.visible\">\r\n <ng-container *ngTemplateOutlet=\"findEsTd(rowItem.propertyName) || defaultEsTd; context: { $implicit: item.properties[rowItem.propertyName], rowItem : rowItem, item : item }\"> </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<ng-template #defaultEsTd let-value let-rowItem='rowItem' let-item='item'>\r\n <td es-td=\"{{rowItem.propertyName}}\" class=\"{{UserDefinedDynamicCols ? rowItem.clss : 'est-nowrap'}}\"\r\n [class.est-pointer]=\"UseCustomCellActions && CustomCellActionsOn.indexOf('$' + rowItem.propertyName + '$') != -1\"\r\n (click)=\"cellClicked(rowItem.propertyName, item) && !CellActionPropagates && $event.stopPropagation()\"\r\n [Internal]=\"false\" [Context]=\"item._hash\">\r\n {{value}}\r\n </td>\r\n</ng-template>\r\n\r\n<!-- Questo template contiene la print condizionale delle celle custom se configurate -->\r\n<ng-template #customCells let-item let-opt=\"templateOptions\">\r\n <ng-container *ngIf=\"UseCustomCells && RowTDs\">\r\n\r\n <td *ngIf=\"HasPinnedColumns\" class=\"est-pinned-body est-col-min\" [class.est-white-selected]=\"item._selected\">\r\n <div [style.width.px]=\"PinnedContainerWidth\" class=\"est-pinned-border\">\r\n <td *ngIf=\"!item.locked && !item._sep && Selection\" class=\"est-no-border est-col-min\">\r\n <input type=\"checkbox\" [disabled]=\"opt.selDisabled\" [class.est-pointer]=\"!item.locked\" [(ngModel)]=\"item._selected\" name=\"check{{item._hash}}\" (click)=\"$event.stopPropagation(); handleClick($event, item);\">\r\n </td>\r\n <td class=\"est-no-border est-col-min\" *ngIf=\"(item.locked || item._sep) && Selection\"></td>\r\n\r\n <ng-container *ngFor=\"let rowItem of RowTDs[item._hash]; let i = index\">\r\n <td *ngIf=\"rowItem && rowItem.Pinned\" [style.width.px]=\"rowItem.PinnedWidth\" es-td=\"{{rowItem.ID}}\" class=\"{{rowItem.Class}}\" [class.est-no-border]=\"true\" [class.est-rg-hdr]=\"rowItem.GroupHeader\" [class.est-rg-agg]=\"rowItem.GroupAggregation\" \r\n [class.est-nowrap]=\"Hierarchy || !rowItem.Wraps\" [Internal]=\"true\">\r\n <ng-container *ngIf=\"Hierarchy && i == 0\"><ng-container *ngTemplateOutlet=\"HierarchyNavigator; context: { $implicit: item }\"></ng-container></ng-container>\r\n <ng-container *ngIf=\"rowItem.Template\"><ng-container *ngTemplateOutlet=\"rowItem.Template; context: { $implicit: item }\"></ng-container></ng-container>\r\n <span *ngIf=\"!rowItem.Template\">{{rowItem.Content}}</span>\r\n </td>\r\n </ng-container>\r\n </div>\r\n </td>\r\n\r\n <ng-container *ngFor=\"let rowItem of RowTDs[item._hash]; let i = index\">\r\n <ng-container *ngIf=\"rowItem && !rowItem.Pinned\">\r\n\r\n <!-- Casistica senza bodyRef, quindi con direttive per i td -->\r\n <ng-container *ngIf=\"!bodyRef && rowItem.Visible\">\r\n <td es-td=\"{{rowItem.ID}}\" class=\"{{rowItem.Class}}\" [class.est-ltab-border]=\"rowItem.LeftBorder\" [class.est-rtab-border]=\"rowItem.RightBorder\" [class.est-rg-hdr]=\"rowItem.GroupHeader\" [class.est-rg-agg]=\"rowItem.GroupAggregation\" \r\n [class.est-nowrap]=\"Hierarchy || !rowItem.Wraps\" [Internal]=\"true\">\r\n <ng-container *ngIf=\"Hierarchy && i == 0\"><ng-container *ngTemplateOutlet=\"HierarchyNavigator; context: { $implicit: item }\"></ng-container></ng-container>\r\n <ng-container *ngIf=\"rowItem.Template\"><ng-container *ngTemplateOutlet=\"rowItem.Template; context: { $implicit: item }\"></ng-container></ng-container>\r\n <span *ngIf=\"!rowItem.Template\">{{rowItem.Content}}</span>\r\n </td>\r\n </ng-container>\r\n\r\n <!-- Casistica bodyRef, quindi con componenti per i td (RouterLink) DEPRECATO -->\r\n <ng-container *ngIf=\"rowItem.RouterLink && rowItem.Visible && bodyRef\">\r\n <td es-td=\"{{rowItem.ID}}\" class=\"{{rowItem.Class}}\" [class.est-nowrap]=\"Hierarchy || !rowItem.Wraps\" [Internal]=\"true\">\r\n <ng-container *ngIf=\"Hierarchy && i == 0\">\r\n <ng-container *ngTemplateOutlet=\"HierarchyNavigator; context: { $implicit: item }\"></ng-container>\r\n </ng-container>\r\n <a [routerLink]='rowItem.RouterLink' class=\"est-link\" [innerHTML]=\"rowItem.Content\"></a>\r\n </td>\r\n </ng-container>\r\n\r\n <!-- Casistica bodyRef, quindi con componenti per i td (NON RouterLink) DEPRECATO -->\r\n <ng-container *ngIf=\"!rowItem.RouterLink && rowItem.Visible && bodyRef\">\r\n <td es-td=\"{{rowItem.ID}}\" class=\"{{rowItem.Class}}\" [class.est-nowrap]=\"Hierarchy || !rowItem.Wraps\" [class.est-pointer]=\"UseCustomCellActions && CustomCellActionsOn.indexOf('$' + $any(rowItem).ID + '$') != -1\" (click)=\"cellClicked(rowItem.ID, item) && !CellActionPropagates && $event.stopPropagation()\" [Internal]=\"true\">\r\n <ng-container *ngIf=\"Hierarchy && i == 0\">\r\n <ng-container *ngTemplateOutlet=\"HierarchyNavigator; context: { $implicit: item }\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"rowItem.Template\">\r\n <ng-container *ngTemplateOutlet=\"rowItem.Template; context: { $implicit: item }\"></ng-container>\r\n </ng-container>\r\n <span *ngIf=\"!rowItem.Template\" [innerHTML]=\"rowItem.Content\"></span>\r\n </td>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<ng-template #HierarchyNavigator let-item>\r\n <span *ngIf=\"!item.parent\" class=\"fa fa-chevron-down\" style=\"visibility:hidden\"></span>\r\n <span *ngIf=\"item.parent && item._expanded\" class=\"fa fa-chevron-down est-pointer est-no-selection\" (click)=\"collapseParent(item[this.OwnKey])\"></span>\r\n <span *ngIf=\"item.parent && !item._expanded\" class=\"fa fa-chevron-up est-pointer est-no-selection\" (click)=\"expandParent(item[this.OwnKey])\"></span>\r\n &nbsp;\r\n</ng-template>\r\n\r\n<!-- Questo template contiene i pulsanti di eliminazione/undo eliminazione ed esportazione che vanno in fondo ad un record edlla tabella -->\r\n<ng-template #bodyDeleteAndExport let-options>\r\n <ng-container *ngIf=\"Removal && !RemovalCondition\">\r\n <td class=\"est-sticky-last-column{{options.even? '-alt' : ''}} {{Export || HiddenColumns || CornerMenuOptions ? 'est-right-10' : ''}}\" *ngIf=\"!(options.item.removed || options.item.deleted)\"><span class=\"fa fa-remove est-pointer text-danger\" [hidden]=\"options.item.removable != undefined && !options.item.removable\" (click)=\"onRemoval.emit(options.item)\"></span></td>\r\n <td class=\"est-sticky-last-column{{options.even? '-alt' : ''}} {{Export || HiddenColumns || CornerMenuOptions ? 'est-right-10' : ''}}\" *ngIf=\"(options.item.removed || options.item.deleted)\"><span class=\"fa fa-undo text-warning est-pointer\" (click)=\"onAbortRemoval.emit(options.item)\"></span></td>\r\n </ng-container>\r\n <ng-container *ngIf=\"Removal && RemovalCondition\">\r\n <td class=\"est-sticky-last-column{{options.even? '-alt' : ''}} {{Export || HiddenColumns || CornerMenuOptions ? 'est-right-10' : ''}}\" *ngIf=\"!(options.item.removed || options.item.deleted) && options.item[RemovalCondition]\"><span class=\"fa fa-remove est-pointer text-danger\" [hidden]=\"options.item.removable != undefined && !options.item.removable\" (click)=\"onRemoval.emit(options.item)\"></span></td>\r\n <td class=\"est-sticky-last-column{{options.even? '-alt' : ''}} {{Export || HiddenColumns || CornerMenuOptions ? 'est-right-10' : ''}}\" *ngIf=\"(options.item.removed || options.item.deleted) && options.item[RemovalCondition]\"><span class=\"fa fa-undo text-warning est-pointer\" (click)=\"onAbortRemoval.emit(options.item)\"></span></td>\r\n <td class=\"est-sticky-last-column{{options.even? '-alt' : ''}} {{Export || HiddenColumns || CornerMenuOptions ? 'est-right-10' : ''}}\" *ngIf=\"!options.item[RemovalCondition]\"><span class=\"fa fa-remove est-hidden-view\"></span></td>\r\n </ng-container>\r\n <td *ngIf=\"Export || HiddenColumns || CornerMenuOptions\" class=\"est-sticky-last-column{{options.even && !Hierarchy ? '-alt' : ''}}\"></td>\r\n</ng-template>\r\n\r\n<!-- Context menu vuoto default per tutte le tabella che non ce l'hanno, in modo che al click destro appaia \"nessuna op disponibile\" -->\r\n<context-menu #emptyMenu>\r\n <ng-template contextMenuItem>\r\n <span>\r\n <em>{{'No operations available' | localize : lc}}...</em>\r\n </span>\r\n </ng-template>\r\n</context-menu>\r\n\r\n<!-- Modal per cambiare posizione e visibilit\u00E0 delle colonne dell'es-table -->\r\n<div bsModal #changeColumnVisibilityModal=\"bs-modal\" class=\"modal fade\" role=\"dialog\" aria-hidden=\"true\">\r\n <div class=\"modal-dialog modal-lg\">\r\n <div class=\"modal-content\">\r\n <div class=\"modal-header\">\r\n <h5 class=\"modal-title pull-left\">\r\n <ng-container *ngIf=\"!HiddenColumns && ColumnsOrdering\">\r\n {{'Columns Order' | localize : lc}}\r\n </ng-container>\r\n <ng-container *ngIf=\"HiddenColumns && !ColumnsOrdering\">\r\n {{'Columns Visibility' | localize : lc}}\r\n </ng-container>\r\n <ng-container *ngIf=\"HiddenColumns && ColumnsOrdering\">\r\n {{'Columns Visibility and Order' | localize : lc}}\r\n </ng-container>\r\n </h5>\r\n <button type=\"button\" class=\"close pull-right\" (click)=\"changeColumnVisibilityModal.hide();\" aria-label=\"Close\">\r\n <span aria-hidden=\"true\">&times;</span>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n <div *ngIf=\"!TMPColumnsList || TMPColumnsList.length == 0\" class=\"card card-info est-padding-10 est-margin-bottom-0\">\r\n {{'There are no columns configured to be hidden/shown in this view' | localize : lc}}\r\n </div>\r\n <div *ngIf=\"TMPColumnsList && TMPColumnsList.length > 0\" style=\"max-height:500px; overflow-y:auto\">\r\n <!--Aaaaaaah la tristezza... qui mi servirebbe l'es-table per facilitare la selezione multipla ecc... peccato che se la linko qui entro in un loop impressionante-->\r\n <table class=\"table table-striped table-sm est-margin-bottom-0\">\r\n <thead>\r\n <tr>\r\n <th class=\"est-col-min\" *ngIf=\"HiddenColumns\">\r\n <input class=\"est-pointer\" type=\"checkbox\" [(ngModel)]=\"globalColVisCheck\" [ngModelOptions]=\"{'standalone': true}\" (ngModelChange)=\"globalColVisCheckChanged();\">\r\n </th>\r\n <th class=\"est-col-min\" *ngIf=\"ColumnsOrdering\"></th>\r\n <th class=\"est-col-min est-nowrap\">{{'Column Name' | localize : lc}}</th>\r\n <!--Filler-->\r\n <th></th>\r\n <!-- Pinner -->\r\n <th class=\"est-col-min\"></th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let item of TMPColumnsList; let i = index; let last = last\" class=\"est-pointer\" [class.est-white-selected]=\"lastSelectedItemID == item.id\" [class.est-no-selection]=\"!item.visible\">\r\n <td *ngIf=\"HiddenColumns\">\r\n <input type=\"checkbox\" [class.est-hidden-view]=\"item.fixed\" class=\"est-pointer\" [(ngModel)]=\"item.visible\" name=\"visible{{i}}\" (ngModelChange)=\"updateGlobalColVisCheck();\" />\r\n </td>\r\n <td class=\"est-nowrap\" *ngIf=\"ColumnsOrdering\">\r\n <span class=\"fa fa-arrow-up\" [class.est-hidden-view]=\"item.fixed || item.pinned\" (click)=\"lastSelectedItemID = item.id; i != 0 && !item.fixed && sendUp(item); $event.stopPropagation();\"></span>\r\n <span class=\"fa fa-arrow-down\" [class.est-hidden-view]=\"item.fixed || item.pinned\" (click)=\"lastSelectedItemID = item.id; !last && !item.fixed && sendDown(item); $event.stopPropagation();\"></span>\r\n </td>\r\n <td class=\"est-nowrap\" (click)=\"columnClicked(item);\">\r\n <ng-container *ngIf=\"item.template\">\r\n <ng-container *ngTemplateOutlet=\"item.template\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"!item.template\">{{item.description}}</ng-container>\r\n </td>\r\n <!--Filler-->\r\n <td (click)=\"columnClicked(item);\"></td>\r\n <!-- Pinner -->\r\n <td><span *ngIf=\"!item.fixed\" class=\"fa fa-thumb-tack\" [class.text-success]=\"item.pinned\" (click)=\"pinOrUnpinColumn(item)\"></span></td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n <div class=\"modal-footer\">\r\n <button type=\"button\" class=\"btn btn-secondary est-margin-right-10\" (click)=\"lastSelectedItemID = null; changeColumnVisibilityModal.hide();\">{{'Close' | localize : lc}}</button>\r\n <button type=\"button\" [disabled]=\"!TMPColumnsList || TMPColumnsList.length == 0\" class=\"btn btn-primary\" (click)=\"confirmColumnVisibilitySelection() && changeColumnVisibilityModal.hide()\">{{'Confirm' | localize : lc}}</button>\r\n </div>\r\n </div>\r\n </div>\r\n</div>",
3360
- styles: [".est-loading-box{height:200px;text-align:center;position:relative;background:#ccc}.est-loading-content{margin:0;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:35px}.est-scrollable{max-height:600px;overflow:auto}.est-pointer{cursor:pointer}.est-high-density td,.est-high-density th{padding:0 .2rem}.est-no-selection{-webkit-user-select:none;-moz-user-select:none;-khtml-user-select:none;-ms-user-select:none}.est-hidden-view{visibility:hidden}.est-no-border{border:none!important}.est-nowrap{white-space:nowrap}.est-white-selected{background-color:#ddd!important}.est-line-through{text-decoration:line-through}.est-no-side-padding{padding-left:0;padding-right:0}.est-no-left-padding,.est-no-right-padding{padding-left:0}.est-col-min{width:1px}.est-margin-bottom-0{margin-bottom:0!important}.est-margin-right-10{margin-right:10px!important}.est-right-10{right:10px!important}.est-table-dotted-menu{padding:0 0 2px!important;color:#999}.est-fs-18{font-size:18px}.est-fs-14{font-size:14px}.est-padding-3{padding:3px!important}.est-page-container{position:relative}.est-bring-to-front-strong{z-index:99999999!important}.est-switch{position:relative;display:inline-block;width:30px;height:17px;margin-bottom:0;margin-right:5px;margin-left:5px}.est-switch input{display:none}.est-slider{cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc}.est-slider,.est-slider:before{position:absolute;transition:.4s}.est-slider:before{content:\"\";height:13px;width:13px;left:3px;bottom:2px;background-color:#fff}input:checked+.est-slider{background-color:#2196f3}input:focus+.est-slider{box-shadow:0 0 1px #2196f3}input:checked+.est-slider:before{transform:translateX(11px)}.est-slider.round{border-radius:10px}.est-slider.round:before{border-radius:50%}.est-custom-input{width:30px;display:inline;padding:1px;height:20px}.est-row-lvl-1 td:first-child{padding-left:5px}.est-row-lvl-2 td:first-child{padding-left:20px}.est-row-lvl-3 td:first-child{padding-left:35px}.est-row-lvl-4 td:first-child{padding-left:50px}.est-row-lvl-5 td:first-child{padding-left:65px}.est-row-lvl-6 td:first-child{padding-left:80px}.est-row-lvl-7 td:first-child{padding-left:95px}.est-row-lvl-8 td:first-child{padding-left:110px}.est-row-lvl-9 td:first-child{padding-left:125px}.est-row-lvl-10 td:first-child{padding-left:140px}.est-row-lvl-11 td:first-child{padding-left:155px}.est-row-lvl-12 td:first-child{padding-left:170px}.est-row-lvl-13 td:first-child{padding-left:185px}.est-row-lvl-14 td:first-child{padding-left:200px}.est-row-lvl-15 td:first-child{padding-left:215px}.est-row-lvl-16 td:first-child{padding-left:230px}.est-row-lvl-17 td:first-child{padding-left:245px}.est-row-lvl-18 td:first-child{padding-left:260px}.est-row-lvl-19 td:first-child{padding-left:275px}.est-row-lvl-20 td:first-child{padding-left:290px}.est-row-lvl-21 td:first-child{padding-left:305px}.est-row-lvl-22 td:first-child{padding-left:320px}.est-row-lvl-23 td:first-child{padding-left:335px}.est-row-lvl-24 td:first-child{padding-left:350px}.est-row-lvl-25 td:first-child{padding-left:365px}.est-row-lvl-26 td:first-child{padding-left:380px}.est-row-lvl-27 td:first-child{padding-left:395px}.est-row-lvl-28 td:first-child{padding-left:410px}.est-row-lvl-29 td:first-child{padding-left:425px}.est-row-lvl-30 td:first-child{padding-left:440px}.est-row-lvl-31 td:first-child{padding-left:455px}.est-row-lvl-32 td:first-child{padding-left:470px}.est-row-lvl-33 td:first-child{padding-left:485px}.est-row-lvl-34 td:first-child{padding-left:500px}.est-row-lvl-35 td:first-child{padding-left:515px}.est-row-lvl-36 td:first-child{padding-left:530px}.est-row-lvl-37 td:first-child{padding-left:545px}.est-row-lvl-38 td:first-child{padding-left:560px}.est-row-lvl-39 td:first-child{padding-left:575px}.est-row-lvl-40 td:first-child{padding-left:590px}.est-row-lvl-41 td:first-child{padding-left:605px}.est-row-lvl-42 td:first-child{padding-left:620px}.est-row-lvl-43 td:first-child{padding-left:635px}.est-row-lvl-44 td:first-child{padding-left:650px}.est-row-lvl-45 td:first-child{padding-left:665px}.est-row-lvl-46 td:first-child{padding-left:680px}.est-row-lvl-47 td:first-child{padding-left:695px}.est-row-lvl-48 td:first-child{padding-left:710px}.est-row-lvl-49 td:first-child{padding-left:725px}.est-row-lvl-50 td:first-child{padding-left:740px}.est-row-lvl-51 td:first-child{padding-left:755px}.est-row-lvl-52 td:first-child{padding-left:770px}.est-row-lvl-53 td:first-child{padding-left:785px}.est-row-lvl-54 td:first-child{padding-left:800px}.est-row-lvl-55 td:first-child{padding-left:815px}.est-row-lvl-56 td:first-child{padding-left:830px}.est-row-lvl-57 td:first-child{padding-left:845px}.est-row-lvl-58 td:first-child{padding-left:860px}.est-row-lvl-59 td:first-child{padding-left:875px}.est-row-lvl-60 td:first-child{padding-left:890px}.est-row-lvl-61 td:first-child{padding-left:905px}.est-row-lvl-62 td:first-child{padding-left:920px}.est-row-lvl-63 td:first-child{padding-left:935px}.est-row-lvl-64 td:first-child{padding-left:950px}.est-row-lvl-65 td:first-child{padding-left:965px}.est-row-lvl-66 td:first-child{padding-left:980px}.est-row-lvl-67 td:first-child{padding-left:995px}.est-row-lvl-68 td:first-child{padding-left:1010px}.est-row-lvl-69 td:first-child{padding-left:1025px}.est-row-lvl-70 td:first-child{padding-left:1040px}.est-row-lvl-71 td:first-child{padding-left:1055px}.est-row-lvl-72 td:first-child{padding-left:1070px}.est-row-lvl-73 td:first-child{padding-left:1085px}.est-row-lvl-74 td:first-child{padding-left:1100px}.est-row-lvl-75 td:first-child{padding-left:1115px}.est-row-lvl-76 td:first-child{padding-left:1130px}.est-row-lvl-77 td:first-child{padding-left:1145px}.est-row-lvl-78 td:first-child{padding-left:1160px}.est-row-lvl-79 td:first-child{padding-left:1175px}.est-row-lvl-80 td:first-child{padding-left:1190px}.est-row-lvl-81 td:first-child{padding-left:1205px}.est-row-lvl-82 td:first-child{padding-left:1220px}.est-row-lvl-83 td:first-child{padding-left:1235px}.est-row-lvl-84 td:first-child{padding-left:1250px}.est-row-lvl-85 td:first-child{padding-left:1265px}.est-row-lvl-86 td:first-child{padding-left:1280px}.est-row-lvl-87 td:first-child{padding-left:1295px}.est-row-lvl-88 td:first-child{padding-left:1310px}.est-row-lvl-89 td:first-child{padding-left:1325px}.est-row-lvl-90 td:first-child{padding-left:1340px}.est-row-lvl-91 td:first-child{padding-left:1355px}.est-row-lvl-92 td:first-child{padding-left:1370px}.est-row-lvl-93 td:first-child{padding-left:1385px}.est-row-lvl-94 td:first-child{padding-left:1400px}.est-row-lvl-95 td:first-child{padding-left:1415px}.est-row-lvl-96 td:first-child{padding-left:1430px}.est-row-lvl-97 td:first-child{padding-left:1445px}.est-row-lvl-98 td:first-child{padding-left:1460px}.est-row-lvl-99 td:first-child{padding-left:1475px}.est-right-10{right:10px}.est-hidden{visibility:hidden}.est-padding-10{padding:10px!important}.est-margin-right-50{margin-right:50px}.est-page-sel{color:#000;margin-left:3px;margin-right:3px;padding:0 5px;font-size:inherit}.est-page-next,.est-page-prev{color:#000;font-size:inherit;padding:3px 0 0}.est-pinned-header{background-color:#fff;left:0;top:0;position:sticky;z-index:1;border-bottom:1px solid #dee2e6!important;padding:0!important}.est-pinned-border{border-right:2px solid #dee2e6!important}.est-cell-padding{padding:.3rem}.est-pinned-body{background-color:#fff;left:0;position:sticky;z-index:1;border-top:1px solid #dee2e6!important;padding:0!important}.est-inline{display:inline!important}.est-inline-block{display:inline-block!important}.est-link{color:#0275d8!important;cursor:pointer;text-decoration:none;display:block}.est-link:hover{color:#23527c!important;cursor:pointer;text-decoration:underline!important}.est-sticky-last-column{right:-1px;position:sticky;z-index:0;background-color:#fff}.est-sticky-last-column-alt{right:-1px;position:sticky;z-index:0;background-color:#f2f2f2}.est-ltab-border{border-left:2px solid #bbb}.est-rtab-border{border-right:2px solid #bbb}.est-cell-group-padding{padding:calc(.3rem + 1px);position:absolute;top:0;left:0;height:100%;width:100%}.est-margin-bottom-10{margin-bottom:10px}.est-text-center{text-align:center}.est-rg-sep-flex-right{display:flex;flex-direction:row-reverse;width:100%;margin:-5px}.est-rg-sep-flex-left{display:flex;flex-direction:row;width:100%;margin:-5px}.est-rg-hdr{font-weight:700}.est-rg-agg{font-style:italic}.est-rg{background-color:hsla(0,0%,46.7%,.4666666666666667)!important}.est-rg-sep{font-size:12px;padding-right:20px!important;background-color:hsla(0,0%,73.3%,.7333333333333333)!important}.est-rg-ipp{text-align:left;display:inline-flex;margin-right:25px}.est-rg-page{text-align:right;display:inline-flex;font-size:inherit;padding-top:5px}"]
3361
- },] }
3362
- ];
3363
- EsTableComponent.ctorParameters = () => [
3364
- { type: NgControl, decorators: [{ type: Self }, { type: Optional }] },
3365
- { type: PreferencesService, decorators: [{ type: Optional }] },
3366
- { type: EsTableDefaultable, decorators: [{ type: Optional }, { type: Inject, args: [EST_DEFAULTS,] }] },
3367
- { type: String, decorators: [{ type: Optional }, { type: Inject, args: [EST_LOCALE,] }] },
3368
- { type: LocalizationService },
3369
- { type: ChangeDetectorRef },
3370
- { type: HashingService },
3371
- { type: UtilityService },
3372
- { type: ExportService },
3373
- { type: DateService },
3374
- { type: MessageService }
3375
- ];
3376
- EsTableComponent.propDecorators = {
3377
- EsTdsDirective: [{ type: ContentChildren, args: [EsTdDirective,] }],
3378
- EsThsDirective: [{ type: ContentChildren, args: [EsThDirective,] }],
3379
- EsThs: [{ type: ContentChildren, args: [forwardRef(() => EsTh),] }],
3380
- EsTds: [{ type: ContentChildren, args: [forwardRef(() => EsTd),] }],
3381
- bodyRef: [{ type: ContentChild, args: ['body', { static: false },] }],
3382
- headerRef: [{ type: ContentChild, args: ['header', { static: false },] }],
3383
- headerGroupRef: [{ type: ContentChild, args: ['headerGroup', { static: false },] }],
3384
- secondaryHeaderGroupRef: [{ type: ContentChild, args: ['secondaryHeaderGroup', { static: false },] }],
3385
- CornerMenuOptions: [{ type: Input }],
3386
- ColumnsResizable: [{ type: Input }],
3387
- AutoUpdate: [{ type: Input }],
3388
- UseCustomCellActions: [{ type: Input }],
3389
- CustomCellActionsOn: [{ type: Input }],
3390
- CellActionPropagates: [{ type: Input }],
3391
- UseCustomCells: [{ type: Input }],
3392
- MaxHeight: [{ type: Input }],
3393
- ContainerClass: [{ type: Input }],
3394
- XLSXExport: [{ type: Input }],
3395
- CSVExport: [{ type: Input }],
3396
- AllSearch: [{ type: Input }],
3397
- HighCellDensity: [{ type: Input }],
3398
- Selection: [{ type: Input }],
3399
- ShowLoadingOnBootstrap: [{ type: Input }],
3400
- Removal: [{ type: Input }],
3401
- RemovalCondition: [{ type: Input }],
3402
- Export: [{ type: Input }],
3403
- ShiftClick: [{ type: Input }],
3404
- HidePaging: [{ type: Input }],
3405
- HidePagingCount: [{ type: Input }],
3406
- HidePagingButtons: [{ type: Input }],
3407
- ContextMenu: [{ type: Input }],
3408
- ExportFileName: [{ type: Input }],
3409
- TableClass: [{ type: Input }],
3410
- ExportFunction: [{ type: Input }],
3411
- HasHeaderGroup: [{ type: Input }],
3412
- HasSecondaryHeaderGroup: [{ type: Input }],
3413
- SliceSize: [{ type: Input }],
3414
- EndlessScroll: [{ type: Input }],
3415
- EndlessScrollOnlyForAll: [{ type: Input }],
3416
- HeaderHidden: [{ type: Input }],
3417
- BodyHidden: [{ type: Input }],
3418
- SelectionDisabled: [{ type: Input }],
3419
- SingleSelection: [{ type: Input }],
3420
- RowClassAssigner: [{ type: Input }],
3421
- OrderByColumn: [{ type: Input }],
3422
- MultipleOrderingDirectives: [{ type: Input }],
3423
- HiddenColumns: [{ type: Input }],
3424
- ColumnsOrdering: [{ type: Input }],
3425
- SearchView: [{ type: Input }],
3426
- SelectAll: [{ type: Input }],
3427
- UseArrayModePaging: [{ type: Input }],
3428
- DynamicRowColumnsDefinition: [{ type: Input }],
3429
- DynamicOperations: [{ type: Input }],
3430
- Hierarchy: [{ type: Input }],
3431
- ParentKey: [{ type: Input }],
3432
- OwnKey: [{ type: Input }],
3433
- StartsExpanded: [{ type: Input }],
3434
- SavePreferences: [{ type: Input }],
3435
- PagingStyle: [{ type: Input }],
3436
- RowGroupingPagingStyle: [{ type: Input }],
3437
- SecondarySource: [{ type: Input }],
3438
- TertiarySource: [{ type: Input }],
3439
- UseSelectionCache: [{ type: Input }],
3440
- ShowItemGroupsColumns: [{ type: Input }],
3441
- onOrderChanged: [{ type: Output }],
3442
- onSearchRequest: [{ type: Output }],
3443
- onSelectionChanged: [{ type: Output }],
3444
- onRemoval: [{ type: Output }],
3445
- onAbortRemoval: [{ type: Output }],
3446
- onCellClick: [{ type: Output }],
3447
- onCornerAction: [{ type: Output }],
3448
- onDynamicOperation: [{ type: Output }],
3449
- exportDownloader: [{ type: ViewChild, args: ['exportDownloader', { static: false },] }],
3450
- tableEmptyMenu: [{ type: ViewChild, args: ['emptyMenu', { static: true },] }],
3451
- ArraymodeItemsPerPage: [{ type: Input }]
3452
- };
3453
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXNfdGFibGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvZXMtdGFibGUvc3JjL2xpYi9lc190YWJsZS5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLFVBQVU7QUFDVixPQUFPLEVBQ0gsU0FBUyxFQUFFLFVBQVUsRUFBRSxlQUFlLEVBQWEsaUJBQWlCLEVBQUUsdUJBQXVCLEVBQUUsS0FBSyxFQUNwRyxZQUFZLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBNEIsU0FBUyxFQUFjLGlCQUFpQixFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQWUsTUFBTSxFQUM5SSxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQXdCLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRWpFLGlCQUFpQjtBQUNqQixPQUFPLEVBQUUsY0FBYyxFQUFFLGNBQWMsRUFBRSxhQUFhLEVBQUUsY0FBYyxFQUFFLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ2xILE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQzlELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBSzNELFVBQVU7QUFDVixPQUFPLEVBQ0gsU0FBUyxFQUFFLFdBQVcsRUFBZSx3QkFBd0IsRUFBb0IsZ0JBQWdCLEVBQWdCLFdBQVcsRUFDaEcsYUFBYSxFQUFFLGdCQUFnQixFQUFFLFVBQVUsRUFBRSxrQkFBa0IsRUFBRSxZQUFZLEVBQzVHLE1BQU0sVUFBVSxDQUFDO0FBRWxCLDhCQUE4QjtBQUM5QixPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDekMsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3pDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUM3RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1B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QUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sSUFBSSxFQUFFLENBQUMsT0FBTyxJQUFJLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO3dCQUMvRyxJQUFJLFNBQVMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7NEJBQ25CLEVBQUUsVUFBVSxFQUFRLFFBQVMsQ0FBQyxNQUFNLEVBQUUsV0FBVyxFQUFRLFFBQVMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsWUFBWSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsV0FBVyxFQUFFLFFBQVEsQ0FBQyxhQUFhLEVBQUUsV0FBVyxFQUFFLEtBQUssRUFBRSxnQkFBZ0IsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLFlBQVksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxPQUFPLEVBQUUsUUFBUSxFQUFFLFFBQVEsQ0FBQyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7NEJBQ25XLEVBQUUsVUFBVSxFQUFRLFFBQVMsQ0FBQyxNQUFNLEVBQUUsV0FBVyxFQUFRLFFBQVMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsWUFBWSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsV0FBVyxFQUFFLFFBQVEsQ0FBQyxhQUFhLEVBQUUsV0FBVyxFQUFFLFFBQVEsQ0FBQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsQ0FBQyxDQUFD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LEVBQUU7b0NBVXZDLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBBbmd1bGFyXHJcbmltcG9ydCB7XHJcbiAgICBDb21wb25lbnQsIGZvcndhcmRSZWYsIENvbnRlbnRDaGlsZHJlbiwgUXVlcnlMaXN0LCBDaGFuZ2VEZXRlY3RvclJlZiwgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIElucHV0LFxyXG4gICAgRXZlbnRFbWl0dGVyLCBPdXRwdXQsIENvbnRlbnRDaGlsZCwgT25DaGFuZ2VzLCBTaW1wbGVDaGFuZ2VzLCBWaWV3Q2hpbGQsIEVsZW1lbnRSZWYsIFZpZXdFbmNhcHN1bGF0aW9uLCBPcHRpb25hbCwgU2VsZiwgVGVtcGxhdGVSZWYsIEluamVjdFxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBDb250cm9sVmFsdWVBY2Nlc3NvciwgTmdDb250cm9sIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5cclxuLy8gQ29uZmlndXJhemlvbmlcclxuaW1wb3J0IHsgSGFzaGluZ1NlcnZpY2UsIFV0aWxpdHlTZXJ2aWNlLCBFeHBvcnRTZXJ2aWNlLCBNZXNzYWdlU2VydmljZSwgRGF0ZVNlcnZpY2UgfSBmcm9tICdAZXNmYWVuemEvZXh0ZW5zaW9ucyc7XHJcbmltcG9ydCB7IExvY2FsaXphdGlvblNlcnZpY2UgfSBmcm9tICdAZXNmYWVuemEvbG9jYWxpemF0aW9ucyc7XHJcbmltcG9ydCB7IFByZWZlcmVuY2VzU2VydmljZSB9IGZyb20gJ0Blc2ZhZW56YS9wcmVmZXJlbmNlcyc7XHJcblxyXG4vLyBQbHVnaW5zXHJcbmltcG9ydCB7IENvbnRleHRNZW51Q29tcG9uZW50IH0gZnJvbSAnQGVzZmFlbnphL25neC1jb250ZXh0bWVudSc7XHJcblxyXG4vLyBNb2RlbGxpXHJcbmltcG9ydCB7XHJcbiAgICBBcHBTZWFyY2gsIEFwcE9yZGVyaW5nLCBHZW5lcmljSXRlbSwgRXNUYWJsZUNvbHVtbnNEZWZpbml0aW9uLCBDb3JuZXJNZW51T3B0aW9uLCBSZXBvcnREZWZpbml0aW9uLCBSZXBvcnRSZXN1bHQsIFJlcG9ydE9yZGVyLCBSZXBvcnRDb2x1bW4sIFxyXG4gICAgRXNUYWJsZU9wZXJhdGlvbkRlZmluaXRpb24sIEVzVGFibGVDb2x1bW4sIEdyb3VwQWdncmVnYXRpb24sIEdyb3VwUGFnZXIsIEdyb3VwUm91dGVGcmFnbWVudCwgQ2FjaGVUcmlwdGljXHJcbn0gZnJvbSAnLi9kb21haW4nO1xyXG5cclxuLy8gQ29tcG9uZW50aSBlIExvY2FsaXp6YXppb25lXHJcbmltcG9ydCB7IEVzVGQgfSBmcm9tICcuL2VzX3RkLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IEVzVGggfSBmcm9tICcuL2VzX3RoLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IEVzVGREaXJlY3RpdmUgfSBmcm9tICcuL2RpcmVjdGl2ZXMvZXNfdGQuZGlyZWN0aXZlJztcclxuaW1wb3J0IHsgRXNUaERpcmVjdGl2ZSB9IGZyb20gJy4vZGlyZWN0aXZlcy9lc190aC5kaXJlY3RpdmUnO1xyXG5pbXBvcnQgeyBFc1RhYmxlTG9jIH0gZnJvbSAnLi9lc190YWJsZS5jb21wb25lbnQubG9jJztcclxuaW1wb3J0IHsgSXRlbXNTZWxlY3Rpb24gfSBmcm9tICcuL2RvbWFpbi9leHRlcm5hbHMvY2xhc3Nlcy9hcHBzZWFyY2gvSXRlbXNTZWxlY3Rpb24nO1xyXG5pbXBvcnQgeyBHcm91cE9yQWdncmVnYXRpb24gfSBmcm9tIFwiLi9kb21haW4vZXh0ZXJuYWxzL2NsYXNzZXMvYXBwc2VhcmNoL0dyb3VwT3JBZ2dyZWdhdGlvblwiO1xyXG5pbXBvcnQgeyBHcm91cEZpbHRlciB9IGZyb20gXCIuL2RvbWFpbi9leHRlcm5hbHMvY2xhc3Nlcy9hcHBzZWFyY2gvR3JvdXBGaWx0ZXJcIjtcclxuaW1wb3J0IHsgR3JvdXAgfSBmcm9tIFwiLi9kb21haW4vZXh0ZXJuYWxzL2NsYXNzZXMvYXBwc2VhcmNoL0dyb3VwXCI7XHJcbmltcG9ydCB7IFRoQWdncmVnYXRpb24gfSBmcm9tICcuL2RvbWFpbi9pbnRlcm5hbHMvY2xhc3Nlcy9UaEFnZ3JlZ2F0aW9uJztcclxuaW1wb3J0IHsgRXNUYWJsZURlZmF1bHRhYmxlIH0gZnJvbSAnLi9tb2RlbHMvRXNUYWJsZURlZmF1bHRhYmxlJztcclxuXHJcbmltcG9ydCB7IEVTVF9ERUZBVUxUUywgRVNUX0xPQ0FMRSB9IGZyb20gJy4vdG9rZW5zJztcclxuXHJcbi8qKiBDb21wb25lbnRlIGNoZSBwZXJtZXR0ZSBkaSByYXBwcmVzZW50YXJlIHVuYSBncmlnbGlhIGRpIHZhbG9yaSAqL1xyXG5AQ29tcG9uZW50KHtcclxuICAgIHNlbGVjdG9yOiAnZXMtdGFibGUnLFxyXG4gICAgdmlld1Byb3ZpZGVyczogW3sgcHJvdmlkZTogTG9jYWxpemF0aW9uU2VydmljZSwgdXNlQ2xhc3M6IEVzVGFibGVMb2MgfV0sXHJcbiAgICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcclxuICAgIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXHJcbiAgICBzdHlsZVVybHM6IFsnLi9lc190YWJsZS5jb21wb25lbnQuc2NzcyddLFxyXG4gICAgdGVtcGxhdGVVcmw6ICcuL2VzX3RhYmxlLmNvbXBvbmVudC5odG1sJ1xyXG59KVxyXG5leHBvcnQgY2xhc3MgRXNUYWJsZUNvbXBvbmVudCBpbXBsZW1lbnRzIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBPbkNoYW5nZXMge1xyXG5cclxuICAgIC8qKiBAaWdub3JlICovXHJcbiAgICBjb25zdHJ1Y3RvcihAU2VsZigpIEBPcHRpb25hbCgpIHB1YmxpYyBuZ0NvbnRyb2w6IE5nQ29udHJvbCwgQE9wdGlvbmFsKCkgcHJpdmF0ZSBwcmVmU2VydmljZTogUHJlZmVyZW5jZXNTZXJ2aWNlLCBAT3B0aW9uYWwoKSBASW5qZWN0KEVTVF9ERUZBVUxUUykgcHJpdmF0ZSBkZWFmdWx0czogRXNUYWJsZURlZmF1bHRhYmxlLCBAT3B0aW9uYWwoKSBASW5qZWN0KEVTVF9MT0NBTEUpIHB1YmxpYyBsb2NhbGU6IHN0cmluZywgcHVibGljIGxjOiBMb2NhbGl6YXRpb25TZXJ2aWNlLCBwcml2YXRlIGNkcjogQ2hhbmdlRGV0ZWN0b3JSZWYsIHByaXZhdGUgaGFzaEV4dHM6IEhhc2hpbmdTZXJ2aWNlLCBwcml2YXRlIHV0aUV4dHM6IFV0aWxpdHlTZXJ2aWNlLCBwcml2YXRlIGV4cEV4dHM6IEV4cG9ydFNlcnZpY2UsIHByaXZhdGUgZGF0ZUV4dHM6IERhdGVTZXJ2aWNlLCBwcml2YXRlIG1zZ0V4dHM6IE1lc3NhZ2VTZXJ2aWNlKSB7XHJcbiAgICAgICAgaWYgKG5nQ29udHJvbClcclxuICAgICAgICAgICAgbmdDb250cm9sLnZhbHVlQWNjZXNzb3IgPSB0aGlzO1xyXG5cclxuICAgICAgICAvLyBBc3NlZ25hemlvbmUgcGVyIHR1dHRpIGdsaSBJbnB1dCBkaSBkZWZhdWx0XHJcbiAgICAgICAgdGhpcy5Db2x1bW5zUmVzaXphYmxlID0gdGhpcy5JbnB1dE9yRGVmYXVsdCh0aGlzLkNvbHVtbnNSZXNpemFibGUsIHRoaXMuZGVhZnVsdHM/LkNvbHVtbnNSZXNpemFibGUpO1xyXG4gICAgICAgIHRoaXMuQXV0b1VwZGF0ZSA9IHRoaXMuSW5wdXRPckRlZmF1bHQodGhpcy5BdXRvVXBkYXRlLCB0aGlzLmRlYWZ1bHRzPy5BdXRvVXBkYXRlKTtcclxuICAgICAgICB0aGlzLkFsbFNlYXJjaCA9IHRoaXMuSW5wdXRPckRlZmF1bHQodGhpcy5BbGxTZWFyY2gsIHRoaXMuZGVhZnVsdHM/LkFsbFNlYXJjaCwgdHJ1ZSk7XHJcbiAgICAgICAgdGhpcy5FeHBvcnQgPSB0aGlzLklucHV0T3JEZWZhdWx0KHRoaXMuRXhwb3J0LCB0aGlzLmRlYWZ1bHRzPy5FeHBvcnQpO1xyXG4gICAgICAgIHRoaXMuSGlkZVBhZ2luZyA9IHRoaXMuSW5wdXRPckRlZmF1bHQodGhpcy5IaWRlUGFnaW5nLCB0aGlzLmRlYWZ1bHRzPy5IaWRlUGFnaW5nLCBmYWxzZSk7XHJcbiAgICAgICAgdGhpcy5IaWRlUGFnaW5nQ291bnQgPSB0aGlzLklucHV0T3JEZWZhdWx0KHRoaXMuSGlkZVBhZ2luZ0NvdW50LCB0aGlzLmRlYWZ1bHRzPy5IaWRlUGFnaW5nQ291bnQpO1xyXG4gICAgICAgIHRoaXMuSGlkZVBhZ2luZ0J1dHRvbnMgPSB0aGlzLklucHV0T3JEZWZhdWx0KHRoaXMuSGlkZVBhZ2luZ0J1dHRvbnMsIHRoaXMuZGVhZnVsdHM/LkhpZGVQYWdpbmdCdXR0b25zKTtcclxuICAgICAgICB0aGlzLkNvbnRhaW5lckNsYXNzID0gdGhpcy5JbnB1dE9yRGVmYXVsdCh0aGlzLkNvbnRhaW5lckNsYXNzLCB0aGlzLmRlYWZ1bHRzPy5Db250YWluZXJDbGFzcywgJycpO1xyXG4gICAgICAgIHRoaXMuVGFibGVDbGFzcyA9IHRoaXMuSW5wdXRPckRlZmF1bHQodGhpcy5UYWJsZUNsYXNzLCB0aGlzLmRlYWZ1bHRzPy5UYWJsZUNsYXNzLCAndGFibGUgdGFibGUtc3RyaXBlZCB0YWJsZS1ob3ZlciB0YWJsZS1zbScpO1xyXG4gICAgICAgIHRoaXMuU2VsZWN0aW9uID0gdGhpcy5JbnB1dE9yRGVmYXVsdCh0aGlzLlNlbGVjdGlvbiwgdGhpcy5kZWFmdWx0cz8uU2VsZWN0aW9uKTtcclxuICAgICAgICB0aGlzLlNhdmVQcmVmZXJlbmNlcyA9IHRoaXMuSW5wdXRPckRlZmF1bHQodGhpcy5TYXZlUHJlZmVyZW5jZXMsIHRoaXMuZGVhZnVsdHM/LlNhdmVQcmVmZXJlbmNlcyk7XHJcbiAgICAgICAgdGhpcy5QYWdpbmdTdHlsZSA9IHRoaXMuSW5wdXRPckRlZmF1bHQodGhpcy5QYWdpbmdTdHlsZSwgdGhpcy5kZWFmdWx0cz8uUGFnaW5nU3R5bGUsICdib3R0b20nKTtcclxuICAgICAgICB0aGlzLlJvd0dyb3VwaW5nUGFnaW5nU3R5bGUgPSB0aGlzLklucHV0T3JEZWZhdWx0KHRoaXMuUm93R3JvdXBpbmdQYWdpbmdTdHlsZSwgdGhpcy5kZWFmdWx0cz8uUm93R3JvdXBpbmdQYWdpbmdTdHlsZSwgJ2xlZnQnKTtcclxuICAgICAgICB0aGlzLlVzZVNlbGVjdGlvbkNhY2hlID0gdGhpcy5JbnB1dE9yRGVmYXVsdCh0aGlzLlVzZVNlbGVjdGlvbkNhY2hlLCB0aGlzLmRlYWZ1bHRzPy5Vc2VTZWxlY3Rpb25DYWNoZSwgdHJ1ZSk7XHJcbiAgICAgICAgdGhpcy5TaG93SXRlbUdyb3Vwc0NvbHVtbnMgPSB0aGlzLklucHV0T3JEZWZhdWx0KHRoaXMuU2hvd0l0ZW1Hcm91cHNDb2x1bW5zLCB0aGlzLmRlYWZ1bHRzPy5TaG93SXRlbUdyb3Vwc0NvbHVtbnMsIGZhbHNlKTtcclxuICAgICAgICB0aGlzLkFycmF5bW9kZUl0ZW1zUGVyUGFnZSA9IHRoaXMuSW5wdXRPckRlZmF1bHQodGhpcy5BcnJheW1vZGVJdGVtc1BlclBhZ2UsIHRoaXMuZGVhZnVsdHM/LkFycmF5bW9kZUl0ZW1zUGVyUGFnZSwgMTUpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBWaWV3IGZpbmFsZSBzdSBjdWkgYmluZGFyc2kgbGF0byBGcm9udGVuZCwgaWwgdGlwbyBwdcOyIGVzc2VyZSBJQXBwU2VhcmNoPGFueT4gKHBlciBsYSAqKnZpZXdNb2RlKiopLCBhbnlbXSAocGVyIGwnKiphcnJheU1vZGUqKikgZSBSZXBvcnREZWZpbml0aW9uIHBlciBsYSAqKnJlcG9ydE1vZGUqKiAqL1xyXG4gICAgcHVibGljIFZpZXc6IGFueSA9IG51bGw7XHJcbiAgICAvKiogTW9kZWxsbyBkYSBjdWkgbCdlcy10YWJsZSBtb3N0cmEgaSBwdWxzYW50aSBkaSBwYWdpbmF6aW9uZSBpbiBiYXNzbyBhIGRlc3RyYSAqL1xyXG4gICAgcHVibGljIGFycmF5UHVsc2FudGk6IGFueTtcclxuICAgIC8qKiBJbmRpY2Egc2UgbCdlcy10YWJsZSBkZXZlIG1vc3RyYXJlIGlsIGNoZWNrIGdsb2JhbGUgbmVsbCdoZWFkZXIgcGVyIGZhcmUgaWwgXCJzZWxlemlvbmEgdHV0dG9cIiAqL1xyXG4gICAgcHVibGljIGdsb2JhbENoZWNrID0gZmFsc2U7XHJcbiAgICAvKiogVGllbmUgZGEgY29udG8gbCd1bHRpbW8gZWxlbWVudG8gc2VsZXppb25hdG8gaW4gbW9kbyBkYSBwb3RlciBlZmZldHR1YXJlIGlsIFNISUZUK0NMSUNLICovXHJcbiAgICBwcml2YXRlIGxhc3RTZWxlY3RlZDogYW55ID0gbnVsbDtcclxuICAgIC8qKiBDb250ZWdnaW8gaW50ZXJubyBwZXIgaWwgbnVtZXJvIGRpIGVsZW1lbnRpIHNlbGV6aW9uYXRpICovXHJcbiAgICBwdWJsaWMgc2VsZWN0ZWRPYmplY3RzID0gMDtcclxuICAgIC8qKiBJbmRpY2Egc2Ugw6ggcG9zc2liaWxlIGVmZmV0dHVhcmUgdW5hIHNlbGV6aW9uZSBtYXNzaXZhICovXHJcbiAgICBwdWJsaWMgY2FuU2VsZWN0QWxsID0gZmFsc2U7XHJcbiAgICAvKiogSW5kaWNhIHNlIGlsIGNvbXBvbmVudGUgc3RhIGdlc3RlbmRvIHVuIElBcHBTZWFyY2g8YW55PiAqL1xyXG4gICAgcHVibGljIHZpZXdNb2RlID0gZmFsc2U7XHJcbiAgICAvKiogSW5kaWNhIHNlIGlsIGNvbXBvbmVudGUgc3RhIGdlc3RlbmRvIHVuIGFueVtdICovXHJcbiAgICBwdWJsaWMgYXJyYXlNb2RlID0gZmFsc2U7XHJcbiAgICAvKiogSW5kaWNhIHNlIGlsIGNvbXBvbmVudGUgc3RhIGdlc3RlbmRvIHVuIFJlcG9ydERlZmluaXRpb24gKi9cclxuICAgIHB1YmxpYyByZXBvcnRNb2RlID0gZmFsc2U7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDb250ZW5pdG9yZSBkZWdsaSBlbGVtZW50aSBkYSBsaXN0YXJlIGxhdG8gaW50ZXJmYWNjaWEgZG9wbyB0dXR0ZSBsZSBlbGFib3JhemlvbmkgZGVsIGNhc28sXHJcbiAgICAgKiBnZW5lcmFsbWVudGUgbm9uIHNvbm8gYWx0cm8gY2hlIHR1dHRpIGdsaSBvZ2dldHRpIGRhIHByZXNlbnRhcmUgY29uIGluIHBpw7kgbCdoYXNoIGNhbGNvbGF0byBwZXIgaWRlbnRpZmljYXJlIDEgb2dnZXR0byBjb24gbGEgcHJvcHJpYSByaWdhXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBib3VuZFNvdXJjZTogYW55W10gPSBbXTtcclxuICAgIC8qKiBTdGVzc2EgY29zYSBkZWxsYSAqKmJvdW5kU291cmNlKiosIHV0aWxpenphdGEgY29tZSBhcHBvZ2dpbyB0ZW1wb3JhbmVvIGludGVybm8gKi9cclxuICAgIHB1YmxpYyBUTVBCb3VuZFNvdXJjZTogYW55W10gPSBbXTtcclxuICAgIC8qKiBcIkZldHRhXCIgZGkgb2dnZXR0aSB1dGlsaXp6YXRhIG5lbGwnZW5kbGVzcyBzY3JvbGwsIG9nbmkgZWxlbWVudG8gZGkgcXVlc3RvIGFycmF5IMOoIHVuIGJsb2NjaGV0dG8gZGkgMTAwIGVsZW1lbnRpICovXHJcbiAgICBwdWJsaWMgYm91bmRTdWJTb3VyY2VzOiBhbnlbXSA9IFtdO1xyXG4gICAgLyoqIFF1ZXN0YSBmdW5nZSBkYSBpbmRpY2F0b3JlIHBlciBnbGkgc2xpY2UgaW5zZXJpdGksIGxhIGx1bmdoZXp6YSBkb3ZyZWJiZSBlc3NlcmUgY29ycmlzcG9uZGVudGUgYSAqKmJvdW5kU3ViU291cmNlcyoqICovXHJcbiAgICBwdWJsaWMgYWRkZWRTbGljZXM6IG51bWJlcltdID0gW107XHJcbiAgICAvKiogVmFyaWFiaWxlIGNoZSBpZGVudGlmaWNhIGlsIHZhbG9yZSBkZWwgXCJzZWxlemlvbmEgVHV0dG9cIiBuZWxsYSBwYWdpbmF6aW9uZSAqL1xyXG4gICAgcHVibGljIGRlZmF1bHRBbGxQYWdlT3ZlcnJpZGUgPSA5OTk5OTk7XHJcbiAgICAvKiogSW5kaWNhIHNlIHV0aWxpenphcmUgaWwgc2lzdGVtYSBkaSBFbmRsZXNzIFNjcm9sbCAqL1xyXG4gICAgcHVibGljIFVzZUVuZGxlc3NzY3JvbGw6IGJvb2xlYW47XHJcbiAgICAvKiogVmFsb3JpIGRlbGwnZXZlbnR1YWxlIHJlcG9ydCBpbiB2aXN1YWxpenphemlvbmUgKi9cclxuICAgIHB1YmxpYyBSZXBvcnRWYWx1ZXM6IFJlcG9ydFJlc3VsdDtcclxuICAgIC8qKiBTZXJ2ZSBwZXIgdGVuZXJlIGluIG1lbW9yaWEgaWwgY29udGVnZ2lvIHByZWNlZGVudGUgZSByZWN1cGVyYXJsbyBpbiBjYXNvIGRpdmVudGkgLTIgKHZlcmlmaWNhcmUgY29uIEFsZSBwZXJjaMOpIGxhIGxvZ2ljYSBkZWwgLTIpICovXHJcbiAgICBwdWJsaWMgcHJldmlvdXNDb3VudDogbnVtYmVyO1xyXG4gICAgLyoqIEluZGljYSBzZSB1dGlsaXp6YXJlIGlsIHNpc3RlbWEgZGkgYXV0b3VwZGF0ZSwgY2lvw6ggdW4gdHJpZ2dlciB0aW1lLWl6emF0byBpbiBhbHRvIGEgZGVzdHJhIGRlbGxhIHRhYmVsbGEgY2hlIHJpcGV0ZSBsZSByaWNlcmNoZSBvZ25pIFggKipzZWNvbmRzKiogKi9cclxuICAgIHB1YmxpYyBhdXRvVXBkYXRlID0gZmFsc2U7XHJcbiAgICAvKiogTnVtZXJvIGRpIHNlY29uZGkgZGEgZmFyZSB0cmFzY29ycmVyZSBmcmEgdW5hIHJpY2VyY2EgZSBsJ2FsdHJhICovXHJcbiAgICBwdWJsaWMgc2Vjb25kcyA9ICcxMCc7XHJcbiAgICAvKiogUmlmZXJpbWVudG8gYWxsJ0ludGVydmFsIGNoZSB2aWVuZSBnZW5lcmF0byBzZSAqKmF1dG9VcGRhdGUqKiDDqCBpbXBvc3RhdGEgYSB0cnVlIGluIG1vZG8gZGEgcG90ZXJsbyByaXB1bGlyZSAqL1xyXG4gICAgcHVibGljIHVwZGF0ZVRpbWVyOiBhbnk7XHJcbiAgICAvKiogSW1wb3N0YXRhIGEgdHJ1ZSBvZ25pIHZvbHRhIGNoZSB2aWVuZSBhdnZpYXRhIHVuYSByaWNlcmNhLCBlIGEgZmFsc2Ugb2duaSB2b2x0YSBjaGUgdW4gbnVvdm8gdmFsb3JlIHZpZW5lIHJpY2V2dXRvICovXHJcbiAgICBwdWJsaWMgcmVzZWFyY2hJblByb2dyZXNzOiBib29sZWFuID0gZmFsc2U7XHJcbiAgICAvKiogTW9kZWxsbyByYXBwcmVzZW50YW50ZSB1biBzaW5nb2xvIHRkIGRlbGxhIHRhYmVsbGEsIGdlbmVyYXRvIGluIGJhc2UgYWxsZSBjb25maWd1cmF6aW9uaSBlIGFnbGkgb2dnZXR0aSByaWNldnV0aSAqL1xyXG4gICAgcHVibGljIFJvd1REczogeyBbY29udGV4dDogc3RyaW5nXTogRXNUZFtdIH0gPSBudWxsO1xyXG4gICAgLyoqIE1vZGVsbG8gZGkgYXBwb2dnaW8gdGVtcG9yYW5lbyBwZXIgaSAqKlJvd1REcyoqICovXHJcbiAgICBwdWJsaWMgVE1QUm93VERzOiB7IFtjb250ZXh0OiBzdHJpbmddOiBFc1RkW10gfSA9IG51bGw7XHJcbiAgICAvKiogTW9kZWxsbyByYXBwcmVzZW50YW50ZSB1biBzaW5nb2xvIHRoIGRlbGxhIHRhYmVsbGEsIGdlbmVyYXRvIGluIGJhc2UgYWxsZSBjb25maWd1cmF6aW9uaSBlIGFnbGkgb2dnZXR0aSByaWNldnV0aSAqL1xyXG4gICAgcHVibGljIFJvd1RIczogeyBQaW5uZWQ6IGJvb2xlYW4sIEZpeGVkOiBib29sZWFuLCBJRDogc3RyaW5nLCBWaXNpYmxlOiBib29sZWFuLCBDbGFzczogc3RyaW5nLCBDb250ZW50OiBzdHJpbmcsIE9yZGVyOiBzdHJpbmcsIE9yZGVyYWJsZTogYm9vbGVhbiwgVGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT4sIFdyYXA6IGJvb2xlYW4gfVtdID0gbnVsbDtcclxuICAgIC8qKiBNb2RlbGxvIGRpIGFwcG9nZ2lvIHRlbXBvcmFuZW8gcGVyIGkgKipSb3dUSHMqKiAqL1xyXG4gICAgcHVibGljIFRNUFJvd1RIczogeyBQaW5uZWQ6IGJvb2xlYW4sIEZpeGVkOiBib29sZWFuLCBJRDogc3RyaW5nLCBWaXNpYmxlOiBib29sZWFuLCBDbGFzczogc3RyaW5nLCBDb250ZW50OiBzdHJpbmcsIE9yZGVyOiBzdHJpbmcsIE9yZGVyYWJsZTogYm9vbGVhbiwgVGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT4sIFdyYXA6IGJvb2xlYW4gfVtdID0gbnVsbDtcclxuICAgIC8qKiBNb2RlbGxvIGRpIGFwcG9nZ2lvIHRlbXBvcmFuZW8gcGVyIGkgKipSb3dUaEdyb3VwcyoqICovXHJcbiAgICBwdWJsaWMgVE1QUm93VGhHcm91cHM6IHsgU3BhbjogbnVtYmVyLCBUZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PiB9W11bXSA9IG51bGw7XHJcbiAgICAvKiogTW9kZWxsbyByYXBwcmVzZW50YW50ZSB1biBzaW5nb2xvIGhlYWRlciBncm91cCBkZWxsYSB0YWJlbGxhLiBRdWVzdGEgbGlzdGEgw6ggZ2nDoCBvcmRpbmF0YSBlIHByb250YSBwZXIgZXNzZXJlIHV0aWxpenphdGEgaW4gbmdGb3IgKi9cclxuICAgIHB1YmxpYyBSb3dUaEdyb3VwczogeyBTcGFuOiBudW1iZXIsIFRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+IH1bXVtdID0gbnVsbDtcclxuICAgIC8qKiBDYWNoZSBwZXIgaSByb3V0ZXJMaW5rIGdlbmVyYXRpIG5lbGxlIHRhYmVsbGUgZGluYW1pY2hlICovXHJcbiAgICBwdWJsaWMgRHluYW1pY1RhYmxlUm91dGVyTGlua0NhY2hlOiB7fSA9IHt9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogTGlzdGEgZGVpIGNvbnRlc3RpLiBVbiBjb250ZXN0byBub24gw6ggYWx0cm8gY2hlIHVuIGhhc2ggcGFydGljb2xhcmUgY2FsY29sYXRvIHN1IHVuIG9nZ2V0dG8gY2hlIGlkZW50aWZpY2EgdW5pdm9jYW1lbnRlIHRhbGUgb2dnZXR0by5cclxuICAgICAqXHJcbiAgICAgKiBPZ251bm8gZGkgcXVlc3RpIGNvbnRlc3RpIHJhcHByZXNlbnRlcsOgIGEgc3VhIHZvbHRhLCB1bml2b2NhbWVudGUsIHVuYSByaWdhIGFsbCdpbnRlcm5vIGRlbGxhIHRhYmVsbGFcclxuICAgICAqL1xyXG4gICAgcHVibGljIFJvd0NvbnRleHRzOiBhbnlbXSA9IFtdO1xyXG4gICAgLyoqIERpcmV0dGl2ZSBkaSBvcmRpbmFtZW50byBkZWxsZSBjb2xvbm5lIChub24gb3JkaW5hbWVudG8gZGVpIGRhdGkgbWEgZGVsbGUgY29sb25uZSBpbiBzZSkgKi9cclxuICAgIHB1YmxpYyBPcmRlckRpcmVjdGl2ZXM6IHN0cmluZ1tdID0gW107XHJcbiAgICAvKiogQ29kaWNlIGRlbGwndWx0aW1vIG9nZ2V0dG8gc29sZXppb25hdG8gKi9cclxuICAgIHB1YmxpYyBsYXN0U2VsZWN0ZWRJdGVtSUQgPSBudWxsO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSW5kaWNhIHNlIG9sdHJlIGFsbGUgY29sb25uZSBkaW5hbWljaGUgc3BlY2lmaWNoZSBkaSB1biB0aXBvIGRpIG9nZ2V0dG8gY2kgc29ubyBhbmNoZSBjb2xvbm5lIGRpbmFtaWNoZSBhZ2dpdW50ZSBkYWxsJ3V0ZW50ZVxyXG4gICAgICpcclxuICAgICAqIEVzLiB1bmEgY29sb25uYSBpbiBjdWkgbW9zdHJhcmUgc2VtcHJlIHVuIGljb25jaW5hXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBVc2VyRGVmaW5lZER5bmFtaWNDb2xzOiBib29sZWFuID0gZmFsc2U7XHJcbiAgICAvKiogSW5kaWNhIGNoZSBxdWVzdG8gw6ggaWwgcHJpbW8gQmluZCBkZWxsYSB0YWJlbGxhLCB2aWVuZSBzZXR0YXRvIGEgZmFsc2Ugbm9uIGFwcGVuYSBpbCBwcmltbyBiaW5kIHZpZW5lIHRlcm1pbmF0byBjb24gc3VjY2Vzc28gKi9cclxuICAgIHB1YmxpYyBGaXJzdEJpbmQ6IGJvb2xlYW4gPSB0cnVlO1xyXG4gICAgLyoqIExpc3RhIGRpIGNvbG9ubmUgY2hlIHNpIHBvc3Nvbm8gdmlzdWFsaXp6YXJlL29yZGluYXJlIGZyYSBkaSBsb3JvICovXHJcbiAgICBwdWJsaWMgQ29sdW1uc0xpc3Q6IEVzVGFibGVDb2x1bW5bXSA9IFtdO1xyXG4gICAgLyoqIFZhcmlhYmlsZSBkJ2FwcG9nZ2lvIHVzYXRhIGRhbGxhIGRpYWxvZyBkaSBzZWxlemlvbmUvbmFzY29uZGltZW50bywgcGVyIGV2aXRhcmUgZGkgZGFubmVnZ2lhcmUgKipDb2x1bW5zTGlzdCoqIGluIGNhc28gZGkgbW9kaWZpY2hlIHBvaSBhbm51bGxhdGUgKi9cclxuICAgIHB1YmxpYyBUTVBDb2x1bW5zTGlzdDogRXNUYWJsZUNvbHVtbltdID0gW107XHJcbiAgICAvKiogVmFsb3JlIGRlbCBjaGVjayBnbG9iYWxlIGRpIHZpc2liaWxpdMOgIHZhbGlkbyBwZXIgdHV0dGUgbGUgY29sb25uZSBpbiAqKkNvbHVtbnNMaXN0KiogKi9cclxuICAgIHB1YmxpYyBnbG9iYWxDb2xWaXNDaGVjayA9IGZhbHNlO1xyXG5cclxuICAgIC8qKiBRdWVyeSBwZXIgcmVjdXBlcmFyZSB0dXR0ZSBsZSBudW92ZSBkaXJldHRpdmUgIGFzc2VnbmF0aSBhIGRpcmV0dGl2YSAoUGVyIGxhIG1vZGFsaXTDoCBkaW5hbWljYSBkZWxsJ2VzLXRhYmxlKSAqL1xyXG4gICAgQENvbnRlbnRDaGlsZHJlbihFc1RkRGlyZWN0aXZlKSBFc1Rkc0RpcmVjdGl2ZTogUXVlcnlMaXN0PEVzVGREaXJlY3RpdmU+O1xyXG4gICAgLyoqIFF1ZXJ5IHBlciByZWN1cGVyYXJlIHR1dHRpIGdsaSBlcy10ZCBhc3NlZ25hdGkgYSBkaXJldHRpdmEgKFBlciBsYSBtb2RhbGl0w6AgZGluYW1pY2EgZGVsbCdlcy10YWJsZSkgKi9cclxuICAgIEBDb250ZW50Q2hpbGRyZW4oRXNUaERpcmVjdGl2ZSkgRXNUaHNEaXJlY3RpdmU6IFF1ZXJ5TGlzdDxFc1RoRGlyZWN0aXZlPjtcclxuICAgIC8qKiBAZGVwcmVjYXRlZCBRdWVyeSBwZXIgcmVjdXBlcmFyZSB0dXR0aSBnbGkgZXMtdGggKi9cclxuICAgIEBDb250ZW50Q2hpbGRyZW4oZm9yd2FyZFJlZigoKSA9PiBFc1RoKSkgcHJpdmF0ZSBFc1RoczogUXVlcnlMaXN0PEVzVGg+O1xyXG4gICAgLyoqIEBkZXByZWNhdGVkIFF1ZXJ5IHBlciByZWN1cGVyYXJlIHR1dHRpIGdsaSBlcy10ZCAqL1xyXG4gICAgQENvbnRlbnRDaGlsZHJlbihmb3J3YXJkUmVmKCgpID0+IEVzVGQpKSBwcml2YXRlIEVzVGRzOiBRdWVyeUxpc3Q8RXNUZD47XHJcbiAgICAvKiogQGRlcHJlY2F0ZWQgUXVlcnkgcGVyIHJlY3VwZXJhcmUgbGUgaW5mb3JtYXppb25pIGRlbCBib2R5IChwdW50byBkZWxsYSB0YWJlbGxhIGRvdmUgdmVuZ29ubyBtb3N0cmF0ZSBsZSByaWdoZSkgKi9cclxuICAgIEBDb250ZW50Q2hpbGQoJ2JvZHknLCB7IHN0YXRpYzogZmFsc2UgfSkgcHVibGljIGJvZHlSZWY6IGFueTtcclxuICAgIC8qKiBAZGVwcmVjYXRlZCBRdWVyeSBwZXIgcmVjdXBlcmFyZSBsZSBpbmZvcm1hemlvbmkgZGVsbCdoZWFkZXIgKHB1bnRvIGRlbGxhIHRhYmVsbGEgZG92ZSB2ZW5nb25vIG1vc3RyYXRlIGxlIGludGVzdGF6aW9uaSBkZWxsZSByaWdoZSkgKi9cclxuICAgIEBDb250ZW50Q2hpbGQoJ2hlYWRlcicsIHsgc3RhdGljOiBmYWxzZSB9KSBwdWJsaWMgaGVhZGVyUmVmOiBhbnk7XHJcbiAgICAvKiogUXVlcnkgcGVyIHJlY3VwZXJhcmUgbGUgaW5mb3JtYXppb25pIHN1bCByYWdncnVwcGFtZW50byBkZWdsaSBoZWFkZXIgKi9cclxuICAgIEBDb250ZW50Q2hpbGQoJ2hlYWRlckdyb3VwJywgeyBzdGF0aWM6IGZhbHNlIH0pIHB1YmxpYyBoZWFkZXJHcm91cFJlZjogYW55O1xyXG4gICAgLyoqIFF1ZXJ5IHBlciByZWN1cGVyYXJlIGxlIGluZm9ybWF6aW9uaSBzdWwgcmFnZ3J1cHBhbWVudG8gZGkgc2Vjb25kbyBsaXZlbGxvIGRlZ2xpIGhlYWRlciAqL1xyXG4gICAgQENvbnRlbnRDaGlsZCgnc2Vjb25kYXJ5SGVhZGVyR3JvdXAnLCB7IHN0YXRpYzogZmFsc2UgfSkgcHVibGljIHNlY29uZGFyeUhlYWRlckdyb3VwUmVmOiBhbnk7XHJcbiAgICAvKiogT3B6aW9uaSBleHRyYSBjaGUgZGV2b25vIGFwcGFyaXJlIG5lbCBNZW7DuSBjb250ZXN0dWFsZSBpbiBhbHRvIGEgZGVzdHJhLCByaWNoaWFtYXRvIGRhaSAzIHBhbGxpbmkgdmVydGljYWxpICovXHJcbiAgICBASW5wdXQoKSBDb3JuZXJNZW51T3B0aW9uczogQ29ybmVyTWVudU9wdGlvbltdID0gbnVsbDtcclxuICAgIC8qKiBJbmRpY2Egc2UgZGV2J2Vzc2VyZSBwb3NzaWJpbGUgZWZmZXR0dWFyZSBpbCByZXNpemUgZGVsbGUgY29sb25uZSAqL1xyXG4gICAgQElucHV0KCkgQ29sdW1uc1Jlc2l6YWJsZTogYm9vbGVhbiA9IG51bGw7XHJcbiAgICAvKiogSW5kaWNhIHNlIGRldidlc3NlcmUgZGlzcG9uaWJpbGUgaWwgc2lzdGVtYSBkaSBhZ2dpb3JuYW1lbnRvIGF1dG9tYXRpY28gKi9cclxuICAgIEBJbnB1dCgpIEF1dG9VcGRhdGU6IGJvb2xlYW4gPSBudWxsO1xyXG5cclxuICAgIC8qKiBJbmRpY2Egc2UgbGEgdGFiZWxsYSAoY29uZmlndXJhdGEgY29uICoqVXNlQ3VzdG9tQ2VsbHMqKikgZGV2ZSBtZXR0ZXJzaSBpbiBhc2NvbHRvIHBlciBpIGNsaWNrIHN1bGxlIGNlbGxlIGRlc2lkZXJhdGVcclxuICAgICAqIFxyXG4gICAgICogQGRlcHJlY2F0ZWQgVXRpbGl6emFyZSBsJ0lucHV0ICoqVGVtcGxhdGUqKiBkZWxsZSBlcy10ZCBlIGFzc2VnbmFyZSB1biB0ZW1wbGF0ZSBjb24gdHV0dGkgaSBiaW5kaW5nIGNoZSBzaSB2dW9sZSBhaSBjbGlja1xyXG4gICAgICovXHJcbiAgICBASW5wdXQoKSBVc2VDdXN0b21DZWxsQWN0aW9uczogYm9vbGVhbiA9IG51bGw7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJbmRpY2EgbGUgY2VsbGUgZGVzaWRlcmF0ZSBzdSBjdWkgaW50ZXJjZXR0YXJlIGkgY2xpY2suIEF0dGl2YSBzb2xvIHF1YW5kbyAqKlVzZUN1c3RvbUNlbGxBY3Rpb25zKiogw6ggdHJ1ZS5cclxuICAgICAqIE9nbmkgY2VsbGEgZGV2J2Vzc2VyZSBzZXBhcmF0YSBkYWxsYSBzdWNjZXNzaXZhIGRhbCBjYXJhdHRlcmUgZGVsIFNpbW9sZW9uOlxyXG4gICAgICpcclxuICAgICAqIEVzLCBcIk1pYUNlbGxhMcKnTWlhQ2VsbGEyXCJcclxuICAgICAqIFxyXG4gICAgICogQGRlcHJlY2F0ZWQgVXRpbGl6emFyZSBsJ0lucHV0ICoqVGVtcGxhdGUqKiBkZWxsZSBlcy10ZCBlIGFzc2VnbmFyZSB1biB0ZW1wbGF0ZSBjb24gdHV0dGkgaSBiaW5kaW5nIGNoZSBzaSB2dW9sZSBhaSBjbGlja1xyXG4gICAgICovXHJcbiAgICBASW5wdXQoKSBDdXN0b21DZWxsQWN0aW9uc09uID0gJyc7XHJcblxyXG4gICAgLyoqIFxyXG4gICAgICogU2VydmUgcGVyIGRlY2lkZXJlIGRpIGxhbmNpYXJlIG8gbWVubyBpbCAqKmV2ZW50LnN0b3BQcm9wYWdhdGlvbigpKiogYWwgdGVybWluZSBkZWxsYSBnZXN0aW9uZSBkZWxsJ2V2ZW50byBcclxuICAgICAqIFxyXG4gICAgICogQGRlcHJlY2F0ZWQgVXRpbGl6emFyZSBsJ0lucHV0ICoqVGVtcGxhdGUqKiBkZWxsZSBlcy10ZCBlIGFzc2VnbmFyZSB1biB0ZW1wbGF0ZSBjb24gdHV0dGkgaSBiaW5kaW5nIGNoZSBzaSB2dW9sZSBhaSBjbGlja1xyXG4gICAgICovXHJcbiAgICBASW5wdXQoKSBDZWxsQWN0aW9uUHJvcGFnYXRlcyA9IHRydWU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWNpZGUgc2UgdXRpbGl6emFyZSBvIG1lbm8gbGUgQ3VzdG9tQ2VsbHMuIEltcG9zdGFuZG9sbyBhICoqdHJ1ZSoqIGwnZXMtdGFibGUgZGl2ZW50YSBpbiBncmFkbyBkaSBnZXN0aXJlIG5hdGl2YW1lbnRlOlxyXG4gICAgICpcclxuICAgICAqIDEpIE9yZGluYW1lbnRvIGUgdmlzaWJpbGl0w6AgZGVsbGUgY29sb25uZVxyXG4gICAgICpcclxuICAgICAqIDIpIE9yZGluYW1lbnRvIGRlaSBkYXRpXHJcbiAgICAgKlxyXG4gICAgICogMykgTW9kYWxpdMOgIEdlcmFyY2hpY2FcclxuICAgICAqXHJcbiAgICAgKiBlY2MuLi5cclxuICAgICAqL1xyXG4gICAgQElucHV0KCkgVXNlQ3VzdG9tQ2VsbHM6IGJvb2xlYW4gPSBudWxsO1xyXG4gICAgLyoqIFBlcm1ldHRlIGRpIGltcG9zdGFyZSBsJ2FsdGV6emEgbWFzc2ltYSBkZWxsYSB0YWJlbGxhLiBTZSBudWxsIGxhIGRpbWVuc2lvbmUgc2kgYWRhdHRhIGFsIG51bWVybyBkaSBlbGVtZW50aSBhdHR1YWxtZW50ZSBpbiB2aXN1YWxpenphemlvbmUgKi9cclxuICAgIEBJbnB1dCgpIE1heEhlaWdodDogbnVtYmVyID0gbnVsbDtcclxuICAgIC8qKiBDbGFzc2kgZGEgYXBwbGljYXJlIGFsIGNvbnRlbml0b3JlIGRlbGxhIHRhYmVsbGEgKi9cclxuICAgIEBJbnB1dCgpIENvbnRhaW5lckNsYXNzID0gbnVsbDtcclxuICAgIC8qKiBQZXJtZXR0ZSBvIG1lbm8gbCdleHBvcnQgaW4gZm9ybWF0byBYTFNYICovXHJcbiAgICBASW5wdXQoKSBYTFNYRXhwb3J0OiBib29sZWFuID0gbnVsbDtcclxuICAgIC8qKiBQZXJtZXR0ZSBvIG1lbm8gbCdleHBvcnQgaW4gZm9ybWF0byBDU1YgKi9cclxuICAgIEBJbnB1dCgpIENTVkV4cG9ydCA9IHRydWU7XHJcbiAgICAvKiogUGVybWV0dGUgZGkgdmlzdWFsaXp6YXJlIG8gbWVubyBsJ29wemlvbmUgZGkgcGFnaW5hemlvbmUgXCJUdXR0aVwiICovXHJcbiAgICBASW5wdXQoKSBBbGxTZWFyY2ggPSBudWxsO1xyXG4gICAgLyoqIERpbWludWlzY2UgZ2xpIHNwYXppIGZyYSB1bmEgY2VsbGEgZSBsJ2FsdHJhLCBlIGludGVybmFtZW50ZSBpbCBwYWRkaW5nIGRlbCBmb250IGluIG1vZG8gZGEgcHJlc2VudGFyZSBtb2x0aSBwacO5IGRhdGkgaW4gdW4ndW5pY2EgcGFnaW5hICovXHJcbiAgICBASW5wdXQoKSBIaWdoQ2VsbERlbnNpdHk6IGJvb2xlYW4gPSBudWxsO1xyXG4gICAgLyoqIEFiaWxpdGEgbyBtZW5vIGxhIHBvc3NpYmlsaXTDoCBkaSBzZWxlemlvbmFyZSBvZ2dldHRpICovXHJcbiAgICBASW5wdXQoKSBTZWxlY3Rpb246IGJvb2xlYW4gPSBudWxsO1xyXG4gICAgLyoqIE1vc3RyYSBvIG1lbm8gdW4gbWVzc2FnZ2lvIGRpIExvYWRpbmcgYWwgcHJpbW8gY2FyaWNhbWVudG8gZGVsbGEgdGFiZWxsYSAqL1xyXG4gICAgQElucHV0KCkgU2hvd0xvYWRpbmdPbkJvb3RzdHJhcDogYm9vbGVhbiA9IG51bGw7XHJcbiAgICAvKiogU2UgaW1wb3N0YXRvIGEgKip0cnVlKiogYWdnaXVuZ2UgdW5hIGNvbG9ubmEgY29uIHB1bHNhbnRlIGRpIGVsaW1pbmF6aW9uZSBwZXIgZWZmZXR0dWFyZSBsJ2VsaW1pbmEgZGVsbCdvZ2dldHRvIHJlbGF0aXZvICovXHJcbiAgICBASW5wdXQoKSBSZW1vdmFsOiBib29sZWFuID0gbnVsbDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIENvbmRpemlvbmUgY2hlIG5hc2NvbmRlIGwnaWNvbmEgZGkgZWxpbWluYXppb25lIGluc2VyaXRhIGltcG9zdGFuZG8gKipSZW1vdmFsKiogYSB0cnVlIHF1YWxvcmEgbGEgY29uZGl6aW9uZSBub24gdmVuaXNzZSByaXNwZXR0YXRhXHJcbiAgICAgKlxyXG4gICAgICogQ29tZSBjb25kaXppb25lIHNpIGNvbnNpZGVyYSB1biBzZW1wbGljZSBjYW1wbyBzdSBjdWkgZWZmZXR0dWFyZSB1biBjb250cm9sbG8gYm9vbGVhbm8sIGNvbWUgYWQgZXNlbXBpbyBcImNhbnJlbW92ZVwiXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpIFJlbW92YWxDb25kaXRpb24gPSAnJztcclxuICAgIC8qKiBJbmRpY2Egc2UgYWJpbGl0YXJlIGxhIHBvc3NpYmlsaXTDoCBkaSBlc3BvcnRhcmUgbGEgdmlzdGEgZGF0aSBhdHR1YWxlICovXHJcbiAgICBASW5wdXQoKSBFeHBvcnQ6IGJvb2xlYW4gPSBudWxsO1xyXG4gICAgLyoqIEluZGljYSBzZSBwZXJtZXR0ZXJlIGxhIHNlbGV6aW9uZSBtdWx0aXBsYSBXaW5kb3dzLWxpa2UgY2xpY2NhbmRvIHVuIG9nZ2V0dG8gZSBmYWNlbmRvIHBvaSBTaGlmdCArIGNsaWNrIHN1IHVuIG9nZ2V0dG8gc3VjY2Vzc2l2byAqL1xyXG4gICAgQElucHV0KCkgU2hpZnRDbGljazogYm9vbGVhbiA9IG51bGw7XHJcbiAgICAvKiogSW5kaWNhIHNlIG5hc2NvbmRlcmUgbyBtb3N0cmFyZSBpbCBjb21wb25lbnRlIGRpIHBhZ2luYXppb25lICovXHJcbiAgICBASW5wdXQoKSBIaWRlUGFnaW5nOiBib29sZWFuID0gbnVsbDtcclxuICAgIC8qKiBJbmRpY2Egc2UgbmFzY29uZGVyZSBvIG1vc3RyYXJlIGlsIGNvbnRlZ2dpbyBkZWdsaSBlbGVtZW50aSB0cm92YXRpICovXHJcbiAgICBASW5wdXQoKSBIaWRlUGFnaW5nQ291bnQ6IGJvb2xlYW4gPSBudWxsO1xyXG4gICAgLyoqIEluZGljYSBzZSBuYXNjb25kZXJlIG8gbW9zdHJhcmUgaSBwdWxzYW50aSBkaSBwYWdpbmF6aW9uZSAqL1xyXG4gICAgQElucHV0KCkgSGlkZVBhZ2luZ0J1dHRvbnM6IGJvb2xlYW4gPSBudWxsO1xyXG4gICAgLyoqIFJpZmVyaW1lbnRvIGFsIENvbnRleHRNZW51IChuZ3gtY29udGV4dG1lbnUpIGFzc29jaWF0byBhbCBjbGljayBkZXN0cm8gZGkgdW5vIG8gcGnDuSBlbGVtZW50aSBzZWxlemlvbmF0aSBuZWxsYSB0YWJlbGxhICovXHJcbiAgICBASW5wdXQoKSBDb250ZXh0TWVudTogQ29udGV4dE1lbnVDb21wb25lbnQgPSBudWxsO1xyXG4gICAgLyoqIE5vbWUgZGVsbCdlc3BvcnRhemlvbmUgZ2VuZXJhdGEgZGEgcXVlc3RhIHRhYmVsbGEgKi9cclxuICAgIEBJbnB1dCgpIEV4cG9ydEZpbGVOYW1lID0gJ0V4cG9ydC5jc3YnO1xyXG4gICAgLyoqIENsYXNzZSAoSFRNTCkgZGkgZGVmYXVsdCBkZWxsYSB0YWJlbGxhICovXHJcbiAgICBASW5wdXQoKSBUYWJsZUNsYXNzID0gbnVsbDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEZ1bnppb25lIGRhIHV0aWxpenphcmUgaW4gZXNwb3J0YXppb25lLiBOZWwgZm9ybWF0byBcIlJlcG9ydFwiIGF2csOgIHVuIHVuaWNvIHBhcmFtZXRybyBcIkZvcm1hdG9cIiBlIG5lc3N1biB2YWxvcmUgZGkgcml0b3Juby5cclxuICAgICAqXHJcbiAgICAgKiBOZWwgZm9ybWF0byBcIlZpZXdcIiBoYSBjb21lIHBhcmFtZXRybyB1bmEgY2FsbGJhY2sgY29uIGkgZGF0aSBjb21wbGV0aSBkYSBlc3BvcnRhcmUgKGRhdG8gY2hlIGRpIGRlZmF1bHQgbGEgcmljZXJjYSDDqCBwYWdpbmF0YSlcclxuICAgICAqL1xyXG4gICAgQElucHV0KCkgRXhwb3J0RnVuY3Rpb246IGFueTtcclxuICAgIC8qKiBAZGVwcmVjYXRlZCBJbmRpY2EgbGEgcHJlc2VuemEgZGkgcmFnZ3J1cHBhbWVudGkgYSBsaXZlbGxvIGRpIGhlYWRlciAqL1xyXG4gICAgQElucHV0KCkgSGFzSGVhZGVyR3JvdXA6IGJvb2xlYW4gPSBudWxsO1xyXG4gICAgLyoqIEBkZXByZWNhdGVkIEluZGljYSBsYSBwcmVzZW56YSBkaSByYWdncnVwcGFtZW50aSBhIGxpdmVsbG8gZGVsIHJhZ2dydXBwYW1lbnRvIHByZWNlZGVudGVtZW50ZSBlc2lzdGVudGUsIGNoaWFyYW1lbnRlIMOoIGluc2Vuc2F0YSBzZW56YSAqKkhhc0hlYWRlckdyb3VwKiogKi9cclxuICAgIEBJbnB1dCgpIEhhc1NlY29uZGFyeUhlYWRlckdyb3VwOiBib29sZWFuID0gbnVsbDtcclxuICAgIC8qKiBVdGlsaXp6YXRvIHBlciBkaXZpZGVyZSBsYSBzb3JnZW50ZSBpbiBtb2RhbGl0w6AgRW5kbGVzc1Njcm9sbCAqL1xyXG4gICAgQElucHV0KCkgU2xpY2VTaXplID0gMTAwO1xyXG4gICAgLyoqIERlY2lkZSBzZSB1dGlsaXp6YXJlIGxhIG1vZGFsaXTDoCBkaSBFbmRsZXNzU2Nyb2xsICovXHJcbiAgICBASW5wdXQoKSBFbmRsZXNzU2Nyb2xsOiBib29sZWFuID0gbnVsbDtcclxuICAgIC8qKiBRdWFsb3JhICoqRW5kbGVzc1Njcm9sbCoqIGZvc3NlIHRydWUsIGluZGljYSBzZSB1dGlsaXp6YXJlIHF1ZXN0YSBtb2RhbGl0w6Agc29sbyBxdWFuZG8gc2kgY2VyY2EgcGVyIFwiVHV0dGlcIiBvIGluIGdlbmVyYWxlICovXHJcbiAgICBASW5wdXQoKSBFbmRsZXNzU2Nyb2xsT25seUZvckFsbCA9IHRydWU7XHJcbiAgICAvKiogSW5kaWNhIHNlIG5hc2NvbmRlcmUgZ2xpIEhlYWRlciBkZWxsYSB0YWJlbGxhICovXHJcbiAgICBASW5wdXQoKSBIZWFkZXJIaWRkZW46IGJvb2xlYW4gPSBudWxsO1xyXG4gICAgLyoqIEluZGljYSBzZSBuYXNjb25kZXJlIGlsIEJvZHkgZGVsbGEgdGFiZWxsYSAqL1xyXG4gICAgQElucHV0KCkgQm9keUhpZGRlbjogYm9vbGVhbiA9IG51bGw7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJbmRpY2Egc2UgbGEgc2VsZXppb25lIMOoIHRlbXBvcmFuZWFtZW50ZSBkaXNhYmlsaXRhdGEuIFJpc3BldHRvIGFsbCdJbnB1dCAqKlNlbGVjdGlvbioqIGNoZSB2aXNpdmFtZW50ZSBnZXN0aXNjZSBzZSBjaSBzb25vIG8gbm8gZ2xpIGlucHV0IGRpIHNlbGV6aW9uZSxcclxuICAgICAqIHF1ZXN0byBJbnB1dCBnZXN0aXNjZSBzZSBxdWVzdGkgaW5wdXQgc29ubyBhYmlsaXRhdGkgbyBtZW5vXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpIFNlbGVjdGlvbkRpc2FibGVkOiBib29sZWFuID0gbnVsbDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEluZGljYSBzZSBmb3J6YXJlIGlsIHNpc3RlbWEgZGkgc2VsZXppb25lIGEgZ2VzdGlyZSB1biBlbGVtZW50byBwZXIgdm9sdGEuXHJcbiAgICAgKiBTZWxlemlvbmFyZSB1bidhbHRyYSByaWdhIGNvbiB1bmEgZ2nDoCBzZWxlemlvbmF0YSBhcHBsaWNoZXLDoCBsYSBzZWxlemlvbmUgYWxsYSBudW92YSByaWdhLCByaW11b3ZlbmRvbGEgZGFsbCdhdHR1YWxlXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpIFNpbmdsZVNlbGVjdGlvbjogYm9vbGVhbiA9IG51bGw7XHJcbiAgICAvKiogQ2FsbGJhY2sgY2hlIGRhdG8gdW4gb2dnZXR0byByZXNpdHVpc2NlIGwnZXZlbnR1YWxlIGNsYXNzZSBkYSBhcHBsaWNhcmUgYWxsYSByaWdhIGNvbGxlZ2F0YSBhbGwnb2dnZXR0byAqL1xyXG4gICAgQElucHV0KCkgUm93Q2xhc3NBc3NpZ25lcjogYW55ID0gbnVsbDtcclxuICAgIC8qKiBQZXJtZXR0ZSBkaSBvcmRpbmFyZSBpIGRhdGkgaW4gbWFuaWVyYSBkaXNjZW5kZW50ZSBvIGFzY2VuZGVudGUgKi9cclxuICAgIEBJbnB1dCgpIE9yZGVyQnlDb2x1bW46IGJvb2xlYW4gPSBudWxsO1xyXG4gICAgLyoqIFBlcm1ldHRlIGRpIGF2ZXJlIHBpw7kgZGlyZXR0aXZlIGRpIG9yZGluYW1lbnRvIGRlaSBkYXRpICovXHJcbiAgICBASW5wdXQoKSBNdWx0aXBsZU9yZGVyaW5nRGlyZWN0aXZlcyA9IHRydWU7XHJcbiAgICAvKiogUGVybWV0dGUgZGkgbmFzY29uZGVyZSBsZSBjb2xvbm5lIGluIGJhc2UgYWxsZSBzZWxlemlvbmkgZWZmZXR0dWF0ZSBkYWwgTWVuw7kgY29udGVzdHVhbGUgaW4gYWx0byBhIGRlc3RyYSAqL1xyXG4gICAgQElucHV0KCkgSGlkZGVuQ29sdW1uczogYm9vbGVhbiA9IG51bGw7XHJcbiAgICAvKiogUGVybWV0dGUgZGkgcmlvcmRpbmFyZSBsZSBjb2xvbm5lIGluIGJhc2UgYWxsZSBpbXBvc3RhemlvbmkgZWZmZXR0dWF0ZSBkYWwgTWVuw7kgY29udGVzdHVhbGUgaW4gYWx0byBhIGRlc3RyYSAqL1xyXG4gICAgQElucHV0KCkgQ29sdW1uc09yZGVyaW5nOiBib29sZWFuID0gbnVsbDtcclxuICAgIC8qKiBFdmVudHVhbGUgc3VwcG9ydG8gYWxsZSByaWNlcmNoZSBhcHBsaWNhdGUgYWxsYSBtb2RhbGl0w6AgQXJyYXkgKi9cclxuICAgIEBJbnB1dCgpIFNlYXJjaFZpZXcgPSBudWxsIGFzIEFwcFNlYXJjaDxhbnk+O1xyXG4gICAgLyoqIEFiaWxpdGEgbyBkaXNhYmlsaXRhIGlsIHNpc3RlbWEgY2hlIHBlcm1ldHRlIGRpIHNlbGV6aW9uYXJlIHR1dHRpIGdsaSBlbGVtZW50aSBuZWxsYSB2aXN0YSAqL1xyXG4gICAgQElucHV0KCkgU2VsZWN0QWxsOiBib29sZWFuID0gbnVsbDtcclxuICAgIC8qKiBTaW11bGEgbGEgcGFnaW5hemlvbmUgYW5jaGUgcGVyIGxlIHRhYmVsbGUgY2hlIGZ1bnppb25hbm8gaW4gbW9kYWxpdMOgIEFycmF5ICovXHJcbiAgICBASW5wdXQoKSBVc2VBcnJheU1vZGVQYWdpbmcgPSB0cnVlO1xyXG4gICAgLyoqIERlZmluaXppb25lIGRpIGNvbG9ubmUgZGluYW1jaGUgcGVyIGxhIG1vZGFsaXTDoCwgYXBwdW50bywgZGluYW1pY2EgKi9cclxuICAgIEBJbnB1dCgpIER5bmFtaWNSb3dDb2x1bW5zRGVmaW5pdGlvbjogRXNUYWJsZUNvbHVtbnNEZWZpbml0aW9uW10gPSBudWxsO1xyXG4gICAgLyoqIEluZGljYSBvcGVyYXppb25pIGRpbmFtaWNoZSBnZW5lcmljaGUgY2hlIHBvc3Nvbm8gZXNzZXJlIGVmZmV0dHVhdGUgcGVyIHJpZ2EuIEFwcGFpb25vIGNvbWUgY29sb25uZSBleHRyYSBzdWwgbGF0byBzaW5pc3RybyBkZWxsYSB0YWJlbGxhICovXHJcbiAgICBASW5wdXQoKSBEeW5hbWljT3BlcmF0aW9uczogRXNUYWJsZU9wZXJhdGlvbkRlZmluaXRpb25bXSA9IFtdO1xyXG4gICAgLyoqIEluZGljYSBzZSB2aXN1YWxpenphcmUgaSBkYXRpIGluIG1hbmllcmEgZ2VyYXJjaGljYSAqL1xyXG4gICAgQElucHV0KCkgSGllcmFyY2h5OiBib29sZWFuID0gbnVsbDtcclxuICAgIC8qKiBOb21lIGRlbGxhIHByb3ByaWV0w6AgY2hlIGNvbnRpZW5lIGwnSUQgZGVsIHBhZHJlLiBEYSB1dGlsaXp6YXJlIHNlICoqSGllcmFyY2h5Kiogw6ggaW1wb3N0YXRvICovXHJcbiAgICBASW5wdXQoKSBQYXJlbnRLZXkgPSAnJztcclxuICAgIC8qKiBOb21lIGRlbGxhIHByb3ByaWV0w6AgY2hlIGNvbnRpZW5lIGwnSUQgZGVsbCdvZ2dldHRvIGF0dHVhbGUuIERhIHV0aWxpenphcmUgc2UgKipIaWVyYXJjaHkqKiDDqCBpbXBvc3RhdG8gKi9cclxuICAgIEBJbnB1dCgpIE93bktleSA9ICcnO1xyXG4gICAgLyoqIEluZGljYSBzZSBwYXJ0aXJlIGNvbiB1biBhbGJlcm8gZXNwYW5zby4gRGEgdXRpbGl6emFyZSBzZSAqKkhpZXJhcmNoeSoqIMOoIGltcG9zdGF0byAqL1xyXG4gICAgQElucHV0KCkgU3RhcnRzRXhwYW5kZWQgPSB0cnVlO1xyXG4gICAgLyoqIEluZGljYSBzZSBlZmZldHR1YXJlIGlsIHNhbHZhdGFnZ2lvIGRlbGxlIHByZWZlcmVuemUgZGkgcmljZXJjYSAqL1xyXG4gICAgQElucHV0KCkgU2F2ZVByZWZlcmVuY2VzOiBib29sZWFuID0gbnVsbDtcclxuXHJcbiAgICAvKiogSW5kaWNhIGRvdmUgdmlzdWFsaXp6YXJlIGxlIGluZm9ybWF6aW9uaSBkaSBwYWdpbmF6aW9uZSwgc2Ugc29wcmEsIHNvdHRvIG8gaW4gZW50cmFtYmkgKi9cclxuICAgIEBJbnB1dCgpIFBhZ2luZ1N0eWxlOiAnYm90aCcgfCAndG9wJyB8ICdib3R0b20nID0gbnVsbDtcclxuICAgIC8qKiBJbmRpY2EgZG92ZSB2aXN1YWxpenphcmUgbGUgaW5mb3JtYXppb25pIGRpIHBhZ2luYXppb25lLCBzZSBzb3ByYSwgc290dG8gbyBpbiBlbnRyYW1iaSAqL1xyXG4gICAgQElucHV0KCkgUm93R3JvdXBpbmdQYWdpbmdTdHlsZTogJ2xlZnQnIHwgJ3JpZ2h0JyA9IG51bGw7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTb3JnZW50ZSBkYXRpIHNlY29uZGFyaWFcclxuICAgICAqXHJcbiAgICAgKiBAZGVwcmVjYXRlZCBVdGlsaXp6YXRvIHNvbG8gcGVyIHVuIGNhc28gcGFydGljb2xhcmUgZGVsIE1ldGVyaW5nXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpIFNlY29uZGFyeVNvdXJjZTogYm9vbGVhbiA9IG51bGw7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTb3JnZW50ZSBkYXRpIHNlY29uZGFyaWFcclxuICAgICAqXHJcbiAgICAgKiBAZGVwcmVjYXRlZCBVdGlsaXp6YXRvIHNvbG8gcGVyIHVuIGNhc28gcGFydGljb2xhcmUgZGVsIE1ldGVyaW5nXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpIFRlcnRpYXJ5U291cmNlOiBib29sZWFuID0gbnVsbDtcclxuICAgIC8qKiBJbmRpY2Egc2UgdXRpbGl6emFyZSBsYSBjYWNoZSBkaSBzZWxlemlvbmUgY2hlIHBlcm1ldHRlIGRpIG1hbnRlbmVyZSBnbGkgc3RhdGkgZGkgc2VsZXppb25lIGRlaSB2YXJpIG9nZ2V0dGkgbmF2aWdhbmRvIGRhIHVuYSBwYWdpbmEgYWxsJ2FsdHJhICovXHJcbiAgICBASW5wdXQoKSBVc2VTZWxlY3Rpb25DYWNoZSA9IG51bGw7XHJcbiAgICAvKiogUGVybWV0dGUgZGkgZGVjaWRlcmUgc2UsIGluIG1vZGFsaXTDoCByYWdncnVwcGFtZW50bywgbW9zdHJhcmUgbyBtZW5vIGlsIHZhbG9yZSBkZWxsZSBjb2xvbm5lIGRpIGdydXBwbyBuZWdsaSBvZ2dldHRpIGZpbmFsaS4gRGkgZGVmYXVsdCBzb25vIG5hc2Nvc3RpICovXHJcbiAgICBASW5wdXQoKSBTaG93SXRlbUdyb3Vwc0NvbHVtbnMgPSBudWxsO1xyXG4gICAgLyoqIEV2ZW50byBjaGUgdmllbmUgcmljaGlhbWF0byBhbCBjYW1iaW8gZGkgb3JpZG5hbWVudG8gZGkgdW5hIGNvbG9ubmEgKi9cclxuICAgIEBPdXRwdXQoKSBvbk9yZGVyQ2hhbmdlZDogRXZlbnRFbWl0dGVyPEFwcE9yZGVyaW5nPiA9IG5ldyBFdmVudEVtaXR0ZXI8QXBwT3JkZXJpbmc+KCk7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBFdmVudG8gY2hlIHZpZW5lIHJpY2hpYW1hdG8gcXVhbmRvIGwnZXMtdGFibGUgcml0aWVuZSBzaWEgbmVjZXNzYXJpbyByaS1lZmZldHR1YXJlIGxhIHJpY2VyY2EuXHJcbiAgICAgKiBJbCBib29sZWFubyBkZWxsJ2V2ZW50byBpbmRpY2Egc2UgdmllbmUgc3VnZ2VyaXRvIGRpIHJlc2V0dGFyZSBsYSBwYWdpbmEgbyBtZW5vLlxyXG4gICAgICogXHJcbiAgICAgKiBTb2xvIGluIGNhc28gdmVuZ2EgdXRpbGl6emF0YSBsYSBtb2RhbGl0w6AgYSByYWdncnVwcGFtZW50aSBkaSByaWdoZSBwdcOyIHN1Y2NlZGVyZSBjaGUgbCdlcy10YWJsZSBwYXNzaSB1biBpbnRlcm8gQXBwU2VhcmNoIGNvbWUgcGFyYW1ldHJvIGRpIHJpY2VyY2EsXHJcbiAgICAgKiBpbiBxdWVsIGNhc28gbCdhcHBsaWNhemlvbmUgcmljZXZlbnRlIGRvdnLDoCBvbm9yYXJlIGxhIHJpY2hpZXN0YSBzcGVkZW5kbyBhbCBiYWNrYW5kIGwnb2dnZXR0byBkaSByaWNlcmNhIEFTLUlTXHJcbiAgICAgKiBcclxuICAgICAqIGlsIHRpcG8gZGVsbCdFbWl0dGVyIGludmVjZSBkaSBlc3NlcmUgW2Jvb2xlYW4gfCBBcHBTZWFyY2g8YW55Pl0gw6ggc3RhdG8gaW1wb3N0YXRvIGEgXCJhbnlcIiBwZXIgZXZpdGFyZSBwcm9ibGVtaSBkaSByZXRyb2NvbXBhdGliaWxpdMOgXHJcbiAgICAgKi9cclxuICAgIEBPdXRwdXQoKSBvblNlYXJjaFJlcXVlc3Q6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XHJcbiAgICAvKiogRXZlbnRvIGNoZSBwYXJ0ZSBhZCBvZ25pIG1vZGlmaWNhIGRpIFwiY2hlY2thZ2dpb1wiIGluIGZvcm1hIGRpIGNvbW9kbyBhcnJheS4gRXNwb25lIGwnb2dnZXR0byBjb24gbG8gc3RhdG8gZGkgY2hlY2sgYXR0dWFsZSAqL1xyXG4gICAgQE91dHB1dCgpIG9uU2VsZWN0aW9uQ2hhbmdlZDogRXZlbnRFbWl0dGVyPEl0ZW1zU2VsZWN0aW9uPGFueT4+ID0gbmV3IEV2ZW50RW1pdHRlcjxJdGVtc1NlbGVjdGlvbjxhbnk+PigpO1xyXG4gICAgLyoqIEV2ZW50byByaWNoaWFtYXRvIGFsbCdlbGltaW5hemlvbmUgZGkgdW4gb2dnZXR0byAqL1xyXG4gICAgQE91dHB1dCgpIG9uUmVtb3ZhbDogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcclxuICAgIC8qKiBFdmVudG8gcmljaGlhbWF0byBhbGwnYW5udWxsYW1lbnRvIGRpIHVuJ2VsaW1pbmF6aW9uZSAqL1xyXG4gICAgQE91dHB1dCgpIG9uQWJvcnRSZW1vdmFsOiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xyXG5cclxuICAgIC8qKiBFdmVudG8gcmljaGlhbWF0byBhbCBjbGljayBzdSB1bmEgY2VsbGEgcXVhbmRvICoqVXNlQ3VzdG9tQ2VsbEFjdGlvbnMqKiDDqCBhdHRpdm8gXHJcbiAgICAgKiBcclxuICAgICAqIEBkZXByZWNhdGVkIFV0aWxpenphcmUgbCdJbnB1dCAqKlRlbXBsYXRlKiogZGVsbGUgZXMtdGQgZSBhc3NlZ25hcmUgdW4gdGVtcGxhdGUgY29uIHR1dHRpIGkgYmluZGluZyBjaGUgc2kgdnVvbGUgYWkgY2xpY2tcclxuICAgICAqL1xyXG4gICAgQE91dHB1dCgpIG9uQ2VsbENsaWNrOiBFdmVudEVtaXR0ZXI8eyBjb2x1bW46IHN0cmluZywgbW9kZWw6IGFueSB9PiA9IG5ldyBFdmVudEVtaXR0ZXI8eyBjb2x1bW46IHN0cmluZywgbW9kZWw6IGFueSB9PigpO1xyXG4gICAgLyoqIEV2ZW50byByaWNoaWFtYXRvIHF1YW5kbyBzaSBjbGljY2Egc3UgdW4gb3B6aW9uZSBkZWZpbml0YSBuZWxsZSAqKkNvcm5lck1lbnVPcHRpb25zKiogKi9cclxuICAgIEBPdXRwdXQoKSBvbkNvcm5lckFjdGlvbjogRXZlbnRFbWl0dGVyPHsgaWQ6IHN0cmluZywgZXN0YWJsZTogYW55IH0+ID0gbmV3IEV2ZW50RW1pdHRlcjx7IGlkOiBzdHJpbmcsIGVzdGFibGU6IGFueSB9PigpO1xyXG4gICAgLyoqIEV2ZW50byByaWNoaWFtYXRvIHF1YW5kbyBzaSBjbGljY2Egc3UgdW4gb3B6aW9uZSBkZWZpbml0YSBuZWxsZSAqKkR5bmFtaWNPcGVyYXRpb25zKiogKi9cclxuICAgIEBPdXRwdXQoKSBvbkR5bmFtaWNPcGVyYXRpb246IEV2ZW50RW1pdHRlcjx7IGlkOiBzdHJpbmcsIGl0ZW06IGFueSB9PiA9IG5ldyBFdmVudEVtaXR0ZXI8eyBpZDogc3RyaW5nLCBpdGVtOiBhbnkgfT4oKTtcclxuXHJcbiAgICAvKiogRGF0aSBlc3BvcnRhdGkgZGEgbmd4LWNzdiAqL1xyXG4gICAgcHVibGljIGRhdGE6IGFueVtdO1xyXG4gICAgLyoqIEhlYWRlciBkZWkgZGF0aSBlc3BvcnRhdGkgZGEgbmd4LWNzdiAqL1xyXG4gICAgcHVibGljIGhlYWRlcnM6IGFueVtdO1xyXG4gICAgLyoqIEVsZW1lbnRvIEhUTUwgZGEgY2xpY2NhcmUgcGVyIGwnZXNwb3J0YXppb25lICovXHJcbiAgICBAVmlld0NoaWxkKCdleHBvcnREb3dubG9hZGVyJywgeyBzdGF0aWM6IGZhbHNlIH0pIHB1YmxpYyBleHBvcnREb3dubG9hZGVyOiBFbGVtZW50UmVmO1xyXG4gICAgLyoqIFBsYWNlaG9sZGVyIGRpIG1lbsO5IGNvbnRlc3R1YWxlIHBlciBxdWFuZG8gbm9uIGNpIHNvbm8gb3B6aW9uaSBuZWwgcGxhY2Vob2xkZXIgXCJWZXJvXCIgICovXHJcbiAgICBAVmlld0NoaWxkKCdlbXB0eU1lbnUnLCB7IHN0YXRpYzogdHJ1ZSB9KSBwdWJsaWMgdGFibGVFbXB0eU1lbnU6IENvbnRleHRNZW51Q29tcG9uZW50O1xyXG5cclxuICAgIC8qKiBTdWJzY3JpcHRpb24gc3VsbCdhcGVydHVyYSBkZWwgY29udGV4dCBtZW51IGRhIHJpcHVsaXJlIGFsIGRlc3Ryb3kgZGVsbGEgY2xhc3NlICovXHJcbiAgICBwcml2YXRlIGN0eE1lbnVTdWJzY3JpcHRpb246IGFueTtcclxuXHJcbiAgICAvKiogUGFnaW5hIGluIHZpc3VhbGl6emF6aW9uZSAoZHVyYW50ZSBsYSBwYWdpbmF6aW9uZSBpbiBtb2RhbGl0w6AgQXJyYXkpICovXHJcbiAgICBwdWJsaWMgYXJyYXltb2RlUGFnZSA9IDE7XHJcbiAgICAvKiogTnVtZXJvIGRpIHBhZ2luZSAoZHVyYW50ZSBsYSBwYWdpbmF6aW9uZSBpbiBtb2RhbGl0w6AgQXJyYXkpICovXHJcbiAgICBwdWJsaWMgYXJyYXltb2RlUGFnZXMgPSAxO1xyXG4gICAgLyoqIE9nZ2V0dGkgcGVyIG9nbmkgcGFnaW5hIChkdXJhbnRlIGxhIHBhZ2luYXppb25lIGluIG1vZGFsaXTDoCBBcnJheSkgKi9cclxuICAgIEBJbnB1dCgpIEFycmF5bW9kZUl0ZW1zUGVyUGFnZSA9IG51bGw7XHJcbiAgICAvKiogT2dnZXR0byBkaSBzZWxlemlvbmUgcGVyIGxhIG1vZGFsaXTDoCBBcnJheSwgY2hlIGRldmUgY29tcG9ydGFyc2kgY29tZSBsYSBjb250cm9wYXJ0ZSBpbiBtb2RhbGl0w6AgVmlldyAqL1xyXG4gICAgcHVibGljIGFycmF5bW9kZVNlbGVjdGlvbjogSXRlbXNTZWxlY3Rpb248YW55PjtcclxuICAgIC8qKiBDb2xvbm5lIGRhIHZpc3VhbGl6emFyZSBpbiBtb2RhbGl0w6AgYXJyYXkgKi9cclxuICAgIHB1YmxpYyBhcnJheUNvbHVtbnM6IHN0cmluZ1tdID0gW107XHJcbiAgICAvKiogT3JkaW5lIGRlbGxlIGNvbG9ubmUgZGEgdmlzdWFsaXp6YXJlIGluIG1vZGFsaXTDoCBhcnJheSAqL1xyXG4gICAgcHVibGljIGFycmF5Q29sdW1uT3JkZXJpbmc6IHN0cmluZ1tdID0gW107XHJcbiAgICAvKiogT3JkaW5hbWVudGkgQVNDLURFU0Mgc3VsbGUgY29sb25uZSBpbiBtb2RhbGl0w6AgYXJyYXkgKi9cclxuICAgIHB1YmxpYyBhcnJheU9yZGVyczogQXBwT3JkZXJpbmdbXSA9IFtdO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogVmFyaWFiaWxlIGNoZSBzZXJ2ZSBhIGdlc3RpcmUgaWwgbW9tZW50byBpbiBjdWkgbCdlcy10YWJsZSBhZ2dpb3JuYSBsYSBwYWdpbmF6aW9uZSAocHVsc2FudGkgZWNjKS5cclxuICAgICAqIEVzc2VuZG8gb3BlcmF6aW9uaSBjb211bnF1ZSBjb3N0b3NlIGxlIGVmZmV0dHVvIHNvbG8gc3UgYmluZGluZyBlc3Rlcm5pLCBub24gc3UgcmV3cml0ZSBnZW5lcmF0aSBpbnRlcm5hbWVudGVcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBpbnRlcm5hbFdyaXRlQ2FsbCA9IGZhbHNlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ2FjaGUgY2hlIGNvbnRlcnLDoCB0dXR0ZSBsZSByaWNlcmNoZSBlZmZldHR1YXRlIHN1IGdydXBwaSBkaXZlcnNpIGRhbCBwcmltbyBlIHN1IGVsZW1lbnRpIGNvbnRlbnV0aSBuZWkgZ3J1cHBpLlxyXG4gICAgICogSW4gY2FzbyBkaSBjYW1iaSBkaSBvcmRpbmFtZW50byBkZWxsZSBjb2xvbm5lIGRpdmVyc2UgZGFsbGEgcHJpbWEgdHV0dGUgbGUgY2hpYW1hdGUgZmF0dGUgZGFsIHNlY29uZG8gbGl2ZWxsbyBpbiBwb2kgZGV2b25vIGVzc2VyZSByaWVzZWd1aXRlIHNlY29uZG8gbGEgc2VndWVudGUgbG9naWNhOlxyXG4gICAgICogXHJcbiAgICAgKiBcclxuICAgICAqICoqQ2FtYmlvIG9yZGluYW1lbnRvIHN1bCBwcmltbyBncnVwcG8qKjogcmVsb2FkIGNvbXBsZXRvLCBub24gbWkgb2NjdXBvIGRpIHJpcHVsaXJlIGdsaSBlbGVtZW50aSBiaW5kYXRpIGluIGFsY3VuIG1vZG9cclxuICAgICAqIFxyXG4gICAgICogKipDYW1iaW8gb3JkaW5hbWVudG8gc3VsbGEgY29sb25uYSByZWxhdGl2YSBhbGwnTi1lc2ltbyBncnVwcG8qKjogcmVsb2FkIGNvbXBsZXRvIGRlbCBjb250ZW51dG8gZGVpIGdydXBwaSBwcmVjZWRlbnRpLCByaXB1bGVuZG8gcHJlY2VkZW50ZW1lbnRlIFxyXG4gICAgICogdHV0dGkgZ2xpIGVsZW1lbnRpIGNvbiAqKl9ncm91cGxldmVsKiogPSBOXHJcbiAgICAgKiBcclxuICAgICAqICoqQ2FtYmlvIG9yZGluYW1lbnRvIHN1IHVuYSBjb2xvbm5hIG5vbiByYWdncnVwcGF0YSoqOiByZWxvYWQgY29tcGxldG8gcGVyIHR1dHRpIGkgZ3J1cHBpIGZpbmFsaSBhcGVydGksIGRldm8gcHJlY2VkZW50ZW1lbnRlIHJpcHVsaXJlIHR1dHRpIGdsaSBlbGVtZW50aSBjb24gKipfaXRlbSoqID0gdHJ1ZVxyXG4gICAgICogXHJcbiAgICAgKiBBbHRyaSBldmVudGkgbm9uIGRvdnJlYmJlcm8gcmFwcHJlc2VudGFyZSBwcm9ibGVtaTpcclxuICAgICAqIC0gU2VsZXppb25lOiBub24gY2FtYmlhIG51bGxhXHJcbiAgICAgKiAtIFBhZ2luYXppb25lOiBjYW1iaWEgYSBsaXZlbGxvIHJvb3QgcXVpbmRpIHZpZW5lIHJpY2FyaWNhdG8gdHV0dG8gY29tdW5xdWUsIHN0ZXNzbyB2YWxlIHBlciBsZSBwYWdpbmF6aW9uaSBpbnRlcm5lXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZ3JvdXBTZWFyY2hSZXF1ZXN0c0NhY2hlOiB7IHBhdGg6IHN0cmluZywgcm91dGU6IEdyb3VwUm91dGVGcmFnbWVudFtdLCB2aWV3OiBBcHBTZWFyY2g8YW55PiwgZ3JvdXBfY29sdW1uOiBzdHJpbmcgfVtdID0gW107XHJcblxyXG4gICAgLyoqIFZhcmlhYmlsZSBkJ2FwcG9nZ2lvIHBlciBjYXBpcmUgc2UgYyfDqCBiaXNvZ25vIGRpIHJpLWVmZmV0dHVhcmUgdW5hIHJpY2VyY2EgbyBtZW5vICovXHJcbiAgICBwcml2YXRlIFJlc2VhcmNoTmVlZGVkOiBib29sZWFuID0gZmFsc2U7XHJcbiAgICAvKiogQ29sb25uZSB2aXNpYmlsaSBkZWxsYSB2aXN0YSBhdHR1YWxlLiBWYWxvcml6emF0byBkaSBkZWZhdWx0IGFsIG51bWVybyBtYXNzaW1vIGRpIGNvbG9ubmUgc3VwcG9ydGF0ZSBkYWxsYSB0YWJlbGxhIHBlciBsZSBjYXNpc3RpY2hlIGluIGFzc2VuemEgZGkgY3VzdG9tIGNlbGxzICovXHJcbiAgICBwdWJsaWMgQ29sdW1uczogeyBWaXNpYmlsZTogbnVtYmVyLCBWaXNpYmxlVW5waW5uZWQ6IG51bWJlciwgR2xvYmFsOiBudW1iZXIgfSA9IHsgVmlzaWJpbGU6IDEwMCwgVmlzaWJsZVVucGlubmVkOiAxMDAsIEdsb2JhbDogMTAwIH07XHJcbiAgICAvKiogSW4gY2FzbyBkaSBSb3cgR3JvdXBpbmcgcXVpIHZpZW5lIHNhbHZhdGEgbGEgdmlzdGEgcHJpbmNpcGFsZSBkZWkgZ3J1cHBpIGJhc2UgKi9cclxuICAgIHB1YmxpYyBNYWluR3JvdXBWaWV3OiBBcHBTZWFyY2g8YW55PiA9IG51bGw7XHJcbiAgICAvKiogQ29udGVnZ2lvIGJhc2UgZGVnbGkgb2dnZXR0aS4gSW4gbW9kYWxpdMOgIG5vcm1hbGUgdmllbmUgcmVzZXR0YXRvIGFkIG9nbmkgbnVvdmEgVmlldyBpbnNlcml0YSwgaW4gbW9kYWxpdMOgIFJvd0dyb3VwaW5nIHZpZW5lIHJlc2V0dGF0byBzb2xvIGFkIHVuYSBudW92YSBWaWV3IGRpIGxpdmVsbG8gXCIwXCIgKi9cclxuICAgIHByaXZhdGUgQmFzZUl0ZW1zQ291bnQgPSBudWxsO1xyXG5cclxuICAgIC8qKiBDYWNoZSBwZXIgc2FsdmFyZSBwZXIgb2duaSBjaGlhdmUgZGkgb2duaSBncnVwcG8gY2hpIMOoIGlsIGdydXBwbyByYXBwcmVzZW50YXRvICovXHJcbiAgICBwcml2YXRlIHJnR3JvdXBDYWNoZTogTWFwPHN0cmluZywgR3JvdXA+ID0gbmV3IE1hcDxzdHJpbmcsIEdyb3VwPigpO1xyXG4gICAgLyoqIENhY2hlIHBlciBzYWx2YXJlIHBlciBvZ25pIGNoaWF2ZSBkaSBvZ25pIGdydXBwbyBjaGkgc29ubyBnbGkgb2dnZXR0aSBzb3R0b3N0YW50aSwgbm9uIGRlaSBzb3R0b2dydXBwaSAqL1xyXG4gICAgcHJpdmF0ZSByZ0l0ZW1DYWNoZTogTWFwPHN0cmluZywgYW55W10+ID0gbmV3IE1hcDxzdHJpbmcsIGFueVtdPigpO1xyXG4gICAgLyoqIENhY2hlIHBlciBzYWx2YXJlIHBlciBvZ25pIGNoaWF2ZSBkaSBvZ25pIGdydXBwbyBjaGkgc29ubyBnbGkgb2dnZXR0aSBzb3R0b3N0YW50aSwgbm9uIGRlaSBzb3R0b2dydXBwaSAqL1xyXG4gICAgcHJpdmF0ZSByZ0NoaWxkR3JvdXBzQ2FjaGU6IE1hcDxzdHJpbmcsIEdyb3VwW10+ID0gbmV3IE1hcDxzdHJpbmcsIEdyb3VwW10+KCk7XHJcblxyXG4gICAgLyoqIENhY2hlIGRpIHNlbGV6aW9uZSBIYXNoIC0gT2dnZXR0byBwZXIgbGEgdmFyaWFiaWxlICoqaXRlbXMqKiBkZWxsJ2l0ZW1TZWxlY3Rvci4gRmFjaWxpdGEgbGUgb3BlcmF6aW9uaSBkaSBsb29rdXAgdmlhIGhhc2gqL1xyXG4gICAgcHJpdmF0ZSBpdGVtc0NhY2hlOiBNYXA8c3RyaW5nLCBhbnk+ID0gbmV3IE1hcCgpO1xyXG4gICAgLyoqIENhY2hlIGRpIHNlbGV6aW9uZSBIYXNoIC0gT2dnZXR0byBwZXIgbGEgdmFyaWFiaWxlICoqZ3JvdXBzKiogZGVsbCdpdGVtU2VsZWN0b3IuIEZhY2lsaXRhIGxlIG9wZXJhemlvbmkgZGkgbG9va3VwIHZpYSBoYXNoICovXHJcbiAgICBwcml2YXRlIGdyb3Vwc0NhY2hlOiBNYXA8c3RyaW5nLCBhbnk+ID0gbmV3IE1hcCgpO1xyXG4gICAgLyoqIENhY2hlIGRpIHNlbGV6aW9uZSBIYXNoIC0gT2dnZXR0byBwZXIgbGEgdmFyaWFiaWxlICoqZXhjbHVzaW9ucyoqIGRlbGwnaXRlbVNlbGVjdG9yLiBGYWNpbGl0YSBsZSBvcGVyYXppb25pIGRpIGxvb2t1cCB2aWEgaGFzaCAqL1xyXG4gICAgcHJpdmF0ZSBleGNsdXNpb25zQ2FjaGU6IE1hcDxzdHJpbmcsIGFueT4gPSBuZXcgTWFwKCk7XHJcbiAgICAvKiogQ2FjaGUgZGkgc2VsZXppb25lIEhhc2ggLSBPZ2dldHRvIHBlciBsYSB2YXJpYWJpbGUgKipncm91cF9leGNsdXNpb25zKiogZGVsbCdpdGVtU2VsZWN0b3IuIEZhY2lsaXRhIGxlIG9wZXJhemlvbmkgZGkgbG9va3VwIHZpYSBoYXNoICovXHJcbiAgICBwcml2YXRlIGdyb3VwX2V4Y2x1c2lvbnNDYWNoZTogTWFwPHN0cmluZywgYW55PiA9IG5ldyBNYXAoKTtcclxuXHJcbiAgICAvKiogQ2FjaGUgZGkgc2VsZXppb25lIEhhc2ggLSBPZ2dldHRvIHBlciBsYSB2YXJpYWJpbGUgKippdGVtcyoqIGRlbGwnaXRlbVNlbGVjdG9yLiBGYWNpbGl0YSBsZSBvcGVyYXppb25pIGRpIGxvb2t1cCB2aWEgaW5kaWNlKi9cclxuICAgIHByaXZhdGUgaV9pdGVtc0NhY2hlOiBNYXA8c3RyaW5nLCBudW1iZXI+ID0gbmV3IE1hcCgpO1xyXG4gICAgLyoqIENhY2hlIGRpIHNlbGV6aW9uZSBIYXNoIC0gT2dnZXR0byBwZXIgbGEgdmFyaWFiaWxlICoqZ3JvdXBzKiogZGVsbCdpdGVtU2VsZWN0b3IuIEZhY2lsaXRhIGxlIG9wZXJhemlvbmkgZGkgbG9va3VwIHZpYSBpbmRpY2UgKi9cclxuICAgIHByaXZhdGUgaV9ncm91cHNDYWNoZTogTWFwPHN0cmluZywgbnVtYmVyPiA9IG5ldyBNYXAoKTtcclxuICAgIC8qKiBDYWNoZSBkaSBzZWxlemlvbmUgSGFzaCAtIE9nZ2V0dG8gcGVyIGxhIHZhcmlhYmlsZSAqKmV4Y2x1c2lvbnMqKiBkZWxsJ2l0ZW1TZWxlY3Rvci4gRmFjaWxpdGEgbGUgb3BlcmF6aW9uaSBkaSBsb29rdXAgdmlhIGluZGljZSAqL1xyXG4gICAgcHJpdmF0ZSBpX2V4Y2x1c2lvbnNDYWNoZTogTWFwPHN0cmluZywgbnVtYmVyPiA9IG5ldyBNYXAoKTtcclxuICAgIC8qKiBDYWNoZSBkaSBzZWxlemlvbmUgSGFzaCAtIE9nZ2V0dG8gcGVyIGxhIHZhcmlhYmlsZSAqKmdyb3VwX2V4Y2x1c2lvbnMqKiBkZWxsJ2l0ZW1TZWxlY3Rvci4gRmFjaWxpdGEgbGUgb3BlcmF6aW9uaSBkaSBsb29rdXAgdmlhIGluZGljZSAqL1xyXG4gICAgcHJpdmF0ZSBpX2dyb3VwX2V4Y2x1c2lvbnNDYWNoZTogTWFwPHN0cmluZywgbnVtYmVyPiA9IG5ldyBNYXAoKTtcclxuXHJcbiAgICAvKiogSW5kaWNhIHNlIGNpIHNvbm8gZGVsbGUgY29sb25uZSBwaW5uYXRlIGUgdmlzaWJpbGkuIFNlcnZlIHBlciBwb3RlciBzZXR0YXJlIHR1dHRlIGxlIGNvbG9ubmUgcHJpbWEgY2hlIGFycml2aW5vIGRhdGkgYSBwaW5uZWQqL1xyXG4gICAgcHVibGljIEhhc1Bpbm5lZENvbHVtbnM6IGJvb2xlYW5cclxuICAgIC8qKiBMYXJnaGV6emEgY2FsY29sYXRhIGRlbCBjb250YWluZXIgZGVsbGUgY29sb25uZSBwaW5uYXRlICovXHJcbiAgICBwdWJsaWMgUGlubmVkQ29udGFpbmVyV2lkdGg6IG51bWJlcjtcclxuICAgIC8qKiBJbmRpY2Egc2Ugbm9ub3N0YW50ZSBzaWFtbyBpbiBtb2RhbGl0w6AgYXJyYXkgc29ubyBzdGF0aSBpbmRpdmlkdWF0aSBkZWkgZ3J1cHBpLiBJbiB0YWwgY2FzbyBlcy10YWJsZSBzaSBjb21wb3J0YSBkYSBwc2V1ZG8gYmFja2VuZCBlZCBlZmZldHR1YSBsZSBhZ2dyZWdhemlvbmkgZSByYWdncnVwcGFtZW50aSBjb21wbGV0YW1lbnRlIGxhdG8gY2xpZW50ICovXHJcbiAgICBwdWJsaWMgQXJyYXlHcm91cGluZzogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAgIHB1YmxpYyBQYWdlck9wdGlvbnM6IHsgUGFnZXJDb3VudDogbnVtYmVyLCBTaG93Q291bnQ6IGJvb2xlYW4sIFNob3dQYWdpbmc6IGJvb2xlYW4sIFVzZXNWaWV3OiBib29sZWFuLCBWaWV3OiBhbnksIFJlYWR5OiBib29sZWFuLCBTZWFyY2hlczogJ2l0ZW1zJyB8ICdncm91cHMnIH0gPVxyXG4gICAgICAgIHsgUGFnZXJDb3VudDogbnVsbCwgU2hvd0NvdW50OiB0cnVlLCBTaG93UGFnaW5nOiB0cnVlLCBVc2VzVmlldzogdHJ1ZSwgVmlldzogbnVsbCwgUmVhZHk6IGZhbHNlLCBTZWFyY2hlczogJ2l0ZW1zJyB9O1xyXG5cclxuICAgIC8vICNyZWdpb24gQ2ljbG8gZGkgdml0YSBFUy1UYWJsZSAtIEluaXppYWxpenphemlvbmlcclxuXHJcbiAgICAvKiogQGlnbm9yZSAqL1xyXG4gICAgcHVibGljIG5nT25Jbml0KCkge1xyXG4gICAgICAgIC8vUGVyIHBvdGVyIGNhbWJpYXJlIGlsIGxheW91dCBpbiBiYXNlIGFsIGxpdmVsbG8gZ2VyYXJjaGljbyBpbCBjb21wb25lbnRlIGRldmEgYXZlcmUgaWwgcGllbm8gY29udHJvbGxvIGRpIG9nbmkgY2VsbGEsXHJcbiAgICAgICAgLy9jaGUgY29uIHNvbG8gbGEgcHJvaWV6aW9uZSAoc2VuemEgY2VsbGUgY3Vzb3RtKSBub24gw6ggZGlzcG9uaWJpbGVcclxuICAgICAgICBpZiAodGhpcy5IaWVyYXJjaHkgJiYgIXRoaXMuVXNlQ3VzdG9tQ2VsbHMpXHJcbiAgICAgICAgICAgIHRocm93IFwiRXMtdGFibGUgZXJyb3I6IFBlciBwb3RlciB1dGlsaXp6YXJlIGwnZXMtdGFibGUgY29uIFtIaWVyYXJjaHldPVxcXCJ0cnVlXFxcIiDDqCByaWNoaWVzdG8gYW5jaGUgW1VzZUN1c3RvbUNlbGxzXT1cXFwidHJ1ZVxcXCJcIjtcclxuXHJcbiAgICAgICAgLy8gY2xpY2sgZGVzdHJvIHN1IHVuYSByaWdhIGNvbiBzZWxlemlvbmUgYXR0aXZhOiBUaXJvIGZ1b3JpIGlsIGNvbnRleHQgbWVudSBlIHNlbGV6aW9uZSBsJ2VsZW1lbnRvIGNvcnJlbnRlXHJcbiAgICAgICAgdGhpcy5jdHhNZW51U3Vic2NyaXB0aW9uID0gKHRoaXMuQ29udGV4dE1lbnUgfHwgdGhpcy50YWJsZUVtcHR5TWVudSkub3Blbi5zdWJzY3JpYmUodCA9PiB7XHJcbiAgICAgICAgICAgIC8vIEdydXBwaSB2YSBiZW5lLCBvZ2dldHRpIHB1cmUsIG1hIHNlcGFyYXRvcmkgZnJhIGdydXBwaSBwcm9wcmlvIG5vLi4uXHJcbiAgICAgICAgICAgIGlmKHQuaXRlbS5fc2VwKSByZXR1cm47XHJcblxyXG4gICAgICAgICAgICBsZXQgc2hvdWxkRW1pdCA9ICF0Lml0ZW0uX3NlbGVjdGVkO1xyXG5cclxuICAgICAgICAgICAgdC5pdGVtLl9zZWxlY3RlZCA9IHRydWU7XHJcbiAgICAgICAgICAgIHZhciBpdGVtU2VsZWN0aW9uID0gdGhpcy5oYW5kbGVJdGVtc1NlbGVjdGlvbihbdC5pdGVtXSk7XHJcbiAgICAgICAgICAgIHRoaXMuY2hhbmdlZCgpO1xyXG5cclxuICAgICAgICAgICAgaWYgKHNob3VsZEVtaXQpXHJcbiAgICAgICAgICAgICAgICB0aGlzLm9uU2VsZWN0aW9uQ2hhbmdlZC5lbWl0KGl0ZW1TZWxlY3Rpb24pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBAaWdub3JlICovXHJcbiAgICBwdWJsaWMgbmdBZnRlclZpZXdJbml0KCkge1xyXG4gICAgICAgIC8vIFNlIHV0aWxpenpvIGxhIG5ldyBzcGljeSBtb2RlIGRlZHVjbyB0dXR0aSBpIHBhcmFtZXRyaSBkaSBsYXZvcm8gcG9zc2liaWxpIGFsIGNhcmljYW1lbnRvIGRlbGxhIHRhYmVsbGFcclxuICAgICAgICAvLyBWZW5nb25vIHNvdnJhc2NyaXR0ZSBzb2xvIGxlIHByb3ByaWV0w6Agbm9uIGltcG9zdGF0ZSBkYWxsJ3V0ZW50ZVxyXG4gICAgICAgIGlmICh0aGlzLkVzVGRzRGlyZWN0aXZlICYmIHRoaXMuRXNUZHNEaXJlY3RpdmUubGVuZ3RoID4gMCAmJiB0aGlzLkVzVGhzRGlyZWN0aXZlICYmIHRoaXMuRXNUaHNEaXJlY3RpdmUubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5Vc2VDdXN0b21DZWxscyA9PSBudWxsKSB0aGlzLlVzZUN1c3RvbUNlbGxzID0gdHJ1ZTtcclxuICAgICAgICAgICAgaWYgKHRoaXMuSGlkZGVuQ29sdW1ucyA9PSBudWxsICYmIHRoaXMuVXNlQ3VzdG9tQ2VsbHMpIHRoaXMuSGlkZGVuQ29sdW1ucyA9IHRydWU7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLkNvbHVtbnNPcmRlcmluZyA9PSBudWxsICYmIHRoaXMuVXNlQ3VzdG9tQ2VsbHMpIHRoaXMuQ29sdW1uc09yZGVyaW5nID0gdHJ1ZTtcclxuICAgICAgICAgICAgaWYgKHRoaXMuT3JkZXJCeUNvbHVtbiA9PSBudWxsICYmIHRoaXMuVXNlQ3VzdG9tQ2VsbHMpIHRoaXMuT3JkZXJCeUNvbHVtbiA9IHRydWU7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLlNlbGVjdEFsbCA9PSBudWxsICYmIHRoaXMuU2VsZWN0aW9uKSB0aGlzLlNlbGVjdEFsbCA9IHRydWU7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLlNoaWZ0Q2xpY2sgPT0gbnVsbCAmJiB0aGlzLlNlbGVjdGlvbikgdGhpcy5TaGlmdENsaWNrID0gdHJ1ZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTZSBsJ0lucHV0IMOoIG51bGwgKHZhbG9yZSBub24gc2V0dGF0bykgdmVkZSBzZSBjJ8OoIHVuIGRlZmF1bHQgY29uIGN1aSB2YWxvcml6emFybG8uIFNlIG5vbiBjJ8OoIHV0aWxpenphIGlsIHZhbG9yZSBkaSBmYWxsYmFjayAocXVhbG9yYSBmb3JuaXRvKVxyXG4gICAgICogXHJcbiAgICAgKiBAcGFyYW0ge1R9IGlucHV0VmFsdWUgVmFsb3JlIGRlbGwnSW5wdXRcclxuICAgICAqIEBwYXJhbSB7VH0gZGVmYXVsdFZhbHVlIFZhbG9yZSBkaSBkZWZhdWx0IGltcG9zdGF0byBkYSBjb25maWd1cmF6aW9uZVxyXG4gICAgICogQHBhcmFtIHtUfSBmYWxsYmFja1ZhbHVlIFZhbG9yZSBkZWxsJ0lucHV0IHBlciBxdWFuZG8gbm9uIMOoIHN0YXRvIGFzc2VnbmF0byBkYWwgcHJvZ3JhbW1hdG9yZSBlIG5vbiBoYSB1biBkZWZhdWx0XHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgSW5wdXRPckRlZmF1bHQ8VD4oaW5wdXRWYWx1ZTogVCwgZGVmYXVsdFZhbHVlOiBULCBmYWxsYmFja1ZhbHVlPzogVCkge1xyXG5cclxuICAgICAgICAvLyBJbnB1dCB2YWxvcml6emF0byBkYWwgcHJvZ3JhbW1hdG9yZVxyXG4gICAgICAgIGlmIChpbnB1dFZhbHVlICE9IG51bGwgJiYgaW5wdXRWYWx1ZSAhPSB1bmRlZmluZWQpXHJcbiAgICAgICAgICAgIHJldHVybiBpbnB1dFZhbHVlO1xyXG5cclxuICAgICAgICAvLyBJbnB1dCB2YWxvcml6emF0byBkYSBjb25maWd1cmF6aW9uZSBnbG9iYWxlXHJcbiAgICAgICAgaWYgKGRlZmF1bHRWYWx1ZSAhPSBudWxsICYmIGRlZmF1bHRWYWx1ZSAhPSB1bmRlZmluZWQpXHJcbiAgICAgICAgICAgIHJldHVybiBkZWZhdWx0VmFsdWU7XHJcblxyXG4gICAgICAgIC8vSW5wdXQgbm9uIHZhbG9yaXp6YXRvIGRhIG5pZW50ZSBlIGRhIG5lc3N1bm9cclxuICAgICAgICBpZiAoZmFsbGJhY2tWYWx1ZSAhPSBudWxsICYmIGZhbGxiYWNrVmFsdWUgIT0gdW5kZWZpbmVkKVxyXG4gICAgICAgICAgICByZXR1cm4gZmFsbGJhY2tWYWx1ZTtcclxuXHJcbiAgICAgICAgLy8gSSBjYXNpIGluIGN1aSBzaSBhcnJpdmEgcXVpIHNvbm8gaSBjYXNpIGRpIElucHV0IGNoZSBkaSBkZWZhdWx0IHZhIGJlbmUgY2hlIHNpYW5vIG51bGxpIGUgY2hlIG5lc3N1bm8gc2kgY2FnYVxyXG4gICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBAaWdub3JlICovXHJcbiAgICBwdWJsaWMgbmdPbkRlc3Ryb3koKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuY3R4TWVudVN1YnNjcmlwdGlvbilcclxuICAgICAgICAgICAgdGhpcy5jdHhNZW51U3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBpZ25vcmUgKi9cclxuICAgIHB1YmxpYyBhc3luYyBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XHJcbiAgICAgICAgbGV0IG5ld1NlYXJjaFZpZXcgPSBjaGFuZ2VzWydTZWFyY2hWaWV3J107XHJcbiAgICAgICAgaWYgKG5ld1NlYXJjaFZpZXcgJiYgdGhpcy5TZWFyY2hWaWV3KVxyXG4gICAgICAgICAgICB0aGlzLmFycmF5UHVsc2FudGkgPSB0aGlzLmdldFBhZ2VzQXJyYXkoNiwgdGhpcy5TZWFyY2hWaWV3LnBhZ2UsIHRoaXMuU2VhcmNoVmlldy5wYWdlcyB8fCAxKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyAjZW5kcmVnaW9uXHJcblxyXG4gICAgLy8gI3JlZ2lvbiBJbXBsZW1lbnRhemlvbmUgQ29udHJvbFZhbHVlQWNjZXNzb3IgaWdub3JhYmlsZVxyXG5cclxuICAgIC8qKiBAaWdub3JlICovXHJcbiAgICBwdWJsaWMgcmVnaXN0ZXJPbkNoYW5nZShmbik6IHZvaWQgeyB0aGlzLnByb3BhZ2F0ZUNoYW5nZSA9IGZuOyB9XHJcbiAgICAvKiogQGlnbm9yZSAqL1xyXG4gICAgcHVibGljIHJlZ2lzdGVyT25Ub3VjaGVkKGZuKTogdm9pZCB7IH1cclxuICAgIC8qKiBAaWdub3JlICovXHJcbiAgICBjaGFuZ2VkKCkgeyB0aGlzLnByb3BhZ2F0ZUNoYW5nZSh0aGlzLlZpZXcpOyB9XHJcbiAgICAvKiogQGlnbm9yZSAqL1xyXG4gICAgcHJvcGFnYXRlQ2hhbmdlID0gKF86IGFueSkgPT4geyB9O1xyXG5cclxuICAgIC8vICNlbmRyZWdpb25cclxuXHJcbiAgICAvKiogQGlnbm9yZSAqL1xyXG4gICAgcHVibGljIHdyaXRlVmFsdWUob2JqKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5WaWV3ID0gb2JqID8gb2JqIDogbnVsbDtcclxuXHJcbiAgICAgICAgLy8gTWkgw6ggYXJyaXZhdGEgbCdBcHBTZWFyY2ggcXVpbmRpIGRpIHNpY3VybyBub24gaG8gdW5hIHJpY2VyY2EgaW4gcHJvZ3Jlc3NcclxuICAgICAgICB0aGlzLnJlc2VhcmNoSW5Qcm9ncmVzcyA9IGZhbHNlO1xyXG5cclxuICAgICAgICBpZiAoIXRoaXMuVmlldyAmJiAhdGhpcy5TZWFyY2hWaWV3KSB7XHJcbiAgICAgICAgICAgIC8vIFN1IHZpZXcgbnVsbGEgZXZpdG8gZGkgZmFyZSBwcmVzc29jaMOpIHF1YWxzaWFzaSBjb3NhLiBTZSBhcnJpdmEgdW4gbnVsbCBkZXZvIGFuY2hlIGFzc2ljdXJhcm1pIGRpIG5vbiBtb3N0cmFyZSBudWxsYVxyXG4gICAgICAgICAgICB0aGlzLmJvdW5kU291cmNlID0gdGhpcy5UTVBCb3VuZFNvdXJjZSB8fCBbXTtcclxuXHJcbiAgICAgICAgICAgIC8vIFBlciBlc3NlcmUgc2ljdXJvIGNoZSBkb3BvIHVuIGJpbmQgZGkgb2dnZXR0aSBsYSBlcy10YWJsZSBhZ2dpb3JuaSBsYSBncmFmaWNhXHJcbiAgICAgICAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBTZSBwZXIgc2JhZ2xpbyBsJ29nZ2V0dG8gY2hlIG1pIGFycml2YSBub24gw6ggdGlwaXp6YXRvIChpbnN0YW5jZW9mIEFwcFNlYXJjaCByZXN0aXR1aXNjZSBmYWxzZSBhbmNoZSBzZSDDqCBkZWwgdGlwbyBnaXVzdG8pXHJcbiAgICAgICAgLy8gbG8gY29ycmVnZ28tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG4gICAgICAgIGlmICh0aGlzLlZpZXcgJiYgdHlwZW9mICh0aGlzLlZpZXcgYXMgYW55KS5yZXN1bHQgIT0gJ3VuZGVmaW5lZCcgJiYgISh0aGlzLlZpZXcgaW5zdGFuY2VvZiBSZXBvcnREZWZpbml0aW9uKSkge1xyXG4gICAgICAgICAgICAodGhpcy5WaWV3IGFzIGFueSkuX19wcm90b19fID0gbmV3IFJlcG9ydERlZmluaXRpb24oKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAodGhpcy5WaWV3ICYmIHR5cGVvZiAodGhpcy5WaWV3IGFzIGFueSkuaXRlbXNwZXJwYWdlb3ZlcnJpZGUgIT0gJ3VuZGVmaW5lZCcgJiYgISh0aGlzLlZpZXcgaW5zdGFuY2VvZiBBcHBTZWFyY2gpKSB7XHJcbiAgICAgICAgICAgICh0aGlzLlZpZXcgYXMgYW55KS5fX3Byb3RvX18gPSBuZXcgQXBwU2VhcmNoKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2UgaWYgKHRoaXMuU2VhcmNoVmlldyAmJiB0eXBlb2YgKHRoaXMuU2VhcmNoVmlldyBhcyBhbnkpLml0ZW1zcGVycGFnZW92ZXJyaWRlICE9ICd1bmRlZmluZWQnICYmICEodGhpcy5TZWFyY2hWaWV3IGluc3RhbmNlb2YgQXBwU2VhcmNoKSkge1xyXG4gICAgICAgICAgICAodGhpcy5TZWFyY2hWaWV3IGFzIGFueSkuX19wcm90b19fID0gbmV3IEFwcFNlYXJjaCgpO1xyXG4gICAgICAgIH1cclxuICAgICAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG4gICAgICAgIGlmICh0aGlzLlZpZXcgJiYgdGhpcy5WaWV3IGluc3RhbmNlb2YgUmVwb3J0RGVmaW5pdGlvbikge1xyXG4gICAgICAgICAgICAvLyBTZSBtaSBhcnJpdmEgdW5hIHJlcG9ydCBkZWZpbml0aW9uIHZ1b2wgZGlyZSBjaGUgcG90cmVpIGF2ZXJlIGRlaSByaXN1bHRhdGkgZGEgdmlzdWFsaXp6YXJlXHJcbiAgICAgICAgICAgIHRoaXMuc2V0TW9kZSgncmVwb3J0Jyk7XHJcblxyXG4gICAgICAgICAgICB0aGlzLlJlcG9ydFZhbHVlcyA9IHRoaXMuVmlldy5yZXN1bHQ7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLlJlcG9ydFZhbHVlcylcclxuICAgICAgICAgICAgICAgIHRoaXMucmV2aWV3UmVwb3J0QmluZGluZ3MoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAodGhpcy5WaWV3ICYmIHRoaXMuVmlldyBpbnN0YW5jZW9mIEFwcFNlYXJjaCkge1xyXG4gICAgICAgICAgICAvLyBTZSBjYW1iaWEgbCdvZ2dldHRvIGludGVybyBzaWduaWZpY2EgY2hlIGhvIHJpbWFuZGF0byBsYSByaWNlcmNhXHJcbiAgICAgICAgICAgIHRoaXMuc2V0TW9kZSgndmlldycpO1xyXG5cclxuICAgICAgICAgICAgbGV0IGZpcnN0SXRlbUdyb3VwT3JOb0dyb3VwaW5nID0gKHRoaXMuVmlldy5yZXF1ZXN0ZWRncm91cHM/Lmxlbmd0aCB8fCAwKSA9PSAwO1xyXG5cclxuICAgICAgICAgICAgLy8gU2UgdmVuZ28gZGEgdW5hIHJpY2VyY2EgaW50ZXJuYSBtYW50ZW5nbyBsbyBzdGF0byBkaSBzZWxlemlvbmUgcHJlY2VkZW50ZSAocXVpbmRpIHN1IGNhbWJpbyBwYWdpbmEsIGNhbWJpbyBpcHAsIGVjYy4uLilcclxuICAgICAgICAgICAgLy8gc2UgaW52ZWNlIGwndXRlbnRlIGhhIGZhdHRvIHVuYSByaWNlcmNhIGx1aSAocXVpbmRpIGNhbWJpYW5kbyBmaWx0cmkpLCBzZWNjbyBsZSBpbmZvIGRpIHNlbGV6aW9uZVxyXG4gICAgICAgICAgICBpZiAoIXRoaXMuVmlldy5zZWxlY3Rpb24gfHwgKCF0aGlzLlZpZXcuaW50ZXJuYWxzZWFyY2hyZXF1ZXN0ICYmIGZpcnN0SXRlbUdyb3VwT3JOb0dyb3VwaW5nKSB8fCAhdGhpcy5Vc2VTZWxlY3Rpb25DYWNoZSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jbGVhclNlbGVjdGlvbkNhY2hlcygpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5WaWV3LnNlbGVjdGlvbiA9IG5ldyBJdGVtc1NlbGVjdGlvbihbXSk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLm9uU2VsZWN0aW9uQ2hhbmdlZC5lbWl0KHRoaXMuVmlldy5zZWxlY3Rpb24pO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICB0aGlzLlZpZXcuaW50ZXJuYWxzZWFyY2hyZXF1ZXN0ID0gZmFsc2U7XHJcblxyXG4gICAgICAgICAgICAvLyBSZWN1cGVybyBQcmVmZXJlbmNlXHJcbiAgICAgICAgICAgIGlmICh0aGlzLlNhdmVQcmVmZXJlbmNlcykge1xyXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLm5nQ29udHJvbC5uYW1lKVxyXG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJOb24gcG9zc28gdXRpbGl6emFyZSBsZSBwcmVmZXJlbmNlIHNlbnphIGF2ZXJlIHVuICduYW1lJyBwZXIgcXVlc3RhIHRhYmVsbGFcIik7XHJcbiAgICAgICAgICAgICAgICBlbHNlIGlmICghdGhpcy5wcmVmU2VydmljZSlcclxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiTm9uIHBvc3NvIHV0aWxpenphcmUgbGUgcHJlZmVyZW5jZSBzZW56YSBjaGUgaWwgcGFjY2hldHRvIEBlc2ZhZW56YS9wcmVmZXJlbmNlcyBzaWEgaW5zdGFsbGF0b1wiKTtcclxuICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmVmcyA9IHRoaXMucHJlZlNlcnZpY2UucmV0cmlldmU8eyBjb2x1bW5zOiBzdHJpbmdbXSwgY29sdW1uX29yZGVyaW5nOiBzdHJpbmdbXSB9Pig8c3RyaW5nPnRoaXMubmdDb250cm9sLm5hbWUpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcmVmcykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLlZpZXcuY29sdW1ucyA9IHByZWZzLmNvbHVtbnM7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuVmlldy5jb2x1bW5fb3JkZXJpbmcgPSBwcmVmcy5jb2x1bW5fb3JkZXJpbmc7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBMYSBwYWdpbmF6aW9uZSBkZXZvIGZhcmxhIHNvbGFtZW50ZSBxdWFuZG8gcmljaGllZG8gbyB1biBncnVwcG8gcHJpbmNpcGFsZSAoc2Ugc29ubyBpbiByb3cgZ3JvdXBpbmcpIG8gc2Ugbm9uIHJpY2hpZWRvIGdydXBwaSAoaW4gdHV0dGkgbGdpIGFsdHJpIGNhc2kpXHJcbiAgICAgICAgICAgIGlmIChmaXJzdEl0ZW1Hcm91cE9yTm9Hcm91cGluZylcclxuICAgICAgICAgICAgICAgIHRoaXMuYXJyYXlQdWxzYW50aSA9IHRoaXMuZ2V0UGFnZXNBcnJheSg2LCB0aGlzLlZpZXcucGFnZSwgdGhpcy5WaWV3LnBhZ2VzIHx8IDEpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIGlmICh0aGlzLlZpZXcgJiYgKHRoaXMuVmlldy5sZW5ndGggIT0gbnVsbCAmJiB0aGlzLlZpZXcubGVuZ3RoICE9IHVuZGVmaW5lZCkpIHtcclxuICAgICAgICAgICAgdGhpcy5zZXRNb2RlKCdhcnJheScpO1xyXG5cclxuICAgICAgICAgICAgaWYgKCF0aGlzLlVzZVNlbGVjdGlvbkNhY2hlIHx8ICF0aGlzLmFycmF5bW9kZVNlbGVjdGlvbikge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jbGVhclNlbGVjdGlvbkNhY2hlcygpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5hcnJheW1vZGVTZWxlY3Rpb24gPSBuZXcgSXRlbXNTZWxlY3Rpb24oW10pOztcclxuICAgICAgICAgICAgICAgIHRoaXMub25TZWxlY3Rpb25DaGFuZ2VkLmVtaXQodGhpcy5hcnJheW1vZGVTZWxlY3Rpb24pO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBSZWN1cGVybyBQcmVmZXJlbmNlXHJcbiAgICAgICAgICAgIGlmICh0aGlzLlNhdmVQcmVmZXJlbmNlcykge1xyXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLm5nQ29udHJvbC5uYW1lKVxyXG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJOb24gcG9zc28gdXRpbGl6emFyZSBsZSBwcmVmZXJlbmNlIHNlbnphIGF2ZXJlIHVuICduYW1lJyBwZXIgcXVlc3RhIHRhYmVsbGFcIik7XHJcbiAgICAgICAgICAgICAgICBlbHNlIGlmICghdGhpcy5wcmVmU2VydmljZSlcclxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiTm9uIHBvc3NvIHV0aWxpenphcmUgbGUgcHJlZmVyZW5jZSBzZW56YSBjaGUgaWwgcGFjY2hldHRvIEBlc2ZhZW56YS9wcmVmZXJlbmNlcyBzaWEgaW5zdGFsbGF0b1wiKTtcclxuICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmVmcyA9IHRoaXMucHJlZlNlcnZpY2UucmV0cmlldmU8eyBjb2x1bW5zOiBzdHJpbmdbXSwgY29sdW1uX29yZGVyaW5nOiBzdHJpbmdbXSB9Pig8c3RyaW5nPnRoaXMubmdDb250cm9sLm5hbWUpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcmVmcykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFycmF5Q29sdW1ucyA9IHByZWZzLmNvbHVtbnM7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYXJyYXlDb2x1bW5PcmRlcmluZyA9IHByZWZzLmNvbHVtbl9vcmRlcmluZztcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLlNlYXJjaFZpZXcpXHJcbiAgICAgICAgICAgICAgICB0aGlzLmFycmF5UHVsc2FudGkgPSB0aGlzLmdldFBhZ2VzQXJyYXkoNiwgdGhpcy5TZWFyY2hWaWV3LnBhZ2UsIHRoaXMuU2VhcmNoVmlldy5wYWdlcyB8fCAxKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0aGlzLlZpZXcgJiYgISh0aGlzLlZpZXcgaW5zdGFuY2VvZiBSZXBvcnREZWZpbml0aW9uKSlcclxuICAgICAgICAgICAgdGhpcy5maW5hbGl6ZUNvbnRleHQoKTtcclxuXHJcbiAgICAgICAgdGhpcy5wb3N0Qm91bmRTb3VyY2VDYWxjdWxhdGlvbigpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogU3VjY2Vzc2l2YW1lbnRlIGFsIGJpbmQgZGVsIG51b3ZvIGlucHV0IHF1ZXN0YSBmdW56aW9uZSBzaSBvY2N1cGEgZGkgZmluYWxpenphcmUgdHV0dGkgaSBwYXJhbWV0cmkgZGkgZnVuemlvbmFtZW50byBkZWxsJ2VzLXRhYmxlIFxyXG4gICAgICogaW4gYmFzZSBhIElucHV0IC0gTW9kZWxsbywgZSBxdWFsc2lhc2kgYWx0cmEgY29zYSBwb3NzYSBzZXJ2aXJlXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZmluYWxpemVDb250ZXh0KCkge1xyXG4gICAgICAgIGxldCB2aWV3Q2FzdGVkID0gdGhpcy5WaWV3IGFzIEFwcFNlYXJjaDxhbnk+O1xyXG5cclxuICAgICAgICAvKlxyXG4gICAgICAgICAqVXNvIGxhIHRlY25pY2EgZGkgRW5kbGVzc1Njcm9sbCBzZSBsYSB2YXJpYWJpbGUgcmVsYXRpdmEgw6ggYXR0aXZhIGUgc2VcclxuICAgICAgICAgKiAxKSBIbyB1biBBcnJheSwgb3BwdXJlXHJcbiAgICAgICAgICogMikgSG8gdW4gQXBwU2VhcmNoIGNoZSBzdGEgY2VyY2FuZG8gY29uIHBhZ2luYXppb25lIFwiVHV0dG9cIiwgb3BwdXJlXHJcbiAgICAgICAgICogMykgSG8gdW4gQXBwU2VhcmNoIGNoZSBzdGEgY2VyY2FuZG8gY29uIHBhZ2luYXppb25lIGRpdmVyc2EgZGEgXCJUdXR0b1wiIG1hIGNvbiBsYSB2YXJpYWJpbGUgRW5kbGVzc1Njcm9sbE9ubHlGb3JBbGwgYSBmYWxzZVxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIGxldCBpc0FwcFNlYXJjaFdpdGhJcHBNYXggPSB0aGlzLnZpZXdNb2RlICYmIHZpZXdDYXN0ZWQuaXRlbXNwZXJwYWdlb3ZlcnJpZGUgPT0gdGhpcy5kZWZhdWx0QWxsUGFnZU92ZXJyaWRlO1xyXG4gICAgICAgIGxldCBpc0FwcFNlYXJjaE5vTWF4SXBwID0gdGhpcy52aWV3TW9kZSAmJiB2aWV3Q2FzdGVkLml0ZW1zcGVycGFnZW92ZXJyaWRlICE9IHRoaXMuZGVmYXVsdEFsbFBhZ2VPdmVycmlkZTtcclxuICAgICAgICB0aGlzLlVzZUVuZGxlc3NzY3JvbGwgPSB0aGlzLkVuZGxlc3NTY3JvbGwgJiYgKHRoaXMuYXJyYXlNb2RlIHx8IGlzQXBwU2VhcmNoV2l0aElwcE1heCB8fCAoaXNBcHBTZWFyY2hOb01heElwcCAmJiAhdGhpcy5FbmRsZXNzU2Nyb2xsT25seUZvckFsbCkpO1xyXG5cclxuICAgICAgICBsZXQgaGFzUm93R3JvdXBzID0gKHZpZXdDYXN0ZWQuZ3JvdXBpbmdzICYmIHZpZXdDYXN0ZWQuZ3JvdXBpbmdzLmZpbHRlcih0ID0+ICF0LmFnZ3JlZ2F0aW9uKS5sZW5ndGggPiAwKSB8fCAodGhpcy5hcnJheU1vZGUgJiYgdGhpcy5Fc1Roc0RpcmVjdGl2ZS5zb21lKHQgPT4gdC50aEdyb3VwKSk7XHJcblxyXG4gICAgICAgIC8vIFNlIGhvIGRlaSBncnVwcGkgaW4gbW9kYWxpdMOgIGFycmF5IGRldm8gc2lzdGVtYXJlIHVuIHBvJyBkaSB2YXJpYWJpbGkgY2hlIGRpdmVudGFubyBpbnNlbnNhdGVcclxuICAgICAgICBpZiAodGhpcy5hcnJheU1vZGUpIHtcclxuICAgICAgICAgICAgaWYgKGhhc1Jvd0dyb3VwcylcclxuICAgICAgICAgICAgICAgIHRoaXMuVXNlQXJyYXlNb2RlUGFnaW5nID0gZmFsc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBSaWVtcGltZW50byBkZWxsYSBUTVBCb3VuZFNvdXJjZSBjb24gZ2xpIG9nZ2V0dGkgY2hlIHZlcnJhbm5vIHBvaSBtb3N0cmF0aSBhZCBpbnRlcmZhY2NpYVxyXG4gICAgICAgIGlmICh0aGlzLlVzZUVuZGxlc3NzY3JvbGwgJiYgIWhhc1Jvd0dyb3Vwcykge1xyXG4gICAgICAgICAgICB0aGlzLmFkZGVkU2xpY2VzID0gW107XHJcbiAgICAgICAgICAgIHRoaXMuYm91bmRTdWJTb3VyY2VzID0gdGhpcy5nZXRJdGVtU2xpY2VzKCk7XHJcbiAgICAgICAgICAgIGxldCBmaXJzdFN1YiA9IHRoaXMuYm91bmRTdWJTb3VyY2VzWzBdO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5UTVBCb3VuZFNvdXJjZSA9IGZpcnN0U3ViID8gZmlyc3RTdWIgOiBbXTtcclxuICAgICAgICAgICAgaWYgKGZpcnN0U3ViKVxyXG4gICAgICAgICAgICAgICAgdGhpcy5hZGRlZFNsaWNlcy5wdXNoKDApO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgIHRoaXMuVE1QQm91bmRTb3VyY2UgPSB0aGlzLmdldEl0ZW1zQnlNb2RlKGZhbHNlLCAhdGhpcy5pbnRlcm5hbFdyaXRlQ2FsbCk7XHJcblxyXG4gICAgICAgIC8vIFNlIGhvIHVuYSBnZXJhcmNoaWEsIGFzc2Vnbm8gaSBsaXZlbGxpIGdlcmFyY2hpY2kgYWxsYSBUTVBCb3VuZFNvdXJjZVxyXG4gICAgICAgIGlmICh0aGlzLkhpZXJhcmNoeSAmJiAhaGFzUm93R3JvdXBzKVxyXG4gICAgICAgICAgICB0aGlzLmFzc2lnbkhpZXJhcmNoeUxldmVscyh0aGlzLlRNUEJvdW5kU291cmNlKTtcclxuXHJcbiAgICAgICAgLy8gTCdoYXNoaW5nIGRlZ2xpIG9nZ2V0dGkgbG8gZmFjY2lvIGEgcHJlc2NpbmRlcmVcclxuICAgICAgICB0aGlzLmNhbGN1bGF0ZUhhc2godGhpcy5UTVBCb3VuZFNvdXJjZSk7XHJcblxyXG4gICAgICAgIC8vIEFzc2Vnbm8gYSB1bmEgdmFyaWFiaWxlIG1pYSBsJ2V2ZW50dWFsZSBvdmVycmlkZSBwZXIgbGEgY2xhc3NlIGRlbGxhIHJpZ2FcclxuICAgICAgICAvLyBTZSBwb2kgc29ubyBpbiBtb2RhbGl0w6AgZ2VyYXJjaGljYSBpbmlldHRvIGFuY2hlIGxhIGNsYXNzZSBwZXIgbGEgY29uZmlndXJhemlvbmUgZGVsIGxpdmVsbG8gZGVsbGEgcmlnYVxyXG4gICAgICAgIGlmICgodGhpcy5UTVBCb3VuZFNvdXJjZSAmJiB0aGlzLlJvd0NsYXNzQXNzaWduZXIpIHx8IHRoaXMuSGllcmFyY2h5KSB7XHJcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5UTVBCb3VuZFNvdXJjZS5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgbGV0IGl0ZW0gPSB0aGlzLlRNUEJvdW5kU291cmNlW2ldO1xyXG4gICAgICAgICAgICAgICAgaXRlbS5fcm93Q2xhc3MgPSB0aGlzLlJvd0NsYXNzQXNzaWduZXIgPyB0aGlzLlJvd0NsYXNzQXNzaWduZXIoaXRlbSkgOiBcIlwiO1xyXG4gICAgICAgICAgICAgICAgaXRlbS5fcm93Q2xhc3MgKz0gdGhpcy5IaWVyYXJjaHkgPyBcIiBlc3Qtcm93LWx2bC1cIiArIGl0ZW0uX2xldmVsIDogXCJcIjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKiogR2VuZXJhIGxlIGluZm9ybXppb25pIGRpIHBhZ2luYXppb25lIHBlciBsYSB2aXN0YSBnbG9iYWxlIGRlbGwnZXMtdGFibGUgKi9cclxuICAgIHByaXZhdGUgc2V0dXBQYWdpbmdJbmZvcm1hdGlvbnMoKSB7XHJcbiAgICAgICAgdGhpcy5QYWdlck9wdGlvbnMuU2hvd0NvdW50ID0gIXRoaXMuSGlkZVBhZ2luZ0NvdW50O1xyXG4gICAgICAgIGlmICh0aGlzLmFycmF5TW9kZSAmJiB0aGlzLlVzZUFycmF5TW9kZVBhZ2luZyAmJiAhdGhpcy5TZWFyY2hWaWV3KSB7XHJcbiAgICAgICAgICAgIHRoaXMuUGFnZXJPcHRpb25zLlBhZ2VyQ291bnQgPSAoPGFueVtdPnRoaXMuVmlldykubGVuZ3RoIHx8IDA7XHJcbiAgICAgICAgICAgIHRoaXMuUGFnZXJPcHRpb25zLlNob3dQYWdpbmcgPSAhdGhpcy5IaWRlUGFnaW5nICYmIHRoaXMuVmlldy5sZW5ndGggPiAxMDtcclxuICAgICAgICAgICAgdGhpcy5QYWdlck9wdGlvbnMuVmlldyA9IHRoaXMuVmlldztcclxuICAgICAgICAgICAgdGhpcy5QYWdlck9wdGlvbnMuVXNlc1ZpZXcgPSBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAodGhpcy5hcnJheU1vZGUgJiYgKCF0aGlzLlVzZUFycmF5TW9kZVBhZ2luZyB8fCB0aGlzLlNlYXJjaFZpZXcpKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLlNlYXJjaFZpZXcpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuUGFnZXJPcHRpb25zLlZpZXcgPSB0aGlzLlNlYXJjaFZpZXdcclxuICAgICAgICAgICAgICAgIHRoaXMuUGFnZXJPcHRpb25zLlBhZ2VyQ291bnQgPSB0aGlzLlNlYXJjaFZpZXcub2JqZWN0Y291bnQgfHwgMDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICB0aGlzLlBhZ2VyT3B0aW9ucy5QYWdlckNvdW50ID0gKDxhbnlbXT50aGlzLlZpZXcpLmxlbmd0aCB8fCAwXHJcblxyXG4gICAgICAgICAgICB0aGlzLlBhZ2VyT3B0aW9ucy5TaG93Q291bnQgPSB0aGlzLlBhZ2VyT3B0aW9ucy5TaG93Q291bnQgfHwgKHRoaXMuVmlldyAmJiB0aGlzLlZpZXcubGVuZ3RoKSB8fCAodGhpcy5TZWFyY2hWaWV3ICYmIHRoaXMuU2VhcmNoVmlldy5vYmplY3Rjb3VudCAmJiB0aGlzLlNlYXJjaFZpZXcub2JqZWN0Y291bnQgIT0gLTEpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIGlmICh0aGlzLnZpZXdNb2RlKSB7XHJcbiAgICAgICAgICAgIGxldCB0bXBWaWV3ID0gdGhpcy5NYWluR3JvdXBWaWV3IHx8IHRoaXMuVmlldztcclxuICAgICAgICAgICAgbGV0IGNvdW50ID0gdG1wVmlldz8uZ3JvdXBjb3VudCB8fCB0bXBWaWV3Py5vYmplY3Rjb3VudDtcclxuICAgICAgICAgICAgdGhpcy5QYWdlck9wdGlvbnMuU2VhcmNoZXMgPSB0bXBWaWV3Py5ncm91cGNvdW50ICE9IG51bGwgJiYgdG1wVmlldz8uZ3JvdXBjb3VudCAhPSB1bmRlZmluZWQgPyAnZ3JvdXBzJyA6ICdpdGVtcyc7XHJcbiAgICAgICAgICAgIHRoaXMuUGFnZXJPcHRpb25zLlBhZ2VyQ291bnQgPSBjb3VudCB8fCAwO1xyXG4gICAgICAgICAgICB0aGlzLlBhZ2VyT3B0aW9ucy5WaWV3ID0gdG1wVmlldztcclxuICAgICAgICAgICAgdGhpcy5QYWdlck9wdGlvbnMuU2hvd0NvdW50ID0gdGhpcy5QYWdlck9wdGlvbnMuU2hvd0NvdW50IHx8ICh0bXBWaWV3ICYmIGNvdW50ICYmIGNvdW50ICE9IC0xKTtcclxuICAgICAgICAgICAgdGhpcy5QYWdlck9wdGlvbnMuU2hvd1BhZ2luZyA9ICF0aGlzLkhpZGVQYWdpbmc7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2UgaWYgKHRoaXMucmVwb3J0TW9kZSkge1xyXG4gICAgICAgICAgICBsZXQgcnZjID0gdGhpcy5SZXBvcnRWYWx1ZXMuY291bnQ7XHJcbiAgICAgICAgICAgIHRoaXMuUGFnZXJPcHRpb25zLlZpZXcgPSB0aGlzLlZpZXc7XHJcbiAgICAgICAgICAgIHRoaXMuUGFnZXJPcHRpb25zLlBhZ2VyQ291bnQgPSBydmMgJiYgcnZjID09IC0xID8gdGhpcy5SZXBvcnRWYWx1ZXMucm93cy5sZW5ndGggOiBydmMgJiYgcnZjID4gMCA/IHRoaXMuUmVwb3J0VmFsdWVzLmNvdW50IDogMDtcclxuICAgICAgICAgICAgdGhpcy5QYWdlck9wdGlvbnMuU2hvd0NvdW50ID0gdGhpcy5QYWdlck9wdGlvbnMuU2hvd0NvdW50IHx8ICh0aGlzLlZpZXcgJiYgdGhpcy5WaWV3Lm9iamVjdGNvdW50ICYmIHRoaXMuVmlldy5vYmplY3Rjb3VudCAhPSAtMSk7XHJcbiAgICAgICAgICAgIHRoaXMuUGFnZXJPcHRpb25zLlNob3dQYWdpbmcgPSAhdGhpcy5IaWRlUGFnaW5nICYmIHRoaXMuVmlldy5wYWdpbmdhdmFpbGFibGU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmlwdWxpc2NlIGxlIGNhY2hlIGRpIHNlbGV6aW9uZVxyXG4gICAgICogXHJcbiAgICAgKiBAdG9kbzogU0VMRUNUSU9OXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgY2xlYXJTZWxlY3Rpb25DYWNoZXMoKSB7XHJcbiAgICAgICAgdGhpcy5pdGVtc0NhY2hlLmNsZWFyKCk7XHJcbiAgICAgICAgdGhpcy5ncm91cHNDYWNoZS5jbGVhcigpO1xyXG4gICAgICAgIHRoaXMuZXhjbHVzaW9uc0NhY2hlLmNsZWFyKCk7XHJcbiAgICAgICAgdGhpcy5ncm91cF9leGNsdXNpb25zQ2FjaGUuY2xlYXIoKTtcclxuXHJcbiAgICAgICAgdGhpcy5pX2l0ZW1zQ2FjaGUuY2xlYXIoKTtcclxuICAgICAgICB0aGlzLmlfZ3JvdXBzQ2FjaGUuY2xlYXIoKTtcclxuICAgICAgICB0aGlzLmlfZXhjbHVzaW9uc0NhY2hlLmNsZWFyKCk7XHJcbiAgICAgICAgdGhpcy5pX2dyb3VwX2V4Y2x1c2lvbnNDYWNoZS5jbGVhcigpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSW4gYmFzZSBhbGxhIG1vZGFsaXTDoCBzcGVjaWZpY2F0YSAoQXJyYXlNb2RlLCBWaWV3TW9kZSwgZWNjLi4uKSBxdWVzdG8gbWV0b2RvIHJlY3VwZXJhIGwnYXJyYXkgZGkgb2dnZXR0aSBkYSBiaW5kYXJlIGFkIGludGVyZmFjY2lhXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvbmx5c2VsZWN0ZWQgW2ZhbHNlXSBJbmRpY2EgZGkgcHJlbmRlcmUgc29sbyBnbGkgb2dnZXR0aSBzZWxlemlvbmF0aVxyXG4gICAgICogQHBhcmFtIHtib29sZWFufSByZWZyZXNoUGFnaW5nIFtmYWxzZV0gSW5kaWNhIHNlIGFnZ2lvcm5hcmUgbGUgaW5mb3JtYXppb25pIGRpIHBhZ2luYXppb25lIG8gbWVub1xyXG4gICAgICogQHBhcmFtIHtib29sZWFufSBhbGxJZlBvc3NpYmxlIFtmYWxzZV0gSW5kaWNhIHNlIHByZW5kZXJlIHR1dHRpIGdsaSBvZ2dldHRpIHF1YW9yYSBwb3NzaWJpbGUsIHVzYXRvIHNvbG8gaW4gQXJyYXlNb2RlXHJcbiAgICAgKlxyXG4gICAgICogQHJldHVybnMge2FueVtdfSBMaXN0YSBkZWdsaSBvZ2dldHRpIHN1IGN1aSBlZmZldHR1YXJlIGlsIGJpbmQgbGF0byBpbnRlcmZhY2NpYVxyXG4gICAgICogXHJcbiAgICAgKiBAdG9kbzogSVRFTVNcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBnZXRJdGVtc0J5TW9kZShvbmx5c2VsZWN0ZWQ6IGJvb2xlYW4gPSBmYWxzZSwgcmVmcmVzaFBhZ2luZzogYm9vbGVhbiA9IGZhbHNlLCBhbGxJZlBvc3NpYmxlOiBib29sZWFuID0gZmFsc2UpOiBhbnlbXSB7XHJcbiAgICAgICAgbGV0IGl0ZW1zOiBhbnlbXSA9IFtdO1xyXG5cclxuICAgICAgICBpZiAoKHRoaXMudmlld01vZGUgJiYgdGhpcy5WaWV3IGluc3RhbmNlb2YgQXBwU2VhcmNoKSkge1xyXG4gICAgICAgICAgICBpdGVtcyA9IHRoaXMuZ2V0Vmlld0l0ZW1zQnlTb3VyY2UoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAodGhpcy5hcnJheU1vZGUpIHtcclxuICAgICAgICAgICAgdGhpcy5WaWV3LmZvckVhY2goaXRtID0+IHsgaXRtLl9pdGVtID0gdHJ1ZTsgfSk7XHJcblxyXG4gICAgICAgICAgICAvLyBTZSBmYWNjaW8gZGVpIHJhZ2dydXBwYW1lbnRpIGlnbm9ybyBsYSBwYWdpbmF6aW9uZVxyXG4gICAgICAgICAgICBpZiAodGhpcy5Vc2VBcnJheU1vZGVQYWdpbmcgJiYgIWFsbElmUG9zc2libGUpIHtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBTZSBzb25vIGluIG1vZGFsaXTDoCBhcnJheSBtYSBsYSByaWNlcmNhIGRpcGVuZGUgZGEgdW5hIHZpZXcgZGV2byByaWFsbGluZWFyZSBnbGkgaXRlbXBlcnBhZ2VcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLlNlYXJjaFZpZXcpXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5BcnJheW1vZGVJdGVtc1BlclBhZ2UgPSB0aGlzLlNlYXJjaFZpZXcuaXRlbXNwZXJwYWdlb3ZlcnJpZGU7XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gRGV2byBjaGlhbWFyZSBpbCByZWZyZXNoIHBhZ2Ugc29sbyBzZSB2ZW5nbyByaWNoaWFtYXRvIGRhIHVuIGJpbmRpbmcgZXN0ZXJub1xyXG4gICAgICAgICAgICAgICAgaWYgKHJlZnJlc2hQYWdpbmcpXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWZyZXNoUGFnaW5nKHRoaXMuQXJyYXltb2RlSXRlbXNQZXJQYWdlKTtcclxuXHJcbiAgICAgICAgICAgICAgICBpdGVtcyA9IHRoaXMuYWRhcHRWaWV3VG9QYWdpbmcoKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGl0ZW1zID0gdGhpcy5WaWV3IGFzIGFueVtdO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBTZSB2b2dsaW8gc29sbyBpIHNlbGV6aW9uYXRpIGZpbHRyb1xyXG4gICAgICAgIGlmIChvbmx5c2VsZWN0ZWQpXHJcbiAgICAgICAgICAgIHJldHVybiBpdGVtcy5maWx0ZXIodCA9PiB0Ll9zZWxlY3RlZCk7XHJcblxyXG4gICAgICAgIHJldHVybiBpdGVtcztcclxuICAgIH1cclxuXHJcbiAgICAvKiogIFxyXG4gICAgICogQGlnbm9yZSBcclxuICAgICAqIFxyXG4gICAgICogQHRvZG86IElURU1TXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZ2V0Vmlld0l0ZW1zQnlTb3VyY2UoKTogYW55W10ge1xyXG4gICAgICAgIGxldCBjYXN0ZWRWaWV3ID0gdGhpcy5WaWV3IGFzIEFwcFNlYXJjaDxhbnk+O1xyXG4gICAgICAgIGxldCBncm91cEtleXMgPSBjYXN0ZWRWaWV3Lmdyb3VwaW5ncyA/IGNhc3RlZFZpZXcuZ3JvdXBpbmdzLmZpbHRlcih0ID0+ICF0LmFnZ3JlZ2F0aW9uKS5sZW5ndGggOiAwO1xyXG5cclxuICAgICAgICAvL0dydXBwaSBpbnRlcm1lZGlcclxuICAgICAgICBpZiAoKGNhc3RlZFZpZXcucmVxdWVzdGVkZ3JvdXBzPy5sZW5ndGggIT0gZ3JvdXBLZXlzIHx8IGNhc3RlZFZpZXcucmVxdWVzdGVkZ3JvdXBzPy5sZW5ndGggPT0gMCkgJiYgZ3JvdXBLZXlzID4gMCkge1xyXG4gICAgICAgICAgICBsZXQgcmV0ID0gY2FzdGVkVmlldy5ncm91cHM7XHJcbiAgICAgICAgICAgIHJldC5mb3JFYWNoKGl0bSA9PiB7XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gU2V0dG8gdmFyaWFiaWxlIGludGVybmEgcGVyIGNhcGlyZSBjaGUgcXVlc3RvIMOoIGluIHJlYWx0w6AgdW4gZ3J1cHBvXHJcbiAgICAgICAgICAgICAgICAoPGFueT5pdG0pLl9ncm91cCA9IHRydWU7XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gTGUgaW5mb3JtYXppb25pIHBhc3NhdGUgY29tZSBsaXN0YSBsZSBtZXR0byBkZW50cm8gYSB1bmEgY2FjaGUgcGVyIHZlbG9jaXp6YXJuZSBsJ2FjY2Vzc28gcXVhbmRvIGRldm8gdGlyYXJlIGZ1b3JpIGlsIGRpc3BsYXkgZGVsbGEgcHJvcHJpZXTDoFxyXG4gICAgICAgICAgICAgICAgdGhpcy5jYWNoZUFnZ3JlZ2F0aW9ucyhpdG0pO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgcmV0dXJuIHJldDtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgIGxldCByZXQgPSB0aGlzLlNlY29uZGFyeVNvdXJjZSA/ICh0aGlzLlZpZXcgYXMgYW55KS5pdGVtczIgOiB0aGlzLlRlcnRpYXJ5U291cmNlID8gKHRoaXMuVmlldyBhcyBhbnkpLml0ZW1zMyA6ICh0aGlzLlZpZXcgYXMgYW55KS5pdGVtcztcclxuICAgICAgICAgICAgLy8gU2V0dG8gdmFyaWFiaWxlIGludGVybmEgcGVyIHNwZWNpZmljYXJlIGNoZSBxdWVzdG8gw6ggdW4gZWxlbWVudG8gbm9ybWFsZSwgbm9uIHVuIGdydXBwbyBvIGFsdHJvXHJcbiAgICAgICAgICAgIHJldC5mb3JFYWNoKGl0bSA9PiB7ICg8YW55Pml0bSkuX2l0ZW0gPSB0cnVlOyB9KTtcclxuICAgICAgICAgICAgcmV0dXJuIHJldDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBIZWxwZXIgcGVyIGVmZmV0dHVhcmUgaWwgY2FjaGluZyBkZWxsZSBhZ2dyZWdhemlvbmkuIExlIHNwb3N0YSBkYSB1bmEgbGlzdGEgZGkgKipHcm91cEFnZ3JlZ2F0aW9uKiogYSB1bmEgKio8TWFwPHN0cmluZywgTWFwPHN0cmluZywgc3RyaW5nPj4qKlxyXG4gICAgICogXHJcbiAgICAgKiBAdG9kbzogUk9XR1JPVVBJTkdcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBjYWNoZUFnZ3JlZ2F0aW9ucyhncm91cDogYW55KSB7XHJcbiAgICAgICAgKDxhbnk+Z3JvdXApLl9hZ2dyZWdhdGlvbnNDYWNoZSA9IG5ldyBNYXAoKTtcclxuICAgICAgICBsZXQgY2FzdGVkQWdDYWNoZSA9ICg8TWFwPHN0cmluZywgTWFwPHN0cmluZywgc3RyaW5nPj4+KDxhbnk+Z3JvdXApLl9hZ2dyZWdhdGlvbnNDYWNoZSk7XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBncm91cC5hZ2dyZWdhdGlvbnMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgbGV0IGFnZyA9IGdyb3VwLmFnZ3JlZ2F0aW9uc1tpXTtcclxuICAgICAgICAgICAgaWYgKGNhc3RlZEFnQ2FjaGUuaGFzKGFnZy5jb2x1bW4pKVxyXG4gICAgICAgICAgICAgICAgY2FzdGVkQWdDYWNoZS5nZXQoYWdnLmNvbHVtbikuc2V0KGFnZy5hZ2dyZWdhdGlvbiwgYWdnLnZhbHVlKTtcclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBsZXQgdG1wOiBNYXA8c3RyaW5nLCBzdHJpbmc+ID0gbmV3IE1hcCgpO1xyXG4gICAgICAgICAgICAgICAgdG1wLnNldChhZ2cuYWdncmVnYXRpb24sIGFnZy52YWx1ZSlcclxuICAgICAgICAgICAgICAgIGNhc3RlZEFnQ2FjaGUuc2V0KGFnZy5jb2x1bW4sIHRtcCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBNZXRvZG8gY2hlIHByZW5kZSB0dXR0aSBnbGkgb2dnZXR0aSBkaSBjdWkgZGlzcG9uZSBkaXZpc2kgaW4gYnVja2V0IGRhIDEwMCBlbGVtZW50aVxyXG4gICAgICpcclxuICAgICAqIEByZXR1cm5zIHthbnlbXVtdfSBNYXRyaWNlIGRpIGFycmF5IE54MTAwXHJcbiAgICAgKiBcclxuICAgICAqIEB0b2RvOiBJVEVNU1xyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGdldEl0ZW1TbGljZXMoKTogYW55W11bXSB7XHJcbiAgICAgICAgLy8gU2Ugc29ubyBxdWkgZGkgc2ljdXJvIG5vbiBobyByb3dncm91cGluZ1xyXG4gICAgICAgIGxldCBpdGVtcyA9IHRoaXMuZ2V0SXRlbXNCeU1vZGUoKTtcclxuICAgICAgICBpZiAoIWl0ZW1zKVxyXG4gICAgICAgICAgICByZXR1cm4gW107XHJcbiAgICAgICAgbGV0IGFycmF5QnkxMDAgPSBbXTtcclxuXHJcbiAgICAgICAgbGV0IHNsaWNlcyA9IE1hdGguY2VpbChpdGVtcy5sZW5ndGggLyB0aGlzLlNsaWNlU2l6ZSk7XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbGljZXM7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgYXJyYXlTbGljZSA9IGl0ZW1zLnNsaWNlKGkgKiB0aGlzLlNsaWNlU2l6ZSwgaSAqIHRoaXMuU2xpY2VTaXplICsgdGhpcy5TbGljZVNpemUpO1xyXG4gICAgICAgICAgICBhcnJheUJ5MTAwLnB1c2goYXJyYXlTbGljZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBhcnJheUJ5MTAwO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTWV0b2RvIGNoZSBnZXN0aXNjZSBsJ2VuZGxlc3Mgc2Nyb2xsIGUgaW4gYmFzZSBhIHF1YW50byBsYSB0YWJlbGxhIMOoIHN0YXRhIHNjcm9sbGF0YSBhZ2dpdW5nZSBkZWdsaSBlbGVtZW50aSBleHRyYSBhICoqVE1QQm91bmRTb3VyY2UqKlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7YW55fSBlIEV2ZW50byBkaSBzY3JvbGwgZGVsIGJyb3dzZXJcclxuICAgICAqL1xyXG4gICAgcHVibGljIG9uU2Nyb2xsKGU6IGFueSkge1xyXG4gICAgICAgIGxldCB0YWJsZVZpZXdIZWlnaHQgPSBlLnRhcmdldC5vZmZzZXRIZWlnaHQ7XHJcbiAgICAgICAgbGV0IHRhYmxlU2Nyb2xsSGVpZ2h0ID0gZS50YXJnZXQuc2Nyb2xsSGVpZ2h0O1xyXG4gICAgICAgIGxldCBzY3JvbGxMb2NhdGlvbiA9IGUudGFyZ2V0LnNjcm9sbFRvcDtcclxuICAgICAgICBsZXQgYnVmZmVyID0gMjAwO1xyXG5cclxuICAgICAgICBsZXQgbGltaXQgPSB0YWJsZVNjcm9sbEhlaWdodCAtIHRhYmxlVmlld0hlaWdodCAtIGJ1ZmZlcjtcclxuICAgICAgICBpZiAoc2Nyb2xsTG9jYXRpb24gPiBsaW1pdCkge1xyXG4gICAgICAgICAgICBsZXQgaW5kZXhUb0FkZCA9IE1hdGguZmxvb3IodGhpcy5UTVBCb3VuZFNvdXJjZS5sZW5ndGggLyAxMDApO1xyXG4gICAgICAgICAgICBpZiAodGhpcy5ib3VuZFN1YlNvdXJjZXNbaW5kZXhUb0FkZF0gJiYgdGhpcy5hZGRlZFNsaWNlcy5pbmRleE9mKGluZGV4VG9BZGQpID09IC0xKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBEZXZvIHJpY29yZGFybWkgZGkgZmFyZSBsJ2hhc2ggZGVsIG51b3ZvIHBlenpvXHJcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGN1bGF0ZUhhc2godGhpcy5ib3VuZFN1YlNvdXJjZXNbaW5kZXhUb0FkZF0pO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5UTVBCb3VuZFNvdXJjZSA9IHRoaXMuVE1QQm91bmRTb3VyY2UuY29uY2F0KHRoaXMuYm91bmRTdWJTb3VyY2VzW2luZGV4VG9BZGRdKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuYWRkZWRTbGljZXMucHVzaChpbmRleFRvQWRkKTtcclxuXHJcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHsgdGhpcy5wb3N0Qm91bmRTb3VyY2VDYWxjdWxhdGlvbigpOyB9KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIE1ldG9kbyBsYW5jaWF0byBkb3BvIGNoZSBsYSBzb3JnZW50ZSBkYXRpIMOoIHN0YXRhIGNvcnJldHRhbWVudGUgYmluZGF0YSwgc2kgb2NjdXBhIGRpIHJpY2FsY29sYXJlIHR1dHRvIGNpw7IgY2hlIHNlcnZlXHJcbiAgICAgKiBhbGwnZXMtdGFibGUgcGVyIHJlbmRlcml6emFyZSBpIHZhbG9yaSBkYSBtb3N0cmFyZVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHBvc3RCb3VuZFNvdXJjZUNhbGN1bGF0aW9uKCkge1xyXG4gICAgICAgIC8vIFJlc2V0dG8gdHV0dG8gdHJhbm5lIFJvd1REcyBlIFJvd1RIcyBwZXIgZXZpdGFyZSBmbGlja2VyaW5nLiBSb3dURHMgZSBSb3dUSHMgc2FyYW5ubyBtb2RpZmljYXRlIGFsbCdpbnRlcm5vIGRlbCBwcm9zc2ltbyBjaWNsbyBkaSBDRFxyXG4gICAgICAgIHRoaXMuUm93Q29udGV4dHMgPSBbXTtcclxuICAgICAgICB0aGlzLk9yZGVyRGlyZWN0aXZlcyA9IFtdO1xyXG4gICAgICAgIHRoaXMubGFzdFNlbGVjdGVkSXRlbUlEID0gbnVsbDtcclxuXHJcbiAgICAgICAgaWYgKHRoaXMuRXNUaHNEaXJlY3RpdmUgJiYgdGhpcy5Fc1Roc0RpcmVjdGl2ZS5sZW5ndGggPiAwICYmIHRoaXMuRXNUZHNEaXJlY3RpdmUgJiYgdGhpcy5Fc1Rkc0RpcmVjdGl2ZS5sZW5ndGggPiAwKVxyXG4gICAgICAgICAgICB0aGlzLmludGVybmFsUG9zdEJvdW5kU291cmNlKCk7XHJcbiAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcclxuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7IHRoaXMuaW50ZXJuYWxQb3N0Qm91bmRTb3VyY2UoKTsgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUGVyIHBvdGVyIGRpc3Rpbmd1ZXJlIGxlIGNoaWFtYXRlIGEgcXVlc3RvIG1ldG9kbzogRG9wbyBpbCBzZXRUaW1lb3V0IHNlIHVzbyBnbGkgRXNUZC9Fc1RoIHZlY2NoaSwgc2VuemEgaWwgc2V0VGltZW91dCBzZSB1c28gbGUgbnVvdmUgZGlyZXR0aXZlXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgaW50ZXJuYWxQb3N0Qm91bmRTb3VyY2UoKSB7XHJcbiAgICAgICAgbGV0IFZpZXcgPSB0aGlzLlZpZXc7XHJcbiAgICAgICAgbGV0IHRocyA9IHRoaXMuRXNUaHMgJiYgdGhpcy5Fc1Rocy5sZW5ndGggPiAwID8gdGhpcy5Fc1Rocy50b0FycmF5KCkgOiB0aGlzLkVzVGhzRGlyZWN0aXZlICYmIHRoaXMuRXNUaHNEaXJlY3RpdmUubGVuZ3RoID4gMCA/IHRoaXMuRXNUaHNEaXJlY3RpdmUudG9BcnJheSgpIDogW107XHJcbiAgICAgICAgbGV0IHRkcyA9IHRoaXMuRXNUZHMgJiYgdGhpcy5Fc1Rkcy5sZW5ndGggPiAwID8gdGhpcy5Fc1Rkcy50b0FycmF5KCkgOiB0aGlzLkVzVGRzRGlyZWN0aXZlICYmIHRoaXMuRXNUZHNEaXJlY3RpdmUubGVuZ3RoID4gMCA/IHRoaXMuRXNUZHNEaXJlY3RpdmUudG9BcnJheSgpIDogW107XHJcblxyXG4gICAgICAgIC8vIFNlIG5vbiBobyBjb2xvbm5lIGRpbmFtaWNoZSBtYSBzb25vIGluIG1vZGFsaXTDoCBkaW5hbWljYSAobG8gY2FwaXNjbyBwZXJjaMOpIGMnw6ggdW5hIHZpZXcgcGllbmEgZGkgZ2VuZXJpY2l0ZW0pIG1ldHRvIGlsIGRlZmF1bHQgZGVsbGUgY29sb25uZVxyXG4gICAgICAgIHRoaXMuZXZlbnR1YWxseVJldmlld0R5bmFtaWNDb2x1bW5zKCk7XHJcbiAgICAgICAgdGhpcy5iaW5kRGlzcGxheVRvTG9hZGVkSXRlbXNPckdyb3VwcyhWaWV3KTtcclxuXHJcbiAgICAgICAgLy8gUXVlc3RvIGRldidlc3NlcmUgcGVyIGZvcnphIGxhbmNpYXRvIGRvcG8gKipiaW5kRGlzcGxheVRvTG9hZGVkSXRlbXNPckdyb3VwcyoqIGRhdG8gY2hlIMOoIGzDrCBjaGUgYWxjdW5lIGNvc2UgdmVuZ29ubyB2YWxvcml6emF0ZVxyXG4gICAgICAgIHRoaXMuc2V0dXBQYWdpbmdJbmZvcm1hdGlvbnMoKTtcclxuXHJcbiAgICAgICAgLy8gTW9sdGUgY29zZSBzb25vIG92dmlhbWVudGUgZGlzcG9uaWJpbGkgc29sbyBpbiBtb2RhbGl0w6AgVmlld1xyXG4gICAgICAgIGlmICgodGhpcy52aWV3TW9kZSB8fCB0aGlzLmFycmF5TW9kZSkgJiYgdGhpcy5Vc2VDdXN0b21DZWxscykge1xyXG4gICAgICAgICAgICBsZXQgdmlldyA9IHRoaXMudmlld01vZGUgPyBWaWV3IGFzIEFwcFNlYXJjaDxhbnk+IDogbnVsbDtcclxuICAgICAgICAgICAgbGV0IGl0ZW1zQW5kR3JvdXBzID0gdGhpcy52aWV3TW9kZSA/IFsuLi4odmlldy5pdGVtcyB8fCBbXSksIC4uLih2aWV3Lmdyb3VwcyB8fCBbXSldIDogVmlldyBhcyBhbnlbXTtcclxuICAgICAgICAgICAgbGV0IHNpID0gdGhpcy52aWV3TW9kZSA/IHZpZXcuc2VsZWN0aW9uIDogdGhpcy5hcnJheW1vZGVTZWxlY3Rpb247XHJcbiAgICAgICAgICAgIC8vIE4uQjogUmlzcGV0dGFyZSBsJ29yZGluZSBkaSBxdWVzdGUgMyBtYWNyb2NhdGVnb3JpZSDDqCBWSVRBTEVcclxuXHJcbiAgICAgICAgICAgIC8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogICAgICAgIFNpc3RlbWF6aW9uaSBkaSBUSCwgVEQsIGUgdmlzaWJpbGl0w6AgdmFyaWUgICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcblxyXG4gICAgICAgICAgICBsZXQgaEkgPSB0aGlzLmV2YWx1YXRlSGVhZGVyc0dyb3VwaW5nSW5mb3ModGhzKTsgICAgICAgIC8vIFByZXBhc3NhZ2dpbyBwZXIgdGlyYXJlIGZ1b3JpIHR1dHRlIGxlIGluZm8gdXRpbGkgc3VnbGkgaGVhZGVycyBpbiBtb2RvIGRhIG5vbiByaWNhY29sYXJzZWxpIHNlbXByZSBkb3BvXHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5hcnJheU1vZGUpIHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluIG1vZGFsaXTDoCBhcnJheSBub24gaG8gdW4gYmFja2VuZC4uLlxyXG4gICAgICAgICAgICAgICAgdGhpcy5hcnJheU1vZGVSZXZpZXdPcmRlcmluZ3MoKSAgICAgICAgICAgICAgICAgICAgIC8vIC4uLiBxdWluZGkgZ2xpIG9yZGluYW1lbnRpIGxpIGRldm8gZmFyZSBsYXRvIGNsaWVudCwgZSAuLi5cclxuICAgICAgICAgICAgICAgIHRoaXMuYXJyYXlNb2RlUmV2aWV3R3JvdXBpbmdzKGhJLmxlYWZzKTsgICAgICAgICAgICAvLyAuLi4gaSByYWdncnVwcGFtZW50aSBsaSBkZXZvIGZhcmUgbGF0byBjbGllbnRcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgdGhpcy5yZXZpZXdDb2x1bW5zTGlzdChoSS5sZWFmcyk7ICAgICAgICAgICAgICAgICAgICAgICAvLyBBZ2dpb3JuYSBsYSBsaXN0YSBkZWxsZSBjb2xvbm5lIGRhIG1vc3RyYXJlIG5lbGxhIGRpYWxvZyBwZXIgb3JkaW5hbWVudG8gZWNjXHJcbiAgICAgICAgICAgIHRoaXMubW92ZUZpeGVkQ29sdW1uc0F0VGhlQmVnaW5uaW5nKGhJLmxlYWZzLCB0ZHMpOyAgICAgLy8gU3Bvc3RvIHR1dHRlIGxlIGNvc2UgZml4ZWQgYWxsJ2luaXppbyBpbiBtb2RvIGNoZSBsYSBjcmVhemlvbmUgZGkgdGggZSB0ZCBzaWEgcGnDuSBzbmVsbGEgKFV0aWxpenphIGxlIENvbHVtbnNMaXN0LCBxdWluZGkgZGV2J2Vzc2VyZSByaWNoaWFtYXRhIFBJUk1BIGRpIHJldmlld0NvbHVtbnNMaXN0KVxyXG4gICAgICAgICAgICB0aGlzLmFsaWduSGVhZGVyc09yZGVyaW5nKGhJLmxlYWZzLCB2aWV3KTsgICAgICAgICAgICAgIC8vIEFsbGluZW8gZ2xpIG9yZGluYW1lbnRpIGFnbGkgaGVhZGVyXHJcbiAgICAgICAgICAgIHRoaXMuYWxpZ25Db2x1bW5zSWZMb2FkZWRWaWV3KHZpZXcpOyAgICAgICAgICAgICAgICAgICAgLy8gU2Ugc3RvIGNhcmljYW5kbyB1bmEgVmlldyBkYSBob3Rwb3RhdG8gKHF1aW5kaSBjb24gc2F2ZWRzdGF0ZSA9IHRydWUpIHJpYWxsaW5lbyBsYSB2aXNpYmlsaXTDoCBkZWxsZSBjb2xvbm5lIGUgaWwgbG9ybyBvcmRpbmUuXHJcbiAgICAgICAgICAgIHRoaXMucmVmcmVzaENvbHVtbnNWaXNpYmlsaXR5KGhJLmxlYWZzLCB0ZHMsIHZpZXcpOyAgICAgLy8gTGF2b3JvIHN1aSBUSCBlZCBldmVudHVhbG1lbnRlIG1vZGlmaWNvIGxhIHZpc2liaWxpdMOgIGFuY2hlIGRlaSBURC5cclxuICAgICAgICAgICAgdGhpcy5ldmFsdWF0ZVBpbm5lZENvbHVtbnNXaWR0aCgpOyAgICAgICAgICAgICAgICAgICAgICAvLyBTZSBzb25vIHByZXNlbnRpIGNvbG9ubmUgcGlubmF0ZSB2YWx1dGEgbGEgZGltZW5zaW9uZSBkZWwgY29udGVuaXRvcmVcclxuXHJcbiAgICAgICAgICAgIHRoaXMuZ2VuZXJhdGVEZWZhdWx0T3JkZXIoaEkubGVhZnMsIHZpZXcpOyAgICAgICAgICAgICAgLy8gR2VuZXJvIGxlIGRpcmV0dGl2ZSBkaSBvcmRpbmFtZW50bywgY2hlIHNpYW5vIGRlZmF1bHQgbyBkZXJpdmFudGkgZGFsbGEgQXBwU2VhcmNoXHJcbiAgICAgICAgICAgIHRoaXMuZXZhbHVhdGVIZWFkZXJHcm91cHMoaEkpOyAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVmFsdXRvIGkgcmFnZ3J1cHBhbWVudGkgZGVnbGkgaGVhZGVyIHNlIHByZXNlbnRpXHJcblxyXG4gICAgICAgICAgICAvLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICAgICAgICBHZW5lcmF6aW9uZSBiaW5kaW5nIHBlciByaWdoZSBlIGNvbG9ubmUgICAgICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcblxyXG4gICAgICAgICAgICB0aGlzLmV2YWx1YXRlUm93VGhzKGhJLmxlYWZzKTsgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJhY2NvbGdvIGkgVEhcclxuICAgICAgICAgICAgdGhpcy5ldmFsdWF0ZVJvd1RkcyhoSS5sZWFmcywgdGRzKTsgICAgICAgICAgICAgICAgICAgICAvLyBSYWNjb2xnbyBpIFREIGluIGNvbnRlc3RpIHNlcGFyYXRpLCB1biBjb250ZXN0byBwZXIgb2duaSBpdGVtIG8gZ3J1cHBvXHJcblxyXG4gICAgICAgICAgICAvLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICAgICAgICBVbHRpbWkgYWdnaXVzdG1hZW50aSBkZWkgYmluZGluZyAgICAgICAgICAgICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcblxyXG4gICAgICAgICAgICB0aGlzLmFwcGx5T3JkZXJpbmcodmlldywgdHJ1ZSk7ICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFwcGxpY28gbCdvcmRpbmFtZW50byBzdWxsZSBjb2xvbm5lIChub24gQVNDIERFU0MsIG1hIFwicHJpbWEgcXVlc3RhIG8gcXVlbGxhIGNvbG9ubmFcIilcclxuICAgICAgICAgICAgdGhpcy5Nb3ZlVGVtcG9yYXJ5VmFyaWFibGVzVG9SZWFsT25lcygpOyAgICAgICAgICAgICAgICAvLyBDb2xsZWdvIFRIIGUgVEQgYWdnaXVzdGF0aSBmaW5vIGFkIG9yYSBhbGxlIHZhcmlhYmlsaSBkaSBCaW5kaW5nIEhUTUxcclxuICAgICAgICAgICAgdGhpcy5ldmFsdWF0ZVNlbGVjdGlvbihpdGVtc0FuZEdyb3Vwcywgc2kpOyAgICAgICAgICAgICAvLyBSaWFsbGluZW8gbGUgaW5mbyBkaSBzZWxlemlvbmUgZGVnbGkgZWxlbWVudGkgZGVsbGEgVmlld1xyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMuUmVzZWFyY2hOZWVkZWQpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuY2hhbmdlZCgpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0U2VhcmNoUmVxdWVzdChmYWxzZSk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLlJlc2VhcmNoTmVlZGVkID0gZmFsc2U7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAoKHRoaXMudmlld01vZGUgfHwgdGhpcy5hcnJheU1vZGUpICYmICF0aGlzLlVzZUN1c3RvbUNlbGxzKSB7XHJcbiAgICAgICAgICAgIC8vIFJpYWxsaW5lbyBsZSBpbmZvIGRpIHNlbGV6aW9uZSBkZWdsaSBlbGVtZW50aSBkZWxsYSBWaWV3XHJcbiAgICAgICAgICAgIGxldCBpdGVtcyA9IHRoaXMudmlld01vZGUgPyAoVmlldyBhcyBBcHBTZWFyY2g8YW55PikuaXRlbXMgOiBWaWV3IGFzIGFueVtdO1xyXG4gICAgICAgICAgICBsZXQgc2kgPSB0aGlzLnZpZXdNb2RlID8gKFZpZXcgYXMgQXBwU2VhcmNoPGFueT4pLnNlbGVjdGlvbiA6IHRoaXMuYXJyYXltb2RlU2VsZWN0aW9uO1xyXG4gICAgICAgICAgICB0aGlzLmV2YWx1YXRlU2VsZWN0aW9uKGl0ZW1zLCBzaSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBQZXIgZXNzZXJlIHNpY3VybyBjaGUgZG9wbyB1biBiaW5kIGRpIG9nZ2V0dGkgbGEgZXMtdGFibGUgYWdnaW9ybmkgbGEgZ3JhZmljYVxyXG4gICAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xyXG4gICAgICAgIHRoaXMuRmlyc3RCaW5kID0gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTZSBpbiBtb2RhbGl0w6AgYXJyYXkgYXBwbGljYSBnbGkgb3JkaW5hbWVudGkgQVNDLURFU0MgZGVsbGUgY29sb25uZVxyXG4gICAgICogXHJcbiAgICAgKiBAdG9kbzogSU5URVJOQUxEQlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGFycmF5TW9kZVJldmlld09yZGVyaW5ncygpIHtcclxuICAgICAgICBpZiAodGhpcy5hcnJheU9yZGVycy5sZW5ndGggPiAwKVxyXG4gICAgICAgICAgICB0aGlzLmFycmF5T3JkZXJzLmZvckVhY2godCA9PiB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmJvdW5kU291cmNlID0gdGhpcy5ib3VuZFNvdXJjZS5zb3J0KChhLCBiKSA9PiAoYVt0LmlkXSA+IGJbdC5pZF0gPyAxIDogLTEpICogKHQub3JkZXIgPT0gJ0RFU0MnID8gLTEgOiAxKSk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogU2UgaW4gbW9kYWxpdMOgIGFycmF5IGFwcGxpY2EgaSByYWdncnVwcGFtZW50aSBkZWZpbml0aSBsYXRvIHJvdy1ncm91cGluZ1xyXG4gICAgICogXHJcbiAgICAgKiBAcGFyYW0ge3RoczogRXNUaFtdIHwgRXNUaERpcmVjdGl2ZVtdfSB0aHMgSGVhZGVyXHJcbiAgICAgKiBcclxuICAgICAqIEB0b2RvOiBST1cgR1JPVVBJTkdcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBhcnJheU1vZGVSZXZpZXdHcm91cGluZ3ModGhzOiBFc1RoW10gfCBFc1RoRGlyZWN0aXZlW10pIHtcclxuICAgICAgICBpZiAodGhzLmxlbmd0aCA9PSAwKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgIGlmICh0aGlzLmlzRXNUaCh0aHNbMF0pKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgIGxldCBoZWFkZXJHcm91cHM6IEdyb3VwW10gPSBbXTtcclxuICAgICAgICBsZXQgaGVhZGVyQWdncmVnYXRpb25zOiBHcm91cE9yQWdncmVnYXRpb25bXSA9IFtdO1xyXG5cclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRocy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgdGggPSB0aHNbaV0gYXMgRXNUaERpcmVjdGl2ZTtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aC50aEdyb3VwKVxyXG4gICAgICAgICAgICAgICAgaGVhZGVyR3JvdXBzLnB1c2gobmV3IEdyb3VwKHRoLnRoLCAwLCBcIlwiKSk7XHJcbiAgICAgICAgICAgIGVsc2UgaWYgKHRoLnRoQWdncmVnYXRpb24pXHJcbiAgICAgICAgICAgICAgICBoZWFkZXJBZ2dyZWdhdGlvbnMgPSBbLi4uaGVhZGVyQWdncmVnYXRpb25zLCAuLi50aGlzLmdldEdyb3VwQWdncmVnYXRpb25zKHRoKV07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoaGVhZGVyR3JvdXBzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgLy8gUHVsaXppYSBkZWxsZSBjYWNoZVxyXG4gICAgICAgICAgICB0aGlzLnJnR3JvdXBDYWNoZS5jbGVhcigpO1xyXG4gICAgICAgICAgICB0aGlzLnJnSXRlbUNhY2hlLmNsZWFyKCk7XHJcbiAgICAgICAgICAgIHRoaXMucmdDaGlsZEdyb3Vwc0NhY2hlLmNsZWFyKCk7XHJcblxyXG4gICAgICAgICAgICB0aGlzLkFycmF5R3JvdXBpbmcgPSB0cnVlO1xyXG4gICAgICAgICAgICB0aGlzLmJvdW5kU291cmNlID0gdGhpcy5nZXRHcm91cHNSZWN1cnNpdmUoaGVhZGVyR3JvdXBzLCAwLCB0aGlzLmJvdW5kU291cmNlLCBoZWFkZXJBZ2dyZWdhdGlvbnMsIG51bGwpXHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGF0YSBsYSBkZWZpbml6aW9uZSBkZWkgZ3J1cHBpIGRhIGdlbmVyYXJlIGRhIHVuYSBsaXN0YSBkaSBvZ2dldHRpLCBzdWRkaXZpZGUgZ2xpIG9nZ2V0dGkgcGFzc2F0aSBpbiBncnVwcGkgZSBzb3R0b2dydXBwaVxyXG4gICAgICogXHJcbiAgICAgKiBAcGFyYW0ge0dyb3VwW119IGdycHMgRGVmaW5pemlvbmUgZGVpIGdydXBwaVxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGN1cnJlbnRJbmRleCBJbmRpY2UgZGkgZWxhYm9yYXppb25lLiBBbCBsaXZlbGxvIDAgaG8gdHV0dGkgZ2xpIG9nZ2V0dGkgZSBkZXZvIGdlbmVyYXJlIGkgcHJpbWkgZ3J1cHBpLCBhIGxpdmVsbG8gMSBobyB0dXR0aSBpIGdydXBwaSBwcmluY2lwYWxpIGUgZGV2b1xyXG4gICAgICogZWxhYm9yYXJlIGkgc290dG9ncnVwcGksIGUgY29zw6wgdmlhIHJpY29yc2l2YW1lbnRlLi4uXHJcbiAgICAgKiBAcGFyYW0ge2FueVtdfSBpdGVtcyBPZ2dldHRpIGRhIHJhZ2dydXBwYXJlXHJcbiAgICAgKiBAcGFyYW0ge0dyb3VwT3JBZ2dyZWdhdGlvbltdfSBhZ2dyZWdhdGlvbnMgSW5mbyBkaSBhZ2dyZWdhemlvbmVcclxuICAgICAqIEBwYXJhbSB7YW55fSBwYXJlbnQgUmlmZXJpbWVudG8gYWwgZ3J1cHBvIHBhZHJlXHJcbiAgICAgKiBcclxuICAgICAqIEB0b2RvOiBJTlRFUk5BTERCXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZ2V0R3JvdXBzUmVjdXJzaXZlKGdycHM6IEdyb3VwW10sIGN1cnJlbnRJbmRleDogbnVtYmVyLCBpdGVtczogYW55W10sIGFnZ3JlZ2F0aW9uczogR3JvdXBPckFnZ3JlZ2F0aW9uW10sIHBhcmVudD86IGFueSk6IGFueVtdIHtcclxuICAgICAgICAvLyBTZSBsJ2luZGljZSDDqCAwIGRldm8gc2ljdXJhbWVudGUgbmFzY29uZGVyZSB0dXR0aSBnbGkgb2dnZXR0aS4gU29sbyBpIGdydXBwaSBzYXJhbm5vIHZpc3VhbGl6emF0aVxyXG4gICAgICAgIGlmIChjdXJyZW50SW5kZXggPT0gMClcclxuICAgICAgICAgICAgaXRlbXMuZm9yRWFjaChpID0+IGkuX3Zpc2libGUgPSBmYWxzZSk7XHJcblxyXG4gICAgICAgIGxldCBncnAgPSBncnBzW2N1cnJlbnRJbmRleF07XHJcbiAgICAgICAgbGV0IHJldDogYW55W10gPSBbXTtcclxuICAgICAgICBsZXQgbGFzdCA9IGdycHMubGVuZ3RoID09IGN1cnJlbnRJbmRleCArIDE7XHJcbiAgICAgICAgbGV0IGdyb3VwcyA9IHRoaXMuZ3JvdXBCeShpdGVtcywgZ3JwLmNvbHVtbik7XHJcbiAgICAgICAgZm9yIChsZXQgcHJvcCBpbiBncm91cHMpIHtcclxuICAgICAgICAgICAgbGV0IGl0bXMgPSBncm91cHNbcHJvcF07XHJcbiAgICAgICAgICAgIGxldCBncCA9IG5ldyBHcm91cChncnAuY29sdW1uLCBpdG1zLmxlbmd0aCwgcHJvcCk7XHJcbiAgICAgICAgICAgIGdwLmFnZ3JlZ2F0aW9ucyA9IHRoaXMuZ2VuZXJhdGVBZ2dyZWdhdGlvbnMoaXRtcywgYWdncmVnYXRpb25zKTtcclxuXHJcbiAgICAgICAgICAgIGxldCBhbnlncCA9ICg8YW55PmdwKTtcclxuICAgICAgICAgICAgYW55Z3AuX2dyb3VwID0gdHJ1ZTtcclxuICAgICAgICAgICAgYW55Z3AuX2V4cGFuZGVkID0gZmFsc2U7XHJcbiAgICAgICAgICAgIGlmICghcGFyZW50KSB7XHJcbiAgICAgICAgICAgICAgICBhbnlncC5fdGhpc1JvdXRlID0gW3sgY29sdW1uOiBncC5jb2x1bW4sIHZhbHVlOiBncC52YWx1ZSB9XTtcclxuICAgICAgICAgICAgICAgIGFueWdwLl90aGlzS2V5ID0gZ3AudmFsdWU7XHJcbiAgICAgICAgICAgICAgICBhbnlncC5fZ3JvdXBsZXZlbCA9IDA7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBhbnlncC5fcGFyZW50ID0gcGFyZW50Ll90aGlzS2V5O1xyXG4gICAgICAgICAgICAgICAgYW55Z3AuX3BhcmVudFJvdXRlID0gcGFyZW50Ll90aGlzUm91dGU7XHJcbiAgICAgICAgICAgICAgICBhbnlncC5fdGhpc1JvdXRlID0gWy4uLnBhcmVudC5fdGhpc1JvdXRlLCB7IGNvbHVtbjogZ3AuY29sdW1uLCB2YWx1ZTogZ3AudmFsdWUgfV07XHJcbiAgICAgICAgICAgICAgICBhbnlncC5fdGhpc0tleSA9IHBhcmVudC5fdGhpc0tleSArIGdwLnZhbHVlO1xyXG4gICAgICAgICAgICAgICAgYW55Z3AuX2dyb3VwbGV2ZWwgPSBwYXJlbnQuX2dyb3VwbGV2ZWwgKyAxO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBQdXNobyBpbCBncnVwcG8sIHR1dHRpIGkgZ3J1cHBpIGRlbCBsaXZlbGxvIHNvdHRvLCBvIGdsaSBpdGVtIHNlIGlvIHNvbm8gbCd1bHRpbW8gZ3J1cHBvLiBcclxuICAgICAgICAgICAgLy8gTGEgdmlzaWJpbGl0w6Agw6ggc29sbyBwZXIgaWwgZ3J1cHBvIGEgbGl2ZWxsbyAwLCB0dXR0aSBnbGkgYWx0cmkgZ3J1cHBpIHNhcmFubm8gbW9zdHJhdGkgbyBuYXNjb3N0aSBkaSBjb25zZWd1ZW56YVxyXG5cclxuICAgICAgICAgICAgaWYgKGN1cnJlbnRJbmRleCA9PSAwKVxyXG4gICAgICAgICAgICAgICAgYW55Z3AuX3Zpc2libGUgPSB0cnVlO1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgdGhpcy5jYWxjdWxhdGVIYXNoKFthbnlncF0pO1xyXG4gICAgICAgICAgICB0aGlzLmNhY2hlQWdncmVnYXRpb25zKGFueWdwKTtcclxuXHJcbiAgICAgICAgICAgIC8vIEFnZ2l1bmdvIGlsIGdydXBwbyBwYWRyZVxyXG4gICAgICAgICAgICByZXQucHVzaChhbnlncCk7XHJcbiAgICAgICAgICAgIHRoaXMucmdHcm91cENhY2hlLnNldChhbnlncC5fdGhpc0tleSwgYW55Z3ApO1xyXG4gICAgICAgICAgICBpZiAoIWxhc3QpIHtcclxuXHJcbiAgICAgICAgICAgICAgICAvL0RhbCBncnVwcG8gcGFkcmUsIHNlIG5vbiDDqCBsJ3VsdGltbyBncnVwcG8gZGVsbGEgY2F0ZW5hLCBjYWxjb2xvIHJpY29yc2l2YW1lbnRlIHR1dHRhIGxhIGNhdGVuYSBzb3R0b1xyXG4gICAgICAgICAgICAgICAgbGV0IHN1Ykdyb3Vwc0FuZEl0ZW1zID0gdGhpcy5nZXRHcm91cHNSZWN1cnNpdmUoZ3JwcywgY3VycmVudEluZGV4ICsgMSwgaXRtcywgYWdncmVnYXRpb25zLCBhbnlncCk7XHJcbiAgICAgICAgICAgICAgICBsZXQgY2hpbGRncm91cHMgPSBzdWJHcm91cHNBbmRJdGVtcy5maWx0ZXIodCA9PiB0Ll9ncm91cCAmJiB0Ll9wYXJlbnQgPT0gYW55Z3AuX3RoaXNLZXkpO1xyXG4gICAgICAgICAgICAgICAgYW55Z3AuX2dyb3Vwc2NvdW50ID0gY2hpbGRncm91cHMubGVuZ3RoO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIEFnZ2l1bmdvIGxhIGNhdGVuYSBkZWwgZ3J1cHBvIHNvdHRvLCBhZ2dpdW5nZW5kbyBhbGxhIGNhY2hlIHNvbG8gaSBncnVwcGkgcGFkcmVcclxuICAgICAgICAgICAgICAgIHJldC5wdXNoKC4uLnN1Ykdyb3Vwc0FuZEl0ZW1zKTtcclxuICAgICAgICAgICAgICAgIHRoaXMucmdDaGlsZEdyb3Vwc0NhY2hlLnNldChhbnlncC5fdGhpc0tleSwgY2hpbGRncm91cHMpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgLy8gQWwgZ3J1cHBvIHBhZHJlLCBzZSDDqCBsJ3VsdGltbyBhc3NlZ25vIHR1dHRlIGxlIGZvZ2xpZSBhc3NlZ25hbmRvZ2xpIGFuY2hlIGxhIGNoaWF2ZSBkZWwgZ3J1cHBvXHJcbiAgICAgICAgICAgICAgICBpdG1zLmZvckVhY2goaSA9PiBpLl90aGlzS2V5ID0gYW55Z3AuX3RoaXNLZXkpO1xyXG5cclxuICAgICAgICAgICAgICAgIHJldC5wdXNoKC4uLml0bXMpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5yZ0l0ZW1DYWNoZS5zZXQoYW55Z3AuX3RoaXNLZXksIGl0bXMpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiByZXQ7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEYXRhIHVuYSBsaXN0YSBkaSBvZ2dldHRpIGdlbmVyYSBsZSBhZ2dyZWdhemlvbmkgc3BlY2lmaWNhdGUuIFNpIGNvbnNpZGVyYSBkaSBhdmVyZSB0dXR0aSBnbGkgb2dnZXR0aVxyXG4gICAgICogXHJcbiAgICAgKiBAcGFyYW0ge2FueVtdfSBpdGVtcyBPZ2dldHRpIGRpIGN1aSBjYWxjb2xhcmUgbGUgYWdncmVnYXppb25lXHJcbiAgICAgKiBAcGFyYW0ge0dyb3VwT3JBZ2dyZWdhdGlvbltdfSBhZ2dyZWdhdGlvbnMgQWdnZXJnYXppb25pIGRhIGdlbmVyYXJlXHJcbiAgICAgKiBcclxuICAgICAqIEB0b2RvOiBJTlRFUk5BTERCXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZ2VuZXJhdGVBZ2dyZWdhdGlvbnMoaXRlbXM6IGFueVtdLCBhZ2dyZWdhdGlvbnM6IEdyb3VwT3JBZ2dyZWdhdGlvbltdKTogR3JvdXBBZ2dyZWdhdGlvbltdIHtcclxuICAgICAgICBsZXQgcmV0czogR3JvdXBBZ2dyZWdhdGlvbltdID0gW11cclxuICAgICAgICBsZXQgYWdncmVnYXRpb25WYWx1ZSA9IFwiXCIsIGZlRmllbGQgPSBudWxsLCBzdHJpbmdBZ2cgPSBudWxsLCBkYXRlQWdnID0gbnVsbCwgbnVtYmVyQWdnID0gbnVsbDtcclxuXHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhZ2dyZWdhdGlvbnMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgbGV0IGFnZyA9IGFnZ3JlZ2F0aW9uc1tpXTtcclxuICAgICAgICAgICAgZmVGaWVsZCA9IGFnZy5jb2x1bW47XHJcbiAgICAgICAgICAgIGlmICghZmVGaWVsZClcclxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xyXG5cclxuICAgICAgICAgICAgc3dpdGNoIChhZ2cuZGF0YXR5cGUpIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgJ3N0cmluZyc6IHN0cmluZ0FnZyA9IGl0ZW1zLm1hcChpID0+IGlbZmVGaWVsZF0udG9TdHJpbmcoKSk7IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSAnZGF0ZSc6IGRhdGVBZ2cgPSBpdGVtcy5tYXAoaSA9PiBuZXcgRGF0ZShpW2ZlRmllbGRdKS5nZXRUaW1lKCkpOyBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgJ251bWJlcic6IG51bWJlckFnZyA9IGl0ZW1zLm1hcChpID0+IHBhcnNlRmxvYXQoaVtmZUZpZWxkXSkpOyBicmVhaztcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgc3dpdGNoIChhZ2cuYWdncmVnYXRpb24pIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgJ21heCc6XHJcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChhZ2cuZGF0YXR5cGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnc3RyaW5nJzogYWdncmVnYXRpb25WYWx1ZSA9IHN0cmluZ0FnZy5zb3J0KCkucmV2ZXJzZSgpWzBdOyBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnZGF0ZSc6IGFnZ3JlZ2F0aW9uVmFsdWUgPSBuZXcgRGF0ZShNYXRoLm1heCguLi5kYXRlQWdnKSkudG9TdHJpbmcoKTsgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ251bWJlcic6IGFnZ3JlZ2F0aW9uVmFsdWUgPSBNYXRoLm1heCguLi5udW1iZXJBZ2cpLnRvU3RyaW5nKCk7IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgJ21pbic6XHJcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChhZ2cuZGF0YXR5cGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnc3RyaW5nJzogYWdncmVnYXRpb25WYWx1ZSA9IHN0cmluZ0FnZy5zb3J0KClbMF07IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdkYXRlJzogYWdncmVnYXRpb25WYWx1ZSA9IG5ldyBEYXRlKE1hdGgubWluKC4uLmRhdGVBZ2cpKS50b1N0cmluZygpOyBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbnVtYmVyJzogYWdncmVnYXRpb25WYWx1ZSA9IE1hdGgubWluKC4uLm51bWJlckFnZykudG9TdHJpbmcoKTsgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSAnc3VtJzpcclxuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGFnZy5kYXRhdHlwZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdzdHJpbmcnOiBhZ2dyZWdhdGlvblZhbHVlID0gc3RyaW5nQWdnLmpvaW4oXCIsIFwiKTsgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ2RhdGUnOiBhZ2dyZWdhdGlvblZhbHVlID0gXCJcIjsgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ251bWJlcic6IGFnZ3JlZ2F0aW9uVmFsdWUgPSBudW1iZXJBZ2cucmVkdWNlKChwcmUsIGN1cnIpID0+IHByZSArIGN1cnIsIDApLnRvU3RyaW5nKCk7IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXRzLnB1c2gobmV3IEdyb3VwQWdncmVnYXRpb24oYWdnLmNvbHVtbiwgYWdnLmFnZ3JlZ2F0aW9uLCBhZ2dyZWdhdGlvblZhbHVlKSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gcmV0cztcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIERhdGEgdW5hIGxpc3RhIGRpIG9nZ2V0dGkgZWZmZXR0dWEgZGVpIHJhZ2dydXBwYW1lbnRpIGluIGJhc2UgYWxsYSBwcm9wcmlldMOgICoqZmllbGQqKiwgcmVzdGl0dWVuZG8gdW4gb2dnZXR0byBkZWwgdGlwbyB7IEdydXBwbzE6IG9nZ2V0dGlbXSwgR3J1cHBvMjogb2dnZXR0aVtdLCBlY2MuLi4gfVxyXG4gICAgICogXHJcbiAgICAgKiBAcGFyYW0ge2FueVtdfSBhcnJheSBMaXN0YSBkZWdsaSBvZ2dldHRpIGRhIHJhZ2dydXBwYXJlXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZmllbGQgQ2FtcG8gc3UgY3VpIGVmZmV0dHVhcmUgaSByYWdncnVwcGFtZW50aVxyXG4gICAgICogXHJcbiAgICAgKiBAcmV0dXJucyB7eyBbaWQ6IHN0cmluZ106IGFueVtdIH19IERpemlvbmFyaW8gZGVpIGdydXBwaVxyXG4gICAgICogXHJcbiAgICAgKiBAdG9kbzogSU5URVJOQUxEQlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGdyb3VwQnkoYXJyYXk6IGFueVtdLCBmaWVsZDogc3RyaW5nKTogeyBbaWQ6IHN0cmluZ106IGFueVtdIH0ge1xyXG4gICAgICAgIGxldCByZXQgPSB7fTtcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGxldCB4ID0gYXJyYXlbaV07XHJcbiAgICAgICAgICAgIChyZXRbeFtmaWVsZF1dID0gcmV0W3hbZmllbGRdXSB8fCBbXSkucHVzaCh4KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHJldDtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBFZmZldHR1YSBpbCBiaW5kaW5nIGRlZ2xpIG9nZ2V0dGkgcGVydmVudXRpIGRhIHF1ZXN0YSBjaGlhbWF0YSBjb24gZ2xpIG9nZ2V0dGkgZWZmZXR0aXZhbWVudGUgZGEgZ3JhZmljYXJlXHJcbiAgICAgKiBcclxuICAgICAqIEBwYXJhbSB7YW55fSB2aWV3IFZpZXcgZGEgY3VpIHNvbm8gYXJyaXZhdGkgZ2xpIG9nZ2V0dGkuIFB1w7IgZXNzZXJlIG8gdW4gYXJyYXkgc2Ugc29ubyBpbiAqKmFycmF5TW9kZSoqIG8gdW5hIEFwcFNlYXJjaDxUPiBzZSBzb25vIGluICoqdmlld01vZGUqKlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGJpbmREaXNwbGF5VG9Mb2FkZWRJdGVtc09yR3JvdXBzKHZpZXc6IGFueSkge1xyXG4gICAgICAgIGlmICh0aGlzLlRNUEJvdW5kU291cmNlLmxlbmd0aCA9PSAwKSB7XHJcbiAgICAgICAgICAgIHRoaXMuQmFzZUl0ZW1zQ291bnQgPSAwO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodGhpcy5hcnJheU1vZGUgfHwgIXRoaXMuVXNlQ3VzdG9tQ2VsbHMpIHtcclxuICAgICAgICAgICAgdGhpcy5ib3VuZFNvdXJjZSA9IHRoaXMuVE1QQm91bmRTb3VyY2U7XHJcbiAgICAgICAgICAgIHRoaXMuQmFzZUl0ZW1zQ291bnQgPSB2aWV3Py5vYmplY3Rjb3VudCB8fCB2aWV3Lmxlbmd0aDtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbGV0IGdyb3VwaW5nS2V5cyA9IHZpZXcuZ3JvdXBpbmdzPy5maWx0ZXIodCA9PiAhdC5hZ2dyZWdhdGlvbik/Lmxlbmd0aCB8fCAwO1xyXG4gICAgICAgIGlmIChncm91cGluZ0tleXMgPT0gMCkge1xyXG4gICAgICAgICAgICB0aGlzLmJvdW5kU291cmNlID0gdGhpcy5UTVBCb3VuZFNvdXJjZTtcclxuICAgICAgICAgICAgdGhpcy5CYXNlSXRlbXNDb3VudCA9IHZpZXcub2JqZWN0Y291bnQ7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMuaGFuZGxlTmV3RGF0YU9uUm93R3JvdXBpbmcodmlldywgZ3JvdXBpbmdLZXlzKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEluIG1vZGFsaXTDoCByb3dncm91cGluZyBxdWFuZG8gbWkgYXJyaXZhIHVuIG51b3ZvIGJsb2NjbyBkaSBvZ2dldHRpIGRldm8gYWdnaXVuZ2VybG8gYWxsYSB2aXN0YSBhdHR1YWxlOlxyXG4gICAgICogXHJcbiAgICAgKiAxKSBTZSBub24gdmllbmUgcmljaGllc3RvIGlsIGRldHRhZ2xpbyBkaSBhbGN1biBncnVwcG8gc2lnbmlmaWNhIGNoZSBkZXZvIGNvbnNpZGVyYXJlIG1pIHNpYW5vIGFycml2YXRpIHR1dHRpIGkgZ3J1cHBpIHByaW5jaXBhbGlcclxuICAgICAqIDIpIFNlIHZpZW5lIHJpY2hpZXN0byBpbCBkZXR0YWdsaW8gZGkgdW4gZ3J1cHBvIGRpdmVyc28gZGFsbCd1bHRpbW8gZGV2byBhZ2dpdW5nZXJlIGRvcG8gYWwgZ3J1cHBvIGNsaWNjYXRvIGxhIGxpc3RhIGRlaSBzb3R0b2dydXBwaVxyXG4gICAgICogMikgU2UgdmllbmUgcmljaGllc3RvIGlsIGRldHRhZ2xpbyBkZWxsJ3VsdGltbyBncnVwcG8gZGV2byBhZ2dpdW5nZXJlIGRvcG8gYWwgZ3J1cHBvIGNsaWNjYXRvIGxhIGxpc3RhIGRlZ2xpIG9nZ2V0dGlcclxuICAgICAqIFxyXG4gICAgICogQHBhcmFtIHthbnl9IHZpZXcgQXBwU2VhcmNoPFQ+IGRhIGN1aSBzb25vIGFycml2YXRpIGdsaSBvZ2dldHRpXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gZ3JvdXBpbmdLZXlzIExpdmVsbGkgZGkgcmFnZ3J1cHBhbWVudG8gZGEgYXNwZXR0YXJzaSBzdWkgZGF0aVxyXG4gICAgICogXHJcbiAgICAgKiBAdG9kbzogUk9XR1JPVVBJTkdcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBoYW5kbGVOZXdEYXRhT25Sb3dHcm91cGluZyh2aWV3OiBBcHBTZWFyY2g8YW55PiwgZ3JvdXBpbmdLZXlzOiBudW1iZXIpe1xyXG4gICAgICAgIC8vIDEpIFNlIG5vbiB2aWVuZSByaWNoaWVzdG8gaWwgZGV0dGFnbGlvIGRpIGFsY3VuIGdydXBwbyBzaWduaWZpY2EgY2hlIGxhIGNoaWFtYXRhIHJlc3RpdHVpc2NlIGxhIGxpc3RhIHBhZ2luYXRhIGRlaSBncnVwcGkgcHJpbmNpcGFsaS5cclxuICAgICAgICAvLyAgICBMaSB0cmF0dG8gY29tZSBzZSBmb3NzZSB1bmEgcXVhbHNpYXNpIGFsdHJhIHF1ZXJ5IHBhZ2luYXRhIHN1IE4gZWxlbWVudGlcclxuICAgICAgICBpZiAoKHZpZXcucmVxdWVzdGVkZ3JvdXBzPy5sZW5ndGggfHwgMCkgPT0gMCkge1xyXG4gICAgICAgICAgICB0aGlzLmJvdW5kU291cmNlID0gdGhpcy5UTVBCb3VuZFNvdXJjZTtcclxuICAgICAgICAgICAgdGhpcy5yZ0dyb3VwQ2FjaGUgPSBuZXcgTWFwPHN0cmluZywgR3JvdXA+KCk7XHJcbiAgICAgICAgICAgIHRoaXMucmdJdGVtQ2FjaGUgPSBuZXcgTWFwPHN0cmluZywgYW55W10+KCk7XHJcbiAgICAgICAgICAgIHRoaXMucmdDaGlsZEdyb3Vwc0NhY2hlID0gbmV3IE1hcDxzdHJpbmcsIEdyb3VwW10+KCk7XHJcblxyXG4gICAgICAgICAgICB0aGlzLlRNUEJvdW5kU291cmNlLmZvckVhY2goaXRtID0+IHtcclxuICAgICAgICAgICAgICAgIGl0bS5fdGhpc1JvdXRlID0gaXRtLl9ncm91cCA/IFt7IGNvbHVtbjogKDxHcm91cD5pdG0pLmNvbHVtbiwgdmFsdWU6ICg8R3JvdXA+aXRtKS52YWx1ZSB9XSA6IFtdO1xyXG4gICAgICAgICAgICAgICAgaXRtLl90aGlzS2V5ID0gaXRtLl9ncm91cCA/ICg8R3JvdXA+aXRtKS52YWx1ZSA6IG51bGw7XHJcbiAgICAgICAgICAgICAgICBpdG0uX2dyb3VwbGV2ZWwgPSAwO1xyXG5cclxuICAgICAgICAgICAgICAgIHRoaXMucmdHcm91cENhY2hlLnNldChpdG0uX3RoaXNLZXksIGl0bSk7XHJcbiAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgLy8gUmVzZXR0byBsYSByaWNlcmNhIGFsbGEgY2FjaGUgZGkgcXVlc3RhIFwic2Vzc2lvbmVcIlxyXG4gICAgICAgICAgICBsZXQgZmlyc3RJdGVtID0gdGhpcy5UTVBCb3VuZFNvdXJjZVswXTtcclxuICAgICAgICAgICAgdGhpcy5NYWluR3JvdXBWaWV3ID0gT2JqZWN0LmFzc2lnbih7fSwgdmlldyk7XHJcbiAgICAgICAgICAgIHRoaXMuZ3JvdXBTZWFyY2hSZXF1ZXN0c0NhY2hlID0gW3sgcGF0aDogJycsIHJvdXRlOiBbeyBjb2x1bW46ICg8R3JvdXA+Zmlyc3RJdGVtKS5jb2x1bW4sIHZhbHVlOiAoPEdyb3VwPmZpcnN0SXRlbSkudmFsdWUgfV0sIHZpZXc6IHRoaXMuTWFpbkdyb3VwVmlldywgZ3JvdXBfY29sdW1uOiAoPEdyb3VwPnRoaXMuVE1QQm91bmRTb3VyY2VbMF0pLmNvbHVtbiB9XTtcclxuICAgICAgICAgICAgdGhpcy5CYXNlSXRlbXNDb3VudCA9IHZpZXcub2JqZWN0Y291bnQ7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAvLyAyKSBTZSB2aWVuZSByaWNoaWVzdG8gaWwgZGV0dGFnbGlvIGRpIHVuIHF1YWxzaWFzaSBncnVwcG8gZGl2ZXJzbyBkYWxsJ3VsdGltbyB2dW9sIGRpcmUgY2hlIGRldm8gYWdnaXVuZ2VyZSBcclxuICAgICAgICAgICAgLy8gICAgZG9wbyBhbCBncnVwcG8gY2hlIGhvIGNsaWNjYXRvIGxhIGxpc3RhIGRlaSBncnVwcGkgdGlyYXRhIGZ1b3JpIHF1ZXN0YSB2b2x0YSAoaW50ZXJtZWRpYXRlR3JvdXAgPSB0cnVlKVxyXG4gICAgICAgICAgICAvKlxyXG4gICAgICAgICAgICAqICAgR3J1cHBvQSAgICAgICAgICAgICAgICAgICAgICBHcnVwcG9BXHJcbiAgICAgICAgICAgICogICBHcnVwcG9CICAgICAgICAgICAgICAgICAgICAgIEdydXBwb0JcclxuICAgICAgICAgICAgKiAgIEdydXBwb0MgPC0gQ2xpY2NvIHF1aSAgICAgICAgR3J1cHBvQ1xyXG4gICAgICAgICAgICAqICAgR3J1cHBvRCAgICAgICAgICAgICAgICAgICAgICAgICAgR3J1cHBvQzFcclxuICAgICAgICAgICAgKiAgIEdydXBwb0UgICAgICAgICAgICAgICAgICAgICAgICAgIEdydXBwb0MyXHJcbiAgICAgICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEdydXBwb0RcclxuICAgICAgICAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR3J1cHBvRVxyXG4gICAgICAgICAgICAqL1xyXG5cclxuICAgICAgICAgICAgLy8gMykgc2UgaSBncnVwcGkgcmljaGllc3RpIGRhbGxhIHZpZXcgc29ubyB1Z3VhbGkgYWkgZ3J1cHBpIHByZXNlbnRpIHZ1b2wgZGlyZSBjaGUgc3RvIHByZW5kZW5kbyBnbGkgb2dnZXR0aSB2ZXJpIGUgcHJvcHJpLCBzb25vIGluIFxyXG4gICAgICAgICAgICAvLyB2aWV3Lml0ZW1zIGUgcXVpbmRpIGluIFRNUEJvdW5kU291cmNlLCBobyBpbm9sdHJlIGxlIGluZm9ybWF6aW9uaSBkaSBwYWdpbmF6aW9uZSAqKnBlciBpbCBzaW5nb2xvIHNvdHRvZ3J1cHBvKiogKGludGVybWVkaWF0ZUdyb3VwID0gZmFsc2UpXHJcbiAgICAgICAgICAgIC8qXHJcbiAgICAgICAgICAgICogICBHcnVwcG9BICAgICAgICAgICAgICAgICAgICAgICAgIEdydXBwb0FcclxuICAgICAgICAgICAgKiAgICAgICBHcnVwcG9DMSAgICAgICAgICAgICAgICAgICAgICAgIEdydXBwb0MxICAgICAgXHJcbiAgICAgICAgICAgICogICBHcnVwcG9CICAgICAgICAgICAgICAgICAgICAgICAgIEdydXBwb0JcclxuICAgICAgICAgICAgKiAgIEdydXBwb0MgICAgICAgICAgICAgICAgICAgICAgICAgR3J1cHBvQ1xyXG4gICAgICAgICAgICAqICAgICAgIEdydXBwb0MxIDwtLSBDbGljY28gcXVpICAgICAgICAgR3J1cHBvQzFcclxuICAgICAgICAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPZ2dldHRvMVxyXG4gICAgICAgICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9nZ2V0dG8yXHJcbiAgICAgICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT2dnZXR0bzNcclxuICAgICAgICAgICAgKiAgICAgICBHcnVwcG9DMiAgICAgICAgICAgICAgICAgICAgICAgIEdydXBwb0MyXHJcbiAgICAgICAgICAgICogICBHcnVwcG9EICAgICAgICAgICAgICAgICAgICAgICAgIEdydXBwb0RcclxuICAgICAgICAgICAgKiAgIEdydXBwb0UgICAgICAgICAgICAgICAgICAgICAgICAgR3J1cHBvRVxyXG4gICAgICAgICAgICAqL1xyXG5cclxuICAgICAgICAgICAgbGV0IGludGVybWVkaWF0ZUdyb3VwID0gdmlldy5yZXF1ZXN0ZWRncm91cHMubGVuZ3RoICE9IGdyb3VwaW5nS2V5cztcclxuXHJcbiAgICAgICAgICAgIGxldCBpdGVtcyA9IHRoaXMuYm91bmRTb3VyY2U7XHJcbiAgICAgICAgICAgIGxldCBpbnNlcnRJbmRleCA9IDA7XHJcbiAgICAgICAgICAgIGxldCBncm91cEtleTogc3RyaW5nID0gXCJcIjtcclxuICAgICAgICAgICAgbGV0IGdyb3VwUm91dGU6IEdyb3VwUm91dGVGcmFnbWVudFtdID0gW107XHJcbiAgICAgICAgICAgIC8vIE5hdmlnbyBsYSBzdHV0dHVyYSBkZWkgZ3J1cHBpIGlnbm9yYW5kbyByaWNvcnNpdmFtZW50ZSB0dXR0aSBnbGkgaW5kaWNpIGZpbm8gYWkgZ3J1cHBpIGNoZSBtaSBpbnRlcmVzc2FubyBpbiBtb2RvIGRhIG5vbiBiZWNjYXJlIGlsIHByaW1vIFwiR3J1cHBvQzFcIiBkZWwgY2FzbyBzb3ByYVxyXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHZpZXcucmVxdWVzdGVkZ3JvdXBzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBsZXQgcmcgPSB2aWV3LnJlcXVlc3RlZGdyb3Vwc1tpXTtcclxuICAgICAgICAgICAgICAgIGdyb3VwS2V5ICs9IHJnLnZhbHVlO1xyXG4gICAgICAgICAgICAgICAgZ3JvdXBSb3V0ZS5wdXNoKHsgY29sdW1uOiByZy5jb2x1bW4sIHZhbHVlOiByZy52YWx1ZSB9KTtcclxuICAgICAgICAgICAgICAgIGluc2VydEluZGV4ID0gaXRlbXMuZmluZEluZGV4KCh0LCBpKSA9PiBpID49IGluc2VydEluZGV4ICYmIHQuX2dyb3VwICYmIHQuY29sdW1uID09IHJnLmNvbHVtbiAmJiB0LnZhbHVlID09IHJnLnZhbHVlKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgbGV0IGl0ZW1zQ2FjaGVSZWZlcmVuY2U7XHJcbiAgICAgICAgICAgIGxldCBjaGlsZEdyb3Vwc0NhY2hlUmVmZXJlbmNlO1xyXG5cclxuICAgICAgICAgICAgLy8gU2Ugbm9uIMOoIHVuIGdydXBwbyBpbnRlcm1lZGlvIGRldm8gcmlwdWxpcmUgbGEgY2FjaGUgZGVsIGdydXBwbyBzdSBjdWkgaG8gYXR0dWFsbWVudGUgY2xpY2NhdG8uIEdsaSBvZ2dldHRpIHNhcmFubm8gcmlhZ2dpdW50aSBkb3BvXHJcbiAgICAgICAgICAgIGlmICghaW50ZXJtZWRpYXRlR3JvdXApIHtcclxuICAgICAgICAgICAgICAgIHRoaXMucmdJdGVtQ2FjaGUuc2V0KGdyb3VwS2V5LCBbXSk7XHJcbiAgICAgICAgICAgICAgICBpdGVtc0NhY2hlUmVmZXJlbmNlID0gdGhpcy5yZ0l0ZW1DYWNoZS5nZXQoZ3JvdXBLZXkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgLy8gU2UgaW52ZWNlIMOoIHVuIGdydXBwbyBpbnRlcm1lZGlvIGRldm8gcmlwdWxpcmUgc2lhIHR1dHRpIGkgY2hpbGQgZ3JvdXAgcmljb3JzaXZhbWVudGUsIHNpYSB0dXR0aSBnbGkgaXRlbVxyXG4gICAgICAgICAgICAgICAgZm9yIChsZXQga2V5IG9mIHRoaXMucmdDaGlsZEdyb3Vwc0NhY2hlLmtleXMoKSlcclxuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5LnN0YXJ0c1dpdGgoZ3JvdXBLZXkpKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJnQ2hpbGRHcm91cHNDYWNoZS5kZWxldGUoa2V5KTtcclxuXHJcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBrZXkgb2YgdGhpcy5yZ0l0ZW1DYWNoZS5rZXlzKCkpXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleS5zdGFydHNXaXRoKGdyb3VwS2V5KSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZ0l0ZW1DYWNoZS5kZWxldGUoa2V5KTtcclxuXHJcbiAgICAgICAgICAgICAgICB0aGlzLnJnQ2hpbGRHcm91cHNDYWNoZS5zZXQoZ3JvdXBLZXksIFtdKTtcclxuICAgICAgICAgICAgICAgIGNoaWxkR3JvdXBzQ2FjaGVSZWZlcmVuY2UgPSB0aGlzLnJnQ2hpbGRHcm91cHNDYWNoZS5nZXQoZ3JvdXBLZXkpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBBc3NlZ25vIHVuIGxpdmVsbG8gYWkgdmFsb3JpIGNoZSBhcnJpdmFubyBkYSB1c2FyZSBwZXIgZm9ybWF0dGFyZSBsYSBwYXJ0ZSBncmFmaWNhLiBJbCBwcmltbyBncnVwcG8gY2xpY2NhdG8gc2Fyw6AgYSBsaXZlbGxvIDEsXHJcbiAgICAgICAgICAgIC8vIGlsIHNlY29uZG8gc2Fyw6AgYSBsaXZlbGxvIDIgZSBjb3PDrCB2aWEuLi5cclxuICAgICAgICAgICAgLy8gTGkgbWFyY28gaW5vbHRyZSBjb24gaWwgcGFyZW50IGluIG1vZG8gZGEgcG90ZXIgZWxpbWluYXJlIGkgdmVjY2hpIHF1YWxvcmEgc2Vydmlzc2VcclxuICAgICAgICAgICAgdGhpcy5UTVBCb3VuZFNvdXJjZS5mb3JFYWNoKGl0bSA9PiB7XHJcbiAgICAgICAgICAgICAgICBpdG0uX3BhcmVudCA9IGdyb3VwS2V5O1xyXG4gICAgICAgICAgICAgICAgaXRtLl9wYXJlbnRSb3V0ZSA9IGdyb3VwUm91dGU7XHJcbiAgICAgICAgICAgICAgICBpdG0uX3RoaXNSb3V0ZSA9IGl0bS5fZ3JvdXAgPyBbLi4uZ3JvdXBSb3V0ZSwgbmV3IEdyb3VwUm91dGVGcmFnbWVudCgoPEdyb3VwPml0bSkuY29sdW1uLCAoPEdyb3VwPml0bSkudmFsdWUpXSA6IFtdO1xyXG4gICAgICAgICAgICAgICAgaXRtLl90aGlzS2V5ID0gaXRtLl9ncm91cCA/IGdyb3VwS2V5ICsgKDxHcm91cD5pdG0pLnZhbHVlIDogZ3JvdXBLZXk7XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gUGVyIGxlIHJpY2VyY2EgaW50ZXJtZWRpZSBtZXR0byBpIGdydXBwaSBuZWxsYSBjYWNoZSBkZWkgZ3J1cHBpXHJcbiAgICAgICAgICAgICAgICBpZiAoaW50ZXJtZWRpYXRlR3JvdXApIHtcclxuICAgICAgICAgICAgICAgICAgICBpdG0uX2dyb3VwbGV2ZWwgPSB2aWV3LnJlcXVlc3RlZGdyb3Vwcy5sZW5ndGg7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZ0dyb3VwQ2FjaGUuc2V0KGl0bS5fdGhpc0tleSwgaXRtKTtcclxuICAgICAgICAgICAgICAgICAgICBjaGlsZEdyb3Vwc0NhY2hlUmVmZXJlbmNlLnB1c2goaXRtKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIE1ldHRvIGFuY2hlIGdsaSBvZ2dldHRpIG5lbGxhIGNhY2hlIG5vbiByaWNvcnNpdmFcclxuICAgICAgICAgICAgICAgICAgICBpdGVtc0NhY2hlUmVmZXJlbmNlLnB1c2goaXRtKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICAvLyBFbGltaW5vIGdsaSBvZ2dldHRpIHZlY2NoaSBcclxuICAgICAgICAgICAgLy8gMSkgUmljZXJjYSBpbnRlcm1lZGlhLCBzdGF0byBzYWx2YXRvIC0gRWxpbWlubyB0dXR0aSBnbGkgaXRlbSBlIHR1dHRpIGkgZ3J1cHBpIGxhIGN1aSByb3V0ZSDDqCBwacO5IGx1bmdhIGRlbGxhIGNvcnJlbnRlLCB0dXR0aSBnbGkgaXRlbSByZWxhdGl2aSBhbGxhIHBhdGggY29ycmVudGUsIGUgdHV0dGVcclxuICAgICAgICAgICAgLy8gICAgbGUgY2FjaGUgZGkgcmljZXJjYSBlZmZldHR1YXRlIHN1IHVuYSBwYXRoIHBpw7kgcHJvZm9uZGEgZGVsbCdhdHR1YWxlXHJcbiAgICAgICAgICAgIC8vIDIpIFJpY2VyY2EgZmluYWxlIG8gcmljZXJjYSBpbnRlcm1lZGlhIHNlbnphIHN0YXRvIHNhbHZhdG8gLSBFbGltaW5vIHR1dHRpIGdsaSBpdGVtIHJlbGF0aXZpIGFsbGEgcGF0aCBjb3JyZW50ZVxyXG4gICAgICAgICAgICAvLyBQZXIgXCJzdGF0byBzYWx2YXRvXCIgc2kgaW50ZW5kb25vIHJpY2VyY2hlIHZlY2NoaWUgc2FsdmF0ZSBwZXIgcG90ZXIgZXNzZXJlIHJpZWZmZXR0dWF0ZSBpbiBjYXNvIGRpIG9yZGluYW1lbnRpIHN1IGNvbG9ubmUgZGkgaW50ZXJlc3NlIFxyXG4gICAgICAgICAgICBpZiAoaW50ZXJtZWRpYXRlR3JvdXAgJiYgdmlldy5zYXZlZHN0YXRlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmJvdW5kU291cmNlID0gdGhpcy5ib3VuZFNvdXJjZS5maWx0ZXIodCA9PiAhKHQuX2l0ZW0gfHwgdC5fdGhpc1JvdXRlLmxlbmd0aCA+IGdyb3VwUm91dGUubGVuZ3RoKSk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmdyb3VwU2VhcmNoUmVxdWVzdHNDYWNoZSA9IHRoaXMuZ3JvdXBTZWFyY2hSZXF1ZXN0c0NhY2hlLmZpbHRlcih0ID0+ICEodC5yb3V0ZS5sZW5ndGggPiBncm91cFJvdXRlLmxlbmd0aCkpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICB0aGlzLmJvdW5kU291cmNlID0gdGhpcy5ib3VuZFNvdXJjZS5maWx0ZXIodCA9PiAhKHQuX3BhcmVudCA9PSBncm91cEtleSkpO1xyXG5cclxuICAgICAgICAgICAgbGV0IHRoaXNHcm91cCA9IHRoaXMuYm91bmRTb3VyY2VbaW5zZXJ0SW5kZXhdO1xyXG4gICAgICAgICAgICBpZihpbnRlcm1lZGlhdGVHcm91cClcclxuICAgICAgICAgICAgICAgIHRoaXNHcm91cC5fZ3JvdXBzY291bnQgPSAoPEFwcFNlYXJjaDxhbnk+PnRoaXMuVmlldyk/Lmdyb3VwY291bnRcclxuXHJcbiAgICAgICAgICAgIC8vIExpIHNvc3RpdHVpc2NvIGNvaSBudW92aSBkaSBxdWVzdGEgcmljZXJjYVxyXG4gICAgICAgICAgICB0aGlzLmJvdW5kU291cmNlLnNwbGljZShpbnNlcnRJbmRleCArIDEsIDAsIC4uLnRoaXMuVE1QQm91bmRTb3VyY2UpO1xyXG5cclxuICAgICAgICAgICAgLy8gQWdnaXVuZ28gdW4gc2VwYXJhdG9yZSBhbGxhIGZpbmUgbyBhbGwnaW5pemlvIGRpIHF1ZXN0aSBncnVwcGkgY2hlIGRvdnLDoCBvY2N1cGFyc2kgZGkgY2FyaWNhcmUgQUxUUkkgZ3J1cHBpIG8gb2dnZXR0aSAoc2Ugc29ubyBhbGwndWx0aW1vIGdydXBwbylcclxuICAgICAgICAgICAgbGV0IGFkZExhc3QgPSBmYWxzZTtcclxuICAgICAgICAgICAgdGhpcy5ib3VuZFNvdXJjZS5zcGxpY2UoaW5zZXJ0SW5kZXggKyAxICsgKGFkZExhc3QgPyB0aGlzLlRNUEJvdW5kU291cmNlLmxlbmd0aCA6IDApLCAwLCB0aGlzLmdldEdyb3VwU2VwYXJhdG9yKHZpZXcsIGdyb3VwS2V5LCBncm91cFJvdXRlLCB2aWV3LnJlcXVlc3RlZGdyb3Vwcy5sZW5ndGgsIGludGVybWVkaWF0ZUdyb3VwID8gJ2dyb3VwcycgOiAnaXRlbXMnKSk7XHJcblxyXG4gICAgICAgICAgICAvLyBBZ2dpdW5nbyBsYSByaWNlcmNhIGFsbGEgY2FjaGUgZGkgcXVlc3RhIFwic2Vzc2lvbmVcIlxyXG4gICAgICAgICAgICBsZXQgdG9BZGQgPSB7IHBhdGg6IGdyb3VwS2V5LCByb3V0ZTogZ3JvdXBSb3V0ZSwgdmlldzogT2JqZWN0LmFzc2lnbih7fSwgdmlldyksIGdyb3VwX2NvbHVtbjogaW50ZXJtZWRpYXRlR3JvdXAgPyAoPEdyb3VwPnRoaXMuVE1QQm91bmRTb3VyY2VbMF0pLmNvbHVtbiA6ICcnIH07XHJcbiAgICAgICAgICAgIGxldCBwcmV2ID0gdGhpcy5ncm91cFNlYXJjaFJlcXVlc3RzQ2FjaGUuZmluZEluZGV4KHQgPT4gdC5wYXRoID09IHRvQWRkLnBhdGggJiYgdC5ncm91cF9jb2x1bW4gPT0gdG9BZGQuZ3JvdXBfY29sdW1uKTtcclxuICAgICAgICAgICAgaWYgKHByZXYgPT0gLTEpXHJcbiAgICAgICAgICAgICAgICB0aGlzLmdyb3VwU2VhcmNoUmVxdWVzdHNDYWNoZS5wdXNoKHRvQWRkKTtcclxuICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgdGhpcy5ncm91cFNlYXJjaFJlcXVlc3RzQ2FjaGUuc3BsaWNlKHByZXYsIDEsIHRvQWRkKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBNZXRvZG8gcmljaGlhbWF0byBzb2xvIHF1YW5kbyAqKlRNUFJvd1REcyoqIGUgKipUTVBSb3dUSHMqKiBzb25vIGNvbXBsZXRhbWVudGUgZ2VuZXJhdGkgZWQgYWdnaXVzdGF0aS4gU2VydmUgcGVyIGNvbGxlZ2FybGkgYWxsZSB2YXJpYWJpbGkgdXNhdGUgbGF0byBiaW5kaW5nIEhUTUxcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBNb3ZlVGVtcG9yYXJ5VmFyaWFibGVzVG9SZWFsT25lcygpIHtcclxuICAgICAgICB0aGlzLlJvd1REcyA9IHRoaXMuVE1QUm93VERzO1xyXG4gICAgICAgIHRoaXMuUm93VEhzID0gdGhpcy5UTVBSb3dUSHM7XHJcbiAgICAgICAgdGhpcy5Sb3dUaEdyb3VwcyA9IHRoaXMuVE1QUm93VGhHcm91cHMgPyB0aGlzLlRNUFJvd1RoR3JvdXBzLnJldmVyc2UoKSA6IG51bGw7XHJcblxyXG4gICAgICAgIHRoaXMuQ29sdW1ucy5WaXNpYmlsZSA9IHRoaXMuUm93VEhzLmZpbHRlcih0ID0+IHQuVmlzaWJsZSkubGVuZ3RoO1xyXG4gICAgICAgIHRoaXMuQ29sdW1ucy5WaXNpYmxlVW5waW5uZWQgPSB0aGlzLlJvd1RIcy5maWx0ZXIodCA9PiB0LlZpc2libGUgJiYgIXQuUGlubmVkKS5sZW5ndGg7XHJcbiAgICAgICAgdGhpcy5Db2x1bW5zLkdsb2JhbCA9IHRoaXMuQ29sdW1ucy5WaXNpYmxlVW5waW5uZWQgKyAodGhpcy5IYXNQaW5uZWRDb2x1bW5zID8gMSA6IDApICsgKHRoaXMuU2VsZWN0aW9uID8gMSA6IDApICsgKHRoaXMuUmVtb3ZhbCA/IDEgOiAwKSArICh0aGlzLkV4cG9ydCB8fCB0aGlzLkhpZGRlbkNvbHVtbnMgfHwgdGhpcy5Db2x1bW5zT3JkZXJpbmcgfHwgdGhpcy5Db3JuZXJNZW51T3B0aW9ucyA/IDEgOiAwKVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUGVybWV0dGUgZGkgc2VsZXppb25hcmUgbyBkZXNlbGV6aW9uYXJlIGluIG1hbmllcmEgYXJiaXRyYXJpYSBkZWdsaSBvZ2dldHRpXHJcbiAgICAgKiBcclxuICAgICAqIEBwYXJhbSB7YW55W119IGl0ZW1zIE9nZ2V0dGkgZGEgc2VsZXppb25hcmUgbyBkZXNlbGV6aW9uYXJlXHJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHNlbGVjdCAqKnRydWUqKiBwZXIgc2VsZXppb25hcmxpLCAqKmZhbHNlKiogcGVyIG5vbiB0b2NjYXJsaVxyXG4gICAgICogXHJcbiAgICAgKiBAdG9kbzogU0VMRUNUSU9OXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzZXRTZWxlY3Rpb25TdGF0dXMoaXRlbXM6IGFueVtdLCBzZWxlY3Q6IGJvb2xlYW4pIHtcclxuICAgICAgICB0aGlzLmhhbmRsZUl0ZW1zU2VsZWN0aW9uKGl0ZW1zLCBzZWxlY3QpO1xyXG4gICAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogU2Ugbm9uIGhvIGwnSW5wdXQgKipEeW5hbWljUm93Q29sdW1uc0RlZmluaXRpb24qKiBpbiBtb2RhbGl0w6AgZGluYW1pY2EgbG8gcmllbXBpbyBjb24gaWwgZGVmYXVsdCBub21lIGRlbGxhIGNvbG9ubmEgPSB0ZXN0byBkZWxsYSBjb2xvbm5hXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZXZlbnR1YWxseVJldmlld0R5bmFtaWNDb2x1bW5zKCkge1xyXG4gICAgICAgIC8vIFNlbnphIG9nZ2V0dGkgZXNjb1xyXG4gICAgICAgIGlmICghdGhpcy5UTVBCb3VuZFNvdXJjZSB8fCB0aGlzLlRNUEJvdW5kU291cmNlLmxlbmd0aCA9PSAwKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgIHZhciB1c2VHZW5lcmljSXRlbXMgPSAhIXRoaXMuVE1QQm91bmRTb3VyY2VbMF1bXCJwcm9wZXJ0aWVzXCJdO1xyXG4gICAgICAgIGlmICghdXNlR2VuZXJpY0l0ZW1zIHx8ICghdGhpcy5GaXJzdEJpbmQgJiYgdGhpcy5EeW5hbWljUm93Q29sdW1uc0RlZmluaXRpb24gJiYgdGhpcy5EeW5hbWljUm93Q29sdW1uc0RlZmluaXRpb24ubGVuZ3RoID4gMCkpXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgaWYgKCghdGhpcy5EeW5hbWljUm93Q29sdW1uc0RlZmluaXRpb24gfHwgdGhpcy5EeW5hbWljUm93Q29sdW1uc0RlZmluaXRpb24ubGVuZ3RoID09IDApKSB7XHJcbiAgICAgICAgICAgIHZhciBwcm9wcyA9IDxSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+PnRoaXMuVE1QQm91bmRTb3VyY2VbMF1bXCJwcm9wZXJ0aWVzXCJdO1xyXG4gICAgICAgICAgICB0aGlzLkR5bmFtaWNSb3dDb2x1bW5zRGVmaW5pdGlvbiA9IFtdO1xyXG4gICAgICAgICAgICBmb3IgKGxldCBrZXkgaW4gcHJvcHMpXHJcbiAgICAgICAgICAgICAgICB0aGlzLkR5bmFtaWNSb3dDb2x1bW5zRGVmaW5pdGlvbi5wdXNoKG5ldyBFc1RhYmxlQ29sdW1uc0RlZmluaXRpb24oa2V5LCBrZXkpKVxyXG4gICAgICAgICAgICB0aGlzLlVzZXJEZWZpbmVkRHluYW1pY0NvbHMgPSBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICB0aGlzLlVzZXJEZWZpbmVkRHluYW1pY0NvbHMgPSB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUGFydGVuZG8gZGFnbGkgKipFc1RocyoqIGVzdHJhcHBvbG8gbGEgbGlzdGEgZGkgKipFc1RhYmxlQ29sdW1uKiogY2hlIHF1ZXN0YSB0YWJlbGxhIGRvdnLDoCBldmVudHVhbG1lbnRlIGdlc3RpcmUgcGVyIFZpc2liaWxpdMOgIGUgT3JkaW5lXHJcbiAgICAgKlxyXG4gICAgICogQ29zdG86IDEgc2NhbiBFc1Roc1xyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7RXNUaFtdIHwgRXNUaERpcmVjdGl2ZVtdfSB0aHMgQ29sb25uZSBkZWxsYSB0YWJlbGxhXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgcmV2aWV3Q29sdW1uc0xpc3QodGhzOiBFc1RoW10gfCBFc1RoRGlyZWN0aXZlW10pIHtcclxuICAgICAgICB0aGlzLlRNUENvbHVtbnNMaXN0ID0gW107XHJcbiAgICAgICAgaWYgKHRocy5sZW5ndGggPT0gMClcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICAvLyBBcHBlbmEgaWwgY29udGVudENoaWxkcmVuIMOoIHZhbG9yaXp6YXRvIHNjb3JybyB0dXR0aSBnbGkgaGVhZGVyXHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aHMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgbGV0IHRoID0gdGhzW2ldO1xyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMuaXNFc1RoKHRoKSkge1xyXG4gICAgICAgICAgICAgICAgLy8gU2Ugbm9uIGhvIHVuIGlkIGlsIHRoIMOoIGNvbnNpZGVyYXRvIGluZXJ0ZVxyXG4gICAgICAgICAgICAgICAgaWYgKCF0aC5JRClcclxuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcclxuXHJcbiAgICAgICAgICAgICAgICB0aC5PcmRlckJ5ID0gdGhpcy5PcmRlckJ5Q29sdW1uO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIFNhbHZvIGxlIGluZm9ybWF6aW9uaSBkZWxsJ2hlYWRlciBwZXIgZmFyIHBhcnRlIGRlbGxhIGxpc3RhIGRhIGN1aSBzY2VnbGllcmUgcXVhbGkgY29sb25uZSB2aXN1YWxpenphcmUvbmFzY29uZGVyZVxyXG4gICAgICAgICAgICAgICAgLy8gRGkgZGVmYXVsdCBsYSB2aXNpYmlsaXTDoCDDqCBxdWVsbGEgaW1wb3N0YXRhIG5lbCBjb21wb25lbnRlXHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5IaWRkZW5Db2x1bW5zIHx8IHRoLlZpc2libGUpXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5UTVBDb2x1bW5zTGlzdC5wdXNoKG5ldyBFc1RhYmxlQ29sdW1uKHRoLklELCB0aC5EZXNjcmlwdGlvbiwgdGguVmlzaWJsZSwgdGguRml4ZWQsIG51bGwsIG51bGwsIG51bGwpKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGxldCBjb2x1bW4gPSB0aC50aDtcclxuICAgICAgICAgICAgICAgIC8vIFNlIG5vbiBobyB1biBpZCBpbCB0aCDDqCBjb25zaWRlcmF0byBpbmVydGVcclxuICAgICAgICAgICAgICAgIGlmICghY29sdW1uKVxyXG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIFNhbHZvIGxlIGluZm9ybWF6aW9uaSBkZWxsJ2hlYWRlciBwZXIgZmFyIHBhcnRlIGRlbGxhIGxpc3RhIGRhIGN1aSBzY2VnbGllcmUgcXVhbGkgY29sb25uZSB2aXN1YWxpenphcmUvbmFzY29uZGVyZVxyXG4gICAgICAgICAgICAgICAgLy8gRGkgZGVmYXVsdCBsYSB2aXNpYmlsaXTDoCDDqCBxdWVsbGEgaW1wb3N0YXRhIG5lbCBjb21wb25lbnRlXHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5IaWRkZW5Db2x1bW5zIHx8IHRoLnRoVmlzaWJsZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBwcmV2aW91c2x5UGlubmVkID0gIXRoaXMuQ29sdW1uc0xpc3QgfHwgdGhpcy5Db2x1bW5zTGlzdC5sZW5ndGggPT0gMCB8fCAhdGhpcy5Db2x1bW5zTGlzdC5maW5kKHQgPT4gdC5pZCA9PSBjb2x1bW4pID8gbnVsbCA6IHRoaXMuQ29sdW1uc0xpc3QuZmluZCh0ID0+IHQuaWQgPT0gY29sdW1uKS5waW5uZWQ7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5UTVBDb2x1bW5zTGlzdC5wdXNoKG5ldyBFc1RhYmxlQ29sdW1uKGNvbHVtbiwgbnVsbCwgdGgudGhWaXNpYmxlLCAodGgudGhGaXhlZCB8fCB0aC50aEdyb3VwKSwgcHJldmlvdXNseVBpbm5lZCA9PSBudWxsID8gdGgudGhQaW5uZWQgOiBwcmV2aW91c2x5UGlubmVkLCB0aC50aFBpbm5lZFdpZHRoLCB0aC5UZW1wbGF0ZSkpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuQ29sdW1uc0xpc3QgPSBbXTtcclxuICAgICAgICB0aGlzLlRNUENvbHVtbnNMaXN0LmZvckVhY2goYyA9PiB7IHRoaXMuQ29sdW1uc0xpc3QucHVzaChPYmplY3QuYXNzaWduKHt9LCBjKSk7IH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUHJlbmRlIGkgdGggZSBpIHRkIGluIG1vZGFsaXTDoCBkaXJldGl2ZSBlIGxpIG9yZGluYSBpbiBiYXNlIGEgc2UgY2kgc29ubyBjb2xvbm5lIGZpeGVkIG8gbWVub1xyXG4gICAgICovXHJcbiAgICBwcml2YXRlIG1vdmVGaXhlZENvbHVtbnNBdFRoZUJlZ2lubmluZyh0aHM6IEVzVGhbXSB8IEVzVGhEaXJlY3RpdmVbXSwgdGRzOiBFc1RkW10gfCBFc1RkRGlyZWN0aXZlW10pIHtcclxuXHJcbiAgICAgICAgbGV0IHRoc0NhY2hlOiB7IFtpbmRleDogc3RyaW5nXTogYW55IH0gPSB7fTtcclxuICAgICAgICBsZXQgZml4ZWRzID0gMCwgcGlubmVkcyA9IDA7XHJcbiAgICAgICAgbGV0IGNvbHVtbnNDYWNoZTogeyBbaW5kZXg6IHN0cmluZ106IEVzVGFibGVDb2x1bW4gfSA9IHt9O1xyXG4gICAgICAgIGxldCBjb2x1bW5zSW5kZXhDYWNoZTogeyBbaW5kZXg6IHN0cmluZ106IG51bWJlciB9ID0ge307XHJcblxyXG4gICAgICAgIC8vIENyZW8gbGEgY2FjaGUgZGVsbGUgY29sb25uZVxyXG4gICAgICAgIGZvciAobGV0IGNvbGkgPSAwOyBjb2xpIDwgdGhpcy5Db2x1bW5zTGlzdC5sZW5ndGg7IGNvbGkrKykge1xyXG4gICAgICAgICAgICBsZXQgY29sID0gdGhpcy5Db2x1bW5zTGlzdFtjb2xpXTtcclxuICAgICAgICAgICAgY29sdW1uc0NhY2hlW2NvbC5pZF0gPSBjb2w7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBTcG9zdG8gdHV0dGkgZ2xpIGhlYWRlciBmaXhlZCBvIHBpbm5lZCBhbGwnaW5pemlvXHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aHMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgbGV0IHRoID0gdGhzW2ldO1xyXG4gICAgICAgICAgICBpZiAodGhpcy5pc0VzVGgodGgpKSB7XHJcbiAgICAgICAgICAgICAgICB0aHNDYWNoZVt0aC5JRF0gPSB0aDtcclxuICAgICAgICAgICAgICAgIGlmICh0aC5GaXhlZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChpICE9IHBpbm5lZHMgKyBmaXhlZHMpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYXJyYXlNb3ZlKHRocywgaSwgcGlubmVkcyArIGZpeGVkcyk7XHJcbiAgICAgICAgICAgICAgICAgICAgZml4ZWRzKytcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuXHJcbiAgICAgICAgICAgICAgICB0aHNDYWNoZVt0aC50aF0gPSB0aDtcclxuICAgICAgICAgICAgICAgIC8vIFJpYXNzZWdubyBzZW1wcmUgcGVyIHJpcHVsaXJlIHZhbG9yaSBkaSBwYXJ0ZW56YSBvIHBlciBhZ2dpb3JuYXJsaSBpbiBjYXNvIGRpIG1vZGlmaWNoZSB1dGVudGVcclxuICAgICAgICAgICAgICAgIHRoLnRoUGlubmVkID0gKCFjb2x1bW5zQ2FjaGVbdGgudGhdICYmIHRoLnRoUGlubmVkKSB8fCAoY29sdW1uc0NhY2hlW3RoLnRoXSAmJiBjb2x1bW5zQ2FjaGVbdGgudGhdLnBpbm5lZCk7XHJcbiAgICAgICAgICAgICAgICBpZiAodGgudGhQaW5uZWQpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoaSAhPSBwaW5uZWRzKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFycmF5TW92ZSh0aHMsIGksIHBpbm5lZHMpO1xyXG4gICAgICAgICAgICAgICAgICAgIHBpbm5lZHMrK1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIC8vSW4gcXVlc3RvIGNhc28gc29ubyBpbmZvcm1hemlvbmkgc3RhdGljaGUgaW52ZWNlLCBub24gbW9kaWZpY2FiaWxpIGRhbGwndXRlbnRlLCBxdWluZGkgbm9uIG1pIGTDsiBwcmVvY2N1cGF6aW9uaVxyXG4gICAgICAgICAgICAgICAgaWYgKHRoLnRoRml4ZWQgfHwgdGgudGhHcm91cCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChpICE9IHBpbm5lZHMgKyBmaXhlZHMpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYXJyYXlNb3ZlKHRocywgaSwgcGlubmVkcyArIGZpeGVkcyk7XHJcbiAgICAgICAgICAgICAgICAgICAgZml4ZWRzKytcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRoaXMuaXNFc1RoKHRoc1swXSkgfHwgdGhpcy5pc0VzVGQodGRzWzBdKSlcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICAvLyBDYWNoZSBkZWdsaSBpbmRpY2kgcGVyIHJpcG9zaXppb25hcmUgaSB0ZCBjb21lIGkgdGhcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRocy5sZW5ndGg7IGkrKylcclxuICAgICAgICAgICAgY29sdW1uc0luZGV4Q2FjaGVbKDxFc1RoRGlyZWN0aXZlPnRoc1tpXSkudGhdID0gaTtcclxuXHJcbiAgICAgICAgLy8gUmlvcmRpbm8gbGUgY2VsbGUgcGVyIGZhcmdsaSBtYW50ZW5lcmUgbGEgc3Rlc3NhIHN0cnV0dHVyYSBkZWkgdGhcclxuICAgICAgICBsZXQgbmV3VGRzID0gbmV3IEFycmF5KHRocy5sZW5ndGgpO1xyXG5cclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRkcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgaXRlbSA9IHRkc1tpXSBhcyBFc1RkRGlyZWN0aXZlO1xyXG4gICAgICAgICAgICBuZXdUZHNbY29sdW1uc0luZGV4Q2FjaGVbaXRlbS50ZF1dID0gaXRlbTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMuSGFzUGlubmVkQ29sdW1ucyA9IHBpbm5lZHMgPiAwO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSW4gYmFzZSBhbGxhIGNvbmZpZ3VyYXppb25lIGRlbGxlIGNvbG9ubmUgY2FsY29sYSBsZSBkaW1lbmlvbmkgZGVsbGUgY29sb25uZSBwaW5uYXRlXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZXZhbHVhdGVQaW5uZWRDb2x1bW5zV2lkdGgoKSB7XHJcbiAgICAgICAgaWYgKCF0aGlzLkhhc1Bpbm5lZENvbHVtbnMpXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgdGhpcy5QaW5uZWRDb250YWluZXJXaWR0aCA9IDA7XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLkNvbHVtbnNMaXN0Lmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGxldCBjb2wgPSB0aGlzLkNvbHVtbnNMaXN0W2ldO1xyXG4gICAgICAgICAgICBpZiAoY29sLnBpbm5lZCAmJiBjb2wudmlzaWJsZSlcclxuICAgICAgICAgICAgICAgIHRoaXMuUGlubmVkQ29udGFpbmVyV2lkdGggKz0gY29sLnBpbm5lZFdpZHRoO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLlBpbm5lZENvbnRhaW5lcldpZHRoICs9IHRoaXMuU2VsZWN0aW9uID8gMjUgOiAwO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSGVscGVyIHBlciBzcG9zdGFyZSB1biBvZ2dldHRvIGRpIHVuIGFycmF5IGRhIHVuIGluZGljZSBhbGwnYWx0cm8sIGluIHBsYWNlXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgYXJyYXlNb3ZlKGFycmF5OiBhbnlbXSwgb2xkSTogbnVtYmVyLCBuZXdJOiBudW1iZXIpIHtcclxuICAgICAgICBpZiAobmV3SSA+IGFycmF5Lmxlbmd0aCAtIDEgfHwgb2xkSSA+IGFycmF5Lmxlbmd0aCAtIDEgfHwgbmV3SSA8IDAgfHwgb2xkSSA8IDApXHJcbiAgICAgICAgICAgIHRocm93IFwiR2xpIGluZGljaSBwYXNzYXRpIG5vbiBmYW5ubyByaWZlcmltZW50byBhIHVuYSBwb3NpemlvbmUgZGVsbCdhcnJheS4gTGVuZ3RoOiBcIiArIGFycmF5Lmxlbmd0aCArIFwiIE9sZDpcIiArIG9sZEkgKyBcIiBOZXc6IFwiICsgbmV3STtcclxuXHJcbiAgICAgICAgYXJyYXkuc3BsaWNlKG5ld0ksIDAsIGFycmF5LnNwbGljZShvbGRJLCAxKVswXSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUZXJtaW5hdG8gaWwgYmluZGluZyBkZWxsZSBjb2xvbm5lIGRhICoqcmV2aWV3Q29sdW1uc0xpc3QqKiBlIGRlbGxhICoqVmlldyoqIGRhbCAqKndyaXRlVmFsdWUqKiBxdWVzdG8gbWV0b2RvIHNpIG9jY3VwYVxyXG4gICAgICogZGVsbCdhbGxpbmVhbWVudG8gZGVsbGUgaW5mb3JtYXppb25pIGZyYSBsZSBjb2xvbm5lIGNhbGNvbGF0ZSBpbnRlcm5hbWVudGUgZSBsZSBpbmZvcm1hemlvbmkgc3VsbGUgY29sb25uZSBjaGUgYXJyaXZhbm8gZGFsbCdBcHBTZWFyY2hcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge0FwcFNlYXJjaDxhbnk+fSB2aWV3IEFwcFNlYXJjaCBkYSB1dGlsaXp6YXJlIHBlciBxdWVzdGEgb3BlcmF6aW9uZVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGFsaWduQ29sdW1uc0lmTG9hZGVkVmlldyh2aWV3OiBBcHBTZWFyY2g8YW55Pikge1xyXG4gICAgICAgIGxldCBlbWl0Q2hhbmdlZCA9IHRoaXMudmlld01vZGUgJiYgdmlldy5zYXZlZHN0YXRlO1xyXG4gICAgICAgIGxldCBuZXdDb2xzZXQgPSBbXTtcclxuXHJcbiAgICAgICAgaWYgKCF0aGlzLkNvbHVtbnNMaXN0IHx8IHRoaXMuQ29sdW1uc0xpc3QubGVuZ3RoID09IDApXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgbGV0IGNvbHVtbnMgPSB0aGlzLnZpZXdNb2RlID8gdmlldy5jb2x1bW5zIDogdGhpcy5hcnJheUNvbHVtbnM7XHJcbiAgICAgICAgdGhpcy5Db2x1bW5zTGlzdC5mb3JFYWNoKGMgPT4ge1xyXG4gICAgICAgICAgICAvLyBTZSBsYSBjb2xvbm5hIMOoIHBpbm5hdGEgbWkgYXJyaXZhIGNvbCBzaW1vbGVvblxyXG4gICAgICAgICAgICBsZXQgZXhDbCA9IGNvbHVtbnMuZmlsdGVyKGNjID0+IGNjLnJlcGxhY2UoJ8KnJywgJycpID09IGMuaWQpO1xyXG5cclxuICAgICAgICAgICAgLy8gU2UgbGEgY29sb25uYSDDqCBwaW5uYXRhIGFnZ2lvcm5vIGwnaW5mb3JtYXppb25lIG5lbGxhIHZpZXdcclxuICAgICAgICAgICAgaWYgKGV4Q2wubGVuZ3RoID09IDEpXHJcbiAgICAgICAgICAgICAgICBjLnBpbm5lZCA9IGV4Q2xbMF0uc3RhcnRzV2l0aCgnwqcnKTtcclxuXHJcbiAgICAgICAgICAgIC8vIFNlIGwnYXBwc2VhcmNoIHZpZW5lIGRhIHVubyBzdGF0byBwcmVjZWRlbnRlLCB1c28gbGUgaW5mb3JtYXppb25pIHN1bGxlIGNvbG9ubmUgY2hlIGhhIGRlbnRybywgYWx0cmltZW50aSBzb3ZyYXNjcml2byB0dXR0byAgKipcclxuICAgICAgICAgICAgaWYgKGMudmlzaWJsZSAmJiBjb2x1bW5zLmxlbmd0aCA9PSAwKVxyXG4gICAgICAgICAgICAgICAgbmV3Q29sc2V0LnB1c2goYy5pZCk7XHJcbiAgICAgICAgICAgIC8vIFNlIGhvIHVuYSBjb2xvbm5hIGxhdG8gQXBwU2VhcmNoIGUgbmVsbGEgQ29sdW1uTGlzdCBub24gw6ggdmlzaWJpbGUsIGFsbGluZW8gYWxsJ0FwcFNlYXJjaFxyXG4gICAgICAgICAgICBlbHNlIGlmIChleENsLmxlbmd0aCA9PSAxICYmICFjLnZpc2libGUpXHJcbiAgICAgICAgICAgICAgICBjLnZpc2libGUgPSB0cnVlO1xyXG4gICAgICAgICAgICAvLyBBbGxpbmVhbWVudG8gc3VsbCdBcHBTZWFyY2ggcGVyIGNhc2lzdGljaGUgaW52ZXJzZSBhbCBkaSBzb3ByYVxyXG4gICAgICAgICAgICBlbHNlIGlmIChleENsLmxlbmd0aCA9PSAwICYmIGMudmlzaWJsZSlcclxuICAgICAgICAgICAgICAgIGMudmlzaWJsZSA9IGZhbHNlO1xyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICAvLyBOb24gaG8gY29sb25uZSBuZWxsYSBhcHBzZWFyY2gsIHZ1b2wgZGlyZSBjaGUgc29ubyBhbCBwcmltbyBiaW5kaW5nXHJcbiAgICAgICAgaWYgKGNvbHVtbnMubGVuZ3RoID09IDApIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMudmlld01vZGUpIHZpZXcuY29sdW1ucyA9IG5ld0NvbHNldDtcclxuICAgICAgICAgICAgZWxzZSB0aGlzLmFycmF5Q29sdW1ucyA9IG5ld0NvbHNldFxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKCh0aGlzLnZpZXdNb2RlICYmIHZpZXcuc2F2ZWRzdGF0ZSkgJiYgdGhpcy5Db2x1bW5zT3JkZXJpbmcgJiYgdmlldy5jb2x1bW5fb3JkZXJpbmcubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICAvLyBTY29ycm8gZ2xpIG9yZGluYW1lbnRpIGNoZSBhdmV2byBzYWx2YXRvIGUgcmljcmVvIGxhIENvbHVtbnNMaXN0IGluIGJhc2UgYSBsb3JvXHJcbiAgICAgICAgICAgIGxldCBuZXdDb2xMaXN0ID0gW107XHJcbiAgICAgICAgICAgIHZpZXcuY29sdW1uX29yZGVyaW5nLmZvckVhY2goY28gPT4geyB0aGlzLkNvbHVtbnNMaXN0LmZvckVhY2goYyA9PiB7IGlmIChjLmlkID09IGNvKSBuZXdDb2xMaXN0LnB1c2goYyk7IH0pOyB9KTtcclxuICAgICAgICAgICAgdGhpcy5Db2x1bW5zTGlzdCA9IG5ld0NvbExpc3Q7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBJbiBvZ25pIGNhc28gcXVlc3RvIG5vbiBtaSBzZXJ2ZSBwacO5LCBsbyByZXNldHRvICAqKlxyXG4gICAgICAgIGlmICh0aGlzLnZpZXdNb2RlKVxyXG4gICAgICAgICAgICB2aWV3LnNhdmVkc3RhdGUgPSBmYWxzZTtcclxuXHJcbiAgICAgICAgaWYgKGVtaXRDaGFuZ2VkKVxyXG4gICAgICAgICAgICB0aGlzLmNoYW5nZWQoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIE1ldG9kbyBjaGUgZ2VzdGlzY2UgaWwgY2FtYmlvIGRpIE9yZGluYW1lbnRvIGRpIHVuYSBjb2xvbm5hXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGlkIElEIGRlbGxhIGNvbG9ubmEgaWwgY3VpIG9yaWRuYW1lbnRvIMOoIGNhbWJpYXRvXHJcbiAgICAgKiBAcGFyYW0geydERVNDJyB8ICdBU0MnfSBvcmRlciBOdW92byBvcmRpbmUgc2VsZXppb25hdG8gcGVyIGxhIGNvbG9ubmFcclxuICAgICAqL1xyXG4gICAgcHVibGljIHRoT3JkZXJDaGFuZ2VkKGlkOiBzdHJpbmcsIG9yZGVyPzogJ0RFU0MnIHwgJ0FTQycpIHtcclxuICAgICAgICBpZiAoIXRoaXMudmlld01vZGUgJiYgIXRoaXMuYXJyYXlNb2RlKSB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignT3JkZXIgY2hhbmdlZCBvbiBhIHRhYmxlIG5vdCBpbiB2aWV3TW9kZSBvciBBcnJheSBtb2RlLiBPcGVyYXRpb24gbm90IHN1cHBvcnRlZCcpO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoIXRoaXMuT3JkZXJCeUNvbHVtbilcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICBsZXQgb3JkZXJzID0gdGhpcy52aWV3TW9kZSA/ICh0aGlzLlZpZXcgYXMgQXBwU2VhcmNoPGFueT4pLm9yZGVycyA6IHRoaXMuYXJyYXlPcmRlcnM7XHJcbiAgICAgICAgbGV0IG9yZGVyVG9BZGQgPSB0cnVlO1xyXG4gICAgICAgIGxldCBvcmRlclRvUmVtb3ZlOiBudW1iZXIgPSBudWxsO1xyXG5cclxuICAgICAgICAvLyBTZSBwZXIgcXVhbGNoZSBtb3Rpdm8gaWwgY29zdHJ1dHRvcmUgbm9uIMOoIHBhc3NhdG8gKGNhY2hlIHRhcnBhdGUgbyBzaW1pbGEpIGZpeG9cclxuICAgICAgICBpZiAoIW9yZGVycyAmJiB0aGlzLnZpZXdNb2RlKVxyXG4gICAgICAgICAgICAodGhpcy5WaWV3IGFzIEFwcFNlYXJjaDxhbnk+KS5vcmRlcnMgPSBbXTtcclxuICAgICAgICBlbHNlIGlmICghb3JkZXJzICYmIHRoaXMuYXJyYXlNb2RlKVxyXG4gICAgICAgICAgICB0aGlzLmFycmF5T3JkZXJzID0gW107XHJcblxyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3JkZXJzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGxldCB0ID0gb3JkZXJzW2ldO1xyXG4gICAgICAgICAgICBpZiAodC5pZCA9PSBpZCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdC5vcmRlciA9IG9yZGVyO1xyXG4gICAgICAgICAgICAgICAgICAgIG9yZGVyVG9BZGQgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgICAgICBvcmRlclRvUmVtb3ZlID0gaTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKG9yZGVyVG9SZW1vdmUgIT0gbnVsbCkge1xyXG4gICAgICAgICAgICBvcmRlcnMuc3BsaWNlKG9yZGVyVG9SZW1vdmUsIDEpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIGlmIChvcmRlclRvQWRkKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLk11bHRpcGxlT3JkZXJpbmdEaXJlY3RpdmVzKVxyXG4gICAgICAgICAgICAgICAgb3JkZXJzLnB1c2gobmV3IEFwcE9yZGVyaW5nKGlkLCBvcmRlcikpO1xyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnZpZXdNb2RlKVxyXG4gICAgICAgICAgICAgICAgICAgICh0aGlzLlZpZXcgYXMgQXBwU2VhcmNoPGFueT4pLm9yZGVycyA9IFtuZXcgQXBwT3JkZXJpbmcoaWQsIG9yZGVyKV07XHJcbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0aGlzLmFycmF5TW9kZSlcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmFycmF5T3JkZXJzID0gW25ldyBBcHBPcmRlcmluZyhpZCwgb3JkZXIpXTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5vbk9yZGVyQ2hhbmdlZC5lbWl0KHsgaWQsIG9yZGVyIH0pO1xyXG5cclxuICAgICAgICBpZiAodGhpcy52aWV3TW9kZSkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5ncm91cFNlYXJjaFJlcXVlc3RzQ2FjaGUubGVuZ3RoID4gMClcclxuICAgICAgICAgICAgICAgIHRoaXMuZW1pdFJvd0dyb3VwaW5nU2VhcmNoZXMoaWQsIG9yZGVycyk7XHJcbiAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgIHRoaXMuZW1pdFNlYXJjaFJlcXVlc3QoZmFsc2UpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIGlmICh0aGlzLmFycmF5TW9kZSlcclxuICAgICAgICAgICAgdGhpcy5pbnRlcm5hbFdyaXRlVmFsdWUoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIE1ldG9kbyBkYSBjaGlhbWFyZSBvZ25pIHZvbHRhIGNoZSBzaSB2dW9sZSBkYXJlIGV2aWRlbnphIGFsbCdlc3Rlcm5vIGRlbCBiaXNvZ25vIGRpIHJpZWZmZXR0dWFyZSBsYSByaWNlcmNhXHJcbiAgICAgKiBcclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gcmVzZXRzUGFnZSBJbmRpY2EgYWwgbGlzdGVuZXIgY2hlIGRldmUgcmVzZXR0YXJlIGlsIG51bWVybyBkaSBwYWdpbmFcclxuICAgICAqIEBwYXJhbSB7QXBwU2VhcmNoPGFueT59IHZpZXdPdmVycmlkZSBPdmVycmlkZSBkZWxsYSB2aWV3IGRhIGVtZXR0ZXJlIHBlciBxdWVzdGEgcmljZXJjYVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGVtaXRTZWFyY2hSZXF1ZXN0KHJlc2V0c1BhZ2U6IGJvb2xlYW4sIHZpZXdPdmVycmlkZT86IEFwcFNlYXJjaDxhbnk+KSB7XHJcbiAgICAgICAgaWYgKHRoaXMudmlld01vZGUgJiYgIXZpZXdPdmVycmlkZSkge1xyXG4gICAgICAgICAgICAodGhpcy5WaWV3IGFzIEFwcFNlYXJjaDxhbnk+KS5pbnRlcm5hbHNlYXJjaHJlcXVlc3QgPSB0cnVlO1xyXG4gICAgICAgICAgICB0aGlzLmNoYW5nZWQoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh2aWV3T3ZlcnJpZGUpIHtcclxuICAgICAgICAgICAgaWYgKHJlc2V0c1BhZ2UpXHJcbiAgICAgICAgICAgICAgICB2aWV3T3ZlcnJpZGUucGFnZSA9IDE7XHJcbiAgICAgICAgICAgIHZpZXdPdmVycmlkZS5pbnRlcm5hbHNlYXJjaHJlcXVlc3QgPSB0cnVlXHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLnJlc2VhcmNoSW5Qcm9ncmVzcyA9IHRydWU7XHJcbiAgICAgICAgdGhpcy5vblNlYXJjaFJlcXVlc3QuZW1pdCh2aWV3T3ZlcnJpZGUgPyB2aWV3T3ZlcnJpZGUgOiByZXNldHNQYWdlKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEluIGJhc2UgYWxsYSB2aXNpYmlsaXTDoCByZWdpc3RyYXRhIG5lbGxlICoqQ29sdW1uc0xpc3QqKiBxdWVzdG8gbWV0b2RvIHNpIG9jY3VwYSBkaSBwcmVuZGVyZSB0dXR0aSBpICoqRXNUaHMqKiBlZCAqKkVzVGRzKiogcmVsYXRpdmkgZSBuYXNvbmRlcmxpL21vc3RyYXJsaVxyXG4gICAgICpcclxuICAgICAqIENvc3RvOiAxIHNjYW4gQ29sdW1uc0xpc3QsIDEgc2NhbiBFc1RocywgMSBzY2FuIEVzVGRzXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtFc1RoW10gfCBFc1RoRGlyZWN0aXZlW119IHRocyBIZWFkZXIgZGVsbGEgdGFiZWxsYVxyXG4gICAgICogQHBhcmFtIHtFc1RkW10gfCBFc1RkRGlyZWN0aXZlW119IHRkcyBDZWxsZSBkZWxsYSB0YWJlbGxhXHJcbiAgICAgKiBAcGFyYW0ge0FwcFNlYXJjaDxhbnk+fSB2aWV3IEFwcFNlYXJjaCBkYSB1dGlsaXp6YXJlIHBlciBxdWVzdGEgb3BlcmF6aW9uZVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHJlZnJlc2hDb2x1bW5zVmlzaWJpbGl0eSh0aHM6IEVzVGhbXSB8IEVzVGhEaXJlY3RpdmVbXSwgdGRzOiBFc1RkW10gfCBFc1RkRGlyZWN0aXZlW10sIHZpZXc6IEFwcFNlYXJjaDxhbnk+KSB7XHJcbiAgICAgICAgbGV0IG5ld0NvbHNldCA9IFtdO1xyXG4gICAgICAgIGxldCBmaXhlZFRoczogeyBbaWQ6IHN0cmluZ106IGJvb2xlYW4gfSA9IHt9O1xyXG4gICAgICAgIGxldCBjb2x1bW5zQ2FjaGU6IHsgW2luZGV4OiBzdHJpbmddOiBFc1RhYmxlQ29sdW1uIH0gPSB7fTtcclxuICAgICAgICBmb3IgKGxldCBjb2xpID0gMDsgY29saSA8IHRoaXMuQ29sdW1uc0xpc3QubGVuZ3RoOyBjb2xpKyspIHtcclxuICAgICAgICAgICAgbGV0IGNvbCA9IHRoaXMuQ29sdW1uc0xpc3RbY29saV07XHJcbiAgICAgICAgICAgIGNvbHVtbnNDYWNoZVtjb2wuaWRdID0gY29sO1xyXG4gICAgICAgICAgICBpZiAoY29sLnZpc2libGUpIG5ld0NvbHNldC5wdXNoKChjb2wucGlubmVkID8gXCLCp1wiIDogXCJcIikgKyBjb2wuaWQpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZih2aWV3KVxyXG4gICAgICAgICAgICB2aWV3LmNvbHVtbnMgPSBuZXdDb2xzZXQ7XHJcbiAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICB0aGlzLmFycmF5Q29sdW1ucyA9IG5ld0NvbHNldDtcclxuXHJcbiAgICAgICAgLy8gRGEgcXVpIGluIHBvaSBkZXZvbm8gZXNzZXJlIGVzZWd1aXRpIFNPTE8gaW4gZmFzZSBkaSB3cml0ZVZhbHVlIHF1aW5kaSBkZXZvIGFzc2ljdXJhcm1pIGRpIHBhc3NhcmxpIG51bGwgaW4gdHV0dGkgaSBwYXNzYWdnaSBkaXZlcnNpIGRhIHF1ZWxsb1xyXG4gICAgICAgIGlmICh0aHMpIHtcclxuICAgICAgICAgICAgLy8gRGVmaW5pc2NvIHNlIGxhIGNvbG9ubmEgw6ggdmlzaWJpbGUgaW4gYmFzZSBhbGxhIHN1YSByYXBwcmVzZW50YXppb25lIGxvY2FsZSBpbiBDb2x1bW5zTGlzdFxyXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRocy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgbGV0IHRoID0gdGhzW2ldO1xyXG4gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pc0VzVGgodGgpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGguVmlzaWJsZSA9IHRoLkZpeGVkIHx8IChjb2x1bW5zQ2FjaGVbdGguSURdID8gY29sdW1uc0NhY2hlW3RoLklEXS52aXNpYmxlIDogdGguVmlzaWJsZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoLkZpeGVkKSBmaXhlZFRoc1t0aC5JRF0gPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGgudGhWaXNpYmxlID0gdGgudGhGaXhlZCB8fCAoY29sdW1uc0NhY2hlW3RoLnRoXSA/IGNvbHVtbnNDYWNoZVt0aC50aF0udmlzaWJsZSA6IHRoLnRoVmlzaWJsZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoLnRoRml4ZWQgfHwgdGgudGhHcm91cCkgZml4ZWRUaHNbdGgudGhdID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRkcykge1xyXG4gICAgICAgICAgICAvLyBEZWZpbmlzY28gc2UgbGEgY2VsbGEgw6ggdmlzaWJpbGUgaW4gYmFzZSBhbGxhIHN1YSByYXBwcmVzZW50YXppb25lIGxvY2FsZSBpbiBDb2x1bW5zTGlzdFxyXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRkcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgbGV0IHRkID0gdGRzW2ldO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzRXNUZCh0ZCkpXHJcbiAgICAgICAgICAgICAgICAgICAgdGQuVmlzaWJsZSA9IGZpeGVkVGhzW3RkLklEXSB8fCAoY29sdW1uc0NhY2hlW3RkLklEXSA/IGNvbHVtbnNDYWNoZVt0ZC5JRF0udmlzaWJsZSA6IHRkLlZpc2libGUpO1xyXG4gICAgICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgICAgIHRkLnRkVmlzaWJsZSA9IGZpeGVkVGhzW3RkLnRkXSB8fCAoY29sdW1uc0NhY2hlW3RkLnRkXSA/IGNvbHVtbnNDYWNoZVt0ZC50ZF0udmlzaWJsZSA6IHRkLnRkVmlzaWJsZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMuY2hhbmdlZCgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQWxsaW5lYSBnbGkgb3JkaW5hbWVudGkgZGF0aSBmcmEgbGUgKipFc1RocyoqIGUgbGUgaW5mb3JtYXppb25pIGFsbCdpbnRlcm5vIGRlbGxhIFZpZXcgYmluZGF0YVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7QXBwU2VhcmNoPGFueT59IHZpZXcgQXBwU2VhcmNoIGRhIHV0aWxpenphcmUgcGVyIHF1ZXN0YSBvcGVyYXppb25lXHJcbiAgICAgKiBAcGFyYW0ge0VzVGhbXSB8IEVzVGhEaXJlY3RpdmVbXX0gdGhzIENvbG9ubmUgZGVsbGEgdGFiZWxsYVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGFsaWduSGVhZGVyc09yZGVyaW5nKHRoczogRXNUaFtdIHwgRXNUaERpcmVjdGl2ZVtdLCB2aWV3OiBBcHBTZWFyY2g8YW55Pikge1xyXG4gICAgICAgIGxldCBvcmRlcnMgPSB2aWV3ID8gdmlldy5vcmRlcnMgOiB0aGlzLmFycmF5T3JkZXJzO1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGxldCB0aCA9IHRoc1tpXTtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLmlzRXNUaCh0aCkpIHtcclxuICAgICAgICAgICAgICAgIHRoLk9yZGVyID0gbnVsbDtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBBc3NlZ25vIHR1dHRpIGdsaSBvcmRpbmFtZW50aSBjaGUgbWkgdmVuZ29ubyBkYSBBcHBTZWFyY2guIFNvbm8gaSBwacO5IGltcG9ydGFudGkuIE5vbiBmYWNjaW8gY2FjaGUgbyBjb3NlIHN0cmFubyBwZXJjaMOpIHRhbnRvIHF1ZXN0YVxyXG4gICAgICAgICAgICAgICAgLy8gdmFyaWFiaWxlIHNhcsOgIHNlbXByZSBtYXNzaW1vIDMgZWxlbWVudGlcclxuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3JkZXJzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IG9yID0gb3JkZXJzW2ldO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChvci5pZCA9PSB0aC5JRClcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGguT3JkZXIgPSBvci5vcmRlcjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHRoLnRoT3JkZXIgPSBudWxsO1xyXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvcmRlcnMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgb3IgPSBvcmRlcnNbaV07XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9yLmlkID09IHRoLnRoKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aC50aE9yZGVyID0gb3Iub3JkZXI7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBQYXJ0ZW5kbyBkYWdsaSAqKkVzVGRzKiogYmluZGF0aSBnZW5lcmEsIGFsbCdpbnRlcm5vIGRlbCBkaXppb25hcmlvICoqVE1QUm93VERzKiogdHV0dGkgaSBjb250ZXN0aSBkZWkgdmFyaSBvZ2dldHRpLlxyXG4gICAgICpcclxuICAgICAqIFZlbmdvbm8gZXNjbHVzaSBpIFREIFwiSW50ZXJuaVwiIGluIHF1YW50byB2ZW5nb25vIGdlbmVyYXRpIGRhZ2xpIG9yaWdpbmFsaSBxdWluZGkgaW5jbHVkZXJsaSB2b3JyZWJiZSBkaXJlIHJpZWZmZXR0dWFyZSBsZSBvcGVyYXppb25pIGR1ZSB2b2x0ZVxyXG4gICAgICpcclxuICAgICAqIENvc3RvOiAyIHNjYW4gRXNUaHMsIDEgc2NhbiBFc1Rkc1xyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7RXNUaFtdIHwgRXNUaERpcmVjdGl2ZVtdfSB0aHMgQ29sb25uZSBkZWxsYSB0YWJlbGxhXHJcbiAgICAgKiBAcGFyYW0ge0VzVGRbXSB8IEVzVGREaXJlY3RpdmVbXX0gdGRzIENlbGxlIGRlbGxhIHRhYmVsbGFcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBldmFsdWF0ZVJvd1Rkcyh0aHM6IEVzVGhbXSB8IEVzVGhEaXJlY3RpdmVbXSwgdGRzOiBFc1RkW10gfCBFc1RkRGlyZWN0aXZlW10pIHtcclxuICAgICAgICBpZiAodGRzLmxlbmd0aCA9PSAwKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgIGxldCB0aHNDYWNoZTogeyBbaW5kZXg6IHN0cmluZ106IEVzVGggfCBFc1RoRGlyZWN0aXZlIH0gPSB7fTtcclxuICAgICAgICBsZXQgY29sdW1uc0NhY2hlOiB7IFtpbmRleDogc3RyaW5nXTogRXNUYWJsZUNvbHVtbiB9ID0ge307XHJcblxyXG4gICAgICAgIGZvciAobGV0IGNvbGkgPSAwOyBjb2xpIDwgdGhpcy5Db2x1bW5zTGlzdC5sZW5ndGg7IGNvbGkrKykge1xyXG4gICAgICAgICAgICBsZXQgY29sID0gdGhpcy5Db2x1bW5zTGlzdFtjb2xpXTtcclxuICAgICAgICAgICAgY29sdW1uc0NhY2hlW2NvbC5pZF0gPSBjb2w7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRocy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgdGggPSB0aHNbaV07XHJcbiAgICAgICAgICAgIHRoc0NhY2hlW3RoaXMuaXNFc1RoKHRoKSA/IHRoLklEIDogdGgudGhdID0gdGg7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLlRNUFJvd1REcyA9IHt9O1xyXG4gICAgICAgIC8vIFZhcmlhYmlsZSBkJ2FwcG9nZ2lvIHBlciBwZXJtZXR0ZXJtaSBkaSBpbnNlcmlyZSB0dXR0ZSBsZSBjb2xvbm5lIFwiRml4ZWRcIiBkYXZhbnRpXHJcbiAgICAgICAgbGV0IGNvbnRleHRGaXhlZHM6IHsgW2NvbnRleHQ6IHN0cmluZ106IG51bWJlciB9ID0ge307XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0ZHMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgbGV0IHRkID0gdGRzW2ldO1xyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMuaXNFc1RkKHRkKSkge1xyXG4gICAgICAgICAgICAgICAgbGV0IHRoID0gdGhzQ2FjaGVbdGQuSURdO1xyXG4gICAgICAgICAgICAgICAgaWYgKCEhdGgpXHJcbiAgICAgICAgICAgICAgICAgICAgdGguX3JlZmVyZW5jZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFwiSUQgZGVsbCdvZ2dldG8gRXNUZCBub24gY29tcGF0aWJpbGUgY29uIGdsaSBJRCBkaWNoYXJhdGkgbmVnbGkgRXNUaDogXCIgKyB0ZC5JRDtcclxuXHJcbiAgICAgICAgICAgICAgICBsZXQgaXNGaXhlZCA9ICh0aGlzLmlzRXNUaCh0aCkgJiYgdGguRml4ZWQpIHx8ICghdGhpcy5pc0VzVGgodGgpICYmICh0aC50aEZpeGVkIHx8IHRoLnRoR3JvdXApKTtcclxuICAgICAgICAgICAgICAgIGxldCBpdGVtVG9BZGQgPSA8YW55PnsgR3JvdXBBZ2dyZWdhdGlvbjogZmFsc2UsIEdyb3VwSGVhZGVyOiBmYWxzZSwgV3JhcHM6IHRydWUsIElEOiB0ZC5JRCwgVmlzaWJsZTogdGQuVmlzaWJsZSwgQ2xhc3M6IHRkLkNsYXNzLCBDb250ZW50OiB0ZC5Db250ZW50LCBSb3V0ZXJMaW5rOiB0ZC5Sb3V0ZXJMaW5rLCBUZW1wbGF0ZTogdGQuVGVtcGxhdGUgfTtcclxuICAgICAgICAgICAgICAgIGxldCBjdHggPSB0ZC5Db250ZXh0O1xyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuVE1QUm93VERzW2N0eF0pIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNGaXhlZClcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5UTVBSb3dURHNbY3R4XS5zcGxpY2UoMCArIChjb250ZXh0Rml4ZWRzW2N0eF0rKyksIDAsIGl0ZW1Ub0FkZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLlRNUFJvd1REc1tjdHhdLnB1c2goaXRlbVRvQWRkKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuUm93Q29udGV4dHMucHVzaChjdHgpO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuVE1QUm93VERzW2N0eF0gPSBbaXRlbVRvQWRkXTtcclxuICAgICAgICAgICAgICAgICAgICBjb250ZXh0Rml4ZWRzW2N0eF0gPSBpc0ZpeGVkID8gMSA6IDBcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5ib3VuZFNvdXJjZS5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBpdGVtID0gdGhpcy5ib3VuZFNvdXJjZVtpXTtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgY3R4ID0gaXRlbS5faGFzaDtcclxuICAgICAgICAgICAgICAgICAgICBsZXQga2V5ID0gdGQudGQ7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IHRoID0gdGhzQ2FjaGVbdGQudGRdO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmICghIXRoKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aC5fcmVmZXJlbmNlZCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBcIklEIGRlbGwnb2dnZXRvIEVzVGQgbm9uIGNvbXBhdGliaWxlIGNvbiBnbGkgSUQgZGljaGFyYXRpIG5lZ2xpIEVzVGg6IFwiICsgdGQudGQ7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0ZC50ZElmIHx8ICghdGhpcy5pc0VzVGgodGgpICYmIHRoLnRoR3JvdXApKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB0aENhc3RlZCA9IDxFc1RoRGlyZWN0aXZlPnRoO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgaXNGaXhlZCA9ICh0aGlzLmlzRXNUaCh0aCkgJiYgdGguRml4ZWQpIHx8ICghdGhpcy5pc0VzVGgodGgpICYmICh0aC50aEZpeGVkIHx8IHRoLnRoR3JvdXAgfHwgdGgudGhQaW5uZWQpKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGl0ZW1Ub0FkZCA9IGl0ZW0uX2l0ZW0gP1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGFueT57IExlZnRCb3JkZXI6ICg8YW55PnRoQ2FzdGVkKS5fbGJvcmQsIFJpZ2h0Qm9yZGVyOiAoPGFueT50aENhc3RlZCkuX3Jib3JkLCBJRDoga2V5LCBQaW5uZWQ6IGNvbHVtbnNDYWNoZVt0ZC50ZF0ucGlubmVkLCBQaW5uZWRXaWR0aDogdGhDYXN0ZWQudGhQaW5uZWRXaWR0aCwgR3JvdXBIZWFkZXI6IGZhbHNlLCBHcm91cEFnZ3JlZ2F0aW9uOiBmYWxzZSwgVmlzaWJsZTogY29sdW1uc0NhY2hlW3RkLnRkXS52aXNpYmxlLCBXcmFwczogZmFsc2UsIENsYXNzOiB0ZC50ZENsYXNzLCBUZW1wbGF0ZTogdGhDYXN0ZWQudGhHcm91cCAmJiAhdGhpcy5TaG93SXRlbUdyb3Vwc0NvbHVtbnMgPyBudWxsIDogdGQuVGVtcGxhdGUgfSA6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YW55PnsgTGVmdEJvcmRlcjogKDxhbnk+dGhDYXN0ZWQpLl9sYm9yZCwgUmlnaHRCb3JkZXI6ICg8YW55PnRoQ2FzdGVkKS5fcmJvcmQsIElEOiBrZXksIFBpbm5lZDogY29sdW1uc0NhY2hlW3RkLnRkXS5waW5uZWQsIFBpbm5lZFdpZHRoOiB0aENhc3RlZC50aFBpbm5lZFdpZHRoLCBHcm91cEhlYWRlcjogdGhDYXN0ZWQudGhHcm91cCwgR3JvdXBBZ2dyZWdhdGlvbjogISF0aENhc3RlZC50aEFnZ3JlZ2F0aW9uLCBWaXNpYmxlOiBjb2x1bW5zQ2FjaGVbdGQudGRdLnZpc2libGUsIFdyYXBzOiBmYWxzZSwgQ2xhc3M6IHRoQ2FzdGVkLnRoR3JvdXBDbGFzcyB8fCAnJywgQ29udGVudDogdGhpcy5nZXRHcm91cENlbGxEaXNwbGF5KDxHcm91cD5pdGVtLCBrZXksIDxFc1RoRGlyZWN0aXZlPnRoKSB9O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuVE1QUm93VERzW2N0eF0pIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5vbiBzZXJ2ZSBwacO5IGdyYXppZSBhbCBtZXRvZG8gKipvdmVGaXhlZENvbHVtbnNBdFRoZUJlZ2lubmluZyoqXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL2lmIChpc0ZpeGVkKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgdGhpcy5UTVBSb3dURHNbY3R4XS5zcGxpY2UoMCArIChjb250ZXh0Rml4ZWRzW2N0eF0rKyksIDAsIGl0ZW1Ub0FkZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL2Vsc2VcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuVE1QUm93VERzW2N0eF0ucHVzaChpdGVtVG9BZGQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5Sb3dDb250ZXh0cy5wdXNoKGN0eCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLlRNUFJvd1REc1tjdHhdID0gW2l0ZW1Ub0FkZF07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0Rml4ZWRzW2N0eF0gPSBpc0ZpeGVkID8gMSA6IDA7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIFNlIG5vbiBobyBvZ2dldHRpIMOoIGludXRpbGUgY2hlIGNvbnRyb2xsbyBnbGkgZXJyb3JpLCBkYXRvIGNoZSBnbGkgZXMtdGQgbm9uIGVzaXN0ZXJhbm5vIGRpIGNlcnRvIGUgZGkgY29uc2VndWVuemEgZ2xpIGVzLXRoIG5vbiBzYXJhbm5vIHJlZmVyZW56aWF0aVxyXG4gICAgICAgIGlmKHRoaXMuVE1QQm91bmRTb3VyY2UubGVuZ3RoID09IDApXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgdmFyIGVycnM6IHN0cmluZ1tdID0gW107XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aHMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgbGV0IHRoID0gdGhzW2ldO1xyXG4gICAgICAgICAgICBpZiAoIXRoLl9yZWZlcmVuY2VkKVxyXG4gICAgICAgICAgICAgICAgZXJycy5wdXNoKHRoaXMuaXNFc1RoKHRoKSA/IHRoLklEIDogdGgudGgpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGVycnMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICB2YXIgZXJySWRzID0gZXJycy5qb2luKCcsICcpO1xyXG4gICAgICAgICAgICB0aHJvdyBcIkwnSUQgZGkgdW5vIG8gcGnDuSBFc1RoIG5vbiBoYW5ubyBhbGN1biBFc1RkIGFzc29jaWF0bzogXCIgKyBlcnJJZHM7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUGFydGVuZG8gZGFnbGkgKipFc1RocyoqIGJpbmRhdGkgZ2VuZXJhLCBhbGwnaW50ZXJubyBkZWwgZGl6aW9uYXJpbyAqKlRNUFJvd1RIcyoqIHR1dHRpIGkgY29udGVzdGkgZGVpIHZhcmkgb2dnZXR0aS5cclxuICAgICAqXHJcbiAgICAgKiBWZW5nb25vIGVzY2x1c2kgaSBUSCBcIkludGVybmlcIiBpbiBxdWFudG8gdmVuZ29ubyBnZW5lcmF0aSBkYWdsaSBvcmlnaW5hbGkgcXVpbmRpIGluY2x1ZGVybGkgdm9ycmViYmUgZGlyZSByaWVmZmV0dHVhcmUgbGUgb3BlcmF6aW9uaSBkdWUgdm9sdGVcclxuICAgICAqXHJcbiAgICAgKiBDb3N0bzogMSBzY2FuIEVzVGhzXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtFc1RoW10gfCBFc1RoRGlyZWN0aXZlW119IHRocyBDb2xvbm5lIGRlbGxhIHRhYmVsbGFcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBldmFsdWF0ZVJvd1Rocyh0aHM6IEVzVGhbXSB8IEVzVGhEaXJlY3RpdmVbXSkge1xyXG4gICAgICAgIGlmICh0aHMubGVuZ3RoID09IDApXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgbGV0IGNvbHVtbnNMaXN0Q2FjaGU6IHsgW2luZGV4OiBzdHJpbmddOiBFc1RhYmxlQ29sdW1uIH0gPSB7fTtcclxuICAgICAgICBsZXQgY2FzdGVkVmlldyA9IDxBcHBTZWFyY2g8YW55Pj50aGlzLlZpZXc7XHJcbiAgICAgICAgbGV0IGdyb3VwaW5nc1VuZGVmaW5lZCA9IHRoaXMudmlld01vZGUgJiYgKGNhc3RlZFZpZXcgJiYgIWNhc3RlZFZpZXcuZ3JvdXBpbmdzIHx8IGNhc3RlZFZpZXcuZ3JvdXBpbmdzLmxlbmd0aCA9PSAwKTtcclxuXHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLkNvbHVtbnNMaXN0Lmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGxldCBpdG0gPSB0aGlzLkNvbHVtbnNMaXN0W2ldO1xyXG4gICAgICAgICAgICBjb2x1bW5zTGlzdENhY2hlW2l0bS5pZF0gPSBpdG1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMuVE1QUm93VEhzID0gW107XHJcbiAgICAgICAgbGV0IGZpeGVkID0gMDtcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRocy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgdGggPSB0aHNbaV07XHJcbiAgICAgICAgICAgIGxldCB0b0FkZDtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLmlzRXNUaCh0aCkpIHtcclxuICAgICAgICAgICAgICAgIHRvQWRkID0geyBQaW5uZWQ6IGZhbHNlLCBJRDogdGguSUQsIFZpc2libGU6IHRoLlZpc2libGUsIENsYXNzOiB0aC5DbGFzcywgT3JkZXI6IHRoLk9yZGVyLCBPcmRlcmFibGU6IHRoLk9yZGVyYWJsZSwgVGVtcGxhdGU6IG51bGwsIENvbnRlbnQ6IHRoLkRlc2NyaXB0aW9uLCBXcmFwOiBmYWxzZSB9O1xyXG4gICAgICAgICAgICAgICAgaWYgKHRoLkZpeGVkKVxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuVE1QUm93VEhzLnNwbGljZSgwICsgKGZpeGVkKyspLCAwLCB0b0FkZCk7XHJcbiAgICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5UTVBSb3dUSHMucHVzaCh0b0FkZCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSBpZiAodGgudGhJZiB8fCB0aC50aEdyb3VwKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgbGV0IHRoQ2xhc3MgPSAodGgudGhDbGFzcyB8fCAnJykgKyAodGgudGhHcm91cCA/IFwiIGVzdC1jb2wtbWluXCIgOiBcIlwiKTtcclxuICAgICAgICAgICAgICAgIHRvQWRkID0geyBQaW5uZWQ6IGNvbHVtbnNMaXN0Q2FjaGVbdGgudGhdLnBpbm5lZCwgUGlubmVkV2lkdGg6IHRoLnRoUGlubmVkV2lkdGgsIElEOiB0aC50aCwgVmlzaWJsZTogdGgudGhWaXNpYmxlLCBDbGFzczogdGhDbGFzcywgT3JkZXI6IHRoLnRoT3JkZXIsIE9yZGVyYWJsZTogdGgudGhPcmRlcmFibGUsIFRlbXBsYXRlOiB0aC5UZW1wbGF0ZSwgQ29udGVudDogbnVsbCwgV3JhcDogZmFsc2UsIExlZnRCb3JkZXI6ICg8YW55PnRoKS5fbGJvcmQsIFJpZ2h0Qm9yZGVyOiAoPGFueT50aCkuX3Jib3JkIH07XHJcbiAgICAgICAgICAgICAgICB0aGlzLlRNUFJvd1RIcy5wdXNoKHRvQWRkKTtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBTZSBobyB1biBtb2RlbGxvIGNoZSBkZXZlIGZ1bnppb25hcmUgYSByb3dncm91cGluZyBtYSBub24gw6ggYW5jb3JhIHN0YXRhIGVmZmV0dHVhdGEgbmVzc3VuYSByaWNlcmNhIHN1aSBncnVwcGkgcHJpbmNpcGFsaSAoZ3JvdXBpbmdzVW5kZWZpbmVkKVxyXG4gICAgICAgICAgICAgICAgLy8gbGkgZ2VuZXJvIGUgbWFuZG8gbGEgcHJpbWEgcmljZXJjYSBjaGUgZGV2J2Vzc2VyZSBzcGVkaXRhIGFsIGJhY2tlbmQgcGVyIGlsIHByaW1vIGNhcmljYW1lbnRvIGRlaSBncnVwcGlcclxuICAgICAgICAgICAgICAgIGlmIChncm91cGluZ3NVbmRlZmluZWQgJiYgKHRoLnRoQWdncmVnYXRpb24gfHwgdGgudGhHcm91cCkpIHtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgZ3JvdXBBZ2dyZWdhdGlvbnM6IEdyb3VwT3JBZ2dyZWdhdGlvbltdID0gdGhpcy5nZXRHcm91cEFnZ3JlZ2F0aW9ucyh0aCk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjYXN0ZWRWaWV3Lmdyb3VwaW5ncylcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzdGVkVmlldy5ncm91cGluZ3MgPSBncm91cEFnZ3JlZ2F0aW9ucztcclxuICAgICAgICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc3RlZFZpZXcuZ3JvdXBpbmdzLnB1c2goLi4uZ3JvdXBBZ2dyZWdhdGlvbnMpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICB0aGlzLlJlc2VhcmNoTmVlZGVkID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGV2YWx1YXRlSGVhZGVyc0dyb3VwaW5nSW5mb3ModGhzOiBFc1RoW10gfCBFc1RoRGlyZWN0aXZlW10pOiB7IGxlYWZzOiBFc1RoW10gfCBFc1RoRGlyZWN0aXZlW10sIGdyb3VwaW5nTGV2ZWw6IG51bWJlciwgcGFyZW50c0NhY2hlOiBhbnksIHRoc0NhY2hlOiBhbnkgfSB7XHJcbiAgICAgICAgLy8gUHJlZ2lybyBwZXIgdHJvdmFyZSBpIHBhcmVudFxyXG4gICAgICAgIGxldCBwYXJlbnRzQ2FjaGU6IHsgW2luZGV4OiBzdHJpbmddOiBib29sZWFuIH0gPSB7fTtcclxuICAgICAgICBsZXQgdGhzQ2FjaGU6IHsgW2luZGV4OiBzdHJpbmddOiBFc1RoRGlyZWN0aXZlIH0gPSB7fTtcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRocy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgdGggPSB0aHNbaV07XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmlzRXNUaCh0aCkpIGNvbnRpbnVlO1xyXG5cclxuICAgICAgICAgICAgdGhzQ2FjaGVbdGgudGhdID0gdGg7XHJcbiAgICAgICAgICAgIGlmICh0aC50aFBhcmVudCAmJiAhcGFyZW50c0NhY2hlW3RoLnRoUGFyZW50XSlcclxuICAgICAgICAgICAgICAgIHBhcmVudHNDYWNoZVt0aC50aFBhcmVudF0gPSB0cnVlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gU2Vjb25kbyBnaXJvIHBlciBiZWNjYXJlIGlsIGxpdmVsbG8gbWFzc2ltbyBlIGxhIGxpc3RhIGRpIGZvZ2xpZSAodGggc2VuemEgcGFyZW50KVxyXG4gICAgICAgIGxldCBoTWF4TGV2ZWwgPSAwO1xyXG4gICAgICAgIGxldCBsZWFmczogYW55W10gPSBbXTtcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRocy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgdGggPSB0aHNbaV07XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmlzRXNUaCh0aCkpIHsgbGVhZnMucHVzaCh0aCk7IGNvbnRpbnVlOyB9XHJcbiAgICAgICAgICAgIC8vIFNlIHNvbm8gdW5hIGZvZ2xpYSB2ZWRvIHF1YW50aSBsaXZlbGxpIGNpIHNvbm8gc29wcmFcclxuICAgICAgICAgICAgaWYgKCFwYXJlbnRzQ2FjaGVbdGgudGhdKSB7XHJcbiAgICAgICAgICAgICAgICBsZWFmcy5wdXNoKHRoKTtcclxuICAgICAgICAgICAgICAgIGxldCB0bXAgPSB0aGlzLmp1bXBzVG9GaW5hbFBhcmVudCh0aCwgdGhzQ2FjaGUpO1xyXG4gICAgICAgICAgICAgICAgaE1heExldmVsID0gdG1wID4gaE1heExldmVsID8gdG1wIDogaE1heExldmVsO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4geyBsZWFmczogbGVhZnMsIGdyb3VwaW5nTGV2ZWw6IGhNYXhMZXZlbCwgcGFyZW50c0NhY2hlOiBwYXJlbnRzQ2FjaGUsIHRoc0NhY2hlOiB0aHNDYWNoZSB9O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2VuZXJhIGdsaSBoZWFkZXIgZ3JvdXBzIGRhIHVuYSBsaXN0YSBkaSBpbmZvIHN1aSB0aCBhbGwnaW50ZXJubyBkZWxsYSB2YXJpYWJpbGUgKipUTVBSb3dUaEdyb3VwcyoqXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZXZhbHVhdGVIZWFkZXJHcm91cHMoaW5mb3M6IHsgbGVhZnM6IEVzVGhbXSB8IEVzVGhEaXJlY3RpdmVbXSwgZ3JvdXBpbmdMZXZlbDogbnVtYmVyLCBwYXJlbnRzQ2FjaGU6IGFueSwgdGhzQ2FjaGU6IGFueSB9KTogRXNUaFtdIHwgRXNUaERpcmVjdGl2ZVtdIHtcclxuICAgICAgICBpZiAoaW5mb3MuZ3JvdXBpbmdMZXZlbCA9PSAwKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgIC8vIEdpcm8gMi41LCBjcmVvIGwnb3V0cHV0IGRlaSByYWdncnVwcGFtZW50aSBwZXIgaGVhZGVyIGluIG1vZG8gZGEgbm9uIGRvdmVybWkgcHJlb2NjdXBhcmUgZGkgY2VsbGUgbm9uIGluaXppYWxpenphdGVcclxuICAgICAgICBsZXQgZXhwYW5kZWRHcm91cHMgPSBbXTtcclxuICAgICAgICBsZXQgdmlzaWJsZVVucGlubmVkTGVhZnM6IEVzVGhEaXJlY3RpdmVbXSA9ICg8YW55W10+aW5mb3MubGVhZnMpLmZpbHRlcigodDogRXNUaERpcmVjdGl2ZSkgPT4gdC50aFZpc2libGUgJiYgIXQudGhQaW5uZWQpO1xyXG4gICAgICAgIGZvciAobGV0IGwgPSAwOyBsIDwgaW5mb3MuZ3JvdXBpbmdMZXZlbDsgbCsrKSB7XHJcbiAgICAgICAgICAgIGV4cGFuZGVkR3JvdXBzLnB1c2goW10pO1xyXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHZpc2libGVVbnBpbm5lZExlYWZzLmxlbmd0aDsgaSsrKVxyXG4gICAgICAgICAgICAgICAgZXhwYW5kZWRHcm91cHNbbF0ucHVzaChcIlwiKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIE9yZGlubyBsZSBmb2dsaWUgaW4gYmFzZSBhZ2xpIG9yZGluYW1lbnRpIGRlbGxlIGNvbG9ubmVcclxuICAgICAgICBsZXQgb3JkZXJlZExlYWZzID0gW107XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLk9yZGVyRGlyZWN0aXZlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgbGVhZjogRXNUaERpcmVjdGl2ZSA9IGluZm9zLnRoc0NhY2hlW3RoaXMuT3JkZXJEaXJlY3RpdmVzW2ldXTtcclxuICAgICAgICAgICAgaWYgKGxlYWYudGhWaXNpYmxlICYmICFsZWFmLnRoUGlubmVkKVxyXG4gICAgICAgICAgICAgICAgb3JkZXJlZExlYWZzLnB1c2gobGVhZik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBUZXJ6byBnaXJvIHBlciBjcmVhcmUgbCdhcnJheSBncm91cCBjb24gdHV0dGkgaSByaWZlcmltZW50aSBkZWwgY2Fzb1xyXG4gICAgICAgIGxldCBjdXJyZW50UGFyZW50ID0gXCJcIjtcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG9yZGVyZWRMZWFmcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgcmVmVGg6IEVzVGhEaXJlY3RpdmUgPSBvcmRlcmVkTGVhZnNbaV07XHJcbiAgICAgICAgICAgIGxldCBwcmV2VGg6IEVzVGhEaXJlY3RpdmUgPSBpIC0gMSA+PSAwID8gb3JkZXJlZExlYWZzW2ktMV0gOiBudWxsO1xyXG5cclxuICAgICAgICAgICAgLy8gUGFyZW50IGRpdmVyc28gZGEgcHJpbWEsIG1ldHRvIGlsIGJvcmRvIGEgc2luaXN0cmEgZSBhIGRlc3RyYSBkZWxsYSBjZWxsYSBwcmVjZWRlbnRlIChzZSBjJ8OoKVxyXG4gICAgICAgICAgICAvLyBBbGwndWx0aW1vIGdpcm8gbWV0dG8gaWwgYm9yZG8gYSBkZXN0cmEuIFR1dHRvIHF1ZXN0byBsbyByaWVzZWd1byBwZXIgb2duaSBjZWxsYSBpbiBtb2RvIGRhIHJpcHVsaXJlIGV2ZW50dWFsaSBhIGN1aSBhdmV2byBhc3NlZ25hdG8gdGFnIHByZWNlZGVudGVtZW50ZVxyXG4gICAgICAgICAgICAoPGFueT5yZWZUaCkuX2xib3JkID0gcmVmVGgudGhQYXJlbnQgIT0gY3VycmVudFBhcmVudDtcclxuICAgICAgICAgICAgKDxhbnk+cmVmVGgpLl9yYm9yZCA9IHZpc2libGVVbnBpbm5lZExlYWZzLmxlbmd0aCA9PSBpICsgMTtcclxuICAgICAgICAgICAgaWYgKHByZXZUaCkgKDxhbnk+cHJldlRoKS5fcmJvcmQgPSByZWZUaC50aFBhcmVudCAhPSBjdXJyZW50UGFyZW50O1xyXG5cclxuICAgICAgICAgICAgY3VycmVudFBhcmVudCA9IHJlZlRoLnRoUGFyZW50O1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgLy8gUGVyIG9nbmkgZ3J1cHBvIHNyb3RvbG8gaWwgcGFyZW50IG5lbGxhIG1hdHJpY2UgZGVpIHJhZ2dydXBwYW1lbnRpXHJcbiAgICAgICAgICAgIGZvciAobGV0IGwgPSAwOyBsIDwgaW5mb3MuZ3JvdXBpbmdMZXZlbDsgbCsrKSB7XHJcbiAgICAgICAgICAgICAgICBsZXQgcGFyZW50ID0gcmVmVGgudGhQYXJlbnQ7XHJcbiAgICAgICAgICAgICAgICBpZiAocGFyZW50ICYmICFyZWZUaC50aFBpbm5lZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGV4cGFuZGVkR3JvdXBzW2xdW2ldID0gcGFyZW50XHJcbiAgICAgICAgICAgICAgICAgICAgcmVmVGggPSBpbmZvcy50aHNDYWNoZVtwYXJlbnRdO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBRdWFydG8gZ2lybyBwZXIgY29tcGF0dGFybG8gbmVsbCdlbGVtZW50byBmaW5hbGUgc3UgY3VpIGJpbmRhcm1pXHJcbiAgICAgICAgY3VycmVudFBhcmVudCA9IFwiXCI7XHJcbiAgICAgICAgbGV0IGN1cnJlbnRTcGFuID0gMDtcclxuICAgICAgICB0aGlzLlRNUFJvd1RoR3JvdXBzID0gW107XHJcbiAgICAgICAgZm9yIChsZXQgbCA9IDA7IGwgPCBleHBhbmRlZEdyb3Vwcy5sZW5ndGg7IGwrKykge1xyXG4gICAgICAgICAgICBsZXQgbGV2ZWxBcnJheTogeyBTcGFuOiBudW1iZXIsIFRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+LCBQaW5uZWQ/OiBib29sZWFuLCBCb3JkZXJzPzogYm9vbGVhbiB9W10gPSBbXTtcclxuICAgICAgICAgICAgdGhpcy5UTVBSb3dUaEdyb3Vwcy5wdXNoKGxldmVsQXJyYXkpXHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5TZWxlY3Rpb24gfHwgdGhpcy5IYXNQaW5uZWRDb2x1bW5zKVxyXG4gICAgICAgICAgICAgICAgbGV2ZWxBcnJheS5wdXNoKHsgU3BhbjogMSwgVGVtcGxhdGU6IG51bGwsIFBpbm5lZCA6IHRoaXMuSGFzUGlubmVkQ29sdW1ucyB9KTtcclxuXHJcbiAgICAgICAgICAgIGZvciAobGV0IGggPSAwOyBoIDwgZXhwYW5kZWRHcm91cHNbbF0ubGVuZ3RoOyBoKyspIHtcclxuICAgICAgICAgICAgICAgIGxldCBpdGVtID0gZXhwYW5kZWRHcm91cHNbbF1baF07XHJcbiAgICAgICAgICAgICAgICBpZiAoaXRlbSA9PSBjdXJyZW50UGFyZW50KVxyXG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTcGFuKys7XHJcbiAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBpZihjdXJyZW50U3BhbiA+IDApXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsQXJyYXkucHVzaCh7IFNwYW46IGN1cnJlbnRTcGFuLCBUZW1wbGF0ZTogKGN1cnJlbnRQYXJlbnQgPyBpbmZvcy50aHNDYWNoZVtjdXJyZW50UGFyZW50XS5UZW1wbGF0ZSA6IG51bGwpLCBCb3JkZXJzOiAhIWN1cnJlbnRQYXJlbnQgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudFNwYW4gPSAxO1xyXG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRQYXJlbnQgPSBpdGVtO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBVbHRpbWEgYWdnaXVudGEgY2hlIGFsdHJpbWVudGkgbWkgcmltYXJyZWJiZSBpbiBjYWNoZVxyXG4gICAgICAgICAgICBsZXZlbEFycmF5LnB1c2goeyBTcGFuOiBjdXJyZW50U3BhbiwgVGVtcGxhdGU6IChjdXJyZW50UGFyZW50ID8gaW5mb3MudGhzQ2FjaGVbY3VycmVudFBhcmVudF0uVGVtcGxhdGUgOiBudWxsKSwgQm9yZGVyczogISFjdXJyZW50UGFyZW50IH0pO1xyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMuUmVtb3ZhbClcclxuICAgICAgICAgICAgICAgIGxldmVsQXJyYXkucHVzaCh7IFNwYW46IDEsIFRlbXBsYXRlOiBudWxsIH0pO1xyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMuRXhwb3J0IHx8IHRoaXMuSGlkZGVuQ29sdW1ucyB8fCB0aGlzLkNvbHVtbnNPcmRlcmluZyB8fCB0aGlzLkNvcm5lck1lbnVPcHRpb25zKVxyXG4gICAgICAgICAgICAgICAgbGV2ZWxBcnJheS5wdXNoKHsgU3BhbjogMSwgVGVtcGxhdGU6IG51bGwgfSk7XHJcblxyXG4gICAgICAgICAgICBjdXJyZW50U3BhbiA9IDA7XHJcbiAgICAgICAgICAgIGN1cnJlbnRQYXJlbnQgPSBcIlwiO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENhbGNvbGEgaWwgbnVtZXJvIGRpIHNhbHRpIGRhIHVuIGhlYWRlciBmb2dsaWEgYWxsJ3VsdGltbyBwYXJlbnQgZGVsbGEgY2F0ZW5hXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUganVtcHNUb0ZpbmFsUGFyZW50KHRoOiBFc1RoRGlyZWN0aXZlLCB0aHNDYWNoZTogeyBbaW5kZXg6IHN0cmluZ106IEVzVGhEaXJlY3RpdmUgfSkge1xyXG4gICAgICAgIGxldCBqdW1wcyA9IDA7IGxldCBwYXJlbnQgPSBudWxsO1xyXG4gICAgICAgIGRvIHtcclxuICAgICAgICAgICAgcGFyZW50ID0gdGgudGhQYXJlbnRcclxuICAgICAgICAgICAgaWYgKHBhcmVudClcclxuICAgICAgICAgICAgICAgIGp1bXBzKys7XHJcbiAgICAgICAgICAgIHRoID0gdGhzQ2FjaGVbcGFyZW50XTtcclxuICAgICAgICB9IHdoaWxlIChwYXJlbnQpXHJcbiAgICAgICAgcmV0dXJuIGp1bXBzO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGF0YSB1bmEgZGlyZXR0aXZhIEVzVGggcmVzdGl0dWlzY2UgbGEgbGlzdGEgZGVsbGUgYWdncmVnYXppb25pIHJpY2hpZXN0YSBwZXIgcXVlc3RhIGNvbG9ubmEgbyBpbCBncnVwcG8gY2hlIHJhcHByZXNlbnRhXHJcbiAgICAgKiBcclxuICAgICAqIEBwYXJhbSB7RXNUaERpcmVjdGl2ZX0gdGggRGlyZXR0aXZhXHJcbiAgICAgKiBcclxuICAgICAqIEByZXR1cm5zIHtHcm91cE9yQWdncmVnYXRpb25bXX0gTGlzdGEgZGVpIGdydXBwaSBvIGFnZ3JlZ2F6aW9uaSByZWxhdGl2aSBhbGxhIERpcmV0dGl2YSBwYXNzYXRhXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZ2V0R3JvdXBBZ2dyZWdhdGlvbnModGg6IEVzVGhEaXJlY3RpdmUpOiBHcm91cE9yQWdncmVnYXRpb25bXSB7XHJcbiAgICAgICAgbGV0IHJldCA9IFtdO1xyXG4gICAgICAgIC8vIEVzOiAne21pbjpkZC9NTS95eXl5fSAtIHttYXg6ZGQvTU0veXl5eX0nXHJcbiAgICAgICAgaWYgKHRoLnRoQWdncmVnYXRpb24pIHtcclxuICAgICAgICAgICAgdGhpcy5nZXRFc1RoRGlyZWN0aXZlTGlzdE9mQWdncmVnYXRpb25zKHRoKS5mb3JFYWNoKChhZ2c6IFRoQWdncmVnYXRpb24pID0+IHtcclxuICAgICAgICAgICAgICAgIGxldCBpc2RhdGUgPSBhZ2cuZm9ybWF0ICYmIFsnc21hbGwnLCAnbG9uZycsICd2ZXJ5bG9uZyddLmluY2x1ZGVzKGFnZy5mb3JtYXQpO1xyXG4gICAgICAgICAgICAgICAgbGV0IGlzbnVtYmVyID0gYWdnLmZvcm1hdCAmJiBhZ2cuZm9ybWF0LnN0YXJ0c1dpdGgoXCJGXCIpICYmICFOdW1iZXIuaXNOYU4oYWdnLmZvcm1hdC5jaGFyQXQoMSkpICYmIGFnZy5mb3JtYXQubGVuZ3RoID09IDI7XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKCFpc2RhdGUgJiYgIWlzbnVtYmVyICYmIGFnZy5mb3JtYXQpXHJcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgXCJMZSBhZ2dlcmdhemlvbmkgc3VwcG9ydGF0ZSBkYWxsJ2VzLXRhYmxlIHNvbm8gc29sbyAnc21hbGwnLCAnbG9uZycsICd2ZXJ5bG9uZycgcGVyIGxlIGRhdGUgZSAnRjAtOScgcGVyIGkgbnVtZXJpXCI7XHJcblxyXG4gICAgICAgICAgICAgICAgcmV0LnB1c2gobmV3IEdyb3VwT3JBZ2dyZWdhdGlvbih0aC50aCwgYWdnLmZ1bmMsIGlzZGF0ZSA/ICdkYXRlJyA6IGlzbnVtYmVyID8gJ251bWJlcicgOiAnc3RyaW5nJykpO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAodGgudGhHcm91cClcclxuICAgICAgICAgICAgcmV0LnB1c2gobmV3IEdyb3VwT3JBZ2dyZWdhdGlvbih0aC50aCwgbnVsbCkpXHJcblxyXG4gICAgICAgIHJldHVybiByZXQ7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEYXRhIHVuYSBkaXJldHRpdmEgY29uIHVuIGZvcm1hdG8gcmVzdGl0dWlzY2UgdHV0dGUgbGUgY29wcGllIEZ1bnppb25lIGRpIEFnZ3JlZ2F6aW9uZSAtIEZvcm1hdG9cclxuICAgICAqIFxyXG4gICAgICogQHBhcmFtIHtFc1RoRGlyZWN0aXZlfSB0aCBEaXJldHRpdmEgRXNUaCBkaSBjdWkgY2FsY29sYXJlIGxlIGZ1bnppb25pIGRpIGFnZ3JlZ2F6aW9uZSB1c2F0ZVxyXG4gICAgICogXHJcbiAgICAgKiBAcmV0dXJucyB7eyBmdW5jOiBzdHJpbmcsIGZvcm1hdDogc3RyaW5nIH1bXX0gTGlzdGEgZGVsbGUgZnVuemlvbmkgZGkgYWdncmVnYXppb25lIHJpbGV2YXRlXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZ2V0RXNUaERpcmVjdGl2ZUxpc3RPZkFnZ3JlZ2F0aW9ucyh0aDogRXNUaERpcmVjdGl2ZSk6IFRoQWdncmVnYXRpb25bXSB7XHJcbiAgICAgICAgaWYgKCF0aC50aEFnZ3JlZ2F0aW9uKVxyXG4gICAgICAgICAgICByZXR1cm4gW107XHJcblxyXG4gICAgICAgIC8vIFNlIGhvIGdpw6AgZWZmZXR0dWF0byBxdWVzdG8gY2FsY29sbyBwZXIgcXVlc3RvIHRoIHJlc3RpdHVpc2NvIGxhIHZlcnNpb25lIGluIGNhY2hlXHJcbiAgICAgICAgaWYodGguX3RoQWdncmVnYXRpb25zKVxyXG4gICAgICAgICAgICByZXR1cm4gdGguX3RoQWdncmVnYXRpb25zO1xyXG5cclxuICAgICAgICBsZXQgcmV0ID0gW107XHJcbiAgICAgICAgbGV0IGRpc3BsYXkgPSB0aC50aEFnZ3JlZ2F0aW9uO1xyXG4gICAgICAgIHZhciBtYXRjaGVzID0gZGlzcGxheS5tYXRjaCgve1thLXpBLVowLTlcXC86XSp9L2dpKTtcclxuICAgICAgICBpZiAoIW1hdGNoZXMpIHJldHVybiBbXTtcclxuICAgICAgICBtYXRjaGVzLmZvckVhY2gobSA9PiB7XHJcbiAgICAgICAgICAgIGxldCBzcGxpdCA9IG0uc3BsaXQoXCI6XCIpO1xyXG4gICAgICAgICAgICBsZXQgZnVuYyA9IG0sIGZvcm1hdCA9IFwiXCI7XHJcbiAgICAgICAgICAgIGlmIChzcGxpdC5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBFc2NsdWRvIHByaW1vIGUgdWx0aW1vIGNhcmF0dGVyZSAobGUgZ3JhZmZlKVxyXG4gICAgICAgICAgICAgICAgZnVuYyA9IHNwbGl0WzBdLnN1YnN0cigxKTtcclxuICAgICAgICAgICAgICAgIGZvcm1hdCA9IHNwbGl0WzFdLnN1YnN0cigwLCBzcGxpdFsxXS5sZW5ndGggLSAxKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgcmV0LnB1c2goeyBmdW5jOiA8J21pbicgfCAnbWF4JyB8ICdzdW0nID5mdW5jLCBmb3JtYXQ6IGZvcm1hdCwgbWF0Y2g6IG0gfSk7XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHRoLl90aEFnZ3JlZ2F0aW9ucyA9IHJldDtcclxuICAgICAgICByZXR1cm4gcmV0O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTWV0b2RvIGNoZSBnZW5lcmEgbCdvcmRpbmUgZGkgZGVmYXVsdCBkZWxsZSBjb2xvbm5lXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtBcHBTZWFyY2g8YW55Pn0gdmlldyBBcHBTZWFyY2ggZGEgdXRpbGl6emFyZSBwZXIgcXVlc3RhIG9wZXJhemlvbmVcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBnZW5lcmF0ZURlZmF1bHRPcmRlcih0aHM6IEVzVGhbXSB8IEVzVGhEaXJlY3RpdmVbXSwgdmlldzogQXBwU2VhcmNoPGFueT4pIHtcclxuICAgICAgICBpZiAodGhzLmxlbmd0aCA9PSAwKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgIGxldCBvcmRlcmluZ3MgPSB0aGlzLnZpZXdNb2RlID8gdmlldy5jb2x1bW5fb3JkZXJpbmcgOiB0aGlzLmFycmF5Q29sdW1uT3JkZXJpbmc7XHJcbiAgICAgICAgLy8gR2VuZXJvIG9yZGluYW1lbnRvIGRpIGRlZmF1bHQgZGEgMCBmaW5vIGEgZG92ZSBkZXZlIGFycml2YXJlLiBTaXR1YXppb25lIGF0dHVhbGUgc2VuemEgaG90cG90YXRvXHJcbiAgICAgICAgaWYgKCFvcmRlcmluZ3MgfHwgb3JkZXJpbmdzLmxlbmd0aCA9PSAwKSB7XHJcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBsZXQgdGggPSB0aHNbaV07XHJcbiAgICAgICAgICAgICAgICBsZXQgb3JkZXIgPSB0aGlzLmlzRXNUaCh0aCkgPyB0aC5JRCA6IHRoLnRoO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5PcmRlckRpcmVjdGl2ZXMucHVzaChvcmRlcik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICB0aGlzLk9yZGVyRGlyZWN0aXZlcyA9IG9yZGVyaW5ncztcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEFwcGxpY2EgbCdvcmRpbmUgc3BlY2lmaWNhdG8gYWxsZSB2YXJpZSBjb2xvbm5lXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtBcHBTZWFyY2g8YW55Pn0gdmlldyBBcHBTZWFyY2ggZGEgdXRpbGl6emFyZSBwZXIgcXVlc3RhIG9wZXJhemlvbmVcclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gZmluYWxpemUgU2UgKip0cnVlKiogc2lnbmlmaWNhIGNoZSBub24gbWkgYXNwZXR0byBkaSBkb3ZlciBlZmZldHR1YXJlIGFsdHJlIG9wZXJhemlvbmkgZSBwb3NzbyByZW5kZXJpenphcmUgbGEgc2l0dWF6aW9uZSBpbiBiYXNlIGFpIFJvd0NvbnRleHRcclxuICAgICAqIFNlbnphIGZpbmFsaXplIHNpZ25pZmljYSBjaGUgbWkgYXNwZXR0byBhbHRyZSBvcGVyYXppb25pIGNoZSBwcmltYSBvIHBvaSByaWNoaWFtZXJhbm5vIHF1ZXN0YSBmdW56aW9uZSBjb2wgZmluYWxpemUuXHJcbiAgICAgKlxyXG4gICAgICogQWQgZXNlbXBpbywgdW5hIHZvbHRhIHNlbGV6aW9uYXRvIG9yZGluYW1lbnRvIGZpc2ljby9sb2dpY28gZGVsbGUgY29sb25uZSBzbyBjaGUgcGFydGUgdW4gYWx0cmEgcmljZXJjYSBjaGUgbWkgcml2YWxvcml6emVyw6AgZGEgXCJ3cml0ZVZhbHVlXCIsIGNoZSBnacOgIGNoaWFtYSBxdWVzdGEgZnVuemlvbmUuXHJcbiAgICAgKiBNZXR0ZW5kbyBzb2xvIGxhIGNoaWFtYXRhIGRhIFwid3JpdGVWYWx1ZVwiIGNvbWUgXCJmaW5hbGl6emFudGVcIiBtaSBhc3NpY3VybyBjaGUgc21hbmF0dGFtZW50aSBhIGZyb250ZW5kIG5vbiBjYXVzaW5vIGZsaWNrZXJpbmcgZmlubyBhIHF1YW5kbyBub24gc2Vydm9ub1xyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGFwcGx5T3JkZXJpbmcodmlldzogQXBwU2VhcmNoPGFueT4sIGZpbmFsaXplOiBib29sZWFuKSB7XHJcbiAgICAgICAgLy8gR2VuZXJvIG9yZGluYW1lbnRvIHBlciBnbGkgaGVhZGVyXHJcbiAgICAgICAgbGV0IG5ld0hlYWRlcnMgPSBbXTtcclxuXHJcbiAgICAgICAgLy8gU2UgZGV2byBmaW5hbGl6emFyZSBhZ2dhbmNpbyB0dXR0ZSBsZSB2YXJpYWJpbGkgZGkgYmluZFxyXG4gICAgICAgIGlmIChmaW5hbGl6ZSkge1xyXG4gICAgICAgICAgICB0aGlzLk9yZGVyRGlyZWN0aXZlcy5mb3JFYWNoKG8gPT4ge1xyXG4gICAgICAgICAgICAgICAgbGV0IGhlYWVkckl0ZW0gPSB0aGlzLlRNUFJvd1RIcy5maWx0ZXIodCA9PiB0LklEID09IG8pWzBdO1xyXG4gICAgICAgICAgICAgICAgbmV3SGVhZGVycy5wdXNoKGhlYWVkckl0ZW0pO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgdGhpcy5UTVBSb3dUSHMgPSBuZXdIZWFkZXJzO1xyXG5cclxuICAgICAgICAgICAgLy8gR2VuZXJvIG9yZGluYW1lbnRvIHBlciBsZSBjZWxsZVxyXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuUm93Q29udGV4dHMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgIGxldCBjb250ZXh0ID0gdGhpcy5UTVBSb3dURHNbdGhpcy5Sb3dDb250ZXh0c1tpXV07XHJcbiAgICAgICAgICAgICAgICBsZXQgbmV3Q29udGV4dCA9IFtdO1xyXG5cclxuICAgICAgICAgICAgICAgIHRoaXMuT3JkZXJEaXJlY3RpdmVzLmZvckVhY2gobyA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGNvbnRleHRJdGVtID0gY29udGV4dC5maWx0ZXIodCA9PiB0LklEID09IG8pWzBdO1xyXG4gICAgICAgICAgICAgICAgICAgIG5ld0NvbnRleHQucHVzaChjb250ZXh0SXRlbSk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgICAgICB0aGlzLlRNUFJvd1REc1t0aGlzLlJvd0NvbnRleHRzW2ldXSA9IG5ld0NvbnRleHQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0aGlzLnZpZXdNb2RlKVxyXG4gICAgICAgICAgICB2aWV3LmNvbHVtbl9vcmRlcmluZyA9IHRoaXMuT3JkZXJEaXJlY3RpdmVzO1xyXG4gICAgICAgIGVsc2VcclxuICAgICAgICAgICAgdGhpcy5hcnJheUNvbHVtbk9yZGVyaW5nID0gdGhpcy5PcmRlckRpcmVjdGl2ZXM7XHJcblxyXG4gICAgICAgIHRoaXMuY2hhbmdlZCgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vICNlbmRyZWdpb25cclxuXHJcbiAgICAvLyAjcmVnaW9uIEdlc3Rpb25lIHJhZ2dydXBwYW1lbnRpIHBlciByaWdhXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBPdHRpZW5lIHVuIGVsZW1lbnRvIGRpIHNlcGFyYXppb25lIGZyYSBHcnVwcGkgY2hlIHNlcnZlIHBlciBwYWdpbmFyZSBsZSByaWNlcmNoZSBhbGwnaW50ZXJubyBkaSBvZ25pIHNpbmdvbG8gZ3J1cHBvXHJcbiAgICAgKiBcclxuICAgICAqIEBwYXJhbSB7QXBwU2VhcmNoPGFueT59IHZpZXcgVmlldyB1dGlsaXp6YXRhIHBlciBsYSByaWNlcmNhLiBNZSBuZSBzYWx2byBpIHBhcmFtZXRyaSBuZWwgc2VwYXJhdG9yZSBhdHR1YWxlIGRhdG8gY2hlIG5lIGhvIGJpc29nbm8gcGVyIGNhcmljYXJlIGFsdHJpIGVsZW1lbnRpXHJcbiAgICAgKiBmYWNlbnRpIHJpZmVyaW1lbnRvIGFsbG8gc3Rlc3NvIGNvbnRlc3RvXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcGFyZW50IFBhcmVudCBwYXRoIGNoZSByYXBwcmVzZW50YSBhIHF1YWxlIGdydXBwbyDDqCBhZmZpYmJpYXRvIHF1ZXN0byBzZXBhcmF0b3JlXHJcbiAgICAgKiBAcGFyYW0ge0dyb3VwUm91dGVGcmFnbWVudFtdfSByb3V0ZSBSb3V0ZSBwYXRoIGNoZSByYXBwcmVzZW50YSBhIHF1YWxlIGdydXBwbyDDqCBhZmZpYmJpYXRvIHF1ZXN0byBzZXBhcmF0b3JlXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbGV2ZWwgTGl2ZWxsbyBkZWwgZ3J1cHBvIGRpIGN1aSBxdWVzdG8gZWxlbWVudG8gw6ggc2VwYXJhdG9yZSwgdmllbmUgdXNhdG8gcGVyIGFwcGxpY2FyZSBsYSBjbGFzc2UgXCJlc3QtbHZsLXt7bGV2ZWx9fVwiXHJcbiAgICAgKiBcclxuICAgICAqIEByZXR1cm5zIHthbnl9IEVsZW1lbnRvIGRpIHNlcGFyYXppb25lIGNvbnRlbmVudGUgdHV0dGkgaSBiaW5kIHBlciBwcmVzZW50YXJlIHVuYSBwYWdpbmF6aW9uZSBzb3R0byBxdWVzdG8gZ3J1cHBvIGxhdG8gaW50ZXJmYWNjaWFcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBnZXRHcm91cFNlcGFyYXRvcih2aWV3OiBBcHBTZWFyY2g8YW55PiwgcGFyZW50OiBzdHJpbmcsIHJvdXRlOiBHcm91cFJvdXRlRnJhZ21lbnRbXSwgbGV2ZWw6IG51bWJlciwgc2VhcmNoZXM6ICdncm91cHMnIHwgJ2l0ZW1zJyk6IEdyb3VwUGFnZXIge1xyXG4gICAgICAgIGxldCBpdGVtID0gbmV3IEdyb3VwUGFnZXIobGV2ZWwsIHJvdXRlLCBwYXJlbnQsIE9iamVjdC5hc3NpZ24oe30sIHZpZXcpLCBzZWFyY2hlcyk7XHJcbiAgICAgICAgaXRlbS5idXR0b25zID0gdGhpcy5nZXRQYWdlc0FycmF5KDYsIHZpZXcucGFnZSwgdmlldy5wYWdlcyk7XHJcbiAgICAgICAgdGhpcy5jYWxjdWxhdGVIYXNoKFtpdGVtXSk7XHJcbiAgICAgICAgcmV0dXJuIGl0ZW07XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTcG9zdGEgbGEgcmljZXJjYSBkaSB1bmEgcGFnaW5hIGluIGF2YW50aSAobyBpbmRpZXRybylcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gcGFnZSBOdW1lcm8gZGkgcGFnaW5lIGRhIGFnZ2l1bmdlcmUgKG8gc290dHJhcnJlLCBzZSBuZWdhdGl2bykgYWxsYSBwYWdpbmEgYXR0dWFsZVxyXG4gICAgICogQHBhcmFtIHthbnl9IHBhZ2VyIEVsZW1lbnRvIGRpIHNlcGFyYXppb25lIHN1IGN1aSDDqCBlZmZldHR1YXRhIGxhIHJpY2VyY2FcclxuICAgICAqL1xyXG4gICAgcHVibGljIGFkZFRvUGFnZUdyb3VwKHBhZ2U6IG51bWJlciwgcGFnZXI6IEdyb3VwUGFnZXIpIHtcclxuICAgICAgICB0aGlzLmdvVG9QYWdlR3JvdXAocGFnZXIudmlldy5wYWdlICsgcGFnZSwgcGFnZXIpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogU3Bvc3RhIGxhIHJpY2VyY2EgYWxsYSBwYWdpbmEgc3BlY2lmaWNhdGFcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gcGFnZSBQYWdpbmEgYSBjdWkgbmF2aWdhcmVcclxuICAgICAqIEBwYXJhbSB7YW55fSBwYWdlciBFbGVtZW50byBkaSBzZXBhcmF6aW9uZSBzdSBjdWkgw6ggZWZmZXR0dWF0YSBsYSByaWNlcmNhXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBnb1RvUGFnZUdyb3VwKHBhZ2U6IG51bWJlciwgcGFnZXI6IEdyb3VwUGFnZXIpIHtcclxuXHJcbiAgICAgICAgbGV0IGFwcFNlYXJjaEVsZW1lbnQgPSBwYWdlci52aWV3O1xyXG4gICAgICAgIGlmIChwYWdlID09PSAwIHx8IHBhZ2UgPiBhcHBTZWFyY2hFbGVtZW50LnBhZ2VzKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgIGFwcFNlYXJjaEVsZW1lbnQucGFnZSA9IHBhZ2U7XHJcbiAgICAgICAgcGFnZXIuYnV0dG9ucyA9IHRoaXMuZ2V0UGFnZXNBcnJheSg2LCBhcHBTZWFyY2hFbGVtZW50LnBhZ2UsIGFwcFNlYXJjaEVsZW1lbnQucGFnZXMpO1xyXG5cclxuICAgICAgICB0aGlzLmVtaXRTZWFyY2hSZXF1ZXN0KGZhbHNlLCBhcHBTZWFyY2hFbGVtZW50KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIERhdGEgdW5hIGNvbG9ubmEgZWZmZXR0dWEgbGEgcmllbWlzc2lvbmUgZGkgdHV0dGUgbGUgcmljZXJjaGUgcmVsYXRpdmUuXHJcbiAgICAgKiBcclxuICAgICAqIEVzLiBIbyAyIGNhbXBpIGRpIGdydXBwbyBlIGhvIGVzcGFuc28gZmlubyBhIHZlZGVyZSBpIHZhbG9yaSBmaW5vIGFkIHVuIGxpdmVsbG8gcXVhbHNpYXNpLlxyXG4gICAgICogQ2xpY2NvIGwnb3JkaW5hbWVudG8gc3VsIHNlY29uZG8gZ3J1cHBvLlxyXG4gICAgICogVHV0dGUgbGUgcmljZXJjaGUgcmVsYXRpdmUgYWkgcHJpbWkgZ3J1cHBpIGRldm9ubyBlc3NlcmUgcmllc2VndWl0ZS4gUXVhbmRvIGkgcmlzdWx0YXRpIGFycml2ZXJhbm5vIGNpIHBlbnNlcsOgIGlsIG1ldG9kbyAqKmJpbmREaXNwbGF5VG9Mb2FkZWRJdGVtc09yR3JvdXBzKipcclxuICAgICAqIGEgdGFnbGlhcmUgdmlhIGdsaSBvZ2dldHRpIG5vbiBwacO5IHZpc3VhbGl6emF0aVxyXG4gICAgICogXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gY29sdW1uIENvbG9ubmEgc3UgY3VpIHNpIMOoIGVmZmV0dHVhdGEgdW4nb3BlcmF6aW9uZSBkaSBvcmRpbmFtZW50b1xyXG4gICAgICogQHBhcmFtIHtBcHBPcmRlcmluZ1tdfSBvcmRlcmluZ3MgRGlyZXR0aXZlIGRpIG9yZGluYW1lbnRvIGRhIGFwcGxpY2FyZSBhbGxlIHZhcmllIHNvdHRvcmljZXJjaGVcclxuICAgICAqIFxyXG4gICAgICogQHRvZG86IFRlc3RhcmVcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBlbWl0Um93R3JvdXBpbmdTZWFyY2hlcyhjb2x1bW46IHN0cmluZywgb3JkZXJpbmdzOiBBcHBPcmRlcmluZ1tdKSB7XHJcbiAgICAgICAgLy8gUGVyIHR1dHRlIGxlIHJpY2VyY2hlIGludGVybWVkaWUgY2hlIGRldm8gcml2YWx1dGFyZSBsZSByZS1lbWl0dG8gaW4gbW9kbyBkYSBhZ2dpb3JuYXJnbGkgaSBkYXRpXHJcbiAgICAgICAgdmFyIG1lYW5pbmdmdWxBcHBTZWFyY2hlcyA9IHRoaXMuZ3JvdXBTZWFyY2hSZXF1ZXN0c0NhY2hlLmZpbHRlcih0ID0+IHQuZ3JvdXBfY29sdW1uID09IGNvbHVtbikubWFwKHQgPT4gdC52aWV3KTtcclxuXHJcbiAgICAgICAgLy8gU2Ugbm9uIG5lIHRyb3ZvIHNpZ25pZmljYSBjaGUgaG8gZmF0dG8gbCdvcmRpbmFtZW50byBvIHN1Z2xpIGl0ZW0sIG8gc3UgY29sb25uZSByZWxhdGl2ZSBhIHVuIHNvdHRvZ3J1cHBvIG5vbiBjYXJpY2F0b1xyXG4gICAgICAgIGlmKCFtZWFuaW5nZnVsQXBwU2VhcmNoZXMgfHwgbWVhbmluZ2Z1bEFwcFNlYXJjaGVzLmxlbmd0aCA9PSAwKVxyXG4gICAgICAgICAgICBtZWFuaW5nZnVsQXBwU2VhcmNoZXMgPSB0aGlzLmdyb3VwU2VhcmNoUmVxdWVzdHNDYWNoZS5maWx0ZXIodCA9PiAhdC5ncm91cF9jb2x1bW4pLm1hcCh0ID0+IHQudmlldyk7XHJcblxyXG4gICAgICAgIC8vIFNlIG5vbiBuZSB0cm92byBxdWkgc2lnbmlmaWNhIGNoZSBzdG8gb3JkaW5hbmRvIHN1IGNvbG9ubmUgcmVsYXRpdmUgYSB1biBzb3R0b2dydXBwbyBub24gY2FyaWNhdG9cclxuICAgICAgICBpZighbWVhbmluZ2Z1bEFwcFNlYXJjaGVzIHx8IG1lYW5pbmdmdWxBcHBTZWFyY2hlcy5sZW5ndGggPT0gMClcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICBtZWFuaW5nZnVsQXBwU2VhcmNoZXMuZm9yRWFjaChhcyA9PiB7XHJcbiAgICAgICAgICAgIC8vIE92dmlhbWVudGUgZ2xpIG9yaWRuYW1lbnRpIGRldm9ubyBlc3NlcmUgcXVlbGxpIGFwcGVuYSBnZW5lcmF0aVxyXG4gICAgICAgICAgICBhcy5vcmRlcnMgPSBvcmRlcmluZ3M7XHJcbiAgICAgICAgICAgIGFzLnNhdmVkc3RhdGUgPSB0cnVlO1xyXG4gICAgICAgICAgICB0aGlzLmVtaXRTZWFyY2hSZXF1ZXN0KGZhbHNlLCBhcyk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBIZWxwZXIgY2hlIGNhbGNvbGEgaWwgY29udGVudXRvIGRpIHVuYSBjZWxsYSByZWxhdGl2YSBhIHVuIGdydXBwbyByaWdhLCB0ZW5lbmRvIGNvbnRvIGRlbCBmb3JtYXRvIGRlbGxlIGV2ZW50dWFsaSBhZ2dyZWdhemlvbmlcclxuICAgICAqIFxyXG4gICAgICogQHBhcmFtIHtHcm91cH0gZ3JwIEdydXBwbyBkaSBjdWkgbW9zdHJhcmUgbGUgY2VsbGVcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBjZWxsIENlbGxhIGF0dHVhbGUgZGkgY3VpIGNhbGNvbGFyZSBpbCB0ZXN0b1xyXG4gICAgICogQHBhcmFtIHtFc1RoRGlyZWN0aXZlfSBoZWFkZXIgSGVhZGVyIHJlbGF0aXZvIGFsbGEgY2VsbGEgYXR0dWFsZSwgdXRpbGl6emF0YSBwZXIgaWRlbnRpZmljYXJlIGxlIGluZm9ybWF6aW9uaSBkaSBhZ2dyZWdhemlvbmVcclxuICAgICAqIFxyXG4gICAgICogQHJldHVybnMge3N0cmluZ30gVGVzdG8gZmluYWxlIGNhbGNvbGF0byBwZXIgbGEgKipjZWxsKiogY29ycmVudGUsIGluIGJhc2UgYWxsZSBhZ2dyZWdhemlvbmkgZGkgKipoZWFkZXIqKlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGdldEdyb3VwQ2VsbERpc3BsYXkoZ3JwOiBHcm91cCwgY2VsbDogc3RyaW5nLCBoZWFkZXI6IEVzVGhEaXJlY3RpdmUpOiBzdHJpbmcge1xyXG4gICAgICAgIGlmICgoPGFueT5ncnApLl9zZXApXHJcbiAgICAgICAgICAgIHJldHVybiBcIlwiO1xyXG4gICAgICAgIGxldCBkaXNwbGF5ID0gaGVhZGVyLnRoQWdncmVnYXRpb247XHJcbiAgICAgICAgaWYgKGdycC5jb2x1bW4gPT0gY2VsbCkge1xyXG4gICAgICAgICAgICBsZXQgZ3JvdXBzUGFydCA9ICg8YW55PmdycCkuX2dyb3Vwc2NvdW50ID8gXCIgLSBcIiArICg8YW55PmdycCkuX2dyb3Vwc2NvdW50ICsgXCIgXCIgKyB0aGlzLmxjLmxvYyhcIkdyb3Vwc1wiKSA6IFwiXCI7XHJcbiAgICAgICAgICAgIHJldHVybiBncnAudmFsdWUgKyBcIiAoXCIgKyBncnAuY291bnQgKyBncm91cHNQYXJ0ICsgXCIpXCI7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2Uge1xyXG5cclxuICAgICAgICAgICAgbGV0IGFnZyA9ICg8TWFwPHN0cmluZywgTWFwPHN0cmluZywgc3RyaW5nPj4+KDxhbnk+Z3JwKS5fYWdncmVnYXRpb25zQ2FjaGUpLmdldChjZWxsKTtcclxuICAgICAgICAgICAgaWYgKCFhZ2cpIHJldHVybiBcIlwiO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5nZXRFc1RoRGlyZWN0aXZlTGlzdE9mQWdncmVnYXRpb25zKGhlYWRlcikuZm9yRWFjaCgoaXRtOiBUaEFnZ3JlZ2F0aW9uKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBkaXNwbGF5ID0gZGlzcGxheS5yZXBsYWNlKGl0bS5tYXRjaCwgdGhpcy5mb3JtYXRBZ2dyZWdhdGlvblZhbHVlKGFnZy5nZXQoaXRtLmZ1bmMpLCBpdG0uZm9ybWF0KSlcclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICByZXR1cm4gZGlzcGxheTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXN0aXNjZSBpIGNsaWNrIHN1bGxhIHRhYmVsbGEgc29sbyBwZXIgbGUgcmlnaGUgYSBncnVwcG8uIFxyXG4gICAgICogTyByaW11b3ZlIGdsaSBlbGVtZW50aSBhdHR1YWxtZW50ZSBwcmVzZW50aSBvIGNhcmljYSBpbCBjb250ZW51dG8gZGVsIGdydXBwb1xyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7YW55fSBncm91cCBHcnVwcG8gYmluZGF0byBzdSBjdWkgc2kgw6ggZWZmZXR0dWF0byBpbCBjbGlja1xyXG4gICAgICpcclxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSAqKnRydWUqKiBzZSBsJ29wZXJhaXpvbmUgw6ggYW5kYXRhIGEgYnVvbiBmaW5lLCAqKmZhbHNlKiogYWx0cmltZW50aVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgaGFuZGxlR3JvdXBDbGljayhncm91cDogR3JvdXApOiBib29sZWFuIHtcclxuICAgICAgICBsZXQgY2FzdGVkID0gdGhpcy5WaWV3IGFzIEFwcFNlYXJjaDxhbnk+O1xyXG4gICAgICAgIGxldCBhbnlHID0gKDxhbnk+Z3JvdXApO1xyXG4gICAgICAgIGFueUcuX2V4cGFuZGVkID0gIWFueUcuX2V4cGFuZGVkXHJcblxyXG4gICAgICAgIC8vIFNvbm8gaW4gbW9kYWxpdMOgIHJhZ2dydXBwYW1lbnRvIHZpcnR1YWxlIGRhIGFycmF5OiBFc3BhbmRlcmUgc2lnbmlmaWNhIHJlbmRlcmUgdmlzaWJpbGkgdHV0dGkgZ2xpIG9nZ2V0dGkgcmVsYXRpdmkgYSBxdWVzdG8gZ3J1cHBvLCB2aWNldmVyc2EgaWwgY29udHJhcnJlXHJcbiAgICAgICAgaWYgKHRoaXMuQXJyYXlHcm91cGluZykge1xyXG4gICAgICAgICAgICBsZXQgYWxsUmVsYXRpdmVzID0gdGhpcy5ib3VuZFNvdXJjZS5maWx0ZXIodCA9PiBcclxuICAgICAgICAgICAgICAgICh0Ll9ncm91cCAmJiAoKGFueUcuX2V4cGFuZGVkICYmIHQuX3BhcmVudCA9PSBhbnlHLl90aGlzS2V5KSB8fCAoIWFueUcuX2V4cGFuZGVkICYmIHQuX3BhcmVudCAmJiB0Ll9wYXJlbnQuc3RhcnRzV2l0aChhbnlHLl90aGlzS2V5KSkpKSB8fCBcclxuICAgICAgICAgICAgICAgICh0Ll9pdGVtICYmICgoYW55Ry5fZXhwYW5kZWQgJiYgdC5fdGhpc0tleSA9PSBhbnlHLl90aGlzS2V5KSB8fCAoIWFueUcuX2V4cGFuZGVkICYmIHQuX3RoaXNLZXkuc3RhcnRzV2l0aChhbnlHLl90aGlzS2V5KSkpKSlcclxuICAgICAgICAgICAgYWxsUmVsYXRpdmVzLmZvckVhY2godCA9PiB7IHQuX3Zpc2libGUgPSBhbnlHLl9leHBhbmRlZDsgaWYodC5fZ3JvdXApIHQuX2V4cGFuZGVkID0gZmFsc2UgfSk7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChhbnlHLl9leHBhbmRlZCkge1xyXG4gICAgICAgICAgICAvLyBSZXNldHRvIGlwcFxyXG4gICAgICAgICAgICBjYXN0ZWQuaXRlbXNwZXJwYWdlb3ZlcnJpZGUgPSAxNTtcclxuICAgICAgICAgICAgaWYgKCFjYXN0ZWQucmVxdWVzdGVkZ3JvdXBzKVxyXG4gICAgICAgICAgICAgICAgY2FzdGVkLnJlcXVlc3RlZGdyb3VwcyA9IFtuZXcgR3JvdXBGaWx0ZXIoZ3JvdXAuY29sdW1uLCBncm91cC52YWx1ZSldO1xyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGxldCBsZXZlbCA9IGFueUcuX2dyb3VwbGV2ZWw7XHJcbiAgICAgICAgICAgICAgICAvLyBzZSBpbCBncnVwcG8gY2xpY2NhdG8gbm9uIGhhIHVuIGxpdmVsbG8gw6ggaWwgcHJpbW8gZ3J1cHBvLCBxdWluZGkgb3JkaW5hbWVudG8gdW5pY29cclxuICAgICAgICAgICAgICAgIC8vIGFsdHJpbWVudGkgZGV2byByaW11b3ZlcmUgdHV0dGkgaSBmaWx0cmkgc3UgbGl2ZWxsaSBzdXBlcmlvcmkgYWwgbGV2ZWwgY2xpY2NhdG8gZSBhZ2dpdW5nZXJlIGlsIGxldmVsIGNsaWNjYXRvXHJcbiAgICAgICAgICAgICAgICBpZiAoIWxldmVsKVxyXG4gICAgICAgICAgICAgICAgICAgIGNhc3RlZC5yZXF1ZXN0ZWRncm91cHMgPSBbbmV3IEdyb3VwRmlsdGVyKGdyb3VwLmNvbHVtbiwgZ3JvdXAudmFsdWUpXTtcclxuICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIGNhc3RlZC5yZXF1ZXN0ZWRncm91cHMgPSBbXTtcclxuICAgICAgICAgICAgICAgICAgICBhbnlHLl9wYXJlbnRSb3V0ZS5mb3JFYWNoKChzdGVwOiBHcm91cFJvdXRlRnJhZ21lbnQpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzdGVkLnJlcXVlc3RlZGdyb3Vwcy5wdXNoKG5ldyBHcm91cEZpbHRlcihzdGVwLmNvbHVtbiwgc3RlcC52YWx1ZSkpO1xyXG4gICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgIGNhc3RlZC5yZXF1ZXN0ZWRncm91cHMucHVzaChuZXcgR3JvdXBGaWx0ZXIoZ3JvdXAuY29sdW1uLCBncm91cC52YWx1ZSkpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICB0aGlzLmNoYW5nZWQoKTtcclxuICAgICAgICAgICAgdGhpcy5lbWl0U2VhcmNoUmVxdWVzdCh0cnVlKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgIGxldCBwYXRoID0gKGFueUcuX3BhcmVudCB8fCAnJykgKyBncm91cC52YWx1ZTtcclxuXHJcbiAgICAgICAgICAgIC8vIFNlIGhvIGNoaXVzbyB1biBncnVwcG8gbm9uIG1pIHNlcnZlIHJpZWZmZXR0dWFyZSByaWNlcmNlLCBtaSBiYXN0YSBlbGltaW5hcmUgZGFnbGkgb2dnZXR0aSBiaW5kYXRpIHR1dHRpIGdsaSBlbGVtZW50aSBzb3R0b3N0YW50aSBhIHF1ZWwgZ3J1cHBvXHJcbiAgICAgICAgICAgIHRoaXMuYm91bmRTb3VyY2UgPSB0aGlzLmJvdW5kU291cmNlLmZpbHRlcih0ID0+ICF0Ll9wYXJlbnQgfHwgIXQuX3BhcmVudC5zdGFydHNXaXRoKHBhdGgpKTtcclxuXHJcbiAgICAgICAgICAgIC8vIGRldm8gcGVyw7IgYW5jaGUgcmltdW92ZXJlIGV2ZW50dWFsaSBjYWNoZSByZWxhdGl2ZVxyXG4gICAgICAgICAgICB0aGlzLmdyb3VwU2VhcmNoUmVxdWVzdHNDYWNoZSA9IHRoaXMuZ3JvdXBTZWFyY2hSZXF1ZXN0c0NhY2hlLmZpbHRlcih0ID0+IHQucGF0aCAhPSBwYXRoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRnVuemlvbmUgY2hlIGRhdG8gdW4gdmFsb3JlIGxvIGZvcm1hdHRhIGluIGJhc2UgYWwgdGlwb1xyXG4gICAgICogXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgVmFsb3JlIGNoZSBnZW5lcmFsZW1udGUgcHXDsiBlc3NlcmUgdW5hIGRhdGEgbyB1biBudW1lcm9cclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBmcm9tYXQgRm9ybWF0byBzdSBjdWkgZm9ybWF0dGFyZSBpbCB2YWxvcmUuIFB1w7IgZXNzZXJlIGFkIGVzZW1waW8gXCJzbWFsbFwiLCBcImxvbmdcIiBcInZlcnlsb25nXCIgcGVyIGxlIGRhdGUgbyBGezAtOX0gcGVyIGkgbnVtZXJpIGRlY2ltYWxpXHJcbiAgICAgKiBcclxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFZhbG9yZSBkZWxsJ2FnZ3JlZ2F6aW9uZSBmb3JtYXR0YXRvIGNvbWUgc2kgZGV2ZVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGZvcm1hdEFnZ3JlZ2F0aW9uVmFsdWUodmFsdWU6IHN0cmluZywgZm9ybWF0Pzogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgICAgICBpZiAoIWZvcm1hdClcclxuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xyXG5cclxuICAgICAgICBsZXQgaXNOdW1iZXIgPSAhTnVtYmVyLmlzTmFOKHZhbHVlKSAmJiAoIWZvcm1hdCB8fCBmb3JtYXQuc3RhcnRzV2l0aChcIkZcIikpO1xyXG5cclxuICAgICAgICBpZiAoaXNOdW1iZXIgJiYgZm9ybWF0LnN0YXJ0c1dpdGgoXCJGXCIpICYmICFOdW1iZXIuaXNOYU4oZm9ybWF0LnN1YnN0cigxKSkpXHJcbiAgICAgICAgICAgIHJldHVybiBwYXJzZUZsb2F0KHZhbHVlKS50b0ZpeGVkKHBhcnNlSW50KGZvcm1hdC5zdWJzdHIoMSkpKTtcclxuXHJcbiAgICAgICAgbGV0IGRhdGUgPSBudWxsO1xyXG4gICAgICAgIC8vIEFsY3VuZSB2ZXJzaW9uZSBkaSBleHRlbnNpb25zIHJpc2NoaWFubyBkaSBjcmFzaGFyZSBjb24gY29zZSBub24gZGF0ZS4uLiDDqCBzdGF0byByaXNvbHRvIGRvcG8gcXVpbmRpIHF1ZXN0byB0cnkgLSBjYXRjaCBpbiByZWFsdMOgXHJcbiAgICAgICAgLy8gdG9ybmEgdXRpbGUgc29sbyBjb24gdmVyc2lvbmkgdmVjY2hpZS9kZXByZWNhdGUgZGVsbGEgbGlicmVyaWEgQGVzZmFlbnphL2V4dGVuc2lvbnNcclxuICAgICAgICB0cnkgeyBkYXRlID0gdGhpcy5kYXRlRXh0cy5nZXREYXRlQ29udmVydGlvbih2YWx1ZSk7IH0gY2F0Y2ggeyB9XHJcblxyXG4gICAgICAgIGlmIChkYXRlKVxyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kYXRlRXh0cy5nZXRGb3JtYXR0ZWQoZGF0ZSwgZm9ybWF0ID09ICdzbWFsbCcsIGZvcm1hdCA9PSAndmVyeWxvbmcnKTtcclxuXHJcbiAgICAgICAgLy8gUXVpIGNpIGZpbmlzY28gc2lhIHBlciBpbnB1dCBjaGUgbm9uIHNvbm8gbsOpIGRhdGUgbsOpIG51bWVyaSwgc2lhIHBlciBmb3JtYXRpIG5vbiByaWNvbm9zY2l1dGlcclxuICAgICAgICByZXR1cm4gdmFsdWU7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gI2VuZHJlZ2lvblxyXG5cclxuICAgIC8vICNyZWdpb24gR2VzdGlvbmUgT3BlcmFpem9uaSBkaWFsb2cgb3JkaW5hbWVudG8vdmlzaWJpbGl0w6AgY29sb25uZVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQWxsJ2ludGVybm8gZGVsbGEgZGlhbG9nIFwiT3JkaW5hbWVudG8gZSBWaXNpYmlsaXTDoCBDb2xvbm5lXCIgbWV0dGUgbGEgY29sb25uYSBzcGVjaWZpY2F0YSBwcmltYSBkZWxsYSBjb2xvbm5hIHByZWNlZGVudGVcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge0VzVGFibGVDb2x1bW59IGNvbHVtbkl0ZW0gQ29sb25uYSBkYSBzcG9zdGFyZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc2VuZFVwKGNvbHVtbkl0ZW06IEVzVGFibGVDb2x1bW4pIHtcclxuICAgICAgICBsZXQgaXRlbUluZGV4ID0gdGhpcy5UTVBDb2x1bW5zTGlzdC5pbmRleE9mKGNvbHVtbkl0ZW0pO1xyXG4gICAgICAgIGlmICh0aGlzLlRNUENvbHVtbnNMaXN0W2l0ZW1JbmRleCAtIDFdLmZpeGVkIHx8IHRoaXMuVE1QQ29sdW1uc0xpc3RbaXRlbUluZGV4IC0gMV0ucGlubmVkKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgdGhpcy51dGlFeHRzLnN3YXAodGhpcy5UTVBDb2x1bW5zTGlzdCwgaXRlbUluZGV4LCBpdGVtSW5kZXggLSAxKTtcclxuXHJcbiAgICAgICAgLy8gTm9uIHBvc3NvIGZhcmUgSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeSh0aGlzLkNvbHVtbnNMaXN0KSkgcGVyY2jDqSBjb250aWVuZSByaWZlcmltZW50aSBhIFRlbXBsYXRlUmVmXHJcbiAgICAgICAgbGV0IHRtcCA9IFtdO1xyXG4gICAgICAgIHRoaXMuVE1QQ29sdW1uc0xpc3QuZm9yRWFjaChjID0+IHsgdG1wLnB1c2goT2JqZWN0LmFzc2lnbih7fSwgYykpOyB9KTtcclxuICAgICAgICB0aGlzLlRNUENvbHVtbnNMaXN0ID0gdG1wO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQWxsJ2ludGVybm8gZGVsbGEgZGlhbG9nIFwiT3JkaW5hbWVudG8gZSBWaXNpYmlsaXTDoCBDb2xvbm5lXCIgbWV0dGUgbGEgY29sb25uYSBzcGVjaWZpY2F0YSBkb3BvIGxhIGNvbG9ubmEgc3VjY2Vzc2l2YVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7RXNUYWJsZUNvbHVtbn0gY29sdW1uSXRlbSBDb2xvbm5hIGRhIHNwb3N0YXJlXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzZW5kRG93bihjb2x1bW5JdGVtOiBFc1RhYmxlQ29sdW1uKSB7XHJcbiAgICAgICAgbGV0IGl0ZW1JbmRleCA9IHRoaXMuVE1QQ29sdW1uc0xpc3QuaW5kZXhPZihjb2x1bW5JdGVtKTtcclxuICAgICAgICB0aGlzLnV0aUV4dHMuc3dhcCh0aGlzLlRNUENvbHVtbnNMaXN0LCBpdGVtSW5kZXgsIGl0ZW1JbmRleCArIDEpO1xyXG5cclxuICAgICAgICAvLyBOb24gcG9zc28gZmFyZSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KHRoaXMuQ29sdW1uc0xpc3QpKSBwZXJjaMOpIGNvbnRpZW5lIHJpZmVyaW1lbnRpIGEgVGVtcGxhdGVSZWZcclxuICAgICAgICBsZXQgdG1wID0gW107XHJcbiAgICAgICAgdGhpcy5UTVBDb2x1bW5zTGlzdC5mb3JFYWNoKGMgPT4geyB0bXAucHVzaChPYmplY3QuYXNzaWduKHt9LCBjKSk7IH0pO1xyXG4gICAgICAgIHRoaXMuVE1QQ29sdW1uc0xpc3QgPSB0bXA7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBBbGwnaW50ZXJubyBkZWxsYSBkaWFsb2cgXCJPcmRpbmFtZW50byBlIFZpc2liaWxpdMOgIENvbG9ubmVcIiBwaW5uYSBsYSBjb2xvbm5hIHNwZWNpZmljYXRhXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtFc1RhYmxlQ29sdW1ufSBjb2x1bW5JdGVtIENvbG9ubmEgZGEgc3Bvc3RhcmVcclxuICAgICAqL1xyXG4gICAgcHVibGljIHBpbk9yVW5waW5Db2x1bW4oY29sdW1uSXRlbTogRXNUYWJsZUNvbHVtbikge1xyXG4gICAgICAgIGxldCBpdGVtSW5kZXggPSB0aGlzLlRNUENvbHVtbnNMaXN0LmluZGV4T2YoY29sdW1uSXRlbSk7XHJcblxyXG4gICAgICAgIC8vIFNwb3N0byBsYSBjb2xvbm5hIGFsbGEgZmluZSBkaSB0dXR0ZSBxdWVsbGUgcGlubmF0ZS4gTGEgY29zYSBmdW56aW9uYSBpbiBlbnRyYW1iaSBzZW5zaTpcclxuICAgICAgICAvLyAxKSBTZSBzdG8gcGlubmFuZG8sIGRldm8gbWV0dGVybGEgY29tZSB1bHRpbWEgcGlubmF0YVxyXG4gICAgICAgIC8vIDIpIFNlIHN0byBzcGlubmFuZG8gZGV2byBtZXR0ZXJsYSBjb21lIHByaW1hIG5vbiBwaW5uYXRhXHJcbiAgICAgICAgLy8gQ29pbmNpZGVuemEgdnVvbGUgY2hlIGlsIHB1bnRvIDEgZSAyIHNpYW5vIGVxdWl2YWxlbnRpXHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLlRNUENvbHVtbnNMaXN0Lmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5UTVBDb2x1bW5zTGlzdFtpXS5waW5uZWQpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuYXJyYXlNb3ZlKHRoaXMuVE1QQ29sdW1uc0xpc3QsIGl0ZW1JbmRleCwgaSk7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29sdW1uSXRlbS5waW5uZWQgPSAhY29sdW1uSXRlbS5waW5uZWQ7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBBbGwnaW50ZXJubyBkZWxsYSBkaWFsb2cgXCJPcmRpbmFtZW50byBlIFZpc2liaWxpdMOgIENvbG9ubmVcIiBpbnZlcnRlIGxlIGltcG9zdGF6aW9uaSBkaSB2aXNpYmlsaXTDoCBkZWxsYSBjb2xvbm5hXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtFc1RhYmxlQ29sdW1ufSBjb2x1bW5JdGVtIENvbG9ubmEgZGEgc3Bvc3RhcmVcclxuICAgICAqL1xyXG4gICAgcHVibGljIGNvbHVtbkNsaWNrZWQoaXRlbTogRXNUYWJsZUNvbHVtbikge1xyXG4gICAgICAgIHRoaXMubGFzdFNlbGVjdGVkSXRlbUlEID0gaXRlbS5pZDtcclxuICAgICAgICBpZiAoIXRoaXMuSGlkZGVuQ29sdW1ucyB8fCBpdGVtLmZpeGVkKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgIGl0ZW0udmlzaWJsZSA9ICFpdGVtLnZpc2libGU7XHJcbiAgICAgICAgdGhpcy51cGRhdGVHbG9iYWxDb2xWaXNDaGVjaygpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQWxsJ2FwZXJ0dXJhIGRlbGxhIGRpYWxvZyBcIk9yZGluYW1lbnRvIGUgVmlzaWJpbGl0w6AgQ29sb25uZVwiIHJpY2FyaWNhIGxlIGluZm9ybWF6aW9uaSBhdHR1YWxpIHBlciBwZXJtZXR0ZXJlIGxhIG1vZGlmaWNhXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyByZXNldENvbHVtblZpc1NlbGVjdGlvbigpIHtcclxuICAgICAgICB0aGlzLlRNUENvbHVtbnNMaXN0ID0gW107XHJcbiAgICAgICAgLy8gTm9uIHBvc3NvIGZhcmUgSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeSh0aGlzLkNvbHVtbnNMaXN0KSkgcGVyY2jDqSBjb250aWVuZSByaWZlcmltZW50aSBhIFRlbXBsYXRlUmVmXHJcblxyXG4gICAgICAgIHRoaXMuVE1QQ29sdW1uc0xpc3QgPSBbXTtcclxuICAgICAgICB0aGlzLkNvbHVtbnNMaXN0LmZvckVhY2goYyA9PiB7IHRoaXMuVE1QQ29sdW1uc0xpc3QucHVzaChPYmplY3QuYXNzaWduKHt9LCBjKSk7IH0pO1xyXG5cclxuICAgICAgICBsZXQgcmVvcmRlcmVkQ29sTGlzdCA9IFtdO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5Db2x1bW5zT3JkZXJpbmcpIHtcclxuICAgICAgICAgICAgdGhpcy5PcmRlckRpcmVjdGl2ZXMuZm9yRWFjaChvID0+IHtcclxuICAgICAgICAgICAgICAgIGxldCBjb2x1bW4gPSB0aGlzLlRNUENvbHVtbnNMaXN0LmZpbHRlcih0ID0+IHQuaWQgPT0gbylbMF07XHJcbiAgICAgICAgICAgICAgICAvLyBQb3RyZWkgbm9uIGF2ZXJuZSBuZWwgY2FzbyBjaSBzaWEgaWwgZmxhZyBIaWRkZW5Db2x1bW5zIGEgZmFsc2UsIGV2aXRvIGRpIGluc2VyaXJlIGRlZ2xpIHVuZGVmaW5lZFxyXG4gICAgICAgICAgICAgICAgaWYgKGNvbHVtbilcclxuICAgICAgICAgICAgICAgICAgICByZW9yZGVyZWRDb2xMaXN0LnB1c2goY29sdW1uKTtcclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICB0aGlzLlRNUENvbHVtbnNMaXN0ID0gcmVvcmRlcmVkQ29sTGlzdDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMudXBkYXRlR2xvYmFsQ29sVmlzQ2hlY2soKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJpYWdnaW9ybmEgbGUgKipPcmRlckRpcmVjdGl2ZXMqKiBjb24gbGUgaW5mb3JtYXppb25pIGluICAqKkNvbHVtbnNMaXN0KipcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSByZWZyZXNoQ29sdW1uT3JkZXJpbmcoKSB7XHJcbiAgICAgICAgdGhpcy5PcmRlckRpcmVjdGl2ZXMgPSBbXTtcclxuXHJcbiAgICAgICAgZm9yIChsZXQgYyA9IDA7IGMgPCB0aGlzLkNvbHVtbnNMaXN0Lmxlbmd0aDsgYysrKVxyXG4gICAgICAgICAgICB0aGlzLk9yZGVyRGlyZWN0aXZlcy5wdXNoKHRoaXMuQ29sdW1uc0xpc3RbY10uaWQpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRWZmZXR0dWEgbGEgc2VsZXppb25lIG8gbWVubyBkZWwgY2hlY2sgZ2xvYmFsZSAoKipnbG9iYWxDb2xWaXNDaGVjayoqKSBkaSB2aXNpYmlsaXTDoCBpbiBiYXNlIGEgc2UgdHV0dGUgbGUgKipUTVBDb2x1bW5zTGlzdCoqIHNvbm8gdmlzaWJpbGkgbyBub1xyXG4gICAgICovXHJcbiAgICBwdWJsaWMgdXBkYXRlR2xvYmFsQ29sVmlzQ2hlY2soKSB7XHJcbiAgICAgICAgLy8gVE1QQ29sTGlzdCB2aWVuZSByaWVtcGl0YSBkaSB1bmRlZmluZWQgbmVsIGNhc28gaW4gY3VpIHNpYSBkaXNhdHRpdmF0YSBsYSBzZWxlemlvbmUgZGVsbGUgY29sb25uZSBuYXNjb3N0ZVxyXG4gICAgICAgIHRoaXMuZ2xvYmFsQ29sVmlzQ2hlY2sgPSB0aGlzLlRNUENvbHVtbnNMaXN0LmV2ZXJ5KHQgPT4gdC52aXNpYmxlKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEZ1bnppb25lIGNoZSBlZmZldHR1YSBsYSBjb25mZXJtYSBkZWxsYSB2aXNpYmlsaXTDoCBlIGRlbGwnb3JkaW5lIGRlbGxlIGNvbG9ubmUuXHJcbiAgICAgKlxyXG4gICAgICogUXVlc3RhIHNlbGV6aW9uZSB2aWVuZSBpbm9sdHJlIHNhbHZhdGEgbmVsbGUgcHJlZmVyZW56ZSAoKipAZXNmYWVuemEvcHJlZmVyZW5jZXMqKiksIHF1YWxvcmEgbCdJbnB1dCAqKlNhdmVQcmVmZXJlbmNlcyoqIGZvc3NlIHZhbG9yaXp6YXRvXHJcbiAgICAgKlxyXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59ICoqdHJ1ZSoqIHNlIG5vbiBjaSBzb25vIHByb2JsZW1pLCAqKmZhbHNlKiogYWx0cmltZW50aVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgY29uZmlybUNvbHVtblZpc2liaWxpdHlTZWxlY3Rpb24oKTogYm9vbGVhbiB7XHJcbiAgICAgICAgLy8gTm9uIHBlcm1ldHRvIGRpIG5vbiBzZWxlemlvbmFyZSBudWxsYVxyXG4gICAgICAgIGlmICh0aGlzLlRNUENvbHVtbnNMaXN0LmV2ZXJ5KHQgPT4gIXQudmlzaWJsZSkpXHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuXHJcbiAgICAgICAgbGV0IGNhc3RlZFZpZXcgPSB0aGlzLnZpZXdNb2RlID8gdGhpcy5WaWV3IGFzIEFwcFNlYXJjaDxhbnk+IDogbnVsbDtcclxuICAgICAgICB0aGlzLkNvbHVtbnNMaXN0ID0gW107XHJcbiAgICAgICAgdGhpcy5UTVBDb2x1bW5zTGlzdC5mb3JFYWNoKGMgPT4geyB0aGlzLkNvbHVtbnNMaXN0LnB1c2goT2JqZWN0LmFzc2lnbih7fSwgYykpOyB9KTtcclxuICAgICAgICBcclxuICAgICAgICB0aGlzLnJlZnJlc2hDb2x1bW5PcmRlcmluZygpO1xyXG4gICAgICAgIHRoaXMuYXBwbHlPcmRlcmluZyhjYXN0ZWRWaWV3LCBmYWxzZSk7XHJcblxyXG4gICAgICAgIHRoaXMucmVmcmVzaENvbHVtbnNWaXNpYmlsaXR5KG51bGwsIG51bGwsIGNhc3RlZFZpZXcpO1xyXG5cclxuICAgICAgICAvL1NhbHZvIGxlIHByZWZlcmVuY2VzIGRpIHF1ZXN0YSB2aWV3XHJcbiAgICAgICAgLy9EaSBkZWZhdWx0IHJlZ2lzdHJvIG9yZGluYW1lbnRvIGUgdmlzaWJpbGl0w6AgZGVsbGUgY29sb25uZSBuZWxsYSB2aXN0YS4gU29sbyBsZSBjb3NlIGRpIFVJXHJcbiAgICAgICAgaWYgKHRoaXMuU2F2ZVByZWZlcmVuY2VzKSB7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5uZ0NvbnRyb2wubmFtZSkge1xyXG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIk5vbiBwb3NzbyB1dGlsaXp6YXJlIGxlIHByZWZlcmVuY2Ugc2VuemEgYXZlcmUgdW4gJ25hbWUnIHBlciBsYSB0YWJlbGxhXCIpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoIXRoaXMucHJlZlNlcnZpY2UpIHtcclxuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJOb24gcG9zc28gdXRpbGl6emFyZSBsZSBwcmVmZXJlbmNlIHNlbnphIGNoZSBpbCBwYWNjaGV0dG8gQGVzZmFlbnphL3ByZWZlcmVuY2VzIHNpYSBpbnN0YWxsYXRvXCIpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBsZXQgY29sdW1ucyA9IHRoaXMuYXJyYXlNb2RlID8gdGhpcy5hcnJheUNvbHVtbnMgOiBjYXN0ZWRWaWV3LmNvbHVtbnM7XHJcbiAgICAgICAgICAgIGxldCBjb2x1bW5zT3JkZXJpbmdzID0gdGhpcy5hcnJheU1vZGUgPyB0aGlzLmFycmF5Q29sdW1uT3JkZXJpbmcgOiBjYXN0ZWRWaWV3LmNvbHVtbl9vcmRlcmluZztcclxuICAgICAgICAgICAgdmFyIHRvU3RvcmUgPSB7IGNvbHVtbnM6IDxzdHJpbmdbXT5KU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGNvbHVtbnMpKSwgY29sdW1uX29yZGVyaW5nOiA8c3RyaW5nW10+SlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShjb2x1bW5zT3JkZXJpbmdzKSkgfTtcclxuICAgICAgICAgICAgdGhpcy5wcmVmU2VydmljZS5zdG9yZSg8c3RyaW5nPnRoaXMubmdDb250cm9sLm5hbWUsIHRvU3RvcmUpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gUmllc2VndW8gbCd1bHRpbWEgcmljZXJjYSBiaW5kYXRhIGFsbGEgdGFiZWxsYVxyXG4gICAgICAgIC8vIE1pIGFzc2ljdXJvIGRpIGZhcmxvIGRvcG8gbCdlc3BhbnNpb25lIGRlbCBjaGFuZ2VkIG8gcmlzY2hpbyBjaGUgbGEgcmljZXJjYSBtaSByaWRpYSBjb2xvbm5lIGNoZSBpbiByZWFsdMOgIG5vbiBlc2lzdG9ub1xyXG4gICAgICAgIGlmICh0aGlzLnZpZXdNb2RlKVxyXG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHsgdGhpcy5lbWl0U2VhcmNoUmVxdWVzdChmYWxzZSk7IH0pO1xyXG4gICAgICAgIGVsc2UgaWYgKHRoaXMuYXJyYXlNb2RlKVxyXG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHsgdGhpcy5pbnRlcm5hbFdyaXRlVmFsdWUoKTsgfSk7XHJcblxyXG4gICAgICAgIC8vIExvIHZvcnJlaSBtZXR0ZXJlIGxhdG8gdGVtcGxhdGUgbWEgbm9cclxuICAgICAgICB0aGlzLmxhc3RTZWxlY3RlZEl0ZW1JRCA9IG51bGw7XHJcbiAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTdWwgY2xpY2sgbmVsbGEgY2hlY2tib3ggZGkgc2VsZXppb25lIGdsb2JhbGUgc2kgc2NvcnJvbm8gdHV0dGUgbGUgY29sb25uZSBlIHNpIGltcG9zdGFubyBhbCB2YWxvcmUgZGVsbGEgY2hlY2sgZ2xvYmFsZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZ2xvYmFsQ29sVmlzQ2hlY2tDaGFuZ2VkKCkge1xyXG4gICAgICAgIHRoaXMuVE1QQ29sdW1uc0xpc3QuZm9yRWFjaCh0ID0+IHsgaWYgKCF0LmZpeGVkKSB0LnZpc2libGUgPSB0aGlzLmdsb2JhbENvbFZpc0NoZWNrOyB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvLyAjZW5kcmVnaW9uXHJcblxyXG4gICAgLy8gI3JlZ2lvbiBHZXN0aW9uZSBkYXRhIHNvdXJjZSBnZXJhcmNoaWNpXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEYXRhIHVuYSBsaXN0YSBkaSBvZ2dldHRpIGFzc2Vnbm8gaWwgbGl2ZWxsbyBnZXJhcmNoaWNvIHJpc3BldHRvIGFsbGEgbGlzdGEgZGkgb2dnZXR0aSBwYXNzYXRhXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHthbnlbXX0gb2JqcyBMaXN0YSBkaSBvZ2dldHRpIGEgY3VpIGFnZ2l1bmdlcmUgbCdpbmZvcm1hemlvbmUgZGVsIGxpdmVsbG8gZ2VyYXJjaGljb1xyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGFzc2lnbkhpZXJhcmNoeUxldmVscyhvYmpzOiBhbnlbXSkge1xyXG4gICAgICAgIC8vIENhc2lzdGljYSBpbnB1dCBudWxsb1xyXG4gICAgICAgIGlmICghb2JqcyB8fCAhb2Jqcy5sZW5ndGgpXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgLy9TZSBtYW5jYW5vIGVudHJhbWJlIGxlIGluZm8gbGUgY2VyY28gZGkgdmFsb3JpenphcmUgaW4gYXV0b21hdGljbyBjb2kgZGVmYXVsdCBcInBhcmVudGlkXCIgZSBcImlkXCIgKHBvc3RvIGNoZSBsZSBwcm9wcyBlc2lzdGFubyBuZWxsJ29nZ2V0dG8pXHJcbiAgICAgICAgaWYgKCF0aGlzLlBhcmVudEtleSAmJiAhdGhpcy5Pd25LZXkpIHtcclxuICAgICAgICAgICAgaWYgKG9ianNbMF1bJ3BhcmVudGlkJ10gIT09IHVuZGVmaW5lZClcclxuICAgICAgICAgICAgICAgIHRoaXMuUGFyZW50S2V5ID0gJ3BhcmVudGlkJztcclxuICAgICAgICAgICAgaWYgKG9ianNbMF1bJ2lkJ10gIT09IHVuZGVmaW5lZClcclxuICAgICAgICAgICAgICAgIHRoaXMuT3duS2V5ID0gJ2lkJztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vQ2hlY2sgZmluYWxlIHBlciBhc3NpY3VyYXJtaSBjaGUgbGUgcHJvcHMgY2kgc2lhbm9cclxuICAgICAgICBpZiAoIXRoaXMuUGFyZW50S2V5IHx8ICF0aGlzLk93bktleSkge1xyXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdQZXIgdXRpbGl6emFyZSBpbCBzaXN0ZW1hIGluIG1vZGFsaXTDoCBnZXJhcmNoaWNhIMOoIG9iYmxpZ2F0b3JpbyBzcGVjaWZpY2FyZSBzaWEgUGFyZW50S2V5IGNoZSBPd25LZXkuIEZhbGxiYWNrIGEgc2lzdGVtYSBub24gZ2VyYXJjaGljbycpO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBWYWxvcml6emF6aW9uZSBjYW1waSBsZXZlbCwgZXhwYW5kZWQsIGUgdmlzaWJsZSBwZXIgb2duaSBpdGVtXHJcbiAgICAgICAgbGV0IGN1cnJlbnRMZXZlbCA9IDE7XHJcbiAgICAgICAgbGV0IGFzc2lnbmVkID0gMDtcclxuICAgICAgICBkbyB7XHJcbiAgICAgICAgICAgIGFzc2lnbmVkID0gdGhpcy5hc3NpZ25MZXZlbChvYmpzLCBjdXJyZW50TGV2ZWwpO1xyXG4gICAgICAgICAgICBjdXJyZW50TGV2ZWwrKztcclxuICAgICAgICB9IHdoaWxlIChhc3NpZ25lZCA+IDApO1xyXG4gICAgICAgIC8vIGJ1dHRvIHN1IGxhdG8gaHRtbCBlIHBvaSBtZSBsYSBnaW9jbyBsw6AgY29uIHBhZGRpbmcgPSAyMCAqIChsZXZlbCAtIDEpIHBlciBmYXIgY2FwaXJlIGlsIGRpdmVyc28gbGl2ZWxsb1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUGVyIG9nbnVubyBkZWdsaSBvZ2dldHRpIHBhc3NhdGkgZ2xpIGFzc2VnbmEgdW4gbGl2ZWxsbyBkaSBnZXJhcmNoaWEgaW4gYmFzZSBhICoqUGFyZW50S2V5KiogZSAqKk93bktleSoqXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHthbnlbXX0gb2JqcyBPZ2dldHRpIGEgY3VpIGFzc2VnbmFyZSBpbCBsaXZlbGxvIGRpIGdlcmFyY2hpYVxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGxldmVsVG9Bc3NpZ24gTGl2ZWxsbyBjaGUgc3RhIGFzc2VnbmFuZG8gYXR0dWFsbWVudGUgcXVlc3RhIGl0ZXJhemlvbmUgKGRhdG8gY2hlIMOoIHJpY29yc2l2YSlcclxuICAgICAqXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBOdW1lcm8gZGkgb2dnZXR0aSBhIGN1aSDDqCBzdGF0byBhc3NlZ25hdG8gdW4gbGl2ZWxsbyBnZXJhcmNoaWNvXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgYXNzaWduTGV2ZWwob2JqczogYW55W10sIGxldmVsVG9Bc3NpZ246IG51bWJlcik6IG51bWJlciB7XHJcbiAgICAgICAgbGV0IGFzc2lnbmVkID0gMDtcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG9ianMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgbGV0IG9iaiA9IG9ianNbaV07XHJcblxyXG4gICAgICAgICAgICAvLyBTZSBsYSBwYXJlbnRLZXkgbm9uIMOoIHZhbG9yaXp6YXRhLCBxdWVzdG8gw6ggaWwgbGl2ZWxsbyAwICgxLi4uIHBlcmNow6kgZ2xpIDAgc29uIHBlcmNpb2xvc2kpXHJcbiAgICAgICAgICAgIGlmICghb2JqW3RoaXMuUGFyZW50S2V5XSAmJiBsZXZlbFRvQXNzaWduID09IDEpIHtcclxuICAgICAgICAgICAgICAgIG9iai5fbGV2ZWwgPSAxO1xyXG4gICAgICAgICAgICAgICAgb2JqLl92aXNpYmxlID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIG9iai5fZXhwYW5kZWQgPSB0aGlzLlN0YXJ0c0V4cGFuZGVkO1xyXG4gICAgICAgICAgICAgICAgYXNzaWduZWQrKztcclxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBQZXIgaSBsaXZlbGxpIHN1cGVyaW9yZSBhbCBwcmltb1xyXG4gICAgICAgICAgICBpZiAob2JqW3RoaXMuUGFyZW50S2V5XSAmJiBsZXZlbFRvQXNzaWduID4gMSkge1xyXG4gICAgICAgICAgICAgICAgLy8gdHJvdm8gaWwgcGFyZW50XHJcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBwID0gMDsgcCA8IG9ianMubGVuZ3RoOyBwKyspIHtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgcG9zc2libGVQYXJlbnQgPSBvYmpzW3BdO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAvLyBUcm92YXRvIGlsIHBhcmVudCBkZWxsJ2l0ZW0sIGFzc2Vnbm8gYWxsJ2l0ZW0gaWwgbGl2ZWxsbyBnaXVzdG9cclxuICAgICAgICAgICAgICAgICAgICBpZiAocG9zc2libGVQYXJlbnRbdGhpcy5Pd25LZXldID09IG9ialt0aGlzLlBhcmVudEtleV0gJiYgcG9zc2libGVQYXJlbnQuX2xldmVsID09IGxldmVsVG9Bc3NpZ24gLSAxKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iai5fbGV2ZWwgPSBsZXZlbFRvQXNzaWduO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gU28gY2hlIHF1ZXN0byBpdGVtIGhhIHVuIHBhcmVudC4gUmliYWRpc2NvIGNoZSBpbCBwYXJlbnQgw6ggZXNwYW5zbyBpbiBiYXNlIGFsbGUgaW1wb3N0YXppb25lIGUgc3Rlc3NhIGxvZ2ljYVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBwZXIgbGEgdmlzaWJpbGl0w6AgZGVsIGZpZ2xpb1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NzaWJsZVBhcmVudC5fZXhwYW5kZWQgPSB0aGlzLlN0YXJ0c0V4cGFuZGVkO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NzaWJsZVBhcmVudC5wYXJlbnQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmouX3Zpc2libGUgPSB0aGlzLlN0YXJ0c0V4cGFuZGVkO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBhc3NpZ25lZCsrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIGFzc2lnbmVkO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRnVuemlvbmUgY2hlIHBlcm1ldHRlIGRpIGVmZmV0dHVhcmUgbCdlc3BhbnNpb25lIGRpIHVuIHBhcmVudCBxdWFuZG8gbGEgdGFiZWxsYSBmdW56aW9uYSBpbiBtb2RhbGl0w6AgZ2VyYXJjaGljYVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgQ2hpYXZlIGRlbCBwYXJlbnQgZGEgZXNwYW5kZXJlXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBleHBhbmRQYXJlbnQoa2V5OiBzdHJpbmcpIHtcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuYm91bmRTb3VyY2UubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgbGV0IG9iaiA9IHRoaXMuYm91bmRTb3VyY2VbaV07XHJcblxyXG4gICAgICAgICAgICAvLyBUcm92byBpbCBwYXJlbnQgY29uIHF1ZWxsJ2lkIGUgbG8gZXNwYW5kb1xyXG4gICAgICAgICAgICBpZiAob2JqW3RoaXMuT3duS2V5XSA9PSBrZXkpIHtcclxuICAgICAgICAgICAgICAgIG9iai5fZXhwYW5kZWQgPSB0cnVlO1xyXG5cclxuICAgICAgICAgICAgICAgIGZvciAobGV0IGljID0gMDsgaWMgPCB0aGlzLmJvdW5kU291cmNlLmxlbmd0aDsgaWMrKykge1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBjaGlsZCA9IHRoaXMuYm91bmRTb3VyY2VbaWNdO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAvLyBUcm92byB0dXR0aSBpIGNoaWxkIGRpIHF1ZWwgcGFyZW50IGUgbGkgcmVuZG8gdmlzaWJpbGlcclxuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGRbdGhpcy5QYXJlbnRLZXldID09IGtleSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGQuX3Zpc2libGUgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRnVuemlvbmUgY2hlIHBlcm1ldHRlIGRpIGVmZmV0dHVhcmUgaWwgY29sbGFwc2UgZGkgdW4gcGFyZW50IHF1YW5kbyBsYSB0YWJlbGxhIGZ1bnppb25hIGluIG1vZGFsaXTDoCBnZXJhcmNoaWNhXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBDaGlhdmUgZGVsIHBhcmVudCBkYSBjb2xsYXNzYXJlXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBjb2xsYXBzZVBhcmVudChrZXk6IHN0cmluZykge1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5ib3VuZFNvdXJjZS5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgb2JqID0gdGhpcy5ib3VuZFNvdXJjZVtpXTtcclxuXHJcbiAgICAgICAgICAgIC8vIFRyb3ZvIGlsIHBhcmVudCBjb24gcXVlbGwnaWQgZSBsbyBjb2xsYXNzb1xyXG4gICAgICAgICAgICBpZiAob2JqW3RoaXMuT3duS2V5XSA9PSBrZXkpIHtcclxuICAgICAgICAgICAgICAgIG9iai5fZXhwYW5kZWQgPSBmYWxzZTtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBDb2xsYXNzby9uYXNjb25kbyB0dXR0aSBpIGNoaWxkIGRlbCBwYXJlbnRcclxuICAgICAgICAgICAgICAgIHRoaXMuY29sbGFwc2VDaGlsZE9mUGFyZW50KGtleSk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDb2xsYXNzYSByaWNvcnNpdmFtZW50ZSB0dXR0aSBpIGZpZ2xpIGRpIHVuIHBhcmVudCBpZGVudGlmaWNhdG8gZGFsbGEgKipwYXJlbnRLZXkqKlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwYXJlbnRLZXkgQ2hpYXZlIGRlbCBwYXJlbnQgZGkgY3VpIGNvbGxhc3NhcmUgaSBmaWdsaVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGNvbGxhcHNlQ2hpbGRPZlBhcmVudChwYXJlbnRLZXk6IHN0cmluZykge1xyXG4gICAgICAgIGZvciAobGV0IGljID0gMDsgaWMgPCB0aGlzLmJvdW5kU291cmNlLmxlbmd0aDsgaWMrKykge1xyXG4gICAgICAgICAgICBsZXQgY2hpbGQgPSB0aGlzLmJvdW5kU291cmNlW2ljXTtcclxuXHJcbiAgICAgICAgICAgIC8vIFRyb3ZvIHR1dHRpIGkgY2hpbGQgZGkgcXVlbCBwYXJlbnQgZSBsaSByZW5kbyBpbnZpc2liaWxpLiBTZSBpbCBjaGlsZCB0cm92YXRvIMOoIGEgc3VhIHZvbHRhIHVuIHBhcmVudCxcclxuICAgICAgICAgICAgLy8gbG8gY29sbGFzc28gZSB2YWRvIGluIHJpY29yc2lvbmUgc3VpIGZpZ2xpXHJcbiAgICAgICAgICAgIGlmIChjaGlsZFt0aGlzLlBhcmVudEtleV0gPT0gcGFyZW50S2V5ICYmICFjaGlsZC5wYXJlbnQpXHJcbiAgICAgICAgICAgICAgICBjaGlsZC5fdmlzaWJsZSA9IGZhbHNlO1xyXG4gICAgICAgICAgICBlbHNlIGlmIChjaGlsZFt0aGlzLlBhcmVudEtleV0gPT0gcGFyZW50S2V5ICYmIGNoaWxkLnBhcmVudCkge1xyXG4gICAgICAgICAgICAgICAgY2hpbGQuX2V4cGFuZGVkID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICBjaGlsZC5fdmlzaWJsZSA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jb2xsYXBzZUNoaWxkT2ZQYXJlbnQoY2hpbGRbdGhpcy5Pd25LZXldKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyAjZW5kcmVnaW9uXHJcblxyXG4gICAgLy8gI3JlZ2lvbiBHZXN0aW9uZSBTZWxlemlvbmVcclxuXHJcbiAgICAvKipcclxuICAgICAqIFZhbHV0YSBxdWFsaSBlbGVtZW50aSBkZXZvbm8gZXNzZXJlIG1hcmNhdGkgY29tZSBzZWxlemlvbmF0aSBuZWxsYSB2aXN0YSBhdHR1YWxlLiBTaSBiYXNhIHN1bGwnb2dnZXR0byAqKnNlbGVjdGlvbioqIGludGVybm8gYWxsJ0FwcFNlYXJjaFxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7YW55W119IGl0ZW1zIE9nZ2V0dGkgZGkgY3VpIHZhbHV0YXJlIGxhIHNlbGV6aW9uZVxyXG4gICAgICogQHBhcmFtIHtJdGVtc1NlbGVjdGlvbjxhbnk+fSBzZWxlY3Rpb25JdGVtIE9nZ2V0dGkgZGkgc2VsZXppb25lIGRlcml2YW50ZSBkYWxsYSB2aWV3IG8gZGFsbCdvZ2dldHRvIHBlciBBcnJheVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGV2YWx1YXRlU2VsZWN0aW9uKGl0ZW1zOiBhbnlbXSwgc2VsZWN0aW9uSXRlbTogSXRlbXNTZWxlY3Rpb248YW55Pikge1xyXG4gICAgICAgIGlmICghc2VsZWN0aW9uSXRlbSlcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICB0aGlzLmhhbmRsZVNlbGVjdGlvbkV2YWx1YXRpb24oaXRlbXMsIHNlbGVjdGlvbkl0ZW0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVmFsdXRhIHF1YWxpIGVsZW1lbnRpIGRldm9ubyBlc3NlcmUgbWFyY2F0aSBjb21lIHNlbGV6aW9uYXRpIG5lbGxhIHZpc3RhIGF0dHVhbGUuIFNpIGJhc2Egc3VsbCdvZ2dldHRvICoqYXJyYXltb2RlU2VsZWN0aW9uKiogZGVsbCdlcy10YWJsZVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7YW55W119IGFycmF5IExpc3RhIGRpIG9nZ2V0dGkgZGkgY3VpIHZhbHV0YXJlIGxhIHNlbGV6aW9uZSBpbiBtb2RhbGl0w6AgYXJyYXlcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBhcnJheU1vZGVFdmFsdWF0ZVNlbGVjdGlvbihhcnJheTogYW55W10pIHtcclxuICAgICAgICBpZiAoYXJyYXkubGVuZ3RoID09IDApXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgdGhpcy5oYW5kbGVTZWxlY3Rpb25FdmFsdWF0aW9uKGFycmF5LCB0aGlzLmFycmF5bW9kZVNlbGVjdGlvbik7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJbXBsZW1lbnRhemlvbmUgYWdub3N0aWNhIGRlbGxhIHZhbHV0YXppb25lIGRlbGxlIHNlbGV6aW9uaSBkZWdsaSBvZ2dldHRpLiBSaWNoaWVkZSBnbGkgb2dnZXR0aSBkZWxsYSB2aXN0YSBhdHR1YWxlIGUgbCdpdGVtU2VsZWN0b3JcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge2FueVtdfSBpdGVtcyBPZ2dldHRpIGRpIGN1aSBhZ2dpb3JuYXJlIGxvIHN0YXRvIGRpIHNlbGV6aW9uZVxyXG4gICAgICogQHBhcmFtIHtJdGVtc1NlbGVjdGlvbjxhbnk+fSBzZWxlY3Rpb25JdGVtIE9nZ2V0dG8gY29udGVuZW50ZSBsbyBzdGF0byBhdHR1YWxlIGRpIHNlbGV6aW9uZVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGhhbmRsZVNlbGVjdGlvbkV2YWx1YXRpb24oaXRlbXM6IGFueVtdLCBzZWxlY3Rpb25JdGVtOiBJdGVtc1NlbGVjdGlvbjxhbnk+KSB7XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpdGVtcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgaXRtID0gaXRlbXNbaV07XHJcbiAgICAgICAgICAgIGxldCBoYXNoID0gaXRtLl9oYXNoO1xyXG4gICAgICAgICAgICBsZXQgaXRlbUdyb3VwID0gaXRtLl9ncm91cCA/IG51bGwgOiB0aGlzLmdldEl0ZW1Hcm91cChpdG0pO1xyXG4gICAgICAgICAgICAvLyBSZWlkcmF0byBsYSBjYWNoZSBkaSBzZWxlemlvbmUgY29pIG51b3ZpIG9nZ2V0dGkgYWx0cmltZW50aSBub24gcml1c2NpcmVpIGEgYmVjY2FyZSBnbGkgaW5kaWNpIGdpdXN0aVxyXG4gICAgICAgICAgICAvLyBEb3BvZGljaMOpIGxhIHVzbyBwZXIgY2FsY29sYXJlIGlzdGFudGFuZWFtZW50ZSBzZSBnbGkgb2dnZXR0aSBzb25vIHNlbGV6aW9uYXRpIG8gbm9cclxuICAgICAgICAgICAgdGhpcy5yZWhpZHJhdGVDYWNoZShpdG0pO1xyXG5cclxuICAgICAgICAgICAgaWYgKGl0bS5faXRlbSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKHNlbGVjdGlvbkl0ZW0uYWxsKVxyXG4gICAgICAgICAgICAgICAgICAgIGl0bS5fc2VsZWN0ZWQgPSAhdGhpcy5leGNsdXNpb25zQ2FjaGUuaGFzKGhhc2gpICYmICgoIXRoaXMuZ3JvdXBzQ2FjaGUuaGFzKGl0ZW1Hcm91cD8uX2hhc2gpICYmIHRoaXMuaXRlbXNDYWNoZS5oYXMoaGFzaCkpIHx8ICF0aGlzLmdyb3VwX2V4Y2x1c2lvbnNDYWNoZS5oYXMoaXRlbUdyb3VwPy5faGFzaCkpO1xyXG4gICAgICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgICAgIGl0bS5fc2VsZWN0ZWQgPSAhdGhpcy5leGNsdXNpb25zQ2FjaGUuaGFzKGhhc2gpICYmICh0aGlzLmdyb3Vwc0NhY2hlLmhhcyhpdGVtR3JvdXA/Ll9oYXNoKSB8fCB0aGlzLml0ZW1zQ2FjaGUuaGFzKGhhc2gpIHx8ICh0aGlzLnBhcmVudFRyZWVTdGF0dXMoaXRlbUdyb3VwKSA9PSAnaW5jbHVkZWQnICYmICF0aGlzLmdyb3VwX2V4Y2x1c2lvbnNDYWNoZS5oYXMoaXRlbUdyb3VwPy5faGFzaCkpKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIGlmIChpdG0uX2dyb3VwKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoc2VsZWN0aW9uSXRlbS5hbGwpXHJcbiAgICAgICAgICAgICAgICAgICAgaXRtLl9zZWxlY3RlZCA9ICF0aGlzLmdyb3VwX2V4Y2x1c2lvbnNDYWNoZS5oYXMoaGFzaCkgJiYgdGhpcy5wYXJlbnRUcmVlU3RhdHVzKGl0bSkgIT0gJ2V4Y2x1ZGVkJztcclxuICAgICAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgICAgICBpdG0uX3NlbGVjdGVkID0gdGhpcy5ncm91cHNDYWNoZS5oYXMoaGFzaCkgfHwgKHRoaXMucGFyZW50VHJlZVN0YXR1cyhpdG0pID09ICdpbmNsdWRlZCcgJiYgIXRoaXMuZ3JvdXBfZXhjbHVzaW9uc0NhY2hlLmhhcyhoYXNoKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIFNlIHR1dHRpIGdsaSBvZ2dldHRpIGRpIHF1ZXN0YSBwYWdpbmEgc29ubyBzb2xlemlvbmF0aSBhbGxvcmEgcG9zc28gbWV0dGVyZSBpbCBnbG9iYWwgY2hlY2sgYSB0cnVlXHJcbiAgICAgICAgLy8gU2Ugc29ubyBpbiBzaXR1YXppb25lIGRpIGFsbC1zZWxlY3QgYW5jaGUgbWV0dG8gbGEgZ2xvYmFsIGNoZWNrYm94LCBub25vc3RhbnRlIGNpIHBvc3Nhbm8gZXNzZXJlIGRlbGxlIGVzY2x1c2lvbmlcclxuICAgICAgICB0aGlzLmdsb2JhbENoZWNrID0gdGhpcy5ib3VuZFNvdXJjZS5maWx0ZXIodCA9PiB0Ll9ncm91cCB8fCB0Ll9pdGVtKS5ldmVyeSh0ID0+IHQuX3NlbGVjdGVkKTtcclxuICAgICAgICB0aGlzLmNhblNlbGVjdEFsbCA9IHNlbGVjdGlvbkl0ZW0uY291bnQgPiAwICYmIHRoaXMuU2VsZWN0QWxsO1xyXG5cclxuICAgICAgICAvLyBQb3RyZWJiZSBjYW1iaWFyZSBxdWFsb3JhIHF1YWxjdW5vIGluc2VyaXNzZSBkYXRpIGEgbWFuYXp6YSBpbiBtb2RhbGl0w6AgQXJyYXkgZSBkZXNzZSBpbCByZWZyZXNoIG1hbnVhbGUgYWxsYSB0YWJlbGxhXHJcbiAgICAgICAgLy8gQ29tdW5xdWUgY29zdGEgMCBxdWluZGkgbWkgcGVybWV0dG8gZGkgcmVmcmVzaGFyZVxyXG4gICAgICAgIGlmICh0aGlzLmFycmF5TW9kZSkge1xyXG4gICAgICAgICAgICBsZXQgcHJldlNlbGVjdGVkID0gdGhpcy5zZWxlY3RlZE9iamVjdHM7XHJcbiAgICAgICAgICAgIHRoaXMuZmluYWxpemVTZWxlY3Rpb25JbmZvcm1hdGlvbnMoc2VsZWN0aW9uSXRlbSk7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLnNlbGVjdGVkT2JqZWN0cyAhPSBwcmV2U2VsZWN0ZWQpXHJcbiAgICAgICAgICAgICAgICB0aGlzLm9uU2VsZWN0aW9uQ2hhbmdlZC5lbWl0KHNlbGVjdGlvbkl0ZW0pO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIERhdG8gdW4gb2dnZXR0byB0cm92YSBsYSBjZWxsYSBkaSBjYWNoZSBpbiBjdWkgw6ggcmVnaXN0cmF0byBlIGFnZ2lvcm5hIGlsIGNvbnRlbnV0b1xyXG4gICAgICogXHJcbiAgICAgKiBAcGFyYW0ge2FueX0gaXRlbSBPZ2dldHRvIGRhIGFnZ2lvcm5hcmVcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSByZWhpZHJhdGVDYWNoZShpdGVtOiBhbnkpIHtcclxuICAgICAgICBsZXQgY3R4ID0gaXRlbS5faGFzaDtcclxuICAgICAgICBpZiAodGhpcy5pdGVtc0NhY2hlLmhhcyhjdHgpKVxyXG4gICAgICAgICAgICB0aGlzLml0ZW1zQ2FjaGUuc2V0KGN0eCwgaXRlbSk7XHJcblxyXG4gICAgICAgIGlmICh0aGlzLmdyb3VwX2V4Y2x1c2lvbnNDYWNoZS5oYXMoY3R4KSlcclxuICAgICAgICAgICAgdGhpcy5ncm91cF9leGNsdXNpb25zQ2FjaGUuc2V0KGN0eCwgaXRlbSk7XHJcblxyXG4gICAgICAgIGlmICh0aGlzLmdyb3Vwc0NhY2hlLmhhcyhjdHgpKVxyXG4gICAgICAgICAgICB0aGlzLmdyb3Vwc0NhY2hlLnNldChjdHgsIGl0ZW0pO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5leGNsdXNpb25zQ2FjaGUuaGFzKGN0eCkpXHJcbiAgICAgICAgICAgIHRoaXMuZXhjbHVzaW9uc0NhY2hlLnNldChjdHgsIGl0ZW0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGF0byB1biBncnVwcG8gY29udHJvbGxhIHJpY29yc2l2YW1lbnRlIGwnYWxiZXJvIGRpIGN1aSBmYSBwYXJ0ZSBzZSBjJ8OoIHN0YXRhIHVuYSBpbmNsdXNpb25lIG8gZXNjbHVzaW9uZSBkaXJldHRhXHJcbiAgICAgKiBcclxuICAgICAqIEBwYXJhbSB7YW55fSBncnAgR3J1cHBvIGRhIGNvbnRyb2xsYXJlXHJcbiAgICAgKiBcclxuICAgICAqIEByZXR1cm5zIHsnbm9uZScgfCAnZXhjbHVkZWQnIHwgJ2luY2x1ZGVkJ30gXHJcbiAgICAgKiAnbm9uZScgc2Ugbm9uIGNpIHNvbm8gaW5mb3JtYXppb25pIHN1IGluY2x1c2lvbmkgbyBlc2NsdXNpb25pIFxyXG4gICAgICogJ2luY2x1ZGVkJyBzZSBpbCBncnVwcG8gY29udHJvbGxhdG8gw6ggc3RhdG8gaW5jbHVzbyBpbiBtYW5pZXJhIGVzcGxpY2l0YSBkYWxsJ2FsYmVybyBkZWkgZ3J1cHBpIHBhZHJpXHJcbiAgICAgKiAnZXhjbHVkZWQnIHNlIGlsIGdydXBwbyBjb250cm9sbGF0byDDqCBzdGF0byBlc2NsdXNvIGluIG1hbmllcmEgZXNwbGljaXRhIGRhbGwnYWxiZXJvIGRlaSBncnVwcGkgcGFkcmlcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBwYXJlbnRUcmVlU3RhdHVzKGdycDogYW55KTogJ25vbmUnIHwgJ2V4Y2x1ZGVkJyB8ICdpbmNsdWRlZCcge1xyXG4gICAgICAgIGlmICghZ3JwKVxyXG4gICAgICAgICAgICByZXR1cm4gJ25vbmUnO1xyXG5cclxuICAgICAgICBsZXQgcGFyZW50R3JvdXA6IGFueSA9IHRoaXMucmdHcm91cENhY2hlLmdldChncnAuX3BhcmVudCk7XHJcblxyXG4gICAgICAgIGlmICghcGFyZW50R3JvdXApXHJcbiAgICAgICAgICAgIHJldHVybiAnbm9uZSc7XHJcblxyXG4gICAgICAgIGlmICh0aGlzLmdyb3VwX2V4Y2x1c2lvbnNDYWNoZS5oYXMocGFyZW50R3JvdXAuX2hhc2gpKVxyXG4gICAgICAgICAgICByZXR1cm4gJ2V4Y2x1ZGVkJztcclxuXHJcbiAgICAgICAgaWYgKHRoaXMuZ3JvdXBzQ2FjaGUuaGFzKHBhcmVudEdyb3VwLl9oYXNoKSlcclxuICAgICAgICAgICAgcmV0dXJuICdpbmNsdWRlZCc7XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzLnBhcmVudFRyZWVTdGF0dXMocGFyZW50R3JvdXApO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2VzdGlzY2UgbGEgc2VsZXppb25lIGdsb2JhbGUgZGVnbGkgb2dnZXR0aSwgc2lhIHBlciBwYWdpbmEgY2hlIGEgbGl2ZWxsbyBkaSAqKlNlbGVjdEFsbCoqXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtib29sZWFufSBmb3JjZWRWYWwgVmFsb3JlIGZvcnphdG8gZGkgY2hlY2sgZGEgYXNzZWduYXJlIGFnbGkgb2dnZXR0aVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZ2xvYmFsQ2hlY2tDaGFuZ2VkKGZvcmNlZFZhbDogYm9vbGVhbiA9IG51bGwpIHtcclxuXHJcbiAgICAgICAgLy8gUHJlbmRvIHR1dHRpIGdsaSBlbGVtZW50aSBwcmVzZW50aSBpbiBxdWVzdGEgdmlzdGEuIFNlIGhvIGdydXBwaSBwcmVuZG8gc29sbyBpIGdydXBwaSBhIGxpdmVsbG8gMCwgYWx0cmltZW50aSBwcmVuZG8gdHV0dGkgZ2xpIG9nZ2V0dGkgcGVyIHNlbGV6aW9uYXJsaVxyXG4gICAgICAgIGxldCBpdGVtcyA9IHRoaXMuYm91bmRTb3VyY2UuZmluZCh0ID0+IHQuX2dyb3VwKSA/IHRoaXMuYm91bmRTb3VyY2UuZmlsdGVyKHQgPT4gdC5fZ3JvdXAgJiYgIXQuX3BhcmVudCkgOiB0aGlzLmJvdW5kU291cmNlO1xyXG4gICAgICAgIHZhciBpdGVtU2VsZWN0aW9uID0gdGhpcy5oYW5kbGVJdGVtc1NlbGVjdGlvbihpdGVtcywgZm9yY2VkVmFsLCB0aGlzLmdsb2JhbENoZWNrKTtcclxuICAgICAgICB0aGlzLmNoYW5nZWQoKTtcclxuXHJcbiAgICAgICAgdGhpcy5vblNlbGVjdGlvbkNoYW5nZWQuZW1pdChpdGVtU2VsZWN0aW9uKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEhlbHBlciBwZXIgZ2VzdGlyZSBsYSBzZWxlemlvbmUgZGkgTiBlbGVtZW50aSB1dGlsaXp6YW5kbyBsYSBDYWNoZSBkaSBzZWxlemlvbmUgZWQgZXZlbnR1YWxtZW50ZSBhZ2dpb3JuYW5kbyBpbCBjb25jZXR0byBkaSBcImFsbCBzZWxlY3Rpb25cIlxyXG4gICAgICpcclxuICAgICAqIFZ1bnppb25hIHNpYSBpbiBtb2RhbGl0w6AgQXJyYXkgY2hlIGluIG1vZGFsaXTDoCBWaWV3IFNlbXBsaWNlIG8gVmlldyBBdmFuemF0YSAoY29uIGxlIEN1c3RvbSBDZWxscylcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge2FueVtdfSBpdGVtcyBPZ2dldHRpIGRhIHNlbGV6aW9uYXJlIG8gZGVzZWxlemlvbmFyZVxyXG4gICAgICogQHBhcmFtIHtib29sZWFufSBmb3JjZWRWYWwgVmFsb3JlIGZvcnphdG8gZGkgY2hlY2sgZGEgYXNzZWduYXJlIGFnbGkgb2dnZXR0aVxyXG4gICAgICogQHBhcmFtIHtib29sZWFufSBnbG9iYWxDaGVjayBWYWxvcmUgZGVsIGNoZWNrIGdsb2JhbGVcclxuICAgICAqXHJcbiAgICAgKiBAcmV0dXJucyB7SXRlbXNTZWxlY3Rpb248YW55Pn0gT2dnZXR0byBkaSBzZWxlemlvbmUgYWdnaW9ybmF0byBjb24gbGUgaW5mb3JtYXppb25pIHN1bGwndWx0aW1hIG9wZXJhemlvbmUgZWZmZXR0dWF0YVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgaGFuZGxlSXRlbXNTZWxlY3Rpb24oaXRlbXM6IGFueVtdLCBmb3JjZWRWYWw6IGJvb2xlYW4gPSBudWxsLCBnbG9iYWxDaGVjazogYm9vbGVhbiA9IG51bGwpOiBJdGVtc1NlbGVjdGlvbjxhbnk+IHtcclxuICAgICAgICBsZXQgc2kgPSAodGhpcy5WaWV3IGFzIEFwcFNlYXJjaDxhbnk+KT8uc2VsZWN0aW9uIHx8IHRoaXMuYXJyYXltb2RlU2VsZWN0aW9uO1xyXG5cclxuICAgICAgICAvLyBTZSBzb25vIGluIG1vZGFsaXTDoCBkaSBzZWxlemlvbmUgc2luZ29sYSBlIGRldm8gc2VsZXppb25hcmUgdW4nb2dnZXR0bywgcGVyIHByaW1hIGNvc2EgZGV2byBkZXNlbGV6aW9uYXJlIHR1dHRpIGdsaSBhbHRyaVxyXG4gICAgICAgIGlmICh0aGlzLlNpbmdsZVNlbGVjdGlvbiAmJiBpdGVtc1swXT8uX3NlbGVjdGVkICYmICFpdGVtc1swXT8uX2dyb3VwKSB7XHJcbiAgICAgICAgICAgIGlmIChpdGVtcy5sZW5ndGggPiAxICYmIGZvcmNlZFZhbCA9PSBudWxsKVxyXG4gICAgICAgICAgICAgICAgdGhyb3cgXCJUZW50YXRpdm8gZGkgc2VsZXppb25hcmUgbyBkZXNlbGV6aW9uYXJlIHBpw7kgZGkgdW4gZWxlbWVudG8gY29uIFNpbmdsZVNlbGVjdGlvbiBhdHRpdm9cIjtcclxuXHJcbiAgICAgICAgICAgIGlmIChpdGVtcy5sZW5ndGggPT0gMSAmJiBmb3JjZWRWYWwgPT0gbnVsbCl7XHJcbiAgICAgICAgICAgICAgICBzaSA9IHRoaXMuaGFuZGxlSXRlbXNTZWxlY3Rpb24odGhpcy5ib3VuZFNvdXJjZS5maWx0ZXIodCA9PiAhdC5fZ3JvdXApLCBmYWxzZSwgbnVsbCk7XHJcbiAgICAgICAgICAgICAgICBpdGVtc1swXS5fc2VsZWN0ZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGl0ZW1zLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGxldCBpdGVtID0gaXRlbXNbaV07XHJcbiAgICAgICAgICAgIGxldCB0b0NoYW5nZSA9IGZvcmNlZFZhbCAhPSBudWxsID8gaXRlbS5fc2VsZWN0ZWQgIT0gZm9yY2VkVmFsIDogZ2xvYmFsQ2hlY2sgIT0gbnVsbCA/IGl0ZW0uX3NlbGVjdGVkICE9IHRoaXMuZ2xvYmFsQ2hlY2sgOiBmYWxzZTtcclxuXHJcbiAgICAgICAgICAgIC8vIFNlIGRldidlc3NlcmUgb3ZlcnJpZGF0byBpbCB2YWxvcmUgZGkgY2hlY2sgZWZmZXR0dW8gbCdvdmVycmlkZSBvIGNvbCB2YWxvcmUgZm9yemF0byBvIGNvbCB2YWxvcmUgZ2xvYmFsZVxyXG4gICAgICAgICAgICBpZiAodG9DaGFuZ2UgJiYgIWl0ZW0ubG9ja2VkKVxyXG4gICAgICAgICAgICAgICAgaXRlbS5fc2VsZWN0ZWQgPSBmb3JjZWRWYWwgIT0gbnVsbCA/IGZvcmNlZFZhbCA6IHRoaXMuZ2xvYmFsQ2hlY2s7XHJcblxyXG4gICAgICAgICAgICAvLyBTZSBpbCB2YWxvcmUgbm9uIGRldidlc3NlcmUgdmFyaWF0byBlIHZlbmdvIGRhIHVuYSBzZWxlemlvbmUgZ2xvYmFsZSBzZW1wbGljZW1lbnRlIGV2aXRvIGRpIGVmZmV0dHVhcmUgb3BlcmFpem9uaSBpbnV0aWxpLiBMJ2l0ZW0vZ3J1cHBvIMOoIGdpw6AgbmVsbG8gc3RhdG8gZ2l1c3RvXHJcbiAgICAgICAgICAgIGlmKCF0b0NoYW5nZSAmJiBnbG9iYWxDaGVjayAhPSBudWxsKVxyXG4gICAgICAgICAgICAgICAgY29udGludWU7XHJcblxyXG4gICAgICAgICAgICBsZXQgYWxsU2VsZWN0aW9uID0gc2kuYWxsO1xyXG4gICAgICAgICAgICBsZXQgaXNHcm91cCA9IGl0ZW0uX2dyb3VwO1xyXG4gICAgICAgICAgICBsZXQgaXNTZWxlY3Rpb24gPSBpdGVtLl9zZWxlY3RlZDtcclxuICAgICAgICAgICAgbGV0IGl0ZW1Hcm91cCA9IG51bGwsIGFsbEl0ZW1zID0gbnVsbCwgc2VsZWN0ZWRJdGVtcyA9IG51bGwsIHVuc2VsZWN0ZWRJdGVtcyA9IG51bGwsIGFsbEdyb3VwcyA9IG51bGwsIHNlbGVjdGVkR3JvdXBzID0gbnVsbCwgdW5zZWxlY3RlZEdyb3VwcyA9IG51bGwsIHBhcmVudEdyb3VwU2VsZWN0ZWQgPSBudWxsLCBwYXJlbnRHcm91cFVuc2VsZWN0ZWQgPSBudWxsO1xyXG5cclxuICAgICAgICAgICAgaWYgKGlzR3JvdXApIHtcclxuICAgICAgICAgICAgICAgIGxldCBwdHMgPSB0aGlzLnBhcmVudFRyZWVTdGF0dXMoaXRlbSk7XHJcbiAgICAgICAgICAgICAgICBwYXJlbnRHcm91cFNlbGVjdGVkID0gcHRzID09ICdpbmNsdWRlZCc7XHJcbiAgICAgICAgICAgICAgICBwYXJlbnRHcm91cFVuc2VsZWN0ZWQgPSBwdHMgPT0gJ2V4Y2x1ZGVkJztcclxuICAgICAgICAgICAgICAgIGFsbEl0ZW1zID0gdGhpcy5nZXRHcm91cEl0ZW1zKHNpLCBpdGVtLCBudWxsLCB0cnVlKTtcclxuICAgICAgICAgICAgICAgIHNlbGVjdGVkSXRlbXMgPSB0aGlzLmdldEdyb3VwSXRlbXMoc2ksIGl0ZW0sICdzZWxlY3RlZCcsIHRydWUsIGFsbEl0ZW1zKTtcclxuICAgICAgICAgICAgICAgIHVuc2VsZWN0ZWRJdGVtcyA9IHRoaXMuZ2V0R3JvdXBJdGVtcyhzaSwgaXRlbSwgJ3Vuc2VsZWN0ZWQnLCB0cnVlLCBhbGxJdGVtcyk7XHJcbiAgICAgICAgICAgICAgICBhbGxHcm91cHMgPSB0aGlzLmdldEdyb3VwQ2hpbGRHcm91cHMoc2ksIGl0ZW0sIG51bGwsIHRydWUpO1xyXG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRHcm91cHMgPSB0aGlzLmdldEdyb3VwQ2hpbGRHcm91cHMoc2ksIGl0ZW0sICdzZWxlY3RlZCcsIHRydWUsIGFsbEdyb3Vwcyk7XHJcbiAgICAgICAgICAgICAgICB1bnNlbGVjdGVkR3JvdXBzID0gdGhpcy5nZXRHcm91cENoaWxkR3JvdXBzKHNpLCBpdGVtLCAndW5zZWxlY3RlZCcsIHRydWUsIGFsbEdyb3Vwcyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBpdGVtR3JvdXAgPSB0aGlzLmdldEl0ZW1Hcm91cChpdGVtKTtcclxuICAgICAgICAgICAgICAgIHBhcmVudEdyb3VwU2VsZWN0ZWQgPSBpdGVtR3JvdXAgPT0gbnVsbCA/IG51bGwgOiBpdGVtR3JvdXAuX3NlbGVjdGVkO1xyXG4gICAgICAgICAgICAgICAgcGFyZW50R3JvdXBVbnNlbGVjdGVkID0gaXRlbUdyb3VwID09IG51bGwgPyBudWxsIDogIWl0ZW1Hcm91cC5fc2VsZWN0ZWQ7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICghdGhpcy5BcnJheUdyb3VwaW5nKVxyXG4gICAgICAgICAgICAgICAgdGhpcy5wZXJmb3JtU2VsZWN0aW9uT3BlcmF0aW9ucyhzaSwgaXRlbSwgYWxsU2VsZWN0aW9uLCBpc0dyb3VwLCBpc1NlbGVjdGlvbiwgc2VsZWN0ZWRJdGVtcywgc2VsZWN0ZWRHcm91cHMsIHVuc2VsZWN0ZWRJdGVtcywgdW5zZWxlY3RlZEdyb3VwcywgYWxsSXRlbXMsIGFsbEdyb3VwcywgcGFyZW50R3JvdXBTZWxlY3RlZCwgcGFyZW50R3JvdXBVbnNlbGVjdGVkKTtcclxuICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgdGhpcy5wZXJmb3JtU2ltcGxlU2VsZWN0aW9uT3BlcmF0aW9ucyhzaSwgaXRlbSwgaXNHcm91cCwgaXNTZWxlY3Rpb24sIGl0ZW1Hcm91cCwgc2VsZWN0ZWRJdGVtcywgdW5zZWxlY3RlZEl0ZW1zLCBhbGxJdGVtcywgYWxsR3JvdXBzKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIEltcG9zdG8gaWwgY2hlY2sgZ2xvYmFsZSBpbiBiYXNlIGEgc2UgdHV0dGkgZ2xpIGVsZW1lbnRpIHNvbm8gc2VsZXppb25hdGkgbyBtZW5vLlxyXG4gICAgICAgIC8vIEV2aXRvIGRpIGZhcmUgcXVlc3RlIG9wZXJhemlvbmkgc2UgbGEgc2VsZXppb25lIGRlcml2YSBwcm9wcmlvIGRhbCBnbG9iYWwgQ2hlY2tcclxuICAgICAgICBpZiAoZ2xvYmFsQ2hlY2sgPT0gbnVsbClcclxuICAgICAgICAgICAgdGhpcy5nbG9iYWxDaGVjayA9ICF0aGlzLmJvdW5kU291cmNlLnNvbWUodCA9PiAhdC5fc2VsZWN0ZWQgJiYgIXQuX3NlcCk7XHJcblxyXG4gICAgICAgIHRoaXMuZmluYWxpemVTZWxlY3Rpb25JbmZvcm1hdGlvbnMoc2kpO1xyXG5cclxuICAgICAgICByZXR1cm4gc2k7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEYXRvIEwnb2dnZXR0byBkaSBzZWxlemlvbmUsIGwnb2dnZXR0byBkYSBzZWxlemlvbmFyZS9kZXNlbGV6aW9uYXJlIGUgdHV0dGkgaSBwYXJhbWV0cmkgZGVsIGNhc28gZWZmZXR0dWEgbGUgb3BlcmF6aW9uaSBjaGUgc2Vydm9uby5cclxuICAgICAqIFxyXG4gICAgICogTG9naWNhIHNlbXBsaWZpY2F0YSByaXNwZXR0byBhbGwnb3JpZ2luYWxlICoqcGVyZm9ybVNlbGVjdGlvbk9wZXJhdGlvbnMqKiBwZXIgbGF2b3JhcmUgaW4gdW5hIG1vZGFsaXTDoCBpbiBjdWkgdHV0dGkgZ2xpIGVsZW1lbnRpIHNvbm8gY2FyaWNhdGkgKCoqQXJyYXlHcm91cGluZyoqID0gdHJ1ZSlcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBwZXJmb3JtU2ltcGxlU2VsZWN0aW9uT3BlcmF0aW9ucyhiYXNlOiBJdGVtc1NlbGVjdGlvbjxhbnk+LCBpdGVtOiBhbnksIGdyb3VwOiBib29sZWFuLCBzZWw6IGJvb2xlYW4sIGl0bV9ncm91cDogYW55LCBzZWxfaXRtOiBhbnlbXSwgZGVzZWxfaXRtOiBhbnlbXSwgYWxsX2l0bXM6IGFueVtdLCBhbGxfZ3JwczogYW55W10pIHtcclxuICAgICAgICBsZXQgdHJpcHRpY0l0ZW0gPSB0aGlzLmdldFRyaXB0aWMoJ2l0ZW0nLCBiYXNlKTtcclxuXHJcbiAgICAgICAgaWYgKGdyb3VwKSB7XHJcbiAgICAgICAgICAgIGlmIChzZWwpIHtcclxuICAgICAgICAgICAgICAgIGFsbF9ncnBzLmZvckVhY2goZ3IgPT4geyBnci5fc2VsZWN0ZWQgPSB0cnVlOyB9KTtcclxuICAgICAgICAgICAgICAgIGlmIChkZXNlbF9pdG0pXHJcbiAgICAgICAgICAgICAgICAgICAgZGVzZWxfaXRtLmZvckVhY2goZWwgPT4geyBlbC5fc2VsZWN0ZWQgPSB0cnVlOyB0aGlzLmFkZEl0ZW0oZWwsIHRyaXB0aWNJdGVtKSB9KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGFsbF9ncnBzLmZvckVhY2goZ3IgPT4geyBnci5fc2VsZWN0ZWQgPSBmYWxzZTsgfSk7XHJcbiAgICAgICAgICAgICAgICBpZiAoc2VsX2l0bSlcclxuICAgICAgICAgICAgICAgICAgICBzZWxfaXRtLmZvckVhY2goZWwgPT4geyBlbC5fc2VsZWN0ZWQgPSBmYWxzZTsgdGhpcy5yZW1vdmVJdGVtKGVsLCB0cmlwdGljSXRlbSkgfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgIGlmIChzZWwpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuYWRkSXRlbShpdGVtLCB0cmlwdGljSXRlbSk7XHJcbiAgICAgICAgICAgICAgICBpZiAoaXRtX2dyb3VwICYmIGFsbF9pdG1zICYmIGFsbF9pdG1zLmV2ZXJ5KHQgPT4gdC5fc2VsZWN0ZWQpKVxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0R3JvdXAoaXRtX2dyb3VwKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlSXRlbShpdGVtLCB0cmlwdGljSXRlbSk7XHJcbiAgICAgICAgICAgICAgICBpZiAoaXRtX2dyb3VwKVxyXG4gICAgICAgICAgICAgICAgICAgIGl0bV9ncm91cC5fc2VsZWN0ZWQgPSBmYWxzZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEhlbHBlciBwZXIgc2VsZXppb25hcmUgdW4gZ3J1cHBvIGUsIHJpY29yc2l2YW1lbnRlLCBzZSB0dXR0aSBpIGdydXBwaSBzb3R0b3N0YW50aSBhbCBwYXJlbnQgc29ubyBzZWxlemlvbmF0aSwgc2VsZXppb25hcmUgaSBncnVwcGkgcGFkcmlcclxuICAgICAqIFxyXG4gICAgICogQHBhcmFtIHthbnl9IGdyb3VwIEdydXBwbyBkYSBzZWxlemlvbmFyZVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHNlbGVjdEdyb3VwKGdyb3VwOiBhbnkpIHtcclxuICAgICAgICBncm91cC5fc2VsZWN0ZWQgPSB0cnVlO1xyXG4gICAgICAgIGxldCBwYXJlbnQgPSB0aGlzLmdldEdyb3VwUGFyZW50KGdyb3VwKTtcclxuICAgICAgICBpZihwYXJlbnQgJiYgdGhpcy5nZXRHcm91cENoaWxkR3JvdXBzKG51bGwsIHBhcmVudCwgbnVsbCwgdHJ1ZSkuZXZlcnkodCA9PiB0Ll9zZWxlY3RlZCkpXHJcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0R3JvdXAocGFyZW50KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIERhdG8gTCdvZ2dldHRvIGRpIHNlbGV6aW9uZSwgbCdvZ2dldHRvIGRhIHNlbGV6aW9uYXJlL2Rlc2VsZXppb25hcmUgZSB0dXR0aSBpIHBhcmFtZXRyaSBkZWwgY2FzbyBlZmZldHR1YSBsZSBvcGVyYXppb25pIGNoZSBzZXJ2b25vLlxyXG4gICAgICogXHJcbiAgICAgKiBMYSBsb2dpY2EgZGkgcXVlc3RhIGZ1bnppb25lIMOoIG5hdGEgZXNzZW56aWFsbWVudGUgZGEgc3BhbSBkaSB0cmlhbCAmIGVycm9yIGVkIMOoIHN0YXRhIHRlc3RhdGEgc29sbyBmaW5vIGEgZHVlIGxpdmVsbGkgZGkgcmFnZ3J1cHBhbWVudG8sXHJcbiAgICAgKiBxdWFsc2lhc2kgY29zYSB2YWRhIG9sdHJlIG5vbiDDqCAxMDAlIGRldHRvIGNoZSBmdW56aW9uaS4uLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHBlcmZvcm1TZWxlY3Rpb25PcGVyYXRpb25zKGJhc2U6IEl0ZW1zU2VsZWN0aW9uPGFueT4sIGl0ZW06IGFueSwgYWxsOiBib29sZWFuLCBncm91cDogYm9vbGVhbiwgc2VsOiBib29sZWFuLCBzZWxfaXRtOiBhbnlbXSwgc2VsX2dycDogYW55W10sIGRlc2VsX2l0bTogYW55W10sIGRlc2VsX2dycDogYW55W10sIGFsbF9pdG1zOiBhbnlbXSwgYWxsX2dycHM6IGFueVtdLCBwYXJlbnRfaW5jbDogYm9vbGVhbiwgcGFyZW50X2V4Y2w6IGJvb2xlYW4pIHtcclxuICAgICAgICBsZXQgdHJpcHRpY0dyb3VwID0gdGhpcy5nZXRUcmlwdGljKCdncm91cCcsIGJhc2UpO1xyXG4gICAgICAgIGxldCB0cmlwdGljSXRlbSA9IHRoaXMuZ2V0VHJpcHRpYygnaXRlbScsIGJhc2UpO1xyXG4gICAgICAgIGxldCB0cmlwdGljRXhjbCA9IHRoaXMuZ2V0VHJpcHRpYygnZXhjbHVzaW9uJywgYmFzZSk7XHJcbiAgICAgICAgbGV0IHRyaXB0aWNncnBFeGNsID0gdGhpcy5nZXRUcmlwdGljKCdncm91cF9leGNsdXNpb24nLCBiYXNlKTtcclxuXHJcbiAgICAgICAgaWYgKGdyb3VwKSB7XHJcbiAgICAgICAgICAgIGlmIChzZWwpIHtcclxuICAgICAgICAgICAgICAgIGlmIChhbGwgfHwgcGFyZW50X2luY2wpXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVJdGVtKGl0ZW0sIHRyaXB0aWNncnBFeGNsKTtcclxuICAgICAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZEl0ZW0oaXRlbSwgdHJpcHRpY0dyb3VwKTtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoc2VsX2l0bSkgc2VsX2l0bS5mb3JFYWNoKGVsID0+IHRoaXMucmVtb3ZlSXRlbShlbCwgdHJpcHRpY0l0ZW0pKTtcclxuICAgICAgICAgICAgICAgIGlmIChzZWxfZ3JwKSBzZWxfZ3JwLmZvckVhY2goZ3IgPT4gdGhpcy5yZW1vdmVJdGVtKGdyLCB0cmlwdGljR3JvdXApKTtcclxuICAgICAgICAgICAgICAgIGlmIChhbGxfaXRtcykgYWxsX2l0bXMuZm9yRWFjaChlbCA9PiB7IGVsLl9zZWxlY3RlZCA9IHRydWU7IHRoaXMucmVtb3ZlSXRlbShlbCwgdHJpcHRpY0V4Y2wpOyB9KTtcclxuICAgICAgICAgICAgICAgIGlmIChhbGxfZ3JwcykgYWxsX2dycHMuZm9yRWFjaChnciA9PiB7IGdyLl9zZWxlY3RlZCA9IHRydWU7IHRoaXMucmVtb3ZlSXRlbShnciwgdHJpcHRpY2dycEV4Y2wpOyB9KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGlmIChhbGwgfHwgcGFyZW50X2luY2wpXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hZGRJdGVtKGl0ZW0sIHRyaXB0aWNncnBFeGNsKTtcclxuICAgICAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUl0ZW0oaXRlbSwgdHJpcHRpY0dyb3VwKTtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoZGVzZWxfaXRtKSBkZXNlbF9pdG0uZm9yRWFjaChlbCA9PiB0aGlzLnJlbW92ZUl0ZW0oZWwsIHRyaXB0aWNFeGNsKSk7XHJcbiAgICAgICAgICAgICAgICBpZiAoZGVzZWxfZ3JwKSBkZXNlbF9ncnAuZm9yRWFjaChnciA9PiB0aGlzLnJlbW92ZUl0ZW0oZ3IsIHRyaXB0aWNFeGNsKSk7XHJcbiAgICAgICAgICAgICAgICBpZiAoYWxsX2l0bXMpIGFsbF9pdG1zLmZvckVhY2goZWwgPT4geyBlbC5fc2VsZWN0ZWQgPSBmYWxzZTsgdGhpcy5yZW1vdmVJdGVtKGVsLCB0cmlwdGljSXRlbSk7IH0pO1xyXG4gICAgICAgICAgICAgICAgaWYgKGFsbF9ncnBzKSBhbGxfZ3Jwcy5mb3JFYWNoKGdyID0+IHsgZ3IuX3NlbGVjdGVkID0gZmFsc2U7IHRoaXMucmVtb3ZlSXRlbShnciwgdHJpcHRpY0dyb3VwKTsgfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgIGlmIChzZWwpIHtcclxuICAgICAgICAgICAgICAgIGlmICgocGFyZW50X2V4Y2wgPT0gbnVsbCAmJiBhbGwpIHx8IHBhcmVudF9pbmNsKVxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlSXRlbShpdGVtLCB0cmlwdGljRXhjbCk7XHJcbiAgICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hZGRJdGVtKGl0ZW0sIHRyaXB0aWNJdGVtKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnRfZXhjbCB8fCAoIWFsbCAmJiBwYXJlbnRfZXhjbCA9PSBudWxsKSlcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUl0ZW0oaXRlbSwgdHJpcHRpY0l0ZW0pO1xyXG4gICAgICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkSXRlbShpdGVtLCB0cmlwdGljRXhjbCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgXHJcbiAgICAvKipcclxuICAgICAqIEhlbHBlciBwZXIgZXZpdGFyZSBkaSByaXNjcml2ZXJlIG9nbmkgc2FudGEgdm9sdGEgYXJyYXkuc3BsaWNlKGFycmF5LmluZGV4b2YoaXRlbSksIDEpO1xyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHJlbW92ZUl0ZW0oaXRlbTogYW55LCB0cmlwdGljPzogQ2FjaGVUcmlwdGljKSB7XHJcbiAgICAgICAgbGV0IGluZGV4ID0gdHJpcHRpYy5pbmRleF9jYWNoZS5nZXQoaXRlbS5faGFzaCk7XHJcbiAgICAgICAgaWYgKGluZGV4ICE9IG51bGwpIHtcclxuICAgICAgICAgICAgdHJpcHRpYy5jYWNoZS5kZWxldGUoaXRlbS5faGFzaCk7XHJcbiAgICAgICAgICAgIHRyaXB0aWMuaW5kZXhfY2FjaGUuZGVsZXRlKGl0ZW0uX2hhc2gpO1xyXG4gICAgICAgICAgICB0cmlwdGljLmFycmF5W2luZGV4XSA9IG51bGw7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gISFpbmRleDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEhlbHBlciBwZXIgZXZpdGFyZSBkaSByaXNjcml2ZXJlIG9nbmkgc2FudGEgdm9sdGEgYXJyYXkucHVzaChpdGVtKTsgZSBsYSBnZXN0aW9uZSBkZWxsYSBcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBhZGRJdGVtKGl0ZW06IGFueSwgdHJpcHRpYz86IENhY2hlVHJpcHRpYyk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGlmICh0cmlwdGljLmluZGV4X2NhY2hlLmdldChpdGVtLl9oYXNoKSA9PSBudWxsKSB7XHJcbiAgICAgICAgICAgIGxldCBpID0gdHJpcHRpYy5hcnJheS5wdXNoKGl0ZW0pIC0gMTtcclxuICAgICAgICAgICAgdHJpcHRpYy5jYWNoZS5zZXQoaXRlbS5faGFzaCwgaXRlbSk7XHJcbiAgICAgICAgICAgIHRyaXB0aWMuaW5kZXhfY2FjaGUuc2V0KGl0ZW0uX2hhc2gsIGkpO1xyXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIE90dGllbmUgaWwgdHJpdHRpY28gZGkgc2VsZXppb25lOiBMJ2FycmF5IGRlZ2xpIG9nZ2V0dGkgZSBsZSBkdWUgY2FjaGVcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBnZXRUcmlwdGljKHN1YmplY3Q6ICdncm91cCcgfCAnaXRlbScgfCAnZ3JvdXBfZXhjbHVzaW9uJyB8ICdleGNsdXNpb24nLCBiYXNlOiBJdGVtc1NlbGVjdGlvbjxhbnk+KTogQ2FjaGVUcmlwdGljIHtcclxuICAgICAgICBzd2l0Y2ggKHN1YmplY3QpIHtcclxuICAgICAgICAgICAgY2FzZSAnZ3JvdXAnOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBDYWNoZVRyaXB0aWModGhpcy5ncm91cHNDYWNoZSwgdGhpcy5pX2dyb3Vwc0NhY2hlLCBiYXNlLmdyb3Vwcyk7XHJcbiAgICAgICAgICAgIGNhc2UgJ2l0ZW0nOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBDYWNoZVRyaXB0aWModGhpcy5pdGVtc0NhY2hlLCB0aGlzLmlfaXRlbXNDYWNoZSwgYmFzZS5pdGVtcyk7XHJcbiAgICAgICAgICAgIGNhc2UgJ2dyb3VwX2V4Y2x1c2lvbic6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IENhY2hlVHJpcHRpYyh0aGlzLmdyb3VwX2V4Y2x1c2lvbnNDYWNoZSwgdGhpcy5pX2dyb3VwX2V4Y2x1c2lvbnNDYWNoZSwgYmFzZS5ncm91cF9leGNsdXNpb25zKTtcclxuICAgICAgICAgICAgY2FzZSAnZXhjbHVzaW9uJzpcclxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQ2FjaGVUcmlwdGljKHRoaXMuZXhjbHVzaW9uc0NhY2hlLCB0aGlzLmlfZXhjbHVzaW9uc0NhY2hlLCBiYXNlLmV4Y2x1c2lvbnMpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIERhdG8gdW4gb2dnZXR0byByZXN0aXR1aXNjZSBpbCBncnVwcG8gZGkgY3VpIGZhIHBhcnRlLCBzZSBlc2lzdGVcclxuICAgICAqIFxyXG4gICAgICogQHBhcmFtIHthbnl9IGl0ZW0gT2dnZXR0byBkaSBjdWkgdHJvdmFyZSBpbCBncnVwcG9cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBnZXRJdGVtR3JvdXAoaXRlbTogYW55KTogYW55IHtcclxuICAgICAgICBsZXQgcGFyZW50ID0gdGhpcy5yZ0dyb3VwQ2FjaGUuZ2V0KGl0ZW0uX3RoaXNLZXkpXHJcbiAgICAgICAgaWYgKHBhcmVudClcclxuICAgICAgICAgICAgcmV0dXJuIHBhcmVudDtcclxuXHJcbiAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEYXRhIGxhIGNoaWF2ZSBkaSB1biBncnVwcG8gcmVzdGl0dWlzY2UgdHV0dGkgZ2xpIG9nZ2V0dGkgY29uIHF1ZWxsYSBjaGlhdmVcclxuICAgICAqIFxyXG4gICAgICogQHBhcmFtIHthbnl9IGdyb3VwIENoaWF2ZSBkYSBjZXJjYXJlXHJcbiAgICAgKiBAcGFyYW0geydzZWxlY3RlZCcgfCAndW5zZWxlY3RlZCd9IHN0YXR1cyBTdGF0byBkZWdsaSBlbGVtZW50aSwgc2VsZXppb25hdGkgbyBub1xyXG4gICAgICogQHBhcmFtIHtib29sZWFufSByZWN1cnNpdmUgSW5kaWNhIHNlIGNlcmNhcmUgc29sbyBnbGkgZWxlbWVudGkgZGlyZXR0YW1lbnRlIGNvbGxlZ2F0aSBvIHNlIHByZW5kZXJlIGFuY2hlIHF1ZWxsaSBkZWkgZ3J1cHBpIGZpZ2xpXHJcbiAgICAgKiBcclxuICAgICAqIEByZXR1cm5zIHthbnlbXX0gT2dnZXR0aSBkaSB0aXBvICoqX2l0ZW0qKiBmYWNlbnRpIGNhcG8gYWxsYSBjaGlhdmUgKipncm91cEtleSoqXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZ2V0R3JvdXBJdGVtcyhzZWwgOkl0ZW1zU2VsZWN0aW9uPGFueT4sIGdyb3VwOiBhbnksIHN0YXR1cz86ICdzZWxlY3RlZCcgfCAndW5zZWxlY3RlZCcsIHJlY3Vyc2l2ZTogYm9vbGVhbiA9IGZhbHNlLCBhbGxiYXNlOiBhbnlbXSA9IG51bGwpOiBhbnlbXSB7XHJcbiAgICAgICAgbGV0IGl0ZW1zID0gW107XHJcblxyXG4gICAgICAgIGlmIChhbGxiYXNlKVxyXG4gICAgICAgICAgICBpdGVtcyA9IGFsbGJhc2U7XHJcbiAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgIGlmIChyZWN1cnNpdmUpIHtcclxuICAgICAgICAgICAgICAgIC8vIEluIG1vZGFsaXTDoCByaWNvcnNpdmEgcHJlbmRvIGdsaSBvZ2dldHRpIGRpIHR1dHRlIGxlIGNoaWF2aSBzaW1pbGkgY2hlIHRyb3ZvXHJcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBrZXkgb2YgdGhpcy5yZ0l0ZW1DYWNoZS5rZXlzKCkpXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleS5zdGFydHNXaXRoKGdyb3VwLl90aGlzS2V5KSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgaXRlbXMucHVzaCguLi50aGlzLnJnSXRlbUNhY2hlLmdldChrZXkpKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICBpdGVtcyA9IHRoaXMucmdJdGVtQ2FjaGUuZ2V0KGdyb3VwLl90aGlzS2V5KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGl0ZW1zID0gaXRlbXMuZmlsdGVyKHQgPT4gIXN0YXR1cyB8fCAodC5fc2VsZWN0ZWQgJiYgc3RhdHVzID09ICdzZWxlY3RlZCcpIHx8ICghdC5fc2VsZWN0ZWQgJiYgc3RhdHVzID09ICd1bnNlbGVjdGVkJykpO1xyXG5cclxuICAgICAgICAvLyBOb24gdHJvdm8gbmVzc3VuIG9nZ2V0dG8sIHBlcsOyIG1hZ2FyaSBkaSBvZ2dldHRpIG5lIGhvIGFsbCdpbnRlcm5vIGRlbGwnb2dnZXR0byBkaSBzZWxlemlvbmUuIFxyXG4gICAgICAgIC8vIFF1ZXN0byBwdcOyIGVzc2VyZSB2ZXJvIHNvbG8gc2UgTk9OIHNvbm8gaW4gbW9kYWxpdMOgIGFycmF5LCBpbiBjYXNvIGNvbnRyYXJpbyBnbGkgb2dnZXR0aSBsaSBkZXZvIHBlciBmb3J6YSBhdmVyZSB0dXR0aVxyXG4gICAgICAgIGlmIChpdGVtcy5sZW5ndGggIT0gMCB8fCAhc2VsIHx8IHRoaXMuYXJyYXlNb2RlKVxyXG4gICAgICAgICAgICByZXR1cm4gaXRlbXM7XHJcblxyXG4gICAgICAgIGlmIChzdGF0dXMgPT0gJ3Vuc2VsZWN0ZWQnKVxyXG4gICAgICAgICAgICBpdGVtcyA9IHNlbC5leGNsdXNpb25zLmZpbHRlcih0ID0+IHQgIT0gbnVsbCAmJlxyXG4gICAgICAgICAgICAgICAgKCFyZWN1cnNpdmUgJiYgdC5fdGhpc0tleSA9PSBncm91cC5fdGhpc0tleSkgfHxcclxuICAgICAgICAgICAgICAgIChyZWN1cnNpdmUgJiYgdC5fdGhpc0tleS5zdGFydHNXaXRoKGdyb3VwLl90aGlzS2V5KSkpO1xyXG4gICAgICAgIGVsc2UgaWYgKHN0YXR1cyA9PSAnc2VsZWN0ZWQnKVxyXG4gICAgICAgICAgICBpdGVtcyA9IHNlbC5pdGVtcy5maWx0ZXIodCA9PiB0ICE9IG51bGwgJiZcclxuICAgICAgICAgICAgICAgICghcmVjdXJzaXZlICYmIHQuX3RoaXNLZXkgPT0gZ3JvdXAuX3RoaXNLZXkpIHx8XHJcbiAgICAgICAgICAgICAgICAocmVjdXJzaXZlICYmIHQuX3RoaXNLZXkuc3RhcnRzV2l0aChncm91cC5fdGhpc0tleSkpKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIGl0ZW1zO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGF0YSBsYSBjaGlhdmUgZGkgdW4gZ3J1cHBvIHJlc3RpdHVpc2NlIHR1dHRpIGdsaSBvZ2dldHRpIGNvbiBxdWVsbGEgY2hpYXZlXHJcbiAgICAgKiBcclxuICAgICAqIEBwYXJhbSB7YW55fSBncm91cCBHcnVwcG8gZGkgY3VpIGNlcmNhcmUgaWwgcGFyZW50XHJcbiAgICAgKiBcclxuICAgICAqIEByZXR1cm5zIHthbnl9IE9nZ2V0dG8gZGkgdGlwbyAqKl9ncm91cCoqIHJhcHByZXNlbnRhbnRlIGlsIHBhcmVudCBkZWwgKipncm91cCoqIGF0dHVhbGVcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBnZXRHcm91cFBhcmVudChncm91cDogYW55KTogYW55IHtcclxuICAgICAgICBsZXQgcGFyZW50ID0gdGhpcy5yZ0dyb3VwQ2FjaGUuZ2V0KGdyb3VwLl9wYXJlbnQpXHJcbiAgICAgICAgaWYgKHBhcmVudClcclxuICAgICAgICAgICAgcmV0dXJuIHBhcmVudDtcclxuXHJcbiAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEYXRhIGxhIGNoaWF2ZSBkaSB1biBncnVwcG8gcmVzdGl0dWlzY2UgdHV0dGkgaSBncnVwcGkgZmlnbGlcclxuICAgICAqIFxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGdyb3VwIEdydXBwbyBjaGUgcmFwcHJlc2VudGEgaWwgcGFkcmUgZGkgY3VpIGNlcmNhcmUgaSBmaWdsaVxyXG4gICAgICogQHBhcmFtIHsnc2VsZWN0ZWQnIHwgJ3Vuc2VsZWN0ZWQnfSBzdGF0dXMgU3RhdG8gZGVpIGdydXBwaSwgc2VsZXppb25hdGkgbyBub1xyXG4gICAgICogQHBhcmFtIHtib29sZWFufSByZWN1cnNpdmUgSW5kaWNhIHNlIGNlcmNhcmUgc29sbyBpIGdydXBwaSBkaXJldHRhbWVudGUgY29sbGVnYXRpIG8gc2UgcHJlbmRlcmUgYW5jaGUgcXVlbGxpIGRlaSBncnVwcGkgZmlnbGlcclxuICAgICAqIFxyXG4gICAgICogQHJldHVybnMge2FueVtdfSBPZ2dldHRpIGRpIHRpcG8gKipfZ3JvdXAqKiBmYWNlbnRpIGNhcG8gYWxsYSBjaGlhdmUgKipncm91cEtleSoqXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZ2V0R3JvdXBDaGlsZEdyb3VwcyhzZWw6IEl0ZW1zU2VsZWN0aW9uPGFueT4sIGdyb3VwOiBhbnksIHN0YXR1cz86ICdzZWxlY3RlZCcgfCAndW5zZWxlY3RlZCcsIHJlY3Vyc2l2ZTogYm9vbGVhbiA9IGZhbHNlLCBhbGxiYXNlOiBhbnlbXSA9IG51bGwpIHtcclxuICAgICAgICBsZXQgdGhpc0dyb3VwOiBhbnkgPSB0aGlzLnJnR3JvdXBDYWNoZS5nZXQoZ3JvdXAuX3RoaXNLZXkpO1xyXG4gICAgICAgIGxldCBpdGVtcyA9IFtdO1xyXG5cclxuICAgICAgICBpZiAoYWxsYmFzZSlcclxuICAgICAgICAgICAgaXRlbXMgPSBhbGxiYXNlO1xyXG4gICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICBpZiAocmVjdXJzaXZlKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBJbiBtb2RhbGl0w6Agcmljb3JzaXZhIHByZW5kbyBnbGkgb2dnZXR0aSBkaSB0dXR0ZSBsZSBjaGlhdmkgc2ltaWxpIGNoZSB0cm92b1xyXG4gICAgICAgICAgICAgICAgZm9yIChsZXQga2V5IG9mIHRoaXMucmdDaGlsZEdyb3Vwc0NhY2hlLmtleXMoKSlcclxuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5LnN0YXJ0c1dpdGgoZ3JvdXAuX3RoaXNLZXkpKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpdGVtcy5wdXNoKC4uLnRoaXMucmdDaGlsZEdyb3Vwc0NhY2hlLmdldChrZXkpKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICBpdGVtcyA9IHRoaXMucmdDaGlsZEdyb3Vwc0NhY2hlLmdldChncm91cC5fdGhpc0tleSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpdGVtcyA9IGl0ZW1zLmZpbHRlcih0ID0+ICFzdGF0dXMgfHwgKHQuX3NlbGVjdGVkICYmIHN0YXR1cyA9PSAnc2VsZWN0ZWQnKSB8fCAoIXQuX3NlbGVjdGVkICYmIHN0YXR1cyA9PSAndW5zZWxlY3RlZCcpKTtcclxuXHJcbiAgICAgICAgLy8gTm9uIHRyb3ZvIG5lc3N1biBvZ2dldHRvLCBwZXLDsiBtYWdhcmkgZGkgb2dnZXR0aSBuZSBobyBhbGwnaW50ZXJubyBkZWxsJ29nZ2V0dG8gZGkgc2VsZXppb25lXHJcbiAgICAgICAgaWYgKGl0ZW1zLmxlbmd0aCAhPSAwIHx8ICFzZWwpXHJcbiAgICAgICAgICAgIHJldHVybiBpdGVtcztcclxuXHJcbiAgICAgICAgaWYgKHN0YXR1cyA9PSAndW5zZWxlY3RlZCcpXHJcbiAgICAgICAgICAgIGl0ZW1zID0gc2VsLmdyb3VwX2V4Y2x1c2lvbnMuZmlsdGVyKCh0OiBhbnkpID0+IHQgIT0gbnVsbCAmJiAoXHJcbiAgICAgICAgICAgICAgICAoIXJlY3Vyc2l2ZSAmJiB0Ll90aGlzUm91dGUubGVuZ3RoID09IHRoaXNHcm91cC5fdGhpc1JvdXRlLmxlbmd0aCArIDEgJiYgdC5fdGhpc1JvdXRlLnN0YXJ0c1dpdGgoZ3JvdXAuX3RoaXNLZXkpKSB8fCBcclxuICAgICAgICAgICAgICAgIChyZWN1cnNpdmUgJiYgdC5fdGhpc0tleS5zdGFydHNXaXRoKGdyb3VwLl90aGlzS2V5KSkpKTtcclxuICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgIGl0ZW1zID0gc2VsLmdyb3Vwcy5maWx0ZXIoKHQ6IGFueSkgPT4gdCAhPSBudWxsICYmIChcclxuICAgICAgICAgICAgICAgICghcmVjdXJzaXZlICYmIHQuX3RoaXNSb3V0ZS5sZW5ndGggPT0gdGhpc0dyb3VwLl90aGlzUm91dGUubGVuZ3RoICsgMSAmJiB0Ll90aGlzUm91dGUuc3RhcnRzV2l0aChncm91cC5fdGhpc0tleSkpIHx8IFxyXG4gICAgICAgICAgICAgICAgKHJlY3Vyc2l2ZSAmJiB0Ll90aGlzS2V5LnN0YXJ0c1dpdGgoZ3JvdXAuX3RoaXNLZXkpKSkpO1xyXG5cclxuICAgICAgICByZXR1cm4gaXRlbXM7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBGaW5hbGl6emEgbGUgaW5mb3JtYXppb25pIGRpIHNlbGV6aW9uZSBkZWwgKipJdGVtc1NlbGVjdGlvbioqIGNvcnJlbnRlXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZmluYWxpemVTZWxlY3Rpb25JbmZvcm1hdGlvbnMoc2VsZWN0aW9uSXRlbTogSXRlbXNTZWxlY3Rpb248YW55Pikge1xyXG4gICAgICAgIC8vIERhdG8gY2hlIGxlIGRlbGV0ZSBzb25vIGxvZ2ljaGUgZGF0byBjaGUgdGVuZ28gbGEgY2FjaGUgZGVnbGkgaW5kaWNpIGRldm8gcmVuZGVybGUgZmlzaWNoZVxyXG4gICAgICAgIGxldCB0bXBHcnAgPSBbXSwgdG1wSXRlbXMgPSBbXSwgdG1wRXhjbCA9IFtdLCB0bXBHcnBFeGNsID0gW107XHJcbiAgICAgICAgbGV0IGdycFJlbW92ZWQgPSBmYWxzZSwgaXRlbXNSZW1vdmVkID0gZmFsc2UsIGV4Y2xSZW1vdmVkID0gZmFsc2UsIGdycEV4Y2xSZW1vdmVkID0gZmFsc2U7XHJcblxyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZWN0aW9uSXRlbS5pdGVtcy5sZW5ndGg7IGkrKylcclxuICAgICAgICAgICAgaWYgKHNlbGVjdGlvbkl0ZW0uaXRlbXNbaV0gIT0gbnVsbCkgdG1wSXRlbXMucHVzaChzZWxlY3Rpb25JdGVtLml0ZW1zW2ldKTtcclxuICAgICAgICAgICAgZWxzZSBpdGVtc1JlbW92ZWQgPSB0cnVlO1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZWN0aW9uSXRlbS5ncm91cHMubGVuZ3RoOyBpKyspXHJcbiAgICAgICAgICAgIGlmIChzZWxlY3Rpb25JdGVtLmdyb3Vwc1tpXSAhPSBudWxsKSB0bXBHcnAucHVzaChzZWxlY3Rpb25JdGVtLmdyb3Vwc1tpXSk7XHJcbiAgICAgICAgICAgIGVsc2UgZ3JwUmVtb3ZlZCA9IHRydWU7XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWxlY3Rpb25JdGVtLmV4Y2x1c2lvbnMubGVuZ3RoOyBpKyspXHJcbiAgICAgICAgICAgIGlmIChzZWxlY3Rpb25JdGVtLmV4Y2x1c2lvbnNbaV0gIT0gbnVsbCkgdG1wRXhjbC5wdXNoKHNlbGVjdGlvbkl0ZW0uZXhjbHVzaW9uc1tpXSk7XHJcbiAgICAgICAgICAgIGVsc2UgZXhjbFJlbW92ZWQgPSB0cnVlO1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZWN0aW9uSXRlbS5ncm91cF9leGNsdXNpb25zLmxlbmd0aDsgaSsrKVxyXG4gICAgICAgICAgICBpZiAoc2VsZWN0aW9uSXRlbS5ncm91cF9leGNsdXNpb25zW2ldICE9IG51bGwpIHRtcEdycEV4Y2wucHVzaChzZWxlY3Rpb25JdGVtLmdyb3VwX2V4Y2x1c2lvbnNbaV0pO1xyXG4gICAgICAgICAgICBlbHNlIGdycEV4Y2xSZW1vdmVkID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgc2VsZWN0aW9uSXRlbS5pdGVtcyA9IHRtcEl0ZW1zO1xyXG4gICAgICAgIHNlbGVjdGlvbkl0ZW0uZ3JvdXBfZXhjbHVzaW9ucyA9IHRtcEdycEV4Y2w7XHJcbiAgICAgICAgc2VsZWN0aW9uSXRlbS5leGNsdXNpb25zID0gdG1wRXhjbDtcclxuICAgICAgICBzZWxlY3Rpb25JdGVtLmdyb3VwcyA9IHRtcEdycDtcclxuXHJcbiAgICAgICAgLy8gTGUgY2FjaGUgZGVnbGkgaW5kaWNpIHBvdHJlYmJlcm8gYXZlcmUgYnVjaGksIHJpc29sdm9cclxuICAgICAgICBpZiAoZ3JwUmVtb3ZlZClcclxuICAgICAgICAgICAgdGhpcy5pX2dyb3Vwc0NhY2hlID0gdGhpcy5jb21wYWN0SW5kZXhNYXAodGhpcy5pX2dyb3Vwc0NhY2hlKTtcclxuICAgICAgICBpZiAoaXRlbXNSZW1vdmVkKVxyXG4gICAgICAgICAgICB0aGlzLmlfaXRlbXNDYWNoZSA9IHRoaXMuY29tcGFjdEluZGV4TWFwKHRoaXMuaV9pdGVtc0NhY2hlKTtcclxuICAgICAgICBpZiAoZXhjbFJlbW92ZWQpXHJcbiAgICAgICAgICAgIHRoaXMuaV9leGNsdXNpb25zQ2FjaGUgPSB0aGlzLmNvbXBhY3RJbmRleE1hcCh0aGlzLmlfZXhjbHVzaW9uc0NhY2hlKTtcclxuICAgICAgICBpZiAoZ3JwRXhjbFJlbW92ZWQpXHJcbiAgICAgICAgICAgIHRoaXMuaV9ncm91cF9leGNsdXNpb25zQ2FjaGUgPSB0aGlzLmNvbXBhY3RJbmRleE1hcCh0aGlzLmlfZ3JvdXBfZXhjbHVzaW9uc0NhY2hlKTtcclxuXHJcbiAgICAgICAgLy8gUG9pIHJpcHJlbmRvIGEgZmFyZSB0dXR0byBpbiBub3JtYWxpdMOgXHJcbiAgICAgICAgc2VsZWN0aW9uSXRlbS5jb3VudCA9IHRoaXMuZXZhbHVhdGVTZWxlY3RlZCgpO1xyXG5cclxuICAgICAgICAvLyBTZSBobyBmYXR0byBzZWxlemlvbmUgXCJhbGxcIiBtYSBwb2kgbWkgc29ubyBtZXNzbyBhIHRvZ2xpZXJlIHR1dHRpIGdsaSBlbGVtZW50aSBmaW5vIGEgcmltYW5lcm5lIDAgcmVzZXR0byBsJ29nZ2V0dG8gZGkgc2VsZXppb25lXHJcbiAgICAgICAgaWYgKHNlbGVjdGlvbkl0ZW0uY291bnQgPT0gMCkge1xyXG4gICAgICAgICAgICB0aGlzLmJvdW5kU291cmNlLmZvckVhY2godCA9PiB0Ll9zZWxlY3RlZCA9IGZhbHNlKTtcclxuICAgICAgICAgICAgc2VsZWN0aW9uSXRlbS5hbGwgPSBmYWxzZTtcclxuICAgICAgICAgICAgc2VsZWN0aW9uSXRlbS5leGNsdXNpb25zID0gW107XHJcbiAgICAgICAgICAgIHNlbGVjdGlvbkl0ZW0uaXRlbXMgPSBbXTtcclxuICAgICAgICAgICAgc2VsZWN0aW9uSXRlbS5ncm91cHMgPSBbXTtcclxuICAgICAgICAgICAgc2VsZWN0aW9uSXRlbS5ncm91cF9leGNsdXNpb25zID0gW107XHJcblxyXG4gICAgICAgICAgICAvLyBSaXB1bGlzY28gbGEgY2FjaGUgYWx0cmltZW50aSBtaSByaW1hbmUgcGllbmEgZGkgdHV0dGUgbGUgZXNjbHVzaW9uaVxyXG4gICAgICAgICAgICB0aGlzLmNsZWFyU2VsZWN0aW9uQ2FjaGVzKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBTZSBsYSBwb3NzaWJpbGl0w6AgZGkgZmFyZSBcIlNlbGV6aW9uYSB0dXR0b1wiIMOoIGFiaWxpdGF0YSBhbGxvcmEgbGEgY29uc2lkZXJvIGFwcGVuYSBtaSB2aWVuZSBzZWxlemlvbmF0byBxdWFsY29zYVxyXG4gICAgICAgIHRoaXMuY2FuU2VsZWN0QWxsID0gc2VsZWN0aW9uSXRlbS5jb3VudCA+IDAgJiYgdGhpcy5TZWxlY3RBbGw7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDb21wYXR0YSB1bmEgY2FjaGUgZGkgaW5kaWNpXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgY29tcGFjdEluZGV4TWFwKG1hcDogTWFwPHN0cmluZywgbnVtYmVyPik6IE1hcDxzdHJpbmcsIG51bWJlcj4ge1xyXG4gICAgICAgIGxldCBpbmRleCA9IDA7XHJcbiAgICAgICAgbGV0IHJldCA9IG5ldyBNYXAoKTtcclxuICAgICAgICBmb3IgKGxldCBrZXkgb2YgbWFwLmtleXMoKSlcclxuICAgICAgICAgICAgcmV0LnNldChrZXksIGluZGV4KyspO1xyXG5cclxuICAgICAgICByZXR1cm4gcmV0O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2VzdGlzY2UgaSBjbGljayBzdWxsYSB0YWJlbGxhLCBnZXN0ZW5kbyBldmVudHVhbG1lbnRlIGFuY2hlIGdsaSBTaGlmdCArIENsaWNrIHBlciBzZWxlemlvbmFyZSB1biByYW5nZSBkaSBvZ2dldHRpXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHthbnl9IGV2ZW50IEV2ZW50byBuYXRpdm8gSFRNTCBkZWwgY2xpY2tcclxuICAgICAqIEBwYXJhbSB7YW55fSBpdGVtIE9nZ2V0dG8gYmluZGF0byBzdSBjdWkgc2kgw6ggZWZmZXR0dWF0byBpbCBjbGlja1xyXG4gICAgICpcclxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSAqKnRydWUqKiBzZSBsJ29wZXJhaXpvbmUgw6ggYW5kYXRhIGEgYnVvbiBmaW5lLCAqKmZhbHNlKiogYWx0cmltZW50aVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgaGFuZGxlQ2xpY2soZXZlbnQ6IGFueSwgaXRlbTogYW55KTogYm9vbGVhbiB7XHJcbiAgICAgICAgLy8gU2VsZXppb25vIGRlbCB0ZXN0byBtYSBub24gaG8gc2hpZnQgcHJlbXV0byAtPiBpZ25vcm8gbGEgc2VsZXppb25lXHJcbiAgICAgICAgaWYgKChldmVudC52aWV3LmdldFNlbGVjdGlvbigpLnR5cGUgPT0gJ1JhbmdlJyB8fCBldmVudC52aWV3LmdldFNlbGVjdGlvbigpLnRvU3RyaW5nKCkubGVuZ3RoID4gMCkgJiYgIWV2ZW50LnNoaWZ0S2V5KVxyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcblxyXG4gICAgICAgIC8vIFNlbGV6aW9ubyBkZWwgdGVzdG8gZSBobyBzaGlmdCBwcmVtdXRvIC0+IGFubnVsbG8gbGEgc2VsZXppb25lIGRlbCB0ZXN0b1xyXG4gICAgICAgIGlmICgoZXZlbnQudmlldy5nZXRTZWxlY3Rpb24oKS50eXBlID09ICdSYW5nZScgfHwgZXZlbnQudmlldy5nZXRTZWxlY3Rpb24oKS50b1N0cmluZygpLmxlbmd0aCA+IDApICYmIGV2ZW50LnNoaWZ0S2V5KVxyXG4gICAgICAgICAgICB0aGlzLnV0aUV4dHMuY2xlYXJUZXh0U2VsZWN0aW9uKCk7XHJcblxyXG4gICAgICAgIGxldCBzZWxlY3RlZGl0ZW1zOiBhbnlbXSA9IFtdO1xyXG4gICAgICAgIGlmIChldmVudC5zaGlmdEtleSAmJiB0aGlzLlNoaWZ0Q2xpY2sgJiYgIXRoaXMuU2luZ2xlU2VsZWN0aW9uKSB7XHJcbiAgICAgICAgICAgIGxldCBzdGFydFNlbGVjdGluZyA9IGZhbHNlO1xyXG5cclxuICAgICAgICAgICAgbGV0IGl0ZW1zID0gdGhpcy5ib3VuZFNvdXJjZS5maWx0ZXIodCA9PiAhdC5fZ3JvdXAgJiYgIXQuX3NlcCk7XHJcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaXRlbXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgIGxldCB0ID0gaXRlbXNbaV07XHJcbiAgICAgICAgICAgICAgICBpZiAoc3RhcnRTZWxlY3RpbmcpIHtcclxuICAgICAgICAgICAgICAgICAgICB0Ll9zZWxlY3RlZCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWRpdGVtcy5wdXNoKHQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaWYgKCh0ID09IGl0ZW0gfHwgdCA9PSB0aGlzLmxhc3RTZWxlY3RlZCkgJiYgIXN0YXJ0U2VsZWN0aW5nKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgc3RhcnRTZWxlY3RpbmcgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgIHQuX3NlbGVjdGVkID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZGl0ZW1zLnB1c2godCk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCh0ID09IGl0ZW0gfHwgdCA9PSB0aGlzLmxhc3RTZWxlY3RlZCkgJiYgc3RhcnRTZWxlY3RpbmcpXHJcbiAgICAgICAgICAgICAgICAgICAgc3RhcnRTZWxlY3RpbmcgPSBmYWxzZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGl0ZW0uX3NlbGVjdGVkID0gIWl0ZW0uX3NlbGVjdGVkO1xyXG4gICAgICAgICAgICB0aGlzLmxhc3RTZWxlY3RlZCA9IGl0ZW07XHJcbiAgICAgICAgICAgIHNlbGVjdGVkaXRlbXMucHVzaChpdGVtKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHZhciBpdGVtU2VsZWN0aW9uID0gdGhpcy5oYW5kbGVJdGVtc1NlbGVjdGlvbihzZWxlY3RlZGl0ZW1zKTtcclxuICAgICAgICB0aGlzLmNoYW5nZWQoKTtcclxuXHJcbiAgICAgICAgdGhpcy5vblNlbGVjdGlvbkNoYW5nZWQuZW1pdChpdGVtU2VsZWN0aW9uKTtcclxuICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFZhbHV0YSBsYSBxdWFudGl0w6AgZGkgb2dnZXR0aSBjaGUgc29ubyBzdGF0aSBzZWxlemlvbmF0aSBhbCB0ZXJtaW5lIGRpIHVuIGV2ZW50byBkaSBzZWxlemlvbmVcclxuICAgICAqXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBOdW1lcm8gZGkgb2dnZXR0aSBzZWxlemlvbmF0aVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGV2YWx1YXRlU2VsZWN0ZWQoKTogbnVtYmVyIHtcclxuICAgICAgICBsZXQgc2kgPSAodGhpcy5WaWV3IGFzIEFwcFNlYXJjaDxhbnk+KT8uc2VsZWN0aW9uIHx8IHRoaXMuYXJyYXltb2RlU2VsZWN0aW9uO1xyXG5cclxuICAgICAgICBsZXQgZXhjQnlHcm91cCA9IHNpLmdyb3VwX2V4Y2x1c2lvbnMucmVkdWNlKChwcmV2LCBjdXJyKSA9PiBwcmV2ICsgY3Vyci5jb3VudCwgMCk7XHJcbiAgICAgICAgbGV0IGluY0J5R3JvdXAgPSBzaS5ncm91cHMucmVkdWNlKChwcmV2LCBjdXJyKSA9PiBwcmV2ICsgY3Vyci5jb3VudCwgMCk7XHJcblxyXG4gICAgICAgIHRoaXMuc2VsZWN0ZWRPYmplY3RzID0gKHNpLmFsbCA/IHRoaXMuQmFzZUl0ZW1zQ291bnQgOiBpbmNCeUdyb3VwKSAtIGV4Y0J5R3JvdXAgKyBzaS5pdGVtcy5sZW5ndGggLSBzaS5leGNsdXNpb25zLmxlbmd0aDtcclxuICAgICAgICByZXR1cm4gdGhpcy5zZWxlY3RlZE9iamVjdHM7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXN0aXNjZSBpbCBjb21hbmRvIGRpIFwiU2VsZXppb25hIHR1dHRvIGluIHR1dHRlIGxlIHBhZ2luZVwiIG8gaWwgc3VvIGNvbnRyYXJpbywgY2lvw6ggXCJSZWltcG9zdGEgc2VsZXppb25lXCJcclxuICAgICAqL1xyXG4gICAgcHVibGljIHNlbGVjdEFsbE9yUmVzZXRTZWxlY3Rpb24oKSB7XHJcbiAgICAgICAgbGV0IHNlbGVjdGlvbkl0ZW0gPSB0aGlzLlZpZXcuc2VsZWN0aW9uIHx8IHRoaXMuYXJyYXltb2RlU2VsZWN0aW9uO1xyXG4gICAgICAgIHRoaXMuY2xlYXJTZWxlY3Rpb25DYWNoZXMoKTtcclxuICAgICAgICBzZWxlY3Rpb25JdGVtLmFsbCA9ICFzZWxlY3Rpb25JdGVtLmFsbDtcclxuICAgICAgICBzZWxlY3Rpb25JdGVtLmV4Y2x1c2lvbnMgPSBbXTtcclxuICAgICAgICBzZWxlY3Rpb25JdGVtLmdyb3VwcyA9IFtdO1xyXG4gICAgICAgIHNlbGVjdGlvbkl0ZW0uZ3JvdXBfZXhjbHVzaW9ucyA9IFtdO1xyXG4gICAgICAgIHNlbGVjdGlvbkl0ZW0uaXRlbXMgPSBbXTtcclxuXHJcbiAgICAgICAgLy8gUmlwdWxpc2NvIGdsaSBzdGF0aSBVSSBkaSBzZWxlemlvbmUgZ2xvYmFsZSBzZSBsJ2hvIGRpc2F0dGl2YXRhXHJcbiAgICAgICAgaWYgKCFzZWxlY3Rpb25JdGVtLmFsbCkge1xyXG4gICAgICAgICAgICB0aGlzLmNhblNlbGVjdEFsbCA9IGZhbHNlO1xyXG4gICAgICAgICAgICB0aGlzLmdsb2JhbENoZWNrID0gZmFsc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLmZpbmFsaXplU2VsZWN0aW9uSW5mb3JtYXRpb25zKHNlbGVjdGlvbkl0ZW0pO1xyXG5cclxuICAgICAgICB0aGlzLm9uU2VsZWN0aW9uQ2hhbmdlZC5lbWl0KHNlbGVjdGlvbkl0ZW0pO1xyXG5cclxuICAgICAgICAvLyBEb3BvIGF2ZXIgcmVzZXR0YXRvIGRpcmV0dGFtZW50ZSBpbCBzb2xvIG9nZ2V0dG8gdGhpcy5WaWV3LnNlbGVjdGlvbiBkZXZvIGFuY2hlIHJpYWxsaW5lYXJlIGEgdHV0dGkgZ2xpIG9nZ2V0dGkgYmluZGF0aVxyXG4gICAgICAgIHRoaXMuZXZhbHVhdGVTZWxlY3Rpb24odGhpcy5ib3VuZFNvdXJjZSwgc2VsZWN0aW9uSXRlbSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gI2VuZHJlZ2lvblxyXG5cclxuICAgIC8vICNyZWdpb24gR2VzdGlvbmUgUGFnaW5hemlvbmVcclxuXHJcbiAgICAvKipcclxuICAgICAqIFNwb3N0YSBsYSByaWNlcmNhIGRpIHVuYSBwYWdpbmEgaW4gYXZhbnRpIChvIGluZGVpdHJvKVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBwYWdlIE51bWVybyBkaSBwYWdpbmUgZGEgYWdnaXVuZ2VyZSAobyBzb3R0cmFycmUsIHNlIG5lZ2F0aXZvKSBhbGxhIHBhZ2luYSBhdHR1YWxlXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBhZGRUb1BhZ2UocGFnZTogbnVtYmVyKSB7XHJcbiAgICAgICAgbGV0IHZpZXcgPSB0aGlzLk1haW5Hcm91cFZpZXcgPyB0aGlzLk1haW5Hcm91cFZpZXcgOiB0aGlzLlZpZXc7XHJcblxyXG4gICAgICAgIHRoaXMuZ29Ub1BhZ2UoKCh0aGlzLlNlYXJjaFZpZXcgfHwgdmlldyk/LnBhZ2UgfHwgMCkgKyBwYWdlKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFNwb3N0YSBsYSByaWNlcmNhIGFsbGEgcGFnaW5hIHNwZWNpZmljYXRhXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHBhZ2UgUGFnaW5hIGEgY3VpIG5hdmlnYXJlXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBnb1RvUGFnZShwYWdlOiBudW1iZXIpIHtcclxuICAgICAgICBsZXQgdmlldyA9IHRoaXMuTWFpbkdyb3VwVmlldyA/IHRoaXMuTWFpbkdyb3VwVmlldyA6IHRoaXMuVmlldztcclxuICAgICAgICBpZiAoIXZpZXcucGFnZSB8fCAhdmlldy5wYWdlcylcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICBsZXQgYXBwU2VhcmNoRWxlbWVudCA9IHRoaXMuU2VhcmNoVmlldyB8fCB2aWV3O1xyXG4gICAgICAgIGlmIChwYWdlID09PSAwIHx8IHBhZ2UgPiBhcHBTZWFyY2hFbGVtZW50LnBhZ2VzKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgIGFwcFNlYXJjaEVsZW1lbnQucGFnZSA9IHBhZ2U7XHJcbiAgICAgICAgdGhpcy5hcnJheVB1bHNhbnRpID0gdGhpcy5nZXRQYWdlc0FycmF5KDYsIGFwcFNlYXJjaEVsZW1lbnQucGFnZSwgYXBwU2VhcmNoRWxlbWVudC5wYWdlcyk7XHJcblxyXG4gICAgICAgIGxldCBoYXNHcm91cGluZ3MgPSAhIXRoaXMuTWFpbkdyb3VwVmlldztcclxuICAgICAgICB0aGlzLmVtaXRTZWFyY2hSZXF1ZXN0KGZhbHNlLCBoYXNHcm91cGluZ3MgPyB2aWV3IDogbnVsbCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBFdmVudG8gcmljaGlhbWF0byBzdWwgY2FtYmlvIGRlbGxhIHBhZ2luYXppb25lLiBWZXJyw6AgcmljaGlhbWF0byBsJ2V2ZW50byAqKmVtaXRTZWFyY2hSZXF1ZXN0KipcclxuICAgICAqIHBlciBjb211bmljYXJlIGFsIGNvbXBvbmVudGUgY2hlIHV0aWxpenphIHF1ZXN0YSB0YWJlbGxhIGNoZSBpIGRhdGkgc29ubyBkYSBhZ2dpb3JuYXJlXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBvbkl0ZW1zUGVyUGFnZUNoYW5nZWQobmV3SXBwKSB7XHJcbiAgICAgICAgdGhpcy5QYWdlck9wdGlvbnMuVmlldy5pdGVtc3BlcnBhZ2VvdmVycmlkZSA9IG5ld0lwcDtcclxuICAgICAgICB0aGlzLmNoYW5nZWQoKTtcclxuICAgICAgICBpZiAodGhpcy5NYWluR3JvdXBWaWV3KVxyXG4gICAgICAgICAgICB0aGlzLmVtaXRTZWFyY2hSZXF1ZXN0KHRydWUsIHRoaXMuTWFpbkdyb3VwVmlldyk7XHJcbiAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICB0aGlzLmVtaXRTZWFyY2hSZXF1ZXN0KHRydWUpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRXZlbnRvIHJpY2hpYW1hdG8gc3VsIGNhbWJpbyBkZWxsYSBwYWdpbmF6aW9uZS4gVmVycsOgIHJpY2hpYW1hdG8gbCdldmVudG8gKiplbWl0U2VhcmNoUmVxdWVzdCoqIGNvbiBsYSB2aXN0YSBkZWwgc2VwYXJhdG9yZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgb25Hcm91cEl0ZW1zUGVyUGFnZUNoYW5nZWQocGFnZXI6IEdyb3VwUGFnZXIsIG5ld0lwcDogbnVtYmVyKSB7XHJcbiAgICAgICAgcGFnZXIudmlldy5pdGVtc3BlcnBhZ2VvdmVycmlkZSA9IG5ld0lwcDtcclxuICAgICAgICB0aGlzLmVtaXRTZWFyY2hSZXF1ZXN0KHRydWUsIHBhZ2VyLnZpZXcpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vICNlbmRyZWdpb25cclxuXHJcbiAgICAvLyAjcmVnaW9uIEdlc3Rpb25lIEV4cG9ydFxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRWZmZXR0dWEgbCdlc3BvcnRhemlvbmUgZGVpIGRhdGlcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZm9ybWF0IEZvcm1hdG8gZGkgZXNwb3J0YXppb25lLiBMZXR0byBzb2xvIGluIG1vZGFsaXTDoCBSZXBvcnQgZGVsbGEgdGFiZWxsYVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgdHJ5RXhwb3J0KGZvcm1hdD86IHN0cmluZykge1xyXG4gICAgICAgIGlmICghdGhpcy5FeHBvcnRGdW5jdGlvbilcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5yZXBvcnRNb2RlKVxyXG4gICAgICAgICAgICB0aGlzLkV4cG9ydEZ1bmN0aW9uKGZvcm1hdCk7XHJcbiAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICB0aGlzLkV4cG9ydEZ1bmN0aW9uKChkYXRhOiBhbnlbXSwgY2FuY2VsOiBib29sZWFuID0gZmFsc2UpID0+IHtcclxuICAgICAgICAgICAgICAgIGlmIChjYW5jZWwpXHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChkYXRhLmxlbmd0aCA9PSAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tc2dFeHRzLnNpbXBsZVdhcm5pbmcodGhpcy5sYy5sb2MoXCJDYW5ub3QgZXhwb3J0IGFuIGVtcHR5IGRhdGFzZXRcIikpO1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICB0aGlzLnNldHVwRXhwb3J0KGRhdGEpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xyXG4gICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7IHRoaXMuZXhwb3J0RG93bmxvYWRlci5uYXRpdmVFbGVtZW50LmNsaWNrKCk7IH0pO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIE1ldG9kbyBjaGUgZWZmZXR0aXZhbWVudGUgZ2VuZXJhIGdsaSBoZWFkZXIgZSBpIGRhdGkgcGVyIGwnZXNwb3J0YXppb25lIGNvbiAqKm5neC1jc3YqKlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7YW55W119IGl0ZW1zIE9nZ2V0dGkgZGEgZXNwb3J0YXJlXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgc2V0dXBFeHBvcnQoaXRlbXM6IGFueVtdKSB7XHJcbiAgICAgICAgbGV0IGRyY2QgPSB0aGlzLkR5bmFtaWNSb3dDb2x1bW5zRGVmaW5pdGlvbjtcclxuXHJcbiAgICAgICAgdGhpcy5oZWFkZXJzID0gZHJjZCAmJiBkcmNkLmxlbmd0aCA+IDAgPyB0aGlzLmV4cEV4dHMuc2V0dXBGb3JHZW5lcmljRXhwb3J0KGl0ZW1zLCBkcmNkLm1hcCh0ID0+IHsgcmV0dXJuIHsgbGFiZWw6IHQuZGVzY3JpcHRpb24sIGtleTogdC5wcm9wZXJ0eU5hbWUsIG9yZGVyOiB0LmNvbHVtbk9yZGVyIH0gfSkpIDogdGhpcy5leHBFeHRzLnNldHVwRm9yRXhwb3J0KGl0ZW1zKTtcclxuICAgICAgICB0aGlzLmRhdGEgPSBpdGVtcztcclxuICAgIH1cclxuXHJcbiAgICAvLyAjZW5kcmVnaW9uXHJcblxyXG4gICAgLy8gI3JlZ2lvbiBHZXN0aW9uZSBNb2RhbGl0w6AgUmVwb3J0XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTdWwgY2xpY2sgZGVsbCdIZWFkZXIgZGkgdW5hIGNvbG9ubmEgcXVlc3RvIG1ldG9kbyBzaSBvY2N1cGEgZGkgYXBwbGljYXJlIGwnb3JkaW5hbWVudG8gc3VjY2Vzc2l2byBlIGRpIG5vdGlmaWNhcmUgY29uICoqZW1pdFNlYXJjaFJlcXVlc3QqKlxyXG4gICAgICogaWwgYmlzb2dubyBkaSBhZ2dpb3JuYXJlIGkgZGF0aSBkYSBwYXJ0ZSBkZWwgY29tcG9uZW50ZSBjaGUgdXRpbGl6emEgbGEgdGFiZWxsYVxyXG4gICAgICpcclxuICAgICAqIFV0aWxpenphdG8gc29sbyBpbiBtb2RhbGl0w6AgUkVwb3J0XHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtSZXBvcnRDb2x1bW59IGNsbSBDb2xvbm5hIGRlbCByZXBvcnQgcGVyIGN1aSBvcmRpbmFyZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc2V0dXBOZXh0T3JkZXJBbmRTZWFyY2goY2xtOiBSZXBvcnRDb2x1bW4pIHtcclxuICAgICAgICBpZiAoISh0aGlzLlZpZXcgaW5zdGFuY2VvZiBSZXBvcnREZWZpbml0aW9uKSkge1xyXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdWaWV3IGRpdmVyc2EgZGEgcmVwb3J0ZGVmaW5pdGlvbiBlbnRyYXRhIG5lbCBtZXRvZG8gc2V0dXBOZXh0T3JkZXJBbmRTZWFyY2gnKTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbGV0IG9yZGVyTmV4dCA9IHsgTk9ORTogJ0RFU0MnLCBERVNDOiAnQVNDJywgQVNDOiBudWxsIH07XHJcbiAgICAgICAgbGV0IG5leHRPcmRlciA9IG9yZGVyTmV4dFtjbG0ub3JkZXIgfHwgJ05PTkUnXTtcclxuICAgICAgICBjbG0ub3JkZXIgPSBuZXh0T3JkZXI7XHJcblxyXG4gICAgICAgIGxldCBvcmRlcjogUmVwb3J0T3JkZXI7XHJcbiAgICAgICAgbGV0IGNsbU9yZGVyID0gdGhpcy5WaWV3Lm9yZGVycyA/IHRoaXMuVmlldy5vcmRlcnMuZmlsdGVyKHQgPT4gdC5jb2x1bW4gPT0gY2xtLmlkKSA6IFtdO1xyXG4gICAgICAgIGlmIChjbG1PcmRlci5sZW5ndGggPT0gMCAmJiBjbG0ub3JkZXIpIHtcclxuICAgICAgICAgICAgb3JkZXIgPSBuZXcgUmVwb3J0T3JkZXIoKTtcclxuICAgICAgICAgICAgb3JkZXIuY29sdW1uID0gY2xtLmlkO1xyXG4gICAgICAgICAgICBvcmRlci5vcmRlciA9IGNsbS5vcmRlcjtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLlZpZXcub3JkZXJzKVxyXG4gICAgICAgICAgICAgICAgdGhpcy5WaWV3Lm9yZGVycyA9IFtdO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5WaWV3Lm9yZGVycy5wdXNoKG9yZGVyKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAoY2xtT3JkZXIubGVuZ3RoID09IDEpIHtcclxuICAgICAgICAgICAgLy8gUmltdW92byBsJ29yZGluYW1lbnRvIG8gYWdnaW9ybm8gcXVlbGxvIGdpw6AgZXNpc3RlbnRlXHJcbiAgICAgICAgICAgIGlmKCFjbG0ub3JkZXIpXHJcbiAgICAgICAgICAgICAgICBjbG1PcmRlciA9IFtdO1xyXG4gICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICBjbG1PcmRlclswXS5vcmRlciA9IGNsbS5vcmRlcjtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0ltcG9zc2liaWxlIHNldHRhcmUgb3JkaW5hbWVudG8uIENvbG9ubmEgJyArIGNsbS5pZCArICcgZGlyZXR0aXZlIGRpIG9yZGluYW1lbnRvICcgKyBjbG1PcmRlci5sZW5ndGggKyAnIG9yZGluYW1lbnRvIHNjZWx0byAnICsgY2xtLm9yZGVyKTtcclxuXHJcbiAgICAgICAgLy8gRG9wbyBhdmVyIGFnZ2lvcm5hdG8gbCdvcmRpbmFtZW50byByaWxhbmNpbyBsYSByaWNlcmNhXHJcbiAgICAgICAgdGhpcy5lbWl0U2VhcmNoUmVxdWVzdChmYWxzZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBNZXRvZG8gY2hlIHNpIG9jY3VwYSBkaSBnZXN0aXJlIGxhIGdyYWZpY2EgZGVsbGEgdGFiZWxsYSBpbiBiYXNlIGFsbGUgaW5mb3JtYXppb25pIGRpIG9yZGluYW1lbnRvIGNvbG9ubmUgZSBwYWdpbmF6aW9uZSBjb250ZW51dGkgbmVsIG1vZGVsbG9cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSByZXZpZXdSZXBvcnRCaW5kaW5ncygpIHtcclxuICAgICAgICBpZiAoISh0aGlzLlZpZXcgaW5zdGFuY2VvZiBSZXBvcnREZWZpbml0aW9uKSkge1xyXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdWaWV3IGRpdmVyc2EgZGEgcmVwb3J0ZGVmaW5pdGlvbiBlbnRyYXRhIG5lbCBtZXRvZG8gcmV2aWV3UmVwb3J0QmluZGluZ3MnKTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gQWxsaW5lbyBsZSBpbmZvcm1hemlvbmkgc3UgZXZlbnR1YWxpIG9yZGluYW1lbnRpIGZhdHRpIHByZWNlZGVudGVtZW50ZVxyXG4gICAgICAgIGlmICh0aGlzLlZpZXcub3JkZXJzICYmIHRoaXMuVmlldy5vcmRlcnMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICB0aGlzLlZpZXcub3JkZXJzLmZvckVhY2godCA9PiB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLlJlcG9ydFZhbHVlcy5jb2x1bW5zLmZpbHRlcihjID0+IGMuaWQgPT0gdC5jb2x1bW4pWzBdLm9yZGVyID0gdC5vcmRlcjtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBSZWN1cGVybyBpbCBjb3VudCBwcmVjZWRlbnRlIHNlIHNlcnZlXHJcbiAgICAgICAgaWYgKHRoaXMuUmVwb3J0VmFsdWVzLmNvdW50ICE9IC0yKVxyXG4gICAgICAgICAgICB0aGlzLnByZXZpb3VzQ291bnQgPSB0aGlzLlJlcG9ydFZhbHVlcy5jb3VudDtcclxuICAgICAgICBlbHNlIGlmICh0aGlzLlJlcG9ydFZhbHVlcy5jb3VudCA9PSAtMilcclxuICAgICAgICAgICAgdGhpcy5SZXBvcnRWYWx1ZXMuY291bnQgPSB0aGlzLnByZXZpb3VzQ291bnQ7XHJcblxyXG4gICAgICAgIGxldCBpcHAgPSAodGhpcy5WaWV3Lml0ZW1zcGVycGFnZW92ZXJyaWRlIHx8IDE1KTtcclxuICAgICAgICB0aGlzLlZpZXcucGFnZXMgPSBNYXRoLmNlaWwodGhpcy5SZXBvcnRWYWx1ZXMuY291bnQgLyBpcHApO1xyXG4gICAgICAgIHRoaXMuYXJyYXlQdWxzYW50aSA9IHRoaXMuZ2V0UGFnZXNBcnJheSg2LCB0aGlzLlZpZXcucGFnZSwgdGhpcy5WaWV3LnBhZ2VzKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyAjZW5kcmVnaW9uXHJcblxyXG4gICAgLy8gI3JlZ2lvbiBHZXN0aW9uZSB1cGRhdGUgYXV0b21hdGljb1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogTWV0b2RvIGNoZSBnZXN0aXNjZSBsYSBtb2RpZmljYSBkZWwgdGVtcG8gc3BlY2lmaWNhdG8gcGVyIGwnYWdnaW9ybmFtZW50byBhdXRvbWF0aWNvXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBhdXRvVXBkYXRlQ2hhbmdlZCgpIHtcclxuICAgICAgICBpZiAoIS9eWzEtOV1cXGQqJC8udGVzdCh0aGlzLnNlY29uZHMpKVxyXG4gICAgICAgICAgICB0aGlzLnNlY29uZHMgPSAnMTAnO1xyXG5cclxuICAgICAgICBsZXQgc2Vjb25kc0luTXMgPSBwYXJzZUludCh0aGlzLnNlY29uZHMsIG51bGwpICogMTAwMDtcclxuXHJcbiAgICAgICAgaWYgKHRoaXMuYXV0b1VwZGF0ZSlcclxuICAgICAgICAgICAgdGhpcy51cGRhdGVUaW1lciA9IHNldEludGVydmFsKCgpID0+IHsgdGhpcy5lbWl0U2VhcmNoUmVxdWVzdChmYWxzZSk7IH0sIHNlY29uZHNJbk1zKTtcclxuICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwodGhpcy51cGRhdGVUaW1lcik7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gI2VuZHJlZ2lvblxyXG5cclxuICAgIC8vICNyZWdpb24gR2VzdGlvbmUgdGFiZWxsYSBkaW5hbWljYVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTWV0b2RvIGNoaWFtYXRvIGRhbCBjbGljayBzdSB1bmEgZGVsbGUgY29sb25uZSBnZW5lcmF0ZSBkYWxsJ0lucHV0ICoqRHluYW1pY09wZXJhdGlvbnMqKlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7YW55fSBpdGVtIEwnb2dnZXR0byBzdSBjdWkgdmEgZWZmZXR0dWF0YSBsJ29wZXJhemlvbmVcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcGlkIENvZGljZSBpZGVudGlmaWNhdGl2byBkZWxsJ29wZXJhemlvbmUgZGEgZWZmZXR0dWFyc2lcclxuICAgICAqL1xyXG4gICAgcHVibGljIGR5bmFtaWNPcGVyYXRpb24oaXRlbTogYW55LCBvcGlkOiBzdHJpbmcpIHtcclxuICAgICAgICB0aGlzLm9uRHluYW1pY09wZXJhdGlvbi5lbWl0KHsgaWQ6IG9waWQsIGl0ZW06IGl0ZW0gfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBPdHRpZW5lIGlsIGNvbnRlbnV0byBkZWxsJ0VzVGQgZGEgdXRpbGl6emFyZSBwZXIgbGEgY29sb25uYSBzcGVjaWZpY2F0YVxyXG4gICAgICogXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gY29sdW1uIENvbG9ubmEgcGVyIGN1aSBjZXJjYXJlIGxhIGNlbGxhXHJcbiAgICAgKiBcclxuICAgICAqIEByZXR1cm5zIHtUZW1wbGF0ZVJlZjxhbnk+fSBUZW1wbGF0ZSBkYSB1c2FyZSBwZXIgbGEgY29sb25uYVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZmluZEVzVGQoY29sdW1uOiBzdHJpbmcpOiBUZW1wbGF0ZVJlZjxhbnk+IHtcclxuICAgICAgICB2YXIgRXNUZCA9IHRoaXMuRXNUZHNEaXJlY3RpdmUuZmluZCgoaXRlbSkgPT4gaXRlbS50ZCA9PT0gY29sdW1uKTtcclxuICAgICAgICByZXR1cm4gRXNUZCA/IEVzVGQuVGVtcGxhdGUgOiBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTWV0b2RvIGRpIHN1cHBvcnRvIGFsbGEgY3JlYXppb25lIGRpIHVuIHJvdXRlciBsaW5rIHBhcmFtZXRyaXp6YXRvIGFsbCdvZ2dldHRvIGNvcnJlbnRlIHV0aWxpenphdG8gbmVsbGEgbW9kYWxpdMOgIGRpbmFtaWNhXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHBhdGggUGF0aCBzdSBjdWkgbmF2aWdhcmUgY29uIGV2ZW50dWFsaSBwYXJhbWV0cmkgcmlmZXJpdGkgYWxsJ29nZ2V0dG8gY290bmVzdHVhbGUgY29tZSB7MH0sIHsxfSwgZWNjLi4uXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBwYXJhbWV0ZXJQcm9wcyBMaXN0YSBwb3NpemlvbmFsZSBkZWxsZSBwcm9wcmlldMOgIGEgY3VpIGJpbmRhcmUgaSByaWZlcmltZW50aSBkZWwgcGFyYW1ldHJvICoqcGF0aCoqXHJcbiAgICAgKiBFcy4gSWwgdmFsb3JlIGRlbGEgcHJvcHJpZXTDoCBhbGwnaW5kaWNlIDAgZGkgcXVlc3RvIGFycmF5IHZlcnLDoCBzb3N0aXR1aXRhIGFsIHZhbG9yZSB7MH0gZGVsIHBhcmFtZXRybyAqKnBhdGgqKlxyXG4gICAgICogQHBhcmFtIHtHZW5lcmljSXRlbX0gaXRlbSBPZ2dldHRvIGdlbmVyaWNvIGNvbGxlZ2F0byBhIHF1ZXN0byBjb250ZXN0b1xyXG4gICAgICpcclxuICAgICAqIEByZXR1cm5zIHthbnl9IFJvdXRlciBsaW5rIGdlbmVyYXRvIGluIGJhc2UgYWwgcGFyYW1ldHJpXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBnZW5lcmF0ZVJvdXRlckxpbmsocGF0aDogc3RyaW5nLCBwYXJhbWV0ZXJQcm9wczogc3RyaW5nW10sIGl0ZW06IEdlbmVyaWNJdGVtKTogYW55IHtcclxuICAgICAgICBpZiAodGhpcy5EeW5hbWljVGFibGVSb3V0ZXJMaW5rQ2FjaGVbaXRlbS5faGFzaCArIHBhdGhdKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLkR5bmFtaWNUYWJsZVJvdXRlckxpbmtDYWNoZVtpdGVtLl9oYXNoICsgcGF0aF07XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgbGV0IGxpbmsgPSB0aGlzLmdldFJvdXRlckxpbmsocGF0aCwgcGFyYW1ldGVyUHJvcHMsIGl0ZW0pO1xyXG4gICAgICAgICAgICB0aGlzLkR5bmFtaWNUYWJsZVJvdXRlckxpbmtDYWNoZVtpdGVtLl9oYXNoICsgcGF0aF0gPSBsaW5rO1xyXG4gICAgICAgICAgICByZXR1cm4gbGluaztcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhIHVuIHJvdXRlciBsaW5rXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHBhdGggUGF0aCBzdSBjdWkgbmF2aWdhcmUgY29uIGV2ZW50dWFsaSBwYXJhbWV0cmkgcmlmZXJpdGkgYWxsJ29nZ2V0dG8gY290bmVzdHVhbGUgY29tZSB7MH0sIHsxfSwgZWNjLi4uXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBwYXJzIExpc3RhIHBvc2l6aW9uYWxlIGRlbGxlIHByb3ByaWV0w6AgYSBjdWkgYmluZGFyZSBpIHJpZmVyaW1lbnRpIGRlbCBwYXJhbWV0cm8gKipwYXRoKipcclxuICAgICAqIEVzLiBJbCB2YWxvcmUgZGVsYSBwcm9wcmlldMOgIGFsbCdpbmRpY2UgMCBkaSBxdWVzdG8gYXJyYXkgdmVycsOgIHNvc3RpdHVpdGEgYWwgdmFsb3JlIHswfSBkZWwgcGFyYW1ldHJvICoqcGF0aCoqXHJcbiAgICAgKiBAcGFyYW0ge0dlbmVyaWNJdGVtfSBpdGVtIE9nZ2V0dG8gZ2VuZXJpY28gY29sbGVnYXRvIGEgcXVlc3RvIGNvbnRlc3RvXHJcbiAgICAgKlxyXG4gICAgICogQHJldHVybnMge2FueX0gUm91dGVyIGxpbmsgZ2VuZXJhdG8gaW4gYmFzZSBhbCBwYXJhbWV0cmlcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBnZXRSb3V0ZXJMaW5rKHBhdGg6IHN0cmluZywgcGFyczogc3RyaW5nW10sIGl0ZW06IEdlbmVyaWNJdGVtKTogYW55IHtcclxuXHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwYXJzLmxlbmd0aDsgaSsrKVxyXG4gICAgICAgICAgICBwYXRoID0gcGF0aC5yZXBsYWNlKCd7JyArIGkgKyAnfScsIGl0ZW0ucHJvcGVydGllc1twYXJzW2ldXSk7XHJcblxyXG4gICAgICAgIHBhdGggPSBwYXRoLnJlcGxhY2UoLycvZywgJ1wiJykucmVwbGFjZSgvIC9nLCAnJyk7XHJcbiAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UocGF0aCk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gI2VuZHJlZ2lvblxyXG5cclxuICAgIC8vICNyZWdpb24gUGFnaW5hemlvbmUgaW4gbW9kYWxpdMOgIEFycmF5XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBFcXVpdmFsZW50ZSBkZWwgbWV0b2RvICoqYWRkVG9QYWdlKiogcmlhZGF0dGF0byBwZXIgbGEgbW9kYWxpdMOgIGFycmF5XHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHBhZ2UgTnVtZXJvIGRpIHBhZ2luZSBkYSBhZ2dpdW5nZXJlIChvIHNvdHRyYXJyZSwgc2UgbmVnYXRpdm8pIGFsbGEgcGFnaW5hIGF0dHVhbGVcclxuICAgICAqL1xyXG4gICAgcHVibGljIGFycmF5QWRkVG9QYWdlKHBhZ2U6IG51bWJlcikge1xyXG4gICAgICAgIHRoaXMuYXJyYXlHb1RvUGFnZSh0aGlzLmFycmF5bW9kZVBhZ2UgKyBwYWdlKVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRXF1aXZhbGVudGUgZGVsIG1ldG9kbyAqKmdvVG9QYWdlKiogcmlhZGF0dGF0byBwZXIgbGEgbW9kYWxpdMOgIGFycmF5XHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHBhZ2UgUGFnaW5hIGEgY3VpIG5hdmlnYXJlXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBhcnJheUdvVG9QYWdlKHBhZ2U6IG51bWJlcikge1xyXG4gICAgICAgIGlmIChwYWdlID09PSAwIHx8IHBhZ2UgPiB0aGlzLmFycmF5bW9kZVBhZ2VzKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgdGhpcy5hcnJheW1vZGVQYWdlID0gcGFnZTtcclxuXHJcbiAgICAgICAgLy8gUmlmb3J6byBpbCB3cml0ZXZhbHVlIGluIG1vZG8gY2hlIGlsIGNvZGljZSBwYXNzaSBkYWxsYSBnZXN0aW9uZSBjb21lIHNlIGZvc3NlIGZhdHRhIHJpcGFydGlyZSB1bmEgcmljZXJjYVxyXG4gICAgICAgIHRoaXMuaW50ZXJuYWxXcml0ZVZhbHVlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBNZXRvZG8gcGVyIGVmZmV0dHVhcmUgaWwgcmVmcmVzaCBkZWxsYSBwYWdpbmF6aW9uZSBzdWwgY2FtYmlhbWVudG8gZGVnbGkgb2dnZXR0aSBkYSB2aXN1YWxpenphcmUgaW4gdW5hIHNpbmdvbGEgcGFnaW5hLlxyXG4gICAgICpcclxuICAgICAqIFZhbGUgc29sbyBwZXIgbGEgbW9kYWxpdMOgIEFycmF5XHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHBhZ2VTaXplIERpbWVuc2lvbmUgZGVsbGEgcGFnaW5hXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyByZWZyZXNoUGFnaW5nKHBhZ2VTaXplOiBudW1iZXIpIHtcclxuICAgICAgICB0aGlzLkFycmF5bW9kZUl0ZW1zUGVyUGFnZSA9IHBhZ2VTaXplO1xyXG4gICAgICAgIHRoaXMuYXJyYXltb2RlUGFnZXMgPSBNYXRoLmNlaWwoKHRoaXMuVmlldyBhcyBhbnlbXSkubGVuZ3RoIC8gdGhpcy5BcnJheW1vZGVJdGVtc1BlclBhZ2UpO1xyXG4gICAgICAgIHRoaXMuYXJyYXltb2RlUGFnZSA9IDE7XHJcblxyXG4gICAgICAgIC8vIFJpZm9yem8gaWwgd3JpdGV2YWx1ZSBpbiBtb2RvIGNoZSBpbCBjb2RpY2UgcGFzc2kgZGFsbGEgZ2VzdGlvbmUgY29tZSBzZSBmb3NzZSBmYXR0YSByaXBhcnRpcmUgdW5hIHJpY2VyY2FcclxuICAgICAgICB0aGlzLmludGVybmFsV3JpdGVWYWx1ZSgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2VuZXJhIGxlIGluZm9ybWF6aW9uaSBkaSBwYWdpbmF6aW9uZSBlIHRhZ2xpYSBsYSBWaWV3IGluIG1vZGFsaXTDoCBhcnJheSBwZXIgbW9zdHJhcmUgc29sbyBnbGkgb2dnZXR0aSBkZWxsYSBwYWdpbmEgc3BlY2lmaWNhdGFcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBhZGFwdFZpZXdUb1BhZ2luZygpIHtcclxuICAgICAgICBsZXQgdG1wSXRlbXM6IGFueVtdID0gW107XHJcblxyXG4gICAgICAgIC8vIFNlIGhvIHVuYSBzZWFyY2ggdmlldyBsJ2FycmF5IHB1bHNhbnRpIHZpZW5lIGNhbGNvbGF0byBkYSBsZWksIG5vbiBkZXZvIHByZW5kZXJlIHF1ZWxsbyBkZWxsYSBtb2RhbGl0w6AgYXJyYXlcclxuICAgICAgICBpZighdGhpcy5TZWFyY2hWaWV3KVxyXG4gICAgICAgICAgICB0aGlzLmFycmF5UHVsc2FudGkgPSB0aGlzLmdldFBhZ2VzQXJyYXkoNiwgdGhpcy5hcnJheW1vZGVQYWdlLCB0aGlzLmFycmF5bW9kZVBhZ2VzKTtcclxuXHJcbiAgICAgICAgLy8gUG9pIHBlciB0dXR0aSBpIHZhbG9yaSBkb3BvIGNvbXByZXNpIGZyYSBsYSBwYWdpbmEgLSAxIGUgbGEgcGFnaW5hXHJcbiAgICAgICAgZm9yIChsZXQgaSA9ICgodGhpcy5hcnJheW1vZGVQYWdlIC0gMSkgKiB0aGlzLkFycmF5bW9kZUl0ZW1zUGVyUGFnZSk7IGkgPCB0aGlzLmFycmF5bW9kZVBhZ2UgKiB0aGlzLkFycmF5bW9kZUl0ZW1zUGVyUGFnZTsgaSsrKSB7XHJcbiAgICAgICAgICAgIGlmIChpIDw9ICh0aGlzLlZpZXcgYXMgYW55W10pLmxlbmd0aCAtIDEpXHJcbiAgICAgICAgICAgICAgICB0bXBJdGVtcy5wdXNoKCh0aGlzLlZpZXcgYXMgYW55W10pW2ldKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRtcEl0ZW1zO1xyXG4gICAgfVxyXG5cclxuICAgIC8vICNlbmRyZWdpb25cclxuXHJcbiAgICAvLyAjcmVnaW9uIEdlc3Rpb25lIGNsaWNrIHN1bGxlIGNlbGxlIGRpbmFtaWNoZSBlIG9wemlvbmkgbmVsIENvcm5lciBNZW51XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXN0b3JlIGRlaSBjbGljayBzdWxsZSBjZWxsZSBwZXIgbGUgcXVhbGkgZXJhIGltcG9zdGF0YSB1bmEgYXppb25lIGN1c3RvbSBkYSAqKkN1c3RvbUNlbGxBY3Rpb25zT24qKlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIE5vbWUgZGVsbGEgY2VsbGEgc3UgY3VpIHNpIMOoIGZhdHRvIGNsaWNrXHJcbiAgICAgKiBAcGFyYW0ge2FueX0gbW9kZWwgTW9kZWxsbyByZWxhdGl2byBhbGxhIGNlbGxhIGNsaWNjYXRhXHJcbiAgICAgKlxyXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59ICoqdHJ1ZSoqIHNlIGlsIGNsaWNrIMOoIHN0YXRvIGZhdHRvIHN1IHVuYSBjZWxsYSBjbGljY2FiaWxlLCAqKmZhbHNlKiogYWx0cmltZW50aVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgY2VsbENsaWNrZWQobmFtZTogc3RyaW5nLCBtb2RlbDogYW55KTogYm9vbGVhbiB7XHJcbiAgICAgICAgaWYgKHRoaXMuVXNlQ3VzdG9tQ2VsbEFjdGlvbnMgJiYgdGhpcy5DdXN0b21DZWxsQWN0aW9uc09uLnNwbGl0KCckJykuaW5kZXhPZihuYW1lKSAhPSAtMSkge1xyXG4gICAgICAgICAgICB0aGlzLm9uQ2VsbENsaWNrLmVtaXQoeyBjb2x1bW46IG5hbWUsIG1vZGVsOiBtb2RlbCB9KTtcclxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXN0aW9uZSBkZWkgY2xpY2sgc3VsbGUgb3B6aW9uaSBkZWwgbWVuw7kgY29udGVzdHVhbGUgaW4gYWx0byBhIGRlc3RyYSBnZW5lcmF0byBkYWxsJ0lucHV0ICoqQ29ybmVyTWVudU9wdGlvbnMqKlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBjb3JuZXJpZCBDb2RpY2UgZGVsbCdvcGVyYXppb25lIHNlbGV6aW9uYXRhXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBjb3JuZXJBY3Rpb25DbGlja2VkKGNvcm5lcmlkOiBzdHJpbmcpIHtcclxuICAgICAgICB0aGlzLm9uQ29ybmVyQWN0aW9uLmVtaXQoeyBpZDogY29ybmVyaWQsIGVzdGFibGU6IHRoaXMgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gI2VuZHJlZ2lvblxyXG5cclxuICAgIC8vICNyZWdpb24gTWV0b2RpIGRpIHV0aWxpdMOgXHJcblxyXG4gICAgLyoqIEhlbHBlciBjaGUgaWRlbnRpZmljYSBzZSBpbCB0ZCBhdHR1YWxlIMOoIGRpIHRpcG8gKipFc1RkKiouIEluIGNhc28gY29udHJhcmlvIMOoIGRhIGNvbnNpZGVyYXJzaSAqKkVzVGREaXJlY3RpdmUqKiAqL1xyXG4gICAgcHJpdmF0ZSBpc0VzVGQodGQ6IGFueSk6IHRkIGlzIEVzVGQge1xyXG4gICAgICAgIHJldHVybiAhdGQuX2RpcmVjdGl2ZTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogIEhlbHBlciBjaGUgaWRlbnRpZmljYSBzZSBpbCB0aCBhdHR1YWxlIMOoIGRpIHRpcG8gKipFc1RoKiouIEluIGNhc28gY29udHJhcmlvIMOoIGRhIGNvbnNpZGVyYXJzaSAqKkVzVGhEaXJlY3RpdmUqKiAqL1xyXG4gICAgcHJpdmF0ZSBpc0VzVGgodGg6IGFueSk6IHRoIGlzIEVzVGgge1xyXG4gICAgICAgIHJldHVybiAhdGguX2RpcmVjdGl2ZTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogSW1wb3N0YXppb25lIG1vZGFsaXTDoCBkZWxsJ0VzVGFibGUgKi9cclxuICAgIHByaXZhdGUgc2V0TW9kZShtb2RlOiAnYXJyYXknIHwgJ3ZpZXcnIHwgJ3JlcG9ydCcpIHtcclxuICAgICAgICB0aGlzLnZpZXdNb2RlID0gbW9kZSA9PSAndmlldyc7XHJcbiAgICAgICAgdGhpcy5hcnJheU1vZGUgPSBtb2RlID09ICdhcnJheSc7XHJcbiAgICAgICAgdGhpcy5yZXBvcnRNb2RlID0gbW9kZSA9PSAncmVwb3J0JztcclxuXHJcbiAgICAgICAgaWYgKHRoaXMucmVwb3J0TW9kZSkge1xyXG4gICAgICAgICAgICAvLyBJbiBtb2RhbGl0w6AgcmVwb3J0IGhvIGRpIHNpY3VybyBxdWVzdGUgZHVlXHJcbiAgICAgICAgICAgIHRoaXMuWExTWEV4cG9ydCA9IHRydWU7XHJcbiAgICAgICAgICAgIHRoaXMuQ1NWRXhwb3J0ID0gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSGVscGVyIHBlciBlZmZldHR1YXJlIGNoaWFtYXRlIGludGVybmUgZGkgYWxsaW5lYW1lbnRvIGFsbGEgZnVuemlvbmUgKip3cml0ZVZhbHVlKiosIFxyXG4gICAgICogaW1wb3N0YW5kbyBwcmltYSAqKmludGVybmFsV3JpdGVDYWxsKiogaW4gbW9kbyBkYSBub24gZWZmZXR0dWFyZSBvcGVyYXppb25pIGludXRpbGlcclxuICAgICAqL1xyXG4gICAgIHByaXZhdGUgaW50ZXJuYWxXcml0ZVZhbHVlKCkge1xyXG4gICAgICAgIHRoaXMuaW50ZXJuYWxXcml0ZUNhbGwgPSB0cnVlO1xyXG4gICAgICAgIHRoaXMud3JpdGVWYWx1ZSh0aGlzLlZpZXcpO1xyXG4gICAgICAgIHRoaXMuaW50ZXJuYWxXcml0ZUNhbGwgPSBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIERhdGUgbGUgaW5mb3JtYXppb25pIGRpIHBhZ2luYXppb25lIG90dGllbmUgbCdhcnJheSBkZWkgcHVsc2FudGlcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbWF4QnRucyBOdW1lcm8gbWFzc2ltbyBkaSBwdWxzYW50aSBkYSB2aXN1YWxpenphcmVcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBwYWdlIFBhZ2luYSBjb3JyZW50ZVxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGxhc3RQYWdlIFVsdGltYSBwYWdpbmEgZGlzcG9uaWJpbGVcclxuICAgICAqXHJcbiAgICAgKiBAcmV0dXJucyB7YW55W119IFBzZXVkby1hcnJheSBkaSBwdWxzYW50aSBhIGN1aSBjaSBzaSBwdcOyIGJpbmRhcmUgbGF0byBIVE1MXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZ2V0UGFnZXNBcnJheShtYXhCdG5zOiBudW1iZXIsIHBhZ2U6IG51bWJlciwgbGFzdFBhZ2U6IG51bWJlcik6IGFueVtdIHtcclxuICAgICAgICBsZXQgcmVzdWx0ID0gW107XHJcbiAgICAgICAgaWYgKGxhc3RQYWdlID09IC0xKVxyXG4gICAgICAgICAgICBsYXN0UGFnZSA9IHBhZ2UgKyAxO1xyXG5cclxuICAgICAgICBsZXQgbWluLCBtYXg7XHJcbiAgICAgICAgaWYgKGxhc3RQYWdlIDw9IG1heEJ0bnMpIHtcclxuICAgICAgICAgICAgbWluID0gMTtcclxuICAgICAgICAgICAgbWF4ID0gbGFzdFBhZ2UgLSAxO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIC8vIHRvbGdvIGxhIHBhZ2luYSBzZWxlY3RlZCDDqCBsJ3VsdGltYSBwYWdpbmEgY2hlIMOoIHF1ZWxsYSBkZWxsZSBwYWdpbmUgdG90YWxpXHJcbiAgICAgICAgICAgIGxldCByYW5nZU91dHNpZGUgPSAobWF4QnRucyAtIDIpIC8gMjtcclxuXHJcbiAgICAgICAgICAgIG1pbiA9IHBhZ2UgLSByYW5nZU91dHNpZGU7XHJcbiAgICAgICAgICAgIG1heCA9IHBhZ2UgKyByYW5nZU91dHNpZGU7XHJcblxyXG4gICAgICAgICAgICBpZiAobWluIDwgMSkge1xyXG4gICAgICAgICAgICAgICAgbWluID0gMTtcclxuICAgICAgICAgICAgICAgIG1heCA9IG1heEJ0bnMgLSAxO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1heCA+PSBsYXN0UGFnZSkge1xyXG4gICAgICAgICAgICAgICAgbWluID0gbGFzdFBhZ2UgLSBtYXhCdG5zICsgMTtcclxuICAgICAgICAgICAgICAgIG1heCA9IGxhc3RQYWdlIC0gMTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmVzdWx0LnB1c2goeyB2YWw6IDEsIGNzc0NsYXNzOiAoMSA9PT0gcGFnZSA/ICdidG4tbWFpbiBhcHAtd2hpdGUtdGV4dCcgOiAnYXBwLXdoaXRlLWJ1dHRvbicpIH0pO1xyXG5cclxuICAgICAgICBpZiAobWF4ID49IG1pbikge1xyXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gbWluOyBpIDw9IG1heDsgaSsrKVxyXG4gICAgICAgICAgICAgICAgaWYgKGkgIT09IDEpXHJcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goeyB2YWw6IGksIGNzc0NsYXNzOiAoaSA9PT0gcGFnZSA/ICdidG4tbWFpbiBhcHAtd2hpdGUtdGV4dCcgOiAnYXBwLXdoaXRlLWJ1dHRvbicpIH0pO1xyXG5cclxuICAgICAgICAgICAgcmVzdWx0LnB1c2goe1xyXG4gICAgICAgICAgICAgICAgdmFsOiBsYXN0UGFnZSxcclxuICAgICAgICAgICAgICAgIGNzc0NsYXNzOiAobGFzdFBhZ2UgPT09IHBhZ2UgPyAnYnRuLW1haW4gYXBwLXdoaXRlLXRleHQnIDogJ2FwcC13aGl0ZS1idXR0b24nKVxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENhbGNvbGEgbCdoYXNoIGRpIHVuIG9nZ2V0dG8gcXVhbHNpYXNpXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHthbnlbXX0gaXRlbXMgT2dnZXR0aSBwZXIgY3VpIGNhbGNvbGFyZSBsJ2hhc2hcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBjYWxjdWxhdGVIYXNoKGl0ZW1zOiBhbnlbXSkge1xyXG4gICAgICAgIGlmICghaXRlbXMpXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgLy8gU3VwcG9ydG8gYSBoYXNoIGR1cGxpY2F0aSBkaSBvZ2dldHRpIHVndWFsaVxyXG4gICAgICAgIGxldCB1c2VkSGFzaGVzQ2FjaGU6IHsgW2luZGV4OiBzdHJpbmddOiBudW1iZXIgfSA9IHt9O1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaXRlbXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgbGV0IGl0ZW0gPSBpdGVtc1tpXTtcclxuXHJcbiAgICAgICAgICAgIC8vIFByaW1hIGRpIGNhbGNvbGFyZSBsJ2hhc2ggcmltdW92byBsZSBwcm9wcmlldMOgIGludGVybmUgcHJpbWEgY2hlIG1pIHNjb21wZW5zaW5vIGkgY2FsY29saSBzdWNjZXNzaXZpXHJcbiAgICAgICAgICAgIGxldCB0bXAgPSBPYmplY3QuYXNzaWduKHt9LCBpdGVtc1tpXSk7XHJcbiAgICAgICAgICAgIGRlbGV0ZSB0bXAuX3NlbGVjdGVkO1xyXG4gICAgICAgICAgICBkZWxldGUgdG1wLl92aXNpYmxlO1xyXG4gICAgICAgICAgICBkZWxldGUgdG1wLl9oYXNoO1xyXG4gICAgICAgICAgICBsZXQgaGFzaCA9IHRoaXMuaGFzaEV4dHMuaGFzaE9iamVjdCh0bXApO1xyXG5cclxuICAgICAgICAgICAgdXNlZEhhc2hlc0NhY2hlW2hhc2hdID0gdXNlZEhhc2hlc0NhY2hlW2hhc2hdID8gdXNlZEhhc2hlc0NhY2hlW2hhc2hdICsgMSA6IDE7XHJcbiAgICAgICAgICAgIGl0ZW0uX2hhc2ggPSBoYXNoICsgKHVzZWRIYXNoZXNDYWNoZVtoYXNoXSA+IDEgPyBcIl9cIiArIHVzZWRIYXNoZXNDYWNoZVtoYXNoXSA6IFwiXCIpXHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTWV0b2RvIGV2ZW50dWFsbWVudGUgcmljaGlhbWFiaWxlIGFuY2hlIGRhbCBjb21wb25lbnRlIGVzdGVybm8gY2hlIHBlcm1ldHRlIGRpIGZvcnphcmUgdW4gcmVmcmVzaCBkZWxsYSB0YWJlbGxhXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBmb3JjZVJlZnJlc2goKSB7XHJcblxyXG4gICAgICAgIC8vIFNlIHNvbm8gaW4gbW9kYWxpdMOgIFZpZXcgdmllbmUgbWFudGVudXRvIGluIGF1dG9tYXRpY28gaWwgbnVtZXJvIGRpIHBhZ2luYSwgbWEgcGVyIGxhIG1vZGFsaXTDoCBhcnJheSBkZXZvIHByZW5kZXJlIGxlIGluZm8gZGkgcGFnaW5hemlvbmUgcHJpbWEgZSByaWFwcGxpY2FybGUgZG9wb1xyXG4gICAgICAgIGxldCBhcnJheVBhZ2U6IG51bWJlcjtcclxuICAgICAgICBsZXQgYXJyYXlJcHA6IG51bWJlcjtcclxuICAgICAgICBpZiAodGhpcy5hcnJheU1vZGUpIHtcclxuICAgICAgICAgICAgYXJyYXlQYWdlID0gdGhpcy5hcnJheW1vZGVQYWdlO1xyXG4gICAgICAgICAgICBhcnJheUlwcCA9IHRoaXMuQXJyYXltb2RlSXRlbXNQZXJQYWdlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy53cml0ZVZhbHVlKHRoaXMuVmlldyk7XHJcbiAgICAgICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5hcnJheU1vZGUpIHtcclxuICAgICAgICAgICAgdGhpcy5BcnJheW1vZGVJdGVtc1BlclBhZ2UgPSBhcnJheUlwcDtcclxuICAgICAgICAgICAgdGhpcy5hcnJheUdvVG9QYWdlKGFycmF5UGFnZSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vICNlbmRyZWdpb25cclxufSJdfQ==