@esfaenza/es-table 12.2.26 → 13.1.3

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 (89) hide show
  1. package/esfaenza-es-table.d.ts +1 -7
  2. package/esm2020/esfaenza-es-table.mjs +5 -0
  3. package/esm2020/lib/components/es-table/es_table.component.loc.mjs +41 -0
  4. package/esm2020/lib/components/es-table/es_table.component.mjs +1396 -0
  5. package/esm2020/lib/components/es-td/es_td.component.mjs +106 -0
  6. package/esm2020/lib/components/es-th/es_th.component.mjs +176 -0
  7. package/esm2020/lib/components/pager/table_pager.component.loc.mjs +27 -0
  8. package/esm2020/lib/components/pager/table_pager.component.mjs +118 -0
  9. package/esm2020/lib/core/handlers/classes/ColumnMetadataHandler.mjs +719 -0
  10. package/{esm2015/lib/core/handlers/classes/DynamicModeHandler.js → esm2020/lib/core/handlers/classes/DynamicModeHandler.mjs} +0 -0
  11. package/esm2020/lib/core/handlers/classes/ExportHandler.mjs +103 -0
  12. package/{esm2015/lib/core/handlers/classes/HierarchyModeHandler.js → esm2020/lib/core/handlers/classes/HierarchyModeHandler.mjs} +0 -0
  13. package/esm2020/lib/core/handlers/classes/ItemsHandler.mjs +129 -0
  14. package/{esm2015/lib/core/handlers/classes/ReportModeHandler.js → esm2020/lib/core/handlers/classes/ReportModeHandler.mjs} +0 -0
  15. package/esm2020/lib/core/handlers/classes/RowGroupingHandler.mjs +474 -0
  16. package/esm2020/lib/core/handlers/classes/SelectionHandler.mjs +525 -0
  17. package/esm2020/lib/core/handlers/classes/UtilitiesHandler.mjs +166 -0
  18. package/{esm2015/lib/core/handlers/index.js → esm2020/lib/core/handlers/index.mjs} +0 -0
  19. package/esm2020/lib/directives/es_td.directive.mjs +32 -0
  20. package/esm2020/lib/directives/es_th.directive.mjs +84 -0
  21. package/{esm2015/lib/domain/configuration/EsTableDefaultable.js → esm2020/lib/domain/configuration/EsTableDefaultable.mjs} +0 -0
  22. package/{esm2015/lib/domain/configuration/EsTableModuleConfig.js → esm2020/lib/domain/configuration/EsTableModuleConfig.mjs} +0 -0
  23. package/{esm2015/lib/domain/externals/classes/CornerMenuOption.js → esm2020/lib/domain/externals/classes/CornerMenuOption.mjs} +0 -0
  24. package/{esm2015/lib/domain/externals/classes/EsTableColumnsDefinition.js → esm2020/lib/domain/externals/classes/EsTableColumnsDefinition.mjs} +0 -0
  25. package/{esm2015/lib/domain/externals/classes/EsTableOperationDefinition.js → esm2020/lib/domain/externals/classes/EsTableOperationDefinition.mjs} +0 -0
  26. package/{esm2015/lib/domain/externals/classes/appsearch/AppOrdering.js → esm2020/lib/domain/externals/classes/appsearch/AppOrdering.mjs} +0 -0
  27. package/{esm2015/lib/domain/externals/classes/appsearch/AppSearch.js → esm2020/lib/domain/externals/classes/appsearch/AppSearch.mjs} +0 -0
  28. package/{esm2015/lib/domain/externals/classes/appsearch/GenericItem.js → esm2020/lib/domain/externals/classes/appsearch/GenericItem.mjs} +0 -0
  29. package/{esm2015/lib/domain/externals/classes/appsearch/Group.js → esm2020/lib/domain/externals/classes/appsearch/Group.mjs} +0 -0
  30. package/{esm2015/lib/domain/externals/classes/appsearch/GroupAggregation.js → esm2020/lib/domain/externals/classes/appsearch/GroupAggregation.mjs} +0 -0
  31. package/{esm2015/lib/domain/externals/classes/appsearch/GroupFilter.js → esm2020/lib/domain/externals/classes/appsearch/GroupFilter.mjs} +0 -0
  32. package/{esm2015/lib/domain/externals/classes/appsearch/GroupOrAggregation.js → esm2020/lib/domain/externals/classes/appsearch/GroupOrAggregation.mjs} +0 -0
  33. package/{esm2015/lib/domain/externals/classes/appsearch/ItemsSelection.js → esm2020/lib/domain/externals/classes/appsearch/ItemsSelection.mjs} +0 -0
  34. package/{esm2015/lib/domain/externals/classes/report/ReportColumn.js → esm2020/lib/domain/externals/classes/report/ReportColumn.mjs} +0 -0
  35. package/{esm2015/lib/domain/externals/classes/report/ReportDefinition.js → esm2020/lib/domain/externals/classes/report/ReportDefinition.mjs} +0 -0
  36. package/{esm2015/lib/domain/externals/classes/report/ReportOrder.js → esm2020/lib/domain/externals/classes/report/ReportOrder.mjs} +0 -0
  37. package/{esm2015/lib/domain/externals/classes/report/ReportParam.js → esm2020/lib/domain/externals/classes/report/ReportParam.mjs} +0 -0
  38. package/{esm2015/lib/domain/externals/classes/report/ReportResult.js → esm2020/lib/domain/externals/classes/report/ReportResult.mjs} +0 -0
  39. package/{esm2015/lib/domain/externals/classes/report/ReportRow.js → esm2020/lib/domain/externals/classes/report/ReportRow.mjs} +0 -0
  40. package/{esm2015/lib/domain/externals/index.js → esm2020/lib/domain/externals/index.mjs} +0 -0
  41. package/{esm2015/lib/domain/index.js → esm2020/lib/domain/index.mjs} +0 -0
  42. package/{esm2015/lib/domain/internals/classes/CacheTriptic.js → esm2020/lib/domain/internals/classes/CacheTriptic.mjs} +0 -0
  43. package/{esm2015/lib/domain/internals/classes/EsTableColumn.js → esm2020/lib/domain/internals/classes/EsTableColumn.mjs} +0 -0
  44. package/{esm2015/lib/domain/internals/classes/GroupPager.js → esm2020/lib/domain/internals/classes/GroupPager.mjs} +0 -0
  45. package/{esm2015/lib/domain/internals/classes/GroupRouteFragment.js → esm2020/lib/domain/internals/classes/GroupRouteFragment.mjs} +0 -0
  46. package/{esm2015/lib/domain/internals/classes/ThAggregation.js → esm2020/lib/domain/internals/classes/ThAggregation.mjs} +0 -0
  47. package/{esm2015/lib/domain/internals/classes/ThElement.js → esm2020/lib/domain/internals/classes/ThElement.mjs} +0 -0
  48. package/{esm2015/lib/domain/internals/index.js → esm2020/lib/domain/internals/index.mjs} +0 -0
  49. package/esm2020/lib/es-table.module.mjs +79 -0
  50. package/{esm2015/lib/tokens.js → esm2020/lib/tokens.mjs} +0 -0
  51. package/esm2020/public-api.mjs +14 -0
  52. package/fesm2015/{esfaenza-es-table.js → esfaenza-es-table.mjs} +622 -380
  53. package/fesm2015/esfaenza-es-table.mjs.map +1 -0
  54. package/fesm2020/esfaenza-es-table.mjs +4731 -0
  55. package/fesm2020/esfaenza-es-table.mjs.map +1 -0
  56. package/lib/components/es-table/es_table.component.d.ts +5 -2
  57. package/lib/components/es-table/es_table.component.loc.d.ts +3 -0
  58. package/lib/components/es-td/es_td.component.d.ts +3 -0
  59. package/lib/components/es-th/es_th.component.d.ts +3 -0
  60. package/lib/components/pager/table_pager.component.d.ts +3 -0
  61. package/lib/components/pager/table_pager.component.loc.d.ts +3 -0
  62. package/lib/core/handlers/classes/ExportHandler.d.ts +8 -2
  63. package/lib/core/handlers/classes/UtilitiesHandler.d.ts +3 -0
  64. package/lib/directives/es_td.directive.d.ts +3 -0
  65. package/lib/directives/es_th.directive.d.ts +3 -0
  66. package/lib/es-table.module.d.ts +21 -0
  67. package/package.json +30 -16
  68. package/public-api.d.ts +3 -0
  69. package/bundles/esfaenza-es-table.umd.js +0 -5075
  70. package/bundles/esfaenza-es-table.umd.js.map +0 -1
  71. package/esfaenza-es-table.metadata.json +0 -1
  72. package/esm2015/esfaenza-es-table.js +0 -12
  73. package/esm2015/lib/components/es-table/es_table.component.js +0 -1312
  74. package/esm2015/lib/components/es-table/es_table.component.loc.js +0 -36
  75. package/esm2015/lib/components/es-td/es_td.component.js +0 -106
  76. package/esm2015/lib/components/es-th/es_th.component.js +0 -160
  77. package/esm2015/lib/components/pager/table_pager.component.js +0 -106
  78. package/esm2015/lib/components/pager/table_pager.component.loc.js +0 -22
  79. package/esm2015/lib/core/handlers/classes/ColumnMetadataHandler.js +0 -712
  80. package/esm2015/lib/core/handlers/classes/ExportHandler.js +0 -43
  81. package/esm2015/lib/core/handlers/classes/ItemsHandler.js +0 -130
  82. package/esm2015/lib/core/handlers/classes/RowGroupingHandler.js +0 -475
  83. package/esm2015/lib/core/handlers/classes/SelectionHandler.js +0 -527
  84. package/esm2015/lib/core/handlers/classes/UtilitiesHandler.js +0 -169
  85. package/esm2015/lib/directives/es_td.directive.js +0 -29
  86. package/esm2015/lib/directives/es_th.directive.js +0 -69
  87. package/esm2015/lib/es-table.module.js +0 -52
  88. package/esm2015/public-api.js +0 -11
  89. package/fesm2015/esfaenza-es-table.js.map +0 -1
@@ -0,0 +1,719 @@
1
+ // Modelli
2
+ import { AppOrdering, EsTableColumn } from "../../../domain";
3
+ import { moveItemInArray } from "@angular/cdk/drag-drop";
4
+ /** Classe che gestisce tutte le informaizoni relative alle colonne: visibilità, posizione, stato di pin/unpin, ecc ecc... */
5
+ export class ColumnMetadataHandler {
6
+ /** @ignore Costruttore*/
7
+ constructor(est, utilities, utiExts, prefService, rgH) {
8
+ this.est = est;
9
+ this.utilities = utilities;
10
+ this.utiExts = utiExts;
11
+ this.prefService = prefService;
12
+ this.rgH = rgH;
13
+ }
14
+ /**
15
+ * Metodo che gestisce il cambio di Ordinamento di una colonna
16
+ *
17
+ * @param {string} id ID della colonna il cui oridnamento è cambiato
18
+ * @param {'DESC' | 'ASC'} order Nuovo ordine selezionato per la colonna
19
+ */
20
+ handleTHOrderChange(id, order) {
21
+ let orders = this.est.viewMode ? this.est.View.orders : this.est.arrayOrders;
22
+ let orderToAdd = true;
23
+ let orderToRemove = null;
24
+ // Se per qualche motivo il costruttore non è passato (cache tarpate o simila) fixo
25
+ if (!orders && this.est.viewMode)
26
+ this.est.View.orders = [];
27
+ else if (!orders && this.est.arrayMode)
28
+ this.est.arrayOrders = [];
29
+ for (let i = 0; i < orders.length; i++) {
30
+ let t = orders[i];
31
+ if (t.id == id) {
32
+ if (order) {
33
+ t.order = order;
34
+ orderToAdd = false;
35
+ }
36
+ else
37
+ orderToRemove = i;
38
+ }
39
+ }
40
+ if (orderToRemove != null) {
41
+ orders.splice(orderToRemove, 1);
42
+ }
43
+ else if (orderToAdd) {
44
+ if (this.est.MultipleOrderingDirectives)
45
+ orders.push(new AppOrdering(id, order));
46
+ else {
47
+ if (this.est.viewMode)
48
+ this.est.View.orders = [new AppOrdering(id, order)];
49
+ else if (this.est.arrayMode)
50
+ this.est.arrayOrders = [new AppOrdering(id, order)];
51
+ }
52
+ }
53
+ this.est.onOrderChanged.emit({ id, order });
54
+ if (this.est.viewMode) {
55
+ if (this.est.groupSearchRequestsCache.length > 0)
56
+ this.rgH.emitRowGroupingSearches(id, orders);
57
+ else
58
+ this.est.emitSearchRequest(false);
59
+ }
60
+ else if (this.est.arrayMode)
61
+ this.est.internalWriteValue();
62
+ }
63
+ /**
64
+ * Partendo dagli **EsThs** estrappolo la lista di **EsTableColumn** che questa tabella dovrà eventualmente gestire per Visibilità e Ordine
65
+ *
66
+ * Costo: 1 scan EsThs
67
+ *
68
+ * @param {EsTh[] | EsThDirective[]} ths Colonne della tabella
69
+ */
70
+ reviewColumnsList(ths) {
71
+ this.est.TMPColumnsList = [];
72
+ if (ths.length == 0)
73
+ return;
74
+ // Appena il contentChildren è valorizzato scorro tutti gli header
75
+ for (let i = 0; i < ths.length; i++) {
76
+ let th = ths[i];
77
+ if (this.utilities.isEsTh(th)) {
78
+ // Se non ho un id il th è considerato inerte
79
+ if (!th.ID)
80
+ continue;
81
+ th.OrderBy = this.est.OrderByColumn;
82
+ // Salvo le informazioni dell'header per far parte della lista da cui scegliere quali colonne visualizzare/nascondere
83
+ // Di default la visibilità è quella impostata nel componente
84
+ if (this.est.HiddenColumns || th.Visible)
85
+ this.est.TMPColumnsList.push(new EsTableColumn(th.ID, th.Description, th.Visible, th.Fixed));
86
+ }
87
+ else {
88
+ let column = th.th;
89
+ // Se non ho un id il th è considerato inerte
90
+ if (!column)
91
+ continue;
92
+ // Salvo le informazioni dell'header per far parte della lista da cui scegliere quali colonne visualizzare/nascondere
93
+ // Di default la visibilità è quella impostata nel componente
94
+ if ((this.est.HiddenColumns || th.thVisible) && th.thIf) {
95
+ let previouslyPinned = !this.est.ColumnsList || this.est.ColumnsList.length == 0 ? null : this.est.ColumnsList.find(t => t.id == column) || null;
96
+ let toAdd = new EsTableColumn(column, null, th.thVisible, (th.thFixed || th.thGroup), previouslyPinned == null ? th.thPinned : previouslyPinned.pinned, th.thPinnedWidth, th.Template, th._thParents);
97
+ if (previouslyPinned)
98
+ toAdd.prev_index = previouslyPinned.prev_index;
99
+ this.est.TMPColumnsList.push(toAdd);
100
+ }
101
+ }
102
+ }
103
+ this.est.ColumnsList = [];
104
+ this.est.TMPColumnsList.forEach(c => { this.est.ColumnsList.push(Object.assign({}, c)); });
105
+ }
106
+ /**
107
+ * Prende i th e i td in modalità diretive e li ordina in base a se ci sono colonne fixed o meno
108
+ */
109
+ moveFixedColumnsAtTheBeginning(ths, tds) {
110
+ let thsCache = {};
111
+ let fixeds = 0, pinneds = 0;
112
+ let columnsCache = {};
113
+ let columnsIndexCache = {};
114
+ // Creo la cache delle colonne
115
+ for (let coli = 0; coli < this.est.ColumnsList.length; coli++) {
116
+ let col = this.est.ColumnsList[coli];
117
+ columnsCache[col.id] = col;
118
+ // Anche per le columnslist sposto le pinnate o le fixed all'inizio
119
+ if (col.pinned) {
120
+ if (coli != pinneds)
121
+ this.utilities.arrayMove(this.est.ColumnsList, coli, pinneds);
122
+ pinneds++;
123
+ }
124
+ // Se una colonna è sia pinnata che fixata la considero unicamente pinnata
125
+ if (col.fixed && !col.pinned) {
126
+ if (coli != pinneds + fixeds)
127
+ this.utilities.arrayMove(ths, coli, pinneds + fixeds);
128
+ fixeds++;
129
+ }
130
+ }
131
+ pinneds = fixeds = 0;
132
+ // Sposto tutti gli header fixed o pinned all'inizio
133
+ for (let i = 0; i < ths.length; i++) {
134
+ let th = ths[i];
135
+ if (this.utilities.isEsTh(th)) {
136
+ thsCache[th.ID] = th;
137
+ if (th.Fixed) {
138
+ if (i != pinneds + fixeds)
139
+ this.utilities.arrayMove(ths, i, pinneds + fixeds);
140
+ fixeds++;
141
+ }
142
+ }
143
+ else {
144
+ thsCache[th.th] = th;
145
+ // Riassegno sempre per ripulire valori di partenza o per aggiornarli in caso di modifiche utente
146
+ th.thPinned = (!columnsCache[th.th] && th.thPinned) || (columnsCache[th.th] && columnsCache[th.th].pinned);
147
+ if (th.thPinned) {
148
+ if (i != pinneds)
149
+ this.utilities.arrayMove(ths, i, pinneds);
150
+ pinneds++;
151
+ }
152
+ //In questo caso sono informazioni statiche invece, non modificabili dall'utente, quindi non mi dò preoccupazioni
153
+ if ((th.thFixed || th.thGroup) && !th.thPinned) {
154
+ if (i != pinneds + fixeds)
155
+ this.utilities.arrayMove(ths, i, pinneds + fixeds);
156
+ fixeds++;
157
+ }
158
+ }
159
+ }
160
+ if (this.utilities.isEsTh(ths[0]) || this.utilities.isEsTd(tds[0]))
161
+ return;
162
+ // Cache degli indici per riposizionare i td come i th
163
+ for (let i = 0; i < ths.length; i++)
164
+ columnsIndexCache[ths[i].th] = i;
165
+ // Riordino le celle per fargli mantenere la stessa struttura dei th
166
+ let newTds = new Array(ths.length);
167
+ for (let i = 0; i < tds.length; i++) {
168
+ let item = tds[i];
169
+ newTds[columnsIndexCache[item.td]] = item;
170
+ }
171
+ this.est.HasPinnedColumns = pinneds > 0;
172
+ }
173
+ /** In base alla configurazione delle colonne calcola le dimenioni delle colonne pinnate */
174
+ evaluatePinnedColumnsWidth() {
175
+ if (!this.est.HasPinnedColumns)
176
+ return;
177
+ this.est.PinnedContainerWidth = 0;
178
+ for (let i = 0; i < this.est.ColumnsList.length; i++) {
179
+ let col = this.est.ColumnsList[i];
180
+ if (col.pinned && col.visible)
181
+ this.est.PinnedContainerWidth += col.pinnedWidth;
182
+ }
183
+ this.est.PinnedContainerWidth += this.est.Selection ? 25 : 0;
184
+ }
185
+ /**
186
+ * Terminato il binding delle colonne da **reviewColumnsList** e della **View** dal **writeValue** questo metodo si occupa
187
+ * dell'allineamento delle informazioni fra le colonne calcolate internamente e le informazioni sulle colonne che arrivano dall'AppSearch
188
+ *
189
+ * @param {AppSearch<any>} view AppSearch da utilizzare per questa operazione
190
+ */
191
+ alignColumnsIfLoadedView(view) {
192
+ let emitChanged = this.est.viewMode && view.savedstate;
193
+ let newColset = [];
194
+ if (!this.est.ColumnsList || this.est.ColumnsList.length == 0)
195
+ return;
196
+ let columns = this.est.viewMode ? view.columns : this.est.arrayColumns;
197
+ this.est.ColumnsList.forEach(c => {
198
+ // Se la colonna è pinnata mi arriva col simoleon, ma anche se è una composizione di più colonne
199
+ let exCl = columns.filter(cc => (cc.startsWith('§') ? cc.substring(1) : cc) == c.id);
200
+ // Se la colonna è pinnata aggiorno l'informazione nella view
201
+ if (exCl.length == 1)
202
+ c.pinned = exCl[0].startsWith('§');
203
+ // Se l'appsearch viene da uno stato precedente, uso le informazioni sulle colonne che ha dentro, altrimenti sovrascrivo tutto **
204
+ if (c.visible && columns.length == 0)
205
+ newColset.push(c.id);
206
+ // Se ho una colonna lato AppSearch e nella ColumnList non è visibile, allineo all'AppSearch
207
+ else if (exCl.length == 1 && !c.visible)
208
+ c.visible = true;
209
+ // Allineamento sull'AppSearch per casistiche inverse al di sopra
210
+ else if (exCl.length == 0 && c.visible)
211
+ c.visible = false;
212
+ });
213
+ // Non ho colonne nella appsearch, vuol dire che sono al primo binding
214
+ if (columns.length == 0) {
215
+ if (this.est.viewMode)
216
+ view.columns = newColset;
217
+ else
218
+ this.est.arrayColumns = newColset;
219
+ }
220
+ if ((this.est.viewMode && view.savedstate) && this.est.ColumnsOrdering && view.column_ordering.length > 0) {
221
+ // Scorro gli ordinamenti che avevo salvato e ricreo la ColumnsList in base a loro
222
+ let newColList = [];
223
+ view.column_ordering.forEach(co => {
224
+ this.est.ColumnsList.forEach(c => {
225
+ if (c.id == co)
226
+ newColList.push(c);
227
+ });
228
+ });
229
+ // Recupero anche campi nuovi che nell'iterazione vecchia non c'erano (serve durante lo sviluppo in modo da non perdersi fra un EDIT + F5 e l'altro)
230
+ this.est.ColumnsList.forEach(c => {
231
+ if (!newColList.find(t => t == c.id))
232
+ newColList.push(c);
233
+ });
234
+ this.est.ColumnsList = newColList;
235
+ }
236
+ // In ogni caso questo non mi serve più, lo resetto **
237
+ if (this.est.viewMode)
238
+ view.savedstate = false;
239
+ if (emitChanged)
240
+ this.est.changed();
241
+ }
242
+ /**
243
+ * In base alla visibilità registrata nelle **ColumnsList** questo metodo si occupa di prendere tutti i **EsThs** ed **EsTds** relativi e nasonderli/mostrarli
244
+ *
245
+ * Costo: 1 scan ColumnsList, 1 scan EsThs, 1 scan EsTds
246
+ *
247
+ * @param {EsTh[] | EsThDirective[]} ths Header della tabella
248
+ * @param {EsTd[] | EsTdDirective[]} tds Celle della tabella
249
+ * @param {AppSearch<any>} view AppSearch da utilizzare per questa operazione
250
+ */
251
+ refreshColumnsVisibility(ths, tds, view) {
252
+ let newColset = [];
253
+ let fixedThs = {};
254
+ let columnsCache = {};
255
+ for (let coli = 0; coli < this.est.ColumnsList.length; coli++) {
256
+ let col = this.est.ColumnsList[coli];
257
+ columnsCache[col.id] = col;
258
+ if (col.visible)
259
+ newColset.push((col.pinned ? "§" : "") + col.id);
260
+ }
261
+ if (view)
262
+ view.columns = newColset;
263
+ else
264
+ this.est.arrayColumns = newColset;
265
+ // 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
266
+ if (ths) {
267
+ // Definisco se la colonna è visibile in base alla sua rappresentazione locale in ColumnsList
268
+ for (let i = 0; i < ths.length; i++) {
269
+ let th = ths[i];
270
+ if (this.utilities.isEsTh(th)) {
271
+ th.Visible = th.Fixed || (columnsCache[th.ID] ? columnsCache[th.ID].visible : th.Visible);
272
+ if (th.Fixed)
273
+ fixedThs[th.ID] = true;
274
+ }
275
+ else {
276
+ th.thVisible = th.thFixed || (columnsCache[th.th] ? columnsCache[th.th].visible : th.thVisible);
277
+ if (th.thFixed || th.thGroup)
278
+ fixedThs[th.th] = true;
279
+ }
280
+ }
281
+ }
282
+ if (tds) {
283
+ // Definisco se la cella è visibile in base alla sua rappresentazione locale in ColumnsList
284
+ for (let i = 0; i < tds.length; i++) {
285
+ let td = tds[i];
286
+ if (this.utilities.isEsTd(td))
287
+ td.Visible = fixedThs[td.ID] || (columnsCache[td.ID] ? columnsCache[td.ID].visible : td.Visible);
288
+ else
289
+ td.tdVisible = fixedThs[td.td] || (columnsCache[td.td] ? columnsCache[td.td].visible : td.tdVisible);
290
+ }
291
+ }
292
+ this.est.changed();
293
+ }
294
+ /**
295
+ * Allinea gli ordinamenti dati fra le **EsThs** e le informazioni all'interno della View bindata
296
+ *
297
+ * @param {AppSearch<any>} view AppSearch da utilizzare per questa operazione
298
+ * @param {EsTh[] | EsThDirective[]} ths Colonne della tabella
299
+ */
300
+ alignHeadersOrdering(ths, view) {
301
+ let orders = view ? view.orders : this.est.arrayOrders;
302
+ for (let i = 0; i < ths.length; i++) {
303
+ let th = ths[i];
304
+ if (this.utilities.isEsTh(th)) {
305
+ th.Order = null;
306
+ // Assegno tutti gli ordinamenti che mi vengono da AppSearch. Sono i più importanti. Non faccio cache o cose strano perché tanto questa
307
+ // variabile sarà sempre massimo 3 elementi
308
+ for (let i = 0; i < orders.length; i++) {
309
+ let or = orders[i];
310
+ if (or.id == th.ID)
311
+ th.Order = or.order;
312
+ }
313
+ }
314
+ else {
315
+ th.thOrder = null;
316
+ for (let i = 0; i < orders.length; i++) {
317
+ let or = orders[i];
318
+ if (or.id == th.th)
319
+ th.thOrder = or.order;
320
+ }
321
+ }
322
+ }
323
+ }
324
+ /**
325
+ * Genera tutte le informazioni che servono per gestire il raggruppamento degli header
326
+ *
327
+ * @param {EsTh[] | EsThDirective[]} ths Colonne della tabella
328
+ *
329
+ * @returns {{ leafs: EsTh[] | EsThDirective[], groupingLevel: number, parentsCache: any, thsCache: any }} Oggetto contenente la lista delle foglie (header base), il livello
330
+ * massimo di raggruppamento raggiunto, una cache in cui vengono indicati tutti i gruppi che sono "parent" (quindi che raggruppano almeno 1 header) e la cache degli header
331
+ */
332
+ evaluateHeadersGroupingInfos(ths) {
333
+ // Pregiro per trovare i parent
334
+ let parentsCache = {};
335
+ let thsCache = {};
336
+ for (let i = 0; i < ths.length; i++) {
337
+ let th = ths[i];
338
+ if (this.utilities.isEsTh(th))
339
+ continue;
340
+ thsCache[th.th] = th;
341
+ if (th.thParent && !parentsCache[th.thParent])
342
+ parentsCache[th.thParent] = true;
343
+ }
344
+ // Secondo giro per beccare il livello massimo e la lista di foglie (th senza parent)
345
+ let hMaxLevel = 0;
346
+ let leafs = [];
347
+ for (let i = 0; i < ths.length; i++) {
348
+ let th = ths[i];
349
+ if (this.utilities.isEsTh(th)) {
350
+ leafs.push(th);
351
+ continue;
352
+ }
353
+ // Se sono una foglia vedo quanti livelli ci sono sopra
354
+ if (!parentsCache[th.th]) {
355
+ leafs.push(th);
356
+ let tmp = this.jumpsToFinalParent(th, thsCache);
357
+ hMaxLevel = tmp > hMaxLevel ? tmp : hMaxLevel;
358
+ }
359
+ }
360
+ return { leafs: leafs, groupingLevel: hMaxLevel, parentsCache: parentsCache, thsCache: thsCache };
361
+ }
362
+ /**
363
+ * Genera gli header groups da una lista di info sui th all'interno della variabile **TMPRowThGroups**
364
+ *
365
+ * @param {{ leafs: EsTh[] | EsThDirective[], groupingLevel: number, parentsCache: any, thsCache: any }} infos Informazioni di raggruppamento valutate precedentemente
366
+ */
367
+ evaluateHeaderGroups(infos) {
368
+ if (infos.groupingLevel == 0)
369
+ return;
370
+ // Giro 2.5, creo l'output dei raggruppamenti per header in modo da non dovermi preoccupare di celle non inizializzate
371
+ let expandedGroups = [];
372
+ let visibleUnpinnedLeafs = infos.leafs.filter((t) => t.thVisible && !t.thPinned);
373
+ for (let l = 0; l < infos.groupingLevel; l++) {
374
+ expandedGroups.push([]);
375
+ for (let i = 0; i < visibleUnpinnedLeafs.length; i++)
376
+ expandedGroups[l].push("");
377
+ }
378
+ // Ordino le foglie in base agli ordinamenti delle colonne
379
+ let orderedLeafs = [];
380
+ for (let i = 0; i < this.est.OrderDirectives.length; i++) {
381
+ let leaf = infos.thsCache[this.est.OrderDirectives[i]];
382
+ if (leaf.thVisible && !leaf.thPinned)
383
+ orderedLeafs.push(leaf);
384
+ }
385
+ // Terzo giro per creare l'array group con tutti i riferimenti del caso
386
+ let currentParent = "";
387
+ for (let i = 0; i < orderedLeafs.length; i++) {
388
+ let refTh = orderedLeafs[i];
389
+ let prevTh = i - 1 >= 0 ? orderedLeafs[i - 1] : null;
390
+ // Parent diverso da prima, metto il bordo a sinistra e a destra della cella precedente (se c'è)
391
+ // 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
392
+ refTh._lbord = refTh.thParent != currentParent;
393
+ refTh._rbord = visibleUnpinnedLeafs.length == i + 1;
394
+ if (prevTh)
395
+ prevTh._rbord = refTh.thParent != currentParent;
396
+ currentParent = refTh.thParent;
397
+ // Per ogni gruppo srotolo il parent nella matrice dei raggruppamenti
398
+ for (let l = 0; l < infos.groupingLevel; l++) {
399
+ let parent = refTh.thParent;
400
+ if (parent && !refTh.thPinned) {
401
+ expandedGroups[l][i] = parent;
402
+ refTh = infos.thsCache[parent];
403
+ }
404
+ }
405
+ }
406
+ // Quarto giro per compattarlo nell'elemento finale su cui bindarmi
407
+ currentParent = "";
408
+ let currentSpan = 0;
409
+ this.est.TMPRowThGroups = [];
410
+ for (let l = 0; l < expandedGroups.length; l++) {
411
+ let levelArray = [];
412
+ this.est.TMPRowThGroups.push(levelArray);
413
+ if (this.est.Selection || this.est.HasPinnedColumns)
414
+ levelArray.push({ Span: 1, Template: null, Pinned: this.est.HasPinnedColumns });
415
+ for (let h = 0; h < expandedGroups[l].length; h++) {
416
+ let item = expandedGroups[l][h];
417
+ if (item == currentParent)
418
+ currentSpan++;
419
+ else {
420
+ if (currentSpan > 0)
421
+ levelArray.push({ Span: currentSpan, Template: (currentParent ? infos.thsCache[currentParent].Template : null), Borders: !!currentParent });
422
+ currentSpan = 1;
423
+ currentParent = item;
424
+ }
425
+ }
426
+ // Ultima aggiunta che altrimenti mi rimarrebbe in cache
427
+ levelArray.push({ Span: currentSpan, Template: (currentParent ? infos.thsCache[currentParent].Template : null), Borders: !!currentParent });
428
+ if (this.est.Removal)
429
+ levelArray.push({ Span: 1, Template: null });
430
+ if (this.est.Export || this.est.HiddenColumns || this.est.ColumnsOrdering || this.est.CornerMenuOptions)
431
+ levelArray.push({ Span: 1, Template: null });
432
+ currentSpan = 0;
433
+ currentParent = "";
434
+ }
435
+ }
436
+ /**
437
+ * Calcola il numero di salti da un header foglia all'ultimo parent della catena
438
+ *
439
+ * @param {EsThDirective} th Header da cui scorrere i padri per capire quanti livelli ci sono sopra
440
+ * @param {{ [index: string]: EsThDirective }} thsCache Cache degli header
441
+ */
442
+ jumpsToFinalParent(th, thsCache) {
443
+ let jumps = 0;
444
+ let parent = null;
445
+ let parentsPrepend = [];
446
+ let baseThRef = th;
447
+ do {
448
+ parent = th.thParent;
449
+ if (parent) {
450
+ th = thsCache[parent];
451
+ if (!th.thEmpty)
452
+ parentsPrepend.unshift(th.Template);
453
+ jumps++;
454
+ }
455
+ } while (parent);
456
+ baseThRef._thParents = parentsPrepend;
457
+ return jumps;
458
+ }
459
+ /**
460
+ * Metodo che genera l'ordine di default delle colonne
461
+ *
462
+ * @param {AppSearch<any>} view AppSearch da utilizzare per questa operazione
463
+ */
464
+ generateDefaultOrder(ths, view) {
465
+ if (ths.length == 0)
466
+ return;
467
+ let orderings = this.est.viewMode ? view.column_ordering : this.est.arrayColumnOrdering;
468
+ // Genero ordinamento di default da 0 fino a dove deve arrivare. Situazione attuale senza hotpotato
469
+ if (!orderings || orderings.length == 0) {
470
+ for (let i = 0; i < ths.length; i++) {
471
+ let th = ths[i];
472
+ let order = this.utilities.isEsTh(th) ? th.ID : th.th;
473
+ this.est.OrderDirectives.push(order);
474
+ }
475
+ }
476
+ else {
477
+ this.est.OrderDirectives = orderings;
478
+ for (let i = 0; i < ths.length; i++) {
479
+ let th = ths[i];
480
+ let thId = this.utilities.isEsTh(th) ? th.ID : th.th;
481
+ if (!this.est.OrderDirectives.find(o => o == thId))
482
+ this.est.OrderDirectives.push(thId);
483
+ }
484
+ }
485
+ }
486
+ /**
487
+ * Applica l'ordine specificato alle varie colonne
488
+ *
489
+ * @param {AppSearch<any>} view AppSearch da utilizzare per questa operazione
490
+ * @param {boolean} finalize Se **true** significa che non mi aspetto di dover effettuare altre operazioni e posso renderizzare la situazione in base ai RowContext
491
+ * Senza finalize significa che mi aspetto altre operazioni che prima o poi richiameranno questa funzione col finalize.
492
+ *
493
+ * 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.
494
+ * Mettendo solo la chiamata da "writeValue" come "finalizzante" mi assicuro che smanattamenti a frontend non causino flickering fino a quando non servono
495
+ */
496
+ applyOrdering(view, finalize) {
497
+ // Genero ordinamento per gli header
498
+ let newHeaders = [];
499
+ // Se devo finalizzare aggancio tutte le variabili di bind
500
+ if (finalize) {
501
+ this.est.OrderDirectives.forEach(o => {
502
+ let heaedrItem = this.est.TMPRowTHs.filter(t => t.ID == o)[0];
503
+ if (heaedrItem)
504
+ newHeaders.push(heaedrItem);
505
+ });
506
+ this.est.TMPRowTHs = newHeaders;
507
+ // Genero ordinamento per le celle
508
+ for (let i = 0; i < this.est.RowContexts.length; i++) {
509
+ let context = this.est.TMPRowTDs[this.est.RowContexts[i]];
510
+ let newContext = [];
511
+ this.est.OrderDirectives.forEach(o => {
512
+ let contextItem = context.filter(t => t.ID == o)[0];
513
+ newContext.push(contextItem);
514
+ });
515
+ this.est.TMPRowTDs[this.est.RowContexts[i]] = newContext;
516
+ }
517
+ }
518
+ if (this.est.viewMode)
519
+ view.column_ordering = this.est.OrderDirectives;
520
+ else
521
+ this.est.arrayColumnOrdering = this.est.OrderDirectives;
522
+ this.est.changed();
523
+ }
524
+ /**
525
+ * All'interno della dialog "Ordinamento e Visibilità Colonne" mette la colonna specificata prima della colonna precedente
526
+ *
527
+ * @param {EsTableColumn} columnItem Colonna da spostare
528
+ */
529
+ sendUp(columnItem) {
530
+ let itemIndex = this.est.TMPColumnsList.indexOf(columnItem);
531
+ if (this.est.TMPColumnsList[itemIndex - 1].fixed || this.est.TMPColumnsList[itemIndex - 1].pinned)
532
+ return;
533
+ this.utiExts.swap(this.est.TMPColumnsList, itemIndex, itemIndex - 1);
534
+ // Non posso fare JSON.parse(JSON.stringify(this.ColumnsList)) perché contiene riferimenti a TemplateRef
535
+ let tmp = [];
536
+ this.est.TMPColumnsList.forEach(c => { tmp.push(Object.assign({}, c)); });
537
+ this.est.TMPColumnsList = tmp;
538
+ }
539
+ /**
540
+ * All'interno della dialog "Ordinamento e Visibilità Colonne" mette la colonna specificata dopo la colonna successiva
541
+ *
542
+ * @param {EsTableColumn} columnItem Colonna da spostare
543
+ */
544
+ sendDown(columnItem) {
545
+ let itemIndex = this.est.TMPColumnsList.indexOf(columnItem);
546
+ this.utiExts.swap(this.est.TMPColumnsList, itemIndex, itemIndex + 1);
547
+ // Non posso fare JSON.parse(JSON.stringify(this.ColumnsList)) perché contiene riferimenti a TemplateRef
548
+ let tmp = [];
549
+ this.est.TMPColumnsList.forEach(c => { tmp.push(Object.assign({}, c)); });
550
+ this.est.TMPColumnsList = tmp;
551
+ }
552
+ /**
553
+ * All'interno della dialog "Ordinamento e Visibilità Colonne" pinna la colonna specificata
554
+ *
555
+ * @param {EsTableColumn} columnItem Colonna da spostare
556
+ */
557
+ pinOrUnpinColumn(columnItem) {
558
+ let itemIndex = this.est.TMPColumnsList.indexOf(columnItem);
559
+ if (!columnItem.pinned) {
560
+ columnItem.prev_index = itemIndex;
561
+ //Quando pinno devo spostare l'elemento come ultima colonna pinnata o come prima colonna se non ce ne sono di pinnate
562
+ for (let i = 0; i < this.est.TMPColumnsList.length; i++) {
563
+ if (!this.est.TMPColumnsList[i].pinned) {
564
+ this.utilities.arrayMove(this.est.TMPColumnsList, itemIndex, i);
565
+ break;
566
+ }
567
+ }
568
+ }
569
+ else {
570
+ //Quando spinno riporto l'elemento allo stesso indice in cui era prima (se sono stati fatti spostamenti nel mezzo cazzi dell'utente)
571
+ if (columnItem.prev_index != null && columnItem.prev_index != undefined)
572
+ this.utilities.arrayMove(this.est.TMPColumnsList, itemIndex, columnItem.prev_index);
573
+ else {
574
+ // Se spinno senza un prev_index vuol dire che la colonna era pinnata da configurazione. La sposto nel primo punto disponibile
575
+ for (let i = 0; i < this.est.TMPColumnsList.length; i++) {
576
+ if (!this.est.TMPColumnsList[i].pinned && !this.est.TMPColumnsList[i].fixed) {
577
+ this.utilities.arrayMove(this.est.TMPColumnsList, itemIndex, i - 1);
578
+ break;
579
+ }
580
+ }
581
+ }
582
+ }
583
+ columnItem.pinned = !columnItem.pinned;
584
+ }
585
+ /**
586
+ * All'interno della dialog "Ordinamento e Visibilità Colonne" inverte le impostazioni di visibilità della colonna
587
+ *
588
+ * @param {EsTableColumn} columnItem Colonna da spostare
589
+ */
590
+ columnClicked(item) {
591
+ this.est.lastSelectedItemID = item.id;
592
+ if (!this.est.HiddenColumns || item.fixed)
593
+ return;
594
+ item.visible = !item.visible;
595
+ this.updateGlobalColVisCheck();
596
+ }
597
+ /** All'apertura della dialog "Ordinamento e Visibilità Colonne" ricarica le informazioni attuali per permettere la modifica */
598
+ resetColumnVisSelection() {
599
+ this.est.TMPColumnsList = [];
600
+ // Non posso fare JSON.parse(JSON.stringify(this.ColumnsList)) perché contiene riferimenti a TemplateRef
601
+ this.est.TMPColumnsList = [];
602
+ this.est.ColumnsList.forEach(c => { this.est.TMPColumnsList.push(Object.assign({}, c)); });
603
+ let reorderedColList = [];
604
+ if (this.est.ColumnsOrdering) {
605
+ this.est.OrderDirectives.forEach(o => {
606
+ let column = this.est.TMPColumnsList.filter(t => t.id == o)[0];
607
+ // Potrei non averne nel caso ci sia il flag HiddenColumns a false, evito di inserire degli undefined
608
+ if (column)
609
+ reorderedColList.push(column);
610
+ });
611
+ this.est.TMPColumnsList = reorderedColList;
612
+ }
613
+ this.updateGlobalColVisCheck();
614
+ }
615
+ /** Riaggiorna le **OrderDirectives** con le informazioni in **ColumnsList** */
616
+ refreshColumnOrdering() {
617
+ this.est.OrderDirectives = [];
618
+ for (let c = 0; c < this.est.ColumnsList.length; c++)
619
+ this.est.OrderDirectives.push(this.est.ColumnsList[c].id);
620
+ }
621
+ /** Effettua la selezione o meno del check globale (**globalColVisCheck**) di visibilità in base a se tutte le **TMPColumnsList** sono visibili o no */
622
+ updateGlobalColVisCheck() {
623
+ // TMPColList viene riempita di undefined nel caso in cui sia disattivata la selezione delle colonne nascoste
624
+ this.est.globalColVisCheck = this.est.TMPColumnsList.every(t => t.visible);
625
+ }
626
+ /**
627
+ * Chiamato quando una colonna viene riordinata all'interno della lista delle visibilità/posizioni colonne
628
+ *
629
+ * @param {CdkDragDrop<EsTableColumn[]>} event Evento di drop della lista
630
+ */
631
+ columnReordered(event) {
632
+ moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
633
+ }
634
+ /**
635
+ * Chiamato quando una colonna viene riordinata all'interno della lista delle visibilità/posizioni colonne
636
+ *
637
+ * @param {number} index Indice in cui voglio droppare l'elemento draggato
638
+ * @param {CdkDrag<EsTableColumn>} item Oggetto che sto draggando
639
+ *
640
+ * @returns {boolean} **true** se la colonna può essere spostata sull'indice **index**, **false** altrimenti
641
+ */
642
+ sortPredicate(index, item) {
643
+ let itemAtIndex = this.est.ColumnsList[index];
644
+ return !itemAtIndex.fixed && !itemAtIndex.pinned && !item.data.pinned && !item.data.pinned;
645
+ }
646
+ /**
647
+ * Funzione che effettua la conferma della visibilità e dell'ordine delle colonne.
648
+ *
649
+ * Questa selezione viene inoltre salvata nelle preferenze (**@esfaenza/preferences**), qualora l'Input **SavePreferences** fosse valorizzato
650
+ *
651
+ * @returns {boolean} **true** se non ci sono problemi, **false** altrimenti
652
+ */
653
+ confirmColumnVisibilitySelection() {
654
+ // Non permetto di non selezionare nulla
655
+ if (this.est.TMPColumnsList.every(t => !t.visible))
656
+ return false;
657
+ let castedView = this.est.viewMode ? (this.est.MainGroupView || this.est.View) : null;
658
+ this.est.ColumnsList = [];
659
+ this.est.TMPColumnsList.forEach(c => { this.est.ColumnsList.push(Object.assign({}, c)); });
660
+ this.refreshColumnOrdering();
661
+ this.applyOrdering(castedView, false);
662
+ this.refreshColumnsVisibility(null, null, castedView);
663
+ //Salvo le preferences di questa view
664
+ //Di default registro ordinamento e visibilità delle colonne nella vista. Solo le cose di UI
665
+ if (this.est.SavePreferences) {
666
+ if (!this.est.ngControl.name) {
667
+ console.error("Non posso utilizzare le preference senza avere un 'name' per la tabella");
668
+ return false;
669
+ }
670
+ if (!this.prefService) {
671
+ console.error("Non posso utilizzare le preference senza che il pacchetto @esfaenza/preferences sia installato");
672
+ return false;
673
+ }
674
+ let columns = this.est.arrayMode ? this.est.arrayColumns : castedView.columns;
675
+ let columnsOrderings = this.est.arrayMode ? this.est.arrayColumnOrdering : castedView.column_ordering;
676
+ var toStore = { columns: JSON.parse(JSON.stringify(columns)), column_ordering: JSON.parse(JSON.stringify(columnsOrderings)) };
677
+ this.prefService.store(this.est.ngControl.name, toStore).subscribe();
678
+ }
679
+ // Rieseguo l'ultima ricerca bindata alla tabella
680
+ // Mi assicuro di farlo dopo l'espansione del changed o rischio che la ricerca mi ridia colonne che in realtà non esistono
681
+ if (this.est.viewMode)
682
+ setTimeout(() => {
683
+ if (this.est.MainGroupView) {
684
+ //this.emitSearchRequest(true, this.MainGroupView);
685
+ for (let i = 0; i < this.est.groupSearchRequestsCache.length; i++) {
686
+ let view = this.est.groupSearchRequestsCache[i].view;
687
+ view.columns = this.est.MainGroupView.columns;
688
+ view.column_ordering = this.est.MainGroupView.column_ordering;
689
+ this.est.emitSearchRequest(true, this.est.groupSearchRequestsCache[i].view);
690
+ }
691
+ }
692
+ else
693
+ this.est.emitSearchRequest(true);
694
+ });
695
+ else if (this.est.arrayMode)
696
+ setTimeout(() => { this.est.internalWriteValue(); });
697
+ // Lo vorrei mettere lato template ma no
698
+ this.est.lastSelectedItemID = null;
699
+ return true;
700
+ }
701
+ /**
702
+ * Effettuo l'unpinning di una colonna in maniera programmatica semplicemente eseguendo una per una le operazioni che verrebbero eseguite altrimenti
703
+ *
704
+ * @param {string} id Codice della colonna da spinnare
705
+ */
706
+ unpinColumn(id) {
707
+ this.resetColumnVisSelection();
708
+ this.pinOrUnpinColumn(this.est.TMPColumnsList.find(t => t.id == id));
709
+ this.confirmColumnVisibilitySelection();
710
+ }
711
+ /** Sul click nella checkbox di selezione globale si scorrono tutte le colonne e si impostano al valore della check globale */
712
+ globalColVisCheckChanged() {
713
+ this.est.TMPColumnsList.forEach(t => {
714
+ if (!t.fixed)
715
+ t.visible = this.est.globalColVisCheck;
716
+ });
717
+ }
718
+ }
719
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29sdW1uTWV0YWRhdGFIYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZXMtdGFibGUvc3JjL2xpYi9jb3JlL2hhbmRsZXJzL2NsYXNzZXMvQ29sdW1uTWV0YWRhdGFIYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQWlCQSxVQUFVO0FBQ1YsT0FBTyxFQUFFLFdBQVcsRUFBYSxhQUFhLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN4RSxPQUFPLEVBQXdCLGVBQWUsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRS9FLDZIQUE2SDtBQUM3SCxNQUFNLE9BQU8scUJBQXFCO0lBRTlCLHlCQUF5QjtJQUN6QixZQUFvQixHQUFxQixFQUFVLFNBQTJCLEVBQVUsT0FBdUIsRUFBVSxXQUErQixFQUFVLEdBQXVCO1FBQXJLLFFBQUcsR0FBSCxHQUFHLENBQWtCO1FBQVUsY0FBUyxHQUFULFNBQVMsQ0FBa0I7UUFBVSxZQUFPLEdBQVAsT0FBTyxDQUFnQjtRQUFVLGdCQUFXLEdBQVgsV0FBVyxDQUFvQjtRQUFVLFFBQUcsR0FBSCxHQUFHLENBQW9CO0lBQUksQ0FBQztJQUU5TDs7Ozs7T0FLRztJQUNJLG1CQUFtQixDQUFDLEVBQVUsRUFBRSxLQUFxQjtRQUN4RCxJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUF1QixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUM7UUFDakcsSUFBSSxVQUFVLEdBQUcsSUFBSSxDQUFDO1FBQ3RCLElBQUksYUFBYSxHQUFXLElBQUksQ0FBQztRQUVqQyxtRkFBbUY7UUFDbkYsSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLFFBQVE7WUFDM0IsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUF1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QUFDLElBQUksQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNyRSxJQUFJLENBQUMsZ0NBQWdDLEVBQUUsQ0FBQztJQUM1QyxDQUFDO0lBRUQsOEhBQThIO0lBQ3ZILHdCQUF3QjtRQUMzQixJQUFJLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUU7WUFDaEMsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLO2dCQUNSLENBQUMsQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQztRQUMvQyxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7Q0FDSiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEFuZ3VsYXJcclxuaW1wb3J0IHsgVGVtcGxhdGVSZWYgfSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xyXG5cclxuLy8gTGlic1xyXG5pbXBvcnQgeyBVdGlsaXR5U2VydmljZSB9IGZyb20gXCJAZXNmYWVuemEvZXh0ZW5zaW9uc1wiO1xyXG5pbXBvcnQgeyBQcmVmZXJlbmNlc1NlcnZpY2UgfSBmcm9tIFwiQGVzZmFlbnphL3ByZWZlcmVuY2VzXCI7XHJcblxyXG4vLyBDb21wb25lbnRpIC8gRGlyZXR0aXZlXHJcbmltcG9ydCB7IEVzVGQgfSBmcm9tIFwiLi4vLi4vLi4vY29tcG9uZW50cy9lcy10ZC9lc190ZC5jb21wb25lbnRcIjtcclxuaW1wb3J0IHsgRXNUaCB9IGZyb20gXCIuLi8uLi8uLi9jb21wb25lbnRzL2VzLXRoL2VzX3RoLmNvbXBvbmVudFwiO1xyXG5pbXBvcnQgeyBFc1RhYmxlQ29tcG9uZW50IH0gZnJvbSBcIi4uLy4uLy4uL2NvbXBvbmVudHMvZXMtdGFibGUvZXNfdGFibGUuY29tcG9uZW50XCJcclxuaW1wb3J0IHsgRXNUZERpcmVjdGl2ZSB9IGZyb20gXCIuLi8uLi8uLi9kaXJlY3RpdmVzL2VzX3RkLmRpcmVjdGl2ZVwiO1xyXG5pbXBvcnQgeyBFc1RoRGlyZWN0aXZlIH0gZnJvbSBcIi4uLy4uLy4uL2RpcmVjdGl2ZXMvZXNfdGguZGlyZWN0aXZlXCI7XHJcblxyXG4vLyBIYW5kbGVyc1xyXG5pbXBvcnQgeyBVdGlsaXRpZXNIYW5kbGVyLCBSb3dHcm91cGluZ0hhbmRsZXIgfSBmcm9tIFwiLi5cIjtcclxuXHJcbi8vIE1vZGVsbGlcclxuaW1wb3J0IHsgQXBwT3JkZXJpbmcsIEFwcFNlYXJjaCwgRXNUYWJsZUNvbHVtbiB9IGZyb20gXCIuLi8uLi8uLi9kb21haW5cIjtcclxuaW1wb3J0IHsgQ2RrRHJhZywgQ2RrRHJhZ0Ryb3AsIG1vdmVJdGVtSW5BcnJheSB9IGZyb20gXCJAYW5ndWxhci9jZGsvZHJhZy1kcm9wXCI7XHJcblxyXG4vKiogQ2xhc3NlIGNoZSBnZXN0aXNjZSB0dXR0ZSBsZSBpbmZvcm1haXpvbmkgcmVsYXRpdmUgYWxsZSBjb2xvbm5lOiB2aXNpYmlsaXTDoCwgcG9zaXppb25lLCBzdGF0byBkaSBwaW4vdW5waW4sIGVjYyBlY2MuLi4gKi9cclxuZXhwb3J0IGNsYXNzIENvbHVtbk1ldGFkYXRhSGFuZGxlciB7XHJcblxyXG4gICAgLyoqIEBpZ25vcmUgQ29zdHJ1dHRvcmUqL1xyXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBlc3Q6IEVzVGFibGVDb21wb25lbnQsIHByaXZhdGUgdXRpbGl0aWVzOiBVdGlsaXRpZXNIYW5kbGVyLCBwcml2YXRlIHV0aUV4dHM6IFV0aWxpdHlTZXJ2aWNlLCBwcml2YXRlIHByZWZTZXJ2aWNlOiBQcmVmZXJlbmNlc1NlcnZpY2UsIHByaXZhdGUgcmdIOiBSb3dHcm91cGluZ0hhbmRsZXIpIHsgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTWV0b2RvIGNoZSBnZXN0aXNjZSBpbCBjYW1iaW8gZGkgT3JkaW5hbWVudG8gZGkgdW5hIGNvbG9ubmFcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgSUQgZGVsbGEgY29sb25uYSBpbCBjdWkgb3JpZG5hbWVudG8gw6ggY2FtYmlhdG9cclxuICAgICAqIEBwYXJhbSB7J0RFU0MnIHwgJ0FTQyd9IG9yZGVyIE51b3ZvIG9yZGluZSBzZWxlemlvbmF0byBwZXIgbGEgY29sb25uYVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgaGFuZGxlVEhPcmRlckNoYW5nZShpZDogc3RyaW5nLCBvcmRlcjogJ0RFU0MnIHwgJ0FTQycpIHtcclxuICAgICAgICBsZXQgb3JkZXJzID0gdGhpcy5lc3Qudmlld01vZGUgPyAodGhpcy5lc3QuVmlldyBhcyBBcHBTZWFyY2g8YW55Pikub3JkZXJzIDogdGhpcy5lc3QuYXJyYXlPcmRlcnM7XHJcbiAgICAgICAgbGV0IG9yZGVyVG9BZGQgPSB0cnVlO1xyXG4gICAgICAgIGxldCBvcmRlclRvUmVtb3ZlOiBudW1iZXIgPSBudWxsO1xyXG5cclxuICAgICAgICAvLyBTZSBwZXIgcXVhbGNoZSBtb3Rpdm8gaWwgY29zdHJ1dHRvcmUgbm9uIMOoIHBhc3NhdG8gKGNhY2hlIHRhcnBhdGUgbyBzaW1pbGEpIGZpeG9cclxuICAgICAgICBpZiAoIW9yZGVycyAmJiB0aGlzLmVzdC52aWV3TW9kZSlcclxuICAgICAgICAgICAgKHRoaXMuZXN0LlZpZXcgYXMgQXBwU2VhcmNoPGFueT4pLm9yZGVycyA9IFtdO1xyXG4gICAgICAgIGVsc2UgaWYgKCFvcmRlcnMgJiYgdGhpcy5lc3QuYXJyYXlNb2RlKVxyXG4gICAgICAgICAgICB0aGlzLmVzdC5hcnJheU9yZGVycyA9IFtdO1xyXG5cclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG9yZGVycy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgdCA9IG9yZGVyc1tpXTtcclxuICAgICAgICAgICAgaWYgKHQuaWQgPT0gaWQpIHtcclxuICAgICAgICAgICAgICAgIGlmIChvcmRlcikge1xyXG4gICAgICAgICAgICAgICAgICAgIHQub3JkZXIgPSBvcmRlcjtcclxuICAgICAgICAgICAgICAgICAgICBvcmRlclRvQWRkID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAgICAgb3JkZXJUb1JlbW92ZSA9IGk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChvcmRlclRvUmVtb3ZlICE9IG51bGwpIHtcclxuICAgICAgICAgICAgb3JkZXJzLnNwbGljZShvcmRlclRvUmVtb3ZlLCAxKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAob3JkZXJUb0FkZCkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5lc3QuTXVsdGlwbGVPcmRlcmluZ0RpcmVjdGl2ZXMpXHJcbiAgICAgICAgICAgICAgICBvcmRlcnMucHVzaChuZXcgQXBwT3JkZXJpbmcoaWQsIG9yZGVyKSk7XHJcbiAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZXN0LnZpZXdNb2RlKVxyXG4gICAgICAgICAgICAgICAgICAgICh0aGlzLmVzdC5WaWV3IGFzIEFwcFNlYXJjaDxhbnk+KS5vcmRlcnMgPSBbbmV3IEFwcE9yZGVyaW5nKGlkLCBvcmRlcildO1xyXG4gICAgICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5lc3QuYXJyYXlNb2RlKVxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXN0LmFycmF5T3JkZXJzID0gW25ldyBBcHBPcmRlcmluZyhpZCwgb3JkZXIpXTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5lc3Qub25PcmRlckNoYW5nZWQuZW1pdCh7IGlkLCBvcmRlciB9KTtcclxuXHJcbiAgICAgICAgaWYgKHRoaXMuZXN0LnZpZXdNb2RlKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmVzdC5ncm91cFNlYXJjaFJlcXVlc3RzQ2FjaGUubGVuZ3RoID4gMClcclxuICAgICAgICAgICAgICAgIHRoaXMucmdILmVtaXRSb3dHcm91cGluZ1NlYXJjaGVzKGlkLCBvcmRlcnMpO1xyXG4gICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICB0aGlzLmVzdC5lbWl0U2VhcmNoUmVxdWVzdChmYWxzZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2UgaWYgKHRoaXMuZXN0LmFycmF5TW9kZSlcclxuICAgICAgICAgICAgdGhpcy5lc3QuaW50ZXJuYWxXcml0ZVZhbHVlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBQYXJ0ZW5kbyBkYWdsaSAqKkVzVGhzKiogZXN0cmFwcG9sbyBsYSBsaXN0YSBkaSAqKkVzVGFibGVDb2x1bW4qKiBjaGUgcXVlc3RhIHRhYmVsbGEgZG92csOgIGV2ZW50dWFsbWVudGUgZ2VzdGlyZSBwZXIgVmlzaWJpbGl0w6AgZSBPcmRpbmVcclxuICAgICAqXHJcbiAgICAgKiBDb3N0bzogMSBzY2FuIEVzVGhzXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtFc1RoW10gfCBFc1RoRGlyZWN0aXZlW119IHRocyBDb2xvbm5lIGRlbGxhIHRhYmVsbGFcclxuICAgICAqL1xyXG4gICAgcHVibGljIHJldmlld0NvbHVtbnNMaXN0KHRoczogRXNUaFtdIHwgRXNUaERpcmVjdGl2ZVtdKSB7XHJcbiAgICAgICAgdGhpcy5lc3QuVE1QQ29sdW1uc0xpc3QgPSBbXTtcclxuICAgICAgICBpZiAodGhzLmxlbmd0aCA9PSAwKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgIC8vIEFwcGVuYSBpbCBjb250ZW50Q2hpbGRyZW4gw6ggdmFsb3JpenphdG8gc2NvcnJvIHR1dHRpIGdsaSBoZWFkZXJcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRocy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgdGggPSB0aHNbaV07XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy51dGlsaXRpZXMuaXNFc1RoKHRoKSkge1xyXG4gICAgICAgICAgICAgICAgLy8gU2Ugbm9uIGhvIHVuIGlkIGlsIHRoIMOoIGNvbnNpZGVyYXRvIGluZXJ0ZVxyXG4gICAgICAgICAgICAgICAgaWYgKCF0aC5JRClcclxuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcclxuXHJcbiAgICAgICAgICAgICAgICB0aC5PcmRlckJ5ID0gdGhpcy5lc3QuT3JkZXJCeUNvbHVtbjtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBTYWx2byBsZSBpbmZvcm1hemlvbmkgZGVsbCdoZWFkZXIgcGVyIGZhciBwYXJ0ZSBkZWxsYSBsaXN0YSBkYSBjdWkgc2NlZ2xpZXJlIHF1YWxpIGNvbG9ubmUgdmlzdWFsaXp6YXJlL25hc2NvbmRlcmVcclxuICAgICAgICAgICAgICAgIC8vIERpIGRlZmF1bHQgbGEgdmlzaWJpbGl0w6Agw6ggcXVlbGxhIGltcG9zdGF0YSBuZWwgY29tcG9uZW50ZVxyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZXN0LkhpZGRlbkNvbHVtbnMgfHwgdGguVmlzaWJsZSlcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmVzdC5UTVBDb2x1bW5zTGlzdC5wdXNoKG5ldyBFc1RhYmxlQ29sdW1uKHRoLklELCB0aC5EZXNjcmlwdGlvbiwgdGguVmlzaWJsZSwgdGguRml4ZWQpKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGxldCBjb2x1bW4gPSB0aC50aDtcclxuICAgICAgICAgICAgICAgIC8vIFNlIG5vbiBobyB1biBpZCBpbCB0aCDDqCBjb25zaWRlcmF0byBpbmVydGVcclxuICAgICAgICAgICAgICAgIGlmICghY29sdW1uKVxyXG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIFNhbHZvIGxlIGluZm9ybWF6aW9uaSBkZWxsJ2hlYWRlciBwZXIgZmFyIHBhcnRlIGRlbGxhIGxpc3RhIGRhIGN1aSBzY2VnbGllcmUgcXVhbGkgY29sb25uZSB2aXN1YWxpenphcmUvbmFzY29uZGVyZVxyXG4gICAgICAgICAgICAgICAgLy8gRGkgZGVmYXVsdCBsYSB2aXNpYmlsaXTDoCDDqCBxdWVsbGEgaW1wb3N0YXRhIG5lbCBjb21wb25lbnRlXHJcbiAgICAgICAgICAgICAgICBpZiAoKHRoaXMuZXN0LkhpZGRlbkNvbHVtbnMgfHwgdGgudGhWaXNpYmxlKSAmJiB0aC50aElmKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IHByZXZpb3VzbHlQaW5uZWQgPSAhdGhpcy5lc3QuQ29sdW1uc0xpc3QgfHwgdGhpcy5lc3QuQ29sdW1uc0xpc3QubGVuZ3RoID09IDAgPyBudWxsIDogdGhpcy5lc3QuQ29sdW1uc0xpc3QuZmluZCh0ID0+IHQuaWQgPT0gY29sdW1uKSB8fCBudWxsO1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCB0b0FkZCA9IG5ldyBFc1RhYmxlQ29sdW1uKGNvbHVtbiwgbnVsbCwgdGgudGhWaXNpYmxlLCAodGgudGhGaXhlZCB8fCB0aC50aEdyb3VwKSwgcHJldmlvdXNseVBpbm5lZCA9PSBudWxsID8gdGgudGhQaW5uZWQgOiBwcmV2aW91c2x5UGlubmVkLnBpbm5lZCwgdGgudGhQaW5uZWRXaWR0aCwgdGguVGVtcGxhdGUsIHRoLl90aFBhcmVudHMpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c2x5UGlubmVkKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0b0FkZC5wcmV2X2luZGV4ID0gcHJldmlvdXNseVBpbm5lZC5wcmV2X2luZGV4O1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXN0LlRNUENvbHVtbnNMaXN0LnB1c2godG9BZGQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuZXN0LkNvbHVtbnNMaXN0ID0gW107XHJcbiAgICAgICAgdGhpcy5lc3QuVE1QQ29sdW1uc0xpc3QuZm9yRWFjaChjID0+IHsgdGhpcy5lc3QuQ29sdW1uc0xpc3QucHVzaChPYmplY3QuYXNzaWduKHt9LCBjKSk7IH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUHJlbmRlIGkgdGggZSBpIHRkIGluIG1vZGFsaXTDoCBkaXJldGl2ZSBlIGxpIG9yZGluYSBpbiBiYXNlIGEgc2UgY2kgc29ubyBjb2xvbm5lIGZpeGVkIG8gbWVub1xyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbW92ZUZpeGVkQ29sdW1uc0F0VGhlQmVnaW5uaW5nKHRoczogRXNUaFtdIHwgRXNUaERpcmVjdGl2ZVtdLCB0ZHM6IEVzVGRbXSB8IEVzVGREaXJlY3RpdmVbXSkge1xyXG5cclxuICAgICAgICBsZXQgdGhzQ2FjaGU6IHsgW2luZGV4OiBzdHJpbmddOiBhbnk7IH0gPSB7fTtcclxuICAgICAgICBsZXQgZml4ZWRzID0gMCwgcGlubmVkcyA9IDA7XHJcbiAgICAgICAgbGV0IGNvbHVtbnNDYWNoZTogeyBbaW5kZXg6IHN0cmluZ106IEVzVGFibGVDb2x1bW47IH0gPSB7fTtcclxuICAgICAgICBsZXQgY29sdW1uc0luZGV4Q2FjaGU6IHsgW2luZGV4OiBzdHJpbmddOiBudW1iZXI7IH0gPSB7fTtcclxuXHJcbiAgICAgICAgLy8gQ3JlbyBsYSBjYWNoZSBkZWxsZSBjb2xvbm5lXHJcbiAgICAgICAgZm9yIChsZXQgY29saSA9IDA7IGNvbGkgPCB0aGlzLmVzdC5Db2x1bW5zTGlzdC5sZW5ndGg7IGNvbGkrKykge1xyXG4gICAgICAgICAgICBsZXQgY29sID0gdGhpcy5lc3QuQ29sdW1uc0xpc3RbY29saV07XHJcbiAgICAgICAgICAgIGNvbHVtbnNDYWNoZVtjb2wuaWRdID0gY29sO1xyXG5cclxuICAgICAgICAgICAgLy8gQW5jaGUgcGVyIGxlIGNvbHVtbnNsaXN0IHNwb3N0byBsZSBwaW5uYXRlIG8gbGUgZml4ZWQgYWxsJ2luaXppb1xyXG4gICAgICAgICAgICBpZiAoY29sLnBpbm5lZCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKGNvbGkgIT0gcGlubmVkcylcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnV0aWxpdGllcy5hcnJheU1vdmUodGhpcy5lc3QuQ29sdW1uc0xpc3QsIGNvbGksIHBpbm5lZHMpO1xyXG4gICAgICAgICAgICAgICAgcGlubmVkcysrO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBTZSB1bmEgY29sb25uYSDDqCBzaWEgcGlubmF0YSBjaGUgZml4YXRhIGxhIGNvbnNpZGVybyB1bmljYW1lbnRlIHBpbm5hdGFcclxuICAgICAgICAgICAgaWYgKGNvbC5maXhlZCAmJiAhY29sLnBpbm5lZCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKGNvbGkgIT0gcGlubmVkcyArIGZpeGVkcylcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnV0aWxpdGllcy5hcnJheU1vdmUodGhzLCBjb2xpLCBwaW5uZWRzICsgZml4ZWRzKTtcclxuICAgICAgICAgICAgICAgIGZpeGVkcysrO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBwaW5uZWRzID0gZml4ZWRzID0gMDtcclxuXHJcbiAgICAgICAgLy8gU3Bvc3RvIHR1dHRpIGdsaSBoZWFkZXIgZml4ZWQgbyBwaW5uZWQgYWxsJ2luaXppb1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGxldCB0aCA9IHRoc1tpXTtcclxuICAgICAgICAgICAgaWYgKHRoaXMudXRpbGl0aWVzLmlzRXNUaCh0aCkpIHtcclxuICAgICAgICAgICAgICAgIHRoc0NhY2hlW3RoLklEXSA9IHRoO1xyXG4gICAgICAgICAgICAgICAgaWYgKHRoLkZpeGVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkgIT0gcGlubmVkcyArIGZpeGVkcylcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy51dGlsaXRpZXMuYXJyYXlNb3ZlKHRocywgaSwgcGlubmVkcyArIGZpeGVkcyk7XHJcbiAgICAgICAgICAgICAgICAgICAgZml4ZWRzKys7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcblxyXG4gICAgICAgICAgICAgICAgdGhzQ2FjaGVbdGgudGhdID0gdGg7XHJcbiAgICAgICAgICAgICAgICAvLyBSaWFzc2Vnbm8gc2VtcHJlIHBlciByaXB1bGlyZSB2YWxvcmkgZGkgcGFydGVuemEgbyBwZXIgYWdnaW9ybmFybGkgaW4gY2FzbyBkaSBtb2RpZmljaGUgdXRlbnRlXHJcbiAgICAgICAgICAgICAgICB0aC50aFBpbm5lZCA9ICghY29sdW1uc0NhY2hlW3RoLnRoXSAmJiB0aC50aFBpbm5lZCkgfHwgKGNvbHVtbnNDYWNoZVt0aC50aF0gJiYgY29sdW1uc0NhY2hlW3RoLnRoXS5waW5uZWQpO1xyXG4gICAgICAgICAgICAgICAgaWYgKHRoLnRoUGlubmVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkgIT0gcGlubmVkcylcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy51dGlsaXRpZXMuYXJyYXlNb3ZlKHRocywgaSwgcGlubmVkcyk7XHJcbiAgICAgICAgICAgICAgICAgICAgcGlubmVkcysrO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIC8vSW4gcXVlc3RvIGNhc28gc29ubyBpbmZvcm1hemlvbmkgc3RhdGljaGUgaW52ZWNlLCBub24gbW9kaWZpY2FiaWxpIGRhbGwndXRlbnRlLCBxdWluZGkgbm9uIG1pIGTDsiBwcmVvY2N1cGF6aW9uaVxyXG4gICAgICAgICAgICAgICAgaWYgKCh0aC50aEZpeGVkIHx8IHRoLnRoR3JvdXApICYmICF0aC50aFBpbm5lZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChpICE9IHBpbm5lZHMgKyBmaXhlZHMpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudXRpbGl0aWVzLmFycmF5TW92ZSh0aHMsIGksIHBpbm5lZHMgKyBmaXhlZHMpO1xyXG4gICAgICAgICAgICAgICAgICAgIGZpeGVkcysrO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodGhpcy51dGlsaXRpZXMuaXNFc1RoKHRoc1swXSkgfHwgdGhpcy51dGlsaXRpZXMuaXNFc1RkKHRkc1swXSkpXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgLy8gQ2FjaGUgZGVnbGkgaW5kaWNpIHBlciByaXBvc2l6aW9uYXJlIGkgdGQgY29tZSBpIHRoXHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aHMubGVuZ3RoOyBpKyspXHJcbiAgICAgICAgICAgIGNvbHVtbnNJbmRleENhY2hlWyg8RXNUaERpcmVjdGl2ZT50aHNbaV0pLnRoXSA9IGk7XHJcblxyXG4gICAgICAgIC8vIFJpb3JkaW5vIGxlIGNlbGxlIHBlciBmYXJnbGkgbWFudGVuZXJlIGxhIHN0ZXNzYSBzdHJ1dHR1cmEgZGVpIHRoXHJcbiAgICAgICAgbGV0IG5ld1RkcyA9IG5ldyBBcnJheSh0aHMubGVuZ3RoKTtcclxuXHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0ZHMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgbGV0IGl0ZW0gPSB0ZHNbaV0gYXMgRXNUZERpcmVjdGl2ZTtcclxuICAgICAgICAgICAgbmV3VGRzW2NvbHVtbnNJbmRleENhY2hlW2l0ZW0udGRdXSA9IGl0ZW07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLmVzdC5IYXNQaW5uZWRDb2x1bW5zID0gcGlubmVkcyA+IDA7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEluIGJhc2UgYWxsYSBjb25maWd1cmF6aW9uZSBkZWxsZSBjb2xvbm5lIGNhbGNvbGEgbGUgZGltZW5pb25pIGRlbGxlIGNvbG9ubmUgcGlubmF0ZSAqL1xyXG4gICAgcHVibGljIGV2YWx1YXRlUGlubmVkQ29sdW1uc1dpZHRoKCkge1xyXG4gICAgICAgIGlmICghdGhpcy5lc3QuSGFzUGlubmVkQ29sdW1ucylcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICB0aGlzLmVzdC5QaW5uZWRDb250YWluZXJXaWR0aCA9IDA7XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmVzdC5Db2x1bW5zTGlzdC5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgY29sID0gdGhpcy5lc3QuQ29sdW1uc0xpc3RbaV07XHJcbiAgICAgICAgICAgIGlmIChjb2wucGlubmVkICYmIGNvbC52aXNpYmxlKVxyXG4gICAgICAgICAgICAgICAgdGhpcy5lc3QuUGlubmVkQ29udGFpbmVyV2lkdGggKz0gY29sLnBpbm5lZFdpZHRoO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLmVzdC5QaW5uZWRDb250YWluZXJXaWR0aCArPSB0aGlzLmVzdC5TZWxlY3Rpb24gPyAyNSA6IDA7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUZXJtaW5hdG8gaWwgYmluZGluZyBkZWxsZSBjb2xvbm5lIGRhICoqcmV2aWV3Q29sdW1uc0xpc3QqKiBlIGRlbGxhICoqVmlldyoqIGRhbCAqKndyaXRlVmFsdWUqKiBxdWVzdG8gbWV0b2RvIHNpIG9jY3VwYVxyXG4gICAgICogZGVsbCdhbGxpbmVhbWVudG8gZGVsbGUgaW5mb3JtYXppb25pIGZyYSBsZSBjb2xvbm5lIGNhbGNvbGF0ZSBpbnRlcm5hbWVudGUgZSBsZSBpbmZvcm1hemlvbmkgc3VsbGUgY29sb25uZSBjaGUgYXJyaXZhbm8gZGFsbCdBcHBTZWFyY2hcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge0FwcFNlYXJjaDxhbnk+fSB2aWV3IEFwcFNlYXJjaCBkYSB1dGlsaXp6YXJlIHBlciBxdWVzdGEgb3BlcmF6aW9uZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgYWxpZ25Db2x1bW5zSWZMb2FkZWRWaWV3KHZpZXc6IEFwcFNlYXJjaDxhbnk+KSB7XHJcbiAgICAgICAgbGV0IGVtaXRDaGFuZ2VkID0gdGhpcy5lc3Qudmlld01vZGUgJiYgdmlldy5zYXZlZHN0YXRlO1xyXG4gICAgICAgIGxldCBuZXdDb2xzZXQgPSBbXTtcclxuXHJcbiAgICAgICAgaWYgKCF0aGlzLmVzdC5Db2x1bW5zTGlzdCB8fCB0aGlzLmVzdC5Db2x1bW5zTGlzdC5sZW5ndGggPT0gMClcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICBsZXQgY29sdW1ucyA9IHRoaXMuZXN0LnZpZXdNb2RlID8gdmlldy5jb2x1bW5zIDogdGhpcy5lc3QuYXJyYXlDb2x1bW5zO1xyXG4gICAgICAgIHRoaXMuZXN0LkNvbHVtbnNMaXN0LmZvckVhY2goYyA9PiB7XHJcbiAgICAgICAgICAgIC8vIFNlIGxhIGNvbG9ubmEgw6ggcGlubmF0YSBtaSBhcnJpdmEgY29sIHNpbW9sZW9uLCBtYSBhbmNoZSBzZSDDqCB1bmEgY29tcG9zaXppb25lIGRpIHBpw7kgY29sb25uZVxyXG4gICAgICAgICAgICBsZXQgZXhDbCA9IGNvbHVtbnMuZmlsdGVyKGNjID0+IChjYy5zdGFydHNXaXRoKCfCpycpID8gY2Muc3Vic3RyaW5nKDEpIDogY2MpID09IGMuaWQpO1xyXG5cclxuICAgICAgICAgICAgLy8gU2UgbGEgY29sb25uYSDDqCBwaW5uYXRhIGFnZ2lvcm5vIGwnaW5mb3JtYXppb25lIG5lbGxhIHZpZXdcclxuICAgICAgICAgICAgaWYgKGV4Q2wubGVuZ3RoID09IDEpXHJcbiAgICAgICAgICAgICAgICBjLnBpbm5lZCA9IGV4Q2xbMF0uc3RhcnRzV2l0aCgnwqcnKTtcclxuXHJcbiAgICAgICAgICAgIC8vIFNlIGwnYXBwc2VhcmNoIHZpZW5lIGRhIHVubyBzdGF0byBwcmVjZWRlbnRlLCB1c28gbGUgaW5mb3JtYXppb25pIHN1bGxlIGNvbG9ubmUgY2hlIGhhIGRlbnRybywgYWx0cmltZW50aSBzb3ZyYXNjcml2byB0dXR0byAgKipcclxuICAgICAgICAgICAgaWYgKGMudmlzaWJsZSAmJiBjb2x1bW5zLmxlbmd0aCA9PSAwKVxyXG4gICAgICAgICAgICAgICAgbmV3Q29sc2V0LnB1c2goYy5pZCk7XHJcblxyXG4gICAgICAgICAgICAvLyBTZSBobyB1bmEgY29sb25uYSBsYXRvIEFwcFNlYXJjaCBlIG5lbGxhIENvbHVtbkxpc3Qgbm9uIMOoIHZpc2liaWxlLCBhbGxpbmVvIGFsbCdBcHBTZWFyY2hcclxuICAgICAgICAgICAgZWxzZSBpZiAoZXhDbC5sZW5ndGggPT0gMSAmJiAhYy52aXNpYmxlKVxyXG4gICAgICAgICAgICAgICAgYy52aXNpYmxlID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgICAgIC8vIEFsbGluZWFtZW50byBzdWxsJ0FwcFNlYXJjaCBwZXIgY2FzaXN0aWNoZSBpbnZlcnNlIGFsIGRpIHNvcHJhXHJcbiAgICAgICAgICAgIGVsc2UgaWYgKGV4Q2wubGVuZ3RoID09IDAgJiYgYy52aXNpYmxlKVxyXG4gICAgICAgICAgICAgICAgYy52aXNpYmxlID0gZmFsc2U7XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIC8vIE5vbiBobyBjb2xvbm5lIG5lbGxhIGFwcHNlYXJjaCwgdnVvbCBkaXJlIGNoZSBzb25vIGFsIHByaW1vIGJpbmRpbmdcclxuICAgICAgICBpZiAoY29sdW1ucy5sZW5ndGggPT0gMCkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5lc3Qudmlld01vZGUpXHJcbiAgICAgICAgICAgICAgICB2aWV3LmNvbHVtbnMgPSBuZXdDb2xzZXQ7XHJcbiAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgIHRoaXMuZXN0LmFycmF5Q29sdW1ucyA9IG5ld0NvbHNldDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICgodGhpcy5lc3Qudmlld01vZGUgJiYgdmlldy5zYXZlZHN0YXRlKSAmJiB0aGlzLmVzdC5Db2x1bW5zT3JkZXJpbmcgJiYgdmlldy5jb2x1bW5fb3JkZXJpbmcubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICAvLyBTY29ycm8gZ2xpIG9yZGluYW1lbnRpIGNoZSBhdmV2byBzYWx2YXRvIGUgcmljcmVvIGxhIENvbHVtbnNMaXN0IGluIGJhc2UgYSBsb3JvXHJcbiAgICAgICAgICAgIGxldCBuZXdDb2xMaXN0ID0gW107XHJcbiAgICAgICAgICAgIHZpZXcuY29sdW1uX29yZGVyaW5nLmZvckVhY2goY28gPT4ge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5lc3QuQ29sdW1uc0xpc3QuZm9yRWFjaChjID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoYy5pZCA9PSBjbylcclxuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q29sTGlzdC5wdXNoKGMpO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgLy8gUmVjdXBlcm8gYW5jaGUgY2FtcGkgbnVvdmkgY2hlIG5lbGwnaXRlcmF6aW9uZSB2ZWNjaGlhIG5vbiBjJ2VyYW5vIChzZXJ2ZSBkdXJhbnRlIGxvIHN2aWx1cHBvIGluIG1vZG8gZGEgbm9uIHBlcmRlcnNpIGZyYSB1biBFRElUICsgRjUgZSBsJ2FsdHJvKVxyXG4gICAgICAgICAgICB0aGlzLmVzdC5Db2x1bW5zTGlzdC5mb3JFYWNoKGMgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFuZXdDb2xMaXN0LmZpbmQodCA9PiB0ID09IGMuaWQpKVxyXG4gICAgICAgICAgICAgICAgICAgIG5ld0NvbExpc3QucHVzaChjKTtcclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICB0aGlzLmVzdC5Db2x1bW5zTGlzdCA9IG5ld0NvbExpc3Q7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBJbiBvZ25pIGNhc28gcXVlc3RvIG5vbiBtaSBzZXJ2ZSBwacO5LCBsbyByZXNldHRvICAqKlxyXG4gICAgICAgIGlmICh0aGlzLmVzdC52aWV3TW9kZSlcclxuICAgICAgICAgICAgdmlldy5zYXZlZHN0YXRlID0gZmFsc2U7XHJcblxyXG4gICAgICAgIGlmIChlbWl0Q2hhbmdlZClcclxuICAgICAgICAgICAgdGhpcy5lc3QuY2hhbmdlZCgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSW4gYmFzZSBhbGxhIHZpc2liaWxpdMOgIHJlZ2lzdHJhdGEgbmVsbGUgKipDb2x1bW5zTGlzdCoqIHF1ZXN0byBtZXRvZG8gc2kgb2NjdXBhIGRpIHByZW5kZXJlIHR1dHRpIGkgKipFc1RocyoqIGVkICoqRXNUZHMqKiByZWxhdGl2aSBlIG5hc29uZGVybGkvbW9zdHJhcmxpXHJcbiAgICAgKlxyXG4gICAgICogQ29zdG86IDEgc2NhbiBDb2x1bW5zTGlzdCwgMSBzY2FuIEVzVGhzLCAxIHNjYW4gRXNUZHNcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge0VzVGhbXSB8IEVzVGhEaXJlY3RpdmVbXX0gdGhzIEhlYWRlciBkZWxsYSB0YWJlbGxhXHJcbiAgICAgKiBAcGFyYW0ge0VzVGRbXSB8IEVzVGREaXJlY3RpdmVbXX0gdGRzIENlbGxlIGRlbGxhIHRhYmVsbGFcclxuICAgICAqIEBwYXJhbSB7QXBwU2VhcmNoPGFueT59IHZpZXcgQXBwU2VhcmNoIGRhIHV0aWxpenphcmUgcGVyIHF1ZXN0YSBvcGVyYXppb25lXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyByZWZyZXNoQ29sdW1uc1Zpc2liaWxpdHkodGhzOiBFc1RoW10gfCBFc1RoRGlyZWN0aXZlW10sIHRkczogRXNUZFtdIHwgRXNUZERpcmVjdGl2ZVtdLCB2aWV3OiBBcHBTZWFyY2g8YW55Pikge1xyXG4gICAgICAgIGxldCBuZXdDb2xzZXQgPSBbXTtcclxuICAgICAgICBsZXQgZml4ZWRUaHM6IHsgW2lkOiBzdHJpbmddOiBib29sZWFuOyB9ID0ge307XHJcbiAgICAgICAgbGV0IGNvbHVtbnNDYWNoZTogeyBbaW5kZXg6IHN0cmluZ106IEVzVGFibGVDb2x1bW47IH0gPSB7fTtcclxuICAgICAgICBmb3IgKGxldCBjb2xpID0gMDsgY29saSA8IHRoaXMuZXN0LkNvbHVtbnNMaXN0Lmxlbmd0aDsgY29saSsrKSB7XHJcbiAgICAgICAgICAgIGxldCBjb2wgPSB0aGlzLmVzdC5Db2x1bW5zTGlzdFtjb2xpXTtcclxuICAgICAgICAgICAgY29sdW1uc0NhY2hlW2NvbC5pZF0gPSBjb2w7XHJcbiAgICAgICAgICAgIGlmIChjb2wudmlzaWJsZSlcclxuICAgICAgICAgICAgICAgIG5ld0NvbHNldC5wdXNoKChjb2wucGlubmVkID8gXCLCp1wiIDogXCJcIikgKyBjb2wuaWQpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAodmlldylcclxuICAgICAgICAgICAgdmlldy5jb2x1bW5zID0gbmV3Q29sc2V0O1xyXG5cclxuICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgIHRoaXMuZXN0LmFycmF5Q29sdW1ucyA9IG5ld0NvbHNldDtcclxuXHJcbiAgICAgICAgLy8gRGEgcXVpIGluIHBvaSBkZXZvbm8gZXNzZXJlIGVzZWd1aXRpIFNPTE8gaW4gZmFzZSBkaSB3cml0ZVZhbHVlIHF1aW5kaSBkZXZvIGFzc2ljdXJhcm1pIGRpIHBhc3NhcmxpIG51bGwgaW4gdHV0dGkgaSBwYXNzYWdnaSBkaXZlcnNpIGRhIHF1ZWxsb1xyXG4gICAgICAgIGlmICh0aHMpIHtcclxuICAgICAgICAgICAgLy8gRGVmaW5pc2NvIHNlIGxhIGNvbG9ubmEgw6ggdmlzaWJpbGUgaW4gYmFzZSBhbGxhIHN1YSByYXBwcmVzZW50YXppb25lIGxvY2FsZSBpbiBDb2x1bW5zTGlzdFxyXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRocy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgbGV0IHRoID0gdGhzW2ldO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnV0aWxpdGllcy5pc0VzVGgodGgpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGguVmlzaWJsZSA9IHRoLkZpeGVkIHx8IChjb2x1bW5zQ2FjaGVbdGguSURdID8gY29sdW1uc0NhY2hlW3RoLklEXS52aXNpYmxlIDogdGguVmlzaWJsZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoLkZpeGVkKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBmaXhlZFRoc1t0aC5JRF0gPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGgudGhWaXNpYmxlID0gdGgudGhGaXhlZCB8fCAoY29sdW1uc0NhY2hlW3RoLnRoXSA/IGNvbHVtbnNDYWNoZVt0aC50aF0udmlzaWJsZSA6IHRoLnRoVmlzaWJsZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoLnRoRml4ZWQgfHwgdGgudGhHcm91cClcclxuICAgICAgICAgICAgICAgICAgICAgICAgZml4ZWRUaHNbdGgudGhdID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRkcykge1xyXG4gICAgICAgICAgICAvLyBEZWZpbmlzY28gc2UgbGEgY2VsbGEgw6ggdmlzaWJpbGUgaW4gYmFzZSBhbGxhIHN1YSByYXBwcmVzZW50YXppb25lIGxvY2FsZSBpbiBDb2x1bW5zTGlzdFxyXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRkcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgbGV0IHRkID0gdGRzW2ldO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnV0aWxpdGllcy5pc0VzVGQodGQpKVxyXG4gICAgICAgICAgICAgICAgICAgIHRkLlZpc2libGUgPSBmaXhlZFRoc1t0ZC5JRF0gfHwgKGNvbHVtbnNDYWNoZVt0ZC5JRF0gPyBjb2x1bW5zQ2FjaGVbdGQuSURdLnZpc2libGUgOiB0ZC5WaXNpYmxlKTtcclxuXHJcbiAgICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAgICAgdGQudGRWaXNpYmxlID0gZml4ZWRUaHNbdGQudGRdIHx8IChjb2x1bW5zQ2FjaGVbdGQudGRdID8gY29sdW1uc0NhY2hlW3RkLnRkXS52aXNpYmxlIDogdGQudGRWaXNpYmxlKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5lc3QuY2hhbmdlZCgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQWxsaW5lYSBnbGkgb3JkaW5hbWVudGkgZGF0aSBmcmEgbGUgKipFc1RocyoqIGUgbGUgaW5mb3JtYXppb25pIGFsbCdpbnRlcm5vIGRlbGxhIFZpZXcgYmluZGF0YVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7QXBwU2VhcmNoPGFueT59IHZpZXcgQXBwU2VhcmNoIGRhIHV0aWxpenphcmUgcGVyIHF1ZXN0YSBvcGVyYXppb25lXHJcbiAgICAgKiBAcGFyYW0ge0VzVGhbXSB8IEVzVGhEaXJlY3RpdmVbXX0gdGhzIENvbG9ubmUgZGVsbGEgdGFiZWxsYVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgYWxpZ25IZWFkZXJzT3JkZXJpbmcodGhzOiBFc1RoW10gfCBFc1RoRGlyZWN0aXZlW10sIHZpZXc6IEFwcFNlYXJjaDxhbnk+KSB7XHJcbiAgICAgICAgbGV0IG9yZGVycyA9IHZpZXcgPyB2aWV3Lm9yZGVycyA6IHRoaXMuZXN0LmFycmF5T3JkZXJzO1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGxldCB0aCA9IHRoc1tpXTtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLnV0aWxpdGllcy5pc0VzVGgodGgpKSB7XHJcbiAgICAgICAgICAgICAgICB0aC5PcmRlciA9IG51bGw7XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gQXNzZWdubyB0dXR0aSBnbGkgb3JkaW5hbWVudGkgY2hlIG1pIHZlbmdvbm8gZGEgQXBwU2VhcmNoLiBTb25vIGkgcGnDuSBpbXBvcnRhbnRpLiBOb24gZmFjY2lvIGNhY2hlIG8gY29zZSBzdHJhbm8gcGVyY2jDqSB0YW50byBxdWVzdGFcclxuICAgICAgICAgICAgICAgIC8vIHZhcmlhYmlsZSBzYXLDoCBzZW1wcmUgbWFzc2ltbyAzIGVsZW1lbnRpXHJcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG9yZGVycy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBvciA9IG9yZGVyc1tpXTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAob3IuaWQgPT0gdGguSUQpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoLk9yZGVyID0gb3Iub3JkZXI7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICB0aC50aE9yZGVyID0gbnVsbDtcclxuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3JkZXJzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IG9yID0gb3JkZXJzW2ldO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChvci5pZCA9PSB0aC50aClcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGgudGhPcmRlciA9IG9yLm9yZGVyO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2VuZXJhIHR1dHRlIGxlIGluZm9ybWF6aW9uaSBjaGUgc2Vydm9ubyBwZXIgZ2VzdGlyZSBpbCByYWdncnVwcGFtZW50byBkZWdsaSBoZWFkZXJcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge0VzVGhbXSB8IEVzVGhEaXJlY3RpdmVbXX0gdGhzIENvbG9ubmUgZGVsbGEgdGFiZWxsYVxyXG4gICAgICpcclxuICAgICAqIEByZXR1cm5zIHt7IGxlYWZzOiBFc1RoW10gfCBFc1RoRGlyZWN0aXZlW10sIGdyb3VwaW5nTGV2ZWw6IG51bWJlciwgcGFyZW50c0NhY2hlOiBhbnksIHRoc0NhY2hlOiBhbnkgfX0gT2dnZXR0byBjb250ZW5lbnRlIGxhIGxpc3RhIGRlbGxlIGZvZ2xpZSAoaGVhZGVyIGJhc2UpLCBpbCBsaXZlbGxvXHJcbiAgICAgKiBtYXNzaW1vIGRpIHJhZ2dydXBwYW1lbnRvIHJhZ2dpdW50bywgdW5hIGNhY2hlIGluIGN1aSB2ZW5nb25vIGluZGljYXRpIHR1dHRpIGkgZ3J1cHBpIGNoZSBzb25vIFwicGFyZW50XCIgKHF1aW5kaSBjaGUgcmFnZ3J1cHBhbm8gYWxtZW5vIDEgaGVhZGVyKSBlIGxhIGNhY2hlIGRlZ2xpIGhlYWRlclxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZXZhbHVhdGVIZWFkZXJzR3JvdXBpbmdJbmZvcyh0aHM6IEVzVGhbXSB8IEVzVGhEaXJlY3RpdmVbXSk6IHsgbGVhZnM6IEVzVGhbXSB8IEVzVGhEaXJlY3RpdmVbXTsgZ3JvdXBpbmdMZXZlbDogbnVtYmVyOyBwYXJlbnRzQ2FjaGU6IGFueTsgdGhzQ2FjaGU6IGFueTsgfSB7XHJcbiAgICAgICAgLy8gUHJlZ2lybyBwZXIgdHJvdmFyZSBpIHBhcmVudFxyXG4gICAgICAgIGxldCBwYXJlbnRzQ2FjaGU6IHsgW2luZGV4OiBzdHJpbmddOiBib29sZWFuOyB9ID0ge307XHJcbiAgICAgICAgbGV0IHRoc0NhY2hlOiB7IFtpbmRleDogc3RyaW5nXTogRXNUaERpcmVjdGl2ZTsgfSA9IHt9O1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGxldCB0aCA9IHRoc1tpXTtcclxuICAgICAgICAgICAgaWYgKHRoaXMudXRpbGl0aWVzLmlzRXNUaCh0aCkpXHJcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcclxuXHJcbiAgICAgICAgICAgIHRoc0NhY2hlW3RoLnRoXSA9IHRoO1xyXG4gICAgICAgICAgICBpZiAodGgudGhQYXJlbnQgJiYgIXBhcmVudHNDYWNoZVt0aC50aFBhcmVudF0pXHJcbiAgICAgICAgICAgICAgICBwYXJlbnRzQ2FjaGVbdGgudGhQYXJlbnRdID0gdHJ1ZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIFNlY29uZG8gZ2lybyBwZXIgYmVjY2FyZSBpbCBsaXZlbGxvIG1hc3NpbW8gZSBsYSBsaXN0YSBkaSBmb2dsaWUgKHRoIHNlbnphIHBhcmVudClcclxuICAgICAgICBsZXQgaE1heExldmVsID0gMDtcclxuICAgICAgICBsZXQgbGVhZnM6IGFueVtdID0gW107XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aHMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgbGV0IHRoID0gdGhzW2ldO1xyXG4gICAgICAgICAgICBpZiAodGhpcy51dGlsaXRpZXMuaXNFc1RoKHRoKSkgeyBsZWFmcy5wdXNoKHRoKTsgY29udGludWU7IH1cclxuICAgICAgICAgICAgLy8gU2Ugc29ubyB1bmEgZm9nbGlhIHZlZG8gcXVhbnRpIGxpdmVsbGkgY2kgc29ubyBzb3ByYVxyXG4gICAgICAgICAgICBpZiAoIXBhcmVudHNDYWNoZVt0aC50aF0pIHtcclxuICAgICAgICAgICAgICAgIGxlYWZzLnB1c2godGgpO1xyXG4gICAgICAgICAgICAgICAgbGV0IHRtcCA9IHRoaXMuanVtcHNUb0ZpbmFsUGFyZW50KHRoLCB0aHNDYWNoZSk7XHJcbiAgICAgICAgICAgICAgICBoTWF4TGV2ZWwgPSB0bXAgPiBoTWF4TGV2ZWwgPyB0bXAgOiBoTWF4TGV2ZWw7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB7IGxlYWZzOiBsZWFmcywgZ3JvdXBpbmdMZXZlbDogaE1heExldmVsLCBwYXJlbnRzQ2FjaGU6IHBhcmVudHNDYWNoZSwgdGhzQ2FjaGU6IHRoc0NhY2hlIH07XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZW5lcmEgZ2xpIGhlYWRlciBncm91cHMgZGEgdW5hIGxpc3RhIGRpIGluZm8gc3VpIHRoIGFsbCdpbnRlcm5vIGRlbGxhIHZhcmlhYmlsZSAqKlRNUFJvd1RoR3JvdXBzKipcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge3sgbGVhZnM6IEVzVGhbXSB8IEVzVGhEaXJlY3RpdmVbXSwgZ3JvdXBpbmdMZXZlbDogbnVtYmVyLCBwYXJlbnRzQ2FjaGU6IGFueSwgdGhzQ2FjaGU6IGFueSB9fSBpbmZvcyBJbmZvcm1hemlvbmkgZGkgcmFnZ3J1cHBhbWVudG8gdmFsdXRhdGUgcHJlY2VkZW50ZW1lbnRlXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBldmFsdWF0ZUhlYWRlckdyb3VwcyhpbmZvczogeyBsZWFmczogRXNUaFtdIHwgRXNUaERpcmVjdGl2ZVtdOyBncm91cGluZ0xldmVsOiBudW1iZXI7IHBhcmVudHNDYWNoZTogYW55OyB0aHNDYWNoZTogYW55OyB9KSB7XHJcbiAgICAgICAgaWYgKGluZm9zLmdyb3VwaW5nTGV2ZWwgPT0gMClcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICAvLyBHaXJvIDIuNSwgY3JlbyBsJ291dHB1dCBkZWkgcmFnZ3J1cHBhbWVudGkgcGVyIGhlYWRlciBpbiBtb2RvIGRhIG5vbiBkb3Zlcm1pIHByZW9jY3VwYXJlIGRpIGNlbGxlIG5vbiBpbml6aWFsaXp6YXRlXHJcbiAgICAgICAgbGV0IGV4cGFuZGVkR3JvdXBzID0gW107XHJcbiAgICAgICAgbGV0IHZpc2libGVVbnBpbm5lZExlYWZzOiBFc1RoRGlyZWN0aXZlW10gPSAoPGFueVtdPmluZm9zLmxlYWZzKS5maWx0ZXIoKHQ6IEVzVGhEaXJlY3RpdmUpID0+IHQudGhWaXNpYmxlICYmICF0LnRoUGlubmVkKTtcclxuICAgICAgICBmb3IgKGxldCBsID0gMDsgbCA8IGluZm9zLmdyb3VwaW5nTGV2ZWw7IGwrKykge1xyXG4gICAgICAgICAgICBleHBhbmRlZEdyb3Vwcy5wdXNoKFtdKTtcclxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB2aXNpYmxlVW5waW5uZWRMZWFmcy5sZW5ndGg7IGkrKylcclxuICAgICAgICAgICAgICAgIGV4cGFuZGVkR3JvdXBzW2xdLnB1c2goXCJcIik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBPcmRpbm8gbGUgZm9nbGllIGluIGJhc2UgYWdsaSBvcmRpbmFtZW50aSBkZWxsZSBjb2xvbm5lXHJcbiAgICAgICAgbGV0IG9yZGVyZWRMZWFmcyA9IFtdO1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5lc3QuT3JkZXJEaXJlY3RpdmVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGxldCBsZWFmOiBFc1RoRGlyZWN0aXZlID0gaW5mb3MudGhzQ2FjaGVbdGhpcy5lc3QuT3JkZXJEaXJlY3RpdmVzW2ldXTtcclxuICAgICAgICAgICAgaWYgKGxlYWYudGhWaXNpYmxlICYmICFsZWFmLnRoUGlubmVkKVxyXG4gICAgICAgICAgICAgICAgb3JkZXJlZExlYWZzLnB1c2gobGVhZik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBUZXJ6byBnaXJvIHBlciBjcmVhcmUgbCdhcnJheSBncm91cCBjb24gdHV0dGkgaSByaWZlcmltZW50aSBkZWwgY2Fzb1xyXG4gICAgICAgIGxldCBjdXJyZW50UGFyZW50ID0gXCJcIjtcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG9yZGVyZWRMZWFmcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgcmVmVGg6IEVzVGhEaXJlY3RpdmUgPSBvcmRlcmVkTGVhZnNbaV07XHJcbiAgICAgICAgICAgIGxldCBwcmV2VGg6IEVzVGhEaXJlY3RpdmUgPSBpIC0gMSA+PSAwID8gb3JkZXJlZExlYWZzW2kgLSAxXSA6IG51bGw7XHJcblxyXG4gICAgICAgICAgICAvLyBQYXJlbnQgZGl2ZXJzbyBkYSBwcmltYSwgbWV0dG8gaWwgYm9yZG8gYSBzaW5pc3RyYSBlIGEgZGVzdHJhIGRlbGxhIGNlbGxhIHByZWNlZGVudGUgKHNlIGMnw6gpXHJcbiAgICAgICAgICAgIC8vIEFsbCd1bHRpbW8gZ2lybyBtZXR0byBpbCBib3JkbyBhIGRlc3RyYS4gVHV0dG8gcXVlc3RvIGxvIHJpZXNlZ3VvIHBlciBvZ25pIGNlbGxhIGluIG1vZG8gZGEgcmlwdWxpcmUgZXZlbnR1YWxpIGEgY3VpIGF2ZXZvIGFzc2VnbmF0byB0YWcgcHJlY2VkZW50ZW1lbnRlXHJcbiAgICAgICAgICAgICg8YW55PnJlZlRoKS5fbGJvcmQgPSByZWZUaC50aFBhcmVudCAhPSBjdXJyZW50UGFyZW50O1xyXG4gICAgICAgICAgICAoPGFueT5yZWZUaCkuX3Jib3JkID0gdmlzaWJsZVVucGlubmVkTGVhZnMubGVuZ3RoID09IGkgKyAxO1xyXG4gICAgICAgICAgICBpZiAocHJldlRoKVxyXG4gICAgICAgICAgICAgICAgKDxhbnk+cHJldlRoKS5fcmJvcmQgPSByZWZUaC50aFBhcmVudCAhPSBjdXJyZW50UGFyZW50O1xyXG5cclxuICAgICAgICAgICAgY3VycmVudFBhcmVudCA9IHJlZlRoLnRoUGFyZW50O1xyXG5cclxuICAgICAgICAgICAgLy8gUGVyIG9nbmkgZ3J1cHBvIHNyb3RvbG8gaWwgcGFyZW50IG5lbGxhIG1hdHJpY2UgZGVpIHJhZ2dydXBwYW1lbnRpXHJcbiAgICAgICAgICAgIGZvciAobGV0IGwgPSAwOyBsIDwgaW5mb3MuZ3JvdXBpbmdMZXZlbDsgbCsrKSB7XHJcbiAgICAgICAgICAgICAgICBsZXQgcGFyZW50ID0gcmVmVGgudGhQYXJlbnQ7XHJcbiAgICAgICAgICAgICAgICBpZiAocGFyZW50ICYmICFyZWZUaC50aFBpbm5lZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGV4cGFuZGVkR3JvdXBzW2xdW2ldID0gcGFyZW50O1xyXG4gICAgICAgICAgICAgICAgICAgIHJlZlRoID0gaW5mb3MudGhzQ2FjaGVbcGFyZW50XTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gUXVhcnRvIGdpcm8gcGVyIGNvbXBhdHRhcmxvIG5lbGwnZWxlbWVudG8gZmluYWxlIHN1IGN1aSBiaW5kYXJtaVxyXG4gICAgICAgIGN1cnJlbnRQYXJlbnQgPSBcIlwiO1xyXG4gICAgICAgIGxldCBjdXJyZW50U3BhbiA9IDA7XHJcbiAgICAgICAgdGhpcy5lc3QuVE1QUm93VGhHcm91cHMgPSBbXTtcclxuICAgICAgICBmb3IgKGxldCBsID0gMDsgbCA8IGV4cGFuZGVkR3JvdXBzLmxlbmd0aDsgbCsrKSB7XHJcbiAgICAgICAgICAgIGxldCBsZXZlbEFycmF5OiB7IFNwYW46IG51bWJlcjsgVGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47IFBpbm5lZD86IGJvb2xlYW47IEJvcmRlcnM/OiBib29sZWFuOyB9W10gPSBbXTtcclxuICAgICAgICAgICAgdGhpcy5lc3QuVE1QUm93VGhHcm91cHMucHVzaChsZXZlbEFycmF5KTtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLmVzdC5TZWxlY3Rpb24gfHwgdGhpcy5lc3QuSGFzUGlubmVkQ29sdW1ucylcclxuICAgICAgICAgICAgICAgIGxldmVsQXJyYXkucHVzaCh7IFNwYW46IDEsIFRlbXBsYXRlOiBudWxsLCBQaW5uZWQ6IHRoaXMuZXN0Lkhhc1Bpbm5lZENvbHVtbnMgfSk7XHJcblxyXG4gICAgICAgICAgICBmb3IgKGxldCBoID0gMDsgaCA8IGV4cGFuZGVkR3JvdXBzW2xdLmxlbmd0aDsgaCsrKSB7XHJcbiAgICAgICAgICAgICAgICBsZXQgaXRlbSA9IGV4cGFuZGVkR3JvdXBzW2xdW2hdO1xyXG4gICAgICAgICAgICAgICAgaWYgKGl0ZW0gPT0gY3VycmVudFBhcmVudClcclxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50U3BhbisrO1xyXG4gICAgICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRTcGFuID4gMClcclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxBcnJheS5wdXNoKHsgU3BhbjogY3VycmVudFNwYW4sIFRlbXBsYXRlOiAoY3VycmVudFBhcmVudCA/IGluZm9zLnRoc0NhY2hlW2N1cnJlbnRQYXJlbnRdLlRlbXBsYXRlIDogbnVsbCksIEJvcmRlcnM6ICEhY3VycmVudFBhcmVudCB9KTtcclxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50U3BhbiA9IDE7XHJcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudFBhcmVudCA9IGl0ZW07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIFVsdGltYSBhZ2dpdW50YSBjaGUgYWx0cmltZW50aSBtaSByaW1hcnJlYmJlIGluIGNhY2hlXHJcbiAgICAgICAgICAgIGxldmVsQXJyYXkucHVzaCh7IFNwYW46IGN1cnJlbnRTcGFuLCBUZW1wbGF0ZTogKGN1cnJlbnRQYXJlbnQgPyBpbmZvcy50aHNDYWNoZVtjdXJyZW50UGFyZW50XS5UZW1wbGF0ZSA6IG51bGwpLCBCb3JkZXJzOiAhIWN1cnJlbnRQYXJlbnQgfSk7XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5lc3QuUmVtb3ZhbClcclxuICAgICAgICAgICAgICAgIGxldmVsQXJyYXkucHVzaCh7IFNwYW46IDEsIFRlbXBsYXRlOiBudWxsIH0pO1xyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMuZXN0LkV4cG9ydCB8fCB0aGlzLmVzdC5IaWRkZW5Db2x1bW5zIHx8IHRoaXMuZXN0LkNvbHVtbnNPcmRlcmluZyB8fCB0aGlzLmVzdC5Db3JuZXJNZW51T3B0aW9ucylcclxuICAgICAgICAgICAgICAgIGxldmVsQXJyYXkucHVzaCh7IFNwYW46IDEsIFRlbXBsYXRlOiBudWxsIH0pO1xyXG5cclxuICAgICAgICAgICAgY3VycmVudFNwYW4gPSAwO1xyXG4gICAgICAgICAgICBjdXJyZW50UGFyZW50ID0gXCJcIjtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDYWxjb2xhIGlsIG51bWVybyBkaSBzYWx0aSBkYSB1biBoZWFkZXIgZm9nbGlhIGFsbCd1bHRpbW8gcGFyZW50IGRlbGxhIGNhdGVuYVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7RXNUaERpcmVjdGl2ZX0gdGggSGVhZGVyIGRhIGN1aSBzY29ycmVyZSBpIHBhZHJpIHBlciBjYXBpcmUgcXVhbnRpIGxpdmVsbGkgY2kgc29ubyBzb3ByYVxyXG4gICAgICogQHBhcmFtIHt7IFtpbmRleDogc3RyaW5nXTogRXNUaERpcmVjdGl2ZSB9fSB0aHNDYWNoZSBDYWNoZSBkZWdsaSBoZWFkZXJcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBqdW1wc1RvRmluYWxQYXJlbnQodGg6IEVzVGhEaXJlY3RpdmUsIHRoc0NhY2hlOiB7IFtpbmRleDogc3RyaW5nXTogRXNUaERpcmVjdGl2ZTsgfSkge1xyXG4gICAgICAgIGxldCBqdW1wcyA9IDA7IGxldCBwYXJlbnQgPSBudWxsOyBsZXQgcGFyZW50c1ByZXBlbmQ6IFRlbXBsYXRlUmVmPGFueT5bXSA9IFtdO1xyXG4gICAgICAgIGxldCBiYXNlVGhSZWYgPSB0aDtcclxuICAgICAgICBkbyB7XHJcbiAgICAgICAgICAgIHBhcmVudCA9IHRoLnRoUGFyZW50O1xyXG4gICAgICAgICAgICBpZiAocGFyZW50KSB7XHJcbiAgICAgICAgICAgICAgICB0aCA9IHRoc0NhY2hlW3BhcmVudF07XHJcbiAgICAgICAgICAgICAgICBpZiAoIXRoLnRoRW1wdHkpXHJcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50c1ByZXBlbmQudW5zaGlmdCh0aC5UZW1wbGF0ZSk7XHJcbiAgICAgICAgICAgICAgICBqdW1wcysrO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSB3aGlsZSAocGFyZW50KTtcclxuICAgICAgICBiYXNlVGhSZWYuX3RoUGFyZW50cyA9IHBhcmVudHNQcmVwZW5kO1xyXG4gICAgICAgIHJldHVybiBqdW1wcztcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIE1ldG9kbyBjaGUgZ2VuZXJhIGwnb3JkaW5lIGRpIGRlZmF1bHQgZGVsbGUgY29sb25uZVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7QXBwU2VhcmNoPGFueT59IHZpZXcgQXBwU2VhcmNoIGRhIHV0aWxpenphcmUgcGVyIHF1ZXN0YSBvcGVyYXppb25lXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBnZW5lcmF0ZURlZmF1bHRPcmRlcih0aHM6IEVzVGhbXSB8IEVzVGhEaXJlY3RpdmVbXSwgdmlldzogQXBwU2VhcmNoPGFueT4pIHtcclxuICAgICAgICBpZiAodGhzLmxlbmd0aCA9PSAwKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgIGxldCBvcmRlcmluZ3MgPSB0aGlzLmVzdC52aWV3TW9kZSA/IHZpZXcuY29sdW1uX29yZGVyaW5nIDogdGhpcy5lc3QuYXJyYXlDb2x1bW5PcmRlcmluZztcclxuICAgICAgICAvLyBHZW5lcm8gb3JkaW5hbWVudG8gZGkgZGVmYXVsdCBkYSAwIGZpbm8gYSBkb3ZlIGRldmUgYXJyaXZhcmUuIFNpdHVhemlvbmUgYXR0dWFsZSBzZW56YSBob3Rwb3RhdG9cclxuICAgICAgICBpZiAoIW9yZGVyaW5ncyB8fCBvcmRlcmluZ3MubGVuZ3RoID09IDApIHtcclxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aHMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgIGxldCB0aCA9IHRoc1tpXTtcclxuICAgICAgICAgICAgICAgIGxldCBvcmRlciA9IHRoaXMudXRpbGl0aWVzLmlzRXNUaCh0aCkgPyB0aC5JRCA6IHRoLnRoO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5lc3QuT3JkZXJEaXJlY3RpdmVzLnB1c2gob3JkZXIpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICB0aGlzLmVzdC5PcmRlckRpcmVjdGl2ZXMgPSBvcmRlcmluZ3M7XHJcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBsZXQgdGggPSB0aHNbaV07XHJcbiAgICAgICAgICAgICAgICBsZXQgdGhJZCA9IHRoaXMudXRpbGl0aWVzLmlzRXNUaCh0aCkgPyB0aC5JRCA6IHRoLnRoO1xyXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmVzdC5PcmRlckRpcmVjdGl2ZXMuZmluZChvID0+IG8gPT0gdGhJZCkpXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lc3QuT3JkZXJEaXJlY3RpdmVzLnB1c2godGhJZCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBBcHBsaWNhIGwnb3JkaW5lIHNwZWNpZmljYXRvIGFsbGUgdmFyaWUgY29sb25uZVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7QXBwU2VhcmNoPGFueT59IHZpZXcgQXBwU2VhcmNoIGRhIHV0aWxpenphcmUgcGVyIHF1ZXN0YSBvcGVyYXppb25lXHJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGZpbmFsaXplIFNlICoqdHJ1ZSoqIHNpZ25pZmljYSBjaGUgbm9uIG1pIGFzcGV0dG8gZGkgZG92ZXIgZWZmZXR0dWFyZSBhbHRyZSBvcGVyYXppb25pIGUgcG9zc28gcmVuZGVyaXp6YXJlIGxhIHNpdHVhemlvbmUgaW4gYmFzZSBhaSBSb3dDb250ZXh0XHJcbiAgICAgKiBTZW56YSBmaW5hbGl6ZSBzaWduaWZpY2EgY2hlIG1pIGFzcGV0dG8gYWx0cmUgb3BlcmF6aW9uaSBjaGUgcHJpbWEgbyBwb2kgcmljaGlhbWVyYW5ubyBxdWVzdGEgZnVuemlvbmUgY29sIGZpbmFsaXplLlxyXG4gICAgICpcclxuICAgICAqIEFkIGVzZW1waW8sIHVuYSB2b2x0YSBzZWxlemlvbmF0byBvcmRpbmFtZW50byBmaXNpY28vbG9naWNvIGRlbGxlIGNvbG9ubmUgc28gY2hlIHBhcnRlIHVuIGFsdHJhIHJpY2VyY2EgY2hlIG1pIHJpdmFsb3JpenplcsOgIGRhIFwid3JpdGVWYWx1ZVwiLCBjaGUgZ2nDoCBjaGlhbWEgcXVlc3RhIGZ1bnppb25lLlxyXG4gICAgICogTWV0dGVuZG8gc29sbyBsYSBjaGlhbWF0YSBkYSBcIndyaXRlVmFsdWVcIiBjb21lIFwiZmluYWxpenphbnRlXCIgbWkgYXNzaWN1cm8gY2hlIHNtYW5hdHRhbWVudGkgYSBmcm9udGVuZCBub24gY2F1c2lubyBmbGlja2VyaW5nIGZpbm8gYSBxdWFuZG8gbm9uIHNlcnZvbm9cclxuICAgICAqL1xyXG4gICAgcHVibGljIGFwcGx5T3JkZXJpbmcodmlldzogQXBwU2VhcmNoPGFueT4sIGZpbmFsaXplOiBib29sZWFuKSB7XHJcbiAgICAgICAgLy8gR2VuZXJvIG9yZGluYW1lbnRvIHBlciBnbGkgaGVhZGVyXHJcbiAgICAgICAgbGV0IG5ld0hlYWRlcnMgPSBbXTtcclxuXHJcbiAgICAgICAgLy8gU2UgZGV2byBmaW5hbGl6emFyZSBhZ2dhbmNpbyB0dXR0ZSBsZSB2YXJpYWJpbGkgZGkgYmluZFxyXG4gICAgICAgIGlmIChmaW5hbGl6ZSkge1xyXG4gICAgICAgICAgICB0aGlzLmVzdC5PcmRlckRpcmVjdGl2ZXMuZm9yRWFjaChvID0+IHtcclxuICAgICAgICAgICAgICAgIGxldCBoZWFlZHJJdGVtID0gdGhpcy5lc3QuVE1QUm93VEhzLmZpbHRlcih0ID0+IHQuSUQgPT0gbylbMF07XHJcbiAgICAgICAgICAgICAgICBpZiAoaGVhZWRySXRlbSlcclxuICAgICAgICAgICAgICAgICAgICBuZXdIZWFkZXJzLnB1c2goaGVhZWRySXRlbSk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB0aGlzLmVzdC5UTVBSb3dUSHMgPSBuZXdIZWFkZXJzO1xyXG5cclxuICAgICAgICAgICAgLy8gR2VuZXJvIG9yZGluYW1lbnRvIHBlciBsZSBjZWxsZVxyXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuZXN0LlJvd0NvbnRleHRzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBsZXQgY29udGV4dCA9IHRoaXMuZXN0LlRNUFJvd1REc1t0aGlzLmVzdC5Sb3dDb250ZXh0c1tpXV07XHJcbiAgICAgICAgICAgICAgICBsZXQgbmV3Q29udGV4dCA9IFtdO1xyXG5cclxuICAgICAgICAgICAgICAgIHRoaXMuZXN0Lk9yZGVyRGlyZWN0aXZlcy5mb3JFYWNoKG8gPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBjb250ZXh0SXRlbSA9IGNvbnRleHQuZmlsdGVyKHQgPT4gdC5JRCA9PSBvKVswXTtcclxuICAgICAgICAgICAgICAgICAgICBuZXdDb250ZXh0LnB1c2goY29udGV4dEl0ZW0pO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICAgICAgdGhpcy5lc3QuVE1QUm93VERzW3RoaXMuZXN0LlJvd0NvbnRleHRzW2ldXSA9IG5ld0NvbnRleHQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0aGlzLmVzdC52aWV3TW9kZSlcclxuICAgICAgICAgICAgdmlldy5jb2x1bW5fb3JkZXJpbmcgPSB0aGlzLmVzdC5PcmRlckRpcmVjdGl2ZXM7XHJcblxyXG4gICAgICAgIGVsc2VcclxuICAgICAgICAgICAgdGhpcy5lc3QuYXJyYXlDb2x1bW5PcmRlcmluZyA9IHRoaXMuZXN0Lk9yZGVyRGlyZWN0aXZlcztcclxuXHJcbiAgICAgICAgdGhpcy5lc3QuY2hhbmdlZCgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICogQWxsJ2ludGVybm8gZGVsbGEgZGlhbG9nIFwiT3JkaW5hbWVudG8gZSBWaXNpYmlsaXTDoCBDb2xvbm5lXCIgbWV0dGUgbGEgY29sb25uYSBzcGVjaWZpY2F0YSBwcmltYSBkZWxsYSBjb2xvbm5hIHByZWNlZGVudGVcclxuICAqXHJcbiAgKiBAcGFyYW0ge0VzVGFibGVDb2x1bW59IGNvbHVtbkl0ZW0gQ29sb25uYSBkYSBzcG9zdGFyZVxyXG4gICovXHJcbiAgICBwdWJsaWMgc2VuZFVwKGNvbHVtbkl0ZW06IEVzVGFibGVDb2x1bW4pIHtcclxuICAgICAgICBsZXQgaXRlbUluZGV4ID0gdGhpcy5lc3QuVE1QQ29sdW1uc0xpc3QuaW5kZXhPZihjb2x1bW5JdGVtKTtcclxuICAgICAgICBpZiAodGhpcy5lc3QuVE1QQ29sdW1uc0xpc3RbaXRlbUluZGV4IC0gMV0uZml4ZWQgfHwgdGhpcy5lc3QuVE1QQ29sdW1uc0xpc3RbaXRlbUluZGV4IC0gMV0ucGlubmVkKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgdGhpcy51dGlFeHRzLnN3YXAodGhpcy5lc3QuVE1QQ29sdW1uc0xpc3QsIGl0ZW1JbmRleCwgaXRlbUluZGV4IC0gMSk7XHJcblxyXG4gICAgICAgIC8vIE5vbiBwb3NzbyBmYXJlIEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkodGhpcy5Db2x1bW5zTGlzdCkpIHBlcmNow6kgY29udGllbmUgcmlmZXJpbWVudGkgYSBUZW1wbGF0ZVJlZlxyXG4gICAgICAgIGxldCB0bXAgPSBbXTtcclxuICAgICAgICB0aGlzLmVzdC5UTVBDb2x1bW5zTGlzdC5mb3JFYWNoKGMgPT4geyB0bXAucHVzaChPYmplY3QuYXNzaWduKHt9LCBjKSk7IH0pO1xyXG4gICAgICAgIHRoaXMuZXN0LlRNUENvbHVtbnNMaXN0ID0gdG1wO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQWxsJ2ludGVybm8gZGVsbGEgZGlhbG9nIFwiT3JkaW5hbWVudG8gZSBWaXNpYmlsaXTDoCBDb2xvbm5lXCIgbWV0dGUgbGEgY29sb25uYSBzcGVjaWZpY2F0YSBkb3BvIGxhIGNvbG9ubmEgc3VjY2Vzc2l2YVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7RXNUYWJsZUNvbHVtbn0gY29sdW1uSXRlbSBDb2xvbm5hIGRhIHNwb3N0YXJlXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzZW5kRG93bihjb2x1bW5JdGVtOiBFc1RhYmxlQ29sdW1uKSB7XHJcbiAgICAgICAgbGV0IGl0ZW1JbmRleCA9IHRoaXMuZXN0LlRNUENvbHVtbnNMaXN0LmluZGV4T2YoY29sdW1uSXRlbSk7XHJcbiAgICAgICAgdGhpcy51dGlFeHRzLnN3YXAodGhpcy5lc3QuVE1QQ29sdW1uc0xpc3QsIGl0ZW1JbmRleCwgaXRlbUluZGV4ICsgMSk7XHJcblxyXG4gICAgICAgIC8vIE5vbiBwb3NzbyBmYXJlIEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkodGhpcy5Db2x1bW5zTGlzdCkpIHBlcmNow6kgY29udGllbmUgcmlmZXJpbWVudGkgYSBUZW1wbGF0ZVJlZlxyXG4gICAgICAgIGxldCB0bXAgPSBbXTtcclxuICAgICAgICB0aGlzLmVzdC5UTVBDb2x1bW5zTGlzdC5mb3JFYWNoKGMgPT4geyB0bXAucHVzaChPYmplY3QuYXNzaWduKHt9LCBjKSk7IH0pO1xyXG4gICAgICAgIHRoaXMuZXN0LlRNUENvbHVtbnNMaXN0ID0gdG1wO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQWxsJ2ludGVybm8gZGVsbGEgZGlhbG9nIFwiT3JkaW5hbWVudG8gZSBWaXNpYmlsaXTDoCBDb2xvbm5lXCIgcGlubmEgbGEgY29sb25uYSBzcGVjaWZpY2F0YVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7RXNUYWJsZUNvbHVtbn0gY29sdW1uSXRlbSBDb2xvbm5hIGRhIHNwb3N0YXJlXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBwaW5PclVucGluQ29sdW1uKGNvbHVtbkl0ZW06IEVzVGFibGVDb2x1bW4pIHtcclxuICAgICAgICBsZXQgaXRlbUluZGV4ID0gdGhpcy5lc3QuVE1QQ29sdW1uc0xpc3QuaW5kZXhPZihjb2x1bW5JdGVtKTtcclxuICAgICAgICBpZiAoIWNvbHVtbkl0ZW0ucGlubmVkKSB7XHJcbiAgICAgICAgICAgIGNvbHVtbkl0ZW0ucHJldl9pbmRleCA9IGl0ZW1JbmRleDtcclxuXHJcbiAgICAgICAgICAgIC8vUXVhbmRvIHBpbm5vIGRldm8gc3Bvc3RhcmUgbCdlbGVtZW50byBjb21lIHVsdGltYSBjb2xvbm5hIHBpbm5hdGEgbyBjb21lIHByaW1hIGNvbG9ubmEgc2Ugbm9uIGNlIG5lIHNvbm8gZGkgcGlubmF0ZVxyXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuZXN0LlRNUENvbHVtbnNMaXN0Lmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuZXN0LlRNUENvbHVtbnNMaXN0W2ldLnBpbm5lZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMudXRpbGl0aWVzLmFycmF5TW92ZSh0aGlzLmVzdC5UTVBDb2x1bW5zTGlzdCwgaXRlbUluZGV4LCBpKTtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgLy9RdWFuZG8gc3Bpbm5vIHJpcG9ydG8gbCdlbGVtZW50byBhbGxvIHN0ZXNzbyBpbmRpY2UgaW4gY3VpIGVyYSBwcmltYSAoc2Ugc29ubyBzdGF0aSBmYXR0aSBzcG9zdGFtZW50aSBuZWwgbWV6em8gY2F6emkgZGVsbCd1dGVudGUpXHJcbiAgICAgICAgICAgIGlmIChjb2x1bW5JdGVtLnByZXZfaW5kZXggIT0gbnVsbCAmJiBjb2x1bW5JdGVtLnByZXZfaW5kZXggIT0gdW5kZWZpbmVkKVxyXG4gICAgICAgICAgICAgICAgdGhpcy51dGlsaXRpZXMuYXJyYXlNb3ZlKHRoaXMuZXN0LlRNUENvbHVtbnNMaXN0LCBpdGVtSW5kZXgsIGNvbHVtbkl0ZW0ucHJldl9pbmRleCk7XHJcbiAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgLy8gU2Ugc3Bpbm5vIHNlbnphIHVuIHByZXZfaW5kZXggdnVvbCBkaXJlIGNoZSBsYSBjb2xvbm5hIGVyYSBwaW5uYXRhIGRhIGNvbmZpZ3VyYXppb25lLiBMYSBzcG9zdG8gbmVsIHByaW1vIHB1bnRvIGRpc3BvbmliaWxlXHJcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuZXN0LlRNUENvbHVtbnNMaXN0Lmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmVzdC5UTVBDb2x1bW5zTGlzdFtpXS5waW5uZWQgJiYgIXRoaXMuZXN0LlRNUENvbHVtbnNMaXN0W2ldLmZpeGVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudXRpbGl0aWVzLmFycmF5TW92ZSh0aGlzLmVzdC5UTVBDb2x1bW5zTGlzdCwgaXRlbUluZGV4LCBpIC0gMSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29sdW1uSXRlbS5waW5uZWQgPSAhY29sdW1uSXRlbS5waW5uZWQ7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBBbGwnaW50ZXJubyBkZWxsYSBkaWFsb2cgXCJPcmRpbmFtZW50byBlIFZpc2liaWxpdMOgIENvbG9ubmVcIiBpbnZlcnRlIGxlIGltcG9zdGF6aW9uaSBkaSB2aXNpYmlsaXTDoCBkZWxsYSBjb2xvbm5hXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtFc1RhYmxlQ29sdW1ufSBjb2x1bW5JdGVtIENvbG9ubmEgZGEgc3Bvc3RhcmVcclxuICAgICAqL1xyXG4gICAgcHVibGljIGNvbHVtbkNsaWNrZWQoaXRlbTogRXNUYWJsZUNvbHVtbikge1xyXG4gICAgICAgIHRoaXMuZXN0Lmxhc3RTZWxlY3RlZEl0ZW1JRCA9IGl0ZW0uaWQ7XHJcbiAgICAgICAgaWYgKCF0aGlzLmVzdC5IaWRkZW5Db2x1bW5zIHx8IGl0ZW0uZml4ZWQpXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgaXRlbS52aXNpYmxlID0gIWl0ZW0udmlzaWJsZTtcclxuICAgICAgICB0aGlzLnVwZGF0ZUdsb2JhbENvbFZpc0NoZWNrKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEFsbCdhcGVydHVyYSBkZWxsYSBkaWFsb2cgXCJPcmRpbmFtZW50byBlIFZpc2liaWxpdMOgIENvbG9ubmVcIiByaWNhcmljYSBsZSBpbmZvcm1hemlvbmkgYXR0dWFsaSBwZXIgcGVybWV0dGVyZSBsYSBtb2RpZmljYSAqL1xyXG4gICAgcHVibGljIHJlc2V0Q29sdW1uVmlzU2VsZWN0aW9uKCkge1xyXG4gICAgICAgIHRoaXMuZXN0LlRNUENvbHVtbnNMaXN0ID0gW107XHJcbiAgICAgICAgLy8gTm9uIHBvc3NvIGZhcmUgSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeSh0aGlzLkNvbHVtbnNMaXN0KSkgcGVyY2jDqSBjb250aWVuZSByaWZlcmltZW50aSBhIFRlbXBsYXRlUmVmXHJcbiAgICAgICAgdGhpcy5lc3QuVE1QQ29sdW1uc0xpc3QgPSBbXTtcclxuICAgICAgICB0aGlzLmVzdC5Db2x1bW5zTGlzdC5mb3JFYWNoKGMgPT4geyB0aGlzLmVzdC5UTVBDb2x1bW5zTGlzdC5wdXNoKE9iamVjdC5hc3NpZ24oe30sIGMpKTsgfSk7XHJcblxyXG4gICAgICAgIGxldCByZW9yZGVyZWRDb2xMaXN0ID0gW107XHJcblxyXG4gICAgICAgIGlmICh0aGlzLmVzdC5Db2x1bW5zT3JkZXJpbmcpIHtcclxuICAgICAgICAgICAgdGhpcy5lc3QuT3JkZXJEaXJlY3RpdmVzLmZvckVhY2gobyA9PiB7XHJcbiAgICAgICAgICAgICAgICBsZXQgY29sdW1uID0gdGhpcy5lc3QuVE1QQ29sdW1uc0xpc3QuZmlsdGVyKHQgPT4gdC5pZCA9PSBvKVswXTtcclxuICAgICAgICAgICAgICAgIC8vIFBvdHJlaSBub24gYXZlcm5lIG5lbCBjYXNvIGNpIHNpYSBpbCBmbGFnIEhpZGRlbkNvbHVtbnMgYSBmYWxzZSwgZXZpdG8gZGkgaW5zZXJpcmUgZGVnbGkgdW5kZWZpbmVkXHJcbiAgICAgICAgICAgICAgICBpZiAoY29sdW1uKVxyXG4gICAgICAgICAgICAgICAgICAgIHJlb3JkZXJlZENvbExpc3QucHVzaChjb2x1bW4pO1xyXG4gICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgIHRoaXMuZXN0LlRNUENvbHVtbnNMaXN0ID0gcmVvcmRlcmVkQ29sTGlzdDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMudXBkYXRlR2xvYmFsQ29sVmlzQ2hlY2soKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogUmlhZ2dpb3JuYSBsZSAqKk9yZGVyRGlyZWN0aXZlcyoqIGNvbiBsZSBpbmZvcm1hemlvbmkgaW4gICoqQ29sdW1uc0xpc3QqKiAqL1xyXG4gICAgcHJpdmF0ZSByZWZyZXNoQ29sdW1uT3JkZXJpbmcoKSB7XHJcbiAgICAgICAgdGhpcy5lc3QuT3JkZXJEaXJlY3RpdmVzID0gW107XHJcblxyXG4gICAgICAgIGZvciAobGV0IGMgPSAwOyBjIDwgdGhpcy5lc3QuQ29sdW1uc0xpc3QubGVuZ3RoOyBjKyspXHJcbiAgICAgICAgICAgIHRoaXMuZXN0Lk9yZGVyRGlyZWN0aXZlcy5wdXNoKHRoaXMuZXN0LkNvbHVtbnNMaXN0W2NdLmlkKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogRWZmZXR0dWEgbGEgc2VsZXppb25lIG8gbWVubyBkZWwgY2hlY2sgZ2xvYmFsZSAoKipnbG9iYWxDb2xWaXNDaGVjayoqKSBkaSB2aXNpYmlsaXTDoCBpbiBiYXNlIGEgc2UgdHV0dGUgbGUgKipUTVBDb2x1bW5zTGlzdCoqIHNvbm8gdmlzaWJpbGkgbyBubyAqL1xyXG4gICAgcHVibGljIHVwZGF0ZUdsb2JhbENvbFZpc0NoZWNrKCkge1xyXG4gICAgICAgIC8vIFRNUENvbExpc3QgdmllbmUgcmllbXBpdGEgZGkgdW5kZWZpbmVkIG5lbCBjYXNvIGluIGN1aSBzaWEgZGlzYXR0aXZhdGEgbGEgc2VsZXppb25lIGRlbGxlIGNvbG9ubmUgbmFzY29zdGVcclxuICAgICAgICB0aGlzLmVzdC5nbG9iYWxDb2xWaXNDaGVjayA9IHRoaXMuZXN0LlRNUENvbHVtbnNMaXN0LmV2ZXJ5KHQgPT4gdC52aXNpYmxlKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENoaWFtYXRvIHF1YW5kbyB1bmEgY29sb25uYSB2aWVuZSByaW9yZGluYXRhIGFsbCdpbnRlcm5vIGRlbGxhIGxpc3RhIGRlbGxlIHZpc2liaWxpdMOgL3Bvc2l6aW9uaSBjb2xvbm5lXHJcbiAgICAgKiBcclxuICAgICAqIEBwYXJhbSB7Q2RrRHJhZ0Ryb3A8RXNUYWJsZUNvbHVtbltdPn0gZXZlbnQgRXZlbnRvIGRpIGRyb3AgZGVsbGEgbGlzdGFcclxuICAgICAqL1xyXG4gICAgcHVibGljIGNvbHVtblJlb3JkZXJlZChldmVudDogQ2RrRHJhZ0Ryb3A8RXNUYWJsZUNvbHVtbltdPikge1xyXG4gICAgICAgIG1vdmVJdGVtSW5BcnJheShldmVudC5jb250YWluZXIuZGF0YSwgZXZlbnQucHJldmlvdXNJbmRleCwgZXZlbnQuY3VycmVudEluZGV4KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENoaWFtYXRvIHF1YW5kbyB1bmEgY29sb25uYSB2aWVuZSByaW9yZGluYXRhIGFsbCdpbnRlcm5vIGRlbGxhIGxpc3RhIGRlbGxlIHZpc2liaWxpdMOgL3Bvc2l6aW9uaSBjb2xvbm5lXHJcbiAgICAgKiBcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBpbmRleCBJbmRpY2UgaW4gY3VpIHZvZ2xpbyBkcm9wcGFyZSBsJ2VsZW1lbnRvIGRyYWdnYXRvXHJcbiAgICAgKiBAcGFyYW0ge0Nka0RyYWc8RXNUYWJsZUNvbHVtbj59IGl0ZW0gT2dnZXR0byBjaGUgc3RvIGRyYWdnYW5kb1xyXG4gICAgICogXHJcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gKip0cnVlKiogc2UgbGEgY29sb25uYSBwdcOyIGVzc2VyZSBzcG9zdGF0YSBzdWxsJ2luZGljZSAqKmluZGV4KiosICoqZmFsc2UqKiBhbHRyaW1lbnRpXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzb3J0UHJlZGljYXRlKGluZGV4OiBudW1iZXIsIGl0ZW06IENka0RyYWc8RXNUYWJsZUNvbHVtbj4pOiBib29sZWFuIHtcclxuICAgICAgICBsZXQgaXRlbUF0SW5kZXggPSB0aGlzLmVzdC5Db2x1bW5zTGlzdFtpbmRleF07XHJcbiAgICAgICAgcmV0dXJuICFpdGVtQXRJbmRleC5maXhlZCAmJiAhaXRlbUF0SW5kZXgucGlubmVkICYmICFpdGVtLmRhdGEucGlubmVkICYmICFpdGVtLmRhdGEucGlubmVkO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRnVuemlvbmUgY2hlIGVmZmV0dHVhIGxhIGNvbmZlcm1hIGRlbGxhIHZpc2liaWxpdMOgIGUgZGVsbCdvcmRpbmUgZGVsbGUgY29sb25uZS5cclxuICAgICAqXHJcbiAgICAgKiBRdWVzdGEgc2VsZXppb25lIHZpZW5lIGlub2x0cmUgc2FsdmF0YSBuZWxsZSBwcmVmZXJlbnplICgqKkBlc2ZhZW56YS9wcmVmZXJlbmNlcyoqKSwgcXVhbG9yYSBsJ0lucHV0ICoqU2F2ZVByZWZlcmVuY2VzKiogZm9zc2UgdmFsb3JpenphdG9cclxuICAgICAqXHJcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gKip0cnVlKiogc2Ugbm9uIGNpIHNvbm8gcHJvYmxlbWksICoqZmFsc2UqKiBhbHRyaW1lbnRpXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBjb25maXJtQ29sdW1uVmlzaWJpbGl0eVNlbGVjdGlvbigpOiBib29sZWFuIHtcclxuICAgICAgICAvLyBOb24gcGVybWV0dG8gZGkgbm9uIHNlbGV6aW9uYXJlIG51bGxhXHJcbiAgICAgICAgaWYgKHRoaXMuZXN0LlRNUENvbHVtbnNMaXN0LmV2ZXJ5KHQgPT4gIXQudmlzaWJsZSkpXHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuXHJcbiAgICAgICAgbGV0IGNhc3RlZFZpZXcgPSB0aGlzLmVzdC52aWV3TW9kZSA/ICh0aGlzLmVzdC5NYWluR3JvdXBWaWV3IHx8IHRoaXMuZXN0LlZpZXcgYXMgQXBwU2VhcmNoPGFueT4pIDogbnVsbDtcclxuICAgICAgICB0aGlzLmVzdC5Db2x1bW5zTGlzdCA9IFtdO1xyXG4gICAgICAgIHRoaXMuZXN0LlRNUENvbHVtbnNMaXN0LmZvckVhY2goYyA9PiB7IHRoaXMuZXN0LkNvbHVtbnNMaXN0LnB1c2goT2JqZWN0LmFzc2lnbih7fSwgYykpOyB9KTtcclxuXHJcbiAgICAgICAgdGhpcy5yZWZyZXNoQ29sdW1uT3JkZXJpbmcoKTtcclxuICAgICAgICB0aGlzLmFwcGx5T3JkZXJpbmcoY2FzdGVkVmlldywgZmFsc2UpO1xyXG5cclxuICAgICAgICB0aGlzLnJlZnJlc2hDb2x1bW5zVmlzaWJpbGl0eShudWxsLCBudWxsLCBjYXN0ZWRWaWV3KTtcclxuXHJcbiAgICAgICAgLy9TYWx2byBsZSBwcmVmZXJlbmNlcyBkaSBxdWVzdGEgdmlld1xyXG4gICAgICAgIC8vRGkgZGVmYXVsdCByZWdpc3RybyBvcmRpbmFtZW50byBlIHZpc2liaWxpdMOgIGRlbGxlIGNvbG9ubmUgbmVsbGEgdmlzdGEuIFNvbG8gbGUgY29zZSBkaSBVSVxyXG4gICAgICAgIGlmICh0aGlzLmVzdC5TYXZlUHJlZmVyZW5jZXMpIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmVzdC5uZ0NvbnRyb2wubmFtZSkge1xyXG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIk5vbiBwb3NzbyB1dGlsaXp6YXJlIGxlIHByZWZlcmVuY2Ugc2VuemEgYXZlcmUgdW4gJ25hbWUnIHBlciBsYSB0YWJlbGxhXCIpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoIXRoaXMucHJlZlNlcnZpY2UpIHtcclxuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJOb24gcG9zc28gdXRpbGl6emFyZSBsZSBwcmVmZXJlbmNlIHNlbnphIGNoZSBpbCBwYWNjaGV0dG8gQGVzZmFlbnphL3ByZWZlcmVuY2VzIHNpYSBpbnN0YWxsYXRvXCIpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBsZXQgY29sdW1ucyA9IHRoaXMuZXN0LmFycmF5TW9kZSA/IHRoaXMuZXN0LmFycmF5Q29sdW1ucyA6IGNhc3RlZFZpZXcuY29sdW1ucztcclxuICAgICAgICAgICAgbGV0IGNvbHVtbnNPcmRlcmluZ3MgPSB0aGlzLmVzdC5hcnJheU1vZGUgPyB0aGlzLmVzdC5hcnJheUNvbHVtbk9yZGVyaW5nIDogY2FzdGVkVmlldy5jb2x1bW5fb3JkZXJpbmc7XHJcbiAgICAgICAgICAgIHZhciB0b1N0b3JlID0geyBjb2x1bW5zOiA8c3RyaW5nW10+SlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShjb2x1bW5zKSksIGNvbHVtbl9vcmRlcmluZzogPHN0cmluZ1tdPkpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoY29sdW1uc09yZGVyaW5ncykpIH07XHJcbiAgICAgICAgICAgIHRoaXMucHJlZlNlcnZpY2Uuc3RvcmUoPHN0cmluZz50aGlzLmVzdC5uZ0NvbnRyb2wubmFtZSwgdG9TdG9yZSkuc3Vic2NyaWJlKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBSaWVzZWd1byBsJ3VsdGltYSByaWNlcmNhIGJpbmRhdGEgYWxsYSB0YWJlbGxhXHJcbiAgICAgICAgLy8gTWkgYXNzaWN1cm8gZGkgZmFybG8gZG9wbyBsJ2VzcGFuc2lvbmUgZGVsIGNoYW5nZWQgbyByaXNjaGlvIGNoZSBsYSByaWNlcmNhIG1pIHJpZGlhIGNvbG9ubmUgY2hlIGluIHJlYWx0w6Agbm9uIGVzaXN0b25vXHJcbiAgICAgICAgaWYgKHRoaXMuZXN0LnZpZXdNb2RlKVxyXG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmVzdC5NYWluR3JvdXBWaWV3KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy90aGlzLmVtaXRTZWFyY2hSZXF1ZXN0KHRydWUsIHRoaXMuTWFpbkdyb3VwVmlldyk7XHJcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmVzdC5ncm91cFNlYXJjaFJlcXVlc3RzQ2FjaGUubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHZpZXcgPSB0aGlzLmVzdC5ncm91cFNlYXJjaFJlcXVlc3RzQ2FjaGVbaV0udmlldztcclxuICAgICAgICAgICAgICAgICAgICAgICAgdmlldy5jb2x1bW5zID0gdGhpcy5lc3QuTWFpbkdyb3VwVmlldy5jb2x1bW5zO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB2aWV3LmNvbHVtbl9vcmRlcmluZyA9IHRoaXMuZXN0Lk1haW5Hcm91cFZpZXcuY29sdW1uX29yZGVyaW5nO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVzdC5lbWl0U2VhcmNoUmVxdWVzdCh0cnVlLCB0aGlzLmVzdC5ncm91cFNlYXJjaFJlcXVlc3RzQ2FjaGVbaV0udmlldyk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmVzdC5lbWl0U2VhcmNoUmVxdWVzdCh0cnVlKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgZWxzZSBpZiAodGhpcy5lc3QuYXJyYXlNb2RlKVxyXG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHsgdGhpcy5lc3QuaW50ZXJuYWxXcml0ZVZhbHVlKCk7IH0pO1xyXG5cclxuICAgICAgICAvLyBMbyB2b3JyZWkgbWV0dGVyZSBsYXRvIHRlbXBsYXRlIG1hIG5vXHJcbiAgICAgICAgdGhpcy5lc3QubGFzdFNlbGVjdGVkSXRlbUlEID0gbnVsbDtcclxuICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEVmZmV0dHVvIGwndW5waW5uaW5nIGRpIHVuYSBjb2xvbm5hIGluIG1hbmllcmEgcHJvZ3JhbW1hdGljYSBzZW1wbGljZW1lbnRlIGVzZWd1ZW5kbyB1bmEgcGVyIHVuYSBsZSBvcGVyYXppb25pIGNoZSB2ZXJyZWJiZXJvIGVzZWd1aXRlIGFsdHJpbWVudGlcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgQ29kaWNlIGRlbGxhIGNvbG9ubmEgZGEgc3Bpbm5hcmVcclxuICAgICAqL1xyXG4gICAgcHVibGljIHVucGluQ29sdW1uKGlkOiBzdHJpbmcpIHtcclxuICAgICAgICB0aGlzLnJlc2V0Q29sdW1uVmlzU2VsZWN0aW9uKCk7XHJcbiAgICAgICAgdGhpcy5waW5PclVucGluQ29sdW1uKHRoaXMuZXN0LlRNUENvbHVtbnNMaXN0LmZpbmQodCA9PiB0LmlkID09IGlkKSk7XHJcbiAgICAgICAgdGhpcy5jb25maXJtQ29sdW1uVmlzaWJpbGl0eVNlbGVjdGlvbigpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBTdWwgY2xpY2sgbmVsbGEgY2hlY2tib3ggZGkgc2VsZXppb25lIGdsb2JhbGUgc2kgc2NvcnJvbm8gdHV0dGUgbGUgY29sb25uZSBlIHNpIGltcG9zdGFubyBhbCB2YWxvcmUgZGVsbGEgY2hlY2sgZ2xvYmFsZSAqL1xyXG4gICAgcHVibGljIGdsb2JhbENvbFZpc0NoZWNrQ2hhbmdlZCgpIHtcclxuICAgICAgICB0aGlzLmVzdC5UTVBDb2x1bW5zTGlzdC5mb3JFYWNoKHQgPT4ge1xyXG4gICAgICAgICAgICBpZiAoIXQuZml4ZWQpXHJcbiAgICAgICAgICAgICAgICB0LnZpc2libGUgPSB0aGlzLmVzdC5nbG9iYWxDb2xWaXNDaGVjaztcclxuICAgICAgICB9KTtcclxuICAgIH1cclxufVxyXG4iXX0=