@esfaenza/es-table 12.2.20 → 12.2.25

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