@esfaenza/es-table 11.2.20 → 11.2.22-beta11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/bundles/esfaenza-es-table.umd.js +3574 -2086
  2. package/bundles/esfaenza-es-table.umd.js.map +1 -1
  3. package/bundles/esfaenza-es-table.umd.min.js +1 -15
  4. package/bundles/esfaenza-es-table.umd.min.js.map +1 -1
  5. package/esfaenza-es-table.d.ts +7 -6
  6. package/esfaenza-es-table.metadata.json +1 -1
  7. package/esm2015/esfaenza-es-table.js +8 -7
  8. package/esm2015/lib/components/es-table/es_table.component.js +1293 -0
  9. package/esm2015/lib/components/es-table/es_table.component.loc.js +36 -0
  10. package/esm2015/lib/components/es-td/es_td.component.js +106 -0
  11. package/esm2015/lib/components/es-th/es_th.component.js +160 -0
  12. package/esm2015/lib/components/pager/table_pager.component.js +100 -0
  13. package/esm2015/lib/components/pager/table_pager.component.loc.js +22 -0
  14. package/esm2015/lib/core/handlers/classes/ColumnMetadataHandler.js +667 -0
  15. package/esm2015/lib/core/handlers/classes/DynamicModeHandler.js +64 -0
  16. package/esm2015/lib/core/handlers/classes/ExportHandler.js +43 -0
  17. package/esm2015/lib/core/handlers/classes/HierarchyModeHandler.js +136 -0
  18. package/esm2015/lib/core/handlers/classes/ItemsHandler.js +121 -0
  19. package/esm2015/lib/core/handlers/classes/ReportModeHandler.js +70 -0
  20. package/esm2015/lib/core/handlers/classes/RowGroupingHandler.js +475 -0
  21. package/esm2015/lib/core/handlers/classes/SelectionHandler.js +527 -0
  22. package/esm2015/lib/core/handlers/classes/UtilitiesHandler.js +169 -0
  23. package/esm2015/lib/core/handlers/index.js +10 -0
  24. package/esm2015/lib/directives/es_td.directive.js +2 -4
  25. package/esm2015/lib/directives/es_th.directive.js +17 -8
  26. package/esm2015/lib/domain/configuration/EsTableDefaultable.js +4 -0
  27. package/esm2015/lib/domain/configuration/EsTableModuleConfig.js +4 -0
  28. package/esm2015/lib/domain/externals/classes/CornerMenuOption.js +4 -0
  29. package/esm2015/lib/domain/externals/classes/EsTableColumnsDefinition.js +31 -0
  30. package/esm2015/lib/domain/externals/classes/EsTableOperationDefinition.js +22 -0
  31. package/esm2015/lib/domain/externals/classes/appsearch/AppOrdering.js +16 -0
  32. package/esm2015/lib/domain/externals/classes/appsearch/AppSearch.js +35 -0
  33. package/esm2015/lib/domain/externals/classes/appsearch/GenericItem.js +11 -0
  34. package/esm2015/lib/domain/externals/classes/appsearch/Group.js +17 -0
  35. package/esm2015/lib/domain/externals/classes/appsearch/GroupAggregation.js +16 -0
  36. package/esm2015/lib/domain/externals/classes/appsearch/GroupFilter.js +14 -0
  37. package/esm2015/lib/domain/externals/classes/appsearch/GroupOrAggregation.js +16 -0
  38. package/esm2015/lib/domain/externals/classes/appsearch/ItemsSelection.js +23 -0
  39. package/esm2015/lib/domain/externals/classes/report/ReportColumn.js +4 -0
  40. package/esm2015/lib/domain/externals/classes/report/ReportDefinition.js +4 -0
  41. package/esm2015/lib/domain/externals/classes/report/ReportOrder.js +4 -0
  42. package/esm2015/lib/domain/externals/classes/report/ReportParam.js +4 -0
  43. package/esm2015/lib/domain/externals/classes/report/ReportResult.js +4 -0
  44. package/esm2015/lib/domain/externals/classes/report/ReportRow.js +4 -0
  45. package/esm2015/lib/domain/externals/index.js +18 -0
  46. package/esm2015/lib/domain/index.js +3 -16
  47. package/esm2015/lib/domain/internals/classes/CacheTriptic.js +16 -0
  48. package/esm2015/lib/domain/internals/classes/EsTableColumn.js +24 -0
  49. package/esm2015/lib/domain/internals/classes/GroupPager.js +21 -0
  50. package/esm2015/lib/domain/internals/classes/GroupRouteFragment.js +17 -0
  51. package/esm2015/lib/domain/internals/classes/ThAggregation.js +16 -0
  52. package/esm2015/lib/domain/internals/classes/ThElement.js +2 -0
  53. package/esm2015/lib/domain/internals/index.js +7 -0
  54. package/esm2015/lib/es-table.module.js +13 -8
  55. package/esm2015/lib/tokens.js +6 -4
  56. package/esm2015/public-api.js +7 -6
  57. package/fesm2015/esfaenza-es-table.js +3267 -1892
  58. package/fesm2015/esfaenza-es-table.js.map +1 -1
  59. package/lib/{es_table.component.d.ts → components/es-table/es_table.component.d.ts} +129 -402
  60. package/lib/{es_table.component.loc.d.ts → components/es-table/es_table.component.loc.d.ts} +2 -6
  61. package/lib/{es_td.component.d.ts → components/es-td/es_td.component.d.ts} +13 -36
  62. package/lib/{es_th.component.d.ts → components/es-th/es_th.component.d.ts} +27 -61
  63. package/lib/components/pager/table_pager.component.d.ts +50 -0
  64. package/lib/{pager → components/pager}/table_pager.component.loc.d.ts +2 -6
  65. package/lib/core/handlers/classes/ColumnMetadataHandler.d.ts +159 -0
  66. package/lib/core/handlers/classes/DynamicModeHandler.d.ts +32 -0
  67. package/lib/core/handlers/classes/ExportHandler.d.ts +22 -0
  68. package/lib/core/handlers/classes/HierarchyModeHandler.d.ts +40 -0
  69. package/lib/core/handlers/classes/ItemsHandler.d.ts +41 -0
  70. package/lib/core/handlers/classes/ReportModeHandler.d.ts +21 -0
  71. package/lib/core/handlers/classes/RowGroupingHandler.d.ts +114 -0
  72. package/lib/core/handlers/classes/SelectionHandler.d.ts +149 -0
  73. package/lib/core/handlers/classes/UtilitiesHandler.d.ts +67 -0
  74. package/lib/core/handlers/index.d.ts +9 -0
  75. package/lib/directives/es_td.directive.d.ts +1 -3
  76. package/lib/directives/es_th.directive.d.ts +14 -7
  77. package/lib/domain/configuration/EsTableDefaultable.d.ts +19 -0
  78. package/lib/domain/configuration/EsTableModuleConfig.d.ts +10 -0
  79. package/lib/domain/externals/classes/CornerMenuOption.d.ts +7 -0
  80. package/lib/domain/{classes → externals/classes}/EsTableColumnsDefinition.d.ts +2 -6
  81. package/lib/domain/{classes → externals/classes}/EsTableOperationDefinition.d.ts +1 -3
  82. package/lib/domain/{classes → externals/classes/appsearch}/AppOrdering.d.ts +0 -0
  83. package/lib/domain/externals/classes/appsearch/AppSearch.d.ts +67 -0
  84. package/lib/domain/externals/classes/appsearch/GenericItem.d.ts +13 -0
  85. package/lib/domain/externals/classes/appsearch/Group.d.ts +17 -0
  86. package/lib/domain/externals/classes/appsearch/GroupAggregation.d.ts +14 -0
  87. package/lib/domain/externals/classes/appsearch/GroupFilter.d.ts +12 -0
  88. package/lib/domain/externals/classes/appsearch/GroupOrAggregation.d.ts +14 -0
  89. package/lib/domain/externals/classes/appsearch/ItemsSelection.d.ts +22 -0
  90. package/lib/domain/externals/classes/report/ReportColumn.d.ts +15 -0
  91. package/lib/domain/externals/classes/report/ReportDefinition.d.ts +24 -0
  92. package/lib/domain/externals/classes/report/ReportOrder.d.ts +7 -0
  93. package/lib/domain/externals/classes/report/ReportParam.d.ts +40 -0
  94. package/lib/domain/externals/classes/report/ReportResult.d.ts +12 -0
  95. package/lib/domain/externals/classes/report/ReportRow.d.ts +5 -0
  96. package/lib/domain/externals/index.d.ts +17 -0
  97. package/lib/domain/index.d.ts +2 -15
  98. package/lib/domain/internals/classes/CacheTriptic.d.ts +14 -0
  99. package/lib/domain/{classes → internals/classes}/EsTableColumn.d.ts +8 -4
  100. package/lib/domain/internals/classes/GroupPager.d.ts +22 -0
  101. package/lib/domain/internals/classes/GroupRouteFragment.d.ts +15 -0
  102. package/lib/domain/internals/classes/ThAggregation.d.ts +14 -0
  103. package/lib/domain/internals/classes/ThElement.d.ts +13 -0
  104. package/lib/domain/internals/index.d.ts +6 -0
  105. package/lib/es-table.module.d.ts +1 -1
  106. package/lib/tokens.d.ts +6 -3
  107. package/package.json +2 -1
  108. package/public-api.d.ts +6 -5
  109. package/esm2015/lib/domain/classes/AppOrdering.js +0 -16
  110. package/esm2015/lib/domain/classes/AppSearch.js +0 -56
  111. package/esm2015/lib/domain/classes/CornerMenuOption.js +0 -6
  112. package/esm2015/lib/domain/classes/EsTableColumn.js +0 -22
  113. package/esm2015/lib/domain/classes/EsTableColumnsDefinition.js +0 -33
  114. package/esm2015/lib/domain/classes/EsTableOperationDefinition.js +0 -24
  115. package/esm2015/lib/domain/classes/GenericItem.js +0 -15
  116. package/esm2015/lib/domain/classes/IAppSearch.js +0 -2
  117. package/esm2015/lib/domain/classes/ItemsSelection.js +0 -25
  118. package/esm2015/lib/domain/classes/ReportColumn.js +0 -6
  119. package/esm2015/lib/domain/classes/ReportDefinition.js +0 -6
  120. package/esm2015/lib/domain/classes/ReportOrder.js +0 -6
  121. package/esm2015/lib/domain/classes/ReportParam.js +0 -6
  122. package/esm2015/lib/domain/classes/ReportResult.js +0 -6
  123. package/esm2015/lib/domain/classes/ReportRow.js +0 -6
  124. package/esm2015/lib/es_table.component.js +0 -2280
  125. package/esm2015/lib/es_table.component.loc.js +0 -38
  126. package/esm2015/lib/es_td.component.js +0 -117
  127. package/esm2015/lib/es_th.component.js +0 -178
  128. package/esm2015/lib/models/EsTableModuleConfig.js +0 -6
  129. package/esm2015/lib/pager/table_pager.component.js +0 -70
  130. package/esm2015/lib/pager/table_pager.component.loc.js +0 -24
  131. package/lib/domain/classes/AppSearch.d.ts +0 -110
  132. package/lib/domain/classes/CornerMenuOption.d.ts +0 -13
  133. package/lib/domain/classes/GenericItem.d.ts +0 -25
  134. package/lib/domain/classes/IAppSearch.d.ts +0 -67
  135. package/lib/domain/classes/ItemsSelection.d.ts +0 -27
  136. package/lib/domain/classes/ReportColumn.d.ts +0 -29
  137. package/lib/domain/classes/ReportDefinition.d.ts +0 -46
  138. package/lib/domain/classes/ReportOrder.d.ts +0 -13
  139. package/lib/domain/classes/ReportParam.d.ts +0 -76
  140. package/lib/domain/classes/ReportResult.d.ts +0 -22
  141. package/lib/domain/classes/ReportRow.d.ts +0 -9
  142. package/lib/models/EsTableModuleConfig.d.ts +0 -9
  143. package/lib/pager/table_pager.component.d.ts +0 -50
@@ -1,2280 +0,0 @@
1
- import { __awaiter } from "tslib";
2
- // Angular
3
- import { Component, forwardRef, ContentChildren, ChangeDetectorRef, ChangeDetectionStrategy, Input, EventEmitter, Output, ContentChild, ViewChild, ViewEncapsulation, Optional, Self } from '@angular/core';
4
- import { NgControl } from '@angular/forms';
5
- // Configurazioni
6
- import { HashingService, UtilityService, ExportService, MessageService, DateService } from '@esfaenza/extensions';
7
- import { LocalizationService } from '@esfaenza/localizations';
8
- import { PreferencesService } from '@esfaenza/preferences';
9
- // Modelli
10
- import { AppSearch, AppOrdering, EsTableColumnsDefinition, ReportDefinition, ReportOrder, EsTableColumn } from './domain';
11
- // Componenti e Localizzazione
12
- import { EsTd } from './es_td.component';
13
- import { EsTh } from './es_th.component';
14
- import { EsTdDirective } from './directives/es_td.directive';
15
- import { EsThDirective } from './directives/es_th.directive';
16
- import { EsTableLoc } from './es_table.component.loc';
17
- import { ItemsSelection } from './domain/classes/ItemsSelection';
18
- import { GroupFilter, GroupOrAggregation } from './domain/classes/AppSearch';
19
- /** Componente che permette di rappresentare una griglia di valori */
20
- export class EsTableComponent {
21
- /** @ignore */
22
- constructor(ngControl, prefService, lc, cdr, hashExts, utiExts, expExts, dateExts, msgExts) {
23
- this.ngControl = ngControl;
24
- this.prefService = prefService;
25
- this.lc = lc;
26
- this.cdr = cdr;
27
- this.hashExts = hashExts;
28
- this.utiExts = utiExts;
29
- this.expExts = expExts;
30
- this.dateExts = dateExts;
31
- this.msgExts = msgExts;
32
- /** View finale su cui bindarsi lato Frontend, il tipo può essere IAppSearch<any> (per la **viewMode**), any[] (per l'**arrayMode**) e ReportDefinition per la **reportMode** */
33
- this.View = null;
34
- /** Indica se l'es-table deve mostrare il check globale nell'header per fare il "seleziona tutto" */
35
- this.globalCheck = false;
36
- /**
37
- * Tiene da conto l'ultimo elemento selezionato in modo da fare ragionamenti del tipo
38
- * "Ho selezionato questo, l'ultimo selezionato era **lastSelected**, devo selezionare tutti quelli in mezzo", ad esempio per la selezione multipla
39
- */
40
- this.lastSelected = null;
41
- /** Conteggio interno per il numero di elementi selezionati */
42
- this.selectedObjects = 0;
43
- /** Indica se è possibile effettuare una selezione massiva */
44
- this.canSelectAll = false;
45
- /** Indica se il componente sta gestendo un IAppSearch<any> */
46
- this.viewMode = false;
47
- /** Indica se il componente sta gestendo un any[] */
48
- this.arrayMode = false;
49
- /** Indica se il componente sta gestendo un ReportDefinition */
50
- this.reportMode = false;
51
- /**
52
- * Contenitore degli elementi da listare lato interfaccia dopo tutte le elaborazioni del caso,
53
- * generalmente non sono altro che tutti gli oggetti da presentare con in più l'hash calcolato per identificare 1 oggetto con la propria riga
54
- */
55
- this.boundSource = [];
56
- /** Stessa cosa della **boundSource**, utilizzata come appoggio temporaneo interno */
57
- this.TMPBoundSource = [];
58
- /** "Fetta" di oggetti utilizzata nell'endless scroll, ogni elemento di questo array è un blocchetto di 100 elementi */
59
- this.boundSubSources = [];
60
- /** Questa funge da indicatore per gli slice inseriti, la lunghezza dovrebbe essere corrispondente a **boundSubSources** */
61
- this.addedSlices = [];
62
- /** Variabile che identifica il valore del "seleziona Tutto" nella paginazione */
63
- this.defaultAllPageOverride = 999999;
64
- /** Indica se utilizzare il sistema di autoupdate, cioè un trigger time-izzato in alto a destra della tabella che ripete le ricerche ogni X **seconds** */
65
- this.autoUpdate = false;
66
- /** Numero di secondi da fare trascorrere fra una ricerca e l'altra */
67
- this.seconds = '10';
68
- /** Impostata a true ogni volta che viene avviata una ricerca, e a false ogni volta che un nuovo valore viene ricevuto */
69
- this.researchInProgress = false;
70
- /** Modello rappresentante un singolo td della tabella, generato in base alle configurazioni e agli oggetti ricevuti */
71
- this.RowTDs = null;
72
- /** Modello di appoggio temporaneo per i **RowTDs** */
73
- this.TMPRowTDs = null;
74
- /** Modello rappresentante un singolo th della tabella, generato in base alle configurazioni e agli oggetti ricevuti */
75
- this.RowTHs = null;
76
- /** Modello di appoggio temporaneo per i **RowTHs** */
77
- this.TMPRowTHs = null;
78
- /** Cache per i routerLink generati nelle tabelle dinamiche */
79
- this.DynamicTableRouterLinkCache = {};
80
- /**
81
- * Lista dei contesti. Un contesto non è altro che un hash particolare calcolato su un oggetto che identifica univocamente tale oggetto.
82
- *
83
- * Ognuno di questi contesti rappresenterà a sua volta, univocamente, una riga all'interno della tabella
84
- */
85
- this.RowContexts = [];
86
- /** Direttive di ordinamento delle colonne (non ordinamento dei dati ma delle colonne in se) */
87
- this.OrderDirectives = [];
88
- /** Codice dell'ultimo oggetto solezionato */
89
- this.lastSelectedItemID = null;
90
- /**
91
- * Indica se oltre alle colonne dinamiche specifiche di un tipo di oggetto ci sono anche colonne dinamiche aggiunte dall'utente
92
- *
93
- * Es. una colonna in cui mostrare sempre un iconcina
94
- */
95
- this.UserDefinedDynamicCols = false;
96
- /** Indica che questo è il primo Bind della tabella, viene settato a false non appena il primo bind viene terminato con successo */
97
- this.FirstBind = true;
98
- /** Lista di colonne che si possono visualizzare/ordinare fra di loro */
99
- this.ColumnsList = [];
100
- /** Variabile d'appoggio usata dalla dialog di selezione/nascondimento, per evitare di danneggiare **ColumnsList** in caso di modifiche poi annullate */
101
- this.TMPColumnsList = [];
102
- /** Valore del check globale di visibilità valido per tutte le colonne in **ColumnsList** */
103
- this.globalColVisCheck = false;
104
- /** Opzioni extra che devono apparire nel Menù contestuale in alto a destra, richiamato dai 3 pallini verticali */
105
- this.CornerMenuOptions = null;
106
- /** Indica se dev'essere possibile effettuare il resize delle colonne */
107
- this.ColumnsResizable = null;
108
- /** Indica se dev'essere disponibile il sistema di aggiornamento automatico */
109
- this.AutoUpdate = null;
110
- /** Indica se la tabella (configurata con **UseCustomCells**) deve mettersi in ascolto per i click sulle celle desiderate
111
- *
112
- * @deprecated Utilizzare l'Input **Template** delle es-td e assegnare un template con tutti i binding che si vuole ai click
113
- */
114
- this.UseCustomCellActions = null;
115
- /**
116
- * Indica le celle desiderate su cui intercettare i click. Attiva solo quando **UseCustomCellActions** è true.
117
- * Ogni cella dev'essere separata dalla successiva dal carattere del Simoleon:
118
- *
119
- * Es, "MiaCella1§MiaCella2"
120
- *
121
- * @deprecated Utilizzare l'Input **Template** delle es-td e assegnare un template con tutti i binding che si vuole ai click
122
- */
123
- this.CustomCellActionsOn = '';
124
- /**
125
- * Serve per decidere di lanciare o meno il **event.stopPropagation()** al termine della gestione dell'evento
126
- *
127
- * @deprecated Utilizzare l'Input **Template** delle es-td e assegnare un template con tutti i binding che si vuole ai click
128
- */
129
- this.CellActionPropagates = true;
130
- /**
131
- * Decide se utilizzare o meno le CustomCells. Impostandolo a **true** l'es-table diventa in grado di gestire nativamente:
132
- *
133
- * 1) Ordinamento e visibilità delle colonne
134
- *
135
- * 2) Ordinamento dei dati
136
- *
137
- * 3) Modalità Gerarchica
138
- *
139
- * ecc...
140
- */
141
- this.UseCustomCells = null;
142
- /** Permette di impostare l'altezza massima della tabella. Se null la dimensione si adatta al numero di elementi attualmente in visualizzazione */
143
- this.MaxHeight = null;
144
- /** Classi da applicare alla tabella oltre a quelle gestite autonomamente dalla libreria */
145
- this.Class = '';
146
- /** Permette o meno l'export in formato XLSX */
147
- this.XLSXExport = null;
148
- /** Permette o meno l'export in formato CSV */
149
- this.CSVExport = true;
150
- /** Permette di visualizzare o meno l'opzione di paginazione "Tutti" */
151
- this.AllSearch = true;
152
- /** Diminuisce gli spazi fra una cella e l'altra, e internamente il padding del font in modo da presentare molti più dati in un'unica pagina */
153
- this.HighCellDensity = null;
154
- /** Abilita o meno la possibilità di selezionare oggetti */
155
- this.Selection = null;
156
- /** Mostra o meno un messaggio di Loading al primo caricamento della tabella */
157
- this.ShowLoadingOnBootstrap = null;
158
- /** Se impostato a **true** aggiunge una colonna con pulsante di eliminazione per effettuare l'elimina dell'oggetto relativo */
159
- this.Removal = null;
160
- /**
161
- * Condizione che nasconde l'icona di eliminazione inserita impostando **Removal** a true qualora la condizione non venisse rispettata
162
- *
163
- * Come condizione si considera un semplice campo su cui effettuare un controllo booleano, come ad esempio "canremove"
164
- */
165
- this.RemovalCondition = '';
166
- /** Indica se abilitare la possibilità di esportare la vista dati attuale */
167
- this.Export = null;
168
- /** Indica se permettere la selezione multipla Windows-like cliccando un oggetto e facendo poi Shift + click su un oggetto successivo */
169
- this.ShiftClick = null;
170
- /** Mostra o nasconde le informazioni di paginazione, sia i pulsanti, sia il selettore degli oggetti per pagina */
171
- this.ShowPaging = true;
172
- /** Indica se nascondere o mostrare il componente di paginazione */
173
- this.HidePaging = null;
174
- /** Indica se nascondere o mostrare il conteggio degli elementi trovati */
175
- this.HidePagingCount = null;
176
- /** Indica se nascondere o mostrare i pulsanti di paginazione */
177
- this.HidePagingButtons = null;
178
- /** Riferimento al ContextMenu (ngx-contextmenu) associato al click destro di uno o più elementi selezionati nella tabella */
179
- this.ContextMenu = null;
180
- /** Nome dell'esportazione generata da questa tabella */
181
- this.ExportFileName = 'Export.csv';
182
- /** Classe (HTML) di default della tabella */
183
- this.TableClass = 'table table-striped table-hover table-sm';
184
- /** Testo da visualizzare nel conteggio. Di default: "Oggetti selezionati" */
185
- this.CountLabel = this.lc.loc('Found objects');
186
- /** Indica la presenza di raggruppamenti a livello di header */
187
- this.HasHeaderGroup = null;
188
- /** Indica la presenza di raggruppamenti a livello del raggruppamento precedentemente esistente, chiaramente è insensata senza **HasHeaderGroup** */
189
- this.HasSecondaryHeaderGroup = null;
190
- /** Utilizzato per dividere la sorgente in modalità EndlessScroll */
191
- this.SliceSize = 100;
192
- /** Decide se utilizzare la modalità di EndlessScroll */
193
- this.EndlessScroll = null;
194
- /** Qualora **EndlessScroll** fosse true, indica se utilizzare questa modalità solo quando si cerca per "Tutti" o in generale */
195
- this.EndlessScrollOnlyForAll = true;
196
- /** Indica se nascondere gli Header della tabella */
197
- this.HeaderHidden = null;
198
- /** Indica se nascondere il Body della tabella */
199
- this.BodyHidden = null;
200
- /**
201
- * Indica se la selezione è temporaneamente disabilitata. Rispetto all'Input **Selection** che visivamente gestisce se ci sono o no gli input di selezione,
202
- * questo Input gestisce se questi input sono abilitati o meno
203
- */
204
- this.SelectionDisabled = null;
205
- /**
206
- * Indica se forzare il sistema di selezione a gestire un elemento per volta.
207
- * Selezionare un'altra riga con una già selezionata applicherà la selezione alla nuova riga, rimuovendola dall'attuale
208
- */
209
- this.SingleSelection = null;
210
- /** Callback che dato un oggetto resituisce l'eventuale classe da applicare alla riga collegata all'oggetto */
211
- this.RowClassAssigner = null;
212
- /** Permette di ordinare i dati in maniera discendente o ascendente */
213
- this.OrderByColumn = null;
214
- /** Permette di avere più direttive di ordinamento dei dati */
215
- this.MultipleOrderingDirectives = true;
216
- /** Permette di nascondere le colonne in base alle selezioni effettuate dal Menù contestuale in alto a destra */
217
- this.HiddenColumns = null;
218
- /** Permette di riordinare le colonne in base alle impostazioni effettuate dal Menù contestuale in alto a destra */
219
- this.ColumnsOrdering = null;
220
- /**
221
- * Eventuale supporto alle ricerche applicate alla modalità Array
222
- *
223
- * @deprecated Utilizzato solo per un caso particolare del Metering
224
- */
225
- this.SearchView = null;
226
- /** Abilita o disabilita il sistema che permette di selezionare tutti gli elementi nella vista */
227
- this.SelectAll = null;
228
- /** Simula la paginazione anche per le tabelle che funzionano in modalità Array */
229
- this.UseArrayModePaging = true;
230
- /** Definizione di colonne dinamche per la modalità, appunto, dinamica */
231
- this.DynamicRowColumnsDefinition = null;
232
- /** Indica operazioni dinamiche generiche che possono essere effettuate per riga. Appaiono come colonne extra sul lato sinistro della tabella */
233
- this.DynamicOperations = [];
234
- /** Indica se visualizzare i dati in maniera gerarchica */
235
- this.Hierarchy = null;
236
- /** Nome della proprietà che contiene l'ID del padre. Da utilizzare se **Hierarchy** è impostato */
237
- this.ParentKey = '';
238
- /** Nome della proprietà che contiene l'ID dell'oggetto attuale. Da utilizzare se **Hierarchy** è impostato */
239
- this.OwnKey = '';
240
- /** Indica se partire con un albero espanso. Da utilizzare se **Hierarchy** è impostato */
241
- this.StartsExpanded = true;
242
- /** Indica se effettuare il salvataggio delle preferenze di ricerca */
243
- this.SavePreferences = null;
244
- /**
245
- * Sorgente dati secondaria
246
- *
247
- * @deprecated Utilizzato solo per un caso particolare del Metering
248
- */
249
- this.SecondarySource = null;
250
- /**
251
- * Sorgente dati secondaria
252
- *
253
- * @deprecated Utilizzato solo per un caso particolare del Metering
254
- */
255
- this.TertiarySource = null;
256
- /** Indica se utilizzare la cache di selezione che permette di mantenere gli stati di selezione dei vari oggetti navigando da una pagina all'altra */
257
- this.UseSelectionCache = true;
258
- /** Evento che viene richiamato al cambio di oridnamento di una colonna */
259
- this.onOrderChanged = new EventEmitter();
260
- /**
261
- * Evento che viene richiamato quando l'es-table ritiene sia necessario ri-effettuare la ricerca.
262
- * Il booleano dell'evento indica se viene suggerito di resettare la pagina o meno.
263
- *
264
- * Solo in caso venga utilizzata la modalità a raggruppamenti di righe può succedere che l'es-table passi un intero AppSearch come parametro di ricerca,
265
- * in quel caso l'applicazione ricevente dovrà onorare la richiesta spedendo al backand l'oggetto di ricerca AS-IS
266
- *
267
- * il tipo dell'Emitter invece di essere [boolean | AppSearch<any>] è stato impostato a "any" per evitare problemi di retrocompatibilità
268
- */
269
- this.onSearchRequest = new EventEmitter();
270
- /** Evento che parte ad ogni modifica di "checkaggio" in forma di comodo array. Espone l'oggetto con lo stato di check attuale */
271
- this.onSelectionChanged = new EventEmitter();
272
- /** Evento richiamato all'eliminazione di un oggetto */
273
- this.onRemoval = new EventEmitter();
274
- /** Evento richiamato all'annullamento di un'eliminazione */
275
- this.onAbortRemoval = new EventEmitter();
276
- /** Evento richiamato al click su una cella quando **UseCustomCellActions** è attivo
277
- *
278
- * @deprecated Utilizzare l'Input **Template** delle es-td e assegnare un template con tutti i binding che si vuole ai click
279
- */
280
- this.onCellClick = new EventEmitter();
281
- /** Evento richiamato quando si clicca su un opzione definita nelle **CornerMenuOptions** */
282
- this.onCornerAction = new EventEmitter();
283
- /** Evento richiamato quando si clicca su un opzione definita nelle **DynamicOperations** */
284
- this.onDynamicOperation = new EventEmitter();
285
- /** Pagina in visualizzazione (durante la paginazione in modalità Array) */
286
- this.arraymodePage = 1;
287
- /** Numero di pagine (durante la paginazione in modalità Array) */
288
- this.arraymodePages = 1;
289
- /** Oggetti per ogni pagina (durante la paginazione in modalità Array) */
290
- this.ArraymodeItemsPerPage = 15;
291
- /**
292
- * Variabile che serve a gestire il momento in cui l'es-table aggiorna la paginazione (pulsanti ecc).
293
- * Essendo operazioni comunque costose le effettuo solo su binding esterni, non su rewrite generati internamente
294
- */
295
- this.internalWriteCall = false;
296
- /** Cache di selezione Hash - Oggetto */
297
- this.selOrDeselCache = {};
298
- /**
299
- * Variabile d'appoggio per capire se c'è bisogno di ri-effettuare una ricerca o meno
300
- */
301
- this.ResearchNeeded = false;
302
- /**
303
- * Variabile da usare nei "colspan" quando si vuole dire "Tutte le colonne". 42 è un numero magico che mi serve per non calcolare questa variabile quando mi serve.
304
- *
305
- * Di base dovrebbe essere la somma dei RowTH con l'aggiunta di tutti gli Header extra in base alle situazioni. Dato che diventa una logica deficiente me la cavo così
306
- *
307
- * Se in una tabella ci sono meno di 42 colonne il colspan si ferma comunque alla fine, se invece ce ne sono di più... beh bisogna allungare sto numero
308
- *
309
- */
310
- this.allColumns = "42";
311
- /** @ignore */
312
- this.propagateChange = (_) => { };
313
- if (ngControl)
314
- ngControl.valueAccessor = this;
315
- }
316
- /** @ignore */
317
- ngOnInit() {
318
- //Per poter cambiare il layout in base al livello gerarchico il componente deva avere il pieno controllo di ogni cella,
319
- //che con solo la proiezione (senza celle cusotm) non è disponibile
320
- if (this.Hierarchy && !this.UseCustomCells)
321
- throw "Es-table error: Per poter utilizzare l'es-table con [Hierarchy]=\"true\" è richiesto anche [UseCustomCells]=\"true\"";
322
- // click destro su una riga con selezione attiva: Tiro fuori il context menu e selezione l'elemento corrente
323
- this.ctxMenuSubscription = (this.ContextMenu || this.tableEmptyMenu).open.subscribe(t => {
324
- let shouldEmit = !t.item._selected;
325
- t.item._selected = true;
326
- var itemSelection = this.handleItemsSelection([t.item]);
327
- this.changed();
328
- if (shouldEmit)
329
- this.onSelectionChanged.emit(itemSelection);
330
- });
331
- }
332
- /** @ignore */
333
- ngAfterViewInit() {
334
- // Se utilizzo la new spicy mode deduco tutti i parametri di lavoro possibili al caricamento della tabella
335
- // Vengono sovrascritte solo le proprietà non impostate dall'utente
336
- if (this.EsTdsDirective && this.EsTdsDirective.length > 0 && this.EsThsDirective && this.EsThsDirective.length > 0) {
337
- if (this.UseCustomCells == null)
338
- this.UseCustomCells = true;
339
- if (this.HiddenColumns == null && this.UseCustomCells)
340
- this.HiddenColumns = true;
341
- if (this.ColumnsOrdering == null && this.UseCustomCells)
342
- this.ColumnsOrdering = true;
343
- if (this.OrderByColumn == null && this.UseCustomCells)
344
- this.OrderByColumn = true;
345
- if (this.SelectAll == null && this.Selection)
346
- this.SelectAll = true;
347
- if (this.ShiftClick == null && this.Selection)
348
- this.ShiftClick = true;
349
- }
350
- }
351
- /** @ignore */
352
- ngOnDestroy() {
353
- if (this.ctxMenuSubscription)
354
- this.ctxMenuSubscription.unsubscribe();
355
- }
356
- /** @ignore */
357
- ngOnChanges(changes) {
358
- return __awaiter(this, void 0, void 0, function* () {
359
- let newSearchView = changes['SearchView'];
360
- if (newSearchView && this.SearchView)
361
- this.arrayPulsanti = this.getPagesArray(6, this.SearchView.page, this.SearchView.pages || 1);
362
- });
363
- }
364
- // #region Implementazione ControlValueAccessor ignorabile
365
- /** @ignore */
366
- registerOnChange(fn) { this.propagateChange = fn; }
367
- /** @ignore */
368
- registerOnTouched(fn) { }
369
- /** @ignore */
370
- changed() { this.propagateChange(this.View); }
371
- // #endregion
372
- /** @ignore */
373
- writeValue(obj) {
374
- this.View = obj ? obj : null;
375
- // Mi è arrivata l'AppSearch quindi di sicuro non ho una ricerca in progress
376
- this.researchInProgress = false;
377
- if (!this.View && !this.SearchView) {
378
- // Su view nulla evito di fare pressoché qualsiasi cosa. Se arriva un null devo anche assicurarmi di non mostrare nulla
379
- this.boundSource = this.TMPBoundSource || [];
380
- // Per essere sicuro che dopo un bind di oggetti la es-table aggiorni la grafica
381
- this.cdr.markForCheck();
382
- return;
383
- }
384
- // Se per sbaglio l'oggetto che mi arriva non è tipizzato (instanceof AppSearch restituisce false anche se è del tipo giusto)
385
- // lo correggo--------------------------------------------------------------------------------------------------------------
386
- if (this.View && typeof this.View.result != 'undefined' && !(this.View instanceof ReportDefinition)) {
387
- this.View.__proto__ = new ReportDefinition();
388
- }
389
- else if (this.View && typeof this.View.itemsperpageoverride != 'undefined' && !(this.View instanceof AppSearch)) {
390
- this.View.__proto__ = new AppSearch();
391
- }
392
- else if (this.SearchView && typeof this.SearchView.itemsperpageoverride != 'undefined' && !(this.SearchView instanceof AppSearch)) {
393
- this.SearchView.__proto__ = new AppSearch();
394
- }
395
- // -------------------------------------------------------------------------------------------------------------------------
396
- if (this.View && this.View instanceof ReportDefinition) {
397
- // Se mi arriva una report definition vuol dire che potrei avere dei risultati da visualizzare
398
- this.setMode('report');
399
- this.ReportValues = this.View.result;
400
- if (this.ReportValues)
401
- this.reviewReportBindings();
402
- }
403
- else if (this.View && this.View instanceof AppSearch) {
404
- // Se cambia l'oggetto intero significa che ho rimandato la ricerca
405
- this.setMode('view');
406
- // Se vengo da una ricerca interna mantengo lo stato di selezione precedente (quindi su cambio pagina, cambio ipp, ecc...)
407
- // se invece l'utente ha fatto una ricerca lui (quindi cambiando filtri), secco le info di selezione
408
- if (!this.View.selection || !this.View.internalsearchrequest || !this.UseSelectionCache) {
409
- this.selOrDeselCache = {};
410
- this.View.selection = new ItemsSelection([]);
411
- this.onSelectionChanged.emit(this.View.selection);
412
- }
413
- this.View.internalsearchrequest = false;
414
- // Recupero Preference
415
- if (this.SavePreferences) {
416
- if (!this.ngControl.name)
417
- console.error("Non posso utilizzare le preference senza avere un 'name' per questa tabella");
418
- else if (!this.prefService)
419
- console.error("Non posso utilizzare le preference senza che il pacchetto @esfaenza/preferences sia installato");
420
- else {
421
- var prefs = this.prefService.retrieve(this.ngControl.name);
422
- if (prefs) {
423
- this.View.columns = prefs.columns;
424
- this.View.column_ordering = prefs.column_ordering;
425
- }
426
- }
427
- }
428
- this.arrayPulsanti = this.getPagesArray(6, this.View.page, this.View.pages || 1);
429
- }
430
- else if (this.View && (this.View.length != null && this.View.length != undefined)) {
431
- this.setMode('array');
432
- if (!this.UseSelectionCache || !this.arraymodeSelection) {
433
- this.selOrDeselCache = {};
434
- this.arraymodeSelection = new ItemsSelection([]);
435
- ;
436
- this.onSelectionChanged.emit(this.arraymodeSelection);
437
- }
438
- if (this.SearchView)
439
- this.arrayPulsanti = this.getPagesArray(6, this.SearchView.page, this.SearchView.pages || 1);
440
- }
441
- if (this.View && !(this.View instanceof ReportDefinition)) {
442
- /*
443
- *Uso la tecnica di EndlessScroll se la variabile relativa è attiva e se
444
- * 1) Ho un Array, oppure
445
- * 2) Ho un AppSearch che sta cercando con paginazione "Tutto", oppure
446
- * 3) Ho un AppSearch che sta cercando con paginazione diversa da "Tutto" ma con la variabile EndlessScrollOnlyForAll a false
447
- */
448
- let viewCasted = this.View;
449
- let hasRowGroups = viewCasted.groupings && viewCasted.groupings.filter(t => !t.aggregation).length > 0;
450
- let isAppSearchWithIppMax = this.viewMode && viewCasted.itemsperpageoverride == this.defaultAllPageOverride;
451
- let isAppSearchNoMaxIpp = this.viewMode && viewCasted.itemsperpageoverride != this.defaultAllPageOverride;
452
- this.UseEndlessscroll = this.EndlessScroll && (this.arrayMode || isAppSearchWithIppMax || (isAppSearchNoMaxIpp && !this.EndlessScrollOnlyForAll));
453
- if (this.UseEndlessscroll && !hasRowGroups) {
454
- this.addedSlices = [];
455
- this.boundSubSources = this.getItemSlices();
456
- this.TMPBoundSource = this.boundSubSources[0] ? this.boundSubSources[0] : [];
457
- if (this.boundSubSources[0])
458
- this.addedSlices.push(0);
459
- }
460
- else
461
- this.TMPBoundSource = this.getItemsByMode(false, !this.internalWriteCall);
462
- if (this.Hierarchy && !hasRowGroups)
463
- this.assignHierarchyLevels(this.TMPBoundSource);
464
- this.calculateHash(this.TMPBoundSource);
465
- // Assegno a una variabile mia l'eventuale override per la classe della riga
466
- // Se poi sono in modalità gerarchica inietto anche la classe per la configurazione del livello della riga
467
- if ((this.TMPBoundSource && this.RowClassAssigner) || this.Hierarchy) {
468
- for (let i = 0; i < this.TMPBoundSource.length; i++) {
469
- let item = this.TMPBoundSource[i];
470
- item._rowClass = this.RowClassAssigner ? this.RowClassAssigner(item) : "";
471
- item._rowClass += this.Hierarchy ? " est-row-lvl-" + item.level : "";
472
- }
473
- }
474
- }
475
- this.postBoundSourceCalculation();
476
- }
477
- // #region Gestione retrieve degli oggetti da mostrare in tabella, considerando eventuali Endless Scrolls
478
- /**
479
- * In base alla modalità specificata (ArrayMode, ViewMode, ecc...) questo metodo recupera l'array di oggetti da bindare ad interfaccia
480
- *
481
- * @param {boolean} onlyselected [false] Indica di prendere solo gli oggetti selezionati
482
- * @param {boolean} refreshPaging [false] Indica se aggiornare le informazioni di paginazione o meno
483
- * @param {boolean} allIfPossible [false] Indica se prendere tutti gli oggetti quaora possibile, usato solo in ArrayMode
484
- *
485
- * @returns {any[]} Lista degli oggetti su cui effettuare il bind lato interfaccia
486
- */
487
- getItemsByMode(onlyselected = false, refreshPaging = false, allIfPossible = false) {
488
- let items = [];
489
- if ((this.viewMode && this.View instanceof AppSearch)) {
490
- items = this.getViewItemsBySource();
491
- }
492
- else if (this.arrayMode) {
493
- if (this.UseArrayModePaging && !allIfPossible) {
494
- // Se sono in modalità array ma la ricerca dipende da una view devo riallineare gli itemperpage
495
- if (this.SearchView)
496
- this.ArraymodeItemsPerPage = this.SearchView.itemsperpageoverride;
497
- // Devo chiamare il refresh page solo se vengo richiamato da un binding esterno
498
- if (refreshPaging)
499
- this.refreshPaging(this.ArraymodeItemsPerPage);
500
- items = this.adaptViewToPaging();
501
- }
502
- else {
503
- items = this.View;
504
- }
505
- }
506
- // Se voglio solo i selezionati filtro
507
- if (onlyselected)
508
- return items.filter(t => t._selected);
509
- return items;
510
- }
511
- /** @ignore */
512
- getViewItemsBySource() {
513
- var _a, _b;
514
- let castedView = this.View;
515
- let groupKeys = castedView.groupings ? castedView.groupings.filter(t => !t.aggregation).length : 0;
516
- //Gruppi intermedi
517
- if ((((_a = castedView.requestedgroups) === null || _a === void 0 ? void 0 : _a.length) != groupKeys || ((_b = castedView.requestedgroups) === null || _b === void 0 ? void 0 : _b.length) == 0) && groupKeys > 0) {
518
- let ret = castedView.groups;
519
- // Setto variabile interna per capire che questo è in realtà un gruppo
520
- ret.forEach(itm => { itm._group = true; });
521
- return ret;
522
- }
523
- else {
524
- let ret = this.SecondarySource ? this.View.items2 : this.TertiarySource ? this.View.items3 : this.View.items;
525
- // Setto variabile interna per specificare che questo è un elemento normale, non un gruppo o altro
526
- ret.forEach(itm => { itm._item = true; });
527
- return ret;
528
- }
529
- }
530
- /**
531
- * Metodo che prende tutti gli oggetti di cui dispone divisi in bucket da 100 elementi
532
- *
533
- * @returns {any[][]} Matrice di array Nx100
534
- */
535
- getItemSlices() {
536
- // Se sono qui di sicuro non ho rowgrouping
537
- let items = this.getItemsByMode();
538
- if (!items)
539
- return [];
540
- let arrayBy100 = [];
541
- let slices = Math.ceil(items.length / this.SliceSize);
542
- for (let i = 0; i < slices; i++) {
543
- let arraySlice = items.slice(i * this.SliceSize, i * this.SliceSize + this.SliceSize);
544
- arrayBy100.push(arraySlice);
545
- }
546
- return arrayBy100;
547
- }
548
- /**
549
- * Metodo che gestisce l'endless scroll e in base a quanto la tabella è stata scrollata aggiunge degli elementi extra a **TMPBoundSource**
550
- *
551
- * @param {any} e Evento di scroll del browser
552
- */
553
- onScroll(e) {
554
- let tableViewHeight = e.target.offsetHeight;
555
- let tableScrollHeight = e.target.scrollHeight;
556
- let scrollLocation = e.target.scrollTop;
557
- let buffer = 200;
558
- let limit = tableScrollHeight - tableViewHeight - buffer;
559
- if (scrollLocation > limit) {
560
- let indexToAdd = Math.floor(this.TMPBoundSource.length / 100);
561
- if (this.boundSubSources[indexToAdd] && this.addedSlices.indexOf(indexToAdd) == -1) {
562
- // Devo ricordarmi di fare l'hash del nuovo pezzo
563
- this.calculateHash(this.boundSubSources[indexToAdd]);
564
- this.TMPBoundSource = this.TMPBoundSource.concat(this.boundSubSources[indexToAdd]);
565
- this.addedSlices.push(indexToAdd);
566
- setTimeout(() => { this.postBoundSourceCalculation(); });
567
- }
568
- }
569
- }
570
- // #endregion
571
- // #region Gestione di tutto il ciclo di vita post binding oggetti
572
- /**
573
- * Metodo lanciato dopo che la sorgente dati è stata correttamente bindata, si occupa di ricalcolare tutto ciò che serve
574
- * all'es-table per renderizzare i valori da mostrare
575
- */
576
- postBoundSourceCalculation() {
577
- // Resetto tutto tranne RowTDs e RowTHs per evitare flickering. RowTDs e RowTHs saranno modificate all'interno del prossimo ciclo di CD
578
- this.RowContexts = [];
579
- this.OrderDirectives = [];
580
- this.lastSelectedItemID = null;
581
- // Set timeout e basta funzionerebbe per la modalità JIT, ma per AOT servono sia quello che detectChanges
582
- this.cdr.detectChanges();
583
- setTimeout(() => {
584
- // Se non ho colonne dinamiche ma sono in modalità dinamica (lo capisco perché c'è una view piena di genericitem) metto il default delle colonne
585
- this.eventuallyReviewDynamicColumns();
586
- this.bindDisplayToLoadedItemsOrGroups();
587
- // Molte cose sono ovviamente disponibili solo in modalità View
588
- if (this.viewMode && this.UseCustomCells) {
589
- let view = this.View;
590
- let ths = this.EsThs && this.EsThs.length > 0 ? this.EsThs.toArray() : this.EsThsDirective && this.EsThsDirective.length > 0 ? this.EsThsDirective.toArray() : [];
591
- let tds = this.EsTds && this.EsTds.length > 0 ? this.EsTds.toArray() : this.EsTdsDirective && this.EsTdsDirective.length > 0 ? this.EsTdsDirective.toArray() : [];
592
- // N.B: Rispettare l'ordine di queste 3 macrocategorie è VITALE
593
- // ************************************* Sistemazioni di TH, TD, e visibilità varie *************************************
594
- this.alignColumnsIfLoadedView(view); // Se sto caricando una View da hotpotato (quindi con savedstate = true) riallineo la visibilità delle colonne e il loro ordine.
595
- this.refreshColumnsVisibility(ths, tds, view); // Lavoro sui TH ed eventualmente modifico la visibilità anche dei TD.
596
- this.alignHeadersOrdering(ths, view); // Allineo gli ordinamenti agli header
597
- this.reviewColumnsList(ths); // Aggiorna la lista delle colonne da mostrare nella dialog per ordinamento ecc
598
- // ************************************* Generazione binding per righe e colonne *************************************
599
- this.evaluateRowThs(ths); // Raccolgo i TH
600
- this.evaluateRowTds(ths, tds); // Raccolgo i TD in contesti separati, un contesto per ogni item o gruppo
601
- // ************************************* Ultimi aggiustmaenti dei binding *************************************
602
- this.generateDefaultOrder(view); // Genero le direttive di ordinamento, che siano default o derivanti dalla AppSearch
603
- this.applyOrdering(view, true); // Applico l'ordinamento sulle colonne (non ASC DESC, ma "prima questa o quella colonna")
604
- this.MoveTemporaryVariablesToRealOnes(); // Collego TH e TD aggiustati fino ad ora alle variabili di Binding HTML
605
- this.evaluateSelection(view.items, view.selection); // Riallineo le info di selezione degli elementi della View
606
- if (this.ResearchNeeded) {
607
- this.changed();
608
- this.emitSearchRequest(false);
609
- this.ResearchNeeded = false;
610
- }
611
- }
612
- else if (this.viewMode && !this.UseCustomCells) {
613
- // Riallineo le info di selezione degli elementi della View
614
- let view = this.View;
615
- this.evaluateSelection(view.items, view.selection);
616
- }
617
- else if (this.arrayMode)
618
- this.arrayModeEvaluateSelection(this.View);
619
- // Per essere sicuro che dopo un bind di oggetti la es-table aggiorni la grafica
620
- this.cdr.markForCheck();
621
- this.FirstBind = false;
622
- });
623
- }
624
- bindDisplayToLoadedItemsOrGroups() {
625
- var _a, _b, _c;
626
- if (this.TMPBoundSource.length == 0)
627
- return;
628
- if (this.arrayMode || !this.UseCustomCells) {
629
- this.boundSource = this.TMPBoundSource;
630
- return;
631
- }
632
- let view = this.View;
633
- let groupingKeys = ((_b = (_a = view.groupings) === null || _a === void 0 ? void 0 : _a.filter(t => !t.aggregation)) === null || _b === void 0 ? void 0 : _b.length) || 0;
634
- if (groupingKeys == 0) {
635
- this.boundSource = this.TMPBoundSource;
636
- return;
637
- }
638
- // 1) Se non viene richiesto il dettaglio di alcun gruppo significa che la chiamata restituisce la lista paginata dei gruppi principali.
639
- // Li tratto come se fosse una qualsiasi altra query paginata su N elementi
640
- if ((((_c = view.requestedgroups) === null || _c === void 0 ? void 0 : _c.length) || 0) == 0) {
641
- this.boundSource = this.TMPBoundSource;
642
- // Resetto la ricerca alla cache di questa "sessione"
643
- this.groupSearchRequestsCache = [{ path: '', view: view }];
644
- }
645
- else {
646
- // 2) Se viene richiesto il dettaglio di un qualsiasi gruppo diverso dall'ultimo vuol dire che devo aggiungere
647
- // dopo al gruppo che ho cliccato la lista dei gruppi tirata fuori questa volta (intermediateGroup = true)
648
- /*
649
- * GruppoA GruppoA
650
- * GruppoB GruppoB
651
- * GruppoC <- Clicco qui GruppoC
652
- * GruppoD GruppoC1
653
- * GruppoE GruppoC2
654
- * GruppoD
655
- * GruppoE
656
- */
657
- // 3) se i gruppi richiesti dalla view sono uguali ai gruppi presenti vuol dire che sto prendendo gli oggetti veri e propri, sono in
658
- // view.items e quindi in TMPBoundSource, ho inoltre le informazioni di paginazione **per il singolo sottogruppo** (intermediateGroup = false)
659
- /*
660
- * GruppoA GruppoA
661
- * GruppoC1 GruppoC1
662
- * GruppoB GruppoB
663
- * GruppoC GruppoC
664
- * GruppoC1 <-- Clicco qui GruppoC1
665
- * Oggetto1
666
- * Oggetto2
667
- * Oggetto3
668
- * GruppoC2 GruppoC2
669
- * GruppoD GruppoD
670
- * GruppoE GruppoE
671
- */
672
- let intermediateGroup = view.requestedgroups.length != groupingKeys;
673
- let items = this.boundSource;
674
- let insertIndex = 0;
675
- let groupKey = "";
676
- let groupRoute = [];
677
- // Navigo la stuttura dei gruppi ignorando ricorsivamente tutti gli indici fino ai gruppi che mi interessano in modo da non beccare il primo "GruppoC1" del caso sopra
678
- for (let i = 0; i < view.requestedgroups.length; i++) {
679
- let rg = view.requestedgroups[i];
680
- groupKey += rg.value;
681
- groupRoute.push({ column: rg.column, value: rg.value });
682
- insertIndex = items.findIndex((t, i) => i >= insertIndex && t._group && t.column == rg.column && t.value == rg.value);
683
- }
684
- // Assegno un livello ai valori che arrivano da usare per formattare la parte grafica. Il primo gruppo cliccato sarà a livello 1,
685
- // il secondo sarà a livello 2 e così via...
686
- // Li marco inoltre con il parent in modo da poter eliminare i vecchi qualora servisse
687
- this.TMPBoundSource.forEach(itm => {
688
- itm._parent = groupKey;
689
- itm._parentRoute = groupRoute;
690
- if (intermediateGroup)
691
- itm._grouplevel = view.requestedgroups.length;
692
- });
693
- //Elimino gli oggetti vecchi qui dentro e li sostituisco coi nuovi di questa ricerca
694
- this.boundSource = this.boundSource.filter(t => t._parent != groupKey);
695
- this.boundSource.splice(insertIndex + 1, 0, ...this.TMPBoundSource);
696
- // Aggiungo un separatore alla fine di questi gruppi che dovrà occuparsi di caricare ALTRI gruppi
697
- this.boundSource.splice(insertIndex + 1 + this.TMPBoundSource.length, 0, this.getGroupSeparator(view, groupKey, view.requestedgroups.length));
698
- // Aggiungo la ricerca alla cache di questa "sessione"
699
- this.groupSearchRequestsCache.push({ path: groupKey, view: view });
700
- }
701
- }
702
- /**
703
- * Metodo richiamato solo quando **TMPRowTDs** e **TMPRowTHs** sono completamente generati ed aggiustati. Serve per collegarli alle variabili usate lato binding HTML
704
- */
705
- MoveTemporaryVariablesToRealOnes() {
706
- this.RowTDs = this.TMPRowTDs;
707
- this.RowTHs = this.TMPRowTHs;
708
- }
709
- /**
710
- * Se non ho l'Input **DynamicRowColumnsDefinition** in modalità dinamica lo riempio con il default nome della colonna = testo della colonna
711
- */
712
- eventuallyReviewDynamicColumns() {
713
- // Senza oggetti esco
714
- if (!this.TMPBoundSource || this.TMPBoundSource.length == 0)
715
- return;
716
- var useGenericItems = !!this.TMPBoundSource[0]["properties"];
717
- if (!useGenericItems || (!this.FirstBind && this.DynamicRowColumnsDefinition && this.DynamicRowColumnsDefinition.length > 0))
718
- return;
719
- if ((!this.DynamicRowColumnsDefinition || this.DynamicRowColumnsDefinition.length == 0)) {
720
- var props = this.TMPBoundSource[0]["properties"];
721
- this.DynamicRowColumnsDefinition = [];
722
- for (let key in props)
723
- this.DynamicRowColumnsDefinition.push(new EsTableColumnsDefinition(key, key));
724
- this.UserDefinedDynamicCols = false;
725
- }
726
- else
727
- this.UserDefinedDynamicCols = true;
728
- }
729
- /**
730
- * Partendo dagli **EsThs** estrappolo la lista di **EsTableColumn** che questa tabella dovrà eventualmente gestire per Visibilità e Ordine
731
- *
732
- * Costo: 1 scan EsThs
733
- *
734
- * @param {EsTh[] | EsThDirective[]} ths Colonne della tabella
735
- */
736
- reviewColumnsList(ths) {
737
- this.ColumnsList = [];
738
- if (ths.length == 0)
739
- return;
740
- // Appena il contentChildren è valorizzato scorro tutti gli header
741
- for (let i = 0; i < ths.length; i++) {
742
- let th = ths[i];
743
- if (this.isEsTh(th)) {
744
- // Se non ho un id il th è considerato inerte
745
- if (!th.ID)
746
- continue;
747
- th.OrderBy = this.OrderByColumn;
748
- // Salvo le informazioni dell'header per far parte della lista da cui scegliere quali colonne visualizzare/nascondere
749
- // Di default la visibilità è quella impostata nel componente
750
- if (this.HiddenColumns || th.Visible)
751
- this.ColumnsList.push(new EsTableColumn(th.ID, th.Description, th.Visible, th.Fixed, null));
752
- }
753
- else {
754
- // Se non ho un id il th è considerato inerte
755
- if (!th.th)
756
- continue;
757
- // Salvo le informazioni dell'header per far parte della lista da cui scegliere quali colonne visualizzare/nascondere
758
- // Di default la visibilità è quella impostata nel componente
759
- if (this.HiddenColumns || th.thVisible)
760
- this.ColumnsList.push(new EsTableColumn(th.th, null, th.thVisible, th.thFixed, th.Template));
761
- }
762
- }
763
- }
764
- /**
765
- * Terminato il binding delle colonne da **reviewColumnsList** e della **View** dal **writeValue** questo metodo si occupa
766
- * dell'allineamento delle informazioni fra le colonne calcolate internamente e le informazioni sulle colonne che arrivano dall'AppSearch
767
- *
768
- * @param {AppSearch<any>} view AppSearch da utilizzare per questa operazione
769
- */
770
- alignColumnsIfLoadedView(view) {
771
- let emitChanged = view.savedstate;
772
- let newColset = [];
773
- if (!this.ColumnsList || this.ColumnsList.length == 0)
774
- return;
775
- this.ColumnsList.forEach(c => {
776
- let exCl = view.columns.filter(cc => cc == c.id);
777
- // Se l'appsearch viene da uno stato precedente, uso le informaizoni sulle colonne che ha dentro, altrimenti sovrascrivo tutto **
778
- if (c.visible && view.columns.length == 0)
779
- newColset.push(c.id);
780
- // Se ho una colonna lato AppSearch e nella ColumnList non è visibile, allineo all'AppSearch
781
- else if (exCl.length == 1 && !c.visible)
782
- c.visible = true;
783
- // Allineamento sull'AppSearch per casistiche inverse al di sopra
784
- else if (exCl.length == 0 && c.visible)
785
- c.visible = false;
786
- });
787
- // Non ho colonne nella appsearch, vuol dire che sono al primo binding
788
- if (view.columns.length == 0)
789
- view.columns = newColset;
790
- if (view.savedstate && this.ColumnsOrdering && view.column_ordering.length > 0) {
791
- let newColList = [];
792
- // Scorro gli ordinamenti che avevo salvato e ricreo la ColumnsList in base a loro
793
- view.column_ordering.forEach(co => {
794
- this.ColumnsList.forEach(c => {
795
- if (c.id == co)
796
- newColList.push(c);
797
- });
798
- });
799
- this.ColumnsList = newColList;
800
- }
801
- // In ogni caso questo non mi serve più, lo resetto **
802
- view.savedstate = false;
803
- if (emitChanged)
804
- this.changed();
805
- }
806
- /**
807
- * Metodo che gestisce il cambio di Ordinamento di una colonna
808
- *
809
- * @param {string} id ID della colonna il cui oridnamento è cambiato
810
- * @param {'DESC' | 'ASC'} order Nuovo ordine selezionato per la colonna
811
- */
812
- thOrderChanged(id, order) {
813
- if (!this.viewMode) {
814
- console.warn('Order changed on a table not in viewMode. Operation not supported');
815
- return;
816
- }
817
- if (!this.OrderByColumn)
818
- return;
819
- let appSearch = this.View;
820
- let orderToAdd = true;
821
- let orderToRemove = null;
822
- // Se per qualche motivo il costruttore non è passato (cache tarpate o simila) fixo
823
- if (!appSearch.orders)
824
- appSearch.orders = [];
825
- for (let i = 0; i < appSearch.orders.length; i++) {
826
- let t = appSearch.orders[i];
827
- if (t.id == id) {
828
- if (order) {
829
- t.order = order;
830
- orderToAdd = false;
831
- }
832
- else
833
- orderToRemove = i;
834
- }
835
- }
836
- if (orderToRemove != null) {
837
- appSearch.orders.splice(orderToRemove, 1);
838
- }
839
- else if (orderToAdd) {
840
- if (this.MultipleOrderingDirectives)
841
- appSearch.orders.push(new AppOrdering(id, order));
842
- else
843
- appSearch.orders = [new AppOrdering(id, order)];
844
- }
845
- this.onOrderChanged.emit({ id, order });
846
- if (this.groupSearchRequestsCache.length > 0)
847
- this.emitRowGroupingSearches(id, appSearch.orders);
848
- else
849
- this.emitSearchRequest(false);
850
- }
851
- /**
852
- * Metodo da chiamare ogni volta che si vuole dare evidenza all'esterno del bisogno di rieffettuare la ricerca
853
- *
854
- * @param {boolean} resetsPage Indica al listener che deve resettare il numero di pagina
855
- * @param {AppSearch<any>} viewOverride Override della view da emettere per questa ricerca
856
- */
857
- emitSearchRequest(resetsPage, viewOverride) {
858
- if (this.viewMode && !viewOverride) {
859
- this.View.internalsearchrequest = true;
860
- this.changed();
861
- }
862
- this.researchInProgress = true;
863
- this.onSearchRequest.emit(viewOverride ? viewOverride : resetsPage);
864
- }
865
- /**
866
- * In base alla visibilità registrata nelle **ColumnsList** questo metodo si occupa di prendere tutti i **EsThs** ed **EsTds** relativi e nasonderli/mostrarli
867
- *
868
- * Costo: 1 scan ColumnsList, 1 scan EsThs, 1 scan EsTds
869
- *
870
- * @param {EsTh[] | EsThDirective[]} ths Header della tabella
871
- * @param {EsTd[] | EsTdDirective[]} tds Celle della tabella
872
- * @param {AppSearch<any>} view AppSearch da utilizzare per questa operazione
873
- */
874
- refreshColumnsVisibility(ths, tds, view) {
875
- let columnsCache = {};
876
- let newColset = [];
877
- let fixedThs = {};
878
- for (let coli = 0; coli < this.ColumnsList.length; coli++) {
879
- let col = this.ColumnsList[coli];
880
- columnsCache[col.id] = col;
881
- if (col.visible)
882
- newColset.push(col.id);
883
- }
884
- view.columns = newColset;
885
- // 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
886
- if (ths) {
887
- // Definisco se la colonna è visibile in base alla sua rappresentazione locale in ColumnsList
888
- for (let i = 0; i < ths.length; i++) {
889
- let th = ths[i];
890
- if (this.isEsTh(th)) {
891
- th.Visible = th.Fixed || (columnsCache[th.ID] ? columnsCache[th.ID].visible : th.Visible);
892
- if (th.Fixed)
893
- fixedThs[th.ID] = true;
894
- }
895
- else {
896
- th.thVisible = th.thFixed || (columnsCache[th.th] ? columnsCache[th.th].visible : th.thVisible);
897
- if (th.thFixed)
898
- fixedThs[th.th] = true;
899
- }
900
- }
901
- }
902
- if (tds) {
903
- // Definisco se la cella è visibile in base alla sua rappresentazione locale in ColumnsList
904
- for (let i = 0; i < tds.length; i++) {
905
- let td = tds[i];
906
- if (this.isEsTd(td))
907
- td.Visible = fixedThs[td.ID] || (columnsCache[td.ID] ? columnsCache[td.ID].visible : td.Visible);
908
- else
909
- td.tdVisible = fixedThs[td.td] || (columnsCache[td.td] ? columnsCache[td.td].visible : td.tdVisible);
910
- }
911
- }
912
- this.changed();
913
- }
914
- /**
915
- * Allinea gli ordinamenti dati fra le **EsThs** e le informazioni all'interno della View bindata
916
- *
917
- * @param {AppSearch<any>} view AppSearch da utilizzare per questa operazione
918
- * @param {EsTh[] | EsThDirective[]} ths Colonne della tabella
919
- */
920
- alignHeadersOrdering(ths, view) {
921
- for (let i = 0; i < ths.length; i++) {
922
- let th = ths[i];
923
- if (this.isEsTh(th)) {
924
- th.Order = null;
925
- // Assegno tutti gli ordinamenti che mi vengono da AppSearch. Sono i più importanti. Non faccio cache o cose strano perché tanto questa
926
- // variabile sarà sempre massimo 3 elementi
927
- for (let i = 0; i < view.orders.length; i++) {
928
- let or = view.orders[i];
929
- if (or.id == th.ID)
930
- th.Order = or.order;
931
- }
932
- }
933
- else {
934
- th.thOrder = null;
935
- for (let i = 0; i < view.orders.length; i++) {
936
- let or = view.orders[i];
937
- if (or.id == th.th)
938
- th.thOrder = or.order;
939
- }
940
- }
941
- }
942
- }
943
- /**
944
- * Partendo dagli **EsTds** bindati genera, all'interno del dizionario **TMPRowTDs** tutti i contesti dei vari oggetti.
945
- *
946
- * Vengono esclusi i TD "Interni" in quanto vengono generati dagli originali quindi includerli vorrebbe dire rieffettuare le operazioni due volte
947
- *
948
- * Costo: 2 scan EsThs, 1 scan EsTds
949
- *
950
- * @param {EsTh[] | EsThDirective[]} ths Colonne della tabella
951
- * @param {EsTd[] | EsTdDirective[]} tds Celle della tabella
952
- */
953
- evaluateRowTds(ths, tds) {
954
- if (tds.length == 0)
955
- return;
956
- let thsCache = {};
957
- for (let i = 0; i < ths.length; i++) {
958
- let th = ths[i];
959
- thsCache[this.isEsTh(th) ? th.ID : th.th] = th;
960
- }
961
- this.TMPRowTDs = {};
962
- // Variabile d'appoggio per permettermi di inserire tutte le colonne "Fixed" davanti
963
- let contextFixeds = {};
964
- for (let i = 0; i < tds.length; i++) {
965
- let td = tds[i];
966
- if (this.isEsTd(td)) {
967
- let th = thsCache[td.ID];
968
- if (!!th)
969
- th.Referenced = true;
970
- else
971
- throw "ID dell'oggeto EsTd non compatibile con gli ID dicharati negli EsTh: " + td.ID;
972
- let isFixed = (this.isEsTh(th) && th.Fixed) || (!this.isEsTh(th) && th.thFixed);
973
- let itemToAdd = { GroupAggregation: false, GroupHeader: false, Wraps: true, ID: td.ID, Visible: td.Visible, Class: td.Class, Content: td.Content, RouterLink: td.RouterLink, Template: td.Template };
974
- let ctx = td.Context;
975
- if (this.TMPRowTDs[ctx]) {
976
- if (isFixed)
977
- this.TMPRowTDs[ctx].splice(0 + (contextFixeds[ctx]++), 0, itemToAdd);
978
- else
979
- this.TMPRowTDs[ctx].push(itemToAdd);
980
- }
981
- else {
982
- this.RowContexts.push(ctx);
983
- this.TMPRowTDs[ctx] = [itemToAdd];
984
- contextFixeds[ctx] = isFixed ? 1 : 0;
985
- }
986
- }
987
- else {
988
- for (let i = 0; i < this.boundSource.length; i++) {
989
- let item = this.boundSource[i];
990
- let ctx = item.hash;
991
- let key = td.td;
992
- let th = thsCache[td.td];
993
- if (!!th)
994
- th.Referenced = true;
995
- else
996
- throw "ID dell'oggeto EsTd non compatibile con gli ID dicharati negli EsTh: " + td.td;
997
- if (td.tdIf || (!this.isEsTh(th) && th.thGroup)) {
998
- let thCasted = th;
999
- let isFixed = (this.isEsTh(th) && th.Fixed) || (!this.isEsTh(th) && th.thFixed);
1000
- let itemToAdd = item._item ?
1001
- { ID: key, GroupHeader: false, GroupAggregation: false, Visible: td.tdVisible, Wraps: true, Class: td.tdClass, Template: td.Template } :
1002
- { ID: key, GroupHeader: thCasted.thGroup, GroupAggregation: !!thCasted.thAggregation, Visible: true, Wraps: false, Class: thCasted.thGroupClass || '', Content: this.getGroupCellDisplay(item, key, th) };
1003
- if (this.TMPRowTDs[ctx]) {
1004
- if (isFixed)
1005
- this.TMPRowTDs[ctx].splice(0 + (contextFixeds[ctx]++), 0, itemToAdd);
1006
- else
1007
- this.TMPRowTDs[ctx].push(itemToAdd);
1008
- }
1009
- else {
1010
- this.RowContexts.push(ctx);
1011
- this.TMPRowTDs[ctx] = [itemToAdd];
1012
- contextFixeds[ctx] = isFixed ? 1 : 0;
1013
- }
1014
- }
1015
- }
1016
- }
1017
- }
1018
- // Se non ho oggetti è inutile che controllo gli errori, dato che gli es-td non esisteranno di certo e di conseguenza gli es-th non saranno referenziati
1019
- if (this.TMPBoundSource.length == 0)
1020
- return;
1021
- var errs = [];
1022
- for (let i = 0; i < ths.length; i++) {
1023
- let th = ths[i];
1024
- if (!th.Referenced)
1025
- errs.push(this.isEsTh(th) ? th.ID : th.th);
1026
- }
1027
- if (errs.length > 0) {
1028
- var errIds = errs.join(', ');
1029
- throw "L'ID di uno o più EsTh non hanno alcun EsTd associato: " + errIds;
1030
- }
1031
- }
1032
- /**
1033
- * Partendo dagli **EsThs** bindati genera, all'interno del dizionario **TMPRowTHs** tutti i contesti dei vari oggetti.
1034
- *
1035
- * Vengono esclusi i TH "Interni" in quanto vengono generati dagli originali quindi includerli vorrebbe dire rieffettuare le operazioni due volte
1036
- *
1037
- * Costo: 1 scan EsThs
1038
- *
1039
- * @param {EsTh[] | EsThDirective[]} ths Colonne della tabella
1040
- */
1041
- evaluateRowThs(ths) {
1042
- if (ths.length == 0)
1043
- return;
1044
- let castedView = this.View;
1045
- let groupingsUndefined = !castedView.groupings || castedView.groupings.length == 0;
1046
- this.TMPRowTHs = [];
1047
- let fixed = 0;
1048
- for (let i = 0; i < ths.length; i++) {
1049
- let th = ths[i];
1050
- let toAdd;
1051
- if (this.isEsTh(th)) {
1052
- toAdd = { Fixed: th.Fixed, ID: th.ID, Visible: th.Visible, Class: th.Class, Order: th.Order, Orderable: th.Orderable, Template: null, Content: th.Description, Wrap: false };
1053
- if (th.Fixed)
1054
- this.TMPRowTHs.splice(0 + (fixed++), 0, toAdd);
1055
- else
1056
- this.TMPRowTHs.push(toAdd);
1057
- }
1058
- else if (th.thIf || th.thGroup) {
1059
- // Mentre inserisco mi assicuro di mettere l'elemento per bene in ordine in base alla proprietà "Fixed". Tutte le colonne Fixed devono finire all'inizio
1060
- // (Questo probabilmente diventerà il comportamento di default anche per le colonne "Pinned")
1061
- let thClass = (th.thClass || '') + (th.thGroup ? " est-col-min" : "");
1062
- toAdd = { Fixed: th.thFixed || th.thGroup, ID: th.th, Visible: th.thVisible, Class: thClass, Order: th.thOrder, Orderable: th.thOrderable, Template: th.Template, Content: null, Wrap: false };
1063
- if (th.thFixed)
1064
- this.TMPRowTHs.splice(0 + (fixed++), 0, toAdd);
1065
- else
1066
- this.TMPRowTHs.push(toAdd);
1067
- if (groupingsUndefined && (th.thAggregation || th.thGroup)) {
1068
- let groupAggregations = this.getGroupAggregations(th);
1069
- if (!castedView.groupings)
1070
- castedView.groupings = groupAggregations;
1071
- else
1072
- castedView.groupings.push(...groupAggregations);
1073
- this.ResearchNeeded = true;
1074
- }
1075
- }
1076
- }
1077
- }
1078
- /**
1079
- * Data una direttiva EsTh restituisce la lista delle aggregazioni richiesta per questa colonna o il gruppo che rappresenta
1080
- *
1081
- * @param {EsThDirective} th Direttiva
1082
- *
1083
- * @returns {GroupOrAggregation[]} Lista dei gruppi o aggregazioni relativi alla Direttiva passata
1084
- */
1085
- getGroupAggregations(th) {
1086
- let ret = [];
1087
- // Es: '{min:dd/MM/yyyy} - {max:dd/MM/yyyy}'
1088
- if (th.thAggregation) {
1089
- this.getEsThDirectiveListOfAggregations(th).forEach((agg) => {
1090
- ret.push(new GroupOrAggregation(th.th, agg.func));
1091
- });
1092
- }
1093
- else if (th.thGroup)
1094
- ret.push(new GroupOrAggregation(th.th, null));
1095
- return ret;
1096
- }
1097
- /**
1098
- * Data una direttiva con un formato restituisce tutte le coppie Funzione di Aggregazione - Formato
1099
- *
1100
- * @param {EsThDirective} th Direttiva EsTh di cui calcolare le funzioni di aggregazione usate
1101
- *
1102
- * @returns {{ func: string, format: string }[]} Lista delle funzioni di aggregazione rilevate
1103
- */
1104
- getEsThDirectiveListOfAggregations(th) {
1105
- if (!th.thAggregation)
1106
- return [];
1107
- let ret = [];
1108
- let display = th.thAggregation;
1109
- var matches = display.match(/{[a-zA-Z0-9\/:]*}/gi);
1110
- if (!matches)
1111
- return [];
1112
- matches.forEach(m => {
1113
- let split = m.split(":");
1114
- let func = m, format = "";
1115
- if (split.length > 0) {
1116
- // Escludo primo e ultimo carattere (le graffe)
1117
- func = split[0].substr(1);
1118
- format = split[1].substr(0, split[1].length - 1);
1119
- }
1120
- ret.push({ func: func, format: format, match: m });
1121
- });
1122
- return ret;
1123
- }
1124
- /**
1125
- * Metodo che genera l'ordine di default delle colonne
1126
- *
1127
- * @param {AppSearch<any>} view AppSearch da utilizzare per questa operazione
1128
- */
1129
- generateDefaultOrder(view) {
1130
- if (this.TMPRowTHs.length == 0)
1131
- return;
1132
- // Genero ordinamento di default da 0 fino a dove deve arrivare. Situazione attuale senza hotpotato
1133
- if (!view.column_ordering || view.column_ordering.length == 0) {
1134
- for (let i = 0; i < this.TMPRowTHs.length; i++)
1135
- this.OrderDirectives.push(this.TMPRowTHs[i].ID);
1136
- }
1137
- else
1138
- this.OrderDirectives = view.column_ordering;
1139
- }
1140
- /**
1141
- * Applica l'ordine specificato alle varie colonne
1142
- *
1143
- * @param {AppSearch<any>} view AppSearch da utilizzare per questa operazione
1144
- * @param {boolean} finalize Se **true** significa che non mi aspetto di dover effettuare altre operazioni e posso renderizzare la situazione in base ai RowContext
1145
- * Senza finalize significa che mi aspetto altre operazioni che prima o poi richiameranno questa funzione col finalize.
1146
- *
1147
- * Ad esempio, una volta selezionato ordinamento fisico/logico delle colonne so che parte un altra ricerca che mi rivalorizzera da "writeValue", che già chiama questa funzione.
1148
- * Mettendo solo la chiamata da "writeValue" come "finalizzante" mi assicuro che smanattamenti a frontend non causino flickering fino a quando non servono
1149
- */
1150
- applyOrdering(view, finalize) {
1151
- // Genero ordinamento per gli header
1152
- let newHeaders = [];
1153
- // Se devo finalizzare aggancio tutte le variabili di bind
1154
- if (finalize) {
1155
- this.OrderDirectives.forEach(o => {
1156
- let heaedrItem = this.TMPRowTHs.filter(t => t.ID == o)[0];
1157
- newHeaders.push(heaedrItem);
1158
- });
1159
- this.TMPRowTHs = newHeaders;
1160
- // Genero ordinamento per le celle
1161
- for (let i = 0; i < this.RowContexts.length; i++) {
1162
- let context = this.TMPRowTDs[this.RowContexts[i]];
1163
- let newContext = [];
1164
- this.OrderDirectives.forEach(o => {
1165
- let contextItem = context.filter(t => t.ID == o)[0];
1166
- newContext.push(contextItem);
1167
- });
1168
- this.TMPRowTDs[this.RowContexts[i]] = newContext;
1169
- }
1170
- }
1171
- view.column_ordering = this.OrderDirectives;
1172
- this.changed();
1173
- }
1174
- // #endregion
1175
- // #region Gestione raggruppamenti per riga
1176
- /**
1177
- * Ottiene un elemento di separazione fra Gruppi che serve per paginare le ricerche all'interno di ogni singolo gruppo
1178
- *
1179
- * @param {AppSearch<any>} view View utilizzata per la ricerca. Me ne salvo i parametri nel separatore attuale dato che ne ho bisogno per caricare altri elementi
1180
- * facenti riferimento allo stesso contesto
1181
- * @param {string} parent Parent path che rappresenta a quale gruppo è affibbiato questo separatore
1182
- * @param {number} level Livello del gruppo di cui questo elemento è separatore, viene usato per applicare la classe "est-lvl-{{level}}"
1183
- *
1184
- * @returns {any} Elemento di separazione contenente tutti i bind per presentare una paginazione sotto questo gruppo lato interfaccia
1185
- */
1186
- getGroupSeparator(view, parent, level) {
1187
- let item = {
1188
- _sep: true,
1189
- _parent: parent,
1190
- _grouplevel: level,
1191
- filters: view.requestedgroups.map(t => { return { column: t.column, value: t.value }; }),
1192
- page: view.page,
1193
- pages: view.pages,
1194
- itemsperpage: view.itemsperpageoverride,
1195
- count: view.objectcount
1196
- };
1197
- this.calculateHash([item]);
1198
- return item;
1199
- }
1200
- /**
1201
- * Data una colonna effettua la riemissione di tutte le ricerche relative.
1202
- *
1203
- * Es. Ho 2 campi di gruppo e ho espanso fino a vedere i valori fino ad un livello qualsiasi.
1204
- * Clicco l'ordinamento sul secondo gruppo.
1205
- * Tutte le ricerche relative ai primi gruppi devono essere rieseguite. Quando i risultati arriveranno ci penserà il metodo **bindDisplayToLoadedItemsOrGroups**
1206
- * a tagliare via gli oggetti non più visualizzati
1207
- *
1208
- * @param {string} column Colonna su cui si è effettuata un'operazione di ordinamento
1209
- * @param {AppOrdering[]} orderings Direttive di ordinamento da applicare alle varie sottoricerche
1210
- *
1211
- * @todo: Testare
1212
- */
1213
- emitRowGroupingSearches(column, orderings) {
1214
- // Per tutte le ricerche intermedie che devo rivalutare le re-emitto in modo da aggiornargli i dati
1215
- var meaningfulAppSearches = this.groupSearchRequestsCache.filter(t => t.path.endsWith(column)).map(t => t.view);
1216
- meaningfulAppSearches.forEach(as => {
1217
- // Ovviamente gli oridnamenti devono essere quelli appena generati
1218
- as.orders = orderings;
1219
- this.emitSearchRequest(false, as);
1220
- });
1221
- }
1222
- /**
1223
- * Helper che calcola il contenuto di una cella relativa a un gruppo riga, tenendo conto del formato delle eventuali aggregazioni
1224
- *
1225
- * @param {Group} grp Gruppo di cui mostrare le celle
1226
- * @param {string} cell Cella attuale di cui calcolare il testo
1227
- * @param {EsThDirective} header Header relativo alla cella attuale, utilizzata per identificare le informazioni di aggregazione
1228
- *
1229
- * @returns {string} Testo finale calcolato per la **cell** corrente, in base alle aggregazioni di **header**
1230
- */
1231
- getGroupCellDisplay(grp, cell, header) {
1232
- if (grp._sep)
1233
- return "";
1234
- let display = header.thAggregation;
1235
- if (grp.column == cell)
1236
- return grp.value;
1237
- else {
1238
- let agg = grp.aggregations.filter(t => t.column == cell);
1239
- if (!agg)
1240
- return "";
1241
- this.getEsThDirectiveListOfAggregations(header).forEach((itm) => {
1242
- let aggValue = agg.find(t => t.aggregation == itm.func).value;
1243
- display = display.replace(itm.match, this.formatAggregationValue(aggValue, itm.format));
1244
- });
1245
- return display;
1246
- }
1247
- }
1248
- /**
1249
- * Gestisce i click sulla tabella solo per le righe a gruppo.
1250
- * O rimuove gli elementi attualmente presenti o carica il contenuto del gruppo
1251
- *
1252
- * @param {any} group Gruppo bindato su cui si è effettuato il click
1253
- *
1254
- * @returns {boolean} **true** se l'operaizone è andata a buon fine, **false** altrimenti
1255
- */
1256
- handleGroupClick(group) {
1257
- let casted = this.View;
1258
- let anyGroup = group;
1259
- anyGroup._expanded = !anyGroup._expanded;
1260
- if (anyGroup._expanded) {
1261
- if (!casted.requestedgroups)
1262
- casted.requestedgroups = [new GroupFilter(group.column, group.value)];
1263
- else {
1264
- let level = anyGroup._grouplevel;
1265
- // se il gruppo cliccato non ha un livello è il primo gruppo, quindi ordinamento unico
1266
- // altrimenti devo rimuovere tutti i filtri su livelli superiori al level cliccato e aggiungere il level cliccato
1267
- if (!level)
1268
- casted.requestedgroups = [new GroupFilter(group.column, group.value)];
1269
- else {
1270
- casted.requestedgroups = [];
1271
- anyGroup._parentRoute.forEach((step) => {
1272
- casted.requestedgroups.push(new GroupFilter(step.column, step.value));
1273
- });
1274
- casted.requestedgroups.push(new GroupFilter(group.column, group.value));
1275
- }
1276
- }
1277
- this.changed();
1278
- this.emitSearchRequest(true);
1279
- }
1280
- else {
1281
- let path = (anyGroup._parent || '') + group.value;
1282
- // Se ho chiuso un gruppo non mi serve rieffettuare ricerce, mi basta eliminare dagli oggetti bindati tutti gli elementi sottostanti a quel gruppo
1283
- this.boundSource = this.boundSource.filter(t => !t._parent || !t._parent.startsWith(path));
1284
- // devo però anche rimuovere eventuali cache relative
1285
- this.groupSearchRequestsCache = this.groupSearchRequestsCache.filter(t => t.path != path);
1286
- }
1287
- return true;
1288
- }
1289
- /**
1290
- * Funzione che dato un valore lo formatta in base al tipo
1291
- *
1292
- * @param {string} value Valore che generalemnte può essere una data o un numero
1293
- * @param {string} fromat Formato su cui formattare il valore. Può essere ad esempio "small", "long" "verylong" per le date o F{0-9} per i numeri decimali
1294
- *
1295
- * @returns {string} Valore dell'aggregazione formattato come si deve
1296
- */
1297
- formatAggregationValue(value, format) {
1298
- if (!format)
1299
- return value;
1300
- let isNumber = !Number.isNaN(value) && !format || format.startsWith("F");
1301
- let date = null;
1302
- // Alcune versione di extensions rischiano di crashare con cose non date... è stato risolto dopo quindi questo try - catch in realtà
1303
- // torna utile solo con versioni vecchie/deprecate della libreria @esfaenza/extensions
1304
- try {
1305
- date = this.dateExts.getDateConvertion(value);
1306
- }
1307
- catch (_a) { }
1308
- if (date)
1309
- return this.dateExts.getFormatted(date, format == 'small', format == 'verylong');
1310
- else if (isNumber) {
1311
- if (format.startsWith("F") && !Number.isNaN(format.substr(1)))
1312
- return parseFloat(value).toFixed(parseInt(format.substr(1)));
1313
- }
1314
- // Qui ci finisco sia per input che non sono né date né numeri, sia per formati non riconosciuti
1315
- return value;
1316
- }
1317
- // #endregion
1318
- // #region Gestione Operaizoni dialog ordinamento/visibilità colonne
1319
- /**
1320
- * All'interno della dialog "Ordinamento e Visibilità Colonne" mette la colonna specificata prima della colonna precedente
1321
- *
1322
- * @param {EsTableColumn} columnItem Colonna da spostare
1323
- */
1324
- sendUp(columnItem) {
1325
- let itemIndex = this.TMPColumnsList.indexOf(columnItem);
1326
- if (this.TMPColumnsList[itemIndex - 1].fixed)
1327
- return;
1328
- this.utiExts.swap(this.TMPColumnsList, itemIndex, itemIndex - 1);
1329
- // Non posso fare JSON.parse(JSON.stringify(this.ColumnsList)) perché contiene riferimenti a TemplateRef
1330
- let tmp = [];
1331
- this.TMPColumnsList.forEach(c => { tmp.push(Object.assign({}, c)); });
1332
- this.TMPColumnsList = tmp;
1333
- }
1334
- /**
1335
- * All'interno della dialog "Ordinamento e Visibilità Colonne" mette la colonna specificata dopo la colonna successiva
1336
- *
1337
- * @param {EsTableColumn} columnItem Colonna da spostare
1338
- */
1339
- sendDown(columnItem) {
1340
- let itemIndex = this.TMPColumnsList.indexOf(columnItem);
1341
- this.utiExts.swap(this.TMPColumnsList, itemIndex, itemIndex + 1);
1342
- // Non posso fare JSON.parse(JSON.stringify(this.ColumnsList)) perché contiene riferimenti a TemplateRef
1343
- let tmp = [];
1344
- this.TMPColumnsList.forEach(c => { tmp.push(Object.assign({}, c)); });
1345
- this.TMPColumnsList = tmp;
1346
- }
1347
- /**
1348
- * All'interno della dialog "Ordinamento e Visibilità Colonne" inverte le impostazioni di visibilità della colonna
1349
- *
1350
- * @param {EsTableColumn} columnItem Colonna da spostare
1351
- */
1352
- columnClicked(item) {
1353
- this.lastSelectedItemID = item.id;
1354
- if (!this.HiddenColumns || item.fixed)
1355
- return;
1356
- item.visible = !item.visible;
1357
- this.updateGlobalColVisCheck();
1358
- }
1359
- /**
1360
- * All'apertura della dialog "Ordinamento e Visibilità Colonne" ricarica le informazioni attuali per permettere la modifica
1361
- */
1362
- resetColumnVisSelection() {
1363
- this.TMPColumnsList = [];
1364
- // Non posso fare JSON.parse(JSON.stringify(this.ColumnsList)) perché contiene riferimenti a TemplateRef
1365
- this.TMPColumnsList = [];
1366
- this.ColumnsList.forEach(c => { this.TMPColumnsList.push(Object.assign({}, c)); });
1367
- let reorderedColList = [];
1368
- if (this.ColumnsOrdering) {
1369
- this.OrderDirectives.forEach(o => {
1370
- let column = this.TMPColumnsList.filter(t => t.id == o)[0];
1371
- // Potrei non averne nel caso ci sia il flag HiddenColumns a false, evito di inserire degli undefined
1372
- if (column)
1373
- reorderedColList.push(column);
1374
- });
1375
- this.TMPColumnsList = reorderedColList;
1376
- }
1377
- this.updateGlobalColVisCheck();
1378
- }
1379
- /**
1380
- * Riaggiorna le **OrderDirectives** con le informazioni in **ColumnsList**
1381
- */
1382
- refreshColumnOrdering() {
1383
- this.OrderDirectives = [];
1384
- for (let c = 0; c < this.ColumnsList.length; c++)
1385
- this.OrderDirectives.push(this.ColumnsList[c].id);
1386
- }
1387
- /**
1388
- * Effettua la selezione o meno del check globale (**globalColVisCheck**) di visibilità in base a se tutte le **TMPColumnsList** sono visibili o no
1389
- */
1390
- updateGlobalColVisCheck() {
1391
- // TMPColList viene riempita di undefined nel caso in cui sia disattivata la selezione delle colonne nascoste
1392
- this.globalColVisCheck = this.TMPColumnsList.every(t => t.visible);
1393
- }
1394
- /**
1395
- * Funzione che effettua la conferma della visibilità e dell'ordine delle colonne.
1396
- *
1397
- * Questa selezione viene inoltre salvata nelle preferenze (**@esfaenza/preferences**), qualora l'Input **SavePreferences** fosse valorizzato
1398
- *
1399
- * @returns {boolean} **true** se non ci sono problemi, **false** altrimenti
1400
- */
1401
- confirmColumnVisibilitySelection() {
1402
- // Non permetto di non selezionare nulla
1403
- if (this.TMPColumnsList.every(t => !t.visible))
1404
- return false;
1405
- let castedView = this.View;
1406
- this.ColumnsList = [];
1407
- this.TMPColumnsList.forEach(c => { this.ColumnsList.push(Object.assign({}, c)); });
1408
- this.refreshColumnOrdering();
1409
- this.refreshColumnsVisibility(null, null, castedView);
1410
- this.applyOrdering(castedView, false);
1411
- //Salvo le preferences di questa view
1412
- //Di default registro ordinamento e visibilità delle colonne nella vista. Solo le cose di UI
1413
- if (this.SavePreferences) {
1414
- if (!this.ngControl.name) {
1415
- console.error("Non posso utilizzare le preference senza avere un 'name' per la tabella");
1416
- return false;
1417
- }
1418
- if (!this.prefService) {
1419
- console.error("Non posso utilizzare le preference senza che il pacchetto @esfaenza/preferences sia installato");
1420
- return false;
1421
- }
1422
- var toStore = { columns: JSON.parse(JSON.stringify(castedView.columns)), column_ordering: JSON.parse(JSON.stringify(castedView.column_ordering)) };
1423
- this.prefService.store(this.ngControl.name, toStore);
1424
- }
1425
- // Mi assicuro di farlo dopo l'espansione del changed o rischio che la ricerca mi ridia colonne che in realtà non esistono
1426
- setTimeout(() => { this.emitSearchRequest(false); });
1427
- // Lo vorrei mettere lato template ma no
1428
- this.lastSelectedItemID = null;
1429
- return true;
1430
- }
1431
- /**
1432
- * Sul click nella checkbox di selezione globale si scorrono tutte le colonne e si impostano al valore della check globale
1433
- */
1434
- globalColVisCheckChanged() {
1435
- this.TMPColumnsList.forEach(t => { t.visible = this.globalColVisCheck; });
1436
- }
1437
- // #endregion
1438
- // #region Gestione data source gerarchici
1439
- /**
1440
- * Data una lista di oggetti assegno il livello gerarchico rispetto alla lista di oggetti passata
1441
- *
1442
- * @param {any[]} objs Lista di oggetti a cui aggiungere l'informazione del livello gerarchico
1443
- */
1444
- assignHierarchyLevels(objs) {
1445
- // Casistica input nullo
1446
- if (!objs || !objs.length)
1447
- return;
1448
- //Se mancano entrambe le info le cerco di valorizzare in automatico coi default "parentid" e "id" (posto che le props esistano nell'oggetto)
1449
- if (!this.ParentKey && !this.OwnKey) {
1450
- if (objs[0]['parentid'] !== undefined)
1451
- this.ParentKey = 'parentid';
1452
- if (objs[0]['id'] !== undefined)
1453
- this.OwnKey = 'id';
1454
- }
1455
- //Check finale per assicurarmi che le props ci siano
1456
- if (!this.ParentKey || !this.OwnKey) {
1457
- console.error('Per utilizzare il sistema in modalità gerarchica è obbligatorio specificare sia ParentKey che OwnKey. Fallback a sistema non gerarchico');
1458
- return;
1459
- }
1460
- // Valorizzazione campi level, expanded, e visible per ogni item
1461
- let currentLevel = 1;
1462
- let assigned = 0;
1463
- do {
1464
- assigned = this.assignLevel(objs, currentLevel);
1465
- currentLevel++;
1466
- } while (assigned > 0);
1467
- // butto su lato html e poi me la gioco là con padding = 20 * (level - 1) per far capire il diverso livello
1468
- }
1469
- /**
1470
- * Per ognuno degli oggetti passati gli assegna un livello di gerarchia in base a **ParentKey** e **OwnKey**
1471
- *
1472
- * @param {any[]} objs Oggetti a cui assegnare il livello di gerarchia
1473
- * @param {number} levelToAssign Livello che sta assegnando attualmente questa iterazione (dato che è ricorsiva)
1474
- *
1475
- * @returns {number} Numero di oggetti a cui è stato assegnato un livello gerarchico
1476
- */
1477
- assignLevel(objs, levelToAssign) {
1478
- let assigned = 0;
1479
- for (let i = 0; i < objs.length; i++) {
1480
- let obj = objs[i];
1481
- // Se la parentKey non è valorizzata, questo è il livello 0 (1... perché gli 0 son perciolosi)
1482
- if (!obj[this.ParentKey] && levelToAssign == 1) {
1483
- obj.level = 1;
1484
- obj.visible = true;
1485
- obj.expanded = this.StartsExpanded;
1486
- assigned++;
1487
- continue;
1488
- }
1489
- // Per i livelli superiore al primo
1490
- if (obj[this.ParentKey] && levelToAssign > 1) {
1491
- // trovo il parent
1492
- for (let p = 0; p < objs.length; p++) {
1493
- let possibleParent = objs[p];
1494
- // Trovato il parent dell'item, assegno all'item il livello giusto
1495
- if (possibleParent[this.OwnKey] == obj[this.ParentKey] && possibleParent.level == levelToAssign - 1) {
1496
- obj.level = levelToAssign;
1497
- // So che questo item ha un parent. Ribadisco che il parent è espanso in base alle impostazione e stessa logica
1498
- // per la visibilità del figlio
1499
- possibleParent.expanded = this.StartsExpanded;
1500
- possibleParent.parent = true;
1501
- obj.visible = this.StartsExpanded;
1502
- assigned++;
1503
- break;
1504
- }
1505
- }
1506
- }
1507
- }
1508
- return assigned;
1509
- }
1510
- /**
1511
- * Funzione che permette di effettuare l'espansione di un parent quando la tabella funziona in modalità gerarchica
1512
- *
1513
- * @param {string} key Chiave del parent da espandere
1514
- */
1515
- expandParent(key) {
1516
- for (let i = 0; i < this.boundSource.length; i++) {
1517
- let obj = this.boundSource[i];
1518
- // Trovo il parent con quell'id e lo espando
1519
- if (obj[this.OwnKey] == key) {
1520
- obj.expanded = true;
1521
- for (let ic = 0; ic < this.boundSource.length; ic++) {
1522
- let child = this.boundSource[ic];
1523
- // Trovo tutti i child di quel parent e li rendo visibili
1524
- if (child[this.ParentKey] == key)
1525
- child.visible = true;
1526
- }
1527
- return;
1528
- }
1529
- }
1530
- }
1531
- /**
1532
- * Funzione che permette di effettuare il collapse di un parent quando la tabella funziona in modalità gerarchica
1533
- *
1534
- * @param {string} key Chiave del parent da collassare
1535
- */
1536
- collapseParent(key) {
1537
- for (let i = 0; i < this.boundSource.length; i++) {
1538
- let obj = this.boundSource[i];
1539
- // Trovo il parent con quell'id e lo collasso
1540
- if (obj[this.OwnKey] == key) {
1541
- obj.expanded = false;
1542
- // Collasso/nascondo tutti i child del parent
1543
- this.collapseChildOfParent(key);
1544
- return;
1545
- }
1546
- }
1547
- }
1548
- /**
1549
- * Collassa ricorsivamente tutti i figli di un parent identificato dalla **parentKey**
1550
- *
1551
- * @param {string} parentKey Chiave del parent di cui collassare i figli
1552
- */
1553
- collapseChildOfParent(parentKey) {
1554
- for (let ic = 0; ic < this.boundSource.length; ic++) {
1555
- let child = this.boundSource[ic];
1556
- // Trovo tutti i child di quel parent e li rendo invisibili. Se il child trovato è a sua volta un parent,
1557
- // lo collasso e vado in ricorsione sui figli
1558
- if (child[this.ParentKey] == parentKey && !child.parent)
1559
- child.visible = false;
1560
- else if (child[this.ParentKey] == parentKey && child.parent) {
1561
- child.expanded = false;
1562
- child.visible = false;
1563
- this.collapseChildOfParent(child[this.OwnKey]);
1564
- }
1565
- }
1566
- }
1567
- // #endregion
1568
- // #region Gestione Selezione
1569
- /**
1570
- * Valuta quali elementi devono essere marcati come selezionati nella vista attuale. Si basa sull'oggetto **selection** interno all'AppSearch
1571
- *
1572
- * @param {any[]} items Oggetti di cui valutare la selezione
1573
- * @param {ItemsSelection<any>} selectionItem Oggetti di selezione derivante dalla view o dall'oggetto per Array
1574
- */
1575
- evaluateSelection(items, selectionItem) {
1576
- if (!selectionItem)
1577
- return;
1578
- this.handleSelectionEvaluation(items, selectionItem);
1579
- }
1580
- /**
1581
- * Valuta quali elementi devono essere marcati come selezionati nella vista attuale. Si basa sull'oggetto **arraymodeSelection** dell'es-table
1582
- *
1583
- * @param {any[]} array Lista di oggetti di cui valutare la selezione in modalità array
1584
- */
1585
- arrayModeEvaluateSelection(array) {
1586
- if (array.length == 0)
1587
- return;
1588
- this.handleSelectionEvaluation(array, this.arraymodeSelection);
1589
- }
1590
- /**
1591
- * Implementazione agnostica della valutazione delle selezioni degli oggetti. Richiede gli oggetti della vista attuale e l'itemSelector
1592
- *
1593
- * @param {any[]} items Oggetti di cui aggiornare lo stato di selezione
1594
- * @param {ItemsSelection<any>} selectionItem Oggetto contenente lo stato attuale di selezione
1595
- */
1596
- handleSelectionEvaluation(items, selectionItem) {
1597
- let allSelected = items.length > 0;
1598
- for (let i = 0; i < items.length; i++) {
1599
- let itm = items[i];
1600
- // Reidrato la cache di selezione coi nuovi oggetti altrimenti non riuscirei a beccare gli indici giusti
1601
- // Dopodiché la uso per calcolare istantaneamente se gli oggetti sono selezionati o no
1602
- if (this.selOrDeselCache[itm.hash])
1603
- this.selOrDeselCache[itm.hash] = itm;
1604
- if (selectionItem.all)
1605
- itm._selected = !this.selOrDeselCache[itm.hash];
1606
- else
1607
- itm._selected = !!this.selOrDeselCache[itm.hash];
1608
- allSelected = allSelected && itm._selected;
1609
- }
1610
- // Se tutti gli oggetti di questa pagina sono solezionati allora posso mettere il global check a true
1611
- // Se sono in situazione di all-select anche metto la global checkbox, nonostante ci possano essere delle esclusioni
1612
- this.globalCheck = allSelected || selectionItem.all;
1613
- this.canSelectAll = selectionItem.count > 0 && this.SelectAll;
1614
- // Potrebbe cambiare qualora qualcuno inserisse dati a manazza in modalità Array e desse il refresh manuale alla tabella
1615
- // Comunque costa 0 quindi mi permetto di refreshare
1616
- if (this.arrayMode) {
1617
- let prevSelected = this.selectedObjects;
1618
- this.finalizeSelectionInformations(selectionItem);
1619
- if (this.selectedObjects != prevSelected)
1620
- this.onSelectionChanged.emit(selectionItem);
1621
- }
1622
- }
1623
- /**
1624
- * Gestisce la selezione globale degli oggetti, sia per pagina che a livello di **SelectAll**
1625
- *
1626
- * @param {boolean} forcedVal Valore forzato di check da assegnare agli oggetti
1627
- */
1628
- globalCheckChanged(forcedVal = null) {
1629
- // Prendo tutti gli elementi presenti in questa vista che non siano gruppi
1630
- let items = this.boundSource.filter(t => !t._group);
1631
- var itemSelection = this.handleItemsSelection(items, forcedVal, this.globalCheck);
1632
- this.changed();
1633
- this.onSelectionChanged.emit(itemSelection);
1634
- }
1635
- /**
1636
- * Helper per gestire la selezione di N elementi utilizzando la Cache di selezione ed eventualmente aggiornando il concetto di "all selection"
1637
- *
1638
- * Vunziona sia in modalità Array che in modalità View Semplice o View Avanzata (con le Custom Cells)
1639
- *
1640
- * @param {any[]} items Oggetti da selezionare o deselezionare
1641
- * @param {boolean} forcedVal Valore forzato di check da assegnare agli oggetti
1642
- *
1643
- * @returns {ItemsSelection<any>} Oggetto di selezione aggiornato con le informazioni sull'ultima operazione effettuata
1644
- */
1645
- handleItemsSelection(items, forcedVal = null, globalCheck = null) {
1646
- var _a, _b;
1647
- let selectionItem = ((_a = this.View) === null || _a === void 0 ? void 0 : _a.selection) || this.arraymodeSelection;
1648
- // Se sono in modalità di selezione singola e devo selezionare un'oggetto, per prima cosa devo deselezionare tutti gli altri
1649
- if (this.SingleSelection && ((_b = items[0]) === null || _b === void 0 ? void 0 : _b._selected)) {
1650
- if (items.length > 1 && forcedVal == null)
1651
- throw "Tentativo di selezionare o deselezionare più di un elemento con SingleSelection attivo";
1652
- if (items.length == 1 && forcedVal == null) {
1653
- selectionItem = this.handleItemsSelection(this.boundSource.filter(t => !t._group), false, null);
1654
- items[0]._selected = true;
1655
- }
1656
- }
1657
- for (let i = 0; i < items.length; i++) {
1658
- let item = items[i];
1659
- let toChange = forcedVal != null ? item._selected != forcedVal : globalCheck != null ? item._selected != this.globalCheck : false;
1660
- // Se dev'essere overridato il valore di check effettuo l'override o col valore forzato o col valore globale
1661
- if (toChange && !item.locked)
1662
- item._selected = forcedVal != null ? forcedVal : this.globalCheck;
1663
- if (selectionItem.all) {
1664
- // In caso di "seleziona tutto"...
1665
- // N.B: la selOrDeselCache agisce come cache di DESELEZIONE in questo blocco di codice
1666
- if (item._selected && this.selOrDeselCache[item.hash]) {
1667
- // Oggetto selezionato: lo rimuovo dalle esclusioni di selezione
1668
- selectionItem.exclusions.splice(selectionItem.exclusions.indexOf(this.selOrDeselCache[item.hash]), 1);
1669
- delete this.selOrDeselCache[item.hash];
1670
- }
1671
- else if (!item._selected && !this.selOrDeselCache[item.hash]) {
1672
- // Oggetto deselezionato: lo aggiungo alle esclusioni di selezione
1673
- this.selOrDeselCache[item.hash] = item;
1674
- selectionItem.exclusions.push(item);
1675
- }
1676
- }
1677
- else {
1678
- //In caso di non "seleziona tutto"...
1679
- // N.B: la selOrDeselCache agisce come cache di SELEZIONE in questo blocco di codice
1680
- if (item._selected && !this.selOrDeselCache[item.hash]) {
1681
- // Oggetto selezionato: lo aggiungo alla selezione attuale
1682
- this.selOrDeselCache[item.hash] = item;
1683
- selectionItem.items.push(item);
1684
- }
1685
- else if (!item._selected && this.selOrDeselCache[item.hash]) {
1686
- // Oggetto deselezionato: lo rimuovo dalla selezione attuale
1687
- selectionItem.items.splice(selectionItem.items.indexOf(this.selOrDeselCache[item.hash]), 1);
1688
- delete this.selOrDeselCache[item.hash];
1689
- }
1690
- }
1691
- }
1692
- // Imposto il check globale in base a se tutti gli elementi sono selezionati o meno.
1693
- // Evito di fare queste operazioni se la selezione deriva proprio dal global Check
1694
- // Non è ottimizzatissimo mettere 2 some ma scrivere questo codice a for sono tipo 25 righe....
1695
- if (globalCheck == null)
1696
- this.globalCheck = !items.some(t => !t._selected) && !this.boundSource.some(t => !t._selected && !t._group);
1697
- this.finalizeSelectionInformations(selectionItem);
1698
- return selectionItem;
1699
- }
1700
- /**
1701
- * Finalizza le informazioni di selezione del **ItemsSelection** corrente
1702
- */
1703
- finalizeSelectionInformations(selectionItem) {
1704
- selectionItem.count = this.evaluateSelected();
1705
- // Se ho fatto selezione "all" ma poi mi sono messo a togliere tutti gli elementi fino a rimanerne 0 resetto l'oggetto di selezione
1706
- if (selectionItem.count == 0 && selectionItem.all) {
1707
- selectionItem.all = false;
1708
- selectionItem.exclusions = [];
1709
- selectionItem.items = [];
1710
- // Ripulisco la cache altrimenti mi rimane piena di tutte le esclusioni
1711
- this.selOrDeselCache = {};
1712
- }
1713
- // Se la possibilità di fare "Seleziona tutto" è abilitata allora la considero appena mi viene selezionato qualcosa
1714
- this.canSelectAll = selectionItem.count > 0 && this.SelectAll;
1715
- }
1716
- /**
1717
- * Gestisce i click sulla tabella, gestendo eventualmente anche gli Shift + Click per selezionare un range di oggetti
1718
- *
1719
- * @param {any} event Evento nativo HTML del click
1720
- * @param {any} item Oggetto bindato su cui si è effettuato il click
1721
- *
1722
- * @returns {boolean} **true** se l'operaizone è andata a buon fine, **false** altrimenti
1723
- */
1724
- handleClick(event, item) {
1725
- // Seleziono del testo ma non ho shift premuto -> ignoro la selezione
1726
- if ((event.view.getSelection().type == 'Range' || event.view.getSelection().toString().length > 0) && !event.shiftKey)
1727
- return false;
1728
- // Seleziono del testo e ho shift premuto -> annullo la selezione del testo
1729
- if ((event.view.getSelection().type == 'Range' || event.view.getSelection().toString().length > 0) && event.shiftKey)
1730
- this.utiExts.clearTextSelection();
1731
- let selecteditems = [];
1732
- if (event.shiftKey && this.ShiftClick && !this.SingleSelection) {
1733
- let startSelecting = false;
1734
- let items = this.boundSource.filter(t => !t.group);
1735
- for (let i = 0; i < items.length; i++) {
1736
- let t = items[i];
1737
- if (startSelecting) {
1738
- t._selected = true;
1739
- selecteditems.push(t);
1740
- }
1741
- if ((t == item || t == this.lastSelected) && !startSelecting) {
1742
- startSelecting = true;
1743
- t._selected = true;
1744
- selecteditems.push(t);
1745
- }
1746
- else if ((t == item || t == this.lastSelected) && startSelecting)
1747
- startSelecting = false;
1748
- }
1749
- }
1750
- else {
1751
- item._selected = !item._selected;
1752
- this.lastSelected = item;
1753
- selecteditems.push(item);
1754
- }
1755
- var itemSelection = this.handleItemsSelection(selecteditems);
1756
- this.changed();
1757
- this.onSelectionChanged.emit(itemSelection);
1758
- return true;
1759
- }
1760
- /**
1761
- * Valuta la quantità di oggetti che sono stati selezionati al termine di un evento di selezione
1762
- *
1763
- * @returns {number} Numero di oggetti selezionati
1764
- */
1765
- evaluateSelected() {
1766
- var _a;
1767
- let selectionItem = ((_a = this.View) === null || _a === void 0 ? void 0 : _a.selection) || this.arraymodeSelection;
1768
- this.selectedObjects = selectionItem.all ? (this.View.objectcount || this.View.length) - selectionItem.exclusions.length : selectionItem.items.length;
1769
- return this.selectedObjects;
1770
- }
1771
- /**
1772
- * Gestisce il comando di "Seleziona tutto in tutte le pagine" o il suo contrario, cioè "Reimposta selezione"
1773
- */
1774
- selectAllOrResetSelection() {
1775
- let selectionItem = this.View.selection || this.arraymodeSelection;
1776
- this.selOrDeselCache = {};
1777
- selectionItem.all = !selectionItem.all;
1778
- selectionItem.exclusions = [];
1779
- selectionItem.items = [];
1780
- // Ripulisco gli stati UI di selezione globale se l'ho disattivata
1781
- if (!selectionItem.all) {
1782
- this.canSelectAll = false;
1783
- this.globalCheck = false;
1784
- }
1785
- this.finalizeSelectionInformations(selectionItem);
1786
- this.onSelectionChanged.emit(selectionItem);
1787
- // Dopo aver resettato direttamente il solo oggetto this.View.selection devo anche riallineare a tutti gli oggetti bindati
1788
- this.evaluateSelection(this.viewMode ? this.View.items : this.View, selectionItem);
1789
- }
1790
- // #endregion
1791
- // #region Gestione Paginazione
1792
- /**
1793
- * Sposta la ricerca di una pagina in avanti (o indeitro)
1794
- *
1795
- * @param {number} page Numero di pagine da aggiungere (o sottrarre, se negativo) alla pagina attuale
1796
- */
1797
- addToPage(page) {
1798
- if (!(this.View instanceof AppSearch) && !(this.SearchView instanceof AppSearch) && !(this.View instanceof ReportDefinition))
1799
- return;
1800
- this.goToPage((this.SearchView || this.View).page + page);
1801
- }
1802
- /**
1803
- * Sposta la ricerca alla pagina specificata
1804
- *
1805
- * @param {number} page Pagina a cui navigare
1806
- */
1807
- goToPage(page) {
1808
- if (!(this.View instanceof AppSearch) && !(this.SearchView instanceof AppSearch) && !(this.View instanceof ReportDefinition))
1809
- return;
1810
- let appSearchElement = this.SearchView || this.View;
1811
- if (page === 0 || page > appSearchElement.pages)
1812
- return;
1813
- appSearchElement.page = page;
1814
- this.arrayPulsanti = this.getPagesArray(6, appSearchElement.page, appSearchElement.pages);
1815
- this.emitSearchRequest(false);
1816
- }
1817
- /**
1818
- * Evento richiamato sul cambio della paginazione. Verrà richiamato l'evento **emitSearchRequest**
1819
- * per comunicare al componente che utilizza questa tabella che i dati sono da aggiornare
1820
- */
1821
- onItemsPerPageChanged() {
1822
- this.emitSearchRequest(true);
1823
- }
1824
- // #endregion
1825
- // #region Gestione Export
1826
- /**
1827
- * Effettua l'esportazione dei dati
1828
- *
1829
- * @param {string} format Formato di esportazione. Letto solo in modalità Report della tabella
1830
- */
1831
- tryExport(format) {
1832
- if (!this.ExportFunction)
1833
- return;
1834
- if (this.reportMode)
1835
- this.ExportFunction(format);
1836
- else
1837
- this.ExportFunction((data, cancel = false) => {
1838
- if (cancel)
1839
- return;
1840
- if (data.length == 0) {
1841
- this.msgExts.simpleWarning(this.lc.loc("Cannot export an empty dataset"));
1842
- return;
1843
- }
1844
- this.setupExport(data);
1845
- this.cdr.detectChanges();
1846
- setTimeout(() => { this.exportDownloader.nativeElement.click(); });
1847
- });
1848
- }
1849
- /**
1850
- * Metodo che effettivamente genera gli header e i dati per l'esportazione con **ngx-csv**
1851
- *
1852
- * @param {any[]} items Oggetti da esportare
1853
- */
1854
- setupExport(items) {
1855
- let drcd = this.DynamicRowColumnsDefinition;
1856
- this.headers = drcd && drcd.length > 0 ? this.expExts.setupForGenericExport(items, drcd.map(t => { return { label: t.description, key: t.propertyName, order: t.columnOrder }; })) : this.expExts.setupForExport(items);
1857
- this.data = items;
1858
- }
1859
- // #endregion
1860
- // #region Gestione Modalità Report
1861
- /**
1862
- * Sul click dell'Header di una colonna questo metodo si occupa di applicare l'ordinamento successivo e di notificare con **emitSearchRequest**
1863
- * il bisogno di aggiornare i dati da parte del componente che utilizza la tabella
1864
- *
1865
- * Utilizzato solo in modalità REport
1866
- *
1867
- * @param {ReportColumn} clm Colonna del report per cui ordinare
1868
- */
1869
- setupNextOrderAndSearch(clm) {
1870
- if (!(this.View instanceof ReportDefinition)) {
1871
- console.error('View diversa da reportdefinition entrata nel metodo setupNextOrderAndSearch');
1872
- return;
1873
- }
1874
- let orderNext = { NONE: 'DESC', DESC: 'ASC', ASC: null };
1875
- let nextOrder = orderNext[clm.order || 'NONE'];
1876
- clm.order = nextOrder;
1877
- let order;
1878
- let clmOrder = this.View.orders ? this.View.orders.filter(t => t.column == clm.id) : [];
1879
- if (clmOrder.length == 0 && clm.order) {
1880
- order = new ReportOrder();
1881
- order.column = clm.id;
1882
- order.order = clm.order;
1883
- if (!this.View.orders)
1884
- this.View.orders = [];
1885
- this.View.orders.push(order);
1886
- }
1887
- else if (clmOrder.length == 1) {
1888
- // Rimuovo l'ordinamento o aggiorno quello già esistente
1889
- if (!clm.order)
1890
- clmOrder = [];
1891
- else
1892
- clmOrder[0].order = clm.order;
1893
- }
1894
- else
1895
- console.warn('Impossibile settare ordinamento. Colonna ' + clm.id + ' direttive di ordinamento ' + clmOrder.length + ' ordinamento scelto ' + clm.order);
1896
- // Dopo aver aggiornato l'ordinamento rilancio la ricerca
1897
- this.emitSearchRequest(false);
1898
- }
1899
- /**
1900
- * Metodo che si occupa di gestire la grafica della tabella in base alle informazioni di ordinamento colonne e paginazione contenuti nel modello
1901
- */
1902
- reviewReportBindings() {
1903
- if (!(this.View instanceof ReportDefinition)) {
1904
- console.error('View diversa da reportdefinition entrata nel metodo reviewReportBindings');
1905
- return;
1906
- }
1907
- // Allineo le informazioni su eventuali ordinamenti fatti precedentemente
1908
- if (this.View.orders && this.View.orders.length > 0) {
1909
- this.View.orders.forEach(t => {
1910
- this.ReportValues.columns.filter(c => c.id == t.column)[0].order = t.order;
1911
- });
1912
- }
1913
- // Recupero il count precedente se serve
1914
- if (this.ReportValues.count != -2)
1915
- this.previousCount = this.ReportValues.count;
1916
- else if (this.ReportValues.count == -2)
1917
- this.ReportValues.count = this.previousCount;
1918
- let ipp = (this.View.itemsperpageoverride || 15);
1919
- this.View.pages = Math.ceil(this.ReportValues.count / ipp);
1920
- this.arrayPulsanti = this.getPagesArray(6, this.View.page, this.View.pages);
1921
- }
1922
- // #endregion
1923
- // #region Gestione update automatico
1924
- /**
1925
- * Metodo che gestisce la modifica del tempo specificato per l'aggiornamento automatico
1926
- */
1927
- autoUpdateChanged() {
1928
- if (!/^[1-9]\d*$/.test(this.seconds))
1929
- this.seconds = '10';
1930
- let secondsInMs = parseInt(this.seconds, null) * 1000;
1931
- if (this.autoUpdate)
1932
- this.updateTimer = setInterval(() => { this.emitSearchRequest(false); }, secondsInMs);
1933
- else
1934
- clearInterval(this.updateTimer);
1935
- }
1936
- // #endregion
1937
- // #region Gestione tabella dinamica
1938
- /**
1939
- * Metodo chiamato dal click su una delle colonne generate dall'Input **DynamicOperations**
1940
- *
1941
- * @param {any} item L'oggetto su cui va effettuata l'operazione
1942
- * @param {string} opid Codice identificativo dell'operazione da effettuarsi
1943
- */
1944
- dynamicOperation(item, opid) {
1945
- this.onDynamicOperation.emit({ id: opid, item: item });
1946
- }
1947
- /**
1948
- * Ottiene il contenuto dell'EsTd da utilizzare per la colonna specificata
1949
- *
1950
- * @param {string} column Colonna per cui cercare la cella
1951
- *
1952
- * @returns {TemplateRef<any>} Template da usare per la colonna
1953
- */
1954
- findEsTd(column) {
1955
- var EsTd = this.EsTdsDirective.find((item) => item.td === column);
1956
- return EsTd ? EsTd.Template : null;
1957
- }
1958
- /**
1959
- * Metodo di supporto alla creazione di un router link parametrizzato all'oggetto corrente utilizzato nella modalità dinamica
1960
- *
1961
- * @param {string} path Path su cui navigare con eventuali parametri riferiti all'oggetto cotnestuale come {0}, {1}, ecc...
1962
- * @param {string[]} parameterProps Lista posizionale delle proprietà a cui bindare i riferimenti del parametro **path**
1963
- * Es. Il valore dela proprietà all'indice 0 di questo array verrà sostituita al valore {0} del parametro **path**
1964
- * @param {GenericItem} item Oggetto generico collegato a questo contesto
1965
- *
1966
- * @returns {any} Router link generato in base al parametri
1967
- */
1968
- generateRouterLink(path, parameterProps, item) {
1969
- if (this.DynamicTableRouterLinkCache[item.hash + path]) {
1970
- return this.DynamicTableRouterLinkCache[item.hash + path];
1971
- }
1972
- else {
1973
- let link = this.getRouterLink(path, parameterProps, item);
1974
- this.DynamicTableRouterLinkCache[item.hash + path] = link;
1975
- return link;
1976
- }
1977
- }
1978
- /**
1979
- * Crea un router link
1980
- *
1981
- * @param {string} path Path su cui navigare con eventuali parametri riferiti all'oggetto cotnestuale come {0}, {1}, ecc...
1982
- * @param {string[]} pars Lista posizionale delle proprietà a cui bindare i riferimenti del parametro **path**
1983
- * Es. Il valore dela proprietà all'indice 0 di questo array verrà sostituita al valore {0} del parametro **path**
1984
- * @param {GenericItem} item Oggetto generico collegato a questo contesto
1985
- *
1986
- * @returns {any} Router link generato in base al parametri
1987
- */
1988
- getRouterLink(path, pars, item) {
1989
- for (let i = 0; i < pars.length; i++)
1990
- path = path.replace('{' + i + '}', item.properties[pars[i]]);
1991
- path = path.replace(/'/g, '"').replace(/ /g, '');
1992
- return JSON.parse(path);
1993
- }
1994
- // #endregion
1995
- // #region Paginazione in modalità Array
1996
- /**
1997
- * Equivalente del metodo **addToPage** riadattato per la modalità array
1998
- *
1999
- * @param {number} page Numero di pagine da aggiungere (o sottrarre, se negativo) alla pagina attuale
2000
- */
2001
- arrayAddToPage(page) {
2002
- this.arrayGoToPage(this.arraymodePage + page);
2003
- }
2004
- /**
2005
- * Equivalente del metodo **goToPage** riadattato per la modalità array
2006
- *
2007
- * @param {number} page Pagina a cui navigare
2008
- */
2009
- arrayGoToPage(page) {
2010
- if (page === 0 || page > this.arraymodePages)
2011
- return;
2012
- this.arraymodePage = page;
2013
- // Riforzo il writevalue in modo che il codice passi dalla gestione come se fosse fatta ripartire una ricerca
2014
- this.internalWriteValue();
2015
- }
2016
- /**
2017
- * Metodo per effettuare il refresh della paginazione sul cambiamento degli oggetti da visualizzare in una singola pagina.
2018
- *
2019
- * Vale solo per la modalità Array
2020
- *
2021
- * @param {number} pageSize Dimensione della pagina
2022
- */
2023
- refreshPaging(pageSize) {
2024
- this.ArraymodeItemsPerPage = pageSize;
2025
- this.arraymodePages = Math.ceil(this.View.length / this.ArraymodeItemsPerPage);
2026
- this.arraymodePage = 1;
2027
- // Riforzo il writevalue in modo che il codice passi dalla gestione come se fosse fatta ripartire una ricerca
2028
- this.internalWriteValue();
2029
- }
2030
- /**
2031
- * Genera le informazioni di paginazione e taglia la View in modalità array per mostrare solo gli oggetti della pagina specificata
2032
- */
2033
- adaptViewToPaging() {
2034
- let tmpItems = [];
2035
- // Se ho una search view l'array pulsanti viene calcolato da lei, non devo prendere quello della modalità array
2036
- if (!this.SearchView)
2037
- this.arrayPulsanti = this.getPagesArray(6, this.arraymodePage, this.arraymodePages);
2038
- // Poi per tutti i valori dopo compresi fra la pagina - 1 e la pagina
2039
- for (let i = ((this.arraymodePage - 1) * this.ArraymodeItemsPerPage); i < this.arraymodePage * this.ArraymodeItemsPerPage; i++) {
2040
- if (i <= this.View.length - 1)
2041
- tmpItems.push(this.View[i]);
2042
- }
2043
- return tmpItems;
2044
- }
2045
- // #endregion
2046
- // #region Gestione click sulle celle dinamiche e opzioni nel Corner Menu
2047
- /**
2048
- * Gestore dei click sulle celle per le quali era impostata una azione custom da **CustomCellActionsOn**
2049
- *
2050
- * @param {string} name Nome della cella su cui si è fatto click
2051
- * @param {any} model Modello relativo alla cella cliccata
2052
- *
2053
- * @returns {boolean} **true** se il click è stato fatto su una cella cliccabile, **false** altrimenti
2054
- */
2055
- cellClicked(name, model) {
2056
- if (this.UseCustomCellActions && this.CustomCellActionsOn.split('$').indexOf(name) != -1) {
2057
- this.onCellClick.emit({ column: name, model: model });
2058
- return true;
2059
- }
2060
- return false;
2061
- }
2062
- /**
2063
- * Gestione dei click sulle opzioni del menù contestuale in alto a destra generato dall'Input **CornerMenuOptions**
2064
- *
2065
- * @param {string} cornerid Codice dell'operazione selezionata
2066
- */
2067
- cornerActionClicked(cornerid) {
2068
- this.onCornerAction.emit({ id: cornerid, estable: this });
2069
- }
2070
- // #endregion
2071
- // #region Metodi di utilità
2072
- /** Helper che identifica se il td attuale è di tipo **EsTd**. In caso contrario è da considerarsi **EsTdDirective** */
2073
- isEsTd(td) {
2074
- return !td._directive;
2075
- }
2076
- /** Helper che identifica se il th attuale è di tipo **EsTh**. In caso contrario è da considerarsi **EsThDirective** */
2077
- isEsTh(th) {
2078
- return !th._directive;
2079
- }
2080
- /** Impostazione modalità dell'EsTable */
2081
- setMode(mode) {
2082
- this.viewMode = mode == 'view';
2083
- this.arrayMode = mode == 'array';
2084
- this.reportMode = mode == 'report';
2085
- if (this.reportMode) {
2086
- // In modalità report ho di sicuro queste due
2087
- this.XLSXExport = true;
2088
- this.CSVExport = false;
2089
- }
2090
- }
2091
- /**
2092
- * Helper per effettuare chiamate interne di allineamento alla funzione **writeValue**,
2093
- * impostando prima **internalWriteCall** in modo da non effettuare operazioni inutili
2094
- */
2095
- internalWriteValue() {
2096
- this.internalWriteCall = true;
2097
- this.writeValue(this.View);
2098
- this.internalWriteCall = false;
2099
- }
2100
- /**
2101
- * Date le informazioni di paginazione ottiene l'array dei pulsanti
2102
- *
2103
- * @param {number} maxBtns Numero massimo di pulsanti da visualizzare
2104
- * @param {number} page Pagina corrente
2105
- * @param {number} lastPage Ultima pagina disponibile
2106
- *
2107
- * @returns {any[]} Pseudo-array di pulsanti a cui ci si può bindare lato HTML
2108
- */
2109
- getPagesArray(maxBtns, page, lastPage) {
2110
- let result = [];
2111
- if (lastPage == -1)
2112
- lastPage = page + 1;
2113
- let min, max;
2114
- if (lastPage <= maxBtns) {
2115
- min = 1;
2116
- max = lastPage - 1;
2117
- }
2118
- else {
2119
- // tolgo la pagina selected è l'ultima pagina che è quella delle pagine totali
2120
- let rangeOutside = (maxBtns - 2) / 2;
2121
- min = page - rangeOutside;
2122
- max = page + rangeOutside;
2123
- if (min < 1) {
2124
- min = 1;
2125
- max = maxBtns - 1;
2126
- }
2127
- else if (max >= lastPage) {
2128
- min = lastPage - maxBtns + 1;
2129
- max = lastPage - 1;
2130
- }
2131
- }
2132
- result.push({ val: 1, cssClass: (1 === page ? 'btn-main app-white-text' : 'app-white-button') });
2133
- if (max >= min) {
2134
- for (let i = min; i <= max; i++)
2135
- if (i !== 1)
2136
- result.push({ val: i, cssClass: (i === page ? 'btn-main app-white-text' : 'app-white-button') });
2137
- result.push({
2138
- val: lastPage,
2139
- cssClass: (lastPage === page ? 'btn-main app-white-text' : 'app-white-button')
2140
- });
2141
- }
2142
- return result;
2143
- }
2144
- /**
2145
- * Calcola l'hash di un oggetto qualsiasi
2146
- *
2147
- * @param {any[]} items Oggetti per cui calcolare l'hash
2148
- */
2149
- calculateHash(items) {
2150
- if (!items)
2151
- return;
2152
- // Supporto a hash duplicati di oggetti uguali
2153
- let usedHashesCache = {};
2154
- for (let i = 0; i < items.length; i++) {
2155
- let item = items[i];
2156
- // Prima di calcolare l'hash rimuovo le proprietà interne prima che mi scompensino i calcoli successivi
2157
- delete item._selected;
2158
- delete item.hash;
2159
- let hash = this.hashExts.hashObject(item);
2160
- usedHashesCache[hash] = usedHashesCache[hash] ? usedHashesCache[hash] + 1 : 1;
2161
- item.hash = hash + (usedHashesCache[hash] > 1 ? "_" + usedHashesCache[hash] : "");
2162
- }
2163
- }
2164
- /**
2165
- * Metodo eventualmente richiamabile anche dal componente esterno che permette di forzare un refresh della tabella
2166
- */
2167
- forceRefresh() {
2168
- // Se sono in modalità View viene mantenuto in automatico il numero di pagina, ma per la modalità array devo prendere le info di paginazione prima e riapplicarle dopo
2169
- let arrayPage;
2170
- let arrayIpp;
2171
- if (this.arrayMode) {
2172
- arrayPage = this.arraymodePage;
2173
- arrayIpp = this.ArraymodeItemsPerPage;
2174
- }
2175
- this.writeValue(this.View);
2176
- this.cdr.detectChanges();
2177
- if (this.arrayMode) {
2178
- this.ArraymodeItemsPerPage = arrayIpp;
2179
- this.arrayGoToPage(arrayPage);
2180
- }
2181
- }
2182
- }
2183
- EsTableComponent.decorators = [
2184
- { type: Component, args: [{
2185
- selector: 'es-table',
2186
- viewProviders: [{ provide: LocalizationService, useClass: EsTableLoc }],
2187
- changeDetection: ChangeDetectionStrategy.OnPush,
2188
- encapsulation: ViewEncapsulation.None,
2189
- template: "<!-- Patacchino di autoaggiornamento -->\r\n<div class=\"w-100\" *ngIf=\"AutoUpdate\">\r\n <div class=\"pull-right\">\r\n {{'Update every' | localize : lc}}&nbsp;<input [readonly]=\"autoUpdate\" maxlength=\"3\" class=\"form-control est-custom-input\" type=\"text\" [(ngModel)]=\"seconds\" />&nbsp;{{'second/s' | localize : lc}}\r\n </div>\r\n <div class=\"pull-right m-t-2\">\r\n <label class=\"est-switch\">\r\n <input type=\"checkbox\" [(ngModel)]=\"autoUpdate\" (ngModelChange)=\"autoUpdateChanged();\" />\r\n <div class=\"est-slider round\"></div>\r\n </label>\r\n </div>\r\n</div>\r\n\r\n<!--\r\nI TH sono contenuto statico, questo significa che senza condizione per RowTHs arriverebbero sia qui sia nell ng-container dell'header in fase non inizializzata, duplicando fisicamente le colonne.\r\nPer ovviare al problema, questo pezzo lo faccio apparire solo se ci sono gi\u00E0 dei RowTHs, quindi su valorizzazione della View succeder\u00E0:\r\n1) appaiono i th nell' ng-container dell'header, e NON qui\r\n2) i TH vengono presi, elaborati e trasformati in RowTHs\r\n3) l'ng-container dell'header sparisce (per la condizione !UseCustomCells || !RowTHs) e qui appaiono i nuovi TH (che poi sono gli stessi di prima che girano)\r\n4) Vengono presi i nuovi TH da qui e trasformati a loro volta in RowTHs\r\n-->\r\n<div hidden *ngIf=\"UseCustomCells && RowTHs\">\r\n <ng-container *ngIf=\"View\">\r\n <!--Qui invece ci sono tutti i TH-->\r\n <ng-container *ngTemplateOutlet=\"headerRef\"></ng-container>\r\n </ng-container>\r\n</div>\r\n\r\n<!--\r\nQuesta parte \u00E8 un po' pi\u00F9 semplice del sopra. Infatti i TD vengono s\u00EC bindati in entrambi i punti (qui e nell'ng-container del body), ma avr\u00F2 le TD statiche prima di generare la TMPBoundSource.\r\nQuesto significa che il workflow di binding sar\u00E0:\r\n1) Appaiono i TD statici nel body e NON qui, perch\u00E9 i TMPBoundSource non sono ancora stati emessi\r\n2) Contemporaneamente all'emissione dei TMPBoundSource vengono anche emessi i RowTds\r\n3) Considerando il punto 2, al giro dopo appariranno i TD qui, perch\u00E9 \u00E8 stata generata la TMPBoundSource, e spariranno contemporaneamente dall'ng-container del body (per la condizione !UseCustomCells || !RowTDs)\r\n-->\r\n<div hidden *ngIf=\"UseCustomCells && bodyRef\">\r\n <ng-container *ngIf=\"View\">\r\n <!--Tutti i TD che dopo verranno presi ed elaborati internamente-->\r\n <ng-container *ngFor=\"let item of TMPBoundSource\">\r\n <ng-container *ngTemplateOutlet=\"bodyRef; context : {$implicit: item}\"></ng-container>\r\n </ng-container>\r\n </ng-container>\r\n</div>\r\n\r\n<ng-container *ngIf=\"View\">\r\n <div *ngIf=\"FirstBind && ShowLoadingOnBootstrap\" class=\"est-loading-box\">\r\n <div class=\"est-loading-content\">\r\n <span class=\"fa fa-spinner fa-spin\"></span>&nbsp;{{'Performing Table bootstrap' | localize: lc}}...\r\n </div>\r\n </div>\r\n\r\n <div class=\"table-responsive datatable {{Class}}\" [class.est-scrollable]=\"UseEndlessscroll\" (scroll)=\"UseEndlessscroll && onScroll($event)\" [style.max-height.px]=\"MaxHeight\">\r\n <table class=\"{{ TableClass }}\" [class.est-high-density]=\"HighCellDensity\">\r\n <thead [hidden]=\"HeaderHidden || FirstBind\">\r\n\r\n <!-- Aggiungo il pezzo che gestisce la selezione di tutto se attivo da config -->\r\n <tr *ngIf=\"SelectAll\">\r\n <th [attr.colspan]=\"allColumns\" [class.est-hidden]=\"!canSelectAll && !(View?.selection || arraymodeSelection).all\">\r\n <span>{{ (selectedObjects || 0).toString() + ' ' + ((selectedObjects == 1 ? 'Object Selected' : 'Objects Selected') | localize : lc) }}</span>&nbsp;\r\n <span class=\"app-link app-inline\" (click)=\"selectAllOrResetSelection()\">{{ (View?.selection || arraymodeSelection).all ? ('Reset Selection' | localize : lc) : ('Select Everything' | localize : lc)}}</span>\r\n </th>\r\n </tr>\r\n\r\n <!-- Blocco header group -->\r\n <tr *ngIf=\"HasHeaderGroup\">\r\n <ng-container *ngTemplateOutlet=\"headerGroupRef\"></ng-container>\r\n <th *ngIf=\"Export\"></th>\r\n </tr>\r\n\r\n <!-- Blocco header group secondario -->\r\n <tr *ngIf=\"HasSecondaryHeaderGroup\">\r\n <ng-container *ngTemplateOutlet=\"secondaryHeaderGroupRef\"></ng-container>\r\n <th *ngIf=\"Export\"></th>\r\n </tr>\r\n\r\n <!-- Blocco effettivo degli header -->\r\n <tr>\r\n <!-- Aggiungo una checkbox se la selezione \u00E8 attiva -->\r\n <th class=\"est-col-min\" *ngIf=\"Selection\">\r\n <input *ngIf=\"!SingleSelection\" class=\"est-pointer\" type=\"checkbox\" [disabled]=\"SelectionDisabled\" [(ngModel)]=\"globalCheck\" [ngModelOptions]=\"{'standalone': true}\" (ngModelChange)=\"globalCheckChanged();\">\r\n </th>\r\n\r\n <!-- Header che valgono per view mode e array mode -->\r\n <ng-container *ngIf=\"(viewMode || arrayMode)\">\r\n\r\n <!-- In una tabella base prendo semplicemente i th scritti dall'utente nell'HTML -->\r\n <ng-container *ngIf=\"(!UseCustomCells || !RowTHs) && !DynamicRowColumnsDefinition\">\r\n <ng-container *ngTemplateOutlet=\"headerRef\"></ng-container>\r\n </ng-container>\r\n\r\n <!-- Se ho un modello dinamico dell'oggetto creo le colonne in base alle propriet\u00E0 -->\r\n <ng-container *ngIf=\"(!UseCustomCells || !RowTHs) && DynamicRowColumnsDefinition\">\r\n <ng-container *ngFor=\"let operation of DynamicOperations\">\r\n <th class=\"est-col-min est-no-side-padding\"></th>\r\n </ng-container>\r\n \r\n <ng-container *ngFor=\"let rowHeader of DynamicRowColumnsDefinition\">\r\n <ng-container *ngIf=\"rowHeader.visible\">\r\n <th *ngIf=\"OrderByColumn\" es-th=\"{{rowHeader.propertyName}}\" class=\"{{UserDefinedDynamicCols ? ((rowHeader.clss || '') + (rowHeader.headerWraps ? '' : ' est-nowrap')) : ' est-nowrap'}}\" [Order]=\"rowHeader.dataOrder\" [Resizable]=\"ColumnsResizable\" [Orderable]=\"rowHeader.orderable\" [OrderBy]=\"OrderByColumn\" [SearchInProgress]=\"!!researchInProgress\" (onOrderChange)=\"thOrderChanged(rowHeader.propertyName, $event)\">{{rowHeader.description}}</th>\r\n <th *ngIf=\"!OrderByColumn\" es-th=\"{{rowHeader.propertyName}}\" class=\"{{UserDefinedDynamicCols ? ((rowHeader.clss || '') + (rowHeader.headerWraps ? '' : ' est-nowrap')) : ' est-nowrap'}}\" [Order]=\"rowHeader.dataOrder\" [Resizable]=\"ColumnsResizable\" [Orderable]=\"rowHeader.orderable\" [OrderBy]=\"OrderByColumn\">{{rowHeader.description}}</th>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <!-- Se non ho un modello dinamico ma invece delle celle custom, genero gli header in base ai row th -->\r\n <ng-container *ngIf=\"UseCustomCells && RowTHs\">\r\n <ng-container *ngFor=\"let rowHeader of RowTHs\">\r\n <ng-container *ngIf=\"rowHeader && rowHeader.Visible\">\r\n <th es-th=\"{{rowHeader.ID}}\" [class.est-nowrap]=\"!rowHeader.Wrap\" class=\"{{rowHeader.Class || ''}}\" [Order]=\"rowHeader.Order\" [Resizable]=\"ColumnsResizable\" [Orderable]=\"rowHeader.Orderable\" [OrderBy]=\"OrderByColumn\" [SearchInProgress]=\"!!researchInProgress\" (onOrderChange)=\"OrderByColumn && thOrderChanged(rowHeader.ID, $event)\">\r\n <ng-container *ngIf=\"rowHeader.Template\">\r\n <ng-container *ngTemplateOutlet=\"rowHeader.Template;\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"!rowHeader.Template\">\r\n {{rowHeader.Content}}\r\n </ng-container>\r\n </th>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <!--Casistica in cui ho il setup proveniente da un report. Gli header sono definiti da come \u00E8 fatto il report-->\r\n <ng-container *ngIf=\"reportMode\">\r\n <th [style.color]=\"clm.color\" *ngFor=\"let clm of ReportValues.columns\" class=\"app-no-selection app-pointer est-nowrap\" (click)=\"setupNextOrderAndSearch(clm)\">\r\n {{clm.description}}<span class=\"fa\" [class.fa-chevron-down]=\"clm.order == 'DESC'\" [class.fa-chevron-up]=\"clm.order == 'ASC'\"></span>\r\n </th>\r\n </ng-container>\r\n\r\n <!--Per l'eliminazione mi serve un header aggiuntivo-->\r\n <th *ngIf=\"Removal\" [class.app-right-10]=\"Export || HiddenColumns\" class=\"est-col-min app-sticky-last-column\"><span class=\"fa fa-trash\"></span></th>\r\n\r\n <!--Per l'esportazione mi serve l'header extra da cui faccio uscire i 3 pallocchi-->\r\n <th *ngIf=\"Export || HiddenColumns || ColumnsOrdering || CornerMenuOptions\" class=\"app-table-dotted-menu app-sticky-last-column est-col-min text-sm-center\">\r\n \r\n <!-- Link nascosto che serve a scaricare il file -->\r\n <a *ngIf=\"headers\" hidden #exportDownloader csvLink [data]=\"data\" [headers]=\"headers\" [delimiter]=\"';'\" [filename]=\"ExportFileName\"></a>\r\n\r\n <!-- Blocco con i 3 pallocchi che tira fuori il context menu delle operazioni -->\r\n <div class=\"btn-group\" container=\"body\" placement=\"bottom right\" dropdown #dropdown=\"bs-dropdown\" [autoClose]=\"true\">\r\n <span dropdownToggle class=\"fa fa-ellipsis-v app-fs-18 app-pointer app-padding-3\"></span>\r\n\r\n <div *dropdownMenu class=\"dropdown-menu dropdown-menu-right app-bring-to-front-strong\">\r\n <div class=\"est-pointer\">\r\n <a class=\"dropdown-item\" *ngIf=\"(HiddenColumns || ColumnsOrdering)\" (click)=\"resetColumnVisSelection(); changeColumnVisibilityModal.show();\">\r\n <ng-container *ngIf=\"!HiddenColumns && ColumnsOrdering\">\r\n {{'Columns Order' | localize : lc}}\r\n </ng-container>\r\n <ng-container *ngIf=\"HiddenColumns && !ColumnsOrdering\">\r\n {{'Columns Visibility' | localize : lc}}\r\n </ng-container>\r\n <ng-container *ngIf=\"HiddenColumns && ColumnsOrdering\">\r\n {{'Columns Visibility and Order' | localize : lc}}\r\n </ng-container>\r\n </a>\r\n <a class=\"dropdown-item\" *ngIf=\"Export && CSVExport\" (click)=\"tryExport('CSV')\">{{'Export View' | localize : lc}} (CSV)</a>\r\n <a class=\"dropdown-item\" *ngIf=\"Export && XLSXExport\" (click)=\"tryExport('XLSX')\">{{'Export View' | localize : lc}} (XLSX)</a>\r\n <a class=\"dropdown-item\" *ngFor=\"let option of CornerMenuOptions\" (click)=\"cornerActionClicked(option.id)\">{{option.description}}</a>\r\n </div>\r\n </div>\r\n </div>\r\n </th>\r\n </tr>\r\n </thead>\r\n \r\n <!-- Valido per modalit\u00E0 View o Array. Se sono in report mode il body \u00E8 creato in altro modo -->\r\n <tbody [hidden]=\"BodyHidden || FirstBind\" *ngIf=\"(arrayMode || viewMode)\">\r\n <!--Con selection attiva richiamo il template che gestisce il context menu-->\r\n <ng-container *ngIf=\"Selection\">\r\n <ng-container *ngTemplateOutlet=\"TBodySelection; context: { $implicit: { selDisabled: arrayMode ? false : SelectionDisabled, sel: Selection }}\"></ng-container>\r\n </ng-container>\r\n\r\n <!--Senza selection richiamo il template che NON gestisce il context menu-->\r\n <ng-container *ngIf=\"!Selection\">\r\n <ng-container *ngTemplateOutlet=\"TBody\"></ng-container>\r\n </ng-container>\r\n </tbody>\r\n\r\n <!-- Per la modalit\u00E0 a report c'\u00E8 un body particolare semi-dinamico -->\r\n <tbody [hidden]=\"BodyHidden\" *ngIf=\"reportMode\">\r\n <tr *ngFor=\"let row of ReportValues.rows; let even = even;\">\r\n <td class=\"est-nowrap\" *ngFor=\"let val of row.values\">{{val}}</td>\r\n <td class=\"app-sticky-last-column{{even && !Hierarchy ? '-alt' : ''}}\"></td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <ng-container *ngIf=\"ShowPaging && !FirstBind\">\r\n\r\n <!-- Paginatore dove appare la count e le opzioni di paginazione -->\r\n <div class=\"pull-left m-t-min-3\">\r\n <ng-container *ngIf=\"viewMode\">\r\n <ng-container *ngTemplateOutlet=\"pagerSelector; context: { $implicit: { ShowCount: !HidePagingCount || (View && View.objectcount && View.objectcount != -1), ShowPaging: !HidePaging, View: View, UsesView: true }}\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"arrayMode && (!UseArrayModePaging || SearchView)\">\r\n <ng-container *ngTemplateOutlet=\"pagerSelector; context: { $implicit: { ShowCount: !HidePagingCount || (View && View.length) || (SearchView && SearchView.objectcount && SearchView.objectcount != -1), ShowPaging: !HidePaging && SearchView, View: SearchView, SecondaryView: View, UsesView: true }}\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"arrayMode && (UseArrayModePaging && !SearchView)\">\r\n <ng-container *ngTemplateOutlet=\"pagerSelector; context: { $implicit: { ShowCount: !HidePagingCount, ShowPaging: !HidePaging && View.length > 10, View: View, UsesView: false }}\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"reportMode\">\r\n <ng-container *ngTemplateOutlet=\"pagerSelector; context: { $implicit: { ShowCount: !HidePagingCount || (View && View.objectcount && View.objectcount != -1), ShowPaging: View.pagingavailable, MightBeNoPaging: true, View: View, Report: ReportValues, UsesView: true }}\"></ng-container>\r\n </ng-container>\r\n </div>\r\n \r\n <!-- Pulsanti avanti-indietro di paginazione -->\r\n <div class=\"pull-right btn-toolbar\" *ngIf=\"ShowPaging && !HidePagingButtons\">\r\n <ng-container *ngIf=\"(!reportMode || View?.pagingavailable) && (!arrayMode || SearchView)\">\r\n <ng-container *ngTemplateOutlet=\"pagingButtons; context: { $implicit: { ATP: addToPage.bind(this), GTP: goToPage.bind(this), Array: arrayPulsanti }}\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"arrayMode && UseArrayModePaging && !SearchView\">\r\n <ng-container *ngTemplateOutlet=\"pagingButtons; context: { $implicit: { ATP: arrayAddToPage.bind(this), GTP: arrayGoToPage.bind(this), Array: arrayPulsanti }}\"></ng-container>\r\n </ng-container>\r\n </div>\r\n <div class=\"clearfix\"></div>\r\n </ng-container>\r\n</ng-container>\r\n\r\n<!-- Template che contiene i pulsanti per cambiare pagina -->\r\n<ng-template #pagingButtons let-options>\r\n <a class=\"btn app-white-button app-no-margin\" (click)=\"options.ATP(-1)\"><span class=\"fa fa-chevron-left\"></span></a>\r\n <div *ngIf=\"options.Array\" class=\"app-inline\">\r\n <a *ngFor=\"let p of options.Array\" class=\"btn {{p.cssClass}} app-no-margin\" (click)=\"options.GTP(p.val)\">{{p.val}}</a>\r\n </div>\r\n <a class=\"btn app-white-button app-no-margin\" (click)=\"options.ATP(1)\"><span class=\"fa fa-chevron-right\"></span></a>\r\n</ng-template>\r\n\r\n<!-- Template che mostra le informazioni base di paginazione: conteggio oggetti, paginazione attuale e pulsanti per cambiarla -->\r\n<ng-template #pagerSelector let-options>\r\n <div *ngIf=\"options.ShowCount\">\r\n {{ CountLabel }}:&nbsp;\r\n <strong *ngIf=\"options.UsesView && !options.Report\">\r\n {{ options.View?.objectcount ? options.View.objectcount : options.SecondaryView && options.SecondaryView.length ? options.SecondaryView.length : \"0\" }}\r\n </strong>\r\n <strong *ngIf=\"!options.UsesView && !options.Report\">\r\n {{ options.View.length ? options.View.length : \"0\" }}\r\n </strong>\r\n <strong *ngIf=\"options.Report\">\r\n {{ options.Report.count && options.Report.count == -1 ? options.Report.rows.length : options.Report.count && options.Report.count > 0 ? options.Report.count : 0 }}\r\n </strong>\r\n </div>\r\n <div *ngIf=\"options.ShowPaging\">\r\n <app-paging *ngIf=\"!options.UsesView\" [Hidden]=\"!options.View || options.View.length == 0\" [WarnOnAll]=\"false\" [CurrentPageSize]=\"ArraymodeItemsPerPage\" (pagingSelected)=\"refreshPaging($event)\"></app-paging>\r\n <app-paging *ngIf=\"options.UsesView\" [AllSearch]=\"AllSearch\" [DefaultAll]=\"defaultAllPageOverride\" [View]=\"options.View\" (pagingSelected)=\"options.View.itemsperpageoverride = $event; changed(); onItemsPerPageChanged();\"></app-paging>\r\n </div>\r\n <div *ngIf=\"options.MightBeNoPaging && !options.ShowPaging\">\r\n <em>{{'Paging options are not available for this report' | localize: lc}}</em>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Questi due template rappresentano effettivamente il body della tabella. essendo il tr l'unica cosa che davvero cambia, il resto \u00E8 templatizzato -->\r\n<ng-template #TBodySelection let-templateOptions>\r\n <ng-container *ngFor=\"let item of boundSource; let even = even; let i=index;\">\r\n <tr *ngIf=\"item.visible || !Hierarchy\" \r\n [class]=\"item._rowClass ? item._rowClass : ''\" \r\n [class.est-line-through]=\"item.removed || item.deleted\" \r\n [class.est-pointer]=\"!item.locked\" \r\n [class.est-white-selected]=\"item._selected && !item.locked\"\r\n [class.est-rg]=\"item._group\"\r\n [contextMenu]=\"!item.locked ? (ContextMenu || emptyMenu) : emptyMenu\" [contextMenuSubject]=\"item\"\r\n (click)=\"(!item.locked && !item._group && !item._sep && handleClick($event, item)) || item._group && handleGroupClick(item)\">\r\n \r\n <td *ngIf=\"!item.locked && !item._group && !item._sep;\"><input type=\"checkbox\" [disabled]=\"templateOptions.selDisabled\" [class.est-pointer]=\"!item.locked\" [(ngModel)]=\"item._selected\" name=\"check{{i}}\"></td>\r\n <td *ngIf=\"item.locked || item._group || item._sep\"></td>\r\n\r\n <ng-container *ngIf=\"item._sep\">\r\n <td [attr.colspan]=\"allColumns\" class=\"est-rg-sep est-l-{{item._grouplevel}}\">\r\n <div class=\"est-rg-ipp\"> \r\n <span class=\"est-rg-ipp-sel\">10</span>&nbsp;|&nbsp;\r\n <span class=\"est-rg-ipp-sel\">15</span>&nbsp;|&nbsp;\r\n <span class=\"est-rg-ipp-sel\">30</span>&nbsp;|&nbsp;\r\n <span class=\"est-rg-ipp-sel\">45</span>&nbsp;|&nbsp;\r\n <span class=\"est-rg-ipp-sel\">100</span>&nbsp;|&nbsp;\r\n <span class=\"est-rg-ipp-sel-all\">{{'All' | localize: lc}}</span>\r\n </div>\r\n <div class=\"est-rg-page\">\r\n <span class=\"est-rg-page-prev\">&lt;</span>\r\n <span class=\"est-rg-page-sel\">1</span>\r\n <span class=\"est-rg-page-sel\">2</span>\r\n <span class=\"est-rg-page-sel\">3</span>\r\n <span class=\"est-rg-page-sel\">4</span>\r\n <span class=\"est-rg-page-sel\">5</span>\r\n <span class=\"est-rg-page-next\">&gt;</span>\r\n </div>\r\n </td>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"!item._sep\">\r\n <ng-container *ngTemplateOutlet=\"basicColumns; context: { $implicit: item }\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"dynamicColumns; context: { $implicit: item }\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"customCells; context: { $implicit: item }\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"bodyDeleteAndExport; context: { $implicit: { even: even, item: item }}\"></ng-container>\r\n </ng-container>\r\n </tr>\r\n </ng-container>\r\n</ng-template> \r\n\r\n<ng-template #TBody>\r\n <ng-container *ngFor=\"let item of boundSource; let even = even;\">\r\n <tr *ngIf=\"item.visible || !Hierarchy\" \r\n [class]=\"item._rowClass ? item._rowClass : ''\" \r\n [class.est-line-through]=\"item.removed || item.deleted\"\r\n [class.est-rg]=\"item._group\"\r\n (click)=\"item._group && handleGroupClick(item)\">\r\n\r\n <ng-container *ngTemplateOutlet=\"basicColumns; context: { $implicit: item }\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"dynamicColumns; context: { $implicit: item }\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"customCells; context: { $implicit: item }\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"bodyDeleteAndExport; context: { $implicit: { even: even, item: item }}\"></ng-container>\r\n\r\n </tr>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<!-- Questo template contiene la print condizionale su tabelle semplici, con header e body scritti a manazza -->\r\n<ng-template #basicColumns let-item>\r\n <ng-container *ngIf=\"(!UseCustomCells || !RowTDs) && !DynamicRowColumnsDefinition\">\r\n <ng-container *ngTemplateOutlet=\"bodyRef; context : {$implicit: item}\"></ng-container>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<!-- Questo template contiene la print condizionale su tabelle definite in maniera dinamica dal modello -->\r\n<ng-template #dynamicColumns let-item>\r\n <ng-container *ngIf=\"(!UseCustomCells || !RowTDs) && DynamicRowColumnsDefinition\">\r\n <ng-container *ngFor=\"let operation of DynamicOperations; let first = first; let last = last;\">\r\n <ng-container *ngIf=\"!operation.conditionField || (item.properties[operation.conditionField] == operation.conditionValue)\">\r\n <td [class.est-no-right-padding]=\"last\" [class.est-no-left-padding]=\"!first\" class=\"est-col-min\"><span title=\"{{operation.title}}\" class=\"{{operation.iconClass}} app-pointer\" (click)=\"dynamicOperation(item, operation.id)\">{{operation.text}}</span></td>\r\n </ng-container>\r\n <ng-container *ngIf=\"operation.conditionField && (item.properties[operation.conditionField] != operation.conditionValue)\">\r\n <td class=\"est-col-min est-no-side-padding\"></td>\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngFor=\"let rowItem of DynamicRowColumnsDefinition\">\r\n <ng-container *ngIf=\"rowItem.routePath && rowItem.visible\">\r\n <td es-td=\"{{rowItem.propertyName}}\" class=\"{{UserDefinedDynamicCols ? rowItem.clss : 'est-nowrap'}}\" [Internal]=\"false\" [Context]=\"item.hash\">\r\n <a [routerLink]=\"generateRouterLink(rowItem.routePath, rowItem.routeParameterProperties, item)\" class=\"app-link\" [innerHTML]=\"item.properties[rowItem.propertyName]\"></a>\r\n </td>\r\n </ng-container>\r\n <ng-container *ngIf=\"!rowItem.routePath && rowItem.visible\">\r\n <ng-container *ngTemplateOutlet=\"findEsTd(rowItem.propertyName) || defaultEsTd; context: { $implicit: item.properties[rowItem.propertyName], rowItem : rowItem, item : item }\"> </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<ng-template #defaultEsTd let-value let-rowItem='rowItem' let-item='item'>\r\n <td es-td=\"{{rowItem.propertyName}}\" class=\"{{UserDefinedDynamicCols ? rowItem.clss : 'est-nowrap'}}\"\r\n [class.app-pointer]=\"UseCustomCellActions && CustomCellActionsOn.indexOf('$' + rowItem.propertyName + '$') != -1\"\r\n (click)=\"cellClicked(rowItem.propertyName, item) && !CellActionPropagates && $event.stopPropagation()\"\r\n [Internal]=\"false\" [Context]=\"item.hash\">\r\n {{value}}\r\n </td>\r\n</ng-template>\r\n\r\n<!-- Questo template contiene la print condizionale delle celle custom se configurate -->\r\n<ng-template #customCells let-item>\r\n <ng-container *ngIf=\"UseCustomCells && RowTDs\">\r\n <ng-container *ngFor=\"let rowItem of RowTDs[item.hash]; let i = index\">\r\n <ng-container *ngIf=\"rowItem\">\r\n\r\n <!-- Casistica senza bodyRef, quindi con direttive per i td -->\r\n <ng-container *ngIf=\"!bodyRef && rowItem.Visible\">\r\n <td es-td=\"{{rowItem.ID}}\" class=\"{{rowItem.Class}}\" \r\n [class.est-rg-hdr]=\"rowItem.GroupHeader\"\r\n [class.est-rg-agg]=\"rowItem.GroupAggregation\" \r\n [class.est-nowrap]=\"Hierarchy || !rowItem.Wraps\"\r\n [Internal]=\"true\">\r\n\r\n <ng-container *ngIf=\"Hierarchy && i == 0\">\r\n <ng-container *ngTemplateOutlet=\"HierarchyNavigator; context: { $implicit: item }\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"rowItem.Template\">\r\n <ng-container *ngTemplateOutlet=\"rowItem.Template; context: { $implicit: item }\"></ng-container>\r\n </ng-container>\r\n <span *ngIf=\"!rowItem.Template\">{{rowItem.Content}}</span>\r\n\r\n </td>\r\n </ng-container>\r\n\r\n <!-- Casistica bodyRef, quindi con componenti per i td (RouterLink) DEPRECATO -->\r\n <ng-container *ngIf=\"rowItem.RouterLink && rowItem.Visible && bodyRef\">\r\n <td es-td=\"{{rowItem.ID}}\" class=\"{{rowItem.Class}}\" [class.est-nowrap]=\"Hierarchy || !rowItem.Wraps\" [Internal]=\"true\">\r\n <ng-container *ngIf=\"Hierarchy && i == 0\">\r\n <ng-container *ngTemplateOutlet=\"HierarchyNavigator; context: { $implicit: item }\"></ng-container>\r\n </ng-container>\r\n <a [routerLink]='rowItem.RouterLink' class=\"app-link\" [innerHTML]=\"rowItem.Content\"></a>\r\n </td>\r\n </ng-container>\r\n\r\n <!-- Casistica bodyRef, quindi con componenti per i td (NON RouterLink) DEPRECATO -->\r\n <ng-container *ngIf=\"!rowItem.RouterLink && rowItem.Visible && bodyRef\">\r\n <td es-td=\"{{rowItem.ID}}\" class=\"{{rowItem.Class}}\" [class.est-nowrap]=\"Hierarchy || !rowItem.Wraps\" [class.app-pointer]=\"UseCustomCellActions && CustomCellActionsOn.indexOf('$' + $any(rowItem).ID + '$') != -1\" (click)=\"cellClicked(rowItem.ID, item) && !CellActionPropagates && $event.stopPropagation()\" [Internal]=\"true\">\r\n <ng-container *ngIf=\"Hierarchy && i == 0\">\r\n <ng-container *ngTemplateOutlet=\"HierarchyNavigator; context: { $implicit: item }\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"rowItem.Template\">\r\n <ng-container *ngTemplateOutlet=\"rowItem.Template; context: { $implicit: item }\"></ng-container>\r\n </ng-container>\r\n <span *ngIf=\"!rowItem.Template\" [innerHTML]=\"rowItem.Content\"></span>\r\n </td>\r\n </ng-container>\r\n\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<ng-template #HierarchyNavigator let-item>\r\n <span *ngIf=\"!item.parent\" class=\"fa fa-chevron-down\" style=\"visibility:hidden\"></span>\r\n <span *ngIf=\"item.parent && item.expanded\" class=\"fa fa-chevron-down est-pointer app-no-selection\" (click)=\"collapseParent(item[this.OwnKey])\"></span>\r\n <span *ngIf=\"item.parent && !item.expanded\" class=\"fa fa-chevron-up est-pointer app-no-selection\" (click)=\"expandParent(item[this.OwnKey])\"></span>\r\n &nbsp;\r\n</ng-template>\r\n\r\n<!-- Questo template contiene i pulsanti di eliminazione/undo eliminazione ed esportazione che vanno in fondo ad un record edlla tabella -->\r\n<ng-template #bodyDeleteAndExport let-options>\r\n <ng-container *ngIf=\"Removal && !RemovalCondition\">\r\n <td class=\"app-sticky-last-column{{options.even? '-alt' : ''}} {{Export || HiddenColumns || CornerMenuOptions ? 'est-right-10' : ''}}\" *ngIf=\"!(options.item.removed || options.item.deleted)\"><span class=\"fa fa-remove app-pointer text-danger\" [hidden]=\"options.item.removable != undefined && !options.item.removable\" (click)=\"onRemoval.emit(options.item)\"></span></td>\r\n <td class=\"app-sticky-last-column{{options.even? '-alt' : ''}} {{Export || HiddenColumns || CornerMenuOptions ? 'est-right-10' : ''}}\" *ngIf=\"(options.item.removed || options.item.deleted)\"><span class=\"fa fa-undo text-warning app-pointer\" (click)=\"onAbortRemoval.emit(options.item)\"></span></td>\r\n </ng-container>\r\n <ng-container *ngIf=\"Removal && RemovalCondition\">\r\n <td class=\"app-sticky-last-column{{options.even? '-alt' : ''}} {{Export || HiddenColumns || CornerMenuOptions ? 'est-right-10' : ''}}\" *ngIf=\"!(options.item.removed || options.item.deleted) && options.item[RemovalCondition]\"><span class=\"fa fa-remove app-pointer text-danger\" [hidden]=\"options.item.removable != undefined && !options.item.removable\" (click)=\"onRemoval.emit(options.item)\"></span></td>\r\n <td class=\"app-sticky-last-column{{options.even? '-alt' : ''}} {{Export || HiddenColumns || CornerMenuOptions ? 'est-right-10' : ''}}\" *ngIf=\"(options.item.removed || options.item.deleted) && options.item[RemovalCondition]\"><span class=\"fa fa-undo text-warning app-pointer\" (click)=\"onAbortRemoval.emit(options.item)\"></span></td>\r\n <td class=\"app-sticky-last-column{{options.even? '-alt' : ''}} {{Export || HiddenColumns || CornerMenuOptions ? 'est-right-10' : ''}}\" *ngIf=\"!options.item[RemovalCondition]\"><span class=\"fa fa-remove app-hidden-view\"></span></td>\r\n </ng-container>\r\n <td *ngIf=\"Export || HiddenColumns || CornerMenuOptions\" class=\"app-sticky-last-column{{options.even && !Hierarchy ? '-alt' : ''}}\"></td>\r\n</ng-template>\r\n\r\n<!-- Context menu vuoto default per tutte le tabella che non ce l'hanno, in modo che al click destro appaia \"nessuna op disponibile\" -->\r\n<context-menu #emptyMenu>\r\n <ng-template contextMenuItem>\r\n <span>\r\n <em>{{'No operations available' | localize : lc}}...</em>\r\n </span>\r\n </ng-template>\r\n</context-menu>\r\n\r\n<!-- Modal per cambiare posizione e visibilit\u00E0 delle colonne dell'es-table -->\r\n<div bsModal #changeColumnVisibilityModal=\"bs-modal\" class=\"modal fade\" role=\"dialog\" aria-hidden=\"true\">\r\n <div class=\"modal-dialog modal-lg\">\r\n <div class=\"modal-content\">\r\n <div class=\"modal-header\">\r\n <h5 class=\"modal-title pull-left\">\r\n <ng-container *ngIf=\"!HiddenColumns && ColumnsOrdering\">\r\n {{'Columns Order' | localize : lc}}\r\n </ng-container>\r\n <ng-container *ngIf=\"HiddenColumns && !ColumnsOrdering\">\r\n {{'Columns Visibility' | localize : lc}}\r\n </ng-container>\r\n <ng-container *ngIf=\"HiddenColumns && ColumnsOrdering\">\r\n {{'Columns Visibility and Order' | localize : lc}}\r\n </ng-container>\r\n </h5>\r\n <button type=\"button\" class=\"close pull-right\" (click)=\"changeColumnVisibilityModal.hide();\" aria-label=\"Close\">\r\n <span aria-hidden=\"true\">&times;</span>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n <div *ngIf=\"!TMPColumnsList || TMPColumnsList.length == 0\" class=\"card card-info app-padding-10 app-margin-bottom-0\">\r\n {{'There are no columns configured to be hidden/shown in this view' | localize : lc}}\r\n </div>\r\n <div *ngIf=\"TMPColumnsList && TMPColumnsList.length > 0\" style=\"max-height:500px; overflow-y:auto\">\r\n <!--Aaaaaaah la tristezza... qui mi servirebbe l'es-table per facilitare la selezione multipla ecc... peccato che se la linko qui entro in un loop impressionante-->\r\n <table class=\"table table-striped table-sm app-margin-bottom-0\">\r\n <thead>\r\n <tr>\r\n <th class=\"est-col-min\" *ngIf=\"HiddenColumns\">\r\n <input class=\"est-pointer\" type=\"checkbox\" [(ngModel)]=\"globalColVisCheck\" [ngModelOptions]=\"{'standalone': true}\" (ngModelChange)=\"globalColVisCheckChanged();\">\r\n </th>\r\n <th class=\"est-col-min\" *ngIf=\"ColumnsOrdering\"></th>\r\n <th class=\"est-col-min est-nowrap\">{{'Column Name' | localize : lc}}</th>\r\n <!--Filler-->\r\n <th></th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let item of TMPColumnsList; let i = index; let last = last\" class=\"est-pointer\" [class.est-white-selected]=\"lastSelectedItemID == item.id\" [class.est-no-selection]=\"!item.visible\" (click)=\"columnClicked(item);\">\r\n <td *ngIf=\"HiddenColumns\">\r\n <input type=\"checkbox\" [class.est-hidden-view]=\"item.fixed\" class=\"est-pointer\" [(ngModel)]=\"item.visible\" name=\"visible{{i}}\" (ngModelChange)=\"updateGlobalColVisCheck();\" />\r\n </td>\r\n <td class=\"est-nowrap\" *ngIf=\"ColumnsOrdering\">\r\n <span class=\"fa fa-arrow-up\" [class.est-hidden-view]=\"item.fixed\" (click)=\"lastSelectedItemID = item.id; i != 0 && !item.fixed && sendUp(item); $event.stopPropagation();\"></span>\r\n <span class=\"fa fa-arrow-down\" [class.est-hidden-view]=\"item.fixed\" (click)=\"lastSelectedItemID = item.id; !last && !item.fixed && sendDown(item); $event.stopPropagation();\"></span>\r\n </td>\r\n <td class=\"est-nowrap\">\r\n <ng-container *ngIf=\"item.template\">\r\n <ng-container *ngTemplateOutlet=\"item.template\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"!item.template\">{{item.description}}</ng-container>\r\n </td>\r\n <!--Filler-->\r\n <td></td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n <div class=\"modal-footer\">\r\n <button type=\"button\" class=\"btn btn-secondary app-margin-right-10\" (click)=\"lastSelectedItemID = null; changeColumnVisibilityModal.hide();\">{{'Close' | localize : lc}}</button>\r\n <button type=\"button\" [disabled]=\"!TMPColumnsList || TMPColumnsList.length == 0\" class=\"btn btn-primary\" (click)=\"confirmColumnVisibilitySelection() && changeColumnVisibilityModal.hide()\">{{'Confirm' | localize : lc}}</button>\r\n </div>\r\n </div>\r\n </div>\r\n</div>",
2190
- styles: [".est-loading-box{height:200px;text-align:center;position:relative;background:#ccc}.est-loading-content{margin:0;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:35px}.est-scrollable{max-height:600px;overflow:auto}.est-pointer{cursor:pointer}.est-high-density td,.est-high-density th{padding:0 .2rem}.est-no-selection{-webkit-user-select:none;-moz-user-select:none;-khtml-user-select:none;-ms-user-select:none}.est-hidden-view{visibility:hidden}.est-nowrap{white-space:nowrap}.est-white-selected{background-color:#ddd!important}.est-line-through{text-decoration:line-through}.est-no-side-padding{padding-left:0;padding-right:0}.est-no-left-padding,.est-no-right-padding{padding-left:0}.est-col-min{width:1px}.est-switch{position:relative;display:inline-block;width:30px;height:17px;margin-bottom:0;margin-right:5px;margin-left:5px}.est-switch input{display:none}.est-slider{cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc}.est-slider,.est-slider:before{position:absolute;transition:.4s}.est-slider:before{content:\"\";height:13px;width:13px;left:3px;bottom:2px;background-color:#fff}input:checked+.est-slider{background-color:#2196f3}input:focus+.est-slider{box-shadow:0 0 1px #2196f3}input:checked+.est-slider:before{transform:translateX(11px)}.est-slider.round{border-radius:10px}.est-slider.round:before{border-radius:50%}.est-custom-input{width:30px;display:inline;padding:1px;height:20px}.est-row-lvl-1 td:first-child{padding-left:5px}.est-row-lvl-2 td:first-child{padding-left:20px}.est-row-lvl-3 td:first-child{padding-left:35px}.est-row-lvl-4 td:first-child{padding-left:50px}.est-row-lvl-5 td:first-child{padding-left:65px}.est-row-lvl-6 td:first-child{padding-left:80px}.est-row-lvl-7 td:first-child{padding-left:95px}.est-row-lvl-8 td:first-child{padding-left:110px}.est-row-lvl-9 td:first-child{padding-left:125px}.est-row-lvl-10 td:first-child{padding-left:140px}.est-row-lvl-11 td:first-child{padding-left:155px}.est-row-lvl-12 td:first-child{padding-left:170px}.est-row-lvl-13 td:first-child{padding-left:185px}.est-row-lvl-14 td:first-child{padding-left:200px}.est-row-lvl-15 td:first-child{padding-left:215px}.est-row-lvl-16 td:first-child{padding-left:230px}.est-row-lvl-17 td:first-child{padding-left:245px}.est-row-lvl-18 td:first-child{padding-left:260px}.est-row-lvl-19 td:first-child{padding-left:275px}.est-row-lvl-20 td:first-child{padding-left:290px}.est-row-lvl-21 td:first-child{padding-left:305px}.est-row-lvl-22 td:first-child{padding-left:320px}.est-row-lvl-23 td:first-child{padding-left:335px}.est-row-lvl-24 td:first-child{padding-left:350px}.est-row-lvl-25 td:first-child{padding-left:365px}.est-row-lvl-26 td:first-child{padding-left:380px}.est-row-lvl-27 td:first-child{padding-left:395px}.est-row-lvl-28 td:first-child{padding-left:410px}.est-row-lvl-29 td:first-child{padding-left:425px}.est-row-lvl-30 td:first-child{padding-left:440px}.est-row-lvl-31 td:first-child{padding-left:455px}.est-row-lvl-32 td:first-child{padding-left:470px}.est-row-lvl-33 td:first-child{padding-left:485px}.est-row-lvl-34 td:first-child{padding-left:500px}.est-row-lvl-35 td:first-child{padding-left:515px}.est-row-lvl-36 td:first-child{padding-left:530px}.est-row-lvl-37 td:first-child{padding-left:545px}.est-row-lvl-38 td:first-child{padding-left:560px}.est-row-lvl-39 td:first-child{padding-left:575px}.est-row-lvl-40 td:first-child{padding-left:590px}.est-row-lvl-41 td:first-child{padding-left:605px}.est-row-lvl-42 td:first-child{padding-left:620px}.est-row-lvl-43 td:first-child{padding-left:635px}.est-row-lvl-44 td:first-child{padding-left:650px}.est-row-lvl-45 td:first-child{padding-left:665px}.est-row-lvl-46 td:first-child{padding-left:680px}.est-row-lvl-47 td:first-child{padding-left:695px}.est-row-lvl-48 td:first-child{padding-left:710px}.est-row-lvl-49 td:first-child{padding-left:725px}.est-row-lvl-50 td:first-child{padding-left:740px}.est-row-lvl-51 td:first-child{padding-left:755px}.est-row-lvl-52 td:first-child{padding-left:770px}.est-row-lvl-53 td:first-child{padding-left:785px}.est-row-lvl-54 td:first-child{padding-left:800px}.est-row-lvl-55 td:first-child{padding-left:815px}.est-row-lvl-56 td:first-child{padding-left:830px}.est-row-lvl-57 td:first-child{padding-left:845px}.est-row-lvl-58 td:first-child{padding-left:860px}.est-row-lvl-59 td:first-child{padding-left:875px}.est-row-lvl-60 td:first-child{padding-left:890px}.est-row-lvl-61 td:first-child{padding-left:905px}.est-row-lvl-62 td:first-child{padding-left:920px}.est-row-lvl-63 td:first-child{padding-left:935px}.est-row-lvl-64 td:first-child{padding-left:950px}.est-row-lvl-65 td:first-child{padding-left:965px}.est-row-lvl-66 td:first-child{padding-left:980px}.est-row-lvl-67 td:first-child{padding-left:995px}.est-row-lvl-68 td:first-child{padding-left:1010px}.est-row-lvl-69 td:first-child{padding-left:1025px}.est-row-lvl-70 td:first-child{padding-left:1040px}.est-row-lvl-71 td:first-child{padding-left:1055px}.est-row-lvl-72 td:first-child{padding-left:1070px}.est-row-lvl-73 td:first-child{padding-left:1085px}.est-row-lvl-74 td:first-child{padding-left:1100px}.est-row-lvl-75 td:first-child{padding-left:1115px}.est-row-lvl-76 td:first-child{padding-left:1130px}.est-row-lvl-77 td:first-child{padding-left:1145px}.est-row-lvl-78 td:first-child{padding-left:1160px}.est-row-lvl-79 td:first-child{padding-left:1175px}.est-row-lvl-80 td:first-child{padding-left:1190px}.est-row-lvl-81 td:first-child{padding-left:1205px}.est-row-lvl-82 td:first-child{padding-left:1220px}.est-row-lvl-83 td:first-child{padding-left:1235px}.est-row-lvl-84 td:first-child{padding-left:1250px}.est-row-lvl-85 td:first-child{padding-left:1265px}.est-row-lvl-86 td:first-child{padding-left:1280px}.est-row-lvl-87 td:first-child{padding-left:1295px}.est-row-lvl-88 td:first-child{padding-left:1310px}.est-row-lvl-89 td:first-child{padding-left:1325px}.est-row-lvl-90 td:first-child{padding-left:1340px}.est-row-lvl-91 td:first-child{padding-left:1355px}.est-row-lvl-92 td:first-child{padding-left:1370px}.est-row-lvl-93 td:first-child{padding-left:1385px}.est-row-lvl-94 td:first-child{padding-left:1400px}.est-row-lvl-95 td:first-child{padding-left:1415px}.est-row-lvl-96 td:first-child{padding-left:1430px}.est-row-lvl-97 td:first-child{padding-left:1445px}.est-row-lvl-98 td:first-child{padding-left:1460px}.est-row-lvl-99 td:first-child{padding-left:1475px}.est-right-10{right:10px}.est-hidden{visibility:hidden}.est-rg-hdr{font-weight:700}.est-rg-agg{font-style:italic}.est-rg{background-color:hsla(0,0%,46.7%,.4666666666666667)!important}.est-rg-ipp{text-align:left}.est-rg-ipp,.est-rg-page{width:50%;display:inline-block}.est-rg-page{text-align:right}.est-l-1{padding-right:20px!important}.est-l-2{padding-left:20px!important;padding-right:40px!important}.est-l-3{padding-left:40px!important;padding-right:60px!important}.est-l-4{padding-left:60px!important;padding-right:80px!important}.est-l-5{padding-left:800px!important;padding-right:100px!important}.est-rg-sep{font-size:12px}.est-rg-ipp-sel{color:#8b4513;margin-left:3px}.est-rg-page-sel{color:#2e8b57;margin-left:3px;margin-right:3px}.est-rg-ipp-sel-all{color:#708090;margin-left:3px;margin-right:3px}.est-rg-page-next,.est-rg-page-prev{color:#000;font-weight:700}"]
2191
- },] }
2192
- ];
2193
- EsTableComponent.ctorParameters = () => [
2194
- { type: NgControl, decorators: [{ type: Self }, { type: Optional }] },
2195
- { type: PreferencesService, decorators: [{ type: Optional }] },
2196
- { type: LocalizationService },
2197
- { type: ChangeDetectorRef },
2198
- { type: HashingService },
2199
- { type: UtilityService },
2200
- { type: ExportService },
2201
- { type: DateService },
2202
- { type: MessageService }
2203
- ];
2204
- EsTableComponent.propDecorators = {
2205
- EsTdsDirective: [{ type: ContentChildren, args: [EsTdDirective,] }],
2206
- EsThsDirective: [{ type: ContentChildren, args: [EsThDirective,] }],
2207
- EsThs: [{ type: ContentChildren, args: [forwardRef(() => EsTh),] }],
2208
- EsTds: [{ type: ContentChildren, args: [forwardRef(() => EsTd),] }],
2209
- bodyRef: [{ type: ContentChild, args: ['body', { static: false },] }],
2210
- headerRef: [{ type: ContentChild, args: ['header', { static: false },] }],
2211
- headerGroupRef: [{ type: ContentChild, args: ['headerGroup', { static: false },] }],
2212
- secondaryHeaderGroupRef: [{ type: ContentChild, args: ['secondaryHeaderGroup', { static: false },] }],
2213
- CornerMenuOptions: [{ type: Input }],
2214
- ColumnsResizable: [{ type: Input }],
2215
- AutoUpdate: [{ type: Input }],
2216
- UseCustomCellActions: [{ type: Input }],
2217
- CustomCellActionsOn: [{ type: Input }],
2218
- CellActionPropagates: [{ type: Input }],
2219
- UseCustomCells: [{ type: Input }],
2220
- MaxHeight: [{ type: Input }],
2221
- Class: [{ type: Input }],
2222
- XLSXExport: [{ type: Input }],
2223
- CSVExport: [{ type: Input }],
2224
- AllSearch: [{ type: Input }],
2225
- HighCellDensity: [{ type: Input }],
2226
- Selection: [{ type: Input }],
2227
- ShowLoadingOnBootstrap: [{ type: Input }],
2228
- Removal: [{ type: Input }],
2229
- RemovalCondition: [{ type: Input }],
2230
- Export: [{ type: Input }],
2231
- ShiftClick: [{ type: Input }],
2232
- ShowPaging: [{ type: Input }],
2233
- HidePaging: [{ type: Input }],
2234
- HidePagingCount: [{ type: Input }],
2235
- HidePagingButtons: [{ type: Input }],
2236
- ContextMenu: [{ type: Input }],
2237
- ExportFileName: [{ type: Input }],
2238
- TableClass: [{ type: Input }],
2239
- CountLabel: [{ type: Input }],
2240
- ExportFunction: [{ type: Input }],
2241
- HasHeaderGroup: [{ type: Input }],
2242
- HasSecondaryHeaderGroup: [{ type: Input }],
2243
- SliceSize: [{ type: Input }],
2244
- EndlessScroll: [{ type: Input }],
2245
- EndlessScrollOnlyForAll: [{ type: Input }],
2246
- HeaderHidden: [{ type: Input }],
2247
- BodyHidden: [{ type: Input }],
2248
- SelectionDisabled: [{ type: Input }],
2249
- SingleSelection: [{ type: Input }],
2250
- RowClassAssigner: [{ type: Input }],
2251
- OrderByColumn: [{ type: Input }],
2252
- MultipleOrderingDirectives: [{ type: Input }],
2253
- HiddenColumns: [{ type: Input }],
2254
- ColumnsOrdering: [{ type: Input }],
2255
- SearchView: [{ type: Input }],
2256
- SelectAll: [{ type: Input }],
2257
- UseArrayModePaging: [{ type: Input }],
2258
- DynamicRowColumnsDefinition: [{ type: Input }],
2259
- DynamicOperations: [{ type: Input }],
2260
- Hierarchy: [{ type: Input }],
2261
- ParentKey: [{ type: Input }],
2262
- OwnKey: [{ type: Input }],
2263
- StartsExpanded: [{ type: Input }],
2264
- SavePreferences: [{ type: Input }],
2265
- SecondarySource: [{ type: Input }],
2266
- TertiarySource: [{ type: Input }],
2267
- UseSelectionCache: [{ type: Input }],
2268
- onOrderChanged: [{ type: Output }],
2269
- onSearchRequest: [{ type: Output }],
2270
- onSelectionChanged: [{ type: Output }],
2271
- onRemoval: [{ type: Output }],
2272
- onAbortRemoval: [{ type: Output }],
2273
- onCellClick: [{ type: Output }],
2274
- onCornerAction: [{ type: Output }],
2275
- onDynamicOperation: [{ type: Output }],
2276
- exportDownloader: [{ type: ViewChild, args: ['exportDownloader', { static: false },] }],
2277
- tableEmptyMenu: [{ type: ViewChild, args: ['emptyMenu', { static: true },] }],
2278
- ArraymodeItemsPerPage: [{ type: Input }]
2279
- };
2280
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXNfdGFibGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvZXMtdGFibGUvc3JjL2xpYi9lc190YWJsZS5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLFVBQVU7QUFDVixPQUFPLEVBQ0gsU0FBUyxFQUFFLFVBQVUsRUFBRSxlQUFlLEVBQWEsaUJBQWlCLEVBQUUsdUJBQXVCLEVBQUUsS0FBSyxFQUNwRyxZQUFZLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBNEIsU0FBUyxFQUFjLGlCQUFpQixFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQ3pILE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBd0IsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFakUsaUJBQWlCO0FBQ2pCLE9BQU8sRUFBRSxjQUFjLEVBQUUsY0FBYyxFQUFFLGFBQWEsRUFBRSxjQUFjLEVBQUUsV0FBVyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbEgsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDOUQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFLM0QsVUFBVTtBQUNWLE9BQU8sRUFDUyxTQUFTLEVBQUUsV0FBVyxFQUFlLHdCQUF3QixFQUN6RSxnQkFBZ0IsRUFBZ0IsV0FBVyxFQUE0QyxhQUFhLEVBQ3ZHLE1BQU0sVUFBVSxDQUFDO0FBRWxCLDhCQUE4QjtBQUM5QixPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDekMsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3pDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUM3RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDN0QsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDBCQUEwQixD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TCxLQUFLO3lCQUdMLEtBQUs7eUJBR0wsS0FBSzs4QkFHTCxLQUFLO2dDQUdMLEtBQUs7MEJBR0wsS0FBSzs2QkFHTCxLQUFLO3lCQUdMLEtBQUs7eUJBR0wsS0FBSzs2QkFPTCxLQUFLOzZCQUdMLEtBQUs7c0NBR0wsS0FBSzt3QkFHTCxLQUFLOzRCQUdMLEtBQUs7c0NBR0wsS0FBSzsyQkFHTCxLQUFLO3lCQUdMLEtBQUs7Z0NBTUwsS0FBSzs4QkFNTCxLQUFLOytCQUdMLEtBQUs7NEJBR0wsS0FBSzt5Q0FHTCxLQUFLOzRCQUdMLEtBQUs7OEJBR0wsS0FBSzt5QkFPTCxLQUFLO3dCQUdMLEtBQUs7aUNBR0wsS0FBSzswQ0FHTCxLQUFLO2dDQUdMLEtBQUs7d0JBR0wsS0FBSzt3QkFHTCxLQUFLO3FCQUdMLEtBQUs7NkJBR0wsS0FBSzs4QkFHTCxLQUFLOzhCQU9MLEtBQUs7NkJBT0wsS0FBSztnQ0FHTCxLQUFLOzZCQUdMLE1BQU07OEJBV04sTUFBTTtpQ0FHTixNQUFNO3dCQUdOLE1BQU07NkJBR04sTUFBTTswQkFNTixNQUFNOzZCQUdOLE1BQU07aUNBR04sTUFBTTsrQkFPTixTQUFTLFNBQUMsa0JBQWtCLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFOzZCQUcvQyxTQUFTLFNBQUMsV0FBVyxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtvQ0FVdkMsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEFuZ3VsYXJcclxuaW1wb3J0IHtcclxuICAgIENvbXBvbmVudCwgZm9yd2FyZFJlZiwgQ29udGVudENoaWxkcmVuLCBRdWVyeUxpc3QsIENoYW5nZURldGVjdG9yUmVmLCBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgSW5wdXQsXHJcbiAgICBFdmVudEVtaXR0ZXIsIE91dHB1dCwgQ29udGVudENoaWxkLCBPbkNoYW5nZXMsIFNpbXBsZUNoYW5nZXMsIFZpZXdDaGlsZCwgRWxlbWVudFJlZiwgVmlld0VuY2Fwc3VsYXRpb24sIE9wdGlvbmFsLCBTZWxmLCBUZW1wbGF0ZVJlZlxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBDb250cm9sVmFsdWVBY2Nlc3NvciwgTmdDb250cm9sIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5cclxuLy8gQ29uZmlndXJhemlvbmlcclxuaW1wb3J0IHsgSGFzaGluZ1NlcnZpY2UsIFV0aWxpdHlTZXJ2aWNlLCBFeHBvcnRTZXJ2aWNlLCBNZXNzYWdlU2VydmljZSwgRGF0ZVNlcnZpY2UgfSBmcm9tICdAZXNmYWVuemEvZXh0ZW5zaW9ucyc7XHJcbmltcG9ydCB7IExvY2FsaXphdGlvblNlcnZpY2UgfSBmcm9tICdAZXNmYWVuemEvbG9jYWxpemF0aW9ucyc7XHJcbmltcG9ydCB7IFByZWZlcmVuY2VzU2VydmljZSB9IGZyb20gJ0Blc2ZhZW56YS9wcmVmZXJlbmNlcyc7XHJcblxyXG4vLyBQbHVnaW5zXHJcbmltcG9ydCB7IENvbnRleHRNZW51Q29tcG9uZW50IH0gZnJvbSAnQGVzZmFlbnphL25neC1jb250ZXh0bWVudSc7XHJcblxyXG4vLyBNb2RlbGxpXHJcbmltcG9ydCB7XHJcbiAgICBJQXBwU2VhcmNoLCBBcHBTZWFyY2gsIEFwcE9yZGVyaW5nLCBHZW5lcmljSXRlbSwgRXNUYWJsZUNvbHVtbnNEZWZpbml0aW9uLCBDb3JuZXJNZW51T3B0aW9uLFxyXG4gICAgUmVwb3J0RGVmaW5pdGlvbiwgUmVwb3J0UmVzdWx0LCBSZXBvcnRPcmRlciwgUmVwb3J0Q29sdW1uLCBFc1RhYmxlT3BlcmF0aW9uRGVmaW5pdGlvbiwgRXNUYWJsZUNvbHVtblxyXG59IGZyb20gJy4vZG9tYWluJztcclxuXHJcbi8vIENvbXBvbmVudGkgZSBMb2NhbGl6emF6aW9uZVxyXG5pbXBvcnQgeyBFc1RkIH0gZnJvbSAnLi9lc190ZC5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBFc1RoIH0gZnJvbSAnLi9lc190aC5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBFc1RkRGlyZWN0aXZlIH0gZnJvbSAnLi9kaXJlY3RpdmVzL2VzX3RkLmRpcmVjdGl2ZSc7XHJcbmltcG9ydCB7IEVzVGhEaXJlY3RpdmUgfSBmcm9tICcuL2RpcmVjdGl2ZXMvZXNfdGguZGlyZWN0aXZlJztcclxuaW1wb3J0IHsgRXNUYWJsZUxvYyB9IGZyb20gJy4vZXNfdGFibGUuY29tcG9uZW50LmxvYyc7XHJcbmltcG9ydCB7IEl0ZW1zU2VsZWN0aW9uIH0gZnJvbSAnLi9kb21haW4vY2xhc3Nlcy9JdGVtc1NlbGVjdGlvbic7XHJcbmltcG9ydCB7IEdyb3VwLCBHcm91cEZpbHRlciwgR3JvdXBPckFnZ3JlZ2F0aW9uIH0gZnJvbSAnLi9kb21haW4vY2xhc3Nlcy9BcHBTZWFyY2gnO1xyXG5cclxuLyoqIENvbXBvbmVudGUgY2hlIHBlcm1ldHRlIGRpIHJhcHByZXNlbnRhcmUgdW5hIGdyaWdsaWEgZGkgdmFsb3JpICovXHJcbkBDb21wb25lbnQoe1xyXG4gICAgc2VsZWN0b3I6ICdlcy10YWJsZScsXHJcbiAgICB2aWV3UHJvdmlkZXJzOiBbeyBwcm92aWRlOiBMb2NhbGl6YXRpb25TZXJ2aWNlLCB1c2VDbGFzczogRXNUYWJsZUxvYyB9XSxcclxuICAgIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxyXG4gICAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcclxuICAgIHN0eWxlVXJsczogWycuL2VzX3RhYmxlLmNvbXBvbmVudC5zY3NzJ10sXHJcbiAgICB0ZW1wbGF0ZVVybDogJy4vZXNfdGFibGUuY29tcG9uZW50Lmh0bWwnXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBFc1RhYmxlQ29tcG9uZW50IGltcGxlbWVudHMgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE9uQ2hhbmdlcyB7XHJcblxyXG4gICAgLyoqIEBpZ25vcmUgKi9cclxuICAgIGNvbnN0cnVjdG9yKEBTZWxmKCkgQE9wdGlvbmFsKCkgcHVibGljIG5nQ29udHJvbDogTmdDb250cm9sLCBAT3B0aW9uYWwoKSBwcml2YXRlIHByZWZTZXJ2aWNlOiBQcmVmZXJlbmNlc1NlcnZpY2UsIHB1YmxpYyBsYzogTG9jYWxpemF0aW9uU2VydmljZSwgcHJpdmF0ZSBjZHI6IENoYW5nZURldGVjdG9yUmVmLCBwcml2YXRlIGhhc2hFeHRzOiBIYXNoaW5nU2VydmljZSwgcHJpdmF0ZSB1dGlFeHRzOiBVdGlsaXR5U2VydmljZSwgcHJpdmF0ZSBleHBFeHRzOiBFeHBvcnRTZXJ2aWNlLCBwcml2YXRlIGRhdGVFeHRzOiBEYXRlU2VydmljZSwgcHJpdmF0ZSBtc2dFeHRzOiBNZXNzYWdlU2VydmljZSkge1xyXG4gICAgICAgIGlmIChuZ0NvbnRyb2wpXHJcbiAgICAgICAgICAgIG5nQ29udHJvbC52YWx1ZUFjY2Vzc29yID0gdGhpcztcclxuICAgIH1cclxuXHJcbiAgICAvKiogVmlldyBmaW5hbGUgc3UgY3VpIGJpbmRhcnNpIGxhdG8gRnJvbnRlbmQsIGlsIHRpcG8gcHXDsiBlc3NlcmUgSUFwcFNlYXJjaDxhbnk+IChwZXIgbGEgKip2aWV3TW9kZSoqKSwgYW55W10gKHBlciBsJyoqYXJyYXlNb2RlKiopIGUgUmVwb3J0RGVmaW5pdGlvbiBwZXIgbGEgKipyZXBvcnRNb2RlKiogKi9cclxuICAgIHB1YmxpYyBWaWV3OiBhbnkgPSBudWxsO1xyXG5cclxuICAgIC8qKiBNb2RlbGxvIGRhIGN1aSBsJ2VzLXRhYmxlIG1vc3RyYSBpIHB1bHNhbnRpIGRpIHBhZ2luYXppb25lIGluIGJhc3NvIGEgZGVzdHJhICovXHJcbiAgICBwdWJsaWMgYXJyYXlQdWxzYW50aTogYW55O1xyXG5cclxuICAgIC8qKiBJbmRpY2Egc2UgbCdlcy10YWJsZSBkZXZlIG1vc3RyYXJlIGlsIGNoZWNrIGdsb2JhbGUgbmVsbCdoZWFkZXIgcGVyIGZhcmUgaWwgXCJzZWxlemlvbmEgdHV0dG9cIiAqL1xyXG4gICAgcHVibGljIGdsb2JhbENoZWNrID0gZmFsc2U7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaWVuZSBkYSBjb250byBsJ3VsdGltbyBlbGVtZW50byBzZWxlemlvbmF0byBpbiBtb2RvIGRhIGZhcmUgcmFnaW9uYW1lbnRpIGRlbCB0aXBvXHJcbiAgICAgKiBcIkhvIHNlbGV6aW9uYXRvIHF1ZXN0bywgbCd1bHRpbW8gc2VsZXppb25hdG8gZXJhICoqbGFzdFNlbGVjdGVkKiosIGRldm8gc2VsZXppb25hcmUgdHV0dGkgcXVlbGxpIGluIG1lenpvXCIsIGFkIGVzZW1waW8gcGVyIGxhIHNlbGV6aW9uZSBtdWx0aXBsYVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGxhc3RTZWxlY3RlZDogYW55ID0gbnVsbDtcclxuXHJcbiAgICAvKiogQ29udGVnZ2lvIGludGVybm8gcGVyIGlsIG51bWVybyBkaSBlbGVtZW50aSBzZWxlemlvbmF0aSAqL1xyXG4gICAgcHVibGljIHNlbGVjdGVkT2JqZWN0cyA9IDA7XHJcblxyXG4gICAgLyoqIEluZGljYSBzZSDDqCBwb3NzaWJpbGUgZWZmZXR0dWFyZSB1bmEgc2VsZXppb25lIG1hc3NpdmEgKi9cclxuICAgIHB1YmxpYyBjYW5TZWxlY3RBbGwgPSBmYWxzZTtcclxuXHJcbiAgICAvKiogSW5kaWNhIHNlIGlsIGNvbXBvbmVudGUgc3RhIGdlc3RlbmRvIHVuIElBcHBTZWFyY2g8YW55PiAqL1xyXG4gICAgcHVibGljIHZpZXdNb2RlID0gZmFsc2U7XHJcblxyXG4gICAgLyoqIEluZGljYSBzZSBpbCBjb21wb25lbnRlIHN0YSBnZXN0ZW5kbyB1biBhbnlbXSAqL1xyXG4gICAgcHVibGljIGFycmF5TW9kZSA9IGZhbHNlO1xyXG5cclxuICAgIC8qKiBJbmRpY2Egc2UgaWwgY29tcG9uZW50ZSBzdGEgZ2VzdGVuZG8gdW4gUmVwb3J0RGVmaW5pdGlvbiAqL1xyXG4gICAgcHVibGljIHJlcG9ydE1vZGUgPSBmYWxzZTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIENvbnRlbml0b3JlIGRlZ2xpIGVsZW1lbnRpIGRhIGxpc3RhcmUgbGF0byBpbnRlcmZhY2NpYSBkb3BvIHR1dHRlIGxlIGVsYWJvcmF6aW9uaSBkZWwgY2FzbyxcclxuICAgICAqIGdlbmVyYWxtZW50ZSBub24gc29ubyBhbHRybyBjaGUgdHV0dGkgZ2xpIG9nZ2V0dGkgZGEgcHJlc2VudGFyZSBjb24gaW4gcGnDuSBsJ2hhc2ggY2FsY29sYXRvIHBlciBpZGVudGlmaWNhcmUgMSBvZ2dldHRvIGNvbiBsYSBwcm9wcmlhIHJpZ2FcclxuICAgICAqL1xyXG4gICAgcHVibGljIGJvdW5kU291cmNlOiBhbnlbXSA9IFtdO1xyXG5cclxuICAgIC8qKiBTdGVzc2EgY29zYSBkZWxsYSAqKmJvdW5kU291cmNlKiosIHV0aWxpenphdGEgY29tZSBhcHBvZ2dpbyB0ZW1wb3JhbmVvIGludGVybm8gKi9cclxuICAgIHB1YmxpYyBUTVBCb3VuZFNvdXJjZTogYW55W10gPSBbXTtcclxuXHJcbiAgICAvKiogXCJGZXR0YVwiIGRpIG9nZ2V0dGkgdXRpbGl6emF0YSBuZWxsJ2VuZGxlc3Mgc2Nyb2xsLCBvZ25pIGVsZW1lbnRvIGRpIHF1ZXN0byBhcnJheSDDqCB1biBibG9jY2hldHRvIGRpIDEwMCBlbGVtZW50aSAqL1xyXG4gICAgcHVibGljIGJvdW5kU3ViU291cmNlczogYW55W10gPSBbXTtcclxuXHJcbiAgICAvKiogUXVlc3RhIGZ1bmdlIGRhIGluZGljYXRvcmUgcGVyIGdsaSBzbGljZSBpbnNlcml0aSwgbGEgbHVuZ2hlenphIGRvdnJlYmJlIGVzc2VyZSBjb3JyaXNwb25kZW50ZSBhICoqYm91bmRTdWJTb3VyY2VzKiogKi9cclxuICAgIHB1YmxpYyBhZGRlZFNsaWNlczogbnVtYmVyW10gPSBbXTtcclxuXHJcbiAgICAvKiogVmFyaWFiaWxlIGNoZSBpZGVudGlmaWNhIGlsIHZhbG9yZSBkZWwgXCJzZWxlemlvbmEgVHV0dG9cIiBuZWxsYSBwYWdpbmF6aW9uZSAqL1xyXG4gICAgcHVibGljIGRlZmF1bHRBbGxQYWdlT3ZlcnJpZGUgPSA5OTk5OTk7XHJcblxyXG4gICAgLyoqIEluZGljYSBzZSB1dGlsaXp6YXJlIGlsIHNpc3RlbWEgZGkgRW5kbGVzcyBTY3JvbGwgKi9cclxuICAgIHB1YmxpYyBVc2VFbmRsZXNzc2Nyb2xsOiBib29sZWFuO1xyXG5cclxuICAgIC8qKiBWYWxvcmkgZGVsbCdldmVudHVhbGUgcmVwb3J0IGluIHZpc3VhbGl6emF6aW9uZSAqL1xyXG4gICAgcHVibGljIFJlcG9ydFZhbHVlczogUmVwb3J0UmVzdWx0O1xyXG5cclxuICAgIC8qKiBTZXJ2ZSBwZXIgdGVuZXJlIGluIG1lbW9yaWEgaWwgY29udGVnZ2lvIHByZWNlZGVudGUgZSByZWN1cGVyYXJsbyBpbiBjYXNvIGRpdmVudGkgLTIgKHZlcmlmaWNhcmUgY29uIEFsZSBwZXJjaMOpIGxhIGxvZ2ljYSBkZWwgLTIpICovXHJcbiAgICBwdWJsaWMgcHJldmlvdXNDb3VudDogbnVtYmVyO1xyXG5cclxuICAgIC8qKiBJbmRpY2Egc2UgdXRpbGl6emFyZSBpbCBzaXN0ZW1hIGRpIGF1dG91cGRhdGUsIGNpb8OoIHVuIHRyaWdnZXIgdGltZS1penphdG8gaW4gYWx0byBhIGRlc3RyYSBkZWxsYSB0YWJlbGxhIGNoZSByaXBldGUgbGUgcmljZXJjaGUgb2duaSBYICoqc2Vjb25kcyoqICovXHJcbiAgICBwdWJsaWMgYXV0b1VwZGF0ZSA9IGZhbHNlO1xyXG5cclxuICAgIC8qKiBOdW1lcm8gZGkgc2Vjb25kaSBkYSBmYXJlIHRyYXNjb3JyZXJlIGZyYSB1bmEgcmljZXJjYSBlIGwnYWx0cmEgKi9cclxuICAgIHB1YmxpYyBzZWNvbmRzID0gJzEwJztcclxuXHJcbiAgICAvKiogUmlmZXJpbWVudG8gYWxsJ0ludGVydmFsIGNoZSB2aWVuZSBnZW5lcmF0byBzZSAqKmF1dG9VcGRhdGUqKiDDqCBpbXBvc3RhdGEgYSB0cnVlIGluIG1vZG8gZGEgcG90ZXJsbyByaXB1bGlyZSAqL1xyXG4gICAgcHVibGljIHVwZGF0ZVRpbWVyOiBhbnk7XHJcblxyXG4gICAgLyoqIEltcG9zdGF0YSBhIHRydWUgb2duaSB2b2x0YSBjaGUgdmllbmUgYXZ2aWF0YSB1bmEgcmljZXJjYSwgZSBhIGZhbHNlIG9nbmkgdm9sdGEgY2hlIHVuIG51b3ZvIHZhbG9yZSB2aWVuZSByaWNldnV0byAqL1xyXG4gICAgcHVibGljIHJlc2VhcmNoSW5Qcm9ncmVzczogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAgIC8qKiBNb2RlbGxvIHJhcHByZXNlbnRhbnRlIHVuIHNpbmdvbG8gdGQgZGVsbGEgdGFiZWxsYSwgZ2VuZXJhdG8gaW4gYmFzZSBhbGxlIGNvbmZpZ3VyYXppb25pIGUgYWdsaSBvZ2dldHRpIHJpY2V2dXRpICovXHJcbiAgICBwdWJsaWMgUm93VERzOiB7IFtjb250ZXh0OiBzdHJpbmddOiBFc1RkW10gfSA9IG51bGw7XHJcblxyXG4gICAgLyoqIE1vZGVsbG8gZGkgYXBwb2dnaW8gdGVtcG9yYW5lbyBwZXIgaSAqKlJvd1REcyoqICovXHJcbiAgICBwdWJsaWMgVE1QUm93VERzOiB7IFtjb250ZXh0OiBzdHJpbmddOiBFc1RkW10gfSA9IG51bGw7XHJcblxyXG4gICAgLyoqIE1vZGVsbG8gcmFwcHJlc2VudGFudGUgdW4gc2luZ29sbyB0aCBkZWxsYSB0YWJlbGxhLCBnZW5lcmF0byBpbiBiYXNlIGFsbGUgY29uZmlndXJhemlvbmkgZSBhZ2xpIG9nZ2V0dGkgcmljZXZ1dGkgKi9cclxuICAgIHB1YmxpYyBSb3dUSHM6IHsgSUQ6IHN0cmluZywgVmlzaWJsZTogYm9vbGVhbiwgQ2xhc3M6IHN0cmluZywgQ29udGVudDogc3RyaW5nLCBPcmRlcjogc3RyaW5nLCBPcmRlcmFibGU6IGJvb2xlYW4sIFRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+LCBXcmFwOiBib29sZWFuIH1bXSA9IG51bGw7XHJcblxyXG4gICAgLyoqIE1vZGVsbG8gZGkgYXBwb2dnaW8gdGVtcG9yYW5lbyBwZXIgaSAqKlJvd1RIcyoqICovXHJcbiAgICBwdWJsaWMgVE1QUm93VEhzOiB7IEZpeGVkOiBib29sZWFuLCBJRDogc3RyaW5nLCBWaXNpYmxlOiBib29sZWFuLCBDbGFzczogc3RyaW5nLCBDb250ZW50OiBzdHJpbmcsIE9yZGVyOiBzdHJpbmcsIE9yZGVyYWJsZTogYm9vbGVhbiwgVGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT4sIFdyYXA6IGJvb2xlYW4gfVtdID0gbnVsbDtcclxuXHJcbiAgICAvKiogQ2FjaGUgcGVyIGkgcm91dGVyTGluayBnZW5lcmF0aSBuZWxsZSB0YWJlbGxlIGRpbmFtaWNoZSAqL1xyXG4gICAgcHVibGljIER5bmFtaWNUYWJsZVJvdXRlckxpbmtDYWNoZToge30gPSB7fTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIExpc3RhIGRlaSBjb250ZXN0aS4gVW4gY29udGVzdG8gbm9uIMOoIGFsdHJvIGNoZSB1biBoYXNoIHBhcnRpY29sYXJlIGNhbGNvbGF0byBzdSB1biBvZ2dldHRvIGNoZSBpZGVudGlmaWNhIHVuaXZvY2FtZW50ZSB0YWxlIG9nZ2V0dG8uXHJcbiAgICAgKlxyXG4gICAgICogT2dudW5vIGRpIHF1ZXN0aSBjb250ZXN0aSByYXBwcmVzZW50ZXLDoCBhIHN1YSB2b2x0YSwgdW5pdm9jYW1lbnRlLCB1bmEgcmlnYSBhbGwnaW50ZXJubyBkZWxsYSB0YWJlbGxhXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBSb3dDb250ZXh0czogYW55W10gPSBbXTtcclxuXHJcbiAgICAvKiogRGlyZXR0aXZlIGRpIG9yZGluYW1lbnRvIGRlbGxlIGNvbG9ubmUgKG5vbiBvcmRpbmFtZW50byBkZWkgZGF0aSBtYSBkZWxsZSBjb2xvbm5lIGluIHNlKSAqL1xyXG4gICAgcHVibGljIE9yZGVyRGlyZWN0aXZlczogc3RyaW5nW10gPSBbXTtcclxuXHJcbiAgICAvKiogQ29kaWNlIGRlbGwndWx0aW1vIG9nZ2V0dG8gc29sZXppb25hdG8gKi9cclxuICAgIHB1YmxpYyBsYXN0U2VsZWN0ZWRJdGVtSUQgPSBudWxsO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSW5kaWNhIHNlIG9sdHJlIGFsbGUgY29sb25uZSBkaW5hbWljaGUgc3BlY2lmaWNoZSBkaSB1biB0aXBvIGRpIG9nZ2V0dG8gY2kgc29ubyBhbmNoZSBjb2xvbm5lIGRpbmFtaWNoZSBhZ2dpdW50ZSBkYWxsJ3V0ZW50ZVxyXG4gICAgICpcclxuICAgICAqIEVzLiB1bmEgY29sb25uYSBpbiBjdWkgbW9zdHJhcmUgc2VtcHJlIHVuIGljb25jaW5hXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBVc2VyRGVmaW5lZER5bmFtaWNDb2xzOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gICAgLyoqIEluZGljYSBjaGUgcXVlc3RvIMOoIGlsIHByaW1vIEJpbmQgZGVsbGEgdGFiZWxsYSwgdmllbmUgc2V0dGF0byBhIGZhbHNlIG5vbiBhcHBlbmEgaWwgcHJpbW8gYmluZCB2aWVuZSB0ZXJtaW5hdG8gY29uIHN1Y2Nlc3NvICovXHJcbiAgICBwdWJsaWMgRmlyc3RCaW5kOiBib29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgICAvKiogTGlzdGEgZGkgY29sb25uZSBjaGUgc2kgcG9zc29ubyB2aXN1YWxpenphcmUvb3JkaW5hcmUgZnJhIGRpIGxvcm8gKi9cclxuICAgIHB1YmxpYyBDb2x1bW5zTGlzdDogRXNUYWJsZUNvbHVtbltdID0gW107XHJcblxyXG4gICAgLyoqIFZhcmlhYmlsZSBkJ2FwcG9nZ2lvIHVzYXRhIGRhbGxhIGRpYWxvZyBkaSBzZWxlemlvbmUvbmFzY29uZGltZW50bywgcGVyIGV2aXRhcmUgZGkgZGFubmVnZ2lhcmUgKipDb2x1bW5zTGlzdCoqIGluIGNhc28gZGkgbW9kaWZpY2hlIHBvaSBhbm51bGxhdGUgKi9cclxuICAgIHB1YmxpYyBUTVBDb2x1bW5zTGlzdDogRXNUYWJsZUNvbHVtbltdID0gW107XHJcblxyXG4gICAgLyoqIFZhbG9yZSBkZWwgY2hlY2sgZ2xvYmFsZSBkaSB2aXNpYmlsaXTDoCB2YWxpZG8gcGVyIHR1dHRlIGxlIGNvbG9ubmUgaW4gKipDb2x1bW5zTGlzdCoqICovXHJcbiAgICBwdWJsaWMgZ2xvYmFsQ29sVmlzQ2hlY2sgPSBmYWxzZTtcclxuXHJcbiAgICAvKiogUXVlcnkgcGVyIHJlY3VwZXJhcmUgdHV0dGUgbGUgbnVvdmUgZGlyZXR0aXZlICBhc3NlZ25hdGkgYSBkaXJldHRpdmEgKFBlciBsYSBtb2RhbGl0w6AgZGluYW1pY2EgZGVsbCdlcy10YWJsZSkgKi9cclxuICAgIEBDb250ZW50Q2hpbGRyZW4oRXNUZERpcmVjdGl2ZSkgRXNUZHNEaXJlY3RpdmU6IFF1ZXJ5TGlzdDxFc1RkRGlyZWN0aXZlPjtcclxuXHJcbiAgICAvKiogUXVlcnkgcGVyIHJlY3VwZXJhcmUgdHV0dGkgZ2xpIGVzLXRkIGFzc2VnbmF0aSBhIGRpcmV0dGl2YSAoUGVyIGxhIG1vZGFsaXTDoCBkaW5hbWljYSBkZWxsJ2VzLXRhYmxlKSAqL1xyXG4gICAgQENvbnRlbnRDaGlsZHJlbihFc1RoRGlyZWN0aXZlKSBFc1Roc0RpcmVjdGl2ZTogUXVlcnlMaXN0PEVzVGhEaXJlY3RpdmU+O1xyXG5cclxuICAgIC8qKiBRdWVyeSBwZXIgcmVjdXBlcmFyZSB0dXR0aSBnbGkgZXMtdGggKi9cclxuICAgIEBDb250ZW50Q2hpbGRyZW4oZm9yd2FyZFJlZigoKSA9PiBFc1RoKSkgcHJpdmF0ZSBFc1RoczogUXVlcnlMaXN0PEVzVGg+O1xyXG5cclxuICAgIC8qKiBRdWVyeSBwZXIgcmVjdXBlcmFyZSB0dXR0aSBnbGkgZXMtdGQgKi9cclxuICAgIEBDb250ZW50Q2hpbGRyZW4oZm9yd2FyZFJlZigoKSA9PiBFc1RkKSkgcHJpdmF0ZSBFc1RkczogUXVlcnlMaXN0PEVzVGQ+O1xyXG5cclxuICAgIC8qKiBRdWVyeSBwZXIgcmVjdXBlcmFyZSBsZSBpbmZvcm1hemlvbmkgZGVsIGJvZHkgKHB1bnRvIGRlbGxhIHRhYmVsbGEgZG92ZSB2ZW5nb25vIG1vc3RyYXRlIGxlIHJpZ2hlKSAqL1xyXG4gICAgQENvbnRlbnRDaGlsZCgnYm9keScsIHsgc3RhdGljOiBmYWxzZSB9KSBwdWJsaWMgYm9keVJlZjogYW55O1xyXG5cclxuICAgIC8qKiBRdWVyeSBwZXIgcmVjdXBlcmFyZSBsZSBpbmZvcm1hemlvbmkgZGVsbCdoZWFkZXIgKHB1bnRvIGRlbGxhIHRhYmVsbGEgZG92ZSB2ZW5nb25vIG1vc3RyYXRlIGxlIGludGVzdGF6aW9uaSBkZWxsZSByaWdoZSkgKi9cclxuICAgIEBDb250ZW50Q2hpbGQoJ2hlYWRlcicsIHsgc3RhdGljOiBmYWxzZSB9KSBwdWJsaWMgaGVhZGVyUmVmOiBhbnk7XHJcblxyXG4gICAgLyoqIFF1ZXJ5IHBlciByZWN1cGVyYXJlIGxlIGluZm9ybWF6aW9uaSBzdWwgcmFnZ3J1cHBhbWVudG8gZGVnbGkgaGVhZGVyICovXHJcbiAgICBAQ29udGVudENoaWxkKCdoZWFkZXJHcm91cCcsIHsgc3RhdGljOiBmYWxzZSB9KSBwdWJsaWMgaGVhZGVyR3JvdXBSZWY6IGFueTtcclxuXHJcbiAgICAvKiogUXVlcnkgcGVyIHJlY3VwZXJhcmUgbGUgaW5mb3JtYXppb25pIHN1bCByYWdncnVwcGFtZW50byBkaSBzZWNvbmRvIGxpdmVsbG8gZGVnbGkgaGVhZGVyICovXHJcbiAgICBAQ29udGVudENoaWxkKCdzZWNvbmRhcnlIZWFkZXJHcm91cCcsIHsgc3RhdGljOiBmYWxzZSB9KSBwdWJsaWMgc2Vjb25kYXJ5SGVhZGVyR3JvdXBSZWY6IGFueTtcclxuXHJcbiAgICAvKiogT3B6aW9uaSBleHRyYSBjaGUgZGV2b25vIGFwcGFyaXJlIG5lbCBNZW7DuSBjb250ZXN0dWFsZSBpbiBhbHRvIGEgZGVzdHJhLCByaWNoaWFtYXRvIGRhaSAzIHBhbGxpbmkgdmVydGljYWxpICovXHJcbiAgICBASW5wdXQoKSBDb3JuZXJNZW51T3B0aW9uczogQ29ybmVyTWVudU9wdGlvbltdID0gbnVsbDtcclxuXHJcbiAgICAvKiogSW5kaWNhIHNlIGRldidlc3NlcmUgcG9zc2liaWxlIGVmZmV0dHVhcmUgaWwgcmVzaXplIGRlbGxlIGNvbG9ubmUgKi9cclxuICAgIEBJbnB1dCgpIENvbHVtbnNSZXNpemFibGU6IGJvb2xlYW4gPSBudWxsO1xyXG5cclxuICAgIC8qKiBJbmRpY2Egc2UgZGV2J2Vzc2VyZSBkaXNwb25pYmlsZSBpbCBzaXN0ZW1hIGRpIGFnZ2lvcm5hbWVudG8gYXV0b21hdGljbyAqL1xyXG4gICAgQElucHV0KCkgQXV0b1VwZGF0ZTogYm9vbGVhbiA9IG51bGw7XHJcblxyXG4gICAgLyoqIEluZGljYSBzZSBsYSB0YWJlbGxhIChjb25maWd1cmF0YSBjb24gKipVc2VDdXN0b21DZWxscyoqKSBkZXZlIG1ldHRlcnNpIGluIGFzY29sdG8gcGVyIGkgY2xpY2sgc3VsbGUgY2VsbGUgZGVzaWRlcmF0ZVxyXG4gICAgICogXHJcbiAgICAgKiBAZGVwcmVjYXRlZCBVdGlsaXp6YXJlIGwnSW5wdXQgKipUZW1wbGF0ZSoqIGRlbGxlIGVzLXRkIGUgYXNzZWduYXJlIHVuIHRlbXBsYXRlIGNvbiB0dXR0aSBpIGJpbmRpbmcgY2hlIHNpIHZ1b2xlIGFpIGNsaWNrXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpIFVzZUN1c3RvbUNlbGxBY3Rpb25zOiBib29sZWFuID0gbnVsbDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEluZGljYSBsZSBjZWxsZSBkZXNpZGVyYXRlIHN1IGN1aSBpbnRlcmNldHRhcmUgaSBjbGljay4gQXR0aXZhIHNvbG8gcXVhbmRvICoqVXNlQ3VzdG9tQ2VsbEFjdGlvbnMqKiDDqCB0cnVlLlxyXG4gICAgICogT2duaSBjZWxsYSBkZXYnZXNzZXJlIHNlcGFyYXRhIGRhbGxhIHN1Y2Nlc3NpdmEgZGFsIGNhcmF0dGVyZSBkZWwgU2ltb2xlb246XHJcbiAgICAgKlxyXG4gICAgICogRXMsIFwiTWlhQ2VsbGExwqdNaWFDZWxsYTJcIlxyXG4gICAgICogXHJcbiAgICAgKiBAZGVwcmVjYXRlZCBVdGlsaXp6YXJlIGwnSW5wdXQgKipUZW1wbGF0ZSoqIGRlbGxlIGVzLXRkIGUgYXNzZWduYXJlIHVuIHRlbXBsYXRlIGNvbiB0dXR0aSBpIGJpbmRpbmcgY2hlIHNpIHZ1b2xlIGFpIGNsaWNrXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpIEN1c3RvbUNlbGxBY3Rpb25zT24gPSAnJztcclxuXHJcbiAgICAvKiogXHJcbiAgICAgKiBTZXJ2ZSBwZXIgZGVjaWRlcmUgZGkgbGFuY2lhcmUgbyBtZW5vIGlsICoqZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCkqKiBhbCB0ZXJtaW5lIGRlbGxhIGdlc3Rpb25lIGRlbGwnZXZlbnRvIFxyXG4gICAgICogXHJcbiAgICAgKiBAZGVwcmVjYXRlZCBVdGlsaXp6YXJlIGwnSW5wdXQgKipUZW1wbGF0ZSoqIGRlbGxlIGVzLXRkIGUgYXNzZWduYXJlIHVuIHRlbXBsYXRlIGNvbiB0dXR0aSBpIGJpbmRpbmcgY2hlIHNpIHZ1b2xlIGFpIGNsaWNrXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpIENlbGxBY3Rpb25Qcm9wYWdhdGVzID0gdHJ1ZTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlY2lkZSBzZSB1dGlsaXp6YXJlIG8gbWVubyBsZSBDdXN0b21DZWxscy4gSW1wb3N0YW5kb2xvIGEgKip0cnVlKiogbCdlcy10YWJsZSBkaXZlbnRhIGluIGdyYWRvIGRpIGdlc3RpcmUgbmF0aXZhbWVudGU6XHJcbiAgICAgKlxyXG4gICAgICogMSkgT3JkaW5hbWVudG8gZSB2aXNpYmlsaXTDoCBkZWxsZSBjb2xvbm5lXHJcbiAgICAgKlxyXG4gICAgICogMikgT3JkaW5hbWVudG8gZGVpIGRhdGlcclxuICAgICAqXHJcbiAgICAgKiAzKSBNb2RhbGl0w6AgR2VyYXJjaGljYVxyXG4gICAgICpcclxuICAgICAqIGVjYy4uLlxyXG4gICAgICovXHJcbiAgICBASW5wdXQoKSBVc2VDdXN0b21DZWxsczogYm9vbGVhbiA9IG51bGw7XHJcblxyXG4gICAgLyoqIFBlcm1ldHRlIGRpIGltcG9zdGFyZSBsJ2FsdGV6emEgbWFzc2ltYSBkZWxsYSB0YWJlbGxhLiBTZSBudWxsIGxhIGRpbWVuc2lvbmUgc2kgYWRhdHRhIGFsIG51bWVybyBkaSBlbGVtZW50aSBhdHR1YWxtZW50ZSBpbiB2aXN1YWxpenphemlvbmUgKi9cclxuICAgIEBJbnB1dCgpIE1heEhlaWdodDogbnVtYmVyID0gbnVsbDtcclxuXHJcbiAgICAvKiogQ2xhc3NpIGRhIGFwcGxpY2FyZSBhbGxhIHRhYmVsbGEgb2x0cmUgYSBxdWVsbGUgZ2VzdGl0ZSBhdXRvbm9tYW1lbnRlIGRhbGxhIGxpYnJlcmlhICovXHJcbiAgICBASW5wdXQoKSBDbGFzcyA9ICcnO1xyXG5cclxuICAgIC8qKiBQZXJtZXR0ZSBvIG1lbm8gbCdleHBvcnQgaW4gZm9ybWF0byBYTFNYICovXHJcbiAgICBASW5wdXQoKSBYTFNYRXhwb3J0OiBib29sZWFuID0gbnVsbDtcclxuXHJcbiAgICAvKiogUGVybWV0dGUgbyBtZW5vIGwnZXhwb3J0IGluIGZvcm1hdG8gQ1NWICovXHJcbiAgICBASW5wdXQoKSBDU1ZFeHBvcnQgPSB0cnVlO1xyXG5cclxuICAgIC8qKiBQZXJtZXR0ZSBkaSB2aXN1YWxpenphcmUgbyBtZW5vIGwnb3B6aW9uZSBkaSBwYWdpbmF6aW9uZSBcIlR1dHRpXCIgKi9cclxuICAgIEBJbnB1dCgpIEFsbFNlYXJjaCA9IHRydWU7XHJcblxyXG4gICAgLyoqIERpbWludWlzY2UgZ2xpIHNwYXppIGZyYSB1bmEgY2VsbGEgZSBsJ2FsdHJhLCBlIGludGVybmFtZW50ZSBpbCBwYWRkaW5nIGRlbCBmb250IGluIG1vZG8gZGEgcHJlc2VudGFyZSBtb2x0aSBwacO5IGRhdGkgaW4gdW4ndW5pY2EgcGFnaW5hICovXHJcbiAgICBASW5wdXQoKSBIaWdoQ2VsbERlbnNpdHk6IGJvb2xlYW4gPSBudWxsO1xyXG5cclxuICAgIC8qKiBBYmlsaXRhIG8gbWVubyBsYSBwb3NzaWJpbGl0w6AgZGkgc2VsZXppb25hcmUgb2dnZXR0aSAqL1xyXG4gICAgQElucHV0KCkgU2VsZWN0aW9uOiBib29sZWFuID0gbnVsbDtcclxuXHJcbiAgICAvKiogTW9zdHJhIG8gbWVubyB1biBtZXNzYWdnaW8gZGkgTG9hZGluZyBhbCBwcmltbyBjYXJpY2FtZW50byBkZWxsYSB0YWJlbGxhICovXHJcbiAgICBASW5wdXQoKSBTaG93TG9hZGluZ09uQm9vdHN0cmFwOiBib29sZWFuID0gbnVsbDtcclxuXHJcbiAgICAvKiogU2UgaW1wb3N0YXRvIGEgKip0cnVlKiogYWdnaXVuZ2UgdW5hIGNvbG9ubmEgY29uIHB1bHNhbnRlIGRpIGVsaW1pbmF6aW9uZSBwZXIgZWZmZXR0dWFyZSBsJ2VsaW1pbmEgZGVsbCdvZ2dldHRvIHJlbGF0aXZvICovXHJcbiAgICBASW5wdXQoKSBSZW1vdmFsOiBib29sZWFuID0gbnVsbDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIENvbmRpemlvbmUgY2hlIG5hc2NvbmRlIGwnaWNvbmEgZGkgZWxpbWluYXppb25lIGluc2VyaXRhIGltcG9zdGFuZG8gKipSZW1vdmFsKiogYSB0cnVlIHF1YWxvcmEgbGEgY29uZGl6aW9uZSBub24gdmVuaXNzZSByaXNwZXR0YXRhXHJcbiAgICAgKlxyXG4gICAgICogQ29tZSBjb25kaXppb25lIHNpIGNvbnNpZGVyYSB1biBzZW1wbGljZSBjYW1wbyBzdSBjdWkgZWZmZXR0dWFyZSB1biBjb250cm9sbG8gYm9vbGVhbm8sIGNvbWUgYWQgZXNlbXBpbyBcImNhbnJlbW92ZVwiXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpIFJlbW92YWxDb25kaXRpb24gPSAnJztcclxuXHJcbiAgICAvKiogSW5kaWNhIHNlIGFiaWxpdGFyZSBsYSBwb3NzaWJpbGl0w6AgZGkgZXNwb3J0YXJlIGxhIHZpc3RhIGRhdGkgYXR0dWFsZSAqL1xyXG4gICAgQElucHV0KCkgRXhwb3J0OiBib29sZWFuID0gbnVsbDtcclxuXHJcbiAgICAvKiogSW5kaWNhIHNlIHBlcm1ldHRlcmUgbGEgc2VsZXppb25lIG11bHRpcGxhIFdpbmRvd3MtbGlrZSBjbGljY2FuZG8gdW4gb2dnZXR0byBlIGZhY2VuZG8gcG9pIFNoaWZ0ICsgY2xpY2sgc3UgdW4gb2dnZXR0byBzdWNjZXNzaXZvICovXHJcbiAgICBASW5wdXQoKSBTaGlmdENsaWNrOiBib29sZWFuID0gbnVsbDtcclxuXHJcbiAgICAvKiogTW9zdHJhIG8gbmFzY29uZGUgbGUgaW5mb3JtYXppb25pIGRpIHBhZ2luYXppb25lLCBzaWEgaSBwdWxzYW50aSwgc2lhIGlsIHNlbGV0dG9yZSBkZWdsaSBvZ2dldHRpIHBlciBwYWdpbmEgKi9cclxuICAgIEBJbnB1dCgpIFNob3dQYWdpbmcgPSB0cnVlO1xyXG5cclxuICAgIC8qKiBJbmRpY2Egc2UgbmFzY29uZGVyZSBvIG1vc3RyYXJlIGlsIGNvbXBvbmVudGUgZGkgcGFnaW5hemlvbmUgKi9cclxuICAgIEBJbnB1dCgpIEhpZGVQYWdpbmc6IGJvb2xlYW4gPSBudWxsO1xyXG5cclxuICAgIC8qKiBJbmRpY2Egc2UgbmFzY29uZGVyZSBvIG1vc3RyYXJlIGlsIGNvbnRlZ2dpbyBkZWdsaSBlbGVtZW50aSB0cm92YXRpICovXHJcbiAgICBASW5wdXQoKSBIaWRlUGFnaW5nQ291bnQ6IGJvb2xlYW4gPSBudWxsO1xyXG5cclxuICAgIC8qKiBJbmRpY2Egc2UgbmFzY29uZGVyZSBvIG1vc3RyYXJlIGkgcHVsc2FudGkgZGkgcGFnaW5hemlvbmUgKi9cclxuICAgIEBJbnB1dCgpIEhpZGVQYWdpbmdCdXR0b25zOiBib29sZWFuID0gbnVsbDtcclxuXHJcbiAgICAvKiogUmlmZXJpbWVudG8gYWwgQ29udGV4dE1lbnUgKG5neC1jb250ZXh0bWVudSkgYXNzb2NpYXRvIGFsIGNsaWNrIGRlc3RybyBkaSB1bm8gbyBwacO5IGVsZW1lbnRpIHNlbGV6aW9uYXRpIG5lbGxhIHRhYmVsbGEgKi9cclxuICAgIEBJbnB1dCgpIENvbnRleHRNZW51OiBDb250ZXh0TWVudUNvbXBvbmVudCA9IG51bGw7XHJcblxyXG4gICAgLyoqIE5vbWUgZGVsbCdlc3BvcnRhemlvbmUgZ2VuZXJhdGEgZGEgcXVlc3RhIHRhYmVsbGEgKi9cclxuICAgIEBJbnB1dCgpIEV4cG9ydEZpbGVOYW1lID0gJ0V4cG9ydC5jc3YnO1xyXG5cclxuICAgIC8qKiBDbGFzc2UgKEhUTUwpIGRpIGRlZmF1bHQgZGVsbGEgdGFiZWxsYSAqL1xyXG4gICAgQElucHV0KCkgVGFibGVDbGFzcyA9ICd0YWJsZSB0YWJsZS1zdHJpcGVkIHRhYmxlLWhvdmVyIHRhYmxlLXNtJztcclxuXHJcbiAgICAvKiogVGVzdG8gZGEgdmlzdWFsaXp6YXJlIG5lbCBjb250ZWdnaW8uIERpIGRlZmF1bHQ6IFwiT2dnZXR0aSBzZWxlemlvbmF0aVwiICovXHJcbiAgICBASW5wdXQoKSBDb3VudExhYmVsOiBzdHJpbmcgPSB0aGlzLmxjLmxvYygnRm91bmQgb2JqZWN0cycpO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogRnVuemlvbmUgZGEgdXRpbGl6emFyZSBpbiBlc3BvcnRhemlvbmUuIE5lbCBmb3JtYXRvIFwiUmVwb3J0XCIgYXZyw6AgdW4gdW5pY28gcGFyYW1ldHJvIFwiRm9ybWF0b1wiIGUgbmVzc3VuIHZhbG9yZSBkaSByaXRvcm5vLlxyXG4gICAgICpcclxuICAgICAqIE5lbCBmb3JtYXRvIFwiVmlld1wiIGhhIGNvbWUgcGFyYW1ldHJvIHVuYSBjYWxsYmFjayBjb24gaSBkYXRpIGNvbXBsZXRpIGRhIGVzcG9ydGFyZSAoZGF0byBjaGUgZGkgZGVmYXVsdCBsYSByaWNlcmNhIMOoIHBhZ2luYXRhKVxyXG4gICAgICovXHJcbiAgICBASW5wdXQoKSBFeHBvcnRGdW5jdGlvbjogYW55O1xyXG5cclxuICAgIC8qKiBJbmRpY2EgbGEgcHJlc2VuemEgZGkgcmFnZ3J1cHBhbWVudGkgYSBsaXZlbGxvIGRpIGhlYWRlciAqL1xyXG4gICAgQElucHV0KCkgSGFzSGVhZGVyR3JvdXA6IGJvb2xlYW4gPSBudWxsO1xyXG5cclxuICAgIC8qKiBJbmRpY2EgbGEgcHJlc2VuemEgZGkgcmFnZ3J1cHBhbWVudGkgYSBsaXZlbGxvIGRlbCByYWdncnVwcGFtZW50byBwcmVjZWRlbnRlbWVudGUgZXNpc3RlbnRlLCBjaGlhcmFtZW50ZSDDqCBpbnNlbnNhdGEgc2VuemEgKipIYXNIZWFkZXJHcm91cCoqICovXHJcbiAgICBASW5wdXQoKSBIYXNTZWNvbmRhcnlIZWFkZXJHcm91cDogYm9vbGVhbiA9IG51bGw7XHJcblxyXG4gICAgLyoqIFV0aWxpenphdG8gcGVyIGRpdmlkZXJlIGxhIHNvcmdlbnRlIGluIG1vZGFsaXTDoCBFbmRsZXNzU2Nyb2xsICovXHJcbiAgICBASW5wdXQoKSBTbGljZVNpemUgPSAxMDA7XHJcblxyXG4gICAgLyoqIERlY2lkZSBzZSB1dGlsaXp6YXJlIGxhIG1vZGFsaXTDoCBkaSBFbmRsZXNzU2Nyb2xsICovXHJcbiAgICBASW5wdXQoKSBFbmRsZXNzU2Nyb2xsOiBib29sZWFuID0gbnVsbDtcclxuXHJcbiAgICAvKiogUXVhbG9yYSAqKkVuZGxlc3NTY3JvbGwqKiBmb3NzZSB0cnVlLCBpbmRpY2Egc2UgdXRpbGl6emFyZSBxdWVzdGEgbW9kYWxpdMOgIHNvbG8gcXVhbmRvIHNpIGNlcmNhIHBlciBcIlR1dHRpXCIgbyBpbiBnZW5lcmFsZSAqL1xyXG4gICAgQElucHV0KCkgRW5kbGVzc1Njcm9sbE9ubHlGb3JBbGwgPSB0cnVlO1xyXG5cclxuICAgIC8qKiBJbmRpY2Egc2UgbmFzY29uZGVyZSBnbGkgSGVhZGVyIGRlbGxhIHRhYmVsbGEgKi9cclxuICAgIEBJbnB1dCgpIEhlYWRlckhpZGRlbjogYm9vbGVhbiA9IG51bGw7XHJcblxyXG4gICAgLyoqIEluZGljYSBzZSBuYXNjb25kZXJlIGlsIEJvZHkgZGVsbGEgdGFiZWxsYSAqL1xyXG4gICAgQElucHV0KCkgQm9keUhpZGRlbjogYm9vbGVhbiA9IG51bGw7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJbmRpY2Egc2UgbGEgc2VsZXppb25lIMOoIHRlbXBvcmFuZWFtZW50ZSBkaXNhYmlsaXRhdGEuIFJpc3BldHRvIGFsbCdJbnB1dCAqKlNlbGVjdGlvbioqIGNoZSB2aXNpdmFtZW50ZSBnZXN0aXNjZSBzZSBjaSBzb25vIG8gbm8gZ2xpIGlucHV0IGRpIHNlbGV6aW9uZSxcclxuICAgICAqIHF1ZXN0byBJbnB1dCBnZXN0aXNjZSBzZSBxdWVzdGkgaW5wdXQgc29ubyBhYmlsaXRhdGkgbyBtZW5vXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpIFNlbGVjdGlvbkRpc2FibGVkOiBib29sZWFuID0gbnVsbDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEluZGljYSBzZSBmb3J6YXJlIGlsIHNpc3RlbWEgZGkgc2VsZXppb25lIGEgZ2VzdGlyZSB1biBlbGVtZW50byBwZXIgdm9sdGEuXHJcbiAgICAgKiBTZWxlemlvbmFyZSB1bidhbHRyYSByaWdhIGNvbiB1bmEgZ2nDoCBzZWxlemlvbmF0YSBhcHBsaWNoZXLDoCBsYSBzZWxlemlvbmUgYWxsYSBudW92YSByaWdhLCByaW11b3ZlbmRvbGEgZGFsbCdhdHR1YWxlXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpIFNpbmdsZVNlbGVjdGlvbjogYm9vbGVhbiA9IG51bGw7XHJcblxyXG4gICAgLyoqIENhbGxiYWNrIGNoZSBkYXRvIHVuIG9nZ2V0dG8gcmVzaXR1aXNjZSBsJ2V2ZW50dWFsZSBjbGFzc2UgZGEgYXBwbGljYXJlIGFsbGEgcmlnYSBjb2xsZWdhdGEgYWxsJ29nZ2V0dG8gKi9cclxuICAgIEBJbnB1dCgpIFJvd0NsYXNzQXNzaWduZXI6IGFueSA9IG51bGw7XHJcblxyXG4gICAgLyoqIFBlcm1ldHRlIGRpIG9yZGluYXJlIGkgZGF0aSBpbiBtYW5pZXJhIGRpc2NlbmRlbnRlIG8gYXNjZW5kZW50ZSAqL1xyXG4gICAgQElucHV0KCkgT3JkZXJCeUNvbHVtbjogYm9vbGVhbiA9IG51bGw7XHJcblxyXG4gICAgLyoqIFBlcm1ldHRlIGRpIGF2ZXJlIHBpw7kgZGlyZXR0aXZlIGRpIG9yZGluYW1lbnRvIGRlaSBkYXRpICovXHJcbiAgICBASW5wdXQoKSBNdWx0aXBsZU9yZGVyaW5nRGlyZWN0aXZlcyA9IHRydWU7XHJcblxyXG4gICAgLyoqIFBlcm1ldHRlIGRpIG5hc2NvbmRlcmUgbGUgY29sb25uZSBpbiBiYXNlIGFsbGUgc2VsZXppb25pIGVmZmV0dHVhdGUgZGFsIE1lbsO5IGNvbnRlc3R1YWxlIGluIGFsdG8gYSBkZXN0cmEgKi9cclxuICAgIEBJbnB1dCgpIEhpZGRlbkNvbHVtbnM6IGJvb2xlYW4gPSBudWxsO1xyXG5cclxuICAgIC8qKiBQZXJtZXR0ZSBkaSByaW9yZGluYXJlIGxlIGNvbG9ubmUgaW4gYmFzZSBhbGxlIGltcG9zdGF6aW9uaSBlZmZldHR1YXRlIGRhbCBNZW7DuSBjb250ZXN0dWFsZSBpbiBhbHRvIGEgZGVzdHJhICovXHJcbiAgICBASW5wdXQoKSBDb2x1bW5zT3JkZXJpbmc6IGJvb2xlYW4gPSBudWxsO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogRXZlbnR1YWxlIHN1cHBvcnRvIGFsbGUgcmljZXJjaGUgYXBwbGljYXRlIGFsbGEgbW9kYWxpdMOgIEFycmF5XHJcbiAgICAgKlxyXG4gICAgICogQGRlcHJlY2F0ZWQgVXRpbGl6emF0byBzb2xvIHBlciB1biBjYXNvIHBhcnRpY29sYXJlIGRlbCBNZXRlcmluZ1xyXG4gICAgICovXHJcbiAgICBASW5wdXQoKSBTZWFyY2hWaWV3ID0gbnVsbCBhcyBJQXBwU2VhcmNoPGFueT47XHJcblxyXG4gICAgLyoqIEFiaWxpdGEgbyBkaXNhYmlsaXRhIGlsIHNpc3RlbWEgY2hlIHBlcm1ldHRlIGRpIHNlbGV6aW9uYXJlIHR1dHRpIGdsaSBlbGVtZW50aSBuZWxsYSB2aXN0YSAqL1xyXG4gICAgQElucHV0KCkgU2VsZWN0QWxsOiBib29sZWFuID0gbnVsbDtcclxuXHJcbiAgICAvKiogU2ltdWxhIGxhIHBhZ2luYXppb25lIGFuY2hlIHBlciBsZSB0YWJlbGxlIGNoZSBmdW56aW9uYW5vIGluIG1vZGFsaXTDoCBBcnJheSAqL1xyXG4gICAgQElucHV0KCkgVXNlQXJyYXlNb2RlUGFnaW5nID0gdHJ1ZTtcclxuXHJcbiAgICAvKiogRGVmaW5pemlvbmUgZGkgY29sb25uZSBkaW5hbWNoZSBwZXIgbGEgbW9kYWxpdMOgLCBhcHB1bnRvLCBkaW5hbWljYSAqL1xyXG4gICAgQElucHV0KCkgRHluYW1pY1Jvd0NvbHVtbnNEZWZpbml0aW9uOiBFc1RhYmxlQ29sdW1uc0RlZmluaXRpb25bXSA9IG51bGw7XHJcblxyXG4gICAgLyoqIEluZGljYSBvcGVyYXppb25pIGRpbmFtaWNoZSBnZW5lcmljaGUgY2hlIHBvc3Nvbm8gZXNzZXJlIGVmZmV0dHVhdGUgcGVyIHJpZ2EuIEFwcGFpb25vIGNvbWUgY29sb25uZSBleHRyYSBzdWwgbGF0byBzaW5pc3RybyBkZWxsYSB0YWJlbGxhICovXHJcbiAgICBASW5wdXQoKSBEeW5hbWljT3BlcmF0aW9uczogRXNUYWJsZU9wZXJhdGlvbkRlZmluaXRpb25bXSA9IFtdO1xyXG5cclxuICAgIC8qKiBJbmRpY2Egc2UgdmlzdWFsaXp6YXJlIGkgZGF0aSBpbiBtYW5pZXJhIGdlcmFyY2hpY2EgKi9cclxuICAgIEBJbnB1dCgpIEhpZXJhcmNoeTogYm9vbGVhbiA9IG51bGw7XHJcblxyXG4gICAgLyoqIE5vbWUgZGVsbGEgcHJvcHJpZXTDoCBjaGUgY29udGllbmUgbCdJRCBkZWwgcGFkcmUuIERhIHV0aWxpenphcmUgc2UgKipIaWVyYXJjaHkqKiDDqCBpbXBvc3RhdG8gKi9cclxuICAgIEBJbnB1dCgpIFBhcmVudEtleSA9ICcnO1xyXG5cclxuICAgIC8qKiBOb21lIGRlbGxhIHByb3ByaWV0w6AgY2hlIGNvbnRpZW5lIGwnSUQgZGVsbCdvZ2dldHRvIGF0dHVhbGUuIERhIHV0aWxpenphcmUgc2UgKipIaWVyYXJjaHkqKiDDqCBpbXBvc3RhdG8gKi9cclxuICAgIEBJbnB1dCgpIE93bktleSA9ICcnO1xyXG5cclxuICAgIC8qKiBJbmRpY2Egc2UgcGFydGlyZSBjb24gdW4gYWxiZXJvIGVzcGFuc28uIERhIHV0aWxpenphcmUgc2UgKipIaWVyYXJjaHkqKiDDqCBpbXBvc3RhdG8gKi9cclxuICAgIEBJbnB1dCgpIFN0YXJ0c0V4cGFuZGVkID0gdHJ1ZTtcclxuXHJcbiAgICAvKiogSW5kaWNhIHNlIGVmZmV0dHVhcmUgaWwgc2FsdmF0YWdnaW8gZGVsbGUgcHJlZmVyZW56ZSBkaSByaWNlcmNhICovXHJcbiAgICBASW5wdXQoKSBTYXZlUHJlZmVyZW5jZXM6IGJvb2xlYW4gPSBudWxsO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogU29yZ2VudGUgZGF0aSBzZWNvbmRhcmlhXHJcbiAgICAgKlxyXG4gICAgICogQGRlcHJlY2F0ZWQgVXRpbGl6emF0byBzb2xvIHBlciB1biBjYXNvIHBhcnRpY29sYXJlIGRlbCBNZXRlcmluZ1xyXG4gICAgICovXHJcbiAgICBASW5wdXQoKSBTZWNvbmRhcnlTb3VyY2U6IGJvb2xlYW4gPSBudWxsO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogU29yZ2VudGUgZGF0aSBzZWNvbmRhcmlhXHJcbiAgICAgKlxyXG4gICAgICogQGRlcHJlY2F0ZWQgVXRpbGl6emF0byBzb2xvIHBlciB1biBjYXNvIHBhcnRpY29sYXJlIGRlbCBNZXRlcmluZ1xyXG4gICAgICovXHJcbiAgICBASW5wdXQoKSBUZXJ0aWFyeVNvdXJjZTogYm9vbGVhbiA9IG51bGw7XHJcblxyXG4gICAgLyoqIEluZGljYSBzZSB1dGlsaXp6YXJlIGxhIGNhY2hlIGRpIHNlbGV6aW9uZSBjaGUgcGVybWV0dGUgZGkgbWFudGVuZXJlIGdsaSBzdGF0aSBkaSBzZWxlemlvbmUgZGVpIHZhcmkgb2dnZXR0aSBuYXZpZ2FuZG8gZGEgdW5hIHBhZ2luYSBhbGwnYWx0cmEgKi9cclxuICAgIEBJbnB1dCgpIFVzZVNlbGVjdGlvbkNhY2hlID0gdHJ1ZTtcclxuXHJcbiAgICAvKiogRXZlbnRvIGNoZSB2aWVuZSByaWNoaWFtYXRvIGFsIGNhbWJpbyBkaSBvcmlkbmFtZW50byBkaSB1bmEgY29sb25uYSAqL1xyXG4gICAgQE91dHB1dCgpIG9uT3JkZXJDaGFuZ2VkOiBFdmVudEVtaXR0ZXI8QXBwT3JkZXJpbmc+ID0gbmV3IEV2ZW50RW1pdHRlcjxBcHBPcmRlcmluZz4oKTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEV2ZW50byBjaGUgdmllbmUgcmljaGlhbWF0byBxdWFuZG8gbCdlcy10YWJsZSByaXRpZW5lIHNpYSBuZWNlc3NhcmlvIHJpLWVmZmV0dHVhcmUgbGEgcmljZXJjYS5cclxuICAgICAqIElsIGJvb2xlYW5vIGRlbGwnZXZlbnRvIGluZGljYSBzZSB2aWVuZSBzdWdnZXJpdG8gZGkgcmVzZXR0YXJlIGxhIHBhZ2luYSBvIG1lbm8uXHJcbiAgICAgKiBcclxuICAgICAqIFNvbG8gaW4gY2FzbyB2ZW5nYSB1dGlsaXp6YXRhIGxhIG1vZGFsaXTDoCBhIHJhZ2dydXBwYW1lbnRpIGRpIHJpZ2hlIHB1w7Igc3VjY2VkZXJlIGNoZSBsJ2VzLXRhYmxlIHBhc3NpIHVuIGludGVybyBBcHBTZWFyY2ggY29tZSBwYXJhbWV0cm8gZGkgcmljZXJjYSxcclxuICAgICAqIGluIHF1ZWwgY2FzbyBsJ2FwcGxpY2F6aW9uZSByaWNldmVudGUgZG92csOgIG9ub3JhcmUgbGEgcmljaGllc3RhIHNwZWRlbmRvIGFsIGJhY2thbmQgbCdvZ2dldHRvIGRpIHJpY2VyY2EgQVMtSVNcclxuICAgICAqIFxyXG4gICAgICogaWwgdGlwbyBkZWxsJ0VtaXR0ZXIgaW52ZWNlIGRpIGVzc2VyZSBbYm9vbGVhbiB8IEFwcFNlYXJjaDxhbnk+XSDDqCBzdGF0byBpbXBvc3RhdG8gYSBcImFueVwiIHBlciBldml0YXJlIHByb2JsZW1pIGRpIHJldHJvY29tcGF0aWJpbGl0w6BcclxuICAgICAqL1xyXG4gICAgQE91dHB1dCgpIG9uU2VhcmNoUmVxdWVzdDogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcclxuXHJcbiAgICAvKiogRXZlbnRvIGNoZSBwYXJ0ZSBhZCBvZ25pIG1vZGlmaWNhIGRpIFwiY2hlY2thZ2dpb1wiIGluIGZvcm1hIGRpIGNvbW9kbyBhcnJheS4gRXNwb25lIGwnb2dnZXR0byBjb24gbG8gc3RhdG8gZGkgY2hlY2sgYXR0dWFsZSAqL1xyXG4gICAgQE91dHB1dCgpIG9uU2VsZWN0aW9uQ2hhbmdlZDogRXZlbnRFbWl0dGVyPEl0ZW1zU2VsZWN0aW9uPGFueT4+ID0gbmV3IEV2ZW50RW1pdHRlcjxJdGVtc1NlbGVjdGlvbjxhbnk+PigpO1xyXG5cclxuICAgIC8qKiBFdmVudG8gcmljaGlhbWF0byBhbGwnZWxpbWluYXppb25lIGRpIHVuIG9nZ2V0dG8gKi9cclxuICAgIEBPdXRwdXQoKSBvblJlbW92YWw6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XHJcblxyXG4gICAgLyoqIEV2ZW50byByaWNoaWFtYXRvIGFsbCdhbm51bGxhbWVudG8gZGkgdW4nZWxpbWluYXppb25lICovXHJcbiAgICBAT3V0cHV0KCkgb25BYm9ydFJlbW92YWw6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XHJcblxyXG4gICAgLyoqIEV2ZW50byByaWNoaWFtYXRvIGFsIGNsaWNrIHN1IHVuYSBjZWxsYSBxdWFuZG8gKipVc2VDdXN0b21DZWxsQWN0aW9ucyoqIMOoIGF0dGl2byBcclxuICAgICAqIFxyXG4gICAgICogQGRlcHJlY2F0ZWQgVXRpbGl6emFyZSBsJ0lucHV0ICoqVGVtcGxhdGUqKiBkZWxsZSBlcy10ZCBlIGFzc2VnbmFyZSB1biB0ZW1wbGF0ZSBjb24gdHV0dGkgaSBiaW5kaW5nIGNoZSBzaSB2dW9sZSBhaSBjbGlja1xyXG4gICAgICovXHJcbiAgICBAT3V0cHV0KCkgb25DZWxsQ2xpY2s6IEV2ZW50RW1pdHRlcjx7IGNvbHVtbjogc3RyaW5nLCBtb2RlbDogYW55IH0+ID0gbmV3IEV2ZW50RW1pdHRlcjx7IGNvbHVtbjogc3RyaW5nLCBtb2RlbDogYW55IH0+KCk7XHJcblxyXG4gICAgLyoqIEV2ZW50byByaWNoaWFtYXRvIHF1YW5kbyBzaSBjbGljY2Egc3UgdW4gb3B6aW9uZSBkZWZpbml0YSBuZWxsZSAqKkNvcm5lck1lbnVPcHRpb25zKiogKi9cclxuICAgIEBPdXRwdXQoKSBvbkNvcm5lckFjdGlvbjogRXZlbnRFbWl0dGVyPHsgaWQ6IHN0cmluZywgZXN0YWJsZTogYW55IH0+ID0gbmV3IEV2ZW50RW1pdHRlcjx7IGlkOiBzdHJpbmcsIGVzdGFibGU6IGFueSB9PigpO1xyXG5cclxuICAgIC8qKiBFdmVudG8gcmljaGlhbWF0byBxdWFuZG8gc2kgY2xpY2NhIHN1IHVuIG9wemlvbmUgZGVmaW5pdGEgbmVsbGUgKipEeW5hbWljT3BlcmF0aW9ucyoqICovXHJcbiAgICBAT3V0cHV0KCkgb25EeW5hbWljT3BlcmF0aW9uOiBFdmVudEVtaXR0ZXI8eyBpZDogc3RyaW5nLCBpdGVtOiBhbnkgfT4gPSBuZXcgRXZlbnRFbWl0dGVyPHsgaWQ6IHN0cmluZywgaXRlbTogYW55IH0+KCk7XHJcblxyXG4gICAgLyoqIERhdGkgZXNwb3J0YXRpIGRhIG5neC1jc3YgKi9cclxuICAgIHB1YmxpYyBkYXRhOiBhbnlbXTtcclxuICAgIC8qKiBIZWFkZXIgZGVpIGRhdGkgZXNwb3J0YXRpIGRhIG5neC1jc3YgKi9cclxuICAgIHB1YmxpYyBoZWFkZXJzOiBhbnlbXTtcclxuICAgIC8qKiBFbGVtZW50byBIVE1MIGRhIGNsaWNjYXJlIHBlciBsJ2VzcG9ydGF6aW9uZSAqL1xyXG4gICAgQFZpZXdDaGlsZCgnZXhwb3J0RG93bmxvYWRlcicsIHsgc3RhdGljOiBmYWxzZSB9KSBwdWJsaWMgZXhwb3J0RG93bmxvYWRlcjogRWxlbWVudFJlZjtcclxuXHJcbiAgICAvKiogUGxhY2Vob2xkZXIgZGkgbWVuw7kgY29udGVzdHVhbGUgcGVyIHF1YW5kbyBub24gY2kgc29ubyBvcHppb25pIG5lbCBwbGFjZWhvbGRlciBcIlZlcm9cIiAgKi9cclxuICAgIEBWaWV3Q2hpbGQoJ2VtcHR5TWVudScsIHsgc3RhdGljOiB0cnVlIH0pIHB1YmxpYyB0YWJsZUVtcHR5TWVudTogQ29udGV4dE1lbnVDb21wb25lbnQ7XHJcblxyXG4gICAgLyoqIFN1YnNjcmlwdGlvbiBzdWxsJ2FwZXJ0dXJhIGRlbCBjb250ZXh0IG1lbnUgZGEgcmlwdWxpcmUgYWwgZGVzdHJveSBkZWxsYSBjbGFzc2UgKi9cclxuICAgIHByaXZhdGUgY3R4TWVudVN1YnNjcmlwdGlvbjogYW55O1xyXG5cclxuICAgIC8qKiBQYWdpbmEgaW4gdmlzdWFsaXp6YXppb25lIChkdXJhbnRlIGxhIHBhZ2luYXppb25lIGluIG1vZGFsaXTDoCBBcnJheSkgKi9cclxuICAgIHB1YmxpYyBhcnJheW1vZGVQYWdlID0gMTtcclxuICAgIC8qKiBOdW1lcm8gZGkgcGFnaW5lIChkdXJhbnRlIGxhIHBhZ2luYXppb25lIGluIG1vZGFsaXTDoCBBcnJheSkgKi9cclxuICAgIHB1YmxpYyBhcnJheW1vZGVQYWdlcyA9IDE7XHJcbiAgICAvKiogT2dnZXR0aSBwZXIgb2duaSBwYWdpbmEgKGR1cmFudGUgbGEgcGFnaW5hemlvbmUgaW4gbW9kYWxpdMOgIEFycmF5KSAqL1xyXG4gICAgQElucHV0KCkgQXJyYXltb2RlSXRlbXNQZXJQYWdlID0gMTU7XHJcbiAgICAvKiogT2dnZXR0byBkaSBzZWxlemlvbmUgcGVyIGxhIG1vZGFsaXTDoCBBcnJheSwgY2hlIGRldmUgY29tcG9ydGFyc2kgY29tZSBsYSBjb250cm9wYXJ0ZSBpbiBtb2RhbGl0w6AgVmlldyAqL1xyXG4gICAgcHVibGljIGFycmF5bW9kZVNlbGVjdGlvbjogSXRlbXNTZWxlY3Rpb248YW55PjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFZhcmlhYmlsZSBjaGUgc2VydmUgYSBnZXN0aXJlIGlsIG1vbWVudG8gaW4gY3VpIGwnZXMtdGFibGUgYWdnaW9ybmEgbGEgcGFnaW5hemlvbmUgKHB1bHNhbnRpIGVjYykuXHJcbiAgICAgKiBFc3NlbmRvIG9wZXJhemlvbmkgY29tdW5xdWUgY29zdG9zZSBsZSBlZmZldHR1byBzb2xvIHN1IGJpbmRpbmcgZXN0ZXJuaSwgbm9uIHN1IHJld3JpdGUgZ2VuZXJhdGkgaW50ZXJuYW1lbnRlXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgaW50ZXJuYWxXcml0ZUNhbGwgPSBmYWxzZTtcclxuXHJcbiAgICAvKiogQ2FjaGUgZGkgc2VsZXppb25lIEhhc2ggLSBPZ2dldHRvICovXHJcbiAgICBwcml2YXRlIHNlbE9yRGVzZWxDYWNoZTogeyBbaGFzaDogc3RyaW5nXTogYW55IH0gPSB7fTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIENhY2hlIGNoZSBjb250ZXJyw6AgdHV0dGUgbGUgcmljZXJjaGUgZWZmZXR0dWF0ZSBzdSBncnVwcGkgZGl2ZXJzaSBkYWwgcHJpbW8gZSBzdSBlbGVtZW50aSBjb250ZW51dGkgbmVpIGdydXBwaS5cclxuICAgICAqIEluIGNhc28gZGkgY2FtYmkgZGkgb3JkaW5hbWVudG8gZGVsbGUgY29sb25uZSBkaXZlcnNlIGRhbGxhIHByaW1hIHR1dHRlIGxlIGNoaWFtYXRlIGZhdHRlIGRhbCBzZWNvbmRvIGxpdmVsbG8gaW4gcG9pIGRldm9ubyBlc3NlcmUgcmllc2VndWl0ZSBzZWNvbmRvIGxhIHNlZ3VlbnRlIGxvZ2ljYTpcclxuICAgICAqIFxyXG4gICAgICogXHJcbiAgICAgKiAqKkNhbWJpbyBvcmRpbmFtZW50byBzdWwgcHJpbW8gZ3J1cHBvKio6IHJlbG9hZCBjb21wbGV0bywgbm9uIG1pIG9jY3VwbyBkaSByaXB1bGlyZSBnbGkgZWxlbWVudGkgYmluZGF0aSBpbiBhbGN1biBtb2RvXHJcbiAgICAgKiBcclxuICAgICAqICoqQ2FtYmlvIG9yZGluYW1lbnRvIHN1bGxhIGNvbG9ubmEgcmVsYXRpdmEgYWxsJ04tZXNpbW8gZ3J1cHBvKio6IHJlbG9hZCBjb21wbGV0byBkZWwgY29udGVudXRvIGRlbCBncnVwcG8gcHJlY2VkZW50ZSwgcGVyIHF1ZWxsaSBhcGVydGksIGRldm8gcHJlY2VkZW50ZW1lbnRlIHJpcHVsaXJlIFxyXG4gICAgICogdHV0dGkgZ2xpIGVsZW1lbnRpIGNvbiAqKl9ncm91cGxldmVsKiogPSBOXHJcbiAgICAgKiBcclxuICAgICAqICoqQ2FtYmlvIG9yZGluYW1lbnRvIHN1IHVuYSBjb2xvbm5hIG5vbiByYWdncnVwcGF0YSoqOiByZWxvYWQgY29tcGxldG8gcGVyIHR1dHRpIGkgZ3J1cHBpIGZpbmFsaSBhcGVydGksIGRldm8gcHJlY2VkZW50ZW1lbnRlIHJpcHVsaXJlIHR1dHRpIGdsaSBlbGVtZW50aSBjb24gKipfaXRlbSoqID0gdHJ1ZVxyXG4gICAgICogXHJcbiAgICAgKiBcclxuICAgICAqIEFsdHJpIGV2ZW50aSBub24gZG92cmViYmVybyByYXBwcmVzZW50YXJlIHByb2JsZW1pOlxyXG4gICAgICogLSBTZWxlemlvbmU6IG5vbiBjYW1iaWEgbnVsbGFcclxuICAgICAqIC0gUGFnaW5hemlvbmU6IGNhbWJpYSBhIGxpdmVsbG8gcm9vdCBxdWluZGkgdmllbmUgcmljYXJpY2F0byB0dXR0byBjb211bnF1ZSwgc3Rlc3NvIHZhbGUgcGVyIGxlIHBhZ2luYXppb25pIGludGVybmVcclxuICAgICAqIFxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGdyb3VwU2VhcmNoUmVxdWVzdHNDYWNoZTogeyBwYXRoOiBzdHJpbmcsIHZpZXc6IEFwcFNlYXJjaDxhbnk+IH1bXTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFZhcmlhYmlsZSBkJ2FwcG9nZ2lvIHBlciBjYXBpcmUgc2UgYyfDqCBiaXNvZ25vIGRpIHJpLWVmZmV0dHVhcmUgdW5hIHJpY2VyY2EgbyBtZW5vXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgUmVzZWFyY2hOZWVkZWQ6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFZhcmlhYmlsZSBkYSB1c2FyZSBuZWkgXCJjb2xzcGFuXCIgcXVhbmRvIHNpIHZ1b2xlIGRpcmUgXCJUdXR0ZSBsZSBjb2xvbm5lXCIuIDQyIMOoIHVuIG51bWVybyBtYWdpY28gY2hlIG1pIHNlcnZlIHBlciBub24gY2FsY29sYXJlIHF1ZXN0YSB2YXJpYWJpbGUgcXVhbmRvIG1pIHNlcnZlLlxyXG4gICAgICogXHJcbiAgICAgKiBEaSBiYXNlIGRvdnJlYmJlIGVzc2VyZSBsYSBzb21tYSBkZWkgUm93VEggY29uIGwnYWdnaXVudGEgZGkgdHV0dGkgZ2xpIEhlYWRlciBleHRyYSBpbiBiYXNlIGFsbGUgc2l0dWF6aW9uaS4gRGF0byBjaGUgZGl2ZW50YSB1bmEgbG9naWNhIGRlZmljaWVudGUgbWUgbGEgY2F2byBjb3PDrFxyXG4gICAgICogXHJcbiAgICAgKiBTZSBpbiB1bmEgdGFiZWxsYSBjaSBzb25vIG1lbm8gZGkgNDIgY29sb25uZSBpbCBjb2xzcGFuIHNpIGZlcm1hIGNvbXVucXVlIGFsbGEgZmluZSwgc2UgaW52ZWNlIGNlIG5lIHNvbm8gZGkgcGnDuS4uLiBiZWggYmlzb2duYSBhbGx1bmdhcmUgc3RvIG51bWVyb1xyXG4gICAgICogXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBhbGxDb2x1bW5zOiBzdHJpbmcgPSBcIjQyXCI7XHJcblxyXG4gICAgLyoqIEBpZ25vcmUgKi9cclxuICAgIHB1YmxpYyBuZ09uSW5pdCgpIHtcclxuICAgICAgICAvL1BlciBwb3RlciBjYW1iaWFyZSBpbCBsYXlvdXQgaW4gYmFzZSBhbCBsaXZlbGxvIGdlcmFyY2hpY28gaWwgY29tcG9uZW50ZSBkZXZhIGF2ZXJlIGlsIHBpZW5vIGNvbnRyb2xsbyBkaSBvZ25pIGNlbGxhLFxyXG4gICAgICAgIC8vY2hlIGNvbiBzb2xvIGxhIHByb2llemlvbmUgKHNlbnphIGNlbGxlIGN1c290bSkgbm9uIMOoIGRpc3BvbmliaWxlXHJcbiAgICAgICAgaWYgKHRoaXMuSGllcmFyY2h5ICYmICF0aGlzLlVzZUN1c3RvbUNlbGxzKVxyXG4gICAgICAgICAgICB0aHJvdyBcIkVzLXRhYmxlIGVycm9yOiBQZXIgcG90ZXIgdXRpbGl6emFyZSBsJ2VzLXRhYmxlIGNvbiBbSGllcmFyY2h5XT1cXFwidHJ1ZVxcXCIgw6ggcmljaGllc3RvIGFuY2hlIFtVc2VDdXN0b21DZWxsc109XFxcInRydWVcXFwiXCI7XHJcblxyXG4gICAgICAgIC8vIGNsaWNrIGRlc3RybyBzdSB1bmEgcmlnYSBjb24gc2VsZXppb25lIGF0dGl2YTogVGlybyBmdW9yaSBpbCBjb250ZXh0IG1lbnUgZSBzZWxlemlvbmUgbCdlbGVtZW50byBjb3JyZW50ZVxyXG4gICAgICAgIHRoaXMuY3R4TWVudVN1YnNjcmlwdGlvbiA9ICh0aGlzLkNvbnRleHRNZW51IHx8IHRoaXMudGFibGVFbXB0eU1lbnUpLm9wZW4uc3Vic2NyaWJlKHQgPT4ge1xyXG4gICAgICAgICAgICBsZXQgc2hvdWxkRW1pdCA9ICF0Lml0ZW0uX3NlbGVjdGVkO1xyXG5cclxuICAgICAgICAgICAgdC5pdGVtLl9zZWxlY3RlZCA9IHRydWU7XHJcbiAgICAgICAgICAgIHZhciBpdGVtU2VsZWN0aW9uID0gdGhpcy5oYW5kbGVJdGVtc1NlbGVjdGlvbihbdC5pdGVtXSk7XHJcbiAgICAgICAgICAgIHRoaXMuY2hhbmdlZCgpO1xyXG5cclxuICAgICAgICAgICAgaWYgKHNob3VsZEVtaXQpXHJcbiAgICAgICAgICAgICAgICB0aGlzLm9uU2VsZWN0aW9uQ2hhbmdlZC5lbWl0KGl0ZW1TZWxlY3Rpb24pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBAaWdub3JlICovXHJcbiAgICBwdWJsaWMgbmdBZnRlclZpZXdJbml0KCkge1xyXG4gICAgICAgIC8vIFNlIHV0aWxpenpvIGxhIG5ldyBzcGljeSBtb2RlIGRlZHVjbyB0dXR0aSBpIHBhcmFtZXRyaSBkaSBsYXZvcm8gcG9zc2liaWxpIGFsIGNhcmljYW1lbnRvIGRlbGxhIHRhYmVsbGFcclxuICAgICAgICAvLyBWZW5nb25vIHNvdnJhc2NyaXR0ZSBzb2xvIGxlIHByb3ByaWV0w6Agbm9uIGltcG9zdGF0ZSBkYWxsJ3V0ZW50ZVxyXG4gICAgICAgIGlmICh0aGlzLkVzVGRzRGlyZWN0aXZlICYmIHRoaXMuRXNUZHNEaXJlY3RpdmUubGVuZ3RoID4gMCAmJiB0aGlzLkVzVGhzRGlyZWN0aXZlICYmIHRoaXMuRXNUaHNEaXJlY3RpdmUubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5Vc2VDdXN0b21DZWxscyA9PSBudWxsKSB0aGlzLlVzZUN1c3RvbUNlbGxzID0gdHJ1ZTtcclxuICAgICAgICAgICAgaWYgKHRoaXMuSGlkZGVuQ29sdW1ucyA9PSBudWxsICYmIHRoaXMuVXNlQ3VzdG9tQ2VsbHMpIHRoaXMuSGlkZGVuQ29sdW1ucyA9IHRydWU7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLkNvbHVtbnNPcmRlcmluZyA9PSBudWxsICYmIHRoaXMuVXNlQ3VzdG9tQ2VsbHMpIHRoaXMuQ29sdW1uc09yZGVyaW5nID0gdHJ1ZTtcclxuICAgICAgICAgICAgaWYgKHRoaXMuT3JkZXJCeUNvbHVtbiA9PSBudWxsICYmIHRoaXMuVXNlQ3VzdG9tQ2VsbHMpIHRoaXMuT3JkZXJCeUNvbHVtbiA9IHRydWU7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLlNlbGVjdEFsbCA9PSBudWxsICYmIHRoaXMuU2VsZWN0aW9uKSB0aGlzLlNlbGVjdEFsbCA9IHRydWU7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLlNoaWZ0Q2xpY2sgPT0gbnVsbCAmJiB0aGlzLlNlbGVjdGlvbikgdGhpcy5TaGlmdENsaWNrID0gdHJ1ZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBpZ25vcmUgKi9cclxuICAgIHB1YmxpYyBuZ09uRGVzdHJveSgpIHtcclxuICAgICAgICBpZiAodGhpcy5jdHhNZW51U3Vic2NyaXB0aW9uKVxyXG4gICAgICAgICAgICB0aGlzLmN0eE1lbnVTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogQGlnbm9yZSAqL1xyXG4gICAgcHVibGljIGFzeW5jIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcclxuICAgICAgICBsZXQgbmV3U2VhcmNoVmlldyA9IGNoYW5nZXNbJ1NlYXJjaFZpZXcnXTtcclxuICAgICAgICBpZiAobmV3U2VhcmNoVmlldyAmJiB0aGlzLlNlYXJjaFZpZXcpXHJcbiAgICAgICAgICAgIHRoaXMuYXJyYXlQdWxzYW50aSA9IHRoaXMuZ2V0UGFnZXNBcnJheSg2LCB0aGlzLlNlYXJjaFZpZXcucGFnZSwgdGhpcy5TZWFyY2hWaWV3LnBhZ2VzIHx8IDEpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vICNyZWdpb24gSW1wbGVtZW50YXppb25lIENvbnRyb2xWYWx1ZUFjY2Vzc29yIGlnbm9yYWJpbGVcclxuXHJcbiAgICAvKiogQGlnbm9yZSAqL1xyXG4gICAgcHVibGljIHJlZ2lzdGVyT25DaGFuZ2UoZm4pOiB2b2lkIHsgdGhpcy5wcm9wYWdhdGVDaGFuZ2UgPSBmbjsgfVxyXG4gICAgLyoqIEBpZ25vcmUgKi9cclxuICAgIHB1YmxpYyByZWdpc3Rlck9uVG91Y2hlZChmbik6IHZvaWQgeyB9XHJcbiAgICAvKiogQGlnbm9yZSAqL1xyXG4gICAgY2hhbmdlZCgpIHsgdGhpcy5wcm9wYWdhdGVDaGFuZ2UodGhpcy5WaWV3KTsgfVxyXG4gICAgLyoqIEBpZ25vcmUgKi9cclxuICAgIHByb3BhZ2F0ZUNoYW5nZSA9IChfOiBhbnkpID0+IHsgfTtcclxuXHJcbiAgICAvLyAjZW5kcmVnaW9uXHJcblxyXG4gICAgLyoqIEBpZ25vcmUgKi9cclxuICAgIHB1YmxpYyB3cml0ZVZhbHVlKG9iaik6IHZvaWQge1xyXG4gICAgICAgIHRoaXMuVmlldyA9IG9iaiA/IG9iaiA6IG51bGw7XHJcblxyXG4gICAgICAgIC8vIE1pIMOoIGFycml2YXRhIGwnQXBwU2VhcmNoIHF1aW5kaSBkaSBzaWN1cm8gbm9uIGhvIHVuYSByaWNlcmNhIGluIHByb2dyZXNzXHJcbiAgICAgICAgdGhpcy5yZXNlYXJjaEluUHJvZ3Jlc3MgPSBmYWxzZTtcclxuXHJcbiAgICAgICAgaWYgKCF0aGlzLlZpZXcgJiYgIXRoaXMuU2VhcmNoVmlldykge1xyXG4gICAgICAgICAgICAvLyBTdSB2aWV3IG51bGxhIGV2aXRvIGRpIGZhcmUgcHJlc3NvY2jDqSBxdWFsc2lhc2kgY29zYS4gU2UgYXJyaXZhIHVuIG51bGwgZGV2byBhbmNoZSBhc3NpY3VyYXJtaSBkaSBub24gbW9zdHJhcmUgbnVsbGFcclxuICAgICAgICAgICAgdGhpcy5ib3VuZFNvdXJjZSA9IHRoaXMuVE1QQm91bmRTb3VyY2UgfHwgW107XHJcblxyXG4gICAgICAgICAgICAvLyBQZXIgZXNzZXJlIHNpY3VybyBjaGUgZG9wbyB1biBiaW5kIGRpIG9nZ2V0dGkgbGEgZXMtdGFibGUgYWdnaW9ybmkgbGEgZ3JhZmljYVxyXG4gICAgICAgICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gU2UgcGVyIHNiYWdsaW8gbCdvZ2dldHRvIGNoZSBtaSBhcnJpdmEgbm9uIMOoIHRpcGl6emF0byAoaW5zdGFuY2VvZiBBcHBTZWFyY2ggcmVzdGl0dWlzY2UgZmFsc2UgYW5jaGUgc2Ugw6ggZGVsIHRpcG8gZ2l1c3RvKVxyXG4gICAgICAgIC8vIGxvIGNvcnJlZ2dvLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuICAgICAgICBpZiAodGhpcy5WaWV3ICYmIHR5cGVvZiAodGhpcy5WaWV3IGFzIGFueSkucmVzdWx0ICE9ICd1bmRlZmluZWQnICYmICEodGhpcy5WaWV3IGluc3RhbmNlb2YgUmVwb3J0RGVmaW5pdGlvbikpIHtcclxuICAgICAgICAgICAgKHRoaXMuVmlldyBhcyBhbnkpLl9fcHJvdG9fXyA9IG5ldyBSZXBvcnREZWZpbml0aW9uKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2UgaWYgKHRoaXMuVmlldyAmJiB0eXBlb2YgKHRoaXMuVmlldyBhcyBhbnkpLml0ZW1zcGVycGFnZW92ZXJyaWRlICE9ICd1bmRlZmluZWQnICYmICEodGhpcy5WaWV3IGluc3RhbmNlb2YgQXBwU2VhcmNoKSkge1xyXG4gICAgICAgICAgICAodGhpcy5WaWV3IGFzIGFueSkuX19wcm90b19fID0gbmV3IEFwcFNlYXJjaCgpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIGlmICh0aGlzLlNlYXJjaFZpZXcgJiYgdHlwZW9mICh0aGlzLlNlYXJjaFZpZXcgYXMgYW55KS5pdGVtc3BlcnBhZ2VvdmVycmlkZSAhPSAndW5kZWZpbmVkJyAmJiAhKHRoaXMuU2VhcmNoVmlldyBpbnN0YW5jZW9mIEFwcFNlYXJjaCkpIHtcclxuICAgICAgICAgICAgKHRoaXMuU2VhcmNoVmlldyBhcyBhbnkpLl9fcHJvdG9fXyA9IG5ldyBBcHBTZWFyY2goKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuICAgICAgICBpZiAodGhpcy5WaWV3ICYmIHRoaXMuVmlldyBpbnN0YW5jZW9mIFJlcG9ydERlZmluaXRpb24pIHtcclxuICAgICAgICAgICAgLy8gU2UgbWkgYXJyaXZhIHVuYSByZXBvcnQgZGVmaW5pdGlvbiB2dW9sIGRpcmUgY2hlIHBvdHJlaSBhdmVyZSBkZWkgcmlzdWx0YXRpIGRhIHZpc3VhbGl6emFyZVxyXG4gICAgICAgICAgICB0aGlzLnNldE1vZGUoJ3JlcG9ydCcpO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5SZXBvcnRWYWx1ZXMgPSB0aGlzLlZpZXcucmVzdWx0O1xyXG4gICAgICAgICAgICBpZiAodGhpcy5SZXBvcnRWYWx1ZXMpXHJcbiAgICAgICAgICAgICAgICB0aGlzLnJldmlld1JlcG9ydEJpbmRpbmdzKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2UgaWYgKHRoaXMuVmlldyAmJiB0aGlzLlZpZXcgaW5zdGFuY2VvZiBBcHBTZWFyY2gpIHtcclxuICAgICAgICAgICAgLy8gU2UgY2FtYmlhIGwnb2dnZXR0byBpbnRlcm8gc2lnbmlmaWNhIGNoZSBobyByaW1hbmRhdG8gbGEgcmljZXJjYVxyXG4gICAgICAgICAgICB0aGlzLnNldE1vZGUoJ3ZpZXcnKTtcclxuXHJcbiAgICAgICAgICAgIC8vIFNlIHZlbmdvIGRhIHVuYSByaWNlcmNhIGludGVybmEgbWFudGVuZ28gbG8gc3RhdG8gZGkgc2VsZXppb25lIHByZWNlZGVudGUgKHF1aW5kaSBzdSBjYW1iaW8gcGFnaW5hLCBjYW1iaW8gaXBwLCBlY2MuLi4pXHJcbiAgICAgICAgICAgIC8vIHNlIGludmVjZSBsJ3V0ZW50ZSBoYSBmYXR0byB1bmEgcmljZXJjYSBsdWkgKHF1aW5kaSBjYW1iaWFuZG8gZmlsdHJpKSwgc2VjY28gbGUgaW5mbyBkaSBzZWxlemlvbmVcclxuICAgICAgICAgICAgaWYgKCF0aGlzLlZpZXcuc2VsZWN0aW9uIHx8ICF0aGlzLlZpZXcuaW50ZXJuYWxzZWFyY2hyZXF1ZXN0IHx8ICF0aGlzLlVzZVNlbGVjdGlvbkNhY2hlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnNlbE9yRGVzZWxDYWNoZSA9IHt9O1xyXG4gICAgICAgICAgICAgICAgdGhpcy5WaWV3LnNlbGVjdGlvbiA9IG5ldyBJdGVtc1NlbGVjdGlvbihbXSk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLm9uU2VsZWN0aW9uQ2hhbmdlZC5lbWl0KHRoaXMuVmlldy5zZWxlY3Rpb24pO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICB0aGlzLlZpZXcuaW50ZXJuYWxzZWFyY2hyZXF1ZXN0ID0gZmFsc2U7XHJcblxyXG4gICAgICAgICAgICAvLyBSZWN1cGVybyBQcmVmZXJlbmNlXHJcbiAgICAgICAgICAgIGlmICh0aGlzLlNhdmVQcmVmZXJlbmNlcykge1xyXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLm5nQ29udHJvbC5uYW1lKVxyXG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJOb24gcG9zc28gdXRpbGl6emFyZSBsZSBwcmVmZXJlbmNlIHNlbnphIGF2ZXJlIHVuICduYW1lJyBwZXIgcXVlc3RhIHRhYmVsbGFcIik7XHJcbiAgICAgICAgICAgICAgICBlbHNlIGlmICghdGhpcy5wcmVmU2VydmljZSlcclxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiTm9uIHBvc3NvIHV0aWxpenphcmUgbGUgcHJlZmVyZW5jZSBzZW56YSBjaGUgaWwgcGFjY2hldHRvIEBlc2ZhZW56YS9wcmVmZXJlbmNlcyBzaWEgaW5zdGFsbGF0b1wiKTtcclxuICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmVmcyA9IHRoaXMucHJlZlNlcnZpY2UucmV0cmlldmU8eyBjb2x1bW5zOiBzdHJpbmdbXSwgY29sdW1uX29yZGVyaW5nOiBzdHJpbmdbXSB9Pig8c3RyaW5nPnRoaXMubmdDb250cm9sLm5hbWUpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcmVmcykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLlZpZXcuY29sdW1ucyA9IHByZWZzLmNvbHVtbnM7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuVmlldy5jb2x1bW5fb3JkZXJpbmcgPSBwcmVmcy5jb2x1bW5fb3JkZXJpbmc7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICB0aGlzLmFycmF5UHVsc2FudGkgPSB0aGlzLmdldFBhZ2VzQXJyYXkoNiwgdGhpcy5WaWV3LnBhZ2UsIHRoaXMuVmlldy5wYWdlcyB8fCAxKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAodGhpcy5WaWV3ICYmICh0aGlzLlZpZXcubGVuZ3RoICE9IG51bGwgJiYgdGhpcy5WaWV3Lmxlbmd0aCAhPSB1bmRlZmluZWQpKSB7XHJcbiAgICAgICAgICAgIHRoaXMuc2V0TW9kZSgnYXJyYXknKTtcclxuXHJcbiAgICAgICAgICAgIGlmICghdGhpcy5Vc2VTZWxlY3Rpb25DYWNoZSB8fCAhdGhpcy5hcnJheW1vZGVTZWxlY3Rpb24pIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuc2VsT3JEZXNlbENhY2hlID0ge307XHJcbiAgICAgICAgICAgICAgICB0aGlzLmFycmF5bW9kZVNlbGVjdGlvbiA9IG5ldyBJdGVtc1NlbGVjdGlvbihbXSk7O1xyXG4gICAgICAgICAgICAgICAgdGhpcy5vblNlbGVjdGlvbkNoYW5nZWQuZW1pdCh0aGlzLmFycmF5bW9kZVNlbGVjdGlvbik7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLlNlYXJjaFZpZXcpXHJcbiAgICAgICAgICAgICAgICB0aGlzLmFycmF5UHVsc2FudGkgPSB0aGlzLmdldFBhZ2VzQXJyYXkoNiwgdGhpcy5TZWFyY2hWaWV3LnBhZ2UsIHRoaXMuU2VhcmNoVmlldy5wYWdlcyB8fCAxKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0aGlzLlZpZXcgJiYgISh0aGlzLlZpZXcgaW5zdGFuY2VvZiBSZXBvcnREZWZpbml0aW9uKSkge1xyXG4gICAgICAgICAgICAvKlxyXG4gICAgICAgICAgICAgKlVzbyBsYSB0ZWNuaWNhIGRpIEVuZGxlc3NTY3JvbGwgc2UgbGEgdmFyaWFiaWxlIHJlbGF0aXZhIMOoIGF0dGl2YSBlIHNlXHJcbiAgICAgICAgICAgICAqIDEpIEhvIHVuIEFycmF5LCBvcHB1cmVcclxuICAgICAgICAgICAgICogMikgSG8gdW4gQXBwU2VhcmNoIGNoZSBzdGEgY2VyY2FuZG8gY29uIHBhZ2luYXppb25lIFwiVHV0dG9cIiwgb3BwdXJlXHJcbiAgICAgICAgICAgICAqIDMpIEhvIHVuIEFwcFNlYXJjaCBjaGUgc3RhIGNlcmNhbmRvIGNvbiBwYWdpbmF6aW9uZSBkaXZlcnNhIGRhIFwiVHV0dG9cIiBtYSBjb24gbGEgdmFyaWFiaWxlIEVuZGxlc3NTY3JvbGxPbmx5Rm9yQWxsIGEgZmFsc2VcclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGxldCB2aWV3Q2FzdGVkID0gdGhpcy5WaWV3IGFzIEFwcFNlYXJjaDxhbnk+O1xyXG4gICAgICAgICAgICBsZXQgaGFzUm93R3JvdXBzID0gdmlld0Nhc3RlZC5ncm91cGluZ3MgJiYgdmlld0Nhc3RlZC5ncm91cGluZ3MuZmlsdGVyKHQgPT4gIXQuYWdncmVnYXRpb24pLmxlbmd0aCA+IDA7XHJcbiAgICAgICAgICAgIGxldCBpc0FwcFNlYXJjaFdpdGhJcHBNYXggPSB0aGlzLnZpZXdNb2RlICYmIHZpZXdDYXN0ZWQuaXRlbXNwZXJwYWdlb3ZlcnJpZGUgPT0gdGhpcy5kZWZhdWx0QWxsUGFnZU92ZXJyaWRlO1xyXG4gICAgICAgICAgICBsZXQgaXNBcHBTZWFyY2hOb01heElwcCA9IHRoaXMudmlld01vZGUgJiYgdmlld0Nhc3RlZC5pdGVtc3BlcnBhZ2VvdmVycmlkZSAhPSB0aGlzLmRlZmF1bHRBbGxQYWdlT3ZlcnJpZGU7XHJcbiAgICAgICAgICAgIHRoaXMuVXNlRW5kbGVzc3Njcm9sbCA9IHRoaXMuRW5kbGVzc1Njcm9sbCAmJiAodGhpcy5hcnJheU1vZGUgfHwgaXNBcHBTZWFyY2hXaXRoSXBwTWF4IHx8IChpc0FwcFNlYXJjaE5vTWF4SXBwICYmICF0aGlzLkVuZGxlc3NTY3JvbGxPbmx5Rm9yQWxsKSk7XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5Vc2VFbmRsZXNzc2Nyb2xsICYmICFoYXNSb3dHcm91cHMpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuYWRkZWRTbGljZXMgPSBbXTtcclxuICAgICAgICAgICAgICAgIHRoaXMuYm91bmRTdWJTb3VyY2VzID0gdGhpcy5nZXRJdGVtU2xpY2VzKCk7XHJcblxyXG4gICAgICAgICAgICAgICAgdGhpcy5UTVBCb3VuZFNvdXJjZSA9IHRoaXMuYm91bmRTdWJTb3VyY2VzWzBdID8gdGhpcy5ib3VuZFN1YlNvdXJjZXNbMF0gOiBbXTtcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmJvdW5kU3ViU291cmNlc1swXSlcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZGVkU2xpY2VzLnB1c2goMCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgdGhpcy5UTVBCb3VuZFNvdXJjZSA9IHRoaXMuZ2V0SXRlbXNCeU1vZGUoZmFsc2UsICF0aGlzLmludGVybmFsV3JpdGVDYWxsKTtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLkhpZXJhcmNoeSAmJiAhaGFzUm93R3JvdXBzKVxyXG4gICAgICAgICAgICAgICAgdGhpcy5hc3NpZ25IaWVyYXJjaHlMZXZlbHModGhpcy5UTVBCb3VuZFNvdXJjZSk7XHJcblxyXG4gICAgICAgICAgICB0aGlzLmNhbGN1bGF0ZUhhc2godGhpcy5UTVBCb3VuZFNvdXJjZSk7XHJcblxyXG4gICAgICAgICAgICAvLyBBc3NlZ25vIGEgdW5hIHZhcmlhYmlsZSBtaWEgbCdldmVudHVhbGUgb3ZlcnJpZGUgcGVyIGxhIGNsYXNzZSBkZWxsYSByaWdhXHJcbiAgICAgICAgICAgIC8vIFNlIHBvaSBzb25vIGluIG1vZGFsaXTDoCBnZXJhcmNoaWNhIGluaWV0dG8gYW5jaGUgbGEgY2xhc3NlIHBlciBsYSBjb25maWd1cmF6aW9uZSBkZWwgbGl2ZWxsbyBkZWxsYSByaWdhXHJcbiAgICAgICAgICAgIGlmICgodGhpcy5UTVBCb3VuZFNvdXJjZSAmJiB0aGlzLlJvd0NsYXNzQXNzaWduZXIpIHx8IHRoaXMuSGllcmFyY2h5KSB7XHJcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuVE1QQm91bmRTb3VyY2UubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgaXRlbSA9IHRoaXMuVE1QQm91bmRTb3VyY2VbaV07XHJcbiAgICAgICAgICAgICAgICAgICAgaXRlbS5fcm93Q2xhc3MgPSB0aGlzLlJvd0NsYXNzQXNzaWduZXIgPyB0aGlzLlJvd0NsYXNzQXNzaWduZXIoaXRlbSkgOiBcIlwiO1xyXG4gICAgICAgICAgICAgICAgICAgIGl0ZW0uX3Jvd0NsYXNzICs9IHRoaXMuSGllcmFyY2h5ID8gXCIgZXN0LXJvdy1sdmwtXCIgKyBpdGVtLmxldmVsIDogXCJcIjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5wb3N0Qm91bmRTb3VyY2VDYWxjdWxhdGlvbigpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vICNyZWdpb24gR2VzdGlvbmUgcmV0cmlldmUgZGVnbGkgb2dnZXR0aSBkYSBtb3N0cmFyZSBpbiB0YWJlbGxhLCBjb25zaWRlcmFuZG8gZXZlbnR1YWxpIEVuZGxlc3MgU2Nyb2xsc1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSW4gYmFzZSBhbGxhIG1vZGFsaXTDoCBzcGVjaWZpY2F0YSAoQXJyYXlNb2RlLCBWaWV3TW9kZSwgZWNjLi4uKSBxdWVzdG8gbWV0b2RvIHJlY3VwZXJhIGwnYXJyYXkgZGkgb2dnZXR0aSBkYSBiaW5kYXJlIGFkIGludGVyZmFjY2lhXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvbmx5c2VsZWN0ZWQgW2ZhbHNlXSBJbmRpY2EgZGkgcHJlbmRlcmUgc29sbyBnbGkgb2dnZXR0aSBzZWxlemlvbmF0aVxyXG4gICAgICogQHBhcmFtIHtib29sZWFufSByZWZyZXNoUGFnaW5nIFtmYWxzZV0gSW5kaWNhIHNlIGFnZ2lvcm5hcmUgbGUgaW5mb3JtYXppb25pIGRpIHBhZ2luYXppb25lIG8gbWVub1xyXG4gICAgICogQHBhcmFtIHtib29sZWFufSBhbGxJZlBvc3NpYmxlIFtmYWxzZV0gSW5kaWNhIHNlIHByZW5kZXJlIHR1dHRpIGdsaSBvZ2dldHRpIHF1YW9yYSBwb3NzaWJpbGUsIHVzYXRvIHNvbG8gaW4gQXJyYXlNb2RlXHJcbiAgICAgKlxyXG4gICAgICogQHJldHVybnMge2FueVtdfSBMaXN0YSBkZWdsaSBvZ2dldHRpIHN1IGN1aSBlZmZldHR1YXJlIGlsIGJpbmQgbGF0byBpbnRlcmZhY2NpYVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGdldEl0ZW1zQnlNb2RlKG9ubHlzZWxlY3RlZDogYm9vbGVhbiA9IGZhbHNlLCByZWZyZXNoUGFnaW5nOiBib29sZWFuID0gZmFsc2UsIGFsbElmUG9zc2libGU6IGJvb2xlYW4gPSBmYWxzZSk6IGFueVtdIHtcclxuICAgICAgICBsZXQgaXRlbXM6IGFueVtdID0gW107XHJcblxyXG4gICAgICAgIGlmICgodGhpcy52aWV3TW9kZSAmJiB0aGlzLlZpZXcgaW5zdGFuY2VvZiBBcHBTZWFyY2gpKSB7XHJcbiAgICAgICAgICAgIGl0ZW1zID0gdGhpcy5nZXRWaWV3SXRlbXNCeVNvdXJjZSgpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIGlmICh0aGlzLmFycmF5TW9kZSkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5Vc2VBcnJheU1vZGVQYWdpbmcgJiYgIWFsbElmUG9zc2libGUpIHtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBTZSBzb25vIGluIG1vZGFsaXTDoCBhcnJheSBtYSBsYSByaWNlcmNhIGRpcGVuZGUgZGEgdW5hIHZpZXcgZGV2byByaWFsbGluZWFyZSBnbGkgaXRlbXBlcnBhZ2VcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLlNlYXJjaFZpZXcpXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5BcnJheW1vZGVJdGVtc1BlclBhZ2UgPSB0aGlzLlNlYXJjaFZpZXcuaXRlbXNwZXJwYWdlb3ZlcnJpZGU7XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gRGV2byBjaGlhbWFyZSBpbCByZWZyZXNoIHBhZ2Ugc29sbyBzZSB2ZW5nbyByaWNoaWFtYXRvIGRhIHVuIGJpbmRpbmcgZXN0ZXJub1xyXG4gICAgICAgICAgICAgICAgaWYgKHJlZnJlc2hQYWdpbmcpXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWZyZXNoUGFnaW5nKHRoaXMuQXJyYXltb2RlSXRlbXNQZXJQYWdlKTtcclxuXHJcbiAgICAgICAgICAgICAgICBpdGVtcyA9IHRoaXMuYWRhcHRWaWV3VG9QYWdpbmcoKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGl0ZW1zID0gdGhpcy5WaWV3IGFzIGFueVtdO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBTZSB2b2dsaW8gc29sbyBpIHNlbGV6aW9uYXRpIGZpbHRyb1xyXG4gICAgICAgIGlmIChvbmx5c2VsZWN0ZWQpXHJcbiAgICAgICAgICAgIHJldHVybiBpdGVtcy5maWx0ZXIodCA9PiB0Ll9zZWxlY3RlZCk7XHJcblxyXG4gICAgICAgIHJldHVybiBpdGVtcztcclxuICAgIH1cclxuXHJcbiAgICAvKiogQGlnbm9yZSAqL1xyXG4gICAgcHJpdmF0ZSBnZXRWaWV3SXRlbXNCeVNvdXJjZSgpOiBhbnlbXSB7XHJcbiAgICAgICAgbGV0IGNhc3RlZFZpZXcgPSB0aGlzLlZpZXcgYXMgQXBwU2VhcmNoPGFueT47XHJcbiAgICAgICAgbGV0IGdyb3VwS2V5cyA9IGNhc3RlZFZpZXcuZ3JvdXBpbmdzID8gY2FzdGVkVmlldy5ncm91cGluZ3MuZmlsdGVyKHQgPT4gIXQuYWdncmVnYXRpb24pLmxlbmd0aCA6IDA7XHJcblxyXG4gICAgICAgIC8vR3J1cHBpIGludGVybWVkaVxyXG4gICAgICAgIGlmICgoY2FzdGVkVmlldy5yZXF1ZXN0ZWRncm91cHM/Lmxlbmd0aCAhPSBncm91cEtleXMgfHwgY2FzdGVkVmlldy5yZXF1ZXN0ZWRncm91cHM/Lmxlbmd0aCA9PSAwKSAmJiBncm91cEtleXMgPiAwKSB7XHJcbiAgICAgICAgICAgIGxldCByZXQgPSBjYXN0ZWRWaWV3Lmdyb3VwcztcclxuICAgICAgICAgICAgLy8gU2V0dG8gdmFyaWFiaWxlIGludGVybmEgcGVyIGNhcGlyZSBjaGUgcXVlc3RvIMOoIGluIHJlYWx0w6AgdW4gZ3J1cHBvXHJcbiAgICAgICAgICAgIHJldC5mb3JFYWNoKGl0bSA9PiB7ICg8YW55Pml0bSkuX2dyb3VwID0gdHJ1ZTsgfSk7XHJcbiAgICAgICAgICAgIHJldHVybiByZXQ7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICBsZXQgcmV0ID0gdGhpcy5TZWNvbmRhcnlTb3VyY2UgPyAodGhpcy5WaWV3IGFzIGFueSkuaXRlbXMyIDogdGhpcy5UZXJ0aWFyeVNvdXJjZSA/ICh0aGlzLlZpZXcgYXMgYW55KS5pdGVtczMgOiAodGhpcy5WaWV3IGFzIGFueSkuaXRlbXM7XHJcbiAgICAgICAgICAgIC8vIFNldHRvIHZhcmlhYmlsZSBpbnRlcm5hIHBlciBzcGVjaWZpY2FyZSBjaGUgcXVlc3RvIMOoIHVuIGVsZW1lbnRvIG5vcm1hbGUsIG5vbiB1biBncnVwcG8gbyBhbHRyb1xyXG4gICAgICAgICAgICByZXQuZm9yRWFjaChpdG0gPT4geyAoPGFueT5pdG0pLl9pdGVtID0gdHJ1ZTsgfSk7XHJcbiAgICAgICAgICAgIHJldHVybiByZXQ7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTWV0b2RvIGNoZSBwcmVuZGUgdHV0dGkgZ2xpIG9nZ2V0dGkgZGkgY3VpIGRpc3BvbmUgZGl2aXNpIGluIGJ1Y2tldCBkYSAxMDAgZWxlbWVudGlcclxuICAgICAqXHJcbiAgICAgKiBAcmV0dXJucyB7YW55W11bXX0gTWF0cmljZSBkaSBhcnJheSBOeDEwMFxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGdldEl0ZW1TbGljZXMoKTogYW55W11bXSB7XHJcbiAgICAgICAgLy8gU2Ugc29ubyBxdWkgZGkgc2ljdXJvIG5vbiBobyByb3dncm91cGluZ1xyXG4gICAgICAgIGxldCBpdGVtcyA9IHRoaXMuZ2V0SXRlbXNCeU1vZGUoKTtcclxuICAgICAgICBpZiAoIWl0ZW1zKVxyXG4gICAgICAgICAgICByZXR1cm4gW107XHJcbiAgICAgICAgbGV0IGFycmF5QnkxMDAgPSBbXTtcclxuXHJcbiAgICAgICAgbGV0IHNsaWNlcyA9IE1hdGguY2VpbChpdGVtcy5sZW5ndGggLyB0aGlzLlNsaWNlU2l6ZSk7XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbGljZXM7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgYXJyYXlTbGljZSA9IGl0ZW1zLnNsaWNlKGkgKiB0aGlzLlNsaWNlU2l6ZSwgaSAqIHRoaXMuU2xpY2VTaXplICsgdGhpcy5TbGljZVNpemUpO1xyXG4gICAgICAgICAgICBhcnJheUJ5MTAwLnB1c2goYXJyYXlTbGljZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBhcnJheUJ5MTAwO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTWV0b2RvIGNoZSBnZXN0aXNjZSBsJ2VuZGxlc3Mgc2Nyb2xsIGUgaW4gYmFzZSBhIHF1YW50byBsYSB0YWJlbGxhIMOoIHN0YXRhIHNjcm9sbGF0YSBhZ2dpdW5nZSBkZWdsaSBlbGVtZW50aSBleHRyYSBhICoqVE1QQm91bmRTb3VyY2UqKlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7YW55fSBlIEV2ZW50byBkaSBzY3JvbGwgZGVsIGJyb3dzZXJcclxuICAgICAqL1xyXG4gICAgcHVibGljIG9uU2Nyb2xsKGU6IGFueSkge1xyXG4gICAgICAgIGxldCB0YWJsZVZpZXdIZWlnaHQgPSBlLnRhcmdldC5vZmZzZXRIZWlnaHQ7XHJcbiAgICAgICAgbGV0IHRhYmxlU2Nyb2xsSGVpZ2h0ID0gZS50YXJnZXQuc2Nyb2xsSGVpZ2h0O1xyXG4gICAgICAgIGxldCBzY3JvbGxMb2NhdGlvbiA9IGUudGFyZ2V0LnNjcm9sbFRvcDtcclxuICAgICAgICBsZXQgYnVmZmVyID0gMjAwO1xyXG5cclxuICAgICAgICBsZXQgbGltaXQgPSB0YWJsZVNjcm9sbEhlaWdodCAtIHRhYmxlVmlld0hlaWdodCAtIGJ1ZmZlcjtcclxuICAgICAgICBpZiAoc2Nyb2xsTG9jYXRpb24gPiBsaW1pdCkge1xyXG4gICAgICAgICAgICBsZXQgaW5kZXhUb0FkZCA9IE1hdGguZmxvb3IodGhpcy5UTVBCb3VuZFNvdXJjZS5sZW5ndGggLyAxMDApO1xyXG4gICAgICAgICAgICBpZiAodGhpcy5ib3VuZFN1YlNvdXJjZXNbaW5kZXhUb0FkZF0gJiYgdGhpcy5hZGRlZFNsaWNlcy5pbmRleE9mKGluZGV4VG9BZGQpID09IC0xKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBEZXZvIHJpY29yZGFybWkgZGkgZmFyZSBsJ2hhc2ggZGVsIG51b3ZvIHBlenpvXHJcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGN1bGF0ZUhhc2godGhpcy5ib3VuZFN1YlNvdXJjZXNbaW5kZXhUb0FkZF0pO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5UTVBCb3VuZFNvdXJjZSA9IHRoaXMuVE1QQm91bmRTb3VyY2UuY29uY2F0KHRoaXMuYm91bmRTdWJTb3VyY2VzW2luZGV4VG9BZGRdKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuYWRkZWRTbGljZXMucHVzaChpbmRleFRvQWRkKTtcclxuXHJcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHsgdGhpcy5wb3N0Qm91bmRTb3VyY2VDYWxjdWxhdGlvbigpOyB9KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyAjZW5kcmVnaW9uXHJcblxyXG4gICAgLy8gI3JlZ2lvbiBHZXN0aW9uZSBkaSB0dXR0byBpbCBjaWNsbyBkaSB2aXRhIHBvc3QgYmluZGluZyBvZ2dldHRpXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBNZXRvZG8gbGFuY2lhdG8gZG9wbyBjaGUgbGEgc29yZ2VudGUgZGF0aSDDqCBzdGF0YSBjb3JyZXR0YW1lbnRlIGJpbmRhdGEsIHNpIG9jY3VwYSBkaSByaWNhbGNvbGFyZSB0dXR0byBjacOyIGNoZSBzZXJ2ZVxyXG4gICAgICogYWxsJ2VzLXRhYmxlIHBlciByZW5kZXJpenphcmUgaSB2YWxvcmkgZGEgbW9zdHJhcmVcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBwb3N0Qm91bmRTb3VyY2VDYWxjdWxhdGlvbigpIHtcclxuICAgICAgICAvLyBSZXNldHRvIHR1dHRvIHRyYW5uZSBSb3dURHMgZSBSb3dUSHMgcGVyIGV2aXRhcmUgZmxpY2tlcmluZy4gUm93VERzIGUgUm93VEhzIHNhcmFubm8gbW9kaWZpY2F0ZSBhbGwnaW50ZXJubyBkZWwgcHJvc3NpbW8gY2ljbG8gZGkgQ0RcclxuICAgICAgICB0aGlzLlJvd0NvbnRleHRzID0gW107XHJcbiAgICAgICAgdGhpcy5PcmRlckRpcmVjdGl2ZXMgPSBbXTtcclxuICAgICAgICB0aGlzLmxhc3RTZWxlY3RlZEl0ZW1JRCA9IG51bGw7XHJcblxyXG4gICAgICAgIC8vIFNldCB0aW1lb3V0IGUgYmFzdGEgZnVuemlvbmVyZWJiZSBwZXIgbGEgbW9kYWxpdMOgIEpJVCwgbWEgcGVyIEFPVCBzZXJ2b25vIHNpYSBxdWVsbG8gY2hlIGRldGVjdENoYW5nZXNcclxuICAgICAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICAgIC8vIFNlIG5vbiBobyBjb2xvbm5lIGRpbmFtaWNoZSBtYSBzb25vIGluIG1vZGFsaXTDoCBkaW5hbWljYSAobG8gY2FwaXNjbyBwZXJjaMOpIGMnw6ggdW5hIHZpZXcgcGllbmEgZGkgZ2VuZXJpY2l0ZW0pIG1ldHRvIGlsIGRlZmF1bHQgZGVsbGUgY29sb25uZVxyXG4gICAgICAgICAgICB0aGlzLmV2ZW50dWFsbHlSZXZpZXdEeW5hbWljQ29sdW1ucygpO1xyXG4gICAgICAgICAgICB0aGlzLmJpbmREaXNwbGF5VG9Mb2FkZWRJdGVtc09yR3JvdXBzKCk7XHJcblxyXG4gICAgICAgICAgICAvLyBNb2x0ZSBjb3NlIHNvbm8gb3Z2aWFtZW50ZSBkaXNwb25pYmlsaSBzb2xvIGluIG1vZGFsaXTDoCBWaWV3XHJcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZXdNb2RlICYmIHRoaXMuVXNlQ3VzdG9tQ2VsbHMpIHtcclxuICAgICAgICAgICAgICAgIGxldCB2aWV3ID0gdGhpcy5WaWV3IGFzIEFwcFNlYXJjaDxhbnk+O1xyXG4gICAgICAgICAgICAgICAgbGV0IHRocyA9IHRoaXMuRXNUaHMgJiYgdGhpcy5Fc1Rocy5sZW5ndGggPiAwID8gdGhpcy5Fc1Rocy50b0FycmF5KCkgOiB0aGlzLkVzVGhzRGlyZWN0aXZlICYmIHRoaXMuRXNUaHNEaXJlY3RpdmUubGVuZ3RoID4gMCA/dGhpcy5Fc1Roc0RpcmVjdGl2ZS50b0FycmF5KCkgOiBbXTtcclxuICAgICAgICAgICAgICAgIGxldCB0ZHMgPSB0aGlzLkVzVGRzICYmIHRoaXMuRXNUZHMubGVuZ3RoID4gMCA/IHRoaXMuRXNUZHMudG9BcnJheSgpIDogdGhpcy5Fc1Rkc0RpcmVjdGl2ZSAmJiB0aGlzLkVzVGRzRGlyZWN0aXZlLmxlbmd0aCA+IDAgPyB0aGlzLkVzVGRzRGlyZWN0aXZlLnRvQXJyYXkoKSA6IFtdO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIE4uQjogUmlzcGV0dGFyZSBsJ29yZGluZSBkaSBxdWVzdGUgMyBtYWNyb2NhdGVnb3JpZSDDqCBWSVRBTEVcclxuXHJcbiAgICAgICAgICAgICAgICAvLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICAgICAgICBTaXN0ZW1hemlvbmkgZGkgVEgsIFRELCBlIHZpc2liaWxpdMOgIHZhcmllICAgICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5cclxuICAgICAgICAgICAgICAgIHRoaXMuYWxpZ25Db2x1bW5zSWZMb2FkZWRWaWV3KHZpZXcpOyAgICAgICAgICAgICAgICAvLyBTZSBzdG8gY2FyaWNhbmRvIHVuYSBWaWV3IGRhIGhvdHBvdGF0byAocXVpbmRpIGNvbiBzYXZlZHN0YXRlID0gdHJ1ZSkgcmlhbGxpbmVvIGxhIHZpc2liaWxpdMOgIGRlbGxlIGNvbG9ubmUgZSBpbCBsb3JvIG9yZGluZS5cclxuICAgICAgICAgICAgICAgIHRoaXMucmVmcmVzaENvbHVtbnNWaXNpYmlsaXR5KHRocywgdGRzLCB2aWV3KTsgICAgICAvLyBMYXZvcm8gc3VpIFRIIGVkIGV2ZW50dWFsbWVudGUgbW9kaWZpY28gbGEgdmlzaWJpbGl0w6AgYW5jaGUgZGVpIFRELlxyXG4gICAgICAgICAgICAgICAgdGhpcy5hbGlnbkhlYWRlcnNPcmRlcmluZyh0aHMsIHZpZXcpOyAgICAgICAgICAgICAgIC8vIEFsbGluZW8gZ2xpIG9yZGluYW1lbnRpIGFnbGkgaGVhZGVyXHJcbiAgICAgICAgICAgICAgICB0aGlzLnJldmlld0NvbHVtbnNMaXN0KHRocyk7ICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWdnaW9ybmEgbGEgbGlzdGEgZGVsbGUgY29sb25uZSBkYSBtb3N0cmFyZSBuZWxsYSBkaWFsb2cgcGVyIG9yZGluYW1lbnRvIGVjY1xyXG5cclxuICAgICAgICAgICAgICAgIC8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogICAgICAgIEdlbmVyYXppb25lIGJpbmRpbmcgcGVyIHJpZ2hlIGUgY29sb25uZSAgICAgICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuXHJcbiAgICAgICAgICAgICAgICB0aGlzLmV2YWx1YXRlUm93VGhzKHRocyk7ICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmFjY29sZ28gaSBUSFxyXG4gICAgICAgICAgICAgICAgdGhpcy5ldmFsdWF0ZVJvd1Rkcyh0aHMsIHRkcyk7ICAgICAgICAgICAgICAgICAgICAgIC8vIFJhY2NvbGdvIGkgVEQgaW4gY29udGVzdGkgc2VwYXJhdGksIHVuIGNvbnRlc3RvIHBlciBvZ25pIGl0ZW0gbyBncnVwcG9cclxuXHJcbiAgICAgICAgICAgICAgICAvLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICAgICAgICBVbHRpbWkgYWdnaXVzdG1hZW50aSBkZWkgYmluZGluZyAgICAgICAgICAgICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcblxyXG4gICAgICAgICAgICAgICAgdGhpcy5nZW5lcmF0ZURlZmF1bHRPcmRlcih2aWV3KTsgICAgICAgICAgICAgICAgICAgIC8vIEdlbmVybyBsZSBkaXJldHRpdmUgZGkgb3JkaW5hbWVudG8sIGNoZSBzaWFubyBkZWZhdWx0IG8gZGVyaXZhbnRpIGRhbGxhIEFwcFNlYXJjaFxyXG4gICAgICAgICAgICAgICAgdGhpcy5hcHBseU9yZGVyaW5nKHZpZXcsIHRydWUpOyAgICAgICAgICAgICAgICAgICAgIC8vIEFwcGxpY28gbCdvcmRpbmFtZW50byBzdWxsZSBjb2xvbm5lIChub24gQVNDIERFU0MsIG1hIFwicHJpbWEgcXVlc3RhIG8gcXVlbGxhIGNvbG9ubmFcIilcclxuICAgICAgICAgICAgICAgIHRoaXMuTW92ZVRlbXBvcmFyeVZhcmlhYmxlc1RvUmVhbE9uZXMoKTsgICAgICAgICAgICAvLyBDb2xsZWdvIFRIIGUgVEQgYWdnaXVzdGF0aSBmaW5vIGFkIG9yYSBhbGxlIHZhcmlhYmlsaSBkaSBCaW5kaW5nIEhUTUxcclxuICAgICAgICAgICAgICAgIHRoaXMuZXZhbHVhdGVTZWxlY3Rpb24odmlldy5pdGVtcywgdmlldy5zZWxlY3Rpb24pOyAvLyBSaWFsbGluZW8gbGUgaW5mbyBkaSBzZWxlemlvbmUgZGVnbGkgZWxlbWVudGkgZGVsbGEgVmlld1xyXG5cclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLlJlc2VhcmNoTmVlZGVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jaGFuZ2VkKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0U2VhcmNoUmVxdWVzdChmYWxzZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5SZXNlYXJjaE5lZWRlZCA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMudmlld01vZGUgJiYgIXRoaXMuVXNlQ3VzdG9tQ2VsbHMpIHtcclxuICAgICAgICAgICAgICAgIC8vIFJpYWxsaW5lbyBsZSBpbmZvIGRpIHNlbGV6aW9uZSBkZWdsaSBlbGVtZW50aSBkZWxsYSBWaWV3XHJcbiAgICAgICAgICAgICAgICBsZXQgdmlldyA9IHRoaXMuVmlldyBhcyBBcHBTZWFyY2g8YW55PjtcclxuICAgICAgICAgICAgICAgIHRoaXMuZXZhbHVhdGVTZWxlY3Rpb24odmlldy5pdGVtcywgdmlldy5zZWxlY3Rpb24pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMuYXJyYXlNb2RlKVxyXG4gICAgICAgICAgICAgICAgdGhpcy5hcnJheU1vZGVFdmFsdWF0ZVNlbGVjdGlvbih0aGlzLlZpZXcgYXMgYW55W10pO1xyXG5cclxuICAgICAgICAgICAgLy8gUGVyIGVzc2VyZSBzaWN1cm8gY2hlIGRvcG8gdW4gYmluZCBkaSBvZ2dldHRpIGxhIGVzLXRhYmxlIGFnZ2lvcm5pIGxhIGdyYWZpY2FcclxuICAgICAgICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XHJcbiAgICAgICAgICAgIHRoaXMuRmlyc3RCaW5kID0gZmFsc2U7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBiaW5kRGlzcGxheVRvTG9hZGVkSXRlbXNPckdyb3VwcygpIHtcclxuICAgICAgICBpZih0aGlzLlRNUEJvdW5kU291cmNlLmxlbmd0aCA9PSAwKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgIGlmICh0aGlzLmFycmF5TW9kZSB8fCAhdGhpcy5Vc2VDdXN0b21DZWxscykge1xyXG4gICAgICAgICAgICB0aGlzLmJvdW5kU291cmNlID0gdGhpcy5UTVBCb3VuZFNvdXJjZTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbGV0IHZpZXcgPSB0aGlzLlZpZXcgYXMgQXBwU2VhcmNoPGFueT47XHJcbiAgICAgICAgbGV0IGdyb3VwaW5nS2V5cyA9IHZpZXcuZ3JvdXBpbmdzPy5maWx0ZXIodCA9PiAhdC5hZ2dyZWdhdGlvbik/Lmxlbmd0aCB8fCAwO1xyXG5cclxuICAgICAgICBpZiAoZ3JvdXBpbmdLZXlzID09IDApIHtcclxuICAgICAgICAgICAgdGhpcy5ib3VuZFNvdXJjZSA9IHRoaXMuVE1QQm91bmRTb3VyY2U7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIDEpIFNlIG5vbiB2aWVuZSByaWNoaWVzdG8gaWwgZGV0dGFnbGlvIGRpIGFsY3VuIGdydXBwbyBzaWduaWZpY2EgY2hlIGxhIGNoaWFtYXRhIHJlc3RpdHVpc2NlIGxhIGxpc3RhIHBhZ2luYXRhIGRlaSBncnVwcGkgcHJpbmNpcGFsaS5cclxuICAgICAgICAvLyAgICBMaSB0cmF0dG8gY29tZSBzZSBmb3NzZSB1bmEgcXVhbHNpYXNpIGFsdHJhIHF1ZXJ5IHBhZ2luYXRhIHN1IE4gZWxlbWVudGlcclxuICAgICAgICBpZiAoKHZpZXcucmVxdWVzdGVkZ3JvdXBzPy5sZW5ndGggfHwgMCkgPT0gMCkge1xyXG4gICAgICAgICAgICB0aGlzLmJvdW5kU291cmNlID0gdGhpcy5UTVBCb3VuZFNvdXJjZTtcclxuXHJcbiAgICAgICAgICAgIC8vIFJlc2V0dG8gbGEgcmljZXJjYSBhbGxhIGNhY2hlIGRpIHF1ZXN0YSBcInNlc3Npb25lXCJcclxuICAgICAgICAgICAgdGhpcy5ncm91cFNlYXJjaFJlcXVlc3RzQ2FjaGUgPSBbeyBwYXRoOiAnJywgdmlldzogdmlldyB9XTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGVsc2V7XHJcbiAgICAgICAgICAgIC8vIDIpIFNlIHZpZW5lIHJpY2hpZXN0byBpbCBkZXR0YWdsaW8gZGkgdW4gcXVhbHNpYXNpIGdydXBwbyBkaXZlcnNvIGRhbGwndWx0aW1vIHZ1b2wgZGlyZSBjaGUgZGV2byBhZ2dpdW5nZXJlIFxyXG4gICAgICAgICAgICAvLyAgICBkb3BvIGFsIGdydXBwbyBjaGUgaG8gY2xpY2NhdG8gbGEgbGlzdGEgZGVpIGdydXBwaSB0aXJhdGEgZnVvcmkgcXVlc3RhIHZvbHRhIChpbnRlcm1lZGlhdGVHcm91cCA9IHRydWUpXHJcbiAgICAgICAgICAgIC8qXHJcbiAgICAgICAgICAgICogICBHcnVwcG9BICAgICAgICAgICAgICAgICAgICAgIEdydXBwb0FcclxuICAgICAgICAgICAgKiAgIEdydXBwb0IgICAgICAgICAgICAgICAgICAgICAgR3J1cHBvQlxyXG4gICAgICAgICAgICAqICAgR3J1cHBvQyA8LSBDbGljY28gcXVpICAgICAgICBHcnVwcG9DXHJcbiAgICAgICAgICAgICogICBHcnVwcG9EICAgICAgICAgICAgICAgICAgICAgICAgICBHcnVwcG9DMVxyXG4gICAgICAgICAgICAqICAgR3J1cHBvRSAgICAgICAgICAgICAgICAgICAgICAgICAgR3J1cHBvQzJcclxuICAgICAgICAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR3J1cHBvRFxyXG4gICAgICAgICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHcnVwcG9FXHJcbiAgICAgICAgICAgICovXHJcblxyXG4gICAgICAgICAgICAvLyAzKSBzZSBpIGdydXBwaSByaWNoaWVzdGkgZGFsbGEgdmlldyBzb25vIHVndWFsaSBhaSBncnVwcGkgcHJlc2VudGkgdnVvbCBkaXJlIGNoZSBzdG8gcHJlbmRlbmRvIGdsaSBvZ2dldHRpIHZlcmkgZSBwcm9wcmksIHNvbm8gaW4gXHJcbiAgICAgICAgICAgIC8vIHZpZXcuaXRlbXMgZSBxdWluZGkgaW4gVE1QQm91bmRTb3VyY2UsIGhvIGlub2x0cmUgbGUgaW5mb3JtYXppb25pIGRpIHBhZ2luYXppb25lICoqcGVyIGlsIHNpbmdvbG8gc290dG9ncnVwcG8qKiAoaW50ZXJtZWRpYXRlR3JvdXAgPSBmYWxzZSlcclxuICAgICAgICAgICAgLypcclxuICAgICAgICAgICAgKiAgIEdydXBwb0EgICAgICAgICAgICAgICAgICAgICAgICAgR3J1cHBvQVxyXG4gICAgICAgICAgICAqICAgICAgIEdydXBwb0MxICAgICAgICAgICAgICAgICAgICAgICAgR3J1cHBvQzEgICAgICBcclxuICAgICAgICAgICAgKiAgIEdydXBwb0IgICAgICAgICAgICAgICAgICAgICAgICAgR3J1cHBvQlxyXG4gICAgICAgICAgICAqICAgR3J1cHBvQyAgICAgICAgICAgICAgICAgICAgICAgICBHcnVwcG9DXHJcbiAgICAgICAgICAgICogICAgICAgR3J1cHBvQzEgPC0tIENsaWNjbyBxdWkgICAgICAgICBHcnVwcG9DMVxyXG4gICAgICAgICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9nZ2V0dG8xXHJcbiAgICAgICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT2dnZXR0bzJcclxuICAgICAgICAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPZ2dldHRvM1xyXG4gICAgICAgICAgICAqICAgICAgIEdydXBwb0MyICAgICAgICAgICAgICAgICAgICAgICAgR3J1cHBvQzJcclxuICAgICAgICAgICAgKiAgIEdydXBwb0QgICAgICAgICAgICAgICAgICAgICAgICAgR3J1cHBvRFxyXG4gICAgICAgICAgICAqICAgR3J1cHBvRSAgICAgICAgICAgICAgICAgICAgICAgICBHcnVwcG9FXHJcbiAgICAgICAgICAgICovXHJcblxyXG4gICAgICAgICAgICBsZXQgaW50ZXJtZWRpYXRlR3JvdXAgPSB2aWV3LnJlcXVlc3RlZGdyb3Vwcy5sZW5ndGggIT0gZ3JvdXBpbmdLZXlzO1xyXG5cclxuICAgICAgICAgICAgbGV0IGl0ZW1zID0gdGhpcy5ib3VuZFNvdXJjZTtcclxuICAgICAgICAgICAgbGV0IGluc2VydEluZGV4ID0gMDtcclxuICAgICAgICAgICAgbGV0IGdyb3VwS2V5OiBzdHJpbmcgPSBcIlwiO1xyXG4gICAgICAgICAgICBsZXQgZ3JvdXBSb3V0ZTogeyBjb2x1bW46IHN0cmluZywgdmFsdWU6IHN0cmluZyB9W10gPSBbXTtcclxuICAgICAgICAgICAgLy8gTmF2aWdvIGxhIHN0dXR0dXJhIGRlaSBncnVwcGkgaWdub3JhbmRvIHJpY29yc2l2YW1lbnRlIHR1dHRpIGdsaSBpbmRpY2kgZmlubyBhaSBncnVwcGkgY2hlIG1pIGludGVyZXNzYW5vIGluIG1vZG8gZGEgbm9uIGJlY2NhcmUgaWwgcHJpbW8gXCJHcnVwcG9DMVwiIGRlbCBjYXNvIHNvcHJhXHJcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdmlldy5yZXF1ZXN0ZWRncm91cHMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgIGxldCByZyA9IHZpZXcucmVxdWVzdGVkZ3JvdXBzW2ldO1xyXG4gICAgICAgICAgICAgICAgZ3JvdXBLZXkgKz0gcmcudmFsdWU7XHJcbiAgICAgICAgICAgICAgICBncm91cFJvdXRlLnB1c2goe2NvbHVtbjogcmcuY29sdW1uLCB2YWx1ZTogcmcudmFsdWV9KTtcclxuICAgICAgICAgICAgICAgIGluc2VydEluZGV4ID0gaXRlbXMuZmluZEluZGV4KCh0LCBpKSA9PiBpID49IGluc2VydEluZGV4ICYmIHQuX2dyb3VwICYmIHQuY29sdW1uID09IHJnLmNvbHVtbiAmJiB0LnZhbHVlID09IHJnLnZhbHVlKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgLy8gQXNzZWdubyB1biBsaXZlbGxvIGFpIHZhbG9yaSBjaGUgYXJyaXZhbm8gZGEgdXNhcmUgcGVyIGZvcm1hdHRhcmUgbGEgcGFydGUgZ3JhZmljYS4gSWwgcHJpbW8gZ3J1cHBvIGNsaWNjYXRvIHNhcsOgIGEgbGl2ZWxsbyAxLFxyXG4gICAgICAgICAgICAvLyBpbCBzZWNvbmRvIHNhcsOgIGEgbGl2ZWxsbyAyIGUgY29zw6wgdmlhLi4uXHJcbiAgICAgICAgICAgIC8vIExpIG1hcmNvIGlub2x0cmUgY29uIGlsIHBhcmVudCBpbiBtb2RvIGRhIHBvdGVyIGVsaW1pbmFyZSBpIHZlY2NoaSBxdWFsb3JhIHNlcnZpc3NlXHJcbiAgICAgICAgICAgIHRoaXMuVE1QQm91bmRTb3VyY2UuZm9yRWFjaChpdG0gPT4ge1xyXG4gICAgICAgICAgICAgICAgaXRtLl9wYXJlbnQgPSBncm91cEtleTtcclxuICAgICAgICAgICAgICAgIGl0bS5fcGFyZW50Um91dGUgPSBncm91cFJvdXRlO1xyXG4gICAgICAgICAgICAgICAgaWYgKGludGVybWVkaWF0ZUdyb3VwKVxyXG4gICAgICAgICAgICAgICAgICAgIGl0bS5fZ3JvdXBsZXZlbCA9IHZpZXcucmVxdWVzdGVkZ3JvdXBzLmxlbmd0aFxyXG4gICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgIC8vRWxpbWlubyBnbGkgb2dnZXR0aSB2ZWNjaGkgcXVpIGRlbnRybyBlIGxpIHNvc3RpdHVpc2NvIGNvaSBudW92aSBkaSBxdWVzdGEgcmljZXJjYVxyXG4gICAgICAgICAgICB0aGlzLmJvdW5kU291cmNlID0gdGhpcy5ib3VuZFNvdXJjZS5maWx0ZXIodCA9PiB0Ll9wYXJlbnQgIT0gZ3JvdXBLZXkpO1xyXG4gICAgICAgICAgICB0aGlzLmJvdW5kU291cmNlLnNwbGljZShpbnNlcnRJbmRleCArIDEsIDAsIC4uLnRoaXMuVE1QQm91bmRTb3VyY2UpO1xyXG5cclxuICAgICAgICAgICAgLy8gQWdnaXVuZ28gdW4gc2VwYXJhdG9yZSBhbGxhIGZpbmUgZGkgcXVlc3RpIGdydXBwaSBjaGUgZG92csOgIG9jY3VwYXJzaSBkaSBjYXJpY2FyZSBBTFRSSSBncnVwcGlcclxuICAgICAgICAgICAgdGhpcy5ib3VuZFNvdXJjZS5zcGxpY2UoaW5zZXJ0SW5kZXggKyAxICsgdGhpcy5UTVBCb3VuZFNvdXJjZS5sZW5ndGgsIDAsIHRoaXMuZ2V0R3JvdXBTZXBhcmF0b3IodmlldywgZ3JvdXBLZXksIHZpZXcucmVxdWVzdGVkZ3JvdXBzLmxlbmd0aCkpO1xyXG5cclxuICAgICAgICAgICAgLy8gQWdnaXVuZ28gbGEgcmljZXJjYSBhbGxhIGNhY2hlIGRpIHF1ZXN0YSBcInNlc3Npb25lXCJcclxuICAgICAgICAgICAgdGhpcy5ncm91cFNlYXJjaFJlcXVlc3RzQ2FjaGUucHVzaCh7IHBhdGg6IGdyb3VwS2V5LCB2aWV3OiB2aWV3IH0pO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIE1ldG9kbyByaWNoaWFtYXRvIHNvbG8gcXVhbmRvICoqVE1QUm93VERzKiogZSAqKlRNUFJvd1RIcyoqIHNvbm8gY29tcGxldGFtZW50ZSBnZW5lcmF0aSBlZCBhZ2dpdXN0YXRpLiBTZXJ2ZSBwZXIgY29sbGVnYXJsaSBhbGxlIHZhcmlhYmlsaSB1c2F0ZSBsYXRvIGJpbmRpbmcgSFRNTFxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIE1vdmVUZW1wb3JhcnlWYXJpYWJsZXNUb1JlYWxPbmVzKCkge1xyXG4gICAgICAgIHRoaXMuUm93VERzID0gdGhpcy5UTVBSb3dURHM7XHJcbiAgICAgICAgdGhpcy5Sb3dUSHMgPSB0aGlzLlRNUFJvd1RIcztcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFNlIG5vbiBobyBsJ0lucHV0ICoqRHluYW1pY1Jvd0NvbHVtbnNEZWZpbml0aW9uKiogaW4gbW9kYWxpdMOgIGRpbmFtaWNhIGxvIHJpZW1waW8gY29uIGlsIGRlZmF1bHQgbm9tZSBkZWxsYSBjb2xvbm5hID0gdGVzdG8gZGVsbGEgY29sb25uYVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGV2ZW50dWFsbHlSZXZpZXdEeW5hbWljQ29sdW1ucygpIHtcclxuICAgICAgICAvLyBTZW56YSBvZ2dldHRpIGVzY29cclxuICAgICAgICBpZiAoIXRoaXMuVE1QQm91bmRTb3VyY2UgfHwgdGhpcy5UTVBCb3VuZFNvdXJjZS5sZW5ndGggPT0gMClcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICB2YXIgdXNlR2VuZXJpY0l0ZW1zID0gISF0aGlzLlRNUEJvdW5kU291cmNlWzBdW1wicHJvcGVydGllc1wiXTtcclxuICAgICAgICBpZiAoIXVzZUdlbmVyaWNJdGVtcyB8fCAoIXRoaXMuRmlyc3RCaW5kICYmIHRoaXMuRHluYW1pY1Jvd0NvbHVtbnNEZWZpbml0aW9uICYmIHRoaXMuRHluYW1pY1Jvd0NvbHVtbnNEZWZpbml0aW9uLmxlbmd0aCA+IDApKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgIGlmICgoIXRoaXMuRHluYW1pY1Jvd0NvbHVtbnNEZWZpbml0aW9uIHx8IHRoaXMuRHluYW1pY1Jvd0NvbHVtbnNEZWZpbml0aW9uLmxlbmd0aCA9PSAwKSkge1xyXG4gICAgICAgICAgICB2YXIgcHJvcHMgPSA8UmVjb3JkPHN0cmluZywgc3RyaW5nPj50aGlzLlRNUEJvdW5kU291cmNlWzBdW1wicHJvcGVydGllc1wiXTtcclxuICAgICAgICAgICAgdGhpcy5EeW5hbWljUm93Q29sdW1uc0RlZmluaXRpb24gPSBbXTtcclxuICAgICAgICAgICAgZm9yIChsZXQga2V5IGluIHByb3BzKVxyXG4gICAgICAgICAgICAgICAgdGhpcy5EeW5hbWljUm93Q29sdW1uc0RlZmluaXRpb24ucHVzaChuZXcgRXNUYWJsZUNvbHVtbnNEZWZpbml0aW9uKGtleSwga2V5KSlcclxuICAgICAgICAgICAgdGhpcy5Vc2VyRGVmaW5lZER5bmFtaWNDb2xzID0gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2VcclxuICAgICAgICAgICAgdGhpcy5Vc2VyRGVmaW5lZER5bmFtaWNDb2xzID0gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFBhcnRlbmRvIGRhZ2xpICoqRXNUaHMqKiBlc3RyYXBwb2xvIGxhIGxpc3RhIGRpICoqRXNUYWJsZUNvbHVtbioqIGNoZSBxdWVzdGEgdGFiZWxsYSBkb3Zyw6AgZXZlbnR1YWxtZW50ZSBnZXN0aXJlIHBlciBWaXNpYmlsaXTDoCBlIE9yZGluZVxyXG4gICAgICpcclxuICAgICAqIENvc3RvOiAxIHNjYW4gRXNUaHNcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge0VzVGhbXSB8IEVzVGhEaXJlY3RpdmVbXX0gdGhzIENvbG9ubmUgZGVsbGEgdGFiZWxsYVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHJldmlld0NvbHVtbnNMaXN0KHRoczogRXNUaFtdIHwgRXNUaERpcmVjdGl2ZVtdKSB7XHJcbiAgICAgICAgdGhpcy5Db2x1bW5zTGlzdCA9IFtdO1xyXG4gICAgICAgIGlmICh0aHMubGVuZ3RoID09IDApXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgLy8gQXBwZW5hIGlsIGNvbnRlbnRDaGlsZHJlbiDDqCB2YWxvcml6emF0byBzY29ycm8gdHV0dGkgZ2xpIGhlYWRlclxyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGxldCB0aCA9IHRoc1tpXTtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLmlzRXNUaCh0aCkpIHtcclxuICAgICAgICAgICAgICAgIC8vIFNlIG5vbiBobyB1biBpZCBpbCB0aCDDqCBjb25zaWRlcmF0byBpbmVydGVcclxuICAgICAgICAgICAgICAgIGlmICghdGguSUQpXHJcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XHJcblxyXG4gICAgICAgICAgICAgICAgdGguT3JkZXJCeSA9IHRoaXMuT3JkZXJCeUNvbHVtbjtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBTYWx2byBsZSBpbmZvcm1hemlvbmkgZGVsbCdoZWFkZXIgcGVyIGZhciBwYXJ0ZSBkZWxsYSBsaXN0YSBkYSBjdWkgc2NlZ2xpZXJlIHF1YWxpIGNvbG9ubmUgdmlzdWFsaXp6YXJlL25hc2NvbmRlcmVcclxuICAgICAgICAgICAgICAgIC8vIERpIGRlZmF1bHQgbGEgdmlzaWJpbGl0w6Agw6ggcXVlbGxhIGltcG9zdGF0YSBuZWwgY29tcG9uZW50ZVxyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuSGlkZGVuQ29sdW1ucyB8fCB0aC5WaXNpYmxlKVxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuQ29sdW1uc0xpc3QucHVzaChuZXcgRXNUYWJsZUNvbHVtbih0aC5JRCwgdGguRGVzY3JpcHRpb24sIHRoLlZpc2libGUsIHRoLkZpeGVkLCBudWxsKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAvLyBTZSBub24gaG8gdW4gaWQgaWwgdGggw6ggY29uc2lkZXJhdG8gaW5lcnRlXHJcbiAgICAgICAgICAgICAgICBpZiAoIXRoLnRoKVxyXG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIFNhbHZvIGxlIGluZm9ybWF6aW9uaSBkZWxsJ2hlYWRlciBwZXIgZmFyIHBhcnRlIGRlbGxhIGxpc3RhIGRhIGN1aSBzY2VnbGllcmUgcXVhbGkgY29sb25uZSB2aXN1YWxpenphcmUvbmFzY29uZGVyZVxyXG4gICAgICAgICAgICAgICAgLy8gRGkgZGVmYXVsdCBsYSB2aXNpYmlsaXTDoCDDqCBxdWVsbGEgaW1wb3N0YXRhIG5lbCBjb21wb25lbnRlXHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5IaWRkZW5Db2x1bW5zIHx8IHRoLnRoVmlzaWJsZSlcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLkNvbHVtbnNMaXN0LnB1c2gobmV3IEVzVGFibGVDb2x1bW4odGgudGgsIG51bGwsIHRoLnRoVmlzaWJsZSwgdGgudGhGaXhlZCwgdGguVGVtcGxhdGUpKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRlcm1pbmF0byBpbCBiaW5kaW5nIGRlbGxlIGNvbG9ubmUgZGEgKipyZXZpZXdDb2x1bW5zTGlzdCoqIGUgZGVsbGEgKipWaWV3KiogZGFsICoqd3JpdGVWYWx1ZSoqIHF1ZXN0byBtZXRvZG8gc2kgb2NjdXBhXHJcbiAgICAgKiBkZWxsJ2FsbGluZWFtZW50byBkZWxsZSBpbmZvcm1hemlvbmkgZnJhIGxlIGNvbG9ubmUgY2FsY29sYXRlIGludGVybmFtZW50ZSBlIGxlIGluZm9ybWF6aW9uaSBzdWxsZSBjb2xvbm5lIGNoZSBhcnJpdmFubyBkYWxsJ0FwcFNlYXJjaFxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7QXBwU2VhcmNoPGFueT59IHZpZXcgQXBwU2VhcmNoIGRhIHV0aWxpenphcmUgcGVyIHF1ZXN0YSBvcGVyYXppb25lXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgYWxpZ25Db2x1bW5zSWZMb2FkZWRWaWV3KHZpZXc6IEFwcFNlYXJjaDxhbnk+KSB7XHJcbiAgICAgICAgbGV0IGVtaXRDaGFuZ2VkID0gdmlldy5zYXZlZHN0YXRlO1xyXG4gICAgICAgIGxldCBuZXdDb2xzZXQgPSBbXTtcclxuXHJcbiAgICAgICAgaWYgKCF0aGlzLkNvbHVtbnNMaXN0IHx8IHRoaXMuQ29sdW1uc0xpc3QubGVuZ3RoID09IDApXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgdGhpcy5Db2x1bW5zTGlzdC5mb3JFYWNoKGMgPT4ge1xyXG4gICAgICAgICAgICBsZXQgZXhDbCA9IHZpZXcuY29sdW1ucy5maWx0ZXIoY2MgPT4gY2MgPT0gYy5pZCk7XHJcblxyXG4gICAgICAgICAgICAvLyBTZSBsJ2FwcHNlYXJjaCB2aWVuZSBkYSB1bm8gc3RhdG8gcHJlY2VkZW50ZSwgdXNvIGxlIGluZm9ybWFpem9uaSBzdWxsZSBjb2xvbm5lIGNoZSBoYSBkZW50cm8sIGFsdHJpbWVudGkgc292cmFzY3Jpdm8gdHV0dG8gICoqXHJcbiAgICAgICAgICAgIGlmIChjLnZpc2libGUgJiYgdmlldy5jb2x1bW5zLmxlbmd0aCA9PSAwKVxyXG4gICAgICAgICAgICAgICAgbmV3Q29sc2V0LnB1c2goYy5pZCk7XHJcblxyXG4gICAgICAgICAgICAvLyBTZSBobyB1bmEgY29sb25uYSBsYXRvIEFwcFNlYXJjaCBlIG5lbGxhIENvbHVtbkxpc3Qgbm9uIMOoIHZpc2liaWxlLCBhbGxpbmVvIGFsbCdBcHBTZWFyY2hcclxuICAgICAgICAgICAgZWxzZSBpZiAoZXhDbC5sZW5ndGggPT0gMSAmJiAhYy52aXNpYmxlKVxyXG4gICAgICAgICAgICAgICAgYy52aXNpYmxlID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgICAgIC8vIEFsbGluZWFtZW50byBzdWxsJ0FwcFNlYXJjaCBwZXIgY2FzaXN0aWNoZSBpbnZlcnNlIGFsIGRpIHNvcHJhXHJcbiAgICAgICAgICAgIGVsc2UgaWYgKGV4Q2wubGVuZ3RoID09IDAgJiYgYy52aXNpYmxlKVxyXG4gICAgICAgICAgICAgICAgYy52aXNpYmxlID0gZmFsc2U7XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIC8vIE5vbiBobyBjb2xvbm5lIG5lbGxhIGFwcHNlYXJjaCwgdnVvbCBkaXJlIGNoZSBzb25vIGFsIHByaW1vIGJpbmRpbmdcclxuICAgICAgICBpZiAodmlldy5jb2x1bW5zLmxlbmd0aCA9PSAwKVxyXG4gICAgICAgICAgICB2aWV3LmNvbHVtbnMgPSBuZXdDb2xzZXQ7XHJcblxyXG4gICAgICAgIGlmICh2aWV3LnNhdmVkc3RhdGUgJiYgdGhpcy5Db2x1bW5zT3JkZXJpbmcgJiYgdmlldy5jb2x1bW5fb3JkZXJpbmcubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICBsZXQgbmV3Q29sTGlzdCA9IFtdO1xyXG4gICAgICAgICAgICAvLyBTY29ycm8gZ2xpIG9yZGluYW1lbnRpIGNoZSBhdmV2byBzYWx2YXRvIGUgcmljcmVvIGxhIENvbHVtbnNMaXN0IGluIGJhc2UgYSBsb3JvXHJcbiAgICAgICAgICAgIHZpZXcuY29sdW1uX29yZGVyaW5nLmZvckVhY2goY28gPT4ge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5Db2x1bW5zTGlzdC5mb3JFYWNoKGMgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChjLmlkID09IGNvKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdDb2xMaXN0LnB1c2goYyk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICB0aGlzLkNvbHVtbnNMaXN0ID0gbmV3Q29sTGlzdDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIEluIG9nbmkgY2FzbyBxdWVzdG8gbm9uIG1pIHNlcnZlIHBpw7ksIGxvIHJlc2V0dG8gICoqXHJcbiAgICAgICAgdmlldy5zYXZlZHN0YXRlID0gZmFsc2U7XHJcblxyXG4gICAgICAgIGlmIChlbWl0Q2hhbmdlZClcclxuICAgICAgICAgICAgdGhpcy5jaGFuZ2VkKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBNZXRvZG8gY2hlIGdlc3Rpc2NlIGlsIGNhbWJpbyBkaSBPcmRpbmFtZW50byBkaSB1bmEgY29sb25uYVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBpZCBJRCBkZWxsYSBjb2xvbm5hIGlsIGN1aSBvcmlkbmFtZW50byDDqCBjYW1iaWF0b1xyXG4gICAgICogQHBhcmFtIHsnREVTQycgfCAnQVNDJ30gb3JkZXIgTnVvdm8gb3JkaW5lIHNlbGV6aW9uYXRvIHBlciBsYSBjb2xvbm5hXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyB0aE9yZGVyQ2hhbmdlZChpZDogc3RyaW5nLCBvcmRlcj86ICdERVNDJyB8ICdBU0MnKSB7XHJcbiAgICAgICAgaWYgKCF0aGlzLnZpZXdNb2RlKSB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignT3JkZXIgY2hhbmdlZCBvbiBhIHRhYmxlIG5vdCBpbiB2aWV3TW9kZS4gT3BlcmF0aW9uIG5vdCBzdXBwb3J0ZWQnKTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKCF0aGlzLk9yZGVyQnlDb2x1bW4pXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgbGV0IGFwcFNlYXJjaCA9IHRoaXMuVmlldyBhcyBBcHBTZWFyY2g8YW55PjtcclxuICAgICAgICBsZXQgb3JkZXJUb0FkZCA9IHRydWU7XHJcbiAgICAgICAgbGV0IG9yZGVyVG9SZW1vdmU6IG51bWJlciA9IG51bGw7XHJcblxyXG4gICAgICAgIC8vIFNlIHBlciBxdWFsY2hlIG1vdGl2byBpbCBjb3N0cnV0dG9yZSBub24gw6ggcGFzc2F0byAoY2FjaGUgdGFycGF0ZSBvIHNpbWlsYSkgZml4b1xyXG4gICAgICAgIGlmICghYXBwU2VhcmNoLm9yZGVycylcclxuICAgICAgICAgICAgYXBwU2VhcmNoLm9yZGVycyA9IFtdO1xyXG5cclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFwcFNlYXJjaC5vcmRlcnMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgbGV0IHQgPSBhcHBTZWFyY2gub3JkZXJzW2ldO1xyXG4gICAgICAgICAgICBpZiAodC5pZCA9PSBpZCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdC5vcmRlciA9IG9yZGVyO1xyXG4gICAgICAgICAgICAgICAgICAgIG9yZGVyVG9BZGQgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgICAgICBvcmRlclRvUmVtb3ZlID0gaTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKG9yZGVyVG9SZW1vdmUgIT0gbnVsbCkge1xyXG4gICAgICAgICAgICBhcHBTZWFyY2gub3JkZXJzLnNwbGljZShvcmRlclRvUmVtb3ZlLCAxKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAob3JkZXJUb0FkZCkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5NdWx0aXBsZU9yZGVyaW5nRGlyZWN0aXZlcylcclxuICAgICAgICAgICAgICAgIGFwcFNlYXJjaC5vcmRlcnMucHVzaChuZXcgQXBwT3JkZXJpbmcoaWQsIG9yZGVyKSk7XHJcbiAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgIGFwcFNlYXJjaC5vcmRlcnMgPSBbbmV3IEFwcE9yZGVyaW5nKGlkLCBvcmRlcildO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5vbk9yZGVyQ2hhbmdlZC5lbWl0KHsgaWQsIG9yZGVyIH0pO1xyXG4gICAgICAgIFxyXG4gICAgICAgIGlmICh0aGlzLmdyb3VwU2VhcmNoUmVxdWVzdHNDYWNoZS5sZW5ndGggPiAwKVxyXG4gICAgICAgICAgICB0aGlzLmVtaXRSb3dHcm91cGluZ1NlYXJjaGVzKGlkLCBhcHBTZWFyY2gub3JkZXJzKTtcclxuICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgIHRoaXMuZW1pdFNlYXJjaFJlcXVlc3QoZmFsc2UpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTWV0b2RvIGRhIGNoaWFtYXJlIG9nbmkgdm9sdGEgY2hlIHNpIHZ1b2xlIGRhcmUgZXZpZGVuemEgYWxsJ2VzdGVybm8gZGVsIGJpc29nbm8gZGkgcmllZmZldHR1YXJlIGxhIHJpY2VyY2FcclxuICAgICAqIFxyXG4gICAgICogQHBhcmFtIHtib29sZWFufSByZXNldHNQYWdlIEluZGljYSBhbCBsaXN0ZW5lciBjaGUgZGV2ZSByZXNldHRhcmUgaWwgbnVtZXJvIGRpIHBhZ2luYVxyXG4gICAgICogQHBhcmFtIHtBcHBTZWFyY2g8YW55Pn0gdmlld092ZXJyaWRlIE92ZXJyaWRlIGRlbGxhIHZpZXcgZGEgZW1ldHRlcmUgcGVyIHF1ZXN0YSByaWNlcmNhXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZW1pdFNlYXJjaFJlcXVlc3QocmVzZXRzUGFnZTogYm9vbGVhbiwgdmlld092ZXJyaWRlPzogQXBwU2VhcmNoPGFueT4pIHtcclxuICAgICAgICBpZiAodGhpcy52aWV3TW9kZSAmJiAhdmlld092ZXJyaWRlKSB7XHJcbiAgICAgICAgICAgICh0aGlzLlZpZXcgYXMgQXBwU2VhcmNoPGFueT4pLmludGVybmFsc2VhcmNocmVxdWVzdCA9IHRydWU7XHJcbiAgICAgICAgICAgIHRoaXMuY2hhbmdlZCgpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLnJlc2VhcmNoSW5Qcm9ncmVzcyA9IHRydWU7XHJcbiAgICAgICAgdGhpcy5vblNlYXJjaFJlcXVlc3QuZW1pdCh2aWV3T3ZlcnJpZGUgPyB2aWV3T3ZlcnJpZGUgOiByZXNldHNQYWdlKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEluIGJhc2UgYWxsYSB2aXNpYmlsaXTDoCByZWdpc3RyYXRhIG5lbGxlICoqQ29sdW1uc0xpc3QqKiBxdWVzdG8gbWV0b2RvIHNpIG9jY3VwYSBkaSBwcmVuZGVyZSB0dXR0aSBpICoqRXNUaHMqKiBlZCAqKkVzVGRzKiogcmVsYXRpdmkgZSBuYXNvbmRlcmxpL21vc3RyYXJsaVxyXG4gICAgICpcclxuICAgICAqIENvc3RvOiAxIHNjYW4gQ29sdW1uc0xpc3QsIDEgc2NhbiBFc1RocywgMSBzY2FuIEVzVGRzXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtFc1RoW10gfCBFc1RoRGlyZWN0aXZlW119IHRocyBIZWFkZXIgZGVsbGEgdGFiZWxsYVxyXG4gICAgICogQHBhcmFtIHtFc1RkW10gfCBFc1RkRGlyZWN0aXZlW119IHRkcyBDZWxsZSBkZWxsYSB0YWJlbGxhXHJcbiAgICAgKiBAcGFyYW0ge0FwcFNlYXJjaDxhbnk+fSB2aWV3IEFwcFNlYXJjaCBkYSB1dGlsaXp6YXJlIHBlciBxdWVzdGEgb3BlcmF6aW9uZVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHJlZnJlc2hDb2x1bW5zVmlzaWJpbGl0eSh0aHM6IEVzVGhbXSB8IEVzVGhEaXJlY3RpdmVbXSwgdGRzOiBFc1RkW10gfCBFc1RkRGlyZWN0aXZlW10sIHZpZXc6IEFwcFNlYXJjaDxhbnk+KSB7XHJcbiAgICAgICAgbGV0IGNvbHVtbnNDYWNoZTogeyBbaW5kZXg6IHN0cmluZ106IEVzVGFibGVDb2x1bW4gfSA9IHt9O1xyXG4gICAgICAgIGxldCBuZXdDb2xzZXQgPSBbXTtcclxuICAgICAgICBsZXQgZml4ZWRUaHM6IHsgW2lkOiBzdHJpbmddOiBib29sZWFuIH0gPSB7fTtcclxuICAgICAgICBmb3IgKGxldCBjb2xpID0gMDsgY29saSA8IHRoaXMuQ29sdW1uc0xpc3QubGVuZ3RoOyBjb2xpKyspIHtcclxuICAgICAgICAgICAgbGV0IGNvbCA9IHRoaXMuQ29sdW1uc0xpc3RbY29saV07XHJcbiAgICAgICAgICAgIGNvbHVtbnNDYWNoZVtjb2wuaWRdID0gY29sO1xyXG4gICAgICAgICAgICBpZiAoY29sLnZpc2libGUpIG5ld0NvbHNldC5wdXNoKGNvbC5pZCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHZpZXcuY29sdW1ucyA9IG5ld0NvbHNldDtcclxuXHJcbiAgICAgICAgLy8gRGEgcXVpIGluIHBvaSBkZXZvbm8gZXNzZXJlIGVzZWd1aXRpIFNPTE8gaW4gZmFzZSBkaSB3cml0ZVZhbHVlIHF1aW5kaSBkZXZvIGFzc2ljdXJhcm1pIGRpIHBhc3NhcmxpIG51bGwgaW4gdHV0dGkgaSBwYXNzYWdnaSBkaXZlcnNpIGRhIHF1ZWxsb1xyXG4gICAgICAgIGlmICh0aHMpIHtcclxuICAgICAgICAgICAgLy8gRGVmaW5pc2NvIHNlIGxhIGNvbG9ubmEgw6ggdmlzaWJpbGUgaW4gYmFzZSBhbGxhIHN1YSByYXBwcmVzZW50YXppb25lIGxvY2FsZSBpbiBDb2x1bW5zTGlzdFxyXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRocy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgbGV0IHRoID0gdGhzW2ldO1xyXG4gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pc0VzVGgodGgpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGguVmlzaWJsZSA9IHRoLkZpeGVkIHx8IChjb2x1bW5zQ2FjaGVbdGguSURdID8gY29sdW1uc0NhY2hlW3RoLklEXS52aXNpYmxlIDogdGguVmlzaWJsZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoLkZpeGVkKSBmaXhlZFRoc1t0aC5JRF0gPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGgudGhWaXNpYmxlID0gdGgudGhGaXhlZCB8fCAoY29sdW1uc0NhY2hlW3RoLnRoXSA/IGNvbHVtbnNDYWNoZVt0aC50aF0udmlzaWJsZSA6IHRoLnRoVmlzaWJsZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoLnRoRml4ZWQpIGZpeGVkVGhzW3RoLnRoXSA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0ZHMpIHtcclxuICAgICAgICAgICAgLy8gRGVmaW5pc2NvIHNlIGxhIGNlbGxhIMOoIHZpc2liaWxlIGluIGJhc2UgYWxsYSBzdWEgcmFwcHJlc2VudGF6aW9uZSBsb2NhbGUgaW4gQ29sdW1uc0xpc3RcclxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0ZHMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgIGxldCB0ZCA9IHRkc1tpXTtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pc0VzVGQodGQpKVxyXG4gICAgICAgICAgICAgICAgICAgIHRkLlZpc2libGUgPSBmaXhlZFRoc1t0ZC5JRF0gfHwgKGNvbHVtbnNDYWNoZVt0ZC5JRF0gPyBjb2x1bW5zQ2FjaGVbdGQuSURdLnZpc2libGUgOiB0ZC5WaXNpYmxlKTtcclxuICAgICAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgICAgICB0ZC50ZFZpc2libGUgPSBmaXhlZFRoc1t0ZC50ZF0gfHwgKGNvbHVtbnNDYWNoZVt0ZC50ZF0gPyBjb2x1bW5zQ2FjaGVbdGQudGRdLnZpc2libGUgOiB0ZC50ZFZpc2libGUpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLmNoYW5nZWQoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEFsbGluZWEgZ2xpIG9yZGluYW1lbnRpIGRhdGkgZnJhIGxlICoqRXNUaHMqKiBlIGxlIGluZm9ybWF6aW9uaSBhbGwnaW50ZXJubyBkZWxsYSBWaWV3IGJpbmRhdGFcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge0FwcFNlYXJjaDxhbnk+fSB2aWV3IEFwcFNlYXJjaCBkYSB1dGlsaXp6YXJlIHBlciBxdWVzdGEgb3BlcmF6aW9uZVxyXG4gICAgICogQHBhcmFtIHtFc1RoW10gfCBFc1RoRGlyZWN0aXZlW119IHRocyBDb2xvbm5lIGRlbGxhIHRhYmVsbGFcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBhbGlnbkhlYWRlcnNPcmRlcmluZyh0aHM6IEVzVGhbXSB8IEVzVGhEaXJlY3RpdmVbXSwgdmlldzogQXBwU2VhcmNoPGFueT4pIHtcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRocy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgdGggPSB0aHNbaV07XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5pc0VzVGgodGgpKSB7XHJcbiAgICAgICAgICAgICAgICB0aC5PcmRlciA9IG51bGw7XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gQXNzZWdubyB0dXR0aSBnbGkgb3JkaW5hbWVudGkgY2hlIG1pIHZlbmdvbm8gZGEgQXBwU2VhcmNoLiBTb25vIGkgcGnDuSBpbXBvcnRhbnRpLiBOb24gZmFjY2lvIGNhY2hlIG8gY29zZSBzdHJhbm8gcGVyY2jDqSB0YW50byBxdWVzdGFcclxuICAgICAgICAgICAgICAgIC8vIHZhcmlhYmlsZSBzYXLDoCBzZW1wcmUgbWFzc2ltbyAzIGVsZW1lbnRpXHJcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHZpZXcub3JkZXJzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IG9yID0gdmlldy5vcmRlcnNbaV07XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9yLmlkID09IHRoLklEKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aC5PcmRlciA9IG9yLm9yZGVyO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgdGgudGhPcmRlciA9IG51bGw7XHJcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHZpZXcub3JkZXJzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IG9yID0gdmlldy5vcmRlcnNbaV07XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9yLmlkID09IHRoLnRoKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aC50aE9yZGVyID0gb3Iub3JkZXI7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBQYXJ0ZW5kbyBkYWdsaSAqKkVzVGRzKiogYmluZGF0aSBnZW5lcmEsIGFsbCdpbnRlcm5vIGRlbCBkaXppb25hcmlvICoqVE1QUm93VERzKiogdHV0dGkgaSBjb250ZXN0aSBkZWkgdmFyaSBvZ2dldHRpLlxyXG4gICAgICpcclxuICAgICAqIFZlbmdvbm8gZXNjbHVzaSBpIFREIFwiSW50ZXJuaVwiIGluIHF1YW50byB2ZW5nb25vIGdlbmVyYXRpIGRhZ2xpIG9yaWdpbmFsaSBxdWluZGkgaW5jbHVkZXJsaSB2b3JyZWJiZSBkaXJlIHJpZWZmZXR0dWFyZSBsZSBvcGVyYXppb25pIGR1ZSB2b2x0ZVxyXG4gICAgICpcclxuICAgICAqIENvc3RvOiAyIHNjYW4gRXNUaHMsIDEgc2NhbiBFc1Rkc1xyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7RXNUaFtdIHwgRXNUaERpcmVjdGl2ZVtdfSB0aHMgQ29sb25uZSBkZWxsYSB0YWJlbGxhXHJcbiAgICAgKiBAcGFyYW0ge0VzVGRbXSB8IEVzVGREaXJlY3RpdmVbXX0gdGRzIENlbGxlIGRlbGxhIHRhYmVsbGFcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBldmFsdWF0ZVJvd1Rkcyh0aHM6IEVzVGhbXSB8IEVzVGhEaXJlY3RpdmVbXSwgdGRzOiBFc1RkW10gfCBFc1RkRGlyZWN0aXZlW10pIHtcclxuICAgICAgICBpZiAodGRzLmxlbmd0aCA9PSAwKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgIGxldCB0aHNDYWNoZTogeyBbaW5kZXg6IHN0cmluZ106IEVzVGggfCBFc1RoRGlyZWN0aXZlIH0gPSB7fTtcclxuXHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aHMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgbGV0IHRoID0gdGhzW2ldO1xyXG4gICAgICAgICAgICB0aHNDYWNoZVt0aGlzLmlzRXNUaCh0aCkgPyB0aC5JRCA6IHRoLnRoXSA9IHRoO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5UTVBSb3dURHMgPSB7fTtcclxuICAgICAgICAvLyBWYXJpYWJpbGUgZCdhcHBvZ2dpbyBwZXIgcGVybWV0dGVybWkgZGkgaW5zZXJpcmUgdHV0dGUgbGUgY29sb25uZSBcIkZpeGVkXCIgZGF2YW50aVxyXG4gICAgICAgIGxldCBjb250ZXh0Rml4ZWRzOiB7IFtjb250ZXh0OiBzdHJpbmddOiBudW1iZXIgfSA9IHt9O1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGRzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGxldCB0ZCA9IHRkc1tpXTtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLmlzRXNUZCh0ZCkpIHtcclxuICAgICAgICAgICAgICAgIGxldCB0aCA9IHRoc0NhY2hlW3RkLklEXTtcclxuICAgICAgICAgICAgICAgIGlmICghIXRoKVxyXG4gICAgICAgICAgICAgICAgICAgIHRoLlJlZmVyZW5jZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFwiSUQgZGVsbCdvZ2dldG8gRXNUZCBub24gY29tcGF0aWJpbGUgY29uIGdsaSBJRCBkaWNoYXJhdGkgbmVnbGkgRXNUaDogXCIgKyB0ZC5JRDtcclxuXHJcbiAgICAgICAgICAgICAgICBsZXQgaXNGaXhlZCA9ICh0aGlzLmlzRXNUaCh0aCkgJiYgdGguRml4ZWQpIHx8ICghdGhpcy5pc0VzVGgodGgpICYmIHRoLnRoRml4ZWQpO1xyXG4gICAgICAgICAgICAgICAgbGV0IGl0ZW1Ub0FkZCA9IDxhbnk+eyBHcm91cEFnZ3JlZ2F0aW9uOiBmYWxzZSwgR3JvdXBIZWFkZXI6IGZhbHNlLCBXcmFwczogdHJ1ZSwgSUQ6IHRkLklELCBWaXNpYmxlOiB0ZC5WaXNpYmxlLCBDbGFzczogdGQuQ2xhc3MsIENvbnRlbnQ6IHRkLkNvbnRlbnQsIFJvdXRlckxpbms6IHRkLlJvdXRlckxpbmssIFRlbXBsYXRlOiB0ZC5UZW1wbGF0ZSB9O1xyXG4gICAgICAgICAgICAgICAgbGV0IGN0eCA9IHRkLkNvbnRleHQ7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5UTVBSb3dURHNbY3R4XSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0ZpeGVkKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLlRNUFJvd1REc1tjdHhdLnNwbGljZSgwICsgKGNvbnRleHRGaXhlZHNbY3R4XSsrKSwgMCwgaXRlbVRvQWRkKTtcclxuICAgICAgICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuVE1QUm93VERzW2N0eF0ucHVzaChpdGVtVG9BZGQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5Sb3dDb250ZXh0cy5wdXNoKGN0eCk7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5UTVBSb3dURHNbY3R4XSA9IFtpdGVtVG9BZGRdO1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHRGaXhlZHNbY3R4XSA9IGlzRml4ZWQgPyAxIDogMFxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmJvdW5kU291cmNlLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGl0ZW0gPSB0aGlzLmJvdW5kU291cmNlW2ldO1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBjdHggPSBpdGVtLmhhc2g7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGtleSA9IHRkLnRkO1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCB0aCA9IHRoc0NhY2hlW3RkLnRkXTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoISF0aClcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGguUmVmZXJlbmNlZCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBcIklEIGRlbGwnb2dnZXRvIEVzVGQgbm9uIGNvbXBhdGliaWxlIGNvbiBnbGkgSUQgZGljaGFyYXRpIG5lZ2xpIEVzVGg6IFwiICsgdGQudGQ7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0ZC50ZElmIHx8ICghdGhpcy5pc0VzVGgodGgpICYmIHRoLnRoR3JvdXApKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB0aENhc3RlZCA9IDxFc1RoRGlyZWN0aXZlPnRoO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgaXNGaXhlZCA9ICh0aGlzLmlzRXNUaCh0aCkgJiYgdGguRml4ZWQpIHx8ICghdGhpcy5pc0VzVGgodGgpICYmIHRoLnRoRml4ZWQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgaXRlbVRvQWRkID0gaXRlbS5faXRlbSA/XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YW55PnsgSUQ6IGtleSwgR3JvdXBIZWFkZXI6IGZhbHNlLCBHcm91cEFnZ3JlZ2F0aW9uOiBmYWxzZSwgVmlzaWJsZTogdGQudGRWaXNpYmxlLCBXcmFwczogdHJ1ZSwgQ2xhc3M6IHRkLnRkQ2xhc3MsIFRlbXBsYXRlOiB0ZC5UZW1wbGF0ZSB9IDpcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxhbnk+eyBJRDoga2V5LCBHcm91cEhlYWRlcjogdGhDYXN0ZWQudGhHcm91cCwgR3JvdXBBZ2dyZWdhdGlvbjogISF0aENhc3RlZC50aEFnZ3JlZ2F0aW9uLCBWaXNpYmxlOiB0cnVlLCBXcmFwczogZmFsc2UsIENsYXNzOiB0aENhc3RlZC50aEdyb3VwQ2xhc3MgfHwgJycsIENvbnRlbnQ6IHRoaXMuZ2V0R3JvdXBDZWxsRGlzcGxheSg8R3JvdXA+aXRlbSwga2V5LCA8RXNUaERpcmVjdGl2ZT50aCkgfTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLlRNUFJvd1REc1tjdHhdKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNGaXhlZClcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLlRNUFJvd1REc1tjdHhdLnNwbGljZSgwICsgKGNvbnRleHRGaXhlZHNbY3R4XSsrKSwgMCwgaXRlbVRvQWRkKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLlRNUFJvd1REc1tjdHhdLnB1c2goaXRlbVRvQWRkKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuUm93Q29udGV4dHMucHVzaChjdHgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5UTVBSb3dURHNbY3R4XSA9IFtpdGVtVG9BZGRdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGV4dEZpeGVkc1tjdHhdID0gaXNGaXhlZCA/IDEgOiAwO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBTZSBub24gaG8gb2dnZXR0aSDDqCBpbnV0aWxlIGNoZSBjb250cm9sbG8gZ2xpIGVycm9yaSwgZGF0byBjaGUgZ2xpIGVzLXRkIG5vbiBlc2lzdGVyYW5ubyBkaSBjZXJ0byBlIGRpIGNvbnNlZ3VlbnphIGdsaSBlcy10aCBub24gc2FyYW5ubyByZWZlcmVuemlhdGlcclxuICAgICAgICBpZih0aGlzLlRNUEJvdW5kU291cmNlLmxlbmd0aCA9PSAwKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgIHZhciBlcnJzOiBzdHJpbmdbXSA9IFtdO1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGxldCB0aCA9IHRoc1tpXTtcclxuICAgICAgICAgICAgaWYgKCF0aC5SZWZlcmVuY2VkKVxyXG4gICAgICAgICAgICAgICAgZXJycy5wdXNoKHRoaXMuaXNFc1RoKHRoKSA/IHRoLklEIDogdGgudGgpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGVycnMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICB2YXIgZXJySWRzID0gZXJycy5qb2luKCcsICcpO1xyXG4gICAgICAgICAgICB0aHJvdyBcIkwnSUQgZGkgdW5vIG8gcGnDuSBFc1RoIG5vbiBoYW5ubyBhbGN1biBFc1RkIGFzc29jaWF0bzogXCIgKyBlcnJJZHM7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUGFydGVuZG8gZGFnbGkgKipFc1RocyoqIGJpbmRhdGkgZ2VuZXJhLCBhbGwnaW50ZXJubyBkZWwgZGl6aW9uYXJpbyAqKlRNUFJvd1RIcyoqIHR1dHRpIGkgY29udGVzdGkgZGVpIHZhcmkgb2dnZXR0aS5cclxuICAgICAqXHJcbiAgICAgKiBWZW5nb25vIGVzY2x1c2kgaSBUSCBcIkludGVybmlcIiBpbiBxdWFudG8gdmVuZ29ubyBnZW5lcmF0aSBkYWdsaSBvcmlnaW5hbGkgcXVpbmRpIGluY2x1ZGVybGkgdm9ycmViYmUgZGlyZSByaWVmZmV0dHVhcmUgbGUgb3BlcmF6aW9uaSBkdWUgdm9sdGVcclxuICAgICAqXHJcbiAgICAgKiBDb3N0bzogMSBzY2FuIEVzVGhzXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtFc1RoW10gfCBFc1RoRGlyZWN0aXZlW119IHRocyBDb2xvbm5lIGRlbGxhIHRhYmVsbGFcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBldmFsdWF0ZVJvd1Rocyh0aHM6IEVzVGhbXSB8IEVzVGhEaXJlY3RpdmVbXSkge1xyXG4gICAgICAgIGlmICh0aHMubGVuZ3RoID09IDApXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgbGV0IGNhc3RlZFZpZXcgPSA8QXBwU2VhcmNoPGFueT4+dGhpcy5WaWV3O1xyXG4gICAgICAgIGxldCBncm91cGluZ3NVbmRlZmluZWQgPSAhY2FzdGVkVmlldy5ncm91cGluZ3MgfHwgY2FzdGVkVmlldy5ncm91cGluZ3MubGVuZ3RoID09IDA7XHJcblxyXG4gICAgICAgIHRoaXMuVE1QUm93VEhzID0gW107XHJcbiAgICAgICAgbGV0IGZpeGVkID0gMDtcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRocy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgdGggPSB0aHNbaV07XHJcbiAgICAgICAgICAgIGxldCB0b0FkZDtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLmlzRXNUaCh0aCkpIHtcclxuICAgICAgICAgICAgICAgIHRvQWRkID0geyBGaXhlZDogdGguRml4ZWQsIElEOiB0aC5JRCwgVmlzaWJsZTogdGguVmlzaWJsZSwgQ2xhc3M6IHRoLkNsYXNzLCBPcmRlcjogdGguT3JkZXIsIE9yZGVyYWJsZTogdGguT3JkZXJhYmxlLCBUZW1wbGF0ZTogbnVsbCwgQ29udGVudDogdGguRGVzY3JpcHRpb24sIFdyYXA6IGZhbHNlIH07XHJcbiAgICAgICAgICAgICAgICBpZiAodGguRml4ZWQpXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5UTVBSb3dUSHMuc3BsaWNlKDAgKyAoZml4ZWQrKyksIDAsIHRvQWRkKTtcclxuICAgICAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLlRNUFJvd1RIcy5wdXNoKHRvQWRkKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIGlmICh0aC50aElmIHx8IHRoLnRoR3JvdXApIHtcclxuICAgICAgICAgICAgICAgIC8vIE1lbnRyZSBpbnNlcmlzY28gbWkgYXNzaWN1cm8gZGkgbWV0dGVyZSBsJ2VsZW1lbnRvIHBlciBiZW5lIGluIG9yZGluZSBpbiBiYXNlIGFsbGEgcHJvcHJpZXTDoCBcIkZpeGVkXCIuIFR1dHRlIGxlIGNvbG9ubmUgRml4ZWQgZGV2b25vIGZpbmlyZSBhbGwnaW5pemlvXHJcbiAgICAgICAgICAgICAgICAvLyAoUXVlc3RvIHByb2JhYmlsbWVudGUgZGl2ZW50ZXLDoCBpbCBjb21wb3J0YW1lbnRvIGRpIGRlZmF1bHQgYW5jaGUgcGVyIGxlIGNvbG9ubmUgXCJQaW5uZWRcIilcclxuXHJcbiAgICAgICAgICAgICAgICBsZXQgdGhDbGFzcyA9ICh0aC50aENsYXNzIHx8ICcnKSArICh0aC50aEdyb3VwID8gXCIgZXN0LWNvbC1taW5cIiA6IFwiXCIpO1xyXG4gICAgICAgICAgICAgICAgdG9BZGQgPSB7IEZpeGVkOiB0aC50aEZpeGVkIHx8IHRoLnRoR3JvdXAsIElEOiB0aC50aCwgVmlzaWJsZTogdGgudGhWaXNpYmxlLCBDbGFzczogdGhDbGFzcywgT3JkZXI6IHRoLnRoT3JkZXIsIE9yZGVyYWJsZTogdGgudGhPcmRlcmFibGUsIFRlbXBsYXRlOiB0aC5UZW1wbGF0ZSwgQ29udGVudDogbnVsbCwgV3JhcDogZmFsc2UgfTtcclxuICAgICAgICAgICAgICAgIGlmICh0aC50aEZpeGVkKVxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuVE1QUm93VEhzLnNwbGljZSgwICsgKGZpeGVkKyspLCAwLCB0b0FkZCk7XHJcbiAgICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5UTVBSb3dUSHMucHVzaCh0b0FkZCk7XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKGdyb3VwaW5nc1VuZGVmaW5lZCAmJiAodGgudGhBZ2dyZWdhdGlvbiB8fCB0aC50aEdyb3VwKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBncm91cEFnZ3JlZ2F0aW9uczogR3JvdXBPckFnZ3JlZ2F0aW9uW10gPSB0aGlzLmdldEdyb3VwQWdncmVnYXRpb25zKHRoKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNhc3RlZFZpZXcuZ3JvdXBpbmdzKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXN0ZWRWaWV3Lmdyb3VwaW5ncyA9IGdyb3VwQWdncmVnYXRpb25zO1xyXG4gICAgICAgICAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzdGVkVmlldy5ncm91cGluZ3MucHVzaCguLi5ncm91cEFnZ3JlZ2F0aW9ucyk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuUmVzZWFyY2hOZWVkZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGF0YSB1bmEgZGlyZXR0aXZhIEVzVGggcmVzdGl0dWlzY2UgbGEgbGlzdGEgZGVsbGUgYWdncmVnYXppb25pIHJpY2hpZXN0YSBwZXIgcXVlc3RhIGNvbG9ubmEgbyBpbCBncnVwcG8gY2hlIHJhcHByZXNlbnRhXHJcbiAgICAgKiBcclxuICAgICAqIEBwYXJhbSB7RXNUaERpcmVjdGl2ZX0gdGggRGlyZXR0aXZhXHJcbiAgICAgKiBcclxuICAgICAqIEByZXR1cm5zIHtHcm91cE9yQWdncmVnYXRpb25bXX0gTGlzdGEgZGVpIGdydXBwaSBvIGFnZ3JlZ2F6aW9uaSByZWxhdGl2aSBhbGxhIERpcmV0dGl2YSBwYXNzYXRhXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZ2V0R3JvdXBBZ2dyZWdhdGlvbnModGg6IEVzVGhEaXJlY3RpdmUpOiBHcm91cE9yQWdncmVnYXRpb25bXSB7XHJcbiAgICAgICAgbGV0IHJldCA9IFtdO1xyXG4gICAgICAgIC8vIEVzOiAne21pbjpkZC9NTS95eXl5fSAtIHttYXg6ZGQvTU0veXl5eX0nXHJcbiAgICAgICAgaWYgKHRoLnRoQWdncmVnYXRpb24pIHtcclxuICAgICAgICAgICAgdGhpcy5nZXRFc1RoRGlyZWN0aXZlTGlzdE9mQWdncmVnYXRpb25zKHRoKS5mb3JFYWNoKChhZ2c6IHsgZnVuYzogJ21pbicgfCAnbWF4JyB8ICdzdW0nIHwgJ2xpc3RhZ2cnLCBmb3JtYXQ6IHN0cmluZywgbWF0Y2g6IHN0cmluZyB9KSA9PiB7XHJcbiAgICAgICAgICAgICAgICByZXQucHVzaChuZXcgR3JvdXBPckFnZ3JlZ2F0aW9uKHRoLnRoLCBhZ2cuZnVuYykpO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAodGgudGhHcm91cClcclxuICAgICAgICAgICAgcmV0LnB1c2gobmV3IEdyb3VwT3JBZ2dyZWdhdGlvbih0aC50aCwgbnVsbCkpXHJcblxyXG4gICAgICAgIHJldHVybiByZXQ7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEYXRhIHVuYSBkaXJldHRpdmEgY29uIHVuIGZvcm1hdG8gcmVzdGl0dWlzY2UgdHV0dGUgbGUgY29wcGllIEZ1bnppb25lIGRpIEFnZ3JlZ2F6aW9uZSAtIEZvcm1hdG9cclxuICAgICAqIFxyXG4gICAgICogQHBhcmFtIHtFc1RoRGlyZWN0aXZlfSB0aCBEaXJldHRpdmEgRXNUaCBkaSBjdWkgY2FsY29sYXJlIGxlIGZ1bnppb25pIGRpIGFnZ3JlZ2F6aW9uZSB1c2F0ZVxyXG4gICAgICogXHJcbiAgICAgKiBAcmV0dXJucyB7eyBmdW5jOiBzdHJpbmcsIGZvcm1hdDogc3RyaW5nIH1bXX0gTGlzdGEgZGVsbGUgZnVuemlvbmkgZGkgYWdncmVnYXppb25lIHJpbGV2YXRlXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZ2V0RXNUaERpcmVjdGl2ZUxpc3RPZkFnZ3JlZ2F0aW9ucyh0aDogRXNUaERpcmVjdGl2ZSk6IHsgZnVuYzogJ21pbicgfCAnbWF4JyB8ICdzdW0nIHwgJ2xpc3RhZ2cnLCBmb3JtYXQ6IHN0cmluZywgbWF0Y2g6IHN0cmluZyB9W10ge1xyXG4gICAgICAgIGlmICghdGgudGhBZ2dyZWdhdGlvbilcclxuICAgICAgICAgICAgcmV0dXJuIFtdO1xyXG5cclxuICAgICAgICBsZXQgcmV0ID0gW107XHJcbiAgICAgICAgbGV0IGRpc3BsYXkgPSB0aC50aEFnZ3JlZ2F0aW9uO1xyXG4gICAgICAgIHZhciBtYXRjaGVzID0gZGlzcGxheS5tYXRjaCgve1thLXpBLVowLTlcXC86XSp9L2dpKTtcclxuICAgICAgICBpZiAoIW1hdGNoZXMpIHJldHVybiBbXTtcclxuICAgICAgICBtYXRjaGVzLmZvckVhY2gobSA9PiB7XHJcbiAgICAgICAgICAgIGxldCBzcGxpdCA9IG0uc3BsaXQoXCI6XCIpO1xyXG4gICAgICAgICAgICBsZXQgZnVuYyA9IG0sIGZvcm1hdCA9IFwiXCI7XHJcbiAgICAgICAgICAgIGlmIChzcGxpdC5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBFc2NsdWRvIHByaW1vIGUgdWx0aW1vIGNhcmF0dGVyZSAobGUgZ3JhZmZlKVxyXG4gICAgICAgICAgICAgICAgZnVuYyA9IHNwbGl0WzBdLnN1YnN0cigxKTtcclxuICAgICAgICAgICAgICAgIGZvcm1hdCA9IHNwbGl0WzFdLnN1YnN0cigwLCBzcGxpdFsxXS5sZW5ndGggLSAxKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgcmV0LnB1c2goeyBmdW5jOiA8J21pbicgfCAnbWF4JyB8ICdzdW0nIHwgJ2xpc3RhZ2cnPmZ1bmMsIGZvcm1hdDogZm9ybWF0LCBtYXRjaDogbSB9KTtcclxuICAgICAgICB9KTtcclxuICAgICAgICByZXR1cm4gcmV0O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTWV0b2RvIGNoZSBnZW5lcmEgbCdvcmRpbmUgZGkgZGVmYXVsdCBkZWxsZSBjb2xvbm5lXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtBcHBTZWFyY2g8YW55Pn0gdmlldyBBcHBTZWFyY2ggZGEgdXRpbGl6emFyZSBwZXIgcXVlc3RhIG9wZXJhemlvbmVcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBnZW5lcmF0ZURlZmF1bHRPcmRlcih2aWV3OiBBcHBTZWFyY2g8YW55Pikge1xyXG4gICAgICAgIGlmICh0aGlzLlRNUFJvd1RIcy5sZW5ndGggPT0gMClcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICAvLyBHZW5lcm8gb3JkaW5hbWVudG8gZGkgZGVmYXVsdCBkYSAwIGZpbm8gYSBkb3ZlIGRldmUgYXJyaXZhcmUuIFNpdHVhemlvbmUgYXR0dWFsZSBzZW56YSBob3Rwb3RhdG9cclxuICAgICAgICBpZiAoIXZpZXcuY29sdW1uX29yZGVyaW5nIHx8IHZpZXcuY29sdW1uX29yZGVyaW5nLmxlbmd0aCA9PSAwKSB7XHJcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5UTVBSb3dUSHMubGVuZ3RoOyBpKyspXHJcbiAgICAgICAgICAgICAgICB0aGlzLk9yZGVyRGlyZWN0aXZlcy5wdXNoKHRoaXMuVE1QUm93VEhzW2ldLklEKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICB0aGlzLk9yZGVyRGlyZWN0aXZlcyA9IHZpZXcuY29sdW1uX29yZGVyaW5nO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQXBwbGljYSBsJ29yZGluZSBzcGVjaWZpY2F0byBhbGxlIHZhcmllIGNvbG9ubmVcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge0FwcFNlYXJjaDxhbnk+fSB2aWV3IEFwcFNlYXJjaCBkYSB1dGlsaXp6YXJlIHBlciBxdWVzdGEgb3BlcmF6aW9uZVxyXG4gICAgICogQHBhcmFtIHtib29sZWFufSBmaW5hbGl6ZSBTZSAqKnRydWUqKiBzaWduaWZpY2EgY2hlIG5vbiBtaSBhc3BldHRvIGRpIGRvdmVyIGVmZmV0dHVhcmUgYWx0cmUgb3BlcmF6aW9uaSBlIHBvc3NvIHJlbmRlcml6emFyZSBsYSBzaXR1YXppb25lIGluIGJhc2UgYWkgUm93Q29udGV4dFxyXG4gICAgICogU2VuemEgZmluYWxpemUgc2lnbmlmaWNhIGNoZSBtaSBhc3BldHRvIGFsdHJlIG9wZXJhemlvbmkgY2hlIHByaW1hIG8gcG9pIHJpY2hpYW1lcmFubm8gcXVlc3RhIGZ1bnppb25lIGNvbCBmaW5hbGl6ZS5cclxuICAgICAqXHJcbiAgICAgKiBBZCBlc2VtcGlvLCB1bmEgdm9sdGEgc2VsZXppb25hdG8gb3JkaW5hbWVudG8gZmlzaWNvL2xvZ2ljbyBkZWxsZSBjb2xvbm5lIHNvIGNoZSBwYXJ0ZSB1biBhbHRyYSByaWNlcmNhIGNoZSBtaSByaXZhbG9yaXp6ZXJhIGRhIFwid3JpdGVWYWx1ZVwiLCBjaGUgZ2nDoCBjaGlhbWEgcXVlc3RhIGZ1bnppb25lLlxyXG4gICAgICogTWV0dGVuZG8gc29sbyBsYSBjaGlhbWF0YSBkYSBcIndyaXRlVmFsdWVcIiBjb21lIFwiZmluYWxpenphbnRlXCIgbWkgYXNzaWN1cm8gY2hlIHNtYW5hdHRhbWVudGkgYSBmcm9udGVuZCBub24gY2F1c2lubyBmbGlja2VyaW5nIGZpbm8gYSBxdWFuZG8gbm9uIHNlcnZvbm9cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBhcHBseU9yZGVyaW5nKHZpZXc6IEFwcFNlYXJjaDxhbnk+LCBmaW5hbGl6ZTogYm9vbGVhbikge1xyXG4gICAgICAgIC8vIEdlbmVybyBvcmRpbmFtZW50byBwZXIgZ2xpIGhlYWRlclxyXG4gICAgICAgIGxldCBuZXdIZWFkZXJzID0gW107XHJcblxyXG4gICAgICAgIC8vIFNlIGRldm8gZmluYWxpenphcmUgYWdnYW5jaW8gdHV0dGUgbGUgdmFyaWFiaWxpIGRpIGJpbmRcclxuICAgICAgICBpZiAoZmluYWxpemUpIHtcclxuICAgICAgICAgICAgdGhpcy5PcmRlckRpcmVjdGl2ZXMuZm9yRWFjaChvID0+IHtcclxuICAgICAgICAgICAgICAgIGxldCBoZWFlZHJJdGVtID0gdGhpcy5UTVBSb3dUSHMuZmlsdGVyKHQgPT4gdC5JRCA9PSBvKVswXTtcclxuICAgICAgICAgICAgICAgIG5ld0hlYWRlcnMucHVzaChoZWFlZHJJdGVtKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIHRoaXMuVE1QUm93VEhzID0gbmV3SGVhZGVycztcclxuXHJcbiAgICAgICAgICAgIC8vIEdlbmVybyBvcmRpbmFtZW50byBwZXIgbGUgY2VsbGVcclxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLlJvd0NvbnRleHRzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBsZXQgY29udGV4dCA9IHRoaXMuVE1QUm93VERzW3RoaXMuUm93Q29udGV4dHNbaV1dO1xyXG4gICAgICAgICAgICAgICAgbGV0IG5ld0NvbnRleHQgPSBbXTtcclxuXHJcbiAgICAgICAgICAgICAgICB0aGlzLk9yZGVyRGlyZWN0aXZlcy5mb3JFYWNoKG8gPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBjb250ZXh0SXRlbSA9IGNvbnRleHQuZmlsdGVyKHQgPT4gdC5JRCA9PSBvKVswXTtcclxuICAgICAgICAgICAgICAgICAgICBuZXdDb250ZXh0LnB1c2goY29udGV4dEl0ZW0pO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICAgICAgdGhpcy5UTVBSb3dURHNbdGhpcy5Sb3dDb250ZXh0c1tpXV0gPSBuZXdDb250ZXh0O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB2aWV3LmNvbHVtbl9vcmRlcmluZyA9IHRoaXMuT3JkZXJEaXJlY3RpdmVzO1xyXG4gICAgICAgIHRoaXMuY2hhbmdlZCgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vICNlbmRyZWdpb25cclxuXHJcbiAgICAvLyAjcmVnaW9uIEdlc3Rpb25lIHJhZ2dydXBwYW1lbnRpIHBlciByaWdhXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBPdHRpZW5lIHVuIGVsZW1lbnRvIGRpIHNlcGFyYXppb25lIGZyYSBHcnVwcGkgY2hlIHNlcnZlIHBlciBwYWdpbmFyZSBsZSByaWNlcmNoZSBhbGwnaW50ZXJubyBkaSBvZ25pIHNpbmdvbG8gZ3J1cHBvXHJcbiAgICAgKiBcclxuICAgICAqIEBwYXJhbSB7QXBwU2VhcmNoPGFueT59IHZpZXcgVmlldyB1dGlsaXp6YXRhIHBlciBsYSByaWNlcmNhLiBNZSBuZSBzYWx2byBpIHBhcmFtZXRyaSBuZWwgc2VwYXJhdG9yZSBhdHR1YWxlIGRhdG8gY2hlIG5lIGhvIGJpc29nbm8gcGVyIGNhcmljYXJlIGFsdHJpIGVsZW1lbnRpXHJcbiAgICAgKiBmYWNlbnRpIHJpZmVyaW1lbnRvIGFsbG8gc3Rlc3NvIGNvbnRlc3RvXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcGFyZW50IFBhcmVudCBwYXRoIGNoZSByYXBwcmVzZW50YSBhIHF1YWxlIGdydXBwbyDDqCBhZmZpYmJpYXRvIHF1ZXN0byBzZXBhcmF0b3JlXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbGV2ZWwgTGl2ZWxsbyBkZWwgZ3J1cHBvIGRpIGN1aSBxdWVzdG8gZWxlbWVudG8gw6ggc2VwYXJhdG9yZSwgdmllbmUgdXNhdG8gcGVyIGFwcGxpY2FyZSBsYSBjbGFzc2UgXCJlc3QtbHZsLXt7bGV2ZWx9fVwiXHJcbiAgICAgKiBcclxuICAgICAqIEByZXR1cm5zIHthbnl9IEVsZW1lbnRvIGRpIHNlcGFyYXppb25lIGNvbnRlbmVudGUgdHV0dGkgaSBiaW5kIHBlciBwcmVzZW50YXJlIHVuYSBwYWdpbmF6aW9uZSBzb3R0byBxdWVzdG8gZ3J1cHBvIGxhdG8gaW50ZXJmYWNjaWFcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBnZXRHcm91cFNlcGFyYXRvcih2aWV3OiBBcHBTZWFyY2g8YW55PiwgcGFyZW50OiBzdHJpbmcsIGxldmVsOiBudW1iZXIpOiB7IF9zZXA6IGJvb2xlYW4sIF9ncm91cGxldmVsOiBudW1iZXIsIF9wYXJlbnQ6IHN0cmluZywgZmlsdGVyczogeyBjb2x1bW46IHN0cmluZywgdmFsdWU6IHN0cmluZyB9W10sIHBhZ2U6IG51bWJlciwgcGFnZXM6IG51bWJlciwgaXRlbXNwZXJwYWdlOiBudW1iZXI7IGNvdW50OiBudW1iZXIgfSB7XHJcbiAgICAgICAgbGV0IGl0ZW0gPSB7XHJcbiAgICAgICAgICAgIF9zZXA6IHRydWUsXHJcbiAgICAgICAgICAgIF9wYXJlbnQ6IHBhcmVudCxcclxuICAgICAgICAgICAgX2dyb3VwbGV2ZWw6IGxldmVsLFxyXG4gICAgICAgICAgICBmaWx0ZXJzOiB2aWV3LnJlcXVlc3RlZGdyb3Vwcy5tYXAodCA9PiB7IHJldHVybiB7IGNvbHVtbjogdC5jb2x1bW4sIHZhbHVlOiB0LnZhbHVlIH0gfSksXHJcbiAgICAgICAgICAgIHBhZ2U6IHZpZXcucGFnZSxcclxuICAgICAgICAgICAgcGFnZXM6IHZpZXcucGFnZXMsXHJcbiAgICAgICAgICAgIGl0ZW1zcGVycGFnZTogdmlldy5pdGVtc3BlcnBhZ2VvdmVycmlkZSxcclxuICAgICAgICAgICAgY291bnQ6IHZpZXcub2JqZWN0Y291bnRcclxuICAgICAgICB9O1xyXG4gICAgICAgIHRoaXMuY2FsY3VsYXRlSGFzaChbaXRlbV0pO1xyXG4gICAgICAgIHJldHVybiBpdGVtO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGF0YSB1bmEgY29sb25uYSBlZmZldHR1YSBsYSByaWVtaXNzaW9uZSBkaSB0dXR0ZSBsZSByaWNlcmNoZSByZWxhdGl2ZS5cclxuICAgICAqIFxyXG4gICAgICogRXMuIEhvIDIgY2FtcGkgZGkgZ3J1cHBvIGUgaG8gZXNwYW5zbyBmaW5vIGEgdmVkZXJlIGkgdmFsb3JpIGZpbm8gYWQgdW4gbGl2ZWxsbyBxdWFsc2lhc2kuXHJcbiAgICAgKiBDbGljY28gbCdvcmRpbmFtZW50byBzdWwgc2Vjb25kbyBncnVwcG8uXHJcbiAgICAgKiBUdXR0ZSBsZSByaWNlcmNoZSByZWxhdGl2ZSBhaSBwcmltaSBncnVwcGkgZGV2b25vIGVzc2VyZSByaWVzZWd1aXRlLiBRdWFuZG8gaSByaXN1bHRhdGkgYXJyaXZlcmFubm8gY2kgcGVuc2Vyw6AgaWwgbWV0b2RvICoqYmluZERpc3BsYXlUb0xvYWRlZEl0ZW1zT3JHcm91cHMqKlxyXG4gICAgICogYSB0YWdsaWFyZSB2aWEgZ2xpIG9nZ2V0dGkgbm9uIHBpw7kgdmlzdWFsaXp6YXRpXHJcbiAgICAgKiBcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBjb2x1bW4gQ29sb25uYSBzdSBjdWkgc2kgw6ggZWZmZXR0dWF0YSB1bidvcGVyYXppb25lIGRpIG9yZGluYW1lbnRvXHJcbiAgICAgKiBAcGFyYW0ge0FwcE9yZGVyaW5nW119IG9yZGVyaW5ncyBEaXJldHRpdmUgZGkgb3JkaW5hbWVudG8gZGEgYXBwbGljYXJlIGFsbGUgdmFyaWUgc290dG9yaWNlcmNoZVxyXG4gICAgICogXHJcbiAgICAgKiBAdG9kbzogVGVzdGFyZVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGVtaXRSb3dHcm91cGluZ1NlYXJjaGVzKGNvbHVtbjogc3RyaW5nLCBvcmRlcmluZ3M6IEFwcE9yZGVyaW5nW10pIHtcclxuICAgICAgICAvLyBQZXIgdHV0dGUgbGUgcmljZXJjaGUgaW50ZXJtZWRpZSBjaGUgZGV2byByaXZhbHV0YXJlIGxlIHJlLWVtaXR0byBpbiBtb2RvIGRhIGFnZ2lvcm5hcmdsaSBpIGRhdGlcclxuICAgICAgICB2YXIgbWVhbmluZ2Z1bEFwcFNlYXJjaGVzID0gdGhpcy5ncm91cFNlYXJjaFJlcXVlc3RzQ2FjaGUuZmlsdGVyKHQgPT4gdC5wYXRoLmVuZHNXaXRoKGNvbHVtbikpLm1hcCh0ID0+IHQudmlldyk7XHJcbiAgICAgICAgbWVhbmluZ2Z1bEFwcFNlYXJjaGVzLmZvckVhY2goYXMgPT4ge1xyXG4gICAgICAgICAgICAvLyBPdnZpYW1lbnRlIGdsaSBvcmlkbmFtZW50aSBkZXZvbm8gZXNzZXJlIHF1ZWxsaSBhcHBlbmEgZ2VuZXJhdGlcclxuICAgICAgICAgICAgYXMub3JkZXJzID0gb3JkZXJpbmdzO1xyXG4gICAgICAgICAgICB0aGlzLmVtaXRTZWFyY2hSZXF1ZXN0KGZhbHNlLCBhcyk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBIZWxwZXIgY2hlIGNhbGNvbGEgaWwgY29udGVudXRvIGRpIHVuYSBjZWxsYSByZWxhdGl2YSBhIHVuIGdydXBwbyByaWdhLCB0ZW5lbmRvIGNvbnRvIGRlbCBmb3JtYXRvIGRlbGxlIGV2ZW50dWFsaSBhZ2dyZWdhemlvbmlcclxuICAgICAqIFxyXG4gICAgICogQHBhcmFtIHtHcm91cH0gZ3JwIEdydXBwbyBkaSBjdWkgbW9zdHJhcmUgbGUgY2VsbGVcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBjZWxsIENlbGxhIGF0dHVhbGUgZGkgY3VpIGNhbGNvbGFyZSBpbCB0ZXN0b1xyXG4gICAgICogQHBhcmFtIHtFc1RoRGlyZWN0aXZlfSBoZWFkZXIgSGVhZGVyIHJlbGF0aXZvIGFsbGEgY2VsbGEgYXR0dWFsZSwgdXRpbGl6emF0YSBwZXIgaWRlbnRpZmljYXJlIGxlIGluZm9ybWF6aW9uaSBkaSBhZ2dyZWdhemlvbmVcclxuICAgICAqIFxyXG4gICAgICogQHJldHVybnMge3N0cmluZ30gVGVzdG8gZmluYWxlIGNhbGNvbGF0byBwZXIgbGEgKipjZWxsKiogY29ycmVudGUsIGluIGJhc2UgYWxsZSBhZ2dyZWdhemlvbmkgZGkgKipoZWFkZXIqKlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGdldEdyb3VwQ2VsbERpc3BsYXkoZ3JwOiBHcm91cCwgY2VsbDogc3RyaW5nLCBoZWFkZXI6IEVzVGhEaXJlY3RpdmUpOiBzdHJpbmcge1xyXG4gICAgICAgIGlmICgoPGFueT5ncnApLl9zZXApXHJcbiAgICAgICAgICAgIHJldHVybiBcIlwiO1xyXG4gICAgICAgIGxldCBkaXNwbGF5ID0gaGVhZGVyLnRoQWdncmVnYXRpb247XHJcbiAgICAgICAgaWYgKGdycC5jb2x1bW4gPT0gY2VsbClcclxuICAgICAgICAgICAgcmV0dXJuIGdycC52YWx1ZTtcclxuICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgbGV0IGFnZyA9IGdycC5hZ2dyZWdhdGlvbnMuZmlsdGVyKHQgPT4gdC5jb2x1bW4gPT0gY2VsbCk7XHJcbiAgICAgICAgICAgIGlmICghYWdnKSByZXR1cm4gXCJcIjtcclxuXHJcbiAgICAgICAgICAgIHRoaXMuZ2V0RXNUaERpcmVjdGl2ZUxpc3RPZkFnZ3JlZ2F0aW9ucyhoZWFkZXIpLmZvckVhY2goKGl0bTogeyBmdW5jOiAnbWluJyB8ICdtYXgnIHwgJ3N1bScgfCAnbGlzdGFnZycsIGZvcm1hdDogc3RyaW5nLCBtYXRjaDogc3RyaW5nIH0pID0+IHtcclxuICAgICAgICAgICAgICAgIGxldCBhZ2dWYWx1ZSA9IGFnZy5maW5kKHQgPT4gdC5hZ2dyZWdhdGlvbiA9PSBpdG0uZnVuYykudmFsdWU7XHJcbiAgICAgICAgICAgICAgICBkaXNwbGF5ID0gZGlzcGxheS5yZXBsYWNlKGl0bS5tYXRjaCwgdGhpcy5mb3JtYXRBZ2dyZWdhdGlvblZhbHVlKGFnZ1ZhbHVlLCBpdG0uZm9ybWF0KSlcclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICByZXR1cm4gZGlzcGxheTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXN0aXNjZSBpIGNsaWNrIHN1bGxhIHRhYmVsbGEgc29sbyBwZXIgbGUgcmlnaGUgYSBncnVwcG8uIFxyXG4gICAgICogTyByaW11b3ZlIGdsaSBlbGVtZW50aSBhdHR1YWxtZW50ZSBwcmVzZW50aSBvIGNhcmljYSBpbCBjb250ZW51dG8gZGVsIGdydXBwb1xyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7YW55fSBncm91cCBHcnVwcG8gYmluZGF0byBzdSBjdWkgc2kgw6ggZWZmZXR0dWF0byBpbCBjbGlja1xyXG4gICAgICpcclxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSAqKnRydWUqKiBzZSBsJ29wZXJhaXpvbmUgw6ggYW5kYXRhIGEgYnVvbiBmaW5lLCAqKmZhbHNlKiogYWx0cmltZW50aVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgaGFuZGxlR3JvdXBDbGljayhncm91cDogR3JvdXApOiBib29sZWFuIHtcclxuICAgICAgICBsZXQgY2FzdGVkID0gdGhpcy5WaWV3IGFzIEFwcFNlYXJjaDxhbnk+O1xyXG4gICAgICAgIGxldCBhbnlHcm91cCA9ICg8YW55Pmdyb3VwKTtcclxuICAgICAgICBhbnlHcm91cC5fZXhwYW5kZWQgPSAhYW55R3JvdXAuX2V4cGFuZGVkXHJcblxyXG4gICAgICAgIGlmIChhbnlHcm91cC5fZXhwYW5kZWQpIHtcclxuICAgICAgICAgICAgaWYgKCFjYXN0ZWQucmVxdWVzdGVkZ3JvdXBzKVxyXG4gICAgICAgICAgICAgICAgY2FzdGVkLnJlcXVlc3RlZGdyb3VwcyA9IFtuZXcgR3JvdXBGaWx0ZXIoZ3JvdXAuY29sdW1uLCBncm91cC52YWx1ZSldO1xyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGxldCBsZXZlbCA9IGFueUdyb3VwLl9ncm91cGxldmVsO1xyXG4gICAgICAgICAgICAgICAgLy8gc2UgaWwgZ3J1cHBvIGNsaWNjYXRvIG5vbiBoYSB1biBsaXZlbGxvIMOoIGlsIHByaW1vIGdydXBwbywgcXVpbmRpIG9yZGluYW1lbnRvIHVuaWNvXHJcbiAgICAgICAgICAgICAgICAvLyBhbHRyaW1lbnRpIGRldm8gcmltdW92ZXJlIHR1dHRpIGkgZmlsdHJpIHN1IGxpdmVsbGkgc3VwZXJpb3JpIGFsIGxldmVsIGNsaWNjYXRvIGUgYWdnaXVuZ2VyZSBpbCBsZXZlbCBjbGljY2F0b1xyXG4gICAgICAgICAgICAgICAgaWYgKCFsZXZlbClcclxuICAgICAgICAgICAgICAgICAgICBjYXN0ZWQucmVxdWVzdGVkZ3JvdXBzID0gW25ldyBHcm91cEZpbHRlcihncm91cC5jb2x1bW4sIGdyb3VwLnZhbHVlKV07XHJcbiAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBjYXN0ZWQucmVxdWVzdGVkZ3JvdXBzID0gW107XHJcbiAgICAgICAgICAgICAgICAgICAgYW55R3JvdXAuX3BhcmVudFJvdXRlLmZvckVhY2goKHN0ZXA6IHsgY29sdW1uOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcgfSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXN0ZWQucmVxdWVzdGVkZ3JvdXBzLnB1c2gobmV3IEdyb3VwRmlsdGVyKHN0ZXAuY29sdW1uLCBzdGVwLnZhbHVlKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgY2FzdGVkLnJlcXVlc3RlZGdyb3Vwcy5wdXNoKG5ldyBHcm91cEZpbHRlcihncm91cC5jb2x1bW4sIGdyb3VwLnZhbHVlKSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHRoaXMuY2hhbmdlZCgpO1xyXG4gICAgICAgICAgICB0aGlzLmVtaXRTZWFyY2hSZXF1ZXN0KHRydWUpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgbGV0IHBhdGggPSAoYW55R3JvdXAuX3BhcmVudCB8fCAnJykgKyBncm91cC52YWx1ZTtcclxuXHJcbiAgICAgICAgICAgIC8vIFNlIGhvIGNoaXVzbyB1biBncnVwcG8gbm9uIG1pIHNlcnZlIHJpZWZmZXR0dWFyZSByaWNlcmNlLCBtaSBiYXN0YSBlbGltaW5hcmUgZGFnbGkgb2dnZXR0aSBiaW5kYXRpIHR1dHRpIGdsaSBlbGVtZW50aSBzb3R0b3N0YW50aSBhIHF1ZWwgZ3J1cHBvXHJcbiAgICAgICAgICAgIHRoaXMuYm91bmRTb3VyY2UgPSB0aGlzLmJvdW5kU291cmNlLmZpbHRlcih0ID0+ICF0Ll9wYXJlbnQgfHwgIXQuX3BhcmVudC5zdGFydHNXaXRoKHBhdGgpKTtcclxuXHJcbiAgICAgICAgICAgIC8vIGRldm8gcGVyw7IgYW5jaGUgcmltdW92ZXJlIGV2ZW50dWFsaSBjYWNoZSByZWxhdGl2ZVxyXG4gICAgICAgICAgICB0aGlzLmdyb3VwU2VhcmNoUmVxdWVzdHNDYWNoZSA9IHRoaXMuZ3JvdXBTZWFyY2hSZXF1ZXN0c0NhY2hlLmZpbHRlcih0ID0+IHQucGF0aCAhPSBwYXRoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRnVuemlvbmUgY2hlIGRhdG8gdW4gdmFsb3JlIGxvIGZvcm1hdHRhIGluIGJhc2UgYWwgdGlwb1xyXG4gICAgICogXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgVmFsb3JlIGNoZSBnZW5lcmFsZW1udGUgcHXDsiBlc3NlcmUgdW5hIGRhdGEgbyB1biBudW1lcm9cclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBmcm9tYXQgRm9ybWF0byBzdSBjdWkgZm9ybWF0dGFyZSBpbCB2YWxvcmUuIFB1w7IgZXNzZXJlIGFkIGVzZW1waW8gXCJzbWFsbFwiLCBcImxvbmdcIiBcInZlcnlsb25nXCIgcGVyIGxlIGRhdGUgbyBGezAtOX0gcGVyIGkgbnVtZXJpIGRlY2ltYWxpXHJcbiAgICAgKiBcclxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFZhbG9yZSBkZWxsJ2FnZ3JlZ2F6aW9uZSBmb3JtYXR0YXRvIGNvbWUgc2kgZGV2ZVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGZvcm1hdEFnZ3JlZ2F0aW9uVmFsdWUodmFsdWU6IHN0cmluZywgZm9ybWF0Pzogc3RyaW5nKTogc3RyaW5ne1xyXG4gICAgICAgIGlmICghZm9ybWF0KVxyXG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XHJcblxyXG4gICAgICAgIGxldCBpc051bWJlciA9ICFOdW1iZXIuaXNOYU4odmFsdWUpICYmICFmb3JtYXQgfHwgZm9ybWF0LnN0YXJ0c1dpdGgoXCJGXCIpO1xyXG5cclxuICAgICAgICBsZXQgZGF0ZSA9IG51bGw7XHJcbiAgICAgICAgLy8gQWxjdW5lIHZlcnNpb25lIGRpIGV4dGVuc2lvbnMgcmlzY2hpYW5vIGRpIGNyYXNoYXJlIGNvbiBjb3NlIG5vbiBkYXRlLi4uIMOoIHN0YXRvIHJpc29sdG8gZG9wbyBxdWluZGkgcXVlc3RvIHRyeSAtIGNhdGNoIGluIHJlYWx0w6BcclxuICAgICAgICAvLyB0b3JuYSB1dGlsZSBzb2xvIGNvbiB2ZXJzaW9uaSB2ZWNjaGllL2RlcHJlY2F0ZSBkZWxsYSBsaWJyZXJpYSBAZXNmYWVuemEvZXh0ZW5zaW9uc1xyXG4gICAgICAgIHRyeSB7IGRhdGUgPSB0aGlzLmRhdGVFeHRzLmdldERhdGVDb252ZXJ0aW9uKHZhbHVlKTsgfSBjYXRjaCB7IH1cclxuXHJcbiAgICAgICAgaWYgKGRhdGUpXHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRhdGVFeHRzLmdldEZvcm1hdHRlZChkYXRlLCBmb3JtYXQgPT0gJ3NtYWxsJywgZm9ybWF0ID09ICd2ZXJ5bG9uZycpO1xyXG4gICAgICAgIGVsc2UgaWYgKGlzTnVtYmVyKSB7XHJcbiAgICAgICAgICAgIGlmIChmb3JtYXQuc3RhcnRzV2l0aChcIkZcIikgJiYgIU51bWJlci5pc05hTihmb3JtYXQuc3Vic3RyKDEpKSlcclxuICAgICAgICAgICAgICAgIHJldHVybiBwYXJzZUZsb2F0KHZhbHVlKS50b0ZpeGVkKHBhcnNlSW50KGZvcm1hdC5zdWJzdHIoMSkpKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIFF1aSBjaSBmaW5pc2NvIHNpYSBwZXIgaW5wdXQgY2hlIG5vbiBzb25vIG7DqSBkYXRlIG7DqSBudW1lcmksIHNpYSBwZXIgZm9ybWF0aSBub24gcmljb25vc2NpdXRpXHJcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xyXG4gICAgfVxyXG5cclxuICAgIC8vICNlbmRyZWdpb25cclxuXHJcbiAgICAvLyAjcmVnaW9uIEdlc3Rpb25lIE9wZXJhaXpvbmkgZGlhbG9nIG9yZGluYW1lbnRvL3Zpc2liaWxpdMOgIGNvbG9ubmVcclxuXHJcbiAgICAvKipcclxuICAgICAqIEFsbCdpbnRlcm5vIGRlbGxhIGRpYWxvZyBcIk9yZGluYW1lbnRvIGUgVmlzaWJpbGl0w6AgQ29sb25uZVwiIG1ldHRlIGxhIGNvbG9ubmEgc3BlY2lmaWNhdGEgcHJpbWEgZGVsbGEgY29sb25uYSBwcmVjZWRlbnRlXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtFc1RhYmxlQ29sdW1ufSBjb2x1bW5JdGVtIENvbG9ubmEgZGEgc3Bvc3RhcmVcclxuICAgICAqL1xyXG4gICAgcHVibGljIHNlbmRVcChjb2x1bW5JdGVtOiBFc1RhYmxlQ29sdW1uKSB7XHJcbiAgICAgICAgbGV0IGl0ZW1JbmRleCA9IHRoaXMuVE1QQ29sdW1uc0xpc3QuaW5kZXhPZihjb2x1bW5JdGVtKTtcclxuICAgICAgICBpZiAodGhpcy5UTVBDb2x1bW5zTGlzdFtpdGVtSW5kZXggLSAxXS5maXhlZClcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIHRoaXMudXRpRXh0cy5zd2FwKHRoaXMuVE1QQ29sdW1uc0xpc3QsIGl0ZW1JbmRleCwgaXRlbUluZGV4IC0gMSk7XHJcblxyXG4gICAgICAgIC8vIE5vbiBwb3NzbyBmYXJlIEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkodGhpcy5Db2x1bW5zTGlzdCkpIHBlcmNow6kgY29udGllbmUgcmlmZXJpbWVudGkgYSBUZW1wbGF0ZVJlZlxyXG4gICAgICAgIGxldCB0bXAgPSBbXTtcclxuICAgICAgICB0aGlzLlRNUENvbHVtbnNMaXN0LmZvckVhY2goYyA9PiB7IHRtcC5wdXNoKE9iamVjdC5hc3NpZ24oe30sIGMpKTsgfSk7XHJcbiAgICAgICAgdGhpcy5UTVBDb2x1bW5zTGlzdCA9IHRtcDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEFsbCdpbnRlcm5vIGRlbGxhIGRpYWxvZyBcIk9yZGluYW1lbnRvIGUgVmlzaWJpbGl0w6AgQ29sb25uZVwiIG1ldHRlIGxhIGNvbG9ubmEgc3BlY2lmaWNhdGEgZG9wbyBsYSBjb2xvbm5hIHN1Y2Nlc3NpdmFcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge0VzVGFibGVDb2x1bW59IGNvbHVtbkl0ZW0gQ29sb25uYSBkYSBzcG9zdGFyZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc2VuZERvd24oY29sdW1uSXRlbTogRXNUYWJsZUNvbHVtbikge1xyXG4gICAgICAgIGxldCBpdGVtSW5kZXggPSB0aGlzLlRNUENvbHVtbnNMaXN0LmluZGV4T2YoY29sdW1uSXRlbSk7XHJcbiAgICAgICAgdGhpcy51dGlFeHRzLnN3YXAodGhpcy5UTVBDb2x1bW5zTGlzdCwgaXRlbUluZGV4LCBpdGVtSW5kZXggKyAxKTtcclxuXHJcbiAgICAgICAgLy8gTm9uIHBvc3NvIGZhcmUgSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeSh0aGlzLkNvbHVtbnNMaXN0KSkgcGVyY2jDqSBjb250aWVuZSByaWZlcmltZW50aSBhIFRlbXBsYXRlUmVmXHJcbiAgICAgICAgbGV0IHRtcCA9IFtdO1xyXG4gICAgICAgIHRoaXMuVE1QQ29sdW1uc0xpc3QuZm9yRWFjaChjID0+IHsgdG1wLnB1c2goT2JqZWN0LmFzc2lnbih7fSwgYykpOyB9KTtcclxuICAgICAgICB0aGlzLlRNUENvbHVtbnNMaXN0ID0gdG1wO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQWxsJ2ludGVybm8gZGVsbGEgZGlhbG9nIFwiT3JkaW5hbWVudG8gZSBWaXNpYmlsaXTDoCBDb2xvbm5lXCIgaW52ZXJ0ZSBsZSBpbXBvc3RhemlvbmkgZGkgdmlzaWJpbGl0w6AgZGVsbGEgY29sb25uYVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7RXNUYWJsZUNvbHVtbn0gY29sdW1uSXRlbSBDb2xvbm5hIGRhIHNwb3N0YXJlXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBjb2x1bW5DbGlja2VkKGl0ZW06IEVzVGFibGVDb2x1bW4pIHtcclxuICAgICAgICB0aGlzLmxhc3RTZWxlY3RlZEl0ZW1JRCA9IGl0ZW0uaWQ7XHJcbiAgICAgICAgaWYgKCF0aGlzLkhpZGRlbkNvbHVtbnMgfHwgaXRlbS5maXhlZClcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICBpdGVtLnZpc2libGUgPSAhaXRlbS52aXNpYmxlO1xyXG4gICAgICAgIHRoaXMudXBkYXRlR2xvYmFsQ29sVmlzQ2hlY2soKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEFsbCdhcGVydHVyYSBkZWxsYSBkaWFsb2cgXCJPcmRpbmFtZW50byBlIFZpc2liaWxpdMOgIENvbG9ubmVcIiByaWNhcmljYSBsZSBpbmZvcm1hemlvbmkgYXR0dWFsaSBwZXIgcGVybWV0dGVyZSBsYSBtb2RpZmljYVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVzZXRDb2x1bW5WaXNTZWxlY3Rpb24oKSB7XHJcbiAgICAgICAgdGhpcy5UTVBDb2x1bW5zTGlzdCA9IFtdO1xyXG4gICAgICAgIC8vIE5vbiBwb3NzbyBmYXJlIEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkodGhpcy5Db2x1bW5zTGlzdCkpIHBlcmNow6kgY29udGllbmUgcmlmZXJpbWVudGkgYSBUZW1wbGF0ZVJlZlxyXG5cclxuICAgICAgICB0aGlzLlRNUENvbHVtbnNMaXN0ID0gW107XHJcbiAgICAgICAgdGhpcy5Db2x1bW5zTGlzdC5mb3JFYWNoKGMgPT4geyB0aGlzLlRNUENvbHVtbnNMaXN0LnB1c2goT2JqZWN0LmFzc2lnbih7fSwgYykpOyB9KTtcclxuXHJcbiAgICAgICAgbGV0IHJlb3JkZXJlZENvbExpc3QgPSBbXTtcclxuXHJcbiAgICAgICAgaWYgKHRoaXMuQ29sdW1uc09yZGVyaW5nKSB7XHJcbiAgICAgICAgICAgIHRoaXMuT3JkZXJEaXJlY3RpdmVzLmZvckVhY2gobyA9PiB7XHJcbiAgICAgICAgICAgICAgICBsZXQgY29sdW1uID0gdGhpcy5UTVBDb2x1bW5zTGlzdC5maWx0ZXIodCA9PiB0LmlkID09IG8pWzBdO1xyXG4gICAgICAgICAgICAgICAgLy8gUG90cmVpIG5vbiBhdmVybmUgbmVsIGNhc28gY2kgc2lhIGlsIGZsYWcgSGlkZGVuQ29sdW1ucyBhIGZhbHNlLCBldml0byBkaSBpbnNlcmlyZSBkZWdsaSB1bmRlZmluZWRcclxuICAgICAgICAgICAgICAgIGlmIChjb2x1bW4pXHJcbiAgICAgICAgICAgICAgICAgICAgcmVvcmRlcmVkQ29sTGlzdC5wdXNoKGNvbHVtbik7XHJcbiAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5UTVBDb2x1bW5zTGlzdCA9IHJlb3JkZXJlZENvbExpc3Q7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLnVwZGF0ZUdsb2JhbENvbFZpc0NoZWNrKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSaWFnZ2lvcm5hIGxlICoqT3JkZXJEaXJlY3RpdmVzKiogY29uIGxlIGluZm9ybWF6aW9uaSBpbiAgKipDb2x1bW5zTGlzdCoqXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgcmVmcmVzaENvbHVtbk9yZGVyaW5nKCkge1xyXG4gICAgICAgIHRoaXMuT3JkZXJEaXJlY3RpdmVzID0gW107XHJcblxyXG4gICAgICAgIGZvciAobGV0IGMgPSAwOyBjIDwgdGhpcy5Db2x1bW5zTGlzdC5sZW5ndGg7IGMrKylcclxuICAgICAgICAgICAgdGhpcy5PcmRlckRpcmVjdGl2ZXMucHVzaCh0aGlzLkNvbHVtbnNMaXN0W2NdLmlkKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEVmZmV0dHVhIGxhIHNlbGV6aW9uZSBvIG1lbm8gZGVsIGNoZWNrIGdsb2JhbGUgKCoqZ2xvYmFsQ29sVmlzQ2hlY2sqKikgZGkgdmlzaWJpbGl0w6AgaW4gYmFzZSBhIHNlIHR1dHRlIGxlICoqVE1QQ29sdW1uc0xpc3QqKiBzb25vIHZpc2liaWxpIG8gbm9cclxuICAgICAqL1xyXG4gICAgcHVibGljIHVwZGF0ZUdsb2JhbENvbFZpc0NoZWNrKCkge1xyXG4gICAgICAgIC8vIFRNUENvbExpc3QgdmllbmUgcmllbXBpdGEgZGkgdW5kZWZpbmVkIG5lbCBjYXNvIGluIGN1aSBzaWEgZGlzYXR0aXZhdGEgbGEgc2VsZXppb25lIGRlbGxlIGNvbG9ubmUgbmFzY29zdGVcclxuICAgICAgICB0aGlzLmdsb2JhbENvbFZpc0NoZWNrID0gdGhpcy5UTVBDb2x1bW5zTGlzdC5ldmVyeSh0ID0+IHQudmlzaWJsZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBGdW56aW9uZSBjaGUgZWZmZXR0dWEgbGEgY29uZmVybWEgZGVsbGEgdmlzaWJpbGl0w6AgZSBkZWxsJ29yZGluZSBkZWxsZSBjb2xvbm5lLlxyXG4gICAgICpcclxuICAgICAqIFF1ZXN0YSBzZWxlemlvbmUgdmllbmUgaW5vbHRyZSBzYWx2YXRhIG5lbGxlIHByZWZlcmVuemUgKCoqQGVzZmFlbnphL3ByZWZlcmVuY2VzKiopLCBxdWFsb3JhIGwnSW5wdXQgKipTYXZlUHJlZmVyZW5jZXMqKiBmb3NzZSB2YWxvcml6emF0b1xyXG4gICAgICpcclxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSAqKnRydWUqKiBzZSBub24gY2kgc29ubyBwcm9ibGVtaSwgKipmYWxzZSoqIGFsdHJpbWVudGlcclxuICAgICAqL1xyXG4gICAgcHVibGljIGNvbmZpcm1Db2x1bW5WaXNpYmlsaXR5U2VsZWN0aW9uKCk6IGJvb2xlYW4ge1xyXG4gICAgICAgIC8vIE5vbiBwZXJtZXR0byBkaSBub24gc2VsZXppb25hcmUgbnVsbGFcclxuICAgICAgICBpZiAodGhpcy5UTVBDb2x1bW5zTGlzdC5ldmVyeSh0ID0+ICF0LnZpc2libGUpKVxyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcblxyXG4gICAgICAgIGxldCBjYXN0ZWRWaWV3ID0gdGhpcy5WaWV3IGFzIEFwcFNlYXJjaDxhbnk+O1xyXG4gICAgICAgIHRoaXMuQ29sdW1uc0xpc3QgPSBbXTtcclxuICAgICAgICB0aGlzLlRNUENvbHVtbnNMaXN0LmZvckVhY2goYyA9PiB7IHRoaXMuQ29sdW1uc0xpc3QucHVzaChPYmplY3QuYXNzaWduKHt9LCBjKSk7IH0pO1xyXG4gICAgICAgIFxyXG4gICAgICAgIHRoaXMucmVmcmVzaENvbHVtbk9yZGVyaW5nKCk7XHJcblxyXG4gICAgICAgIHRoaXMucmVmcmVzaENvbHVtbnNWaXNpYmlsaXR5KG51bGwsIG51bGwsIGNhc3RlZFZpZXcpO1xyXG4gICAgICAgIHRoaXMuYXBwbHlPcmRlcmluZyhjYXN0ZWRWaWV3LCBmYWxzZSk7XHJcblxyXG4gICAgICAgIC8vU2Fsdm8gbGUgcHJlZmVyZW5jZXMgZGkgcXVlc3RhIHZpZXdcclxuICAgICAgICAvL0RpIGRlZmF1bHQgcmVnaXN0cm8gb3JkaW5hbWVudG8gZSB2aXNpYmlsaXTDoCBkZWxsZSBjb2xvbm5lIG5lbGxhIHZpc3RhLiBTb2xvIGxlIGNvc2UgZGkgVUlcclxuICAgICAgICBpZiAodGhpcy5TYXZlUHJlZmVyZW5jZXMpIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLm5nQ29udHJvbC5uYW1lKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiTm9uIHBvc3NvIHV0aWxpenphcmUgbGUgcHJlZmVyZW5jZSBzZW56YSBhdmVyZSB1biAnbmFtZScgcGVyIGxhIHRhYmVsbGFcIik7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICghdGhpcy5wcmVmU2VydmljZSkge1xyXG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIk5vbiBwb3NzbyB1dGlsaXp6YXJlIGxlIHByZWZlcmVuY2Ugc2VuemEgY2hlIGlsIHBhY2NoZXR0byBAZXNmYWVuemEvcHJlZmVyZW5jZXMgc2lhIGluc3RhbGxhdG9cIik7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHZhciB0b1N0b3JlID0geyBjb2x1bW5zOiA8c3RyaW5nW10+SlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShjYXN0ZWRWaWV3LmNvbHVtbnMpKSwgY29sdW1uX29yZGVyaW5nOiA8c3RyaW5nW10+SlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShjYXN0ZWRWaWV3LmNvbHVtbl9vcmRlcmluZykpIH07XHJcbiAgICAgICAgICAgIHRoaXMucHJlZlNlcnZpY2Uuc3RvcmUoPHN0cmluZz50aGlzLm5nQ29udHJvbC5uYW1lLCB0b1N0b3JlKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIE1pIGFzc2ljdXJvIGRpIGZhcmxvIGRvcG8gbCdlc3BhbnNpb25lIGRlbCBjaGFuZ2VkIG8gcmlzY2hpbyBjaGUgbGEgcmljZXJjYSBtaSByaWRpYSBjb2xvbm5lIGNoZSBpbiByZWFsdMOgIG5vbiBlc2lzdG9ub1xyXG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4geyB0aGlzLmVtaXRTZWFyY2hSZXF1ZXN0KGZhbHNlKTsgfSk7XHJcblxyXG4gICAgICAgIC8vIExvIHZvcnJlaSBtZXR0ZXJlIGxhdG8gdGVtcGxhdGUgbWEgbm9cclxuICAgICAgICB0aGlzLmxhc3RTZWxlY3RlZEl0ZW1JRCA9IG51bGw7XHJcbiAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTdWwgY2xpY2sgbmVsbGEgY2hlY2tib3ggZGkgc2VsZXppb25lIGdsb2JhbGUgc2kgc2NvcnJvbm8gdHV0dGUgbGUgY29sb25uZSBlIHNpIGltcG9zdGFubyBhbCB2YWxvcmUgZGVsbGEgY2hlY2sgZ2xvYmFsZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZ2xvYmFsQ29sVmlzQ2hlY2tDaGFuZ2VkKCkge1xyXG4gICAgICAgIHRoaXMuVE1QQ29sdW1uc0xpc3QuZm9yRWFjaCh0ID0+IHsgdC52aXNpYmxlID0gdGhpcy5nbG9iYWxDb2xWaXNDaGVjazsgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gI2VuZHJlZ2lvblxyXG5cclxuICAgIC8vICNyZWdpb24gR2VzdGlvbmUgZGF0YSBzb3VyY2UgZ2VyYXJjaGljaVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGF0YSB1bmEgbGlzdGEgZGkgb2dnZXR0aSBhc3NlZ25vIGlsIGxpdmVsbG8gZ2VyYXJjaGljbyByaXNwZXR0byBhbGxhIGxpc3RhIGRpIG9nZ2V0dGkgcGFzc2F0YVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7YW55W119IG9ianMgTGlzdGEgZGkgb2dnZXR0aSBhIGN1aSBhZ2dpdW5nZXJlIGwnaW5mb3JtYXppb25lIGRlbCBsaXZlbGxvIGdlcmFyY2hpY29cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBhc3NpZ25IaWVyYXJjaHlMZXZlbHMob2JqczogYW55W10pIHtcclxuICAgICAgICAvLyBDYXNpc3RpY2EgaW5wdXQgbnVsbG9cclxuICAgICAgICBpZiAoIW9ianMgfHwgIW9ianMubGVuZ3RoKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgIC8vU2UgbWFuY2FubyBlbnRyYW1iZSBsZSBpbmZvIGxlIGNlcmNvIGRpIHZhbG9yaXp6YXJlIGluIGF1dG9tYXRpY28gY29pIGRlZmF1bHQgXCJwYXJlbnRpZFwiIGUgXCJpZFwiIChwb3N0byBjaGUgbGUgcHJvcHMgZXNpc3Rhbm8gbmVsbCdvZ2dldHRvKVxyXG4gICAgICAgIGlmICghdGhpcy5QYXJlbnRLZXkgJiYgIXRoaXMuT3duS2V5KSB7XHJcbiAgICAgICAgICAgIGlmIChvYmpzWzBdWydwYXJlbnRpZCddICE9PSB1bmRlZmluZWQpXHJcbiAgICAgICAgICAgICAgICB0aGlzLlBhcmVudEtleSA9ICdwYXJlbnRpZCc7XHJcbiAgICAgICAgICAgIGlmIChvYmpzWzBdWydpZCddICE9PSB1bmRlZmluZWQpXHJcbiAgICAgICAgICAgICAgICB0aGlzLk93bktleSA9ICdpZCc7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvL0NoZWNrIGZpbmFsZSBwZXIgYXNzaWN1cmFybWkgY2hlIGxlIHByb3BzIGNpIHNpYW5vXHJcbiAgICAgICAgaWYgKCF0aGlzLlBhcmVudEtleSB8fCAhdGhpcy5Pd25LZXkpIHtcclxuICAgICAgICAgICAgY29uc29sZS5lcnJvcignUGVyIHV0aWxpenphcmUgaWwgc2lzdGVtYSBpbiBtb2RhbGl0w6AgZ2VyYXJjaGljYSDDqCBvYmJsaWdhdG9yaW8gc3BlY2lmaWNhcmUgc2lhIFBhcmVudEtleSBjaGUgT3duS2V5LiBGYWxsYmFjayBhIHNpc3RlbWEgbm9uIGdlcmFyY2hpY28nKTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gVmFsb3JpenphemlvbmUgY2FtcGkgbGV2ZWwsIGV4cGFuZGVkLCBlIHZpc2libGUgcGVyIG9nbmkgaXRlbVxyXG4gICAgICAgIGxldCBjdXJyZW50TGV2ZWwgPSAxO1xyXG4gICAgICAgIGxldCBhc3NpZ25lZCA9IDA7XHJcbiAgICAgICAgZG8ge1xyXG4gICAgICAgICAgICBhc3NpZ25lZCA9IHRoaXMuYXNzaWduTGV2ZWwob2JqcywgY3VycmVudExldmVsKTtcclxuICAgICAgICAgICAgY3VycmVudExldmVsKys7XHJcbiAgICAgICAgfSB3aGlsZSAoYXNzaWduZWQgPiAwKTtcclxuICAgICAgICAvLyBidXR0byBzdSBsYXRvIGh0bWwgZSBwb2kgbWUgbGEgZ2lvY28gbMOgIGNvbiBwYWRkaW5nID0gMjAgKiAobGV2ZWwgLSAxKSBwZXIgZmFyIGNhcGlyZSBpbCBkaXZlcnNvIGxpdmVsbG9cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFBlciBvZ251bm8gZGVnbGkgb2dnZXR0aSBwYXNzYXRpIGdsaSBhc3NlZ25hIHVuIGxpdmVsbG8gZGkgZ2VyYXJjaGlhIGluIGJhc2UgYSAqKlBhcmVudEtleSoqIGUgKipPd25LZXkqKlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7YW55W119IG9ianMgT2dnZXR0aSBhIGN1aSBhc3NlZ25hcmUgaWwgbGl2ZWxsbyBkaSBnZXJhcmNoaWFcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBsZXZlbFRvQXNzaWduIExpdmVsbG8gY2hlIHN0YSBhc3NlZ25hbmRvIGF0dHVhbG1lbnRlIHF1ZXN0YSBpdGVyYXppb25lIChkYXRvIGNoZSDDqCByaWNvcnNpdmEpXHJcbiAgICAgKlxyXG4gICAgICogQHJldHVybnMge251bWJlcn0gTnVtZXJvIGRpIG9nZ2V0dGkgYSBjdWkgw6ggc3RhdG8gYXNzZWduYXRvIHVuIGxpdmVsbG8gZ2VyYXJjaGljb1xyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGFzc2lnbkxldmVsKG9ianM6IGFueVtdLCBsZXZlbFRvQXNzaWduOiBudW1iZXIpOiBudW1iZXIge1xyXG4gICAgICAgIGxldCBhc3NpZ25lZCA9IDA7XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvYmpzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGxldCBvYmogPSBvYmpzW2ldO1xyXG5cclxuICAgICAgICAgICAgLy8gU2UgbGEgcGFyZW50S2V5IG5vbiDDqCB2YWxvcml6emF0YSwgcXVlc3RvIMOoIGlsIGxpdmVsbG8gMCAoMS4uLiBwZXJjaMOpIGdsaSAwIHNvbiBwZXJjaW9sb3NpKVxyXG4gICAgICAgICAgICBpZiAoIW9ialt0aGlzLlBhcmVudEtleV0gJiYgbGV2ZWxUb0Fzc2lnbiA9PSAxKSB7XHJcbiAgICAgICAgICAgICAgICBvYmoubGV2ZWwgPSAxO1xyXG4gICAgICAgICAgICAgICAgb2JqLnZpc2libGUgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgb2JqLmV4cGFuZGVkID0gdGhpcy5TdGFydHNFeHBhbmRlZDtcclxuICAgICAgICAgICAgICAgIGFzc2lnbmVkKys7XHJcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gUGVyIGkgbGl2ZWxsaSBzdXBlcmlvcmUgYWwgcHJpbW9cclxuICAgICAgICAgICAgaWYgKG9ialt0aGlzLlBhcmVudEtleV0gJiYgbGV2ZWxUb0Fzc2lnbiA+IDEpIHtcclxuICAgICAgICAgICAgICAgIC8vIHRyb3ZvIGlsIHBhcmVudFxyXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgcCA9IDA7IHAgPCBvYmpzLmxlbmd0aDsgcCsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IHBvc3NpYmxlUGFyZW50ID0gb2Jqc1twXTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gVHJvdmF0byBpbCBwYXJlbnQgZGVsbCdpdGVtLCBhc3NlZ25vIGFsbCdpdGVtIGlsIGxpdmVsbG8gZ2l1c3RvXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBvc3NpYmxlUGFyZW50W3RoaXMuT3duS2V5XSA9PSBvYmpbdGhpcy5QYXJlbnRLZXldICYmIHBvc3NpYmxlUGFyZW50LmxldmVsID09IGxldmVsVG9Bc3NpZ24gLSAxKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iai5sZXZlbCA9IGxldmVsVG9Bc3NpZ247XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBTbyBjaGUgcXVlc3RvIGl0ZW0gaGEgdW4gcGFyZW50LiBSaWJhZGlzY28gY2hlIGlsIHBhcmVudCDDqCBlc3BhbnNvIGluIGJhc2UgYWxsZSBpbXBvc3RhemlvbmUgZSBzdGVzc2EgbG9naWNhXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHBlciBsYSB2aXNpYmlsaXTDoCBkZWwgZmlnbGlvXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc3NpYmxlUGFyZW50LmV4cGFuZGVkID0gdGhpcy5TdGFydHNFeHBhbmRlZDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcG9zc2libGVQYXJlbnQucGFyZW50ID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgb2JqLnZpc2libGUgPSB0aGlzLlN0YXJ0c0V4cGFuZGVkO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBhc3NpZ25lZCsrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIGFzc2lnbmVkO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRnVuemlvbmUgY2hlIHBlcm1ldHRlIGRpIGVmZmV0dHVhcmUgbCdlc3BhbnNpb25lIGRpIHVuIHBhcmVudCBxdWFuZG8gbGEgdGFiZWxsYSBmdW56aW9uYSBpbiBtb2RhbGl0w6AgZ2VyYXJjaGljYVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgQ2hpYXZlIGRlbCBwYXJlbnQgZGEgZXNwYW5kZXJlXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBleHBhbmRQYXJlbnQoa2V5OiBzdHJpbmcpIHtcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuYm91bmRTb3VyY2UubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgbGV0IG9iaiA9IHRoaXMuYm91bmRTb3VyY2VbaV07XHJcblxyXG4gICAgICAgICAgICAvLyBUcm92byBpbCBwYXJlbnQgY29uIHF1ZWxsJ2lkIGUgbG8gZXNwYW5kb1xyXG4gICAgICAgICAgICBpZiAob2JqW3RoaXMuT3duS2V5XSA9PSBrZXkpIHtcclxuICAgICAgICAgICAgICAgIG9iai5leHBhbmRlZCA9IHRydWU7XHJcblxyXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaWMgPSAwOyBpYyA8IHRoaXMuYm91bmRTb3VyY2UubGVuZ3RoOyBpYysrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGNoaWxkID0gdGhpcy5ib3VuZFNvdXJjZVtpY107XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8vIFRyb3ZvIHR1dHRpIGkgY2hpbGQgZGkgcXVlbCBwYXJlbnQgZSBsaSByZW5kbyB2aXNpYmlsaVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZFt0aGlzLlBhcmVudEtleV0gPT0ga2V5KVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZC52aXNpYmxlID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEZ1bnppb25lIGNoZSBwZXJtZXR0ZSBkaSBlZmZldHR1YXJlIGlsIGNvbGxhcHNlIGRpIHVuIHBhcmVudCBxdWFuZG8gbGEgdGFiZWxsYSBmdW56aW9uYSBpbiBtb2RhbGl0w6AgZ2VyYXJjaGljYVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgQ2hpYXZlIGRlbCBwYXJlbnQgZGEgY29sbGFzc2FyZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgY29sbGFwc2VQYXJlbnQoa2V5OiBzdHJpbmcpIHtcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuYm91bmRTb3VyY2UubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgbGV0IG9iaiA9IHRoaXMuYm91bmRTb3VyY2VbaV07XHJcblxyXG4gICAgICAgICAgICAvLyBUcm92byBpbCBwYXJlbnQgY29uIHF1ZWxsJ2lkIGUgbG8gY29sbGFzc29cclxuICAgICAgICAgICAgaWYgKG9ialt0aGlzLk93bktleV0gPT0ga2V5KSB7XHJcbiAgICAgICAgICAgICAgICBvYmouZXhwYW5kZWQgPSBmYWxzZTtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBDb2xsYXNzby9uYXNjb25kbyB0dXR0aSBpIGNoaWxkIGRlbCBwYXJlbnRcclxuICAgICAgICAgICAgICAgIHRoaXMuY29sbGFwc2VDaGlsZE9mUGFyZW50KGtleSk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDb2xsYXNzYSByaWNvcnNpdmFtZW50ZSB0dXR0aSBpIGZpZ2xpIGRpIHVuIHBhcmVudCBpZGVudGlmaWNhdG8gZGFsbGEgKipwYXJlbnRLZXkqKlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwYXJlbnRLZXkgQ2hpYXZlIGRlbCBwYXJlbnQgZGkgY3VpIGNvbGxhc3NhcmUgaSBmaWdsaVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGNvbGxhcHNlQ2hpbGRPZlBhcmVudChwYXJlbnRLZXk6IHN0cmluZykge1xyXG4gICAgICAgIGZvciAobGV0IGljID0gMDsgaWMgPCB0aGlzLmJvdW5kU291cmNlLmxlbmd0aDsgaWMrKykge1xyXG4gICAgICAgICAgICBsZXQgY2hpbGQgPSB0aGlzLmJvdW5kU291cmNlW2ljXTtcclxuXHJcbiAgICAgICAgICAgIC8vIFRyb3ZvIHR1dHRpIGkgY2hpbGQgZGkgcXVlbCBwYXJlbnQgZSBsaSByZW5kbyBpbnZpc2liaWxpLiBTZSBpbCBjaGlsZCB0cm92YXRvIMOoIGEgc3VhIHZvbHRhIHVuIHBhcmVudCxcclxuICAgICAgICAgICAgLy8gbG8gY29sbGFzc28gZSB2YWRvIGluIHJpY29yc2lvbmUgc3VpIGZpZ2xpXHJcbiAgICAgICAgICAgIGlmIChjaGlsZFt0aGlzLlBhcmVudEtleV0gPT0gcGFyZW50S2V5ICYmICFjaGlsZC5wYXJlbnQpXHJcbiAgICAgICAgICAgICAgICBjaGlsZC52aXNpYmxlID0gZmFsc2U7XHJcbiAgICAgICAgICAgIGVsc2UgaWYgKGNoaWxkW3RoaXMuUGFyZW50S2V5XSA9PSBwYXJlbnRLZXkgJiYgY2hpbGQucGFyZW50KSB7XHJcbiAgICAgICAgICAgICAgICBjaGlsZC5leHBhbmRlZCA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgY2hpbGQudmlzaWJsZSA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jb2xsYXBzZUNoaWxkT2ZQYXJlbnQoY2hpbGRbdGhpcy5Pd25LZXldKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyAjZW5kcmVnaW9uXHJcblxyXG4gICAgLy8gI3JlZ2lvbiBHZXN0aW9uZSBTZWxlemlvbmVcclxuXHJcbiAgICAvKipcclxuICAgICAqIFZhbHV0YSBxdWFsaSBlbGVtZW50aSBkZXZvbm8gZXNzZXJlIG1hcmNhdGkgY29tZSBzZWxlemlvbmF0aSBuZWxsYSB2aXN0YSBhdHR1YWxlLiBTaSBiYXNhIHN1bGwnb2dnZXR0byAqKnNlbGVjdGlvbioqIGludGVybm8gYWxsJ0FwcFNlYXJjaFxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7YW55W119IGl0ZW1zIE9nZ2V0dGkgZGkgY3VpIHZhbHV0YXJlIGxhIHNlbGV6aW9uZVxyXG4gICAgICogQHBhcmFtIHtJdGVtc1NlbGVjdGlvbjxhbnk+fSBzZWxlY3Rpb25JdGVtIE9nZ2V0dGkgZGkgc2VsZXppb25lIGRlcml2YW50ZSBkYWxsYSB2aWV3IG8gZGFsbCdvZ2dldHRvIHBlciBBcnJheVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGV2YWx1YXRlU2VsZWN0aW9uKGl0ZW1zOiBhbnlbXSwgc2VsZWN0aW9uSXRlbTogSXRlbXNTZWxlY3Rpb248YW55Pikge1xyXG4gICAgICAgIGlmICghc2VsZWN0aW9uSXRlbSlcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICB0aGlzLmhhbmRsZVNlbGVjdGlvbkV2YWx1YXRpb24oaXRlbXMsIHNlbGVjdGlvbkl0ZW0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVmFsdXRhIHF1YWxpIGVsZW1lbnRpIGRldm9ubyBlc3NlcmUgbWFyY2F0aSBjb21lIHNlbGV6aW9uYXRpIG5lbGxhIHZpc3RhIGF0dHVhbGUuIFNpIGJhc2Egc3VsbCdvZ2dldHRvICoqYXJyYXltb2RlU2VsZWN0aW9uKiogZGVsbCdlcy10YWJsZVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7YW55W119IGFycmF5IExpc3RhIGRpIG9nZ2V0dGkgZGkgY3VpIHZhbHV0YXJlIGxhIHNlbGV6aW9uZSBpbiBtb2RhbGl0w6AgYXJyYXlcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBhcnJheU1vZGVFdmFsdWF0ZVNlbGVjdGlvbihhcnJheTogYW55W10pIHtcclxuICAgICAgICBpZiAoYXJyYXkubGVuZ3RoID09IDApXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgdGhpcy5oYW5kbGVTZWxlY3Rpb25FdmFsdWF0aW9uKGFycmF5LCB0aGlzLmFycmF5bW9kZVNlbGVjdGlvbik7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJbXBsZW1lbnRhemlvbmUgYWdub3N0aWNhIGRlbGxhIHZhbHV0YXppb25lIGRlbGxlIHNlbGV6aW9uaSBkZWdsaSBvZ2dldHRpLiBSaWNoaWVkZSBnbGkgb2dnZXR0aSBkZWxsYSB2aXN0YSBhdHR1YWxlIGUgbCdpdGVtU2VsZWN0b3JcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge2FueVtdfSBpdGVtcyBPZ2dldHRpIGRpIGN1aSBhZ2dpb3JuYXJlIGxvIHN0YXRvIGRpIHNlbGV6aW9uZVxyXG4gICAgICogQHBhcmFtIHtJdGVtc1NlbGVjdGlvbjxhbnk+fSBzZWxlY3Rpb25JdGVtIE9nZ2V0dG8gY29udGVuZW50ZSBsbyBzdGF0byBhdHR1YWxlIGRpIHNlbGV6aW9uZVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGhhbmRsZVNlbGVjdGlvbkV2YWx1YXRpb24oaXRlbXM6IGFueVtdLCBzZWxlY3Rpb25JdGVtOiBJdGVtc1NlbGVjdGlvbjxhbnk+KSB7XHJcbiAgICAgICAgbGV0IGFsbFNlbGVjdGVkID0gaXRlbXMubGVuZ3RoID4gMDtcclxuXHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpdGVtcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgaXRtID0gaXRlbXNbaV07XHJcblxyXG4gICAgICAgICAgICAvLyBSZWlkcmF0byBsYSBjYWNoZSBkaSBzZWxlemlvbmUgY29pIG51b3ZpIG9nZ2V0dGkgYWx0cmltZW50aSBub24gcml1c2NpcmVpIGEgYmVjY2FyZSBnbGkgaW5kaWNpIGdpdXN0aVxyXG4gICAgICAgICAgICAvLyBEb3BvZGljaMOpIGxhIHVzbyBwZXIgY2FsY29sYXJlIGlzdGFudGFuZWFtZW50ZSBzZSBnbGkgb2dnZXR0aSBzb25vIHNlbGV6aW9uYXRpIG8gbm9cclxuICAgICAgICAgICAgaWYgKHRoaXMuc2VsT3JEZXNlbENhY2hlW2l0bS5oYXNoXSlcclxuICAgICAgICAgICAgICAgIHRoaXMuc2VsT3JEZXNlbENhY2hlW2l0bS5oYXNoXSA9IGl0bTtcclxuXHJcbiAgICAgICAgICAgIGlmIChzZWxlY3Rpb25JdGVtLmFsbClcclxuICAgICAgICAgICAgICAgIGl0bS5fc2VsZWN0ZWQgPSAhdGhpcy5zZWxPckRlc2VsQ2FjaGVbaXRtLmhhc2hdO1xyXG4gICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICBpdG0uX3NlbGVjdGVkID0gISF0aGlzLnNlbE9yRGVzZWxDYWNoZVtpdG0uaGFzaF07XHJcblxyXG4gICAgICAgICAgICBhbGxTZWxlY3RlZCA9IGFsbFNlbGVjdGVkICYmIGl0bS5fc2VsZWN0ZWQ7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBTZSB0dXR0aSBnbGkgb2dnZXR0aSBkaSBxdWVzdGEgcGFnaW5hIHNvbm8gc29sZXppb25hdGkgYWxsb3JhIHBvc3NvIG1ldHRlcmUgaWwgZ2xvYmFsIGNoZWNrIGEgdHJ1ZVxyXG4gICAgICAgIC8vIFNlIHNvbm8gaW4gc2l0dWF6aW9uZSBkaSBhbGwtc2VsZWN0IGFuY2hlIG1ldHRvIGxhIGdsb2JhbCBjaGVja2JveCwgbm9ub3N0YW50ZSBjaSBwb3NzYW5vIGVzc2VyZSBkZWxsZSBlc2NsdXNpb25pXHJcbiAgICAgICAgdGhpcy5nbG9iYWxDaGVjayA9IGFsbFNlbGVjdGVkIHx8IHNlbGVjdGlvbkl0ZW0uYWxsO1xyXG4gICAgICAgIHRoaXMuY2FuU2VsZWN0QWxsID0gc2VsZWN0aW9uSXRlbS5jb3VudCA+IDAgJiYgdGhpcy5TZWxlY3RBbGw7XHJcblxyXG4gICAgICAgIC8vIFBvdHJlYmJlIGNhbWJpYXJlIHF1YWxvcmEgcXVhbGN1bm8gaW5zZXJpc3NlIGRhdGkgYSBtYW5henphIGluIG1vZGFsaXTDoCBBcnJheSBlIGRlc3NlIGlsIHJlZnJlc2ggbWFudWFsZSBhbGxhIHRhYmVsbGFcclxuICAgICAgICAvLyBDb211bnF1ZSBjb3N0YSAwIHF1aW5kaSBtaSBwZXJtZXR0byBkaSByZWZyZXNoYXJlXHJcbiAgICAgICAgaWYgKHRoaXMuYXJyYXlNb2RlKSB7XHJcbiAgICAgICAgICAgIGxldCBwcmV2U2VsZWN0ZWQgPSB0aGlzLnNlbGVjdGVkT2JqZWN0cztcclxuICAgICAgICAgICAgdGhpcy5maW5hbGl6ZVNlbGVjdGlvbkluZm9ybWF0aW9ucyhzZWxlY3Rpb25JdGVtKTtcclxuICAgICAgICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRPYmplY3RzICE9IHByZXZTZWxlY3RlZClcclxuICAgICAgICAgICAgICAgIHRoaXMub25TZWxlY3Rpb25DaGFuZ2VkLmVtaXQoc2VsZWN0aW9uSXRlbSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2VzdGlzY2UgbGEgc2VsZXppb25lIGdsb2JhbGUgZGVnbGkgb2dnZXR0aSwgc2lhIHBlciBwYWdpbmEgY2hlIGEgbGl2ZWxsbyBkaSAqKlNlbGVjdEFsbCoqXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtib29sZWFufSBmb3JjZWRWYWwgVmFsb3JlIGZvcnphdG8gZGkgY2hlY2sgZGEgYXNzZWduYXJlIGFnbGkgb2dnZXR0aVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZ2xvYmFsQ2hlY2tDaGFuZ2VkKGZvcmNlZFZhbDogYm9vbGVhbiA9IG51bGwpIHtcclxuXHJcbiAgICAgICAgLy8gUHJlbmRvIHR1dHRpIGdsaSBlbGVtZW50aSBwcmVzZW50aSBpbiBxdWVzdGEgdmlzdGEgY2hlIG5vbiBzaWFubyBncnVwcGlcclxuICAgICAgICBsZXQgaXRlbXMgPSB0aGlzLmJvdW5kU291cmNlLmZpbHRlcih0ID0+ICF0Ll9ncm91cCk7XHJcbiAgICAgICAgdmFyIGl0ZW1TZWxlY3Rpb24gPSB0aGlzLmhhbmRsZUl0ZW1zU2VsZWN0aW9uKGl0ZW1zLCBmb3JjZWRWYWwsIHRoaXMuZ2xvYmFsQ2hlY2spO1xyXG4gICAgICAgIHRoaXMuY2hhbmdlZCgpO1xyXG5cclxuICAgICAgICB0aGlzLm9uU2VsZWN0aW9uQ2hhbmdlZC5lbWl0KGl0ZW1TZWxlY3Rpb24pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSGVscGVyIHBlciBnZXN0aXJlIGxhIHNlbGV6aW9uZSBkaSBOIGVsZW1lbnRpIHV0aWxpenphbmRvIGxhIENhY2hlIGRpIHNlbGV6aW9uZSBlZCBldmVudHVhbG1lbnRlIGFnZ2lvcm5hbmRvIGlsIGNvbmNldHRvIGRpIFwiYWxsIHNlbGVjdGlvblwiXHJcbiAgICAgKlxyXG4gICAgICogVnVuemlvbmEgc2lhIGluIG1vZGFsaXTDoCBBcnJheSBjaGUgaW4gbW9kYWxpdMOgIFZpZXcgU2VtcGxpY2UgbyBWaWV3IEF2YW56YXRhIChjb24gbGUgQ3VzdG9tIENlbGxzKVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7YW55W119IGl0ZW1zIE9nZ2V0dGkgZGEgc2VsZXppb25hcmUgbyBkZXNlbGV6aW9uYXJlXHJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGZvcmNlZFZhbCBWYWxvcmUgZm9yemF0byBkaSBjaGVjayBkYSBhc3NlZ25hcmUgYWdsaSBvZ2dldHRpXHJcbiAgICAgKlxyXG4gICAgICogQHJldHVybnMge0l0ZW1zU2VsZWN0aW9uPGFueT59IE9nZ2V0dG8gZGkgc2VsZXppb25lIGFnZ2lvcm5hdG8gY29uIGxlIGluZm9ybWF6aW9uaSBzdWxsJ3VsdGltYSBvcGVyYXppb25lIGVmZmV0dHVhdGFcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBoYW5kbGVJdGVtc1NlbGVjdGlvbihpdGVtczogYW55W10sIGZvcmNlZFZhbDogYm9vbGVhbiA9IG51bGwsIGdsb2JhbENoZWNrOiBib29sZWFuID0gbnVsbCk6IEl0ZW1zU2VsZWN0aW9uPGFueT4ge1xyXG4gICAgICAgIGxldCBzZWxlY3Rpb25JdGVtID0gKHRoaXMuVmlldyBhcyBBcHBTZWFyY2g8YW55Pik/LnNlbGVjdGlvbiB8fCB0aGlzLmFycmF5bW9kZVNlbGVjdGlvbjtcclxuXHJcbiAgICAgICAgLy8gU2Ugc29ubyBpbiBtb2RhbGl0w6AgZGkgc2VsZXppb25lIHNpbmdvbGEgZSBkZXZvIHNlbGV6aW9uYXJlIHVuJ29nZ2V0dG8sIHBlciBwcmltYSBjb3NhIGRldm8gZGVzZWxlemlvbmFyZSB0dXR0aSBnbGkgYWx0cmlcclxuICAgICAgICBpZiAodGhpcy5TaW5nbGVTZWxlY3Rpb24gJiYgaXRlbXNbMF0/Ll9zZWxlY3RlZCkge1xyXG4gICAgICAgICAgICBpZiAoaXRlbXMubGVuZ3RoID4gMSAmJiBmb3JjZWRWYWwgPT0gbnVsbClcclxuICAgICAgICAgICAgICAgIHRocm93IFwiVGVudGF0aXZvIGRpIHNlbGV6aW9uYXJlIG8gZGVzZWxlemlvbmFyZSBwacO5IGRpIHVuIGVsZW1lbnRvIGNvbiBTaW5nbGVTZWxlY3Rpb24gYXR0aXZvXCI7XHJcblxyXG4gICAgICAgICAgICBpZiAoaXRlbXMubGVuZ3RoID09IDEgJiYgZm9yY2VkVmFsID09IG51bGwpe1xyXG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uSXRlbSA9IHRoaXMuaGFuZGxlSXRlbXNTZWxlY3Rpb24odGhpcy5ib3VuZFNvdXJjZS5maWx0ZXIodCA9PiAhdC5fZ3JvdXApLCBmYWxzZSwgbnVsbCk7XHJcbiAgICAgICAgICAgICAgICBpdGVtc1swXS5fc2VsZWN0ZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGl0ZW1zLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGxldCBpdGVtID0gaXRlbXNbaV07XHJcbiAgICAgICAgICAgIGxldCB0b0NoYW5nZSA9IGZvcmNlZFZhbCAhPSBudWxsID8gaXRlbS5fc2VsZWN0ZWQgIT0gZm9yY2VkVmFsIDogZ2xvYmFsQ2hlY2sgIT0gbnVsbCA/IGl0ZW0uX3NlbGVjdGVkICE9IHRoaXMuZ2xvYmFsQ2hlY2sgOiBmYWxzZTtcclxuXHJcbiAgICAgICAgICAgIC8vIFNlIGRldidlc3NlcmUgb3ZlcnJpZGF0byBpbCB2YWxvcmUgZGkgY2hlY2sgZWZmZXR0dW8gbCdvdmVycmlkZSBvIGNvbCB2YWxvcmUgZm9yemF0byBvIGNvbCB2YWxvcmUgZ2xvYmFsZVxyXG4gICAgICAgICAgICBpZiAodG9DaGFuZ2UgJiYgIWl0ZW0ubG9ja2VkKVxyXG4gICAgICAgICAgICAgICAgaXRlbS5fc2VsZWN0ZWQgPSBmb3JjZWRWYWwgIT0gbnVsbCA/IGZvcmNlZFZhbCA6IHRoaXMuZ2xvYmFsQ2hlY2s7XHJcblxyXG5cclxuICAgICAgICAgICAgaWYgKHNlbGVjdGlvbkl0ZW0uYWxsKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBJbiBjYXNvIGRpIFwic2VsZXppb25hIHR1dHRvXCIuLi5cclxuICAgICAgICAgICAgICAgIC8vIE4uQjogbGEgc2VsT3JEZXNlbENhY2hlIGFnaXNjZSBjb21lIGNhY2hlIGRpIERFU0VMRVpJT05FIGluIHF1ZXN0byBibG9jY28gZGkgY29kaWNlXHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKGl0ZW0uX3NlbGVjdGVkICYmIHRoaXMuc2VsT3JEZXNlbENhY2hlW2l0ZW0uaGFzaF0pIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBPZ2dldHRvIHNlbGV6aW9uYXRvOiBsbyByaW11b3ZvIGRhbGxlIGVzY2x1c2lvbmkgZGkgc2VsZXppb25lXHJcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0aW9uSXRlbS5leGNsdXNpb25zLnNwbGljZShzZWxlY3Rpb25JdGVtLmV4Y2x1c2lvbnMuaW5kZXhPZih0aGlzLnNlbE9yRGVzZWxDYWNoZVtpdGVtLmhhc2hdKSwgMSk7XHJcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuc2VsT3JEZXNlbENhY2hlW2l0ZW0uaGFzaF07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBlbHNlIGlmICghaXRlbS5fc2VsZWN0ZWQgJiYgIXRoaXMuc2VsT3JEZXNlbENhY2hlW2l0ZW0uaGFzaF0pIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBPZ2dldHRvIGRlc2VsZXppb25hdG86IGxvIGFnZ2l1bmdvIGFsbGUgZXNjbHVzaW9uaSBkaSBzZWxlemlvbmVcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnNlbE9yRGVzZWxDYWNoZVtpdGVtLmhhc2hdID0gaXRlbTtcclxuICAgICAgICAgICAgICAgICAgICBzZWxlY3Rpb25JdGVtLmV4Y2x1c2lvbnMucHVzaChpdGVtKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIC8vSW4gY2FzbyBkaSBub24gXCJzZWxlemlvbmEgdHV0dG9cIi4uLlxyXG4gICAgICAgICAgICAgICAgLy8gTi5COiBsYSBzZWxPckRlc2VsQ2FjaGUgYWdpc2NlIGNvbWUgY2FjaGUgZGkgU0VMRVpJT05FIGluIHF1ZXN0byBibG9jY28gZGkgY29kaWNlXHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKGl0ZW0uX3NlbGVjdGVkICYmICF0aGlzLnNlbE9yRGVzZWxDYWNoZVtpdGVtLmhhc2hdKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gT2dnZXR0byBzZWxlemlvbmF0bzogbG8gYWdnaXVuZ28gYWxsYSBzZWxlemlvbmUgYXR0dWFsZVxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2VsT3JEZXNlbENhY2hlW2l0ZW0uaGFzaF0gPSBpdGVtO1xyXG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdGlvbkl0ZW0uaXRlbXMucHVzaChpdGVtKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKCFpdGVtLl9zZWxlY3RlZCAmJiB0aGlzLnNlbE9yRGVzZWxDYWNoZVtpdGVtLmhhc2hdKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gT2dnZXR0byBkZXNlbGV6aW9uYXRvOiBsbyByaW11b3ZvIGRhbGxhIHNlbGV6aW9uZSBhdHR1YWxlXHJcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0aW9uSXRlbS5pdGVtcy5zcGxpY2Uoc2VsZWN0aW9uSXRlbS5pdGVtcy5pbmRleE9mKHRoaXMuc2VsT3JEZXNlbENhY2hlW2l0ZW0uaGFzaF0pLCAxKTtcclxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5zZWxPckRlc2VsQ2FjaGVbaXRlbS5oYXNoXTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gSW1wb3N0byBpbCBjaGVjayBnbG9iYWxlIGluIGJhc2UgYSBzZSB0dXR0aSBnbGkgZWxlbWVudGkgc29ubyBzZWxlemlvbmF0aSBvIG1lbm8uXHJcbiAgICAgICAgLy8gRXZpdG8gZGkgZmFyZSBxdWVzdGUgb3BlcmF6aW9uaSBzZSBsYSBzZWxlemlvbmUgZGVyaXZhIHByb3ByaW8gZGFsIGdsb2JhbCBDaGVja1xyXG4gICAgICAgIC8vIE5vbiDDqCBvdHRpbWl6emF0aXNzaW1vIG1ldHRlcmUgMiBzb21lIG1hIHNjcml2ZXJlIHF1ZXN0byBjb2RpY2UgYSBmb3Igc29ubyB0aXBvIDI1IHJpZ2hlLi4uLlxyXG4gICAgICAgIGlmIChnbG9iYWxDaGVjayA9PSBudWxsKVxyXG4gICAgICAgICAgICB0aGlzLmdsb2JhbENoZWNrID0gIWl0ZW1zLnNvbWUodCA9PiAhdC5fc2VsZWN0ZWQpICYmICF0aGlzLmJvdW5kU291cmNlLnNvbWUodCA9PiAhdC5fc2VsZWN0ZWQgJiYgIXQuX2dyb3VwKTtcclxuXHJcbiAgICAgICAgdGhpcy5maW5hbGl6ZVNlbGVjdGlvbkluZm9ybWF0aW9ucyhzZWxlY3Rpb25JdGVtKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIHNlbGVjdGlvbkl0ZW07XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBGaW5hbGl6emEgbGUgaW5mb3JtYXppb25pIGRpIHNlbGV6aW9uZSBkZWwgKipJdGVtc1NlbGVjdGlvbioqIGNvcnJlbnRlXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZmluYWxpemVTZWxlY3Rpb25JbmZvcm1hdGlvbnMoc2VsZWN0aW9uSXRlbTogSXRlbXNTZWxlY3Rpb248YW55Pikge1xyXG4gICAgICAgIHNlbGVjdGlvbkl0ZW0uY291bnQgPSB0aGlzLmV2YWx1YXRlU2VsZWN0ZWQoKTtcclxuXHJcbiAgICAgICAgLy8gU2UgaG8gZmF0dG8gc2VsZXppb25lIFwiYWxsXCIgbWEgcG9pIG1pIHNvbm8gbWVzc28gYSB0b2dsaWVyZSB0dXR0aSBnbGkgZWxlbWVudGkgZmlubyBhIHJpbWFuZXJuZSAwIHJlc2V0dG8gbCdvZ2dldHRvIGRpIHNlbGV6aW9uZVxyXG4gICAgICAgIGlmIChzZWxlY3Rpb25JdGVtLmNvdW50ID09IDAgJiYgc2VsZWN0aW9uSXRlbS5hbGwpIHtcclxuICAgICAgICAgICAgc2VsZWN0aW9uSXRlbS5hbGwgPSBmYWxzZTtcclxuICAgICAgICAgICAgc2VsZWN0aW9uSXRlbS5leGNsdXNpb25zID0gW107XHJcbiAgICAgICAgICAgIHNlbGVjdGlvbkl0ZW0uaXRlbXMgPSBbXTtcclxuXHJcbiAgICAgICAgICAgIC8vIFJpcHVsaXNjbyBsYSBjYWNoZSBhbHRyaW1lbnRpIG1pIHJpbWFuZSBwaWVuYSBkaSB0dXR0ZSBsZSBlc2NsdXNpb25pXHJcbiAgICAgICAgICAgIHRoaXMuc2VsT3JEZXNlbENhY2hlID0ge307XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBTZSBsYSBwb3NzaWJpbGl0w6AgZGkgZmFyZSBcIlNlbGV6aW9uYSB0dXR0b1wiIMOoIGFiaWxpdGF0YSBhbGxvcmEgbGEgY29uc2lkZXJvIGFwcGVuYSBtaSB2aWVuZSBzZWxlemlvbmF0byBxdWFsY29zYVxyXG4gICAgICAgIHRoaXMuY2FuU2VsZWN0QWxsID0gc2VsZWN0aW9uSXRlbS5jb3VudCA+IDAgJiYgdGhpcy5TZWxlY3RBbGw7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXN0aXNjZSBpIGNsaWNrIHN1bGxhIHRhYmVsbGEsIGdlc3RlbmRvIGV2ZW50dWFsbWVudGUgYW5jaGUgZ2xpIFNoaWZ0ICsgQ2xpY2sgcGVyIHNlbGV6aW9uYXJlIHVuIHJhbmdlIGRpIG9nZ2V0dGlcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge2FueX0gZXZlbnQgRXZlbnRvIG5hdGl2byBIVE1MIGRlbCBjbGlja1xyXG4gICAgICogQHBhcmFtIHthbnl9IGl0ZW0gT2dnZXR0byBiaW5kYXRvIHN1IGN1aSBzaSDDqCBlZmZldHR1YXRvIGlsIGNsaWNrXHJcbiAgICAgKlxyXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59ICoqdHJ1ZSoqIHNlIGwnb3BlcmFpem9uZSDDqCBhbmRhdGEgYSBidW9uIGZpbmUsICoqZmFsc2UqKiBhbHRyaW1lbnRpXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBoYW5kbGVDbGljayhldmVudDogYW55LCBpdGVtOiBhbnkpOiBib29sZWFuIHtcclxuICAgICAgICAvLyBTZWxlemlvbm8gZGVsIHRlc3RvIG1hIG5vbiBobyBzaGlmdCBwcmVtdXRvIC0+IGlnbm9ybyBsYSBzZWxlemlvbmVcclxuICAgICAgICBpZiAoKGV2ZW50LnZpZXcuZ2V0U2VsZWN0aW9uKCkudHlwZSA9PSAnUmFuZ2UnIHx8IGV2ZW50LnZpZXcuZ2V0U2VsZWN0aW9uKCkudG9TdHJpbmcoKS5sZW5ndGggPiAwKSAmJiAhZXZlbnQuc2hpZnRLZXkpXHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuXHJcbiAgICAgICAgLy8gU2VsZXppb25vIGRlbCB0ZXN0byBlIGhvIHNoaWZ0IHByZW11dG8gLT4gYW5udWxsbyBsYSBzZWxlemlvbmUgZGVsIHRlc3RvXHJcbiAgICAgICAgaWYgKChldmVudC52aWV3LmdldFNlbGVjdGlvbigpLnR5cGUgPT0gJ1JhbmdlJyB8fCBldmVudC52aWV3LmdldFNlbGVjdGlvbigpLnRvU3RyaW5nKCkubGVuZ3RoID4gMCkgJiYgZXZlbnQuc2hpZnRLZXkpXHJcbiAgICAgICAgICAgIHRoaXMudXRpRXh0cy5jbGVhclRleHRTZWxlY3Rpb24oKTtcclxuXHJcbiAgICAgICAgbGV0IHNlbGVjdGVkaXRlbXM6IGFueVtdID0gW107XHJcbiAgICAgICAgaWYgKGV2ZW50LnNoaWZ0S2V5ICYmIHRoaXMuU2hpZnRDbGljayAmJiAhdGhpcy5TaW5nbGVTZWxlY3Rpb24pIHtcclxuICAgICAgICAgICAgbGV0IHN0YXJ0U2VsZWN0aW5nID0gZmFsc2U7XHJcblxyXG4gICAgICAgICAgICBsZXQgaXRlbXMgPSB0aGlzLmJvdW5kU291cmNlLmZpbHRlcih0ID0+ICF0Lmdyb3VwKTtcclxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpdGVtcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgbGV0IHQgPSBpdGVtc1tpXTtcclxuICAgICAgICAgICAgICAgIGlmIChzdGFydFNlbGVjdGluZykge1xyXG4gICAgICAgICAgICAgICAgICAgIHQuX3NlbGVjdGVkID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZGl0ZW1zLnB1c2godCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpZiAoKHQgPT0gaXRlbSB8fCB0ID09IHRoaXMubGFzdFNlbGVjdGVkKSAmJiAhc3RhcnRTZWxlY3RpbmcpIHtcclxuICAgICAgICAgICAgICAgICAgICBzdGFydFNlbGVjdGluZyA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgdC5fc2VsZWN0ZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkaXRlbXMucHVzaCh0KTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoKHQgPT0gaXRlbSB8fCB0ID09IHRoaXMubGFzdFNlbGVjdGVkKSAmJiBzdGFydFNlbGVjdGluZylcclxuICAgICAgICAgICAgICAgICAgICBzdGFydFNlbGVjdGluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgaXRlbS5fc2VsZWN0ZWQgPSAhaXRlbS5fc2VsZWN0ZWQ7XHJcbiAgICAgICAgICAgIHRoaXMubGFzdFNlbGVjdGVkID0gaXRlbTtcclxuICAgICAgICAgICAgc2VsZWN0ZWRpdGVtcy5wdXNoKGl0ZW0pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdmFyIGl0ZW1TZWxlY3Rpb24gPSB0aGlzLmhhbmRsZUl0ZW1zU2VsZWN0aW9uKHNlbGVjdGVkaXRlbXMpO1xyXG4gICAgICAgIHRoaXMuY2hhbmdlZCgpO1xyXG5cclxuICAgICAgICB0aGlzLm9uU2VsZWN0aW9uQ2hhbmdlZC5lbWl0KGl0ZW1TZWxlY3Rpb24pO1xyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVmFsdXRhIGxhIHF1YW50aXTDoCBkaSBvZ2dldHRpIGNoZSBzb25vIHN0YXRpIHNlbGV6aW9uYXRpIGFsIHRlcm1pbmUgZGkgdW4gZXZlbnRvIGRpIHNlbGV6aW9uZVxyXG4gICAgICpcclxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IE51bWVybyBkaSBvZ2dldHRpIHNlbGV6aW9uYXRpXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZXZhbHVhdGVTZWxlY3RlZCgpOiBudW1iZXIge1xyXG4gICAgICAgIGxldCBzZWxlY3Rpb25JdGVtID0gKHRoaXMuVmlldyBhcyBBcHBTZWFyY2g8YW55Pik/LnNlbGVjdGlvbiB8fCB0aGlzLmFycmF5bW9kZVNlbGVjdGlvbjtcclxuICAgICAgICB0aGlzLnNlbGVjdGVkT2JqZWN0cyA9IHNlbGVjdGlvbkl0ZW0uYWxsID8gKHRoaXMuVmlldy5vYmplY3Rjb3VudCB8fCB0aGlzLlZpZXcubGVuZ3RoKSAgLSBzZWxlY3Rpb25JdGVtLmV4Y2x1c2lvbnMubGVuZ3RoIDogc2VsZWN0aW9uSXRlbS5pdGVtcy5sZW5ndGg7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuc2VsZWN0ZWRPYmplY3RzO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2VzdGlzY2UgaWwgY29tYW5kbyBkaSBcIlNlbGV6aW9uYSB0dXR0byBpbiB0dXR0ZSBsZSBwYWdpbmVcIiBvIGlsIHN1byBjb250cmFyaW8sIGNpb8OoIFwiUmVpbXBvc3RhIHNlbGV6aW9uZVwiXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzZWxlY3RBbGxPclJlc2V0U2VsZWN0aW9uKCkge1xyXG4gICAgICAgIGxldCBzZWxlY3Rpb25JdGVtID0gdGhpcy5WaWV3LnNlbGVjdGlvbiB8fCB0aGlzLmFycmF5bW9kZVNlbGVjdGlvbjtcclxuICAgICAgICB0aGlzLnNlbE9yRGVzZWxDYWNoZSA9IHt9O1xyXG4gICAgICAgIHNlbGVjdGlvbkl0ZW0uYWxsID0gIXNlbGVjdGlvbkl0ZW0uYWxsO1xyXG4gICAgICAgIHNlbGVjdGlvbkl0ZW0uZXhjbHVzaW9ucyA9IFtdO1xyXG4gICAgICAgIHNlbGVjdGlvbkl0ZW0uaXRlbXMgPSBbXTtcclxuXHJcbiAgICAgICAgLy8gUmlwdWxpc2NvIGdsaSBzdGF0aSBVSSBkaSBzZWxlemlvbmUgZ2xvYmFsZSBzZSBsJ2hvIGRpc2F0dGl2YXRhXHJcbiAgICAgICAgaWYgKCFzZWxlY3Rpb25JdGVtLmFsbCkge1xyXG4gICAgICAgICAgICB0aGlzLmNhblNlbGVjdEFsbCA9IGZhbHNlO1xyXG4gICAgICAgICAgICB0aGlzLmdsb2JhbENoZWNrID0gZmFsc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLmZpbmFsaXplU2VsZWN0aW9uSW5mb3JtYXRpb25zKHNlbGVjdGlvbkl0ZW0pO1xyXG5cclxuICAgICAgICB0aGlzLm9uU2VsZWN0aW9uQ2hhbmdlZC5lbWl0KHNlbGVjdGlvbkl0ZW0pO1xyXG5cclxuICAgICAgICAvLyBEb3BvIGF2ZXIgcmVzZXR0YXRvIGRpcmV0dGFtZW50ZSBpbCBzb2xvIG9nZ2V0dG8gdGhpcy5WaWV3LnNlbGVjdGlvbiBkZXZvIGFuY2hlIHJpYWxsaW5lYXJlIGEgdHV0dGkgZ2xpIG9nZ2V0dGkgYmluZGF0aVxyXG4gICAgICAgIHRoaXMuZXZhbHVhdGVTZWxlY3Rpb24odGhpcy52aWV3TW9kZSA/IHRoaXMuVmlldy5pdGVtcyA6IHRoaXMuVmlldywgc2VsZWN0aW9uSXRlbSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gI2VuZHJlZ2lvblxyXG5cclxuICAgIC8vICNyZWdpb24gR2VzdGlvbmUgUGFnaW5hemlvbmVcclxuXHJcbiAgICAvKipcclxuICAgICAqIFNwb3N0YSBsYSByaWNlcmNhIGRpIHVuYSBwYWdpbmEgaW4gYXZhbnRpIChvIGluZGVpdHJvKVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBwYWdlIE51bWVybyBkaSBwYWdpbmUgZGEgYWdnaXVuZ2VyZSAobyBzb3R0cmFycmUsIHNlIG5lZ2F0aXZvKSBhbGxhIHBhZ2luYSBhdHR1YWxlXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBhZGRUb1BhZ2UocGFnZTogbnVtYmVyKSB7XHJcbiAgICAgICAgaWYgKCEodGhpcy5WaWV3IGluc3RhbmNlb2YgQXBwU2VhcmNoKSAmJiAhKHRoaXMuU2VhcmNoVmlldyBpbnN0YW5jZW9mIEFwcFNlYXJjaCkgJiYgISh0aGlzLlZpZXcgaW5zdGFuY2VvZiBSZXBvcnREZWZpbml0aW9uKSlcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICB0aGlzLmdvVG9QYWdlKCh0aGlzLlNlYXJjaFZpZXcgfHwgdGhpcy5WaWV3KS5wYWdlICsgcGFnZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTcG9zdGEgbGEgcmljZXJjYSBhbGxhIHBhZ2luYSBzcGVjaWZpY2F0YVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBwYWdlIFBhZ2luYSBhIGN1aSBuYXZpZ2FyZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZ29Ub1BhZ2UocGFnZTogbnVtYmVyKSB7XHJcblxyXG4gICAgICAgIGlmICghKHRoaXMuVmlldyBpbnN0YW5jZW9mIEFwcFNlYXJjaCkgJiYgISh0aGlzLlNlYXJjaFZpZXcgaW5zdGFuY2VvZiBBcHBTZWFyY2gpICYmICEodGhpcy5WaWV3IGluc3RhbmNlb2YgUmVwb3J0RGVmaW5pdGlvbikpXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgbGV0IGFwcFNlYXJjaEVsZW1lbnQgPSB0aGlzLlNlYXJjaFZpZXcgfHwgdGhpcy5WaWV3O1xyXG4gICAgICAgIGlmIChwYWdlID09PSAwIHx8IHBhZ2UgPiBhcHBTZWFyY2hFbGVtZW50LnBhZ2VzKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgIGFwcFNlYXJjaEVsZW1lbnQucGFnZSA9IHBhZ2U7XHJcbiAgICAgICAgdGhpcy5hcnJheVB1bHNhbnRpID0gdGhpcy5nZXRQYWdlc0FycmF5KDYsIGFwcFNlYXJjaEVsZW1lbnQucGFnZSwgYXBwU2VhcmNoRWxlbWVudC5wYWdlcyk7XHJcblxyXG4gICAgICAgIHRoaXMuZW1pdFNlYXJjaFJlcXVlc3QoZmFsc2UpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRXZlbnRvIHJpY2hpYW1hdG8gc3VsIGNhbWJpbyBkZWxsYSBwYWdpbmF6aW9uZS4gVmVycsOgIHJpY2hpYW1hdG8gbCdldmVudG8gKiplbWl0U2VhcmNoUmVxdWVzdCoqXHJcbiAgICAgKiBwZXIgY29tdW5pY2FyZSBhbCBjb21wb25lbnRlIGNoZSB1dGlsaXp6YSBxdWVzdGEgdGFiZWxsYSBjaGUgaSBkYXRpIHNvbm8gZGEgYWdnaW9ybmFyZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgb25JdGVtc1BlclBhZ2VDaGFuZ2VkKCkge1xyXG4gICAgICAgIHRoaXMuZW1pdFNlYXJjaFJlcXVlc3QodHJ1ZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gI2VuZHJlZ2lvblxyXG5cclxuICAgIC8vICNyZWdpb24gR2VzdGlvbmUgRXhwb3J0XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBFZmZldHR1YSBsJ2VzcG9ydGF6aW9uZSBkZWkgZGF0aVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBmb3JtYXQgRm9ybWF0byBkaSBlc3BvcnRhemlvbmUuIExldHRvIHNvbG8gaW4gbW9kYWxpdMOgIFJlcG9ydCBkZWxsYSB0YWJlbGxhXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyB0cnlFeHBvcnQoZm9ybWF0Pzogc3RyaW5nKSB7XHJcbiAgICAgICAgaWYgKCF0aGlzLkV4cG9ydEZ1bmN0aW9uKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgIGlmICh0aGlzLnJlcG9ydE1vZGUpXHJcbiAgICAgICAgICAgIHRoaXMuRXhwb3J0RnVuY3Rpb24oZm9ybWF0KTtcclxuICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgIHRoaXMuRXhwb3J0RnVuY3Rpb24oKGRhdGE6IGFueVtdLCBjYW5jZWw6IGJvb2xlYW4gPSBmYWxzZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKGNhbmNlbClcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKGRhdGEubGVuZ3RoID09IDApIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLm1zZ0V4dHMuc2ltcGxlV2FybmluZyh0aGlzLmxjLmxvYyhcIkNhbm5vdCBleHBvcnQgYW4gZW1wdHkgZGF0YXNldFwiKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIHRoaXMuc2V0dXBFeHBvcnQoZGF0YSk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHsgdGhpcy5leHBvcnREb3dubG9hZGVyLm5hdGl2ZUVsZW1lbnQuY2xpY2soKTsgfSk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTWV0b2RvIGNoZSBlZmZldHRpdmFtZW50ZSBnZW5lcmEgZ2xpIGhlYWRlciBlIGkgZGF0aSBwZXIgbCdlc3BvcnRhemlvbmUgY29uICoqbmd4LWNzdioqXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHthbnlbXX0gaXRlbXMgT2dnZXR0aSBkYSBlc3BvcnRhcmVcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBzZXR1cEV4cG9ydChpdGVtczogYW55W10pIHtcclxuICAgICAgICBsZXQgZHJjZCA9IHRoaXMuRHluYW1pY1Jvd0NvbHVtbnNEZWZpbml0aW9uO1xyXG5cclxuICAgICAgICB0aGlzLmhlYWRlcnMgPSBkcmNkICYmIGRyY2QubGVuZ3RoID4gMCA/IHRoaXMuZXhwRXh0cy5zZXR1cEZvckdlbmVyaWNFeHBvcnQoaXRlbXMsIGRyY2QubWFwKHQgPT4geyByZXR1cm4geyBsYWJlbDogdC5kZXNjcmlwdGlvbiwga2V5OiB0LnByb3BlcnR5TmFtZSwgb3JkZXI6IHQuY29sdW1uT3JkZXIgfSB9KSkgOiB0aGlzLmV4cEV4dHMuc2V0dXBGb3JFeHBvcnQoaXRlbXMpO1xyXG4gICAgICAgIHRoaXMuZGF0YSA9IGl0ZW1zO1xyXG4gICAgfVxyXG5cclxuICAgIC8vICNlbmRyZWdpb25cclxuXHJcbiAgICAvLyAjcmVnaW9uIEdlc3Rpb25lIE1vZGFsaXTDoCBSZXBvcnRcclxuXHJcbiAgICAvKipcclxuICAgICAqIFN1bCBjbGljayBkZWxsJ0hlYWRlciBkaSB1bmEgY29sb25uYSBxdWVzdG8gbWV0b2RvIHNpIG9jY3VwYSBkaSBhcHBsaWNhcmUgbCdvcmRpbmFtZW50byBzdWNjZXNzaXZvIGUgZGkgbm90aWZpY2FyZSBjb24gKiplbWl0U2VhcmNoUmVxdWVzdCoqXHJcbiAgICAgKiBpbCBiaXNvZ25vIGRpIGFnZ2lvcm5hcmUgaSBkYXRpIGRhIHBhcnRlIGRlbCBjb21wb25lbnRlIGNoZSB1dGlsaXp6YSBsYSB0YWJlbGxhXHJcbiAgICAgKlxyXG4gICAgICogVXRpbGl6emF0byBzb2xvIGluIG1vZGFsaXTDoCBSRXBvcnRcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge1JlcG9ydENvbHVtbn0gY2xtIENvbG9ubmEgZGVsIHJlcG9ydCBwZXIgY3VpIG9yZGluYXJlXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzZXR1cE5leHRPcmRlckFuZFNlYXJjaChjbG06IFJlcG9ydENvbHVtbikge1xyXG4gICAgICAgIGlmICghKHRoaXMuVmlldyBpbnN0YW5jZW9mIFJlcG9ydERlZmluaXRpb24pKSB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1ZpZXcgZGl2ZXJzYSBkYSByZXBvcnRkZWZpbml0aW9uIGVudHJhdGEgbmVsIG1ldG9kbyBzZXR1cE5leHRPcmRlckFuZFNlYXJjaCcpO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBsZXQgb3JkZXJOZXh0ID0geyBOT05FOiAnREVTQycsIERFU0M6ICdBU0MnLCBBU0M6IG51bGwgfTtcclxuICAgICAgICBsZXQgbmV4dE9yZGVyID0gb3JkZXJOZXh0W2NsbS5vcmRlciB8fCAnTk9ORSddO1xyXG4gICAgICAgIGNsbS5vcmRlciA9IG5leHRPcmRlcjtcclxuXHJcbiAgICAgICAgbGV0IG9yZGVyOiBSZXBvcnRPcmRlcjtcclxuICAgICAgICBsZXQgY2xtT3JkZXIgPSB0aGlzLlZpZXcub3JkZXJzID8gdGhpcy5WaWV3Lm9yZGVycy5maWx0ZXIodCA9PiB0LmNvbHVtbiA9PSBjbG0uaWQpIDogW107XHJcbiAgICAgICAgaWYgKGNsbU9yZGVyLmxlbmd0aCA9PSAwICYmIGNsbS5vcmRlcikge1xyXG4gICAgICAgICAgICBvcmRlciA9IG5ldyBSZXBvcnRPcmRlcigpO1xyXG4gICAgICAgICAgICBvcmRlci5jb2x1bW4gPSBjbG0uaWQ7XHJcbiAgICAgICAgICAgIG9yZGVyLm9yZGVyID0gY2xtLm9yZGVyO1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuVmlldy5vcmRlcnMpXHJcbiAgICAgICAgICAgICAgICB0aGlzLlZpZXcub3JkZXJzID0gW107XHJcblxyXG4gICAgICAgICAgICB0aGlzLlZpZXcub3JkZXJzLnB1c2gob3JkZXIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIGlmIChjbG1PcmRlci5sZW5ndGggPT0gMSkge1xyXG4gICAgICAgICAgICAvLyBSaW11b3ZvIGwnb3JkaW5hbWVudG8gbyBhZ2dpb3JubyBxdWVsbG8gZ2nDoCBlc2lzdGVudGVcclxuICAgICAgICAgICAgaWYoIWNsbS5vcmRlcilcclxuICAgICAgICAgICAgICAgIGNsbU9yZGVyID0gW107XHJcbiAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgIGNsbU9yZGVyWzBdLm9yZGVyID0gY2xtLm9yZGVyO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignSW1wb3NzaWJpbGUgc2V0dGFyZSBvcmRpbmFtZW50by4gQ29sb25uYSAnICsgY2xtLmlkICsgJyBkaXJldHRpdmUgZGkgb3JkaW5hbWVudG8gJyArIGNsbU9yZGVyLmxlbmd0aCArICcgb3JkaW5hbWVudG8gc2NlbHRvICcgKyBjbG0ub3JkZXIpO1xyXG5cclxuICAgICAgICAvLyBEb3BvIGF2ZXIgYWdnaW9ybmF0byBsJ29yZGluYW1lbnRvIHJpbGFuY2lvIGxhIHJpY2VyY2FcclxuICAgICAgICB0aGlzLmVtaXRTZWFyY2hSZXF1ZXN0KGZhbHNlKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIE1ldG9kbyBjaGUgc2kgb2NjdXBhIGRpIGdlc3RpcmUgbGEgZ3JhZmljYSBkZWxsYSB0YWJlbGxhIGluIGJhc2UgYWxsZSBpbmZvcm1hemlvbmkgZGkgb3JkaW5hbWVudG8gY29sb25uZSBlIHBhZ2luYXppb25lIGNvbnRlbnV0aSBuZWwgbW9kZWxsb1xyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHJldmlld1JlcG9ydEJpbmRpbmdzKCkge1xyXG4gICAgICAgIGlmICghKHRoaXMuVmlldyBpbnN0YW5jZW9mIFJlcG9ydERlZmluaXRpb24pKSB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1ZpZXcgZGl2ZXJzYSBkYSByZXBvcnRkZWZpbml0aW9uIGVudHJhdGEgbmVsIG1ldG9kbyByZXZpZXdSZXBvcnRCaW5kaW5ncycpO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBBbGxpbmVvIGxlIGluZm9ybWF6aW9uaSBzdSBldmVudHVhbGkgb3JkaW5hbWVudGkgZmF0dGkgcHJlY2VkZW50ZW1lbnRlXHJcbiAgICAgICAgaWYgKHRoaXMuVmlldy5vcmRlcnMgJiYgdGhpcy5WaWV3Lm9yZGVycy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIHRoaXMuVmlldy5vcmRlcnMuZm9yRWFjaCh0ID0+IHtcclxuICAgICAgICAgICAgICAgIHRoaXMuUmVwb3J0VmFsdWVzLmNvbHVtbnMuZmlsdGVyKGMgPT4gYy5pZCA9PSB0LmNvbHVtbilbMF0ub3JkZXIgPSB0Lm9yZGVyO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIFJlY3VwZXJvIGlsIGNvdW50IHByZWNlZGVudGUgc2Ugc2VydmVcclxuICAgICAgICBpZiAodGhpcy5SZXBvcnRWYWx1ZXMuY291bnQgIT0gLTIpXHJcbiAgICAgICAgICAgIHRoaXMucHJldmlvdXNDb3VudCA9IHRoaXMuUmVwb3J0VmFsdWVzLmNvdW50O1xyXG4gICAgICAgIGVsc2UgaWYgKHRoaXMuUmVwb3J0VmFsdWVzLmNvdW50ID09IC0yKVxyXG4gICAgICAgICAgICB0aGlzLlJlcG9ydFZhbHVlcy5jb3VudCA9IHRoaXMucHJldmlvdXNDb3VudDtcclxuXHJcbiAgICAgICAgbGV0IGlwcCA9ICh0aGlzLlZpZXcuaXRlbXNwZXJwYWdlb3ZlcnJpZGUgfHwgMTUpO1xyXG4gICAgICAgIHRoaXMuVmlldy5wYWdlcyA9IE1hdGguY2VpbCh0aGlzLlJlcG9ydFZhbHVlcy5jb3VudCAvIGlwcCk7XHJcbiAgICAgICAgdGhpcy5hcnJheVB1bHNhbnRpID0gdGhpcy5nZXRQYWdlc0FycmF5KDYsIHRoaXMuVmlldy5wYWdlLCB0aGlzLlZpZXcucGFnZXMpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vICNlbmRyZWdpb25cclxuXHJcbiAgICAvLyAjcmVnaW9uIEdlc3Rpb25lIHVwZGF0ZSBhdXRvbWF0aWNvXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBNZXRvZG8gY2hlIGdlc3Rpc2NlIGxhIG1vZGlmaWNhIGRlbCB0ZW1wbyBzcGVjaWZpY2F0byBwZXIgbCdhZ2dpb3JuYW1lbnRvIGF1dG9tYXRpY29cclxuICAgICAqL1xyXG4gICAgcHVibGljIGF1dG9VcGRhdGVDaGFuZ2VkKCkge1xyXG4gICAgICAgIGlmICghL15bMS05XVxcZCokLy50ZXN0KHRoaXMuc2Vjb25kcykpXHJcbiAgICAgICAgICAgIHRoaXMuc2Vjb25kcyA9ICcxMCc7XHJcblxyXG4gICAgICAgIGxldCBzZWNvbmRzSW5NcyA9IHBhcnNlSW50KHRoaXMuc2Vjb25kcywgbnVsbCkgKiAxMDAwO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5hdXRvVXBkYXRlKVxyXG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVRpbWVyID0gc2V0SW50ZXJ2YWwoKCkgPT4geyB0aGlzLmVtaXRTZWFyY2hSZXF1ZXN0KGZhbHNlKTsgfSwgc2Vjb25kc0luTXMpO1xyXG4gICAgICAgIGVsc2VcclxuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLnVwZGF0ZVRpbWVyKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyAjZW5kcmVnaW9uXHJcblxyXG4gICAgLy8gI3JlZ2lvbiBHZXN0aW9uZSB0YWJlbGxhIGRpbmFtaWNhXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBNZXRvZG8gY2hpYW1hdG8gZGFsIGNsaWNrIHN1IHVuYSBkZWxsZSBjb2xvbm5lIGdlbmVyYXRlIGRhbGwnSW5wdXQgKipEeW5hbWljT3BlcmF0aW9ucyoqXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHthbnl9IGl0ZW0gTCdvZ2dldHRvIHN1IGN1aSB2YSBlZmZldHR1YXRhIGwnb3BlcmF6aW9uZVxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9waWQgQ29kaWNlIGlkZW50aWZpY2F0aXZvIGRlbGwnb3BlcmF6aW9uZSBkYSBlZmZldHR1YXJzaVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZHluYW1pY09wZXJhdGlvbihpdGVtOiBhbnksIG9waWQ6IHN0cmluZykge1xyXG4gICAgICAgIHRoaXMub25EeW5hbWljT3BlcmF0aW9uLmVtaXQoeyBpZDogb3BpZCwgaXRlbTogaXRlbSB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIE90dGllbmUgaWwgY29udGVudXRvIGRlbGwnRXNUZCBkYSB1dGlsaXp6YXJlIHBlciBsYSBjb2xvbm5hIHNwZWNpZmljYXRhXHJcbiAgICAgKiBcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBjb2x1bW4gQ29sb25uYSBwZXIgY3VpIGNlcmNhcmUgbGEgY2VsbGFcclxuICAgICAqIFxyXG4gICAgICogQHJldHVybnMge1RlbXBsYXRlUmVmPGFueT59IFRlbXBsYXRlIGRhIHVzYXJlIHBlciBsYSBjb2xvbm5hXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBmaW5kRXNUZChjb2x1bW46IHN0cmluZyk6IFRlbXBsYXRlUmVmPGFueT4ge1xyXG4gICAgICAgIHZhciBFc1RkID0gdGhpcy5Fc1Rkc0RpcmVjdGl2ZS5maW5kKChpdGVtKSA9PiBpdGVtLnRkID09PSBjb2x1bW4pO1xyXG4gICAgICAgIHJldHVybiBFc1RkID8gRXNUZC5UZW1wbGF0ZSA6IG51bGw7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBNZXRvZG8gZGkgc3VwcG9ydG8gYWxsYSBjcmVhemlvbmUgZGkgdW4gcm91dGVyIGxpbmsgcGFyYW1ldHJpenphdG8gYWxsJ29nZ2V0dG8gY29ycmVudGUgdXRpbGl6emF0byBuZWxsYSBtb2RhbGl0w6AgZGluYW1pY2FcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcGF0aCBQYXRoIHN1IGN1aSBuYXZpZ2FyZSBjb24gZXZlbnR1YWxpIHBhcmFtZXRyaSByaWZlcml0aSBhbGwnb2dnZXR0byBjb3RuZXN0dWFsZSBjb21lIHswfSwgezF9LCBlY2MuLi5cclxuICAgICAqIEBwYXJhbSB7c3RyaW5nW119IHBhcmFtZXRlclByb3BzIExpc3RhIHBvc2l6aW9uYWxlIGRlbGxlIHByb3ByaWV0w6AgYSBjdWkgYmluZGFyZSBpIHJpZmVyaW1lbnRpIGRlbCBwYXJhbWV0cm8gKipwYXRoKipcclxuICAgICAqIEVzLiBJbCB2YWxvcmUgZGVsYSBwcm9wcmlldMOgIGFsbCdpbmRpY2UgMCBkaSBxdWVzdG8gYXJyYXkgdmVycsOgIHNvc3RpdHVpdGEgYWwgdmFsb3JlIHswfSBkZWwgcGFyYW1ldHJvICoqcGF0aCoqXHJcbiAgICAgKiBAcGFyYW0ge0dlbmVyaWNJdGVtfSBpdGVtIE9nZ2V0dG8gZ2VuZXJpY28gY29sbGVnYXRvIGEgcXVlc3RvIGNvbnRlc3RvXHJcbiAgICAgKlxyXG4gICAgICogQHJldHVybnMge2FueX0gUm91dGVyIGxpbmsgZ2VuZXJhdG8gaW4gYmFzZSBhbCBwYXJhbWV0cmlcclxuICAgICAqL1xyXG4gICAgcHVibGljIGdlbmVyYXRlUm91dGVyTGluayhwYXRoOiBzdHJpbmcsIHBhcmFtZXRlclByb3BzOiBzdHJpbmdbXSwgaXRlbTogR2VuZXJpY0l0ZW0pOiBhbnkge1xyXG4gICAgICAgIGlmICh0aGlzLkR5bmFtaWNUYWJsZVJvdXRlckxpbmtDYWNoZVtpdGVtLmhhc2ggKyBwYXRoXSkge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5EeW5hbWljVGFibGVSb3V0ZXJMaW5rQ2FjaGVbaXRlbS5oYXNoICsgcGF0aF07XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgbGV0IGxpbmsgPSB0aGlzLmdldFJvdXRlckxpbmsocGF0aCwgcGFyYW1ldGVyUHJvcHMsIGl0ZW0pO1xyXG4gICAgICAgICAgICB0aGlzLkR5bmFtaWNUYWJsZVJvdXRlckxpbmtDYWNoZVtpdGVtLmhhc2ggKyBwYXRoXSA9IGxpbms7XHJcbiAgICAgICAgICAgIHJldHVybiBsaW5rO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENyZWEgdW4gcm91dGVyIGxpbmtcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcGF0aCBQYXRoIHN1IGN1aSBuYXZpZ2FyZSBjb24gZXZlbnR1YWxpIHBhcmFtZXRyaSByaWZlcml0aSBhbGwnb2dnZXR0byBjb3RuZXN0dWFsZSBjb21lIHswfSwgezF9LCBlY2MuLi5cclxuICAgICAqIEBwYXJhbSB7c3RyaW5nW119IHBhcnMgTGlzdGEgcG9zaXppb25hbGUgZGVsbGUgcHJvcHJpZXTDoCBhIGN1aSBiaW5kYXJlIGkgcmlmZXJpbWVudGkgZGVsIHBhcmFtZXRybyAqKnBhdGgqKlxyXG4gICAgICogRXMuIElsIHZhbG9yZSBkZWxhIHByb3ByaWV0w6AgYWxsJ2luZGljZSAwIGRpIHF1ZXN0byBhcnJheSB2ZXJyw6Agc29zdGl0dWl0YSBhbCB2YWxvcmUgezB9IGRlbCBwYXJhbWV0cm8gKipwYXRoKipcclxuICAgICAqIEBwYXJhbSB7R2VuZXJpY0l0ZW19IGl0ZW0gT2dnZXR0byBnZW5lcmljbyBjb2xsZWdhdG8gYSBxdWVzdG8gY29udGVzdG9cclxuICAgICAqXHJcbiAgICAgKiBAcmV0dXJucyB7YW55fSBSb3V0ZXIgbGluayBnZW5lcmF0byBpbiBiYXNlIGFsIHBhcmFtZXRyaVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGdldFJvdXRlckxpbmsocGF0aDogc3RyaW5nLCBwYXJzOiBzdHJpbmdbXSwgaXRlbTogR2VuZXJpY0l0ZW0pOiBhbnkge1xyXG5cclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBhcnMubGVuZ3RoOyBpKyspXHJcbiAgICAgICAgICAgIHBhdGggPSBwYXRoLnJlcGxhY2UoJ3snICsgaSArICd9JywgaXRlbS5wcm9wZXJ0aWVzW3BhcnNbaV1dKTtcclxuXHJcbiAgICAgICAgcGF0aCA9IHBhdGgucmVwbGFjZSgvJy9nLCAnXCInKS5yZXBsYWNlKC8gL2csICcnKTtcclxuICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShwYXRoKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyAjZW5kcmVnaW9uXHJcblxyXG4gICAgLy8gI3JlZ2lvbiBQYWdpbmF6aW9uZSBpbiBtb2RhbGl0w6AgQXJyYXlcclxuXHJcbiAgICAvKipcclxuICAgICAqIEVxdWl2YWxlbnRlIGRlbCBtZXRvZG8gKiphZGRUb1BhZ2UqKiByaWFkYXR0YXRvIHBlciBsYSBtb2RhbGl0w6AgYXJyYXlcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gcGFnZSBOdW1lcm8gZGkgcGFnaW5lIGRhIGFnZ2l1bmdlcmUgKG8gc290dHJhcnJlLCBzZSBuZWdhdGl2bykgYWxsYSBwYWdpbmEgYXR0dWFsZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgYXJyYXlBZGRUb1BhZ2UocGFnZTogbnVtYmVyKSB7XHJcbiAgICAgICAgdGhpcy5hcnJheUdvVG9QYWdlKHRoaXMuYXJyYXltb2RlUGFnZSArIHBhZ2UpXHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBFcXVpdmFsZW50ZSBkZWwgbWV0b2RvICoqZ29Ub1BhZ2UqKiByaWFkYXR0YXRvIHBlciBsYSBtb2RhbGl0w6AgYXJyYXlcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gcGFnZSBQYWdpbmEgYSBjdWkgbmF2aWdhcmVcclxuICAgICAqL1xyXG4gICAgcHVibGljIGFycmF5R29Ub1BhZ2UocGFnZTogbnVtYmVyKSB7XHJcbiAgICAgICAgaWYgKHBhZ2UgPT09IDAgfHwgcGFnZSA+IHRoaXMuYXJyYXltb2RlUGFnZXMpXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB0aGlzLmFycmF5bW9kZVBhZ2UgPSBwYWdlO1xyXG5cclxuICAgICAgICAvLyBSaWZvcnpvIGlsIHdyaXRldmFsdWUgaW4gbW9kbyBjaGUgaWwgY29kaWNlIHBhc3NpIGRhbGxhIGdlc3Rpb25lIGNvbWUgc2UgZm9zc2UgZmF0dGEgcmlwYXJ0aXJlIHVuYSByaWNlcmNhXHJcbiAgICAgICAgdGhpcy5pbnRlcm5hbFdyaXRlVmFsdWUoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIE1ldG9kbyBwZXIgZWZmZXR0dWFyZSBpbCByZWZyZXNoIGRlbGxhIHBhZ2luYXppb25lIHN1bCBjYW1iaWFtZW50byBkZWdsaSBvZ2dldHRpIGRhIHZpc3VhbGl6emFyZSBpbiB1bmEgc2luZ29sYSBwYWdpbmEuXHJcbiAgICAgKlxyXG4gICAgICogVmFsZSBzb2xvIHBlciBsYSBtb2RhbGl0w6AgQXJyYXlcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gcGFnZVNpemUgRGltZW5zaW9uZSBkZWxsYSBwYWdpbmFcclxuICAgICAqL1xyXG4gICAgcHVibGljIHJlZnJlc2hQYWdpbmcocGFnZVNpemU6IG51bWJlcikge1xyXG4gICAgICAgIHRoaXMuQXJyYXltb2RlSXRlbXNQZXJQYWdlID0gcGFnZVNpemU7XHJcbiAgICAgICAgdGhpcy5hcnJheW1vZGVQYWdlcyA9IE1hdGguY2VpbCgodGhpcy5WaWV3IGFzIGFueVtdKS5sZW5ndGggLyB0aGlzLkFycmF5bW9kZUl0ZW1zUGVyUGFnZSk7XHJcbiAgICAgICAgdGhpcy5hcnJheW1vZGVQYWdlID0gMTtcclxuXHJcbiAgICAgICAgLy8gUmlmb3J6byBpbCB3cml0ZXZhbHVlIGluIG1vZG8gY2hlIGlsIGNvZGljZSBwYXNzaSBkYWxsYSBnZXN0aW9uZSBjb21lIHNlIGZvc3NlIGZhdHRhIHJpcGFydGlyZSB1bmEgcmljZXJjYVxyXG4gICAgICAgIHRoaXMuaW50ZXJuYWxXcml0ZVZhbHVlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZW5lcmEgbGUgaW5mb3JtYXppb25pIGRpIHBhZ2luYXppb25lIGUgdGFnbGlhIGxhIFZpZXcgaW4gbW9kYWxpdMOgIGFycmF5IHBlciBtb3N0cmFyZSBzb2xvIGdsaSBvZ2dldHRpIGRlbGxhIHBhZ2luYSBzcGVjaWZpY2F0YVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGFkYXB0Vmlld1RvUGFnaW5nKCkge1xyXG4gICAgICAgIGxldCB0bXBJdGVtczogYW55W10gPSBbXTtcclxuXHJcbiAgICAgICAgLy8gU2UgaG8gdW5hIHNlYXJjaCB2aWV3IGwnYXJyYXkgcHVsc2FudGkgdmllbmUgY2FsY29sYXRvIGRhIGxlaSwgbm9uIGRldm8gcHJlbmRlcmUgcXVlbGxvIGRlbGxhIG1vZGFsaXTDoCBhcnJheVxyXG4gICAgICAgIGlmKCF0aGlzLlNlYXJjaFZpZXcpXHJcbiAgICAgICAgICAgIHRoaXMuYXJyYXlQdWxzYW50aSA9IHRoaXMuZ2V0UGFnZXNBcnJheSg2LCB0aGlzLmFycmF5bW9kZVBhZ2UsIHRoaXMuYXJyYXltb2RlUGFnZXMpO1xyXG5cclxuICAgICAgICAvLyBQb2kgcGVyIHR1dHRpIGkgdmFsb3JpIGRvcG8gY29tcHJlc2kgZnJhIGxhIHBhZ2luYSAtIDEgZSBsYSBwYWdpbmFcclxuICAgICAgICBmb3IgKGxldCBpID0gKCh0aGlzLmFycmF5bW9kZVBhZ2UgLSAxKSAqIHRoaXMuQXJyYXltb2RlSXRlbXNQZXJQYWdlKTsgaSA8IHRoaXMuYXJyYXltb2RlUGFnZSAqIHRoaXMuQXJyYXltb2RlSXRlbXNQZXJQYWdlOyBpKyspIHtcclxuICAgICAgICAgICAgaWYgKGkgPD0gKHRoaXMuVmlldyBhcyBhbnlbXSkubGVuZ3RoIC0gMSlcclxuICAgICAgICAgICAgICAgIHRtcEl0ZW1zLnB1c2goKHRoaXMuVmlldyBhcyBhbnlbXSlbaV0pO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdG1wSXRlbXM7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gI2VuZHJlZ2lvblxyXG5cclxuICAgIC8vICNyZWdpb24gR2VzdGlvbmUgY2xpY2sgc3VsbGUgY2VsbGUgZGluYW1pY2hlIGUgb3B6aW9uaSBuZWwgQ29ybmVyIE1lbnVcclxuXHJcbiAgICAvKipcclxuICAgICAqIEdlc3RvcmUgZGVpIGNsaWNrIHN1bGxlIGNlbGxlIHBlciBsZSBxdWFsaSBlcmEgaW1wb3N0YXRhIHVuYSBhemlvbmUgY3VzdG9tIGRhICoqQ3VzdG9tQ2VsbEFjdGlvbnNPbioqXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgTm9tZSBkZWxsYSBjZWxsYSBzdSBjdWkgc2kgw6ggZmF0dG8gY2xpY2tcclxuICAgICAqIEBwYXJhbSB7YW55fSBtb2RlbCBNb2RlbGxvIHJlbGF0aXZvIGFsbGEgY2VsbGEgY2xpY2NhdGFcclxuICAgICAqXHJcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gKip0cnVlKiogc2UgaWwgY2xpY2sgw6ggc3RhdG8gZmF0dG8gc3UgdW5hIGNlbGxhIGNsaWNjYWJpbGUsICoqZmFsc2UqKiBhbHRyaW1lbnRpXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBjZWxsQ2xpY2tlZChuYW1lOiBzdHJpbmcsIG1vZGVsOiBhbnkpOiBib29sZWFuIHtcclxuICAgICAgICBpZiAodGhpcy5Vc2VDdXN0b21DZWxsQWN0aW9ucyAmJiB0aGlzLkN1c3RvbUNlbGxBY3Rpb25zT24uc3BsaXQoJyQnKS5pbmRleE9mKG5hbWUpICE9IC0xKSB7XHJcbiAgICAgICAgICAgIHRoaXMub25DZWxsQ2xpY2suZW1pdCh7IGNvbHVtbjogbmFtZSwgbW9kZWw6IG1vZGVsIH0pO1xyXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEdlc3Rpb25lIGRlaSBjbGljayBzdWxsZSBvcHppb25pIGRlbCBtZW7DuSBjb250ZXN0dWFsZSBpbiBhbHRvIGEgZGVzdHJhIGdlbmVyYXRvIGRhbGwnSW5wdXQgKipDb3JuZXJNZW51T3B0aW9ucyoqXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGNvcm5lcmlkIENvZGljZSBkZWxsJ29wZXJhemlvbmUgc2VsZXppb25hdGFcclxuICAgICAqL1xyXG4gICAgcHVibGljIGNvcm5lckFjdGlvbkNsaWNrZWQoY29ybmVyaWQ6IHN0cmluZykge1xyXG4gICAgICAgIHRoaXMub25Db3JuZXJBY3Rpb24uZW1pdCh7IGlkOiBjb3JuZXJpZCwgZXN0YWJsZTogdGhpcyB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvLyAjZW5kcmVnaW9uXHJcblxyXG4gICAgLy8gI3JlZ2lvbiBNZXRvZGkgZGkgdXRpbGl0w6BcclxuXHJcbiAgICAvKiogSGVscGVyIGNoZSBpZGVudGlmaWNhIHNlIGlsIHRkIGF0dHVhbGUgw6ggZGkgdGlwbyAqKkVzVGQqKi4gSW4gY2FzbyBjb250cmFyaW8gw6ggZGEgY29uc2lkZXJhcnNpICoqRXNUZERpcmVjdGl2ZSoqICovXHJcbiAgICBwcml2YXRlIGlzRXNUZCh0ZDogYW55KTogdGQgaXMgRXNUZCB7XHJcbiAgICAgICAgcmV0dXJuICF0ZC5fZGlyZWN0aXZlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiAgSGVscGVyIGNoZSBpZGVudGlmaWNhIHNlIGlsIHRoIGF0dHVhbGUgw6ggZGkgdGlwbyAqKkVzVGgqKi4gSW4gY2FzbyBjb250cmFyaW8gw6ggZGEgY29uc2lkZXJhcnNpICoqRXNUaERpcmVjdGl2ZSoqICovXHJcbiAgICBwcml2YXRlIGlzRXNUaCh0aDogYW55KTogdGggaXMgRXNUaCB7XHJcbiAgICAgICAgcmV0dXJuICF0aC5fZGlyZWN0aXZlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBJbXBvc3RhemlvbmUgbW9kYWxpdMOgIGRlbGwnRXNUYWJsZSAqL1xyXG4gICAgcHJpdmF0ZSBzZXRNb2RlKG1vZGU6ICdhcnJheScgfCAndmlldycgfCAncmVwb3J0Jykge1xyXG4gICAgICAgIHRoaXMudmlld01vZGUgPSBtb2RlID09ICd2aWV3JztcclxuICAgICAgICB0aGlzLmFycmF5TW9kZSA9IG1vZGUgPT0gJ2FycmF5JztcclxuICAgICAgICB0aGlzLnJlcG9ydE1vZGUgPSBtb2RlID09ICdyZXBvcnQnO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5yZXBvcnRNb2RlKSB7XHJcbiAgICAgICAgICAgIC8vIEluIG1vZGFsaXTDoCByZXBvcnQgaG8gZGkgc2ljdXJvIHF1ZXN0ZSBkdWVcclxuICAgICAgICAgICAgdGhpcy5YTFNYRXhwb3J0ID0gdHJ1ZTtcclxuICAgICAgICAgICAgdGhpcy5DU1ZFeHBvcnQgPSBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBIZWxwZXIgcGVyIGVmZmV0dHVhcmUgY2hpYW1hdGUgaW50ZXJuZSBkaSBhbGxpbmVhbWVudG8gYWxsYSBmdW56aW9uZSAqKndyaXRlVmFsdWUqKiwgXHJcbiAgICAgKiBpbXBvc3RhbmRvIHByaW1hICoqaW50ZXJuYWxXcml0ZUNhbGwqKiBpbiBtb2RvIGRhIG5vbiBlZmZldHR1YXJlIG9wZXJhemlvbmkgaW51dGlsaVxyXG4gICAgICovXHJcbiAgICAgcHJpdmF0ZSBpbnRlcm5hbFdyaXRlVmFsdWUoKSB7XHJcbiAgICAgICAgdGhpcy5pbnRlcm5hbFdyaXRlQ2FsbCA9IHRydWU7XHJcbiAgICAgICAgdGhpcy53cml0ZVZhbHVlKHRoaXMuVmlldyk7XHJcbiAgICAgICAgdGhpcy5pbnRlcm5hbFdyaXRlQ2FsbCA9IGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGF0ZSBsZSBpbmZvcm1hemlvbmkgZGkgcGFnaW5hemlvbmUgb3R0aWVuZSBsJ2FycmF5IGRlaSBwdWxzYW50aVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBtYXhCdG5zIE51bWVybyBtYXNzaW1vIGRpIHB1bHNhbnRpIGRhIHZpc3VhbGl6emFyZVxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHBhZ2UgUGFnaW5hIGNvcnJlbnRlXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbGFzdFBhZ2UgVWx0aW1hIHBhZ2luYSBkaXNwb25pYmlsZVxyXG4gICAgICpcclxuICAgICAqIEByZXR1cm5zIHthbnlbXX0gUHNldWRvLWFycmF5IGRpIHB1bHNhbnRpIGEgY3VpIGNpIHNpIHB1w7IgYmluZGFyZSBsYXRvIEhUTUxcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBnZXRQYWdlc0FycmF5KG1heEJ0bnM6IG51bWJlciwgcGFnZTogbnVtYmVyLCBsYXN0UGFnZTogbnVtYmVyKTogYW55W10ge1xyXG4gICAgICAgIGxldCByZXN1bHQgPSBbXTtcclxuICAgICAgICBpZiAobGFzdFBhZ2UgPT0gLTEpXHJcbiAgICAgICAgICAgIGxhc3RQYWdlID0gcGFnZSArIDE7XHJcblxyXG4gICAgICAgIGxldCBtaW4sIG1heDtcclxuICAgICAgICBpZiAobGFzdFBhZ2UgPD0gbWF4QnRucykge1xyXG4gICAgICAgICAgICBtaW4gPSAxO1xyXG4gICAgICAgICAgICBtYXggPSBsYXN0UGFnZSAtIDE7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgLy8gdG9sZ28gbGEgcGFnaW5hIHNlbGVjdGVkIMOoIGwndWx0aW1hIHBhZ2luYSBjaGUgw6ggcXVlbGxhIGRlbGxlIHBhZ2luZSB0b3RhbGlcclxuICAgICAgICAgICAgbGV0IHJhbmdlT3V0c2lkZSA9IChtYXhCdG5zIC0gMikgLyAyO1xyXG5cclxuICAgICAgICAgICAgbWluID0gcGFnZSAtIHJhbmdlT3V0c2lkZTtcclxuICAgICAgICAgICAgbWF4ID0gcGFnZSArIHJhbmdlT3V0c2lkZTtcclxuXHJcbiAgICAgICAgICAgIGlmIChtaW4gPCAxKSB7XHJcbiAgICAgICAgICAgICAgICBtaW4gPSAxO1xyXG4gICAgICAgICAgICAgICAgbWF4ID0gbWF4QnRucyAtIDE7XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWF4ID49IGxhc3RQYWdlKSB7XHJcbiAgICAgICAgICAgICAgICBtaW4gPSBsYXN0UGFnZSAtIG1heEJ0bnMgKyAxO1xyXG4gICAgICAgICAgICAgICAgbWF4ID0gbGFzdFBhZ2UgLSAxO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXN1bHQucHVzaCh7IHZhbDogMSwgY3NzQ2xhc3M6ICgxID09PSBwYWdlID8gJ2J0bi1tYWluIGFwcC13aGl0ZS10ZXh0JyA6ICdhcHAtd2hpdGUtYnV0dG9uJykgfSk7XHJcblxyXG4gICAgICAgIGlmIChtYXggPj0gbWluKSB7XHJcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBtaW47IGkgPD0gbWF4OyBpKyspXHJcbiAgICAgICAgICAgICAgICBpZiAoaSAhPT0gMSlcclxuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaCh7IHZhbDogaSwgY3NzQ2xhc3M6IChpID09PSBwYWdlID8gJ2J0bi1tYWluIGFwcC13aGl0ZS10ZXh0JyA6ICdhcHAtd2hpdGUtYnV0dG9uJykgfSk7XHJcblxyXG4gICAgICAgICAgICByZXN1bHQucHVzaCh7XHJcbiAgICAgICAgICAgICAgICB2YWw6IGxhc3RQYWdlLFxyXG4gICAgICAgICAgICAgICAgY3NzQ2xhc3M6IChsYXN0UGFnZSA9PT0gcGFnZSA/ICdidG4tbWFpbiBhcHAtd2hpdGUtdGV4dCcgOiAnYXBwLXdoaXRlLWJ1dHRvbicpXHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ2FsY29sYSBsJ2hhc2ggZGkgdW4gb2dnZXR0byBxdWFsc2lhc2lcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge2FueVtdfSBpdGVtcyBPZ2dldHRpIHBlciBjdWkgY2FsY29sYXJlIGwnaGFzaFxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGNhbGN1bGF0ZUhhc2goaXRlbXM6IGFueVtdKSB7XHJcbiAgICAgICAgaWYgKCFpdGVtcylcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG5cclxuICAgICAgICAvLyBTdXBwb3J0byBhIGhhc2ggZHVwbGljYXRpIGRpIG9nZ2V0dGkgdWd1YWxpXHJcbiAgICAgICAgbGV0IHVzZWRIYXNoZXNDYWNoZTogeyBbaW5kZXg6IHN0cmluZ106IG51bWJlciB9ID0ge307XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpdGVtcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBsZXQgaXRlbSA9IGl0ZW1zW2ldO1xyXG5cclxuICAgICAgICAgICAgLy8gUHJpbWEgZGkgY2FsY29sYXJlIGwnaGFzaCByaW11b3ZvIGxlIHByb3ByaWV0w6AgaW50ZXJuZSBwcmltYSBjaGUgbWkgc2NvbXBlbnNpbm8gaSBjYWxjb2xpIHN1Y2Nlc3NpdmlcclxuICAgICAgICAgICAgZGVsZXRlIGl0ZW0uX3NlbGVjdGVkO1xyXG4gICAgICAgICAgICBkZWxldGUgaXRlbS5oYXNoO1xyXG5cclxuICAgICAgICAgICAgbGV0IGhhc2ggPSB0aGlzLmhhc2hFeHRzLmhhc2hPYmplY3QoaXRlbSk7XHJcbiAgICAgICAgICAgIHVzZWRIYXNoZXNDYWNoZVtoYXNoXSA9IHVzZWRIYXNoZXNDYWNoZVtoYXNoXSA/IHVzZWRIYXNoZXNDYWNoZVtoYXNoXSArIDEgOiAxO1xyXG4gICAgICAgICAgICBpdGVtLmhhc2ggPSBoYXNoICsgKHVzZWRIYXNoZXNDYWNoZVtoYXNoXSA+IDEgPyBcIl9cIiArIHVzZWRIYXNoZXNDYWNoZVtoYXNoXSA6IFwiXCIpXHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTWV0b2RvIGV2ZW50dWFsbWVudGUgcmljaGlhbWFiaWxlIGFuY2hlIGRhbCBjb21wb25lbnRlIGVzdGVybm8gY2hlIHBlcm1ldHRlIGRpIGZvcnphcmUgdW4gcmVmcmVzaCBkZWxsYSB0YWJlbGxhXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBmb3JjZVJlZnJlc2goKSB7XHJcblxyXG4gICAgICAgIC8vIFNlIHNvbm8gaW4gbW9kYWxpdMOgIFZpZXcgdmllbmUgbWFudGVudXRvIGluIGF1dG9tYXRpY28gaWwgbnVtZXJvIGRpIHBhZ2luYSwgbWEgcGVyIGxhIG1vZGFsaXTDoCBhcnJheSBkZXZvIHByZW5kZXJlIGxlIGluZm8gZGkgcGFnaW5hemlvbmUgcHJpbWEgZSByaWFwcGxpY2FybGUgZG9wb1xyXG4gICAgICAgIGxldCBhcnJheVBhZ2U6IG51bWJlcjtcclxuICAgICAgICBsZXQgYXJyYXlJcHA6IG51bWJlcjtcclxuICAgICAgICBpZiAodGhpcy5hcnJheU1vZGUpIHtcclxuICAgICAgICAgICAgYXJyYXlQYWdlID0gdGhpcy5hcnJheW1vZGVQYWdlO1xyXG4gICAgICAgICAgICBhcnJheUlwcCA9IHRoaXMuQXJyYXltb2RlSXRlbXNQZXJQYWdlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy53cml0ZVZhbHVlKHRoaXMuVmlldyk7XHJcbiAgICAgICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5hcnJheU1vZGUpIHtcclxuICAgICAgICAgICAgdGhpcy5BcnJheW1vZGVJdGVtc1BlclBhZ2UgPSBhcnJheUlwcDtcclxuICAgICAgICAgICAgdGhpcy5hcnJheUdvVG9QYWdlKGFycmF5UGFnZSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vICNlbmRyZWdpb25cclxufSJdfQ==