@esfaenza/es-table 12.2.17 → 12.2.21

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