@esfaenza/es-table 11.2.39 → 11.2.40

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