@techextensor/tab-sdk 0.0.41 → 0.0.43
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.
- package/README.md +24 -24
- package/fesm2022/techextensor-tab-sdk.mjs +770 -48
- package/fesm2022/techextensor-tab-sdk.mjs.map +1 -1
- package/lib/interface/state.interface.d.ts +151 -0
- package/lib/model/component-state.model.d.ts +63 -0
- package/lib/model/query-state.model.d.ts +37 -0
- package/lib/model/screen-state.model.d.ts +56 -0
- package/lib/model/script-state.model.d.ts +21 -0
- package/lib/state/state.service.d.ts +101 -0
- package/lib/tab-sdk.service.d.ts +4 -0
- package/lib/ui/ui.service.d.ts +5 -5
- package/lib/workflow/workflow.service.d.ts +8 -0
- package/package.json +2 -4
- package/public-api.d.ts +1 -0
- package/esm2022/lib/app/analytics.service.mjs +0 -51
- package/esm2022/lib/app/app.service.mjs +0 -175
- package/esm2022/lib/app/file.service.mjs +0 -84
- package/esm2022/lib/app/release.service.mjs +0 -38
- package/esm2022/lib/app/report.service.mjs +0 -48
- package/esm2022/lib/app/translator.service.mjs +0 -77
- package/esm2022/lib/auth/auth.service.mjs +0 -95
- package/esm2022/lib/crud/crud.service.mjs +0 -191
- package/esm2022/lib/enum/store.enum.mjs +0 -6
- package/esm2022/lib/enum/ui.enum.mjs +0 -13
- package/esm2022/lib/http/http.service.mjs +0 -58
- package/esm2022/lib/interface/http.interface.mjs +0 -2
- package/esm2022/lib/interface/ui.interface.mjs +0 -2
- package/esm2022/lib/store/store.service.mjs +0 -829
- package/esm2022/lib/tab-sdk.service.mjs +0 -84
- package/esm2022/lib/ui/form.service.mjs +0 -79
- package/esm2022/lib/ui/ui.service.mjs +0 -344
- package/esm2022/lib/util/util.service.mjs +0 -54
- package/esm2022/lib/workflow/transition.service.mjs +0 -40
- package/esm2022/public-api.mjs +0 -9
- package/esm2022/techextensor-tab-sdk.mjs +0 -5
|
@@ -1,829 +0,0 @@
|
|
|
1
|
-
import { inject, Injectable } from '@angular/core';
|
|
2
|
-
import { LocalStorageService, SessionStorageService, StorageConstants } from '@techextensor/tab-core-utility';
|
|
3
|
-
import { StorageType } from '../enum/store.enum';
|
|
4
|
-
import * as i0 from "@angular/core";
|
|
5
|
-
export class StoreService {
|
|
6
|
-
_localStorageService = inject(LocalStorageService);
|
|
7
|
-
_sessionStorageService = inject(SessionStorageService);
|
|
8
|
-
/**
|
|
9
|
-
* Retrieves the tenant ID from the local storage.
|
|
10
|
-
*/
|
|
11
|
-
get tenantId() {
|
|
12
|
-
return this.getOrgInfo()?.Id || null;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Sets the tenant ID in the organization info.
|
|
16
|
-
*
|
|
17
|
-
* @param value - The tenant ID to set.
|
|
18
|
-
*/
|
|
19
|
-
set tenantId(value) {
|
|
20
|
-
// Retrieve the existing organization info or initialize a new object
|
|
21
|
-
const orgInfo = this.getOrgInfo() || {};
|
|
22
|
-
// Update the tenant ID value
|
|
23
|
-
orgInfo.Id = value;
|
|
24
|
-
// Save the updated organization info back to storage
|
|
25
|
-
this.setOrgInfo(orgInfo);
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Retrieves the tenant name from the organization info.
|
|
29
|
-
*/
|
|
30
|
-
get tenantName() {
|
|
31
|
-
// Retrieve the organization info from storage
|
|
32
|
-
const orgInfo = this.getOrgInfo();
|
|
33
|
-
// Return the tenant name if it exists, otherwise return null
|
|
34
|
-
return orgInfo?.OrganizationName || null;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Sets the tenant name in the organization info.
|
|
38
|
-
*
|
|
39
|
-
* @param value - The tenant name to set.
|
|
40
|
-
*/
|
|
41
|
-
set tenantName(value) {
|
|
42
|
-
// Retrieve the existing organization info or initialize a new object
|
|
43
|
-
const orgInfo = this.getOrgInfo() || {};
|
|
44
|
-
// Update the organization name value
|
|
45
|
-
orgInfo.OrganizationName = value;
|
|
46
|
-
// Save the updated organization info back to storage
|
|
47
|
-
this.setOrgInfo(orgInfo);
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Retrieves the subdomain from the organization info.
|
|
51
|
-
*
|
|
52
|
-
* @returns The subdomain if it exists, otherwise `null`.
|
|
53
|
-
*/
|
|
54
|
-
get subdomain() {
|
|
55
|
-
// Retrieve the organization info from storage
|
|
56
|
-
const orgInfo = this.getOrgInfo();
|
|
57
|
-
// Return the subdomain if it exists, otherwise return null
|
|
58
|
-
return orgInfo?.Subdomain || null;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Sets the subdomain in the organization info.
|
|
62
|
-
*
|
|
63
|
-
* @param value - The subdomain to set.
|
|
64
|
-
*/
|
|
65
|
-
set subdomain(value) {
|
|
66
|
-
// Retrieve the existing organization info or initialize a new object
|
|
67
|
-
const orgInfo = this.getOrgInfo() || {};
|
|
68
|
-
// Update the subdomain value
|
|
69
|
-
orgInfo.Subdomain = value;
|
|
70
|
-
// Save the updated organization info back to storage
|
|
71
|
-
this.setOrgInfo(orgInfo);
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Retrieves the locale settings from the organization info.
|
|
75
|
-
*
|
|
76
|
-
* @returns The locale settings if they exist, otherwise `null`.
|
|
77
|
-
*/
|
|
78
|
-
get orgLocaleSettings() {
|
|
79
|
-
// Retrieve the locale settings from the organization info
|
|
80
|
-
let localSettings = this.getOrgInfo()?.LocaleSettings;
|
|
81
|
-
// If the locale settings are a string, parse them as JSON
|
|
82
|
-
if (typeof localSettings === 'string') {
|
|
83
|
-
localSettings = JSON.parse(localSettings);
|
|
84
|
-
}
|
|
85
|
-
// Return the locale settings
|
|
86
|
-
return localSettings;
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Sets the locale settings in the organization info.
|
|
90
|
-
*
|
|
91
|
-
* @param value - The locale settings to set.
|
|
92
|
-
*/
|
|
93
|
-
set orgLocaleSettings(value) {
|
|
94
|
-
// Retrieve the existing organization info or initialize a new object
|
|
95
|
-
const orgInfo = this.getOrgInfo() || {};
|
|
96
|
-
// Update the locale settings value
|
|
97
|
-
orgInfo.LocaleSettings = value;
|
|
98
|
-
// Save the updated organization info back to storage
|
|
99
|
-
this.setOrgInfo(orgInfo);
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Retrieves the app ID from the app info.
|
|
103
|
-
*
|
|
104
|
-
* @returns The app ID if it exists, otherwise `null`.
|
|
105
|
-
*/
|
|
106
|
-
get appId() {
|
|
107
|
-
return this.getAppInfo()?.Id || null;
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Sets the app ID in the app info.
|
|
111
|
-
*
|
|
112
|
-
* @param value - The app ID to set.
|
|
113
|
-
*/
|
|
114
|
-
set appId(value) {
|
|
115
|
-
// Retrieve the existing app info or initialize a new object
|
|
116
|
-
const appInfo = this.getAppInfo() || {};
|
|
117
|
-
// Update the app ID value
|
|
118
|
-
appInfo.Id = value;
|
|
119
|
-
// Save the updated app info back to storage
|
|
120
|
-
this.setAppInfo(appInfo);
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Retrieves the app name from the app info.
|
|
124
|
-
*
|
|
125
|
-
* @returns The app name if it exists, otherwise `null`.
|
|
126
|
-
*/
|
|
127
|
-
get appName() {
|
|
128
|
-
// Retrieve and return the app name from the app info, or return null if it doesn't exist
|
|
129
|
-
return this.getAppInfo()?.AppName || null;
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Sets the app name in the app info.
|
|
133
|
-
*
|
|
134
|
-
* @param value - The app name to set.
|
|
135
|
-
*/
|
|
136
|
-
set appName(value) {
|
|
137
|
-
// Retrieve the existing app info or initialize a new object
|
|
138
|
-
const appInfo = this.getAppInfo() || {};
|
|
139
|
-
// Update the app name value
|
|
140
|
-
appInfo.AppName = value;
|
|
141
|
-
// Save the updated app info back to storage
|
|
142
|
-
this.setAppInfo(appInfo);
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Retrieves the environment ID from the environment info.
|
|
146
|
-
*
|
|
147
|
-
* @returns The environment ID if it exists, otherwise `null`.
|
|
148
|
-
*/
|
|
149
|
-
get environmentId() {
|
|
150
|
-
// Retrieve and return the environment ID from the environment info, or return null if it doesn't exist
|
|
151
|
-
return this.getEnvironmentInfo()?.Id || null;
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Sets the environment ID in the environment info.
|
|
155
|
-
*
|
|
156
|
-
* @param value - The environment ID to set.
|
|
157
|
-
*/
|
|
158
|
-
set environmentId(value) {
|
|
159
|
-
// Retrieve the existing environment info or initialize a new object
|
|
160
|
-
const environmentInfo = this.getEnvironmentInfo() || {};
|
|
161
|
-
// Update the environment ID value
|
|
162
|
-
environmentInfo.Id = value;
|
|
163
|
-
// Save the updated environment info back to storage
|
|
164
|
-
this.setEnvironmentInfo(environmentInfo);
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* Retrieves the environment name from the environment info.
|
|
168
|
-
*
|
|
169
|
-
* @returns The environment name if it exists, otherwise `null`.
|
|
170
|
-
*/
|
|
171
|
-
get environmentName() {
|
|
172
|
-
// Retrieve and return the environment name from the environment info, or return null if it doesn't exist
|
|
173
|
-
return this.getEnvironmentInfo()?.Name || null;
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* Sets the environment name in the environment info.
|
|
177
|
-
*
|
|
178
|
-
* @param value - The environment name to set.
|
|
179
|
-
*/
|
|
180
|
-
set environmentName(value) {
|
|
181
|
-
// Retrieve the existing environment info or initialize a new object
|
|
182
|
-
const environmentInfo = this.getEnvironmentInfo() || {};
|
|
183
|
-
// Update the environment name value
|
|
184
|
-
environmentInfo.Name = value;
|
|
185
|
-
// Save the updated environment info back to storage
|
|
186
|
-
this.setEnvironmentInfo(environmentInfo);
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Retrieves the token from the token info.
|
|
190
|
-
*
|
|
191
|
-
* @returns The token if it exists, otherwise `null`.
|
|
192
|
-
*/
|
|
193
|
-
get token() {
|
|
194
|
-
// Retrieve and return the token from the token info, or return null if it doesn't exist
|
|
195
|
-
return this.getTokenInfo()?.token || null;
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Sets the token in the token info.
|
|
199
|
-
*
|
|
200
|
-
* @param value - The token to set.
|
|
201
|
-
*/
|
|
202
|
-
set token(value) {
|
|
203
|
-
// Retrieve the existing token info or initialize a new object
|
|
204
|
-
const tokenInfo = this.getTokenInfo() || {};
|
|
205
|
-
// Update the token value
|
|
206
|
-
tokenInfo.token = value;
|
|
207
|
-
// Save the updated token info back to storage
|
|
208
|
-
this.setTokenInfo(tokenInfo);
|
|
209
|
-
}
|
|
210
|
-
/**
|
|
211
|
-
* Retrieves the refresh token from the token info.
|
|
212
|
-
*
|
|
213
|
-
* @returns The refresh token if it exists, otherwise `null`.
|
|
214
|
-
*/
|
|
215
|
-
get refreshToken() {
|
|
216
|
-
// Retrieve and return the refresh token from the token info, or return null if it doesn't exist
|
|
217
|
-
return this.getTokenInfo()?.refreshToken || null;
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* Sets the refresh token in the token info.
|
|
221
|
-
*
|
|
222
|
-
* @param value - The refresh token to set.
|
|
223
|
-
*/
|
|
224
|
-
set refreshToken(value) {
|
|
225
|
-
// Retrieve the existing token info or initialize a new object
|
|
226
|
-
const tokenInfo = this.getTokenInfo() || {};
|
|
227
|
-
// Update the refresh token value
|
|
228
|
-
tokenInfo.refreshToken = value;
|
|
229
|
-
// Save the updated token info back to storage
|
|
230
|
-
this.setTokenInfo(tokenInfo);
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Retrieves the refresh token expiry time from the token info.
|
|
234
|
-
*
|
|
235
|
-
* @returns The refresh token expiry time if it exists, otherwise `null`.
|
|
236
|
-
*/
|
|
237
|
-
get refreshTokenExpiry() {
|
|
238
|
-
// Retrieve and return the refresh token expiry time from the token info,
|
|
239
|
-
// or return null if it doesn't exist
|
|
240
|
-
return this.getTokenInfo()?.refreshTokenExpiry || null;
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* Sets the refresh token expiry time in the token info.
|
|
244
|
-
*
|
|
245
|
-
* @param value - The refresh token expiry time to set.
|
|
246
|
-
*/
|
|
247
|
-
set refreshTokenExpiry(value) {
|
|
248
|
-
// Retrieve the existing token info or initialize a new object
|
|
249
|
-
const tokenInfo = this.getTokenInfo() || {};
|
|
250
|
-
// Update the refresh token expiry time
|
|
251
|
-
tokenInfo.refreshTokenExpiry = value;
|
|
252
|
-
// Save the updated token info back to storage
|
|
253
|
-
this.setTokenInfo(tokenInfo);
|
|
254
|
-
}
|
|
255
|
-
/**
|
|
256
|
-
* Retrieves the static token from the token info.
|
|
257
|
-
*
|
|
258
|
-
* @returns The static token if it exists, otherwise `null`.
|
|
259
|
-
*/
|
|
260
|
-
get staticToken() {
|
|
261
|
-
// Retrieve and return the static token from the token info,
|
|
262
|
-
// or return null if it doesn't exist
|
|
263
|
-
return this.getTokenInfo()?.staticToken || null;
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* Sets the static token in the token info.
|
|
267
|
-
*
|
|
268
|
-
* @param value - The static token to set.
|
|
269
|
-
*/
|
|
270
|
-
set staticToken(value) {
|
|
271
|
-
// Retrieve the existing token info or initialize a new object
|
|
272
|
-
const tokenInfo = this.getTokenInfo() || {};
|
|
273
|
-
// Update the static token value
|
|
274
|
-
tokenInfo.staticToken = value;
|
|
275
|
-
// Save the updated token info back to storage
|
|
276
|
-
this.setTokenInfo(tokenInfo);
|
|
277
|
-
}
|
|
278
|
-
/**
|
|
279
|
-
* Retrieves the user ID from the user info.
|
|
280
|
-
*
|
|
281
|
-
* @returns The user ID if it exists, otherwise `null`.
|
|
282
|
-
*/
|
|
283
|
-
get userId() {
|
|
284
|
-
// Retrieve and return the user ID from the user info, or return null if it doesn't exist
|
|
285
|
-
return this.getUserInfo()?.user?.Id || null;
|
|
286
|
-
}
|
|
287
|
-
/**
|
|
288
|
-
* Retrieves the user's roles from the user information.
|
|
289
|
-
*
|
|
290
|
-
* @returns An array of user roles if they exist, otherwise `null`.
|
|
291
|
-
*/
|
|
292
|
-
get userRoles() {
|
|
293
|
-
// Retrieve and return the user roles from the user info, or return null if they don't exist
|
|
294
|
-
return this.getUserInfo()?.user?.Roles || null;
|
|
295
|
-
}
|
|
296
|
-
/**
|
|
297
|
-
* Retrieves the user's teams from the user information.
|
|
298
|
-
*
|
|
299
|
-
* @returns An array of user teams if they exist, otherwise `null`.
|
|
300
|
-
*/
|
|
301
|
-
get userTeams() {
|
|
302
|
-
// Retrieve and return the user teams from the user info, or return null if they don't exist
|
|
303
|
-
return this.getUserInfo()?.user?.Teams || null;
|
|
304
|
-
}
|
|
305
|
-
/**
|
|
306
|
-
* Removes the tenant ID from the organization information.
|
|
307
|
-
*/
|
|
308
|
-
removeTenantId() {
|
|
309
|
-
this.removeFromOrgInfo('Id');
|
|
310
|
-
}
|
|
311
|
-
/**
|
|
312
|
-
* Removes the tenant name from the organization information.
|
|
313
|
-
*/
|
|
314
|
-
removeTenantName() {
|
|
315
|
-
// Remove the tenant name from the organization information
|
|
316
|
-
this.removeFromOrgInfo('OrganizationName');
|
|
317
|
-
}
|
|
318
|
-
/**
|
|
319
|
-
* Removes the subdomain from the organization information.
|
|
320
|
-
*
|
|
321
|
-
* This removes the subdomain property from the organization information
|
|
322
|
-
* stored in local storage.
|
|
323
|
-
*/
|
|
324
|
-
removeSubdomain() {
|
|
325
|
-
// Remove the subdomain from the organization information
|
|
326
|
-
this.removeFromOrgInfo('Subdomain');
|
|
327
|
-
}
|
|
328
|
-
/**
|
|
329
|
-
* Removes the app ID from the app information.
|
|
330
|
-
*
|
|
331
|
-
* This removes the app ID property from the app information stored in local storage.
|
|
332
|
-
*/
|
|
333
|
-
removeAppId() {
|
|
334
|
-
this.removeFromAppInfo('Id');
|
|
335
|
-
}
|
|
336
|
-
/**
|
|
337
|
-
* Removes the app name from the app information.
|
|
338
|
-
*
|
|
339
|
-
* This removes the app name property from the app information stored in local storage.
|
|
340
|
-
*/
|
|
341
|
-
removeAppName() {
|
|
342
|
-
this.removeFromAppInfo('AppName');
|
|
343
|
-
}
|
|
344
|
-
/**
|
|
345
|
-
* Removes the environment ID from the environment information.
|
|
346
|
-
*
|
|
347
|
-
* This removes the ID property from the environment information
|
|
348
|
-
* stored in local storage.
|
|
349
|
-
*/
|
|
350
|
-
removeEnvironmentId() {
|
|
351
|
-
// Remove the environment ID from the environment information
|
|
352
|
-
this.removeFromEnvironmentInfo('Id');
|
|
353
|
-
}
|
|
354
|
-
/**
|
|
355
|
-
* Removes the environment name from the environment information.
|
|
356
|
-
*
|
|
357
|
-
* This removes the Name property from the environment information
|
|
358
|
-
* stored in local storage.
|
|
359
|
-
*/
|
|
360
|
-
removeEnvironmentName() {
|
|
361
|
-
// Remove the environment name from the environment information
|
|
362
|
-
this.removeFromEnvironmentInfo('Name');
|
|
363
|
-
}
|
|
364
|
-
/**
|
|
365
|
-
* Removes the token from the token info.
|
|
366
|
-
*
|
|
367
|
-
* This removes the token property from the token information stored in session
|
|
368
|
-
* storage.
|
|
369
|
-
*/
|
|
370
|
-
removeToken() {
|
|
371
|
-
// Remove the token from the token info
|
|
372
|
-
this.removeFromTokenInfo('token');
|
|
373
|
-
}
|
|
374
|
-
/**
|
|
375
|
-
* Removes the refresh token from the token information.
|
|
376
|
-
*
|
|
377
|
-
* This removes the refresh token property from the token information stored in session
|
|
378
|
-
* storage.
|
|
379
|
-
*/
|
|
380
|
-
removeRefreshToken() {
|
|
381
|
-
this.removeFromTokenInfo('refreshToken');
|
|
382
|
-
}
|
|
383
|
-
/**
|
|
384
|
-
* Removes the refresh token expiry time from the token information.
|
|
385
|
-
*
|
|
386
|
-
* This removes the refresh token expiry time property from the token information stored in session
|
|
387
|
-
* storage.
|
|
388
|
-
*/
|
|
389
|
-
removeRefreshTokenExpiry() {
|
|
390
|
-
// Remove the refresh token expiry from the token info
|
|
391
|
-
this.removeFromTokenInfo('refreshTokenExpiry');
|
|
392
|
-
}
|
|
393
|
-
/**
|
|
394
|
-
* Removes the static token from the token information.
|
|
395
|
-
*
|
|
396
|
-
* This removes the static token property from the token information stored in session
|
|
397
|
-
* storage.
|
|
398
|
-
*/
|
|
399
|
-
removeStaticToken() {
|
|
400
|
-
// Remove the static token from the token info
|
|
401
|
-
this.removeFromTokenInfo('staticToken');
|
|
402
|
-
}
|
|
403
|
-
/**
|
|
404
|
-
* Removes the specified key from the organization information.
|
|
405
|
-
*
|
|
406
|
-
* This removes the specified key from the organization information stored in local storage.
|
|
407
|
-
*
|
|
408
|
-
* @param key The key to remove from the organization information.
|
|
409
|
-
*/
|
|
410
|
-
removeFromOrgInfo(key) {
|
|
411
|
-
const orgInfo = this.getOrgInfo();
|
|
412
|
-
if (orgInfo) {
|
|
413
|
-
// Remove the key from the organization information
|
|
414
|
-
delete orgInfo[key];
|
|
415
|
-
// Save the updated organization information back to local storage
|
|
416
|
-
this.setOrgInfo(orgInfo);
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
/**
|
|
420
|
-
* Removes the specified key from the app information.
|
|
421
|
-
*
|
|
422
|
-
* This removes the specified key from the app information stored in session
|
|
423
|
-
* storage.
|
|
424
|
-
*
|
|
425
|
-
* @param key The key to remove from the app information.
|
|
426
|
-
*/
|
|
427
|
-
removeFromAppInfo(key) {
|
|
428
|
-
const appInfo = this.getAppInfo();
|
|
429
|
-
if (appInfo) {
|
|
430
|
-
// Remove the key from the app information
|
|
431
|
-
delete appInfo[key];
|
|
432
|
-
// Save the updated app information back to session storage
|
|
433
|
-
this.setAppInfo(appInfo);
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
/**
|
|
437
|
-
* Removes the specified key from the environment information.
|
|
438
|
-
*
|
|
439
|
-
* This removes the specified key from the environment information stored in session
|
|
440
|
-
* storage.
|
|
441
|
-
*
|
|
442
|
-
* @param key The key to remove from the environment information.
|
|
443
|
-
*/
|
|
444
|
-
removeFromEnvironmentInfo(key) {
|
|
445
|
-
const environmentInfo = this.getEnvironmentInfo();
|
|
446
|
-
if (environmentInfo) {
|
|
447
|
-
// Remove the key from the environment information
|
|
448
|
-
delete environmentInfo[key];
|
|
449
|
-
// Save the updated environment information back to session storage
|
|
450
|
-
this.setEnvironmentInfo(environmentInfo);
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
/**
|
|
454
|
-
* Removes the specified key from the token information.
|
|
455
|
-
*
|
|
456
|
-
* This removes the specified key from the token information stored in session
|
|
457
|
-
* storage.
|
|
458
|
-
*
|
|
459
|
-
* @param key The key to remove from the token information.
|
|
460
|
-
*/
|
|
461
|
-
removeFromTokenInfo(key) {
|
|
462
|
-
const tokenInfo = this.getTokenInfo();
|
|
463
|
-
if (tokenInfo) {
|
|
464
|
-
// Remove the key from the token information
|
|
465
|
-
delete tokenInfo[key];
|
|
466
|
-
// Save the updated token information back to session storage
|
|
467
|
-
this.setTokenInfo(tokenInfo);
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
/**
|
|
471
|
-
* Retrieves the organization information from local storage.
|
|
472
|
-
*
|
|
473
|
-
* @returns The organization information object or null if it doesn't exist.
|
|
474
|
-
*/
|
|
475
|
-
getOrgInfo() {
|
|
476
|
-
return this.getFromStorage(StorageType.Local, StorageConstants.orgInfo);
|
|
477
|
-
}
|
|
478
|
-
/**
|
|
479
|
-
* Saves the organization information to local storage.
|
|
480
|
-
*
|
|
481
|
-
* @param orgInfo - The organization information to store.
|
|
482
|
-
*/
|
|
483
|
-
setOrgInfo(orgInfo) {
|
|
484
|
-
// temp once remove from dropdown, we can remove this
|
|
485
|
-
// if (orgInfo.Id) {
|
|
486
|
-
// this.setSession(StorageConstants.TenantId, orgInfo.Id);
|
|
487
|
-
// } else {
|
|
488
|
-
// this.removeSession(StorageConstants.TenantId);
|
|
489
|
-
// }
|
|
490
|
-
// Save the organization info to local storage
|
|
491
|
-
this.setToStorage(StorageType.Local, StorageConstants.orgInfo, orgInfo);
|
|
492
|
-
}
|
|
493
|
-
/**
|
|
494
|
-
* Retrieves the app information from session storage.
|
|
495
|
-
*
|
|
496
|
-
* @returns The app information object or null if it doesn't exist.
|
|
497
|
-
*/
|
|
498
|
-
getAppInfo() {
|
|
499
|
-
return this.getFromStorage(StorageType.Session, StorageConstants.appInfo);
|
|
500
|
-
}
|
|
501
|
-
/**
|
|
502
|
-
* Saves the app information to session storage.
|
|
503
|
-
*
|
|
504
|
-
* @param appInfo - The app information to store.
|
|
505
|
-
*/
|
|
506
|
-
setAppInfo(appInfo) {
|
|
507
|
-
// temp once remove from dropdown, we can remove this
|
|
508
|
-
// if (appInfo?.Id) {
|
|
509
|
-
// this.setSession(StorageConstants.AppId, appInfo.Id);
|
|
510
|
-
// } else {
|
|
511
|
-
// this.removeSession(StorageConstants.AppId);
|
|
512
|
-
// }
|
|
513
|
-
// if (appInfo?.AppName) {
|
|
514
|
-
// this.setSession(StorageConstants.applicationCode, appInfo.AppName);
|
|
515
|
-
// } else {
|
|
516
|
-
// this.removeSession(StorageConstants.applicationCode);
|
|
517
|
-
// }
|
|
518
|
-
// Save the app info to session storage
|
|
519
|
-
this.setToStorage(StorageType.Session, StorageConstants.appInfo, appInfo);
|
|
520
|
-
}
|
|
521
|
-
/**
|
|
522
|
-
* Retrieves the environment information from session storage.
|
|
523
|
-
*
|
|
524
|
-
* @returns The environment information object or null if it doesn't exist.
|
|
525
|
-
*/
|
|
526
|
-
getEnvironmentInfo() {
|
|
527
|
-
return this.getFromStorage(StorageType.Session, StorageConstants.environmentInfo);
|
|
528
|
-
}
|
|
529
|
-
/**
|
|
530
|
-
* Saves the environment information to session storage.
|
|
531
|
-
*
|
|
532
|
-
* @param envInfo - The environment information to store.
|
|
533
|
-
*/
|
|
534
|
-
setEnvironmentInfo(envInfo) {
|
|
535
|
-
// Save the environment info to session storage
|
|
536
|
-
this.setToStorage(StorageType.Session, StorageConstants.environmentInfo, envInfo);
|
|
537
|
-
}
|
|
538
|
-
/**
|
|
539
|
-
* Retrieves the token information from session storage.
|
|
540
|
-
*
|
|
541
|
-
* @returns The token information object or null if it doesn't exist.
|
|
542
|
-
*/
|
|
543
|
-
getTokenInfo() {
|
|
544
|
-
return this.getFromStorage(StorageType.Local, StorageConstants.tokenInfo);
|
|
545
|
-
}
|
|
546
|
-
/**
|
|
547
|
-
* Saves the token information to session storage.
|
|
548
|
-
*
|
|
549
|
-
* @param tokenInfo - The token information to store.
|
|
550
|
-
*/
|
|
551
|
-
setTokenInfo(tokenInfo) {
|
|
552
|
-
// temp once remove from dropdown, we can remove this
|
|
553
|
-
// if (tokenInfo?.token) {
|
|
554
|
-
// this.setSession(StorageConstants.token, tokenInfo?.token);
|
|
555
|
-
// } else {
|
|
556
|
-
// this.removeSession(StorageConstants.token);
|
|
557
|
-
// }
|
|
558
|
-
// Save the token info to session storage
|
|
559
|
-
this.setToStorage(StorageType.Local, StorageConstants.tokenInfo, tokenInfo);
|
|
560
|
-
}
|
|
561
|
-
/**
|
|
562
|
-
* Retrieves the user information from local storage.
|
|
563
|
-
*
|
|
564
|
-
* @returns The user information object or null if it doesn't exist.
|
|
565
|
-
*/
|
|
566
|
-
getUserInfo() {
|
|
567
|
-
return this.getFromStorage(StorageType.Local, StorageConstants.userInfo);
|
|
568
|
-
}
|
|
569
|
-
/**
|
|
570
|
-
* Sets the user information in local storage.
|
|
571
|
-
*
|
|
572
|
-
* @param userInfo The user information to store.
|
|
573
|
-
*/
|
|
574
|
-
setUserInfo(userInfo) {
|
|
575
|
-
// Save the user info to local storage
|
|
576
|
-
this.setToStorage(StorageType.Local, StorageConstants.userInfo, userInfo);
|
|
577
|
-
}
|
|
578
|
-
/**
|
|
579
|
-
* Sets a key-value pair in local storage.
|
|
580
|
-
*
|
|
581
|
-
* @param key The key to store the value under.
|
|
582
|
-
* @param data The value to store.
|
|
583
|
-
*/
|
|
584
|
-
setLocal(key, data) {
|
|
585
|
-
this.setToStorage(StorageType.Local, key, data);
|
|
586
|
-
}
|
|
587
|
-
/**
|
|
588
|
-
* Retrieves a value from local storage by key.
|
|
589
|
-
*
|
|
590
|
-
* @param key The key associated with the value to retrieve.
|
|
591
|
-
* @returns The value stored in local storage, or null if it doesn't exist.
|
|
592
|
-
*/
|
|
593
|
-
getLocal(key) {
|
|
594
|
-
return this.getFromStorage(StorageType.Local, key);
|
|
595
|
-
}
|
|
596
|
-
/**
|
|
597
|
-
* Removes a key-value pair from local storage.
|
|
598
|
-
*
|
|
599
|
-
* @param key The key associated with the value to remove.
|
|
600
|
-
*/
|
|
601
|
-
removeLocal(key) {
|
|
602
|
-
// Remove the key from local storage
|
|
603
|
-
this.removeFromStorage(StorageType.Local, key);
|
|
604
|
-
}
|
|
605
|
-
/**
|
|
606
|
-
* Clears all local storage data.
|
|
607
|
-
*/
|
|
608
|
-
clearLocal() {
|
|
609
|
-
this.clearStorage(StorageType.Local);
|
|
610
|
-
}
|
|
611
|
-
/**
|
|
612
|
-
* Sets a key-value pair in session storage.
|
|
613
|
-
*
|
|
614
|
-
* @param key The key to store the value under.
|
|
615
|
-
* @param data The value to store.
|
|
616
|
-
*/
|
|
617
|
-
setSession(key, data) {
|
|
618
|
-
// Save data to session storage under the specified key
|
|
619
|
-
this.setToStorage(StorageType.Session, key, data);
|
|
620
|
-
}
|
|
621
|
-
/**
|
|
622
|
-
* Retrieves a value from session storage by key.
|
|
623
|
-
*
|
|
624
|
-
* @param key The key associated with the value to retrieve.
|
|
625
|
-
* @returns The value stored in session storage, or null if it doesn't exist.
|
|
626
|
-
*/
|
|
627
|
-
getSession(key) {
|
|
628
|
-
// Retrieve the value from session storage
|
|
629
|
-
return this.getFromStorage(StorageType.Session, key);
|
|
630
|
-
}
|
|
631
|
-
/**
|
|
632
|
-
* Removes a key-value pair from session storage.
|
|
633
|
-
*
|
|
634
|
-
* @param key The key associated with the value to remove.
|
|
635
|
-
*/
|
|
636
|
-
removeSession(key) {
|
|
637
|
-
// Remove the key from session storage
|
|
638
|
-
this.removeFromStorage(StorageType.Session, key);
|
|
639
|
-
}
|
|
640
|
-
/**
|
|
641
|
-
* Clears all session storage data.
|
|
642
|
-
*/
|
|
643
|
-
clearSession() {
|
|
644
|
-
// Remove all key-value pairs from session storage
|
|
645
|
-
this.clearStorage(StorageType.Session);
|
|
646
|
-
}
|
|
647
|
-
/**
|
|
648
|
-
* Clears all authentication-related data from local and session storage.
|
|
649
|
-
*
|
|
650
|
-
* This method is typically used after a user logs out.
|
|
651
|
-
*/
|
|
652
|
-
clearAuth() {
|
|
653
|
-
// Remove user info from local storage
|
|
654
|
-
this.removeFromStorage(StorageType.Local, StorageConstants.userInfo);
|
|
655
|
-
// Remove token info from session storage
|
|
656
|
-
this.removeFromStorage(StorageType.Local, StorageConstants.tokenInfo);
|
|
657
|
-
}
|
|
658
|
-
/**
|
|
659
|
-
* Generic getter method for retrieving data from either local or session storage.
|
|
660
|
-
*
|
|
661
|
-
* @param storage The type of storage to retrieve from.
|
|
662
|
-
* @param key The key associated with the data to retrieve.
|
|
663
|
-
* @returns The retrieved data, deserialized from JSON if it was stored as a string.
|
|
664
|
-
*/
|
|
665
|
-
getFromStorage(storage, key) {
|
|
666
|
-
// Retrieve the data from the specified storage
|
|
667
|
-
const data = storage === StorageType.Local
|
|
668
|
-
? this._localStorageService.getLocalStorage(key)
|
|
669
|
-
: this._sessionStorageService.getSessionStorage(key);
|
|
670
|
-
try {
|
|
671
|
-
// Attempt to parse the data as JSON
|
|
672
|
-
return typeof data === 'string' ? JSON.parse(data) : data;
|
|
673
|
-
}
|
|
674
|
-
catch (e) {
|
|
675
|
-
// If the data cannot be parsed, return it as is
|
|
676
|
-
return data;
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
/**
|
|
680
|
-
* Sets a key-value pair in the specified storage type.
|
|
681
|
-
*
|
|
682
|
-
* @param storage The type of storage to use (local or session).
|
|
683
|
-
* @param key The key under which the data should be stored.
|
|
684
|
-
* @param data The data to store.
|
|
685
|
-
*/
|
|
686
|
-
setToStorage(storage, key, data) {
|
|
687
|
-
// Check if the storage type is local
|
|
688
|
-
if (storage === StorageType.Local) {
|
|
689
|
-
// Set the data in local storage
|
|
690
|
-
this._localStorageService.setLocalStorage(key, data);
|
|
691
|
-
}
|
|
692
|
-
else {
|
|
693
|
-
// Otherwise, set the data in session storage
|
|
694
|
-
this._sessionStorageService.setSessionStorage(key, data);
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
/**
|
|
698
|
-
* Removes a key-value pair from the specified storage type.
|
|
699
|
-
*
|
|
700
|
-
* This method removes the given key from either local or session storage
|
|
701
|
-
* based on the specified storage type.
|
|
702
|
-
*
|
|
703
|
-
* @param storage The type of storage to remove from (local or session).
|
|
704
|
-
* @param key The key associated with the value to remove.
|
|
705
|
-
*/
|
|
706
|
-
removeFromStorage(storage, key) {
|
|
707
|
-
if (storage === StorageType.Local) {
|
|
708
|
-
// Remove the key from local storage
|
|
709
|
-
this._localStorageService.removeLocalStorage(key);
|
|
710
|
-
}
|
|
711
|
-
else {
|
|
712
|
-
// Remove the key from session storage
|
|
713
|
-
this._sessionStorageService.removeSessionStorage(key);
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
/**
|
|
717
|
-
* Clears all key-value pairs from the specified storage type.
|
|
718
|
-
*
|
|
719
|
-
* This method clears all key-value pairs from either local or session storage
|
|
720
|
-
* based on the specified storage type.
|
|
721
|
-
*
|
|
722
|
-
* @param storage The type of storage to clear (local or session).
|
|
723
|
-
*/
|
|
724
|
-
clearStorage(storage) {
|
|
725
|
-
if (storage === StorageType.Local) {
|
|
726
|
-
// Clear local storage
|
|
727
|
-
this._localStorageService.clearLocalStorage();
|
|
728
|
-
}
|
|
729
|
-
else {
|
|
730
|
-
// Clear session storage
|
|
731
|
-
this._sessionStorageService.clearSessionStorage();
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
/**
|
|
735
|
-
* Adds a screen context with the given key and data.
|
|
736
|
-
*
|
|
737
|
-
* The screen context is a collection of key-value pairs that are stored in session storage.
|
|
738
|
-
* The key is used to identify the screen context and the data is the value associated with the key.
|
|
739
|
-
*
|
|
740
|
-
* @param key The key for the screen context.
|
|
741
|
-
* @param data The data to store in the screen context.
|
|
742
|
-
*/
|
|
743
|
-
addScreenContext(key, data) {
|
|
744
|
-
try {
|
|
745
|
-
if (!key || data == null)
|
|
746
|
-
return;
|
|
747
|
-
const screenContext = this.getSession(StorageConstants.screenContext) || {};
|
|
748
|
-
if (!screenContext[key]) {
|
|
749
|
-
// Initialize the key with an empty array if it doesn't exist
|
|
750
|
-
screenContext[key] = [];
|
|
751
|
-
}
|
|
752
|
-
else if (screenContext[key].length >= 5) {
|
|
753
|
-
// Remove the oldest data if the array exceeds 5 elements
|
|
754
|
-
screenContext[key].shift();
|
|
755
|
-
}
|
|
756
|
-
// Add the data to the existing array
|
|
757
|
-
screenContext[key].push(data);
|
|
758
|
-
// Update the screen context with the new data
|
|
759
|
-
this.setSession(StorageConstants.screenContext, screenContext);
|
|
760
|
-
}
|
|
761
|
-
catch (error) {
|
|
762
|
-
console.error('Error adding screen context:', error);
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
/**
|
|
766
|
-
* Retrieves the latest screen context data associated with the given key.
|
|
767
|
-
*
|
|
768
|
-
* The screen context is a collection of key-value pairs that are stored in session storage.
|
|
769
|
-
* The key is used to identify the screen context and the data is the value associated with the key.
|
|
770
|
-
*
|
|
771
|
-
* @param key The key for the screen context.
|
|
772
|
-
* @returns The latest screen context data associated with the key, or null if the key is not found.
|
|
773
|
-
*/
|
|
774
|
-
getScreenContext(key) {
|
|
775
|
-
try {
|
|
776
|
-
if (!key)
|
|
777
|
-
return null;
|
|
778
|
-
const screenContext = this.getSession(StorageConstants.screenContext);
|
|
779
|
-
if (!screenContext || !screenContext[key] || screenContext[key].length === 0) {
|
|
780
|
-
return null;
|
|
781
|
-
}
|
|
782
|
-
// Return the latest screen context data (LIFO)
|
|
783
|
-
return screenContext[key][screenContext[key].length - 1];
|
|
784
|
-
}
|
|
785
|
-
catch (error) {
|
|
786
|
-
console.error('Error getting screen context:', error);
|
|
787
|
-
return null;
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
/**
|
|
791
|
-
* Removes the latest screen context data associated with the given key from session storage.
|
|
792
|
-
*
|
|
793
|
-
* The screen context is a collection of key-value pairs that are stored in session storage.
|
|
794
|
-
* The key is used to identify the screen context and the data is the value associated with the key.
|
|
795
|
-
*
|
|
796
|
-
* @param key The key for the screen context.
|
|
797
|
-
* @returns The removed screen context data, or null if the key is not found or the data is not present.
|
|
798
|
-
*/
|
|
799
|
-
cleanScreenContext(key) {
|
|
800
|
-
try {
|
|
801
|
-
if (!key)
|
|
802
|
-
return null;
|
|
803
|
-
const screenContext = this.getSession(StorageConstants.screenContext);
|
|
804
|
-
if (!screenContext || !screenContext[key] || screenContext[key].length === 0) {
|
|
805
|
-
return null;
|
|
806
|
-
}
|
|
807
|
-
const removedData = screenContext[key].pop(); // Remove latest (LIFO)
|
|
808
|
-
// Auto-cleanup: Remove key if array becomes empty
|
|
809
|
-
if (screenContext[key].length === 0) {
|
|
810
|
-
delete screenContext[key];
|
|
811
|
-
}
|
|
812
|
-
this.setSession(StorageConstants.screenContext, screenContext);
|
|
813
|
-
return removedData;
|
|
814
|
-
}
|
|
815
|
-
catch (error) {
|
|
816
|
-
console.error('Error cleaning screen context:', error);
|
|
817
|
-
return null;
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: StoreService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
821
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: StoreService, providedIn: 'root' });
|
|
822
|
-
}
|
|
823
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: StoreService, decorators: [{
|
|
824
|
-
type: Injectable,
|
|
825
|
-
args: [{
|
|
826
|
-
providedIn: 'root'
|
|
827
|
-
}]
|
|
828
|
-
}] });
|
|
829
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmUuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RhYi1zZGsvc3JjL2xpYi9zdG9yZS9zdG9yZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxxQkFBcUIsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQzlHLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQzs7QUFLakQsTUFBTSxPQUFPLFlBQVk7SUFDSixvQkFBb0IsR0FBd0IsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFDeEUsc0JBQXNCLEdBQTBCLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO0lBRS9GOztPQUVHO0lBQ0gsSUFBSSxRQUFRO1FBQ1IsT0FBTyxJQUFJLENBQUMsVUFBVSxFQUFFLEVBQUUsRUFBRSxJQUFJLElBQUksQ0FBQztJQUN6QyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILElBQUksUUFBUSxDQUFDLEtBQW9CO1FBQzdCLHFFQUFxRTtRQUNyRSxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFDO1FBRXhDLDZCQUE2QjtRQUM3QixPQUFPLENBQUMsRUFBRSxHQUFHLEtBQUssQ0FBQztRQUVuQixxREFBcUQ7UUFDckQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM3QixDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUFJLFVBQVU7UUFDViw4Q0FBOEM7UUFDOUMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBRWxDLDZEQUE2RDtRQUM3RCxPQUFPLE9BQU8sRUFBRSxnQkFBZ0IsSUFBSSxJQUFJLENBQUM7SUFDN0MsQ0FBQztJQUVE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V0FBVyxDQUFDO1FBQ3ZCLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2IsT0FBTyxDQUFDLEtBQUssQ0FBQyxnQ0FBZ0MsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUN2RCxPQUFPLElBQUksQ0FBQztRQUNoQixDQUFDO0lBQ0wsQ0FBQzt3R0FsNUJRLFlBQVk7NEdBQVosWUFBWSxjQUZULE1BQU07OzRGQUVULFlBQVk7a0JBSHhCLFVBQVU7bUJBQUM7b0JBQ1IsVUFBVSxFQUFFLE1BQU07aUJBQ3JCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaW5qZWN0LCBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBMb2NhbFN0b3JhZ2VTZXJ2aWNlLCBTZXNzaW9uU3RvcmFnZVNlcnZpY2UsIFN0b3JhZ2VDb25zdGFudHMgfSBmcm9tICdAdGVjaGV4dGVuc29yL3RhYi1jb3JlLXV0aWxpdHknO1xuaW1wb3J0IHsgU3RvcmFnZVR5cGUgfSBmcm9tICcuLi9lbnVtL3N0b3JlLmVudW0nO1xuXG5ASW5qZWN0YWJsZSh7XG4gICAgcHJvdmlkZWRJbjogJ3Jvb3QnXG59KVxuZXhwb3J0IGNsYXNzIFN0b3JlU2VydmljZSB7XG4gICAgcHJpdmF0ZSByZWFkb25seSBfbG9jYWxTdG9yYWdlU2VydmljZTogTG9jYWxTdG9yYWdlU2VydmljZSA9IGluamVjdChMb2NhbFN0b3JhZ2VTZXJ2aWNlKTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9zZXNzaW9uU3RvcmFnZVNlcnZpY2U6IFNlc3Npb25TdG9yYWdlU2VydmljZSA9IGluamVjdChTZXNzaW9uU3RvcmFnZVNlcnZpY2UpO1xuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIHRoZSB0ZW5hbnQgSUQgZnJvbSB0aGUgbG9jYWwgc3RvcmFnZS5cbiAgICAgKi9cbiAgICBnZXQgdGVuYW50SWQoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldE9yZ0luZm8oKT8uSWQgfHwgbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSB0ZW5hbnQgSUQgaW4gdGhlIG9yZ2FuaXphdGlvbiBpbmZvLlxuICAgICAqIFxuICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB0ZW5hbnQgSUQgdG8gc2V0LlxuICAgICAqL1xuICAgIHNldCB0ZW5hbnRJZCh2YWx1ZTogc3RyaW5nIHwgbnVsbCkge1xuICAgICAgICAvLyBSZXRyaWV2ZSB0aGUgZXhpc3Rpbmcgb3JnYW5pemF0aW9uIGluZm8gb3IgaW5pdGlhbGl6ZSBhIG5ldyBvYmplY3RcbiAgICAgICAgY29uc3Qgb3JnSW5mbyA9IHRoaXMuZ2V0T3JnSW5mbygpIHx8IHt9O1xuXG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgdGVuYW50IElEIHZhbHVlXG4gICAgICAgIG9yZ0luZm8uSWQgPSB2YWx1ZTtcblxuICAgICAgICAvLyBTYXZlIHRoZSB1cGRhdGVkIG9yZ2FuaXphdGlvbiBpbmZvIGJhY2sgdG8gc3RvcmFnZVxuICAgICAgICB0aGlzLnNldE9yZ0luZm8ob3JnSW5mbyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIHRoZSB0ZW5hbnQgbmFtZSBmcm9tIHRoZSBvcmdhbml6YXRpb24gaW5mby5cbiAgICAgKi9cbiAgICBnZXQgdGVuYW50TmFtZSgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICAgICAgLy8gUmV0cmlldmUgdGhlIG9yZ2FuaXphdGlvbiBpbmZvIGZyb20gc3RvcmFnZVxuICAgICAgICBjb25zdCBvcmdJbmZvID0gdGhpcy5nZXRPcmdJbmZvKCk7XG5cbiAgICAgICAgLy8gUmV0dXJuIHRoZSB0ZW5hbnQgbmFtZSBpZiBpdCBleGlzdHMsIG90aGVyd2lzZSByZXR1cm4gbnVsbFxuICAgICAgICByZXR1cm4gb3JnSW5mbz8uT3JnYW5pemF0aW9uTmFtZSB8fCBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHRlbmFudCBuYW1lIGluIHRoZSBvcmdhbml6YXRpb24gaW5mby5cbiAgICAgKiBcbiAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgdGVuYW50IG5hbWUgdG8gc2V0LlxuICAgICAqL1xuICAgIHNldCB0ZW5hbnROYW1lKHZhbHVlOiBzdHJpbmcgfCBudWxsKSB7XG4gICAgICAgIC8vIFJldHJpZXZlIHRoZSBleGlzdGluZyBvcmdhbml6YXRpb24gaW5mbyBvciBpbml0aWFsaXplIGEgbmV3IG9iamVjdFxuICAgICAgICBjb25zdCBvcmdJbmZvID0gdGhpcy5nZXRPcmdJbmZvKCkgfHwge307XG5cbiAgICAgICAgLy8gVXBkYXRlIHRoZSBvcmdhbml6YXRpb24gbmFtZSB2YWx1ZVxuICAgICAgICBvcmdJbmZvLk9yZ2FuaXphdGlvbk5hbWUgPSB2YWx1ZTtcblxuICAgICAgICAvLyBTYXZlIHRoZSB1cGRhdGVkIG9yZ2FuaXphdGlvbiBpbmZvIGJhY2sgdG8gc3RvcmFnZVxuICAgICAgICB0aGlzLnNldE9yZ0luZm8ob3JnSW5mbyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIHRoZSBzdWJkb21haW4gZnJvbSB0aGUgb3JnYW5pemF0aW9uIGluZm8uXG4gICAgICogXG4gICAgICogQHJldHVybnMgVGhlIHN1YmRvbWFpbiBpZiBpdCBleGlzdHMsIG90aGVyd2lzZSBgbnVsbGAuXG4gICAgICovXG4gICAgZ2V0IHN1YmRvbWFpbigpOiBzdHJpbmcgfCBudWxsIHtcbiAgICAgICAgLy8gUmV0cmlldmUgdGhlIG9yZ2FuaXphdGlvbiBpbmZvIGZyb20gc3RvcmFnZVxuICAgICAgICBjb25zdCBvcmdJbmZvID0gdGhpcy5nZXRPcmdJbmZvKCk7XG5cbiAgICAgICAgLy8gUmV0dXJuIHRoZSBzdWJkb21haW4gaWYgaXQgZXhpc3RzLCBvdGhlcndpc2UgcmV0dXJuIG51bGxcbiAgICAgICAgcmV0dXJuIG9yZ0luZm8/LlN1YmRvbWFpbiB8fCBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHN1YmRvbWFpbiBpbiB0aGUgb3JnYW5pemF0aW9uIGluZm8uXG4gICAgICogXG4gICAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHN1YmRvbWFpbiB0byBzZXQuXG4gICAgICovXG4gICAgc2V0IHN1YmRvbWFpbih2YWx1ZTogc3RyaW5nIHwgbnVsbCkge1xuICAgICAgICAvLyBSZXRyaWV2ZSB0aGUgZXhpc3Rpbmcgb3JnYW5pemF0aW9uIGluZm8gb3IgaW5pdGlhbGl6ZSBhIG5ldyBvYmplY3RcbiAgICAgICAgY29uc3Qgb3JnSW5mbyA9IHRoaXMuZ2V0T3JnSW5mbygpIHx8IHt9O1xuXG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgc3ViZG9tYWluIHZhbHVlXG4gICAgICAgIG9yZ0luZm8uU3ViZG9tYWluID0gdmFsdWU7XG5cbiAgICAgICAgLy8gU2F2ZSB0aGUgdXBkYXRlZCBvcmdhbml6YXRpb24gaW5mbyBiYWNrIHRvIHN0b3JhZ2VcbiAgICAgICAgdGhpcy5zZXRPcmdJbmZvKG9yZ0luZm8pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyB0aGUgbG9jYWxlIHNldHRpbmdzIGZyb20gdGhlIG9yZ2FuaXphdGlvbiBpbmZvLlxuICAgICAqIFxuICAgICAqIEByZXR1cm5zIFRoZSBsb2NhbGUgc2V0dGluZ3MgaWYgdGhleSBleGlzdCwgb3RoZXJ3aXNlIGBudWxsYC5cbiAgICAgKi9cbiAgICBnZXQgb3JnTG9jYWxlU2V0dGluZ3MoKTogYW55IHtcbiAgICAgICAgLy8gUmV0cmlldmUgdGhlIGxvY2FsZSBzZXR0aW5ncyBmcm9tIHRoZSBvcmdhbml6YXRpb24gaW5mb1xuICAgICAgICBsZXQgbG9jYWxTZXR0aW5ncyA9IHRoaXMuZ2V0T3JnSW5mbygpPy5Mb2NhbGVTZXR0aW5ncztcblxuICAgICAgICAvLyBJZiB0aGUgbG9jYWxlIHNldHRpbmdzIGFyZSBhIHN0cmluZywgcGFyc2UgdGhlbSBhcyBKU09OXG4gICAgICAgIGlmICh0eXBlb2YgbG9jYWxTZXR0aW5ncyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGxvY2FsU2V0dGluZ3MgPSBKU09OLnBhcnNlKGxvY2FsU2V0dGluZ3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmV0dXJuIHRoZSBsb2NhbGUgc2V0dGluZ3NcbiAgICAgICAgcmV0dXJuIGxvY2FsU2V0dGluZ3M7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgbG9jYWxlIHNldHRpbmdzIGluIHRoZSBvcmdhbml6YXRpb24gaW5mby5cbiAgICAgKiBcbiAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgbG9jYWxlIHNldHRpbmdzIHRvIHNldC5cbiAgICAgKi9cbiAgICBzZXQgb3JnTG9jYWxlU2V0dGluZ3ModmFsdWU6IGFueSkge1xuICAgICAgICAvLyBSZXRyaWV2ZSB0aGUgZXhpc3Rpbmcgb3JnYW5pemF0aW9uIGluZm8gb3IgaW5pdGlhbGl6ZSBhIG5ldyBvYmplY3RcbiAgICAgICAgY29uc3Qgb3JnSW5mbyA9IHRoaXMuZ2V0T3JnSW5mbygpIHx8IHt9O1xuXG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgbG9jYWxlIHNldHRpbmdzIHZhbHVlXG4gICAgICAgIG9yZ0luZm8uTG9jYWxlU2V0dGluZ3MgPSB2YWx1ZTtcblxuICAgICAgICAvLyBTYXZlIHRoZSB1cGRhdGVkIG9yZ2FuaXphdGlvbiBpbmZvIGJhY2sgdG8gc3RvcmFnZVxuICAgICAgICB0aGlzLnNldE9yZ0luZm8ob3JnSW5mbyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIHRoZSBhcHAgSUQgZnJvbSB0aGUgYXBwIGluZm8uXG4gICAgICogXG4gICAgICogQHJldHVybnMgVGhlIGFwcCBJRCBpZiBpdCBleGlzdHMsIG90aGVyd2lzZSBgbnVsbGAuXG4gICAgICovXG4gICAgZ2V0IGFwcElkKCk6IHN0cmluZyB8IG51bGwge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRBcHBJbmZvKCk/LklkIHx8IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgYXBwIElEIGluIHRoZSBhcHAgaW5mby5cbiAgICAgKiBcbiAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgYXBwIElEIHRvIHNldC5cbiAgICAgKi9cbiAgICBzZXQgYXBwSWQodmFsdWU6IHN0cmluZyB8IG51bGwpIHtcbiAgICAgICAgLy8gUmV0cmlldmUgdGhlIGV4aXN0aW5nIGFwcCBpbmZvIG9yIGluaXRpYWxpemUgYSBuZXcgb2JqZWN0XG4gICAgICAgIGNvbnN0IGFwcEluZm8gPSB0aGlzLmdldEFwcEluZm8oKSB8fCB7fTtcblxuICAgICAgICAvLyBVcGRhdGUgdGhlIGFwcCBJRCB2YWx1ZVxuICAgICAgICBhcHBJbmZvLklkID0gdmFsdWU7XG5cbiAgICAgICAgLy8gU2F2ZSB0aGUgdXBkYXRlZCBhcHAgaW5mbyBiYWNrIHRvIHN0b3JhZ2VcbiAgICAgICAgdGhpcy5zZXRBcHBJbmZvKGFwcEluZm8pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyB0aGUgYXBwIG5hbWUgZnJvbSB0aGUgYXBwIGluZm8uXG4gICAgICogXG4gICAgICogQHJldHVybnMgVGhlIGFwcCBuYW1lIGlmIGl0IGV4aXN0cywgb3RoZXJ3aXNlIGBudWxsYC5cbiAgICAgKi9cbiAgICBnZXQgYXBwTmFtZSgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICAgICAgLy8gUmV0cmlldmUgYW5kIHJldHVybiB0aGUgYXBwIG5hbWUgZnJvbSB0aGUgYXBwIGluZm8sIG9yIHJldHVybiBudWxsIGlmIGl0IGRvZXNuJ3QgZXhpc3RcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0QXBwSW5mbygpPy5BcHBOYW1lIHx8IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgYXBwIG5hbWUgaW4gdGhlIGFwcCBpbmZvLlxuICAgICAqIFxuICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBhcHAgbmFtZSB0byBzZXQuXG4gICAgICovXG4gICAgc2V0IGFwcE5hbWUodmFsdWU6IHN0cmluZyB8IG51bGwpIHtcbiAgICAgICAgLy8gUmV0cmlldmUgdGhlIGV4aXN0aW5nIGFwcCBpbmZvIG9yIGluaXRpYWxpemUgYSBuZXcgb2JqZWN0XG4gICAgICAgIGNvbnN0IGFwcEluZm8gPSB0aGlzLmdldEFwcEluZm8oKSB8fCB7fTtcblxuICAgICAgICAvLyBVcGRhdGUgdGhlIGFwcCBuYW1lIHZhbHVlXG4gICAgICAgIGFwcEluZm8uQXBwTmFtZSA9IHZhbHVlO1xuXG4gICAgICAgIC8vIFNhdmUgdGhlIHVwZGF0ZWQgYXBwIGluZm8gYmFjayB0byBzdG9yYWdlXG4gICAgICAgIHRoaXMuc2V0QXBwSW5mbyhhcHBJbmZvKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgdGhlIGVudmlyb25tZW50IElEIGZyb20gdGhlIGVudmlyb25tZW50IGluZm8uXG4gICAgICogXG4gICAgICogQHJldHVybnMgVGhlIGVudmlyb25tZW50IElEIGlmIGl0IGV4aXN0cywgb3RoZXJ3aXNlIGBudWxsYC5cbiAgICAgKi9cbiAgICBnZXQgZW52aXJvbm1lbnRJZCgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICAgICAgLy8gUmV0cmlldmUgYW5kIHJldHVybiB0aGUgZW52aXJvbm1lbnQgSUQgZnJvbSB0aGUgZW52aXJvbm1lbnQgaW5mbywgb3IgcmV0dXJuIG51bGwgaWYgaXQgZG9lc24ndCBleGlzdFxuICAgICAgICByZXR1cm4gdGhpcy5nZXRFbnZpcm9ubWVudEluZm8oKT8uSWQgfHwgbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBlbnZpcm9ubWVudCBJRCBpbiB0aGUgZW52aXJvbm1lbnQgaW5mby5cbiAgICAgKiBcbiAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgZW52aXJvbm1lbnQgSUQgdG8gc2V0LlxuICAgICAqL1xuICAgIHNldCBlbnZpcm9ubWVudElkKHZhbHVlOiBzdHJpbmcgfCBudWxsKSB7XG4gICAgICAgIC8vIFJldHJpZXZlIHRoZSBleGlzdGluZyBlbnZpcm9ubWVudCBpbmZvIG9yIGluaXRpYWxpemUgYSBuZXcgb2JqZWN0XG4gICAgICAgIGNvbnN0IGVudmlyb25tZW50SW5mbyA9IHRoaXMuZ2V0RW52aXJvbm1lbnRJbmZvKCkgfHwge307XG5cbiAgICAgICAgLy8gVXBkYXRlIHRoZSBlbnZpcm9ubWVudCBJRCB2YWx1ZVxuICAgICAgICBlbnZpcm9ubWVudEluZm8uSWQgPSB2YWx1ZTtcblxuICAgICAgICAvLyBTYXZlIHRoZSB1cGRhdGVkIGVudmlyb25tZW50IGluZm8gYmFjayB0byBzdG9yYWdlXG4gICAgICAgIHRoaXMuc2V0RW52aXJvbm1lbnRJbmZvKGVudmlyb25tZW50SW5mbyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIHRoZSBlbnZpcm9ubWVudCBuYW1lIGZyb20gdGhlIGVudmlyb25tZW50IGluZm8uXG4gICAgICogXG4gICAgICogQHJldHVybnMgVGhlIGVudmlyb25tZW50IG5hbWUgaWYgaXQgZXhpc3RzLCBvdGhlcndpc2UgYG51bGxgLlxuICAgICAqL1xuICAgIGdldCBlbnZpcm9ubWVudE5hbWUoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgICAgIC8vIFJldHJpZXZlIGFuZCByZXR1cm4gdGhlIGVudmlyb25tZW50IG5hbWUgZnJvbSB0aGUgZW52aXJvbm1lbnQgaW5mbywgb3IgcmV0dXJuIG51bGwgaWYgaXQgZG9lc24ndCBleGlzdFxuICAgICAgICByZXR1cm4gdGhpcy5nZXRFbnZpcm9ubWVudEluZm8oKT8uTmFtZSB8fCBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGVudmlyb25tZW50IG5hbWUgaW4gdGhlIGVudmlyb25tZW50IGluZm8uXG4gICAgICogXG4gICAgICogQHBhcmFtIHZhbHVlIC0gVGhlIGVudmlyb25tZW50IG5hbWUgdG8gc2V0LlxuICAgICAqL1xuICAgIHNldCBlbnZpcm9ubWVudE5hbWUodmFsdWU6IHN0cmluZyB8IG51bGwpIHtcbiAgICAgICAgLy8gUmV0cmlldmUgdGhlIGV4aXN0aW5nIGVudmlyb25tZW50IGluZm8gb3IgaW5pdGlhbGl6ZSBhIG5ldyBvYmplY3RcbiAgICAgICAgY29uc3QgZW52aXJvbm1lbnRJbmZvID0gdGhpcy5nZXRFbnZpcm9ubWVudEluZm8oKSB8fCB7fTtcblxuICAgICAgICAvLyBVcGRhdGUgdGhlIGVudmlyb25tZW50IG5hbWUgdmFsdWVcbiAgICAgICAgZW52aXJvbm1lbnRJbmZvLk5hbWUgPSB2YWx1ZTtcblxuICAgICAgICAvLyBTYXZlIHRoZSB1cGRhdGVkIGVudmlyb25tZW50IGluZm8gYmFjayB0byBzdG9yYWdlXG4gICAgICAgIHRoaXMuc2V0RW52aXJvbm1lbnRJbmZvKGVudmlyb25tZW50SW5mbyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIHRoZSB0b2tlbiBmcm9tIHRoZSB0b2tlbiBpbmZvLlxuICAgICAqIFxuICAgICAqIEByZXR1cm5zIFRoZSB0b2tlbiBpZiBpdCBleGlzdHMsIG90aGVyd2lzZSBgbnVsbGAuXG4gICAgICovXG4gICAgZ2V0IHRva2VuKCk6IHN0cmluZyB8IG51bGwge1xuICAgICAgICAvLyBSZXRyaWV2ZSBhbmQgcmV0dXJuIHRoZSB0b2tlbiBmcm9tIHRoZSB0b2tlbiBpbmZvLCBvciByZXR1cm4gbnVsbCBpZiBpdCBkb2Vzbid0IGV4aXN0XG4gICAgICAgIHJldHVybiB0aGlzLmdldFRva2VuSW5mbygpPy50b2tlbiB8fCBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHRva2VuIGluIHRoZSB0b2tlbiBpbmZvLlxuICAgICAqIFxuICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB0b2tlbiB0byBzZXQuXG4gICAgICovXG4gICAgc2V0IHRva2VuKHZhbHVlOiBzdHJpbmcgfCBudWxsKSB7XG4gICAgICAgIC8vIFJldHJpZXZlIHRoZSBleGlzdGluZyB0b2tlbiBpbmZvIG9yIGluaXRpYWxpemUgYSBuZXcgb2JqZWN0XG4gICAgICAgIGNvbnN0IHRva2VuSW5mbyA9IHRoaXMuZ2V0VG9rZW5JbmZvKCkgfHwge307XG5cbiAgICAgICAgLy8gVXBkYXRlIHRoZSB0b2tlbiB2YWx1ZVxuICAgICAgICB0b2tlbkluZm8udG9rZW4gPSB2YWx1ZTtcblxuICAgICAgICAvLyBTYXZlIHRoZSB1cGRhdGVkIHRva2VuIGluZm8gYmFjayB0byBzdG9yYWdlXG4gICAgICAgIHRoaXMuc2V0VG9rZW5JbmZvKHRva2VuSW5mbyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIHRoZSByZWZyZXNoIHRva2VuIGZyb20gdGhlIHRva2VuIGluZm8uXG4gICAgICogXG4gICAgICogQHJldHVybnMgVGhlIHJlZnJlc2ggdG9rZW4gaWYgaXQgZXhpc3RzLCBvdGhlcndpc2UgYG51bGxgLlxuICAgICAqL1xuICAgIGdldCByZWZyZXNoVG9rZW4oKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgICAgIC8vIFJldHJpZXZlIGFuZCByZXR1cm4gdGhlIHJlZnJlc2ggdG9rZW4gZnJvbSB0aGUgdG9rZW4gaW5mbywgb3IgcmV0dXJuIG51bGwgaWYgaXQgZG9lc24ndCBleGlzdFxuICAgICAgICByZXR1cm4gdGhpcy5nZXRUb2tlbkluZm8oKT8ucmVmcmVzaFRva2VuIHx8IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgcmVmcmVzaCB0b2tlbiBpbiB0aGUgdG9rZW4gaW5mby5cbiAgICAgKiBcbiAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgcmVmcmVzaCB0b2tlbiB0byBzZXQuXG4gICAgICovXG4gICAgc2V0IHJlZnJlc2hUb2tlbih2YWx1ZTogc3RyaW5nIHwgbnVsbCkge1xuICAgICAgICAvLyBSZXRyaWV2ZSB0aGUgZXhpc3RpbmcgdG9rZW4gaW5mbyBvciBpbml0aWFsaXplIGEgbmV3IG9iamVjdFxuICAgICAgICBjb25zdCB0b2tlbkluZm8gPSB0aGlzLmdldFRva2VuSW5mbygpIHx8IHt9O1xuXG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgcmVmcmVzaCB0b2tlbiB2YWx1ZVxuICAgICAgICB0b2tlbkluZm8ucmVmcmVzaFRva2VuID0gdmFsdWU7XG5cbiAgICAgICAgLy8gU2F2ZSB0aGUgdXBkYXRlZCB0b2tlbiBpbmZvIGJhY2sgdG8gc3RvcmFnZVxuICAgICAgICB0aGlzLnNldFRva2VuSW5mbyh0b2tlbkluZm8pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyB0aGUgcmVmcmVzaCB0b2tlbiBleHBpcnkgdGltZSBmcm9tIHRoZSB0b2tlbiBpbmZvLlxuICAgICAqIFxuICAgICAqIEByZXR1cm5zIFRoZSByZWZyZXNoIHRva2VuIGV4cGlyeSB0aW1lIGlmIGl0IGV4aXN0cywgb3RoZXJ3aXNlIGBudWxsYC5cbiAgICAgKi9cbiAgICBnZXQgcmVmcmVzaFRva2VuRXhwaXJ5KCk6IHN0cmluZyB8IG51bGwge1xuICAgICAgICAvLyBSZXRyaWV2ZSBhbmQgcmV0dXJuIHRoZSByZWZyZXNoIHRva2VuIGV4cGlyeSB0aW1lIGZyb20gdGhlIHRva2VuIGluZm8sXG4gICAgICAgIC8vIG9yIHJldHVybiBudWxsIGlmIGl0IGRvZXNuJ3QgZXhpc3RcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0VG9rZW5JbmZvKCk/LnJlZnJlc2hUb2tlbkV4cGlyeSB8fCBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHJlZnJlc2ggdG9rZW4gZXhwaXJ5IHRpbWUgaW4gdGhlIHRva2VuIGluZm8uXG4gICAgICogXG4gICAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHJlZnJlc2ggdG9rZW4gZXhwaXJ5IHRpbWUgdG8gc2V0LlxuICAgICAqL1xuICAgIHNldCByZWZyZXNoVG9rZW5FeHBpcnkodmFsdWU6IHN0cmluZyB8IG51bGwpIHtcbiAgICAgICAgLy8gUmV0cmlldmUgdGhlIGV4aXN0aW5nIHRva2VuIGluZm8gb3IgaW5pdGlhbGl6ZSBhIG5ldyBvYmplY3RcbiAgICAgICAgY29uc3QgdG9rZW5JbmZvID0gdGhpcy5nZXRUb2tlbkluZm8oKSB8fCB7fTtcblxuICAgICAgICAvLyBVcGRhdGUgdGhlIHJlZnJlc2ggdG9rZW4gZXhwaXJ5IHRpbWVcbiAgICAgICAgdG9rZW5JbmZvLnJlZnJlc2hUb2tlbkV4cGlyeSA9IHZhbHVlO1xuXG4gICAgICAgIC8vIFNhdmUgdGhlIHVwZGF0ZWQgdG9rZW4gaW5mbyBiYWNrIHRvIHN0b3JhZ2VcbiAgICAgICAgdGhpcy5zZXRUb2tlbkluZm8odG9rZW5JbmZvKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgdGhlIHN0YXRpYyB0b2tlbiBmcm9tIHRoZSB0b2tlbiBpbmZvLlxuICAgICAqIFxuICAgICAqIEByZXR1cm5zIFRoZSBzdGF0aWMgdG9rZW4gaWYgaXQgZXhpc3RzLCBvdGhlcndpc2UgYG51bGxgLlxuICAgICAqL1xuICAgIGdldCBzdGF0aWNUb2tlbigpOiBzdHJpbmcgfCBudWxsIHtcbiAgICAgICAgLy8gUmV0cmlldmUgYW5kIHJldHVybiB0aGUgc3RhdGljIHRva2VuIGZyb20gdGhlIHRva2VuIGluZm8sXG4gICAgICAgIC8vIG9yIHJldHVybiBudWxsIGlmIGl0IGRvZXNuJ3QgZXhpc3RcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0VG9rZW5JbmZvKCk/LnN0YXRpY1Rva2VuIHx8IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgc3RhdGljIHRva2VuIGluIHRoZSB0b2tlbiBpbmZvLlxuICAgICAqIFxuICAgICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBzdGF0aWMgdG9rZW4gdG8gc2V0LlxuICAgICAqL1xuICAgIHNldCBzdGF0aWNUb2tlbih2YWx1ZTogc3RyaW5nIHwgbnVsbCkge1xuICAgICAgICAvLyBSZXRyaWV2ZSB0aGUgZXhpc3RpbmcgdG9rZW4gaW5mbyBvciBpbml0aWFsaXplIGEgbmV3IG9iamVjdFxuICAgICAgICBjb25zdCB0b2tlbkluZm8gPSB0aGlzLmdldFRva2VuSW5mbygpIHx8IHt9O1xuXG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgc3RhdGljIHRva2VuIHZhbHVlXG4gICAgICAgIHRva2VuSW5mby5zdGF0aWNUb2tlbiA9IHZhbHVlO1xuXG4gICAgICAgIC8vIFNhdmUgdGhlIHVwZGF0ZWQgdG9rZW4gaW5mbyBiYWNrIHRvIHN0b3JhZ2VcbiAgICAgICAgdGhpcy5zZXRUb2tlbkluZm8odG9rZW5JbmZvKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgdGhlIHVzZXIgSUQgZnJvbSB0aGUgdXNlciBpbmZvLlxuICAgICAqIFxuICAgICAqIEByZXR1cm5zIFRoZSB1c2VyIElEIGlmIGl0IGV4aXN0cywgb3RoZXJ3aXNlIGBudWxsYC5cbiAgICAgKi9cbiAgICBnZXQgdXNlcklkKCk6IHN0cmluZyB8IG51bGwge1xuICAgICAgICAvLyBSZXRyaWV2ZSBhbmQgcmV0dXJuIHRoZSB1c2VyIElEIGZyb20gdGhlIHVzZXIgaW5mbywgb3IgcmV0dXJuIG51bGwgaWYgaXQgZG9lc24ndCBleGlzdFxuICAgICAgICByZXR1cm4gdGhpcy5nZXRVc2VySW5mbygpPy51c2VyPy5JZCB8fCBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyB0aGUgdXNlcidzIHJvbGVzIGZyb20gdGhlIHVzZXIgaW5mb3JtYXRpb24uXG4gICAgICogXG4gICAgICogQHJldHVybnMgQW4gYXJyYXkgb2YgdXNlciByb2xlcyBpZiB0aGV5IGV4aXN0LCBvdGhlcndpc2UgYG51bGxgLlxuICAgICAqL1xuICAgIGdldCB1c2VyUm9sZXMoKTogYW55W10gfCBudWxsIHtcbiAgICAgICAgLy8gUmV0cmlldmUgYW5kIHJldHVybiB0aGUgdXNlciByb2xlcyBmcm9tIHRoZSB1c2VyIGluZm8sIG9yIHJldHVybiBudWxsIGlmIHRoZXkgZG9uJ3QgZXhpc3RcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0VXNlckluZm8oKT8udXNlcj8uUm9sZXMgfHwgbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgdGhlIHVzZXIncyB0ZWFtcyBmcm9tIHRoZSB1c2VyIGluZm9ybWF0aW9uLlxuICAgICAqIFxuICAgICAqIEByZXR1cm5zIEFuIGFycmF5IG9mIHVzZXIgdGVhbXMgaWYgdGhleSBleGlzdCwgb3RoZXJ3aXNlIGBudWxsYC5cbiAgICAgKi9cbiAgICBnZXQgdXNlclRlYW1zKCk6IGFueVtdIHwgbnVsbCB7XG4gICAgICAgIC8vIFJldHJpZXZlIGFuZCByZXR1cm4gdGhlIHVzZXIgdGVhbXMgZnJvbSB0aGUgdXNlciBpbmZvLCBvciByZXR1cm4gbnVsbCBpZiB0aGV5IGRvbid0IGV4aXN0XG4gICAgICAgIHJldHVybiB0aGlzLmdldFVzZXJJbmZvKCk/LnVzZXI/LlRlYW1zIHx8IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgdGVuYW50IElEIGZyb20gdGhlIG9yZ2FuaXphdGlvbiBpbmZvcm1hdGlvbi5cbiAgICAgKi9cbiAgICByZW1vdmVUZW5hbnRJZCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5yZW1vdmVGcm9tT3JnSW5mbygnSWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIHRoZSB0ZW5hbnQgbmFtZSBmcm9tIHRoZSBvcmdhbml6YXRpb24gaW5mb3JtYXRpb24uXG4gICAgICovXG4gICAgcmVtb3ZlVGVuYW50TmFtZSgpOiB2b2lkIHtcbiAgICAgICAgLy8gUmVtb3ZlIHRoZSB0ZW5hbnQgbmFtZSBmcm9tIHRoZSBvcmdhbml6YXRpb24gaW5mb3JtYXRpb25cbiAgICAgICAgdGhpcy5yZW1vdmVGcm9tT3JnSW5mbygnT3JnYW5pemF0aW9uTmFtZScpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgdGhlIHN1YmRvbWFpbiBmcm9tIHRoZSBvcmdhbml6YXRpb24gaW5mb3JtYXRpb24uXG4gICAgICogXG4gICAgICogVGhpcyByZW1vdmVzIHRoZSBzdWJkb21haW4gcHJvcGVydHkgZnJvbSB0aGUgb3JnYW5pemF0aW9uIGluZm9ybWF0aW9uXG4gICAgICogc3RvcmVkIGluIGxvY2FsIHN0b3JhZ2UuXG4gICAgICovXG4gICAgcmVtb3ZlU3ViZG9tYWluKCk6IHZvaWQge1xuICAgICAgICAvLyBSZW1vdmUgdGhlIHN1YmRvbWFpbiBmcm9tIHRoZSBvcmdhbml6YXRpb24gaW5mb3JtYXRpb25cbiAgICAgICAgdGhpcy5yZW1vdmVGcm9tT3JnSW5mbygnU3ViZG9tYWluJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgYXBwIElEIGZyb20gdGhlIGFwcCBpbmZvcm1hdGlvbi5cbiAgICAgKiBcbiAgICAgKiBUaGlzIHJlbW92ZXMgdGhlIGFwcCBJRCBwcm9wZXJ0eSBmcm9tIHRoZSBhcHAgaW5mb3JtYXRpb24gc3RvcmVkIGluIGxvY2FsIHN0b3JhZ2UuXG4gICAgICovXG4gICAgcmVtb3ZlQXBwSWQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMucmVtb3ZlRnJvbUFwcEluZm8oJ0lkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgYXBwIG5hbWUgZnJvbSB0aGUgYXBwIGluZm9ybWF0aW9uLlxuICAgICAqIFxuICAgICAqIFRoaXMgcmVtb3ZlcyB0aGUgYXBwIG5hbWUgcHJvcGVydHkgZnJvbSB0aGUgYXBwIGluZm9ybWF0aW9uIHN0b3JlZCBpbiBsb2NhbCBzdG9yYWdlLlxuICAgICAqL1xuICAgIHJlbW92ZUFwcE5hbWUoKTogdm9pZCB7XG4gICAgICAgIHRoaXMucmVtb3ZlRnJvbUFwcEluZm8oJ0FwcE5hbWUnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIHRoZSBlbnZpcm9ubWVudCBJRCBmcm9tIHRoZSBlbnZpcm9ubWVudCBpbmZvcm1hdGlvbi5cbiAgICAgKiBcbiAgICAgKiBUaGlzIHJlbW92ZXMgdGhlIElEIHByb3BlcnR5IGZyb20gdGhlIGVudmlyb25tZW50IGluZm9ybWF0aW9uXG4gICAgICogc3RvcmVkIGluIGxvY2FsIHN0b3JhZ2UuXG4gICAgICovXG4gICAgcmVtb3ZlRW52aXJvbm1lbnRJZCgpOiB2b2lkIHtcbiAgICAgICAgLy8gUmVtb3ZlIHRoZSBlbnZpcm9ubWVudCBJRCBmcm9tIHRoZSBlbnZpcm9ubWVudCBpbmZvcm1hdGlvblxuICAgICAgICB0aGlzLnJlbW92ZUZyb21FbnZpcm9ubWVudEluZm8oJ0lkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgZW52aXJvbm1lbnQgbmFtZSBmcm9tIHRoZSBlbnZpcm9ubWVudCBpbmZvcm1hdGlvbi5cbiAgICAgKiBcbiAgICAgKiBUaGlzIHJlbW92ZXMgdGhlIE5hbWUgcHJvcGVydHkgZnJvbSB0aGUgZW52aXJvbm1lbnQgaW5mb3JtYXRpb25cbiAgICAgKiBzdG9yZWQgaW4gbG9jYWwgc3RvcmFnZS5cbiAgICAgKi9cbiAgICByZW1vdmVFbnZpcm9ubWVudE5hbWUoKTogdm9pZCB7XG4gICAgICAgIC8vIFJlbW92ZSB0aGUgZW52aXJvbm1lbnQgbmFtZSBmcm9tIHRoZSBlbnZpcm9ubWVudCBpbmZvcm1hdGlvblxuICAgICAgICB0aGlzLnJlbW92ZUZyb21FbnZpcm9ubWVudEluZm8oJ05hbWUnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIHRoZSB0b2tlbiBmcm9tIHRoZSB0b2tlbiBpbmZvLlxuICAgICAqIFxuICAgICAqIFRoaXMgcmVtb3ZlcyB0aGUgdG9rZW4gcHJvcGVydHkgZnJvbSB0aGUgdG9rZW4gaW5mb3JtYXRpb24gc3RvcmVkIGluIHNlc3Npb25cbiAgICAgKiBzdG9yYWdlLlxuICAgICAqL1xuICAgIHJlbW92ZVRva2VuKCk6IHZvaWQge1xuICAgICAgICAvLyBSZW1vdmUgdGhlIHRva2VuIGZyb20gdGhlIHRva2VuIGluZm9cbiAgICAgICAgdGhpcy5yZW1vdmVGcm9tVG9rZW5JbmZvKCd0b2tlbicpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgdGhlIHJlZnJlc2ggdG9rZW4gZnJvbSB0aGUgdG9rZW4gaW5mb3JtYXRpb24uXG4gICAgICogXG4gICAgICogVGhpcyByZW1vdmVzIHRoZSByZWZyZXNoIHRva2VuIHByb3BlcnR5IGZyb20gdGhlIHRva2VuIGluZm9ybWF0aW9uIHN0b3JlZCBpbiBzZXNzaW9uXG4gICAgICogc3RvcmFnZS5cbiAgICAgKi9cbiAgICByZW1vdmVSZWZyZXNoVG9rZW4oKTogdm9pZCB7XG4gICAgICAgIHRoaXMucmVtb3ZlRnJvbVRva2VuSW5mbygncmVmcmVzaFRva2VuJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgcmVmcmVzaCB0b2tlbiBleHBpcnkgdGltZSBmcm9tIHRoZSB0b2tlbiBpbmZvcm1hdGlvbi5cbiAgICAgKiBcbiAgICAgKiBUaGlzIHJlbW92ZXMgdGhlIHJlZnJlc2ggdG9rZW4gZXhwaXJ5IHRpbWUgcHJvcGVydHkgZnJvbSB0aGUgdG9rZW4gaW5mb3JtYXRpb24gc3RvcmVkIGluIHNlc3Npb25cbiAgICAgKiBzdG9yYWdlLlxuICAgICAqL1xuICAgIHJlbW92ZVJlZnJlc2hUb2tlbkV4cGlyeSgpOiB2b2lkIHtcbiAgICAgICAgLy8gUmVtb3ZlIHRoZSByZWZyZXNoIHRva2VuIGV4cGlyeSBmcm9tIHRoZSB0b2tlbiBpbmZvXG4gICAgICAgIHRoaXMucmVtb3ZlRnJvbVRva2VuSW5mbygncmVmcmVzaFRva2VuRXhwaXJ5Jyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgc3RhdGljIHRva2VuIGZyb20gdGhlIHRva2VuIGluZm9ybWF0aW9uLlxuICAgICAqIFxuICAgICAqIFRoaXMgcmVtb3ZlcyB0aGUgc3RhdGljIHRva2VuIHByb3BlcnR5IGZyb20gdGhlIHRva2VuIGluZm9ybWF0aW9uIHN0b3JlZCBpbiBzZXNzaW9uXG4gICAgICogc3RvcmFnZS5cbiAgICAgKi9cbiAgICByZW1vdmVTdGF0aWNUb2tlbigpOiB2b2lkIHtcbiAgICAgICAgLy8gUmVtb3ZlIHRoZSBzdGF0aWMgdG9rZW4gZnJvbSB0aGUgdG9rZW4gaW5mb1xuICAgICAgICB0aGlzLnJlbW92ZUZyb21Ub2tlbkluZm8oJ3N0YXRpY1Rva2VuJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgc3BlY2lmaWVkIGtleSBmcm9tIHRoZSBvcmdhbml6YXRpb24gaW5mb3JtYXRpb24uXG4gICAgICogXG4gICAgICogVGhpcyByZW1vdmVzIHRoZSBzcGVjaWZpZWQga2V5IGZyb20gdGhlIG9yZ2FuaXphdGlvbiBpbmZvcm1hdGlvbiBzdG9yZWQgaW4gbG9jYWwgc3RvcmFnZS5cbiAgICAgKiBcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgdG8gcmVtb3ZlIGZyb20gdGhlIG9yZ2FuaXphdGlvbiBpbmZvcm1hdGlvbi5cbiAgICAgKi9cbiAgICBwcml2YXRlIHJlbW92ZUZyb21PcmdJbmZvKGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IG9yZ0luZm8gPSB0aGlzLmdldE9yZ0luZm8oKTtcbiAgICAgICAgaWYgKG9yZ0luZm8pIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSB0aGUga2V5IGZyb20gdGhlIG9yZ2FuaXphdGlvbiBpbmZvcm1hdGlvblxuICAgICAgICAgICAgZGVsZXRlIG9yZ0luZm9ba2V5XTtcbiAgICAgICAgICAgIC8vIFNhdmUgdGhlIHVwZGF0ZWQgb3JnYW5pemF0aW9uIGluZm9ybWF0aW9uIGJhY2sgdG8gbG9jYWwgc3RvcmFnZVxuICAgICAgICAgICAgdGhpcy5zZXRPcmdJbmZvKG9yZ0luZm8pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgc3BlY2lmaWVkIGtleSBmcm9tIHRoZSBhcHAgaW5mb3JtYXRpb24uXG4gICAgICogXG4gICAgICogVGhpcyByZW1vdmVzIHRoZSBzcGVjaWZpZWQga2V5IGZyb20gdGhlIGFwcCBpbmZvcm1hdGlvbiBzdG9yZWQgaW4gc2Vzc2lvblxuICAgICAqIHN0b3JhZ2UuXG4gICAgICogXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IHRvIHJlbW92ZSBmcm9tIHRoZSBhcHAgaW5mb3JtYXRpb24uXG4gICAgICovXG4gICAgcHJpdmF0ZSByZW1vdmVGcm9tQXBwSW5mbyhrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBjb25zdCBhcHBJbmZvID0gdGhpcy5nZXRBcHBJbmZvKCk7XG4gICAgICAgIGlmIChhcHBJbmZvKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgdGhlIGtleSBmcm9tIHRoZSBhcHAgaW5mb3JtYXRpb25cbiAgICAgICAgICAgIGRlbGV0ZSBhcHBJbmZvW2tleV07XG4gICAgICAgICAgICAvLyBTYXZlIHRoZSB1cGRhdGVkIGFwcCBpbmZvcm1hdGlvbiBiYWNrIHRvIHNlc3Npb24gc3RvcmFnZVxuICAgICAgICAgICAgdGhpcy5zZXRBcHBJbmZvKGFwcEluZm8pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgc3BlY2lmaWVkIGtleSBmcm9tIHRoZSBlbnZpcm9ubWVudCBpbmZvcm1hdGlvbi5cbiAgICAgKiBcbiAgICAgKiBUaGlzIHJlbW92ZXMgdGhlIHNwZWNpZmllZCBrZXkgZnJvbSB0aGUgZW52aXJvbm1lbnQgaW5mb3JtYXRpb24gc3RvcmVkIGluIHNlc3Npb25cbiAgICAgKiBzdG9yYWdlLlxuICAgICAqIFxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSB0byByZW1vdmUgZnJvbSB0aGUgZW52aXJvbm1lbnQgaW5mb3JtYXRpb24uXG4gICAgICovXG4gICAgcHJpdmF0ZSByZW1vdmVGcm9tRW52aXJvbm1lbnRJbmZvKGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGVudmlyb25tZW50SW5mbyA9IHRoaXMuZ2V0RW52aXJvbm1lbnRJbmZvKCk7XG4gICAgICAgIGlmIChlbnZpcm9ubWVudEluZm8pIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSB0aGUga2V5IGZyb20gdGhlIGVudmlyb25tZW50IGluZm9ybWF0aW9uXG4gICAgICAgICAgICBkZWxldGUgZW52aXJvbm1lbnRJbmZvW2tleV07XG4gICAgICAgICAgICAvLyBTYXZlIHRoZSB1cGRhdGVkIGVudmlyb25tZW50IGluZm9ybWF0aW9uIGJhY2sgdG8gc2Vzc2lvbiBzdG9yYWdlXG4gICAgICAgICAgICB0aGlzLnNldEVudmlyb25tZW50SW5mbyhlbnZpcm9ubWVudEluZm8pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgc3BlY2lmaWVkIGtleSBmcm9tIHRoZSB0b2tlbiBpbmZvcm1hdGlvbi5cbiAgICAgKiBcbiAgICAgKiBUaGlzIHJlbW92ZXMgdGhlIHNwZWNpZmllZCBrZXkgZnJvbSB0aGUgdG9rZW4gaW5mb3JtYXRpb24gc3RvcmVkIGluIHNlc3Npb25cbiAgICAgKiBzdG9yYWdlLlxuICAgICAqIFxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSB0byByZW1vdmUgZnJvbSB0aGUgdG9rZW4gaW5mb3JtYXRpb24uXG4gICAgICovXG4gICAgcHJpdmF0ZSByZW1vdmVGcm9tVG9rZW5JbmZvKGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHRva2VuSW5mbyA9IHRoaXMuZ2V0VG9rZW5JbmZvKCk7XG4gICAgICAgIGlmICh0b2tlbkluZm8pIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSB0aGUga2V5IGZyb20gdGhlIHRva2VuIGluZm9ybWF0aW9uXG4gICAgICAgICAgICBkZWxldGUgdG9rZW5JbmZvW2tleV07XG4gICAgICAgICAgICAvLyBTYXZlIHRoZSB1cGRhdGVkIHRva2VuIGluZm9ybWF0aW9uIGJhY2sgdG8gc2Vzc2lvbiBzdG9yYWdlXG4gICAgICAgICAgICB0aGlzLnNldFRva2VuSW5mbyh0b2tlbkluZm8pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIHRoZSBvcmdhbml6YXRpb24gaW5mb3JtYXRpb24gZnJvbSBsb2NhbCBzdG9yYWdlLlxuICAgICAqIFxuICAgICAqIEByZXR1cm5zIFRoZSBvcmdhbml6YXRpb24gaW5mb3JtYXRpb24gb2JqZWN0IG9yIG51bGwgaWYgaXQgZG9lc24ndCBleGlzdC5cbiAgICAgKi9cbiAgICBnZXRPcmdJbmZvKCk6IGFueSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEZyb21TdG9yYWdlKFN0b3JhZ2VUeXBlLkxvY2FsLCBTdG9yYWdlQ29uc3RhbnRzLm9yZ0luZm8pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNhdmVzIHRoZSBvcmdhbml6YXRpb24gaW5mb3JtYXRpb24gdG8gbG9jYWwgc3RvcmFnZS5cbiAgICAgKiBcbiAgICAgKiBAcGFyYW0gb3JnSW5mbyAtIFRoZSBvcmdhbml6YXRpb24gaW5mb3JtYXRpb24gdG8gc3RvcmUuXG4gICAgICovXG4gICAgc2V0T3JnSW5mbyhvcmdJbmZvOiBhbnkpOiB2b2lkIHtcbiAgICAgICAgLy8gdGVtcCBvbmNlIHJlbW92ZSBmcm9tIGRyb3Bkb3duLCB3ZSBjYW4gcmVtb3ZlIHRoaXNcbiAgICAgICAgLy8gaWYgKG9yZ0luZm8uSWQpIHtcbiAgICAgICAgLy8gICAgIHRoaXMuc2V0U2Vzc2lvbihTdG9yYWdlQ29uc3RhbnRzLlRlbmFudElkLCBvcmdJbmZvLklkKTtcbiAgICAgICAgLy8gfSBlbHNlIHtcbiAgICAgICAgLy8gICAgIHRoaXMucmVtb3ZlU2Vzc2lvbihTdG9yYWdlQ29uc3RhbnRzLlRlbmFudElkKTtcbiAgICAgICAgLy8gfVxuXG4gICAgICAgIC8vIFNhdmUgdGhlIG9yZ2FuaXphdGlvbiBpbmZvIHRvIGxvY2FsIHN0b3JhZ2VcbiAgICAgICAgdGhpcy5zZXRUb1N0b3JhZ2UoU3RvcmFnZVR5cGUuTG9jYWwsIFN0b3JhZ2VDb25zdGFudHMub3JnSW5mbywgb3JnSW5mbyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIHRoZSBhcHAgaW5mb3JtYXRpb24gZnJvbSBzZXNzaW9uIHN0b3JhZ2UuXG4gICAgICogXG4gICAgICogQHJldHVybnMgVGhlIGFwcCBpbmZvcm1hdGlvbiBvYmplY3Qgb3IgbnVsbCBpZiBpdCBkb2Vzbid0IGV4aXN0LlxuICAgICAqL1xuICAgIGdldEFwcEluZm8oKTogYW55IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0RnJvbVN0b3JhZ2UoU3RvcmFnZVR5cGUuU2Vzc2lvbiwgU3RvcmFnZUNvbnN0YW50cy5hcHBJbmZvKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTYXZlcyB0aGUgYXBwIGluZm9ybWF0aW9uIHRvIHNlc3Npb24gc3RvcmFnZS5cbiAgICAgKiBcbiAgICAgKiBAcGFyYW0gYXBwSW5mbyAtIFRoZSBhcHAgaW5mb3JtYXRpb24gdG8gc3RvcmUuXG4gICAgICovXG4gICAgc2V0QXBwSW5mbyhhcHBJbmZvOiBhbnkpOiB2b2lkIHtcbiAgICAgICAgLy8gdGVtcCBvbmNlIHJlbW92ZSBmcm9tIGRyb3Bkb3duLCB3ZSBjYW4gcmVtb3ZlIHRoaXNcbiAgICAgICAgLy8gaWYgKGFwcEluZm8/LklkKSB7XG4gICAgICAgIC8vICAgICB0aGlzLnNldFNlc3Npb24oU3RvcmFnZUNvbnN0YW50cy5BcHBJZCwgYXBwSW5mby5JZCk7XG4gICAgICAgIC8vIH0gZWxzZSB7XG4gICAgICAgIC8vICAgICB0aGlzLnJlbW92ZVNlc3Npb24oU3RvcmFnZUNvbnN0YW50cy5BcHBJZCk7XG4gICAgICAgIC8vIH1cblxuICAgICAgICAvLyBpZiAoYXBwSW5mbz8uQXBwTmFtZSkge1xuICAgICAgICAvLyAgICAgdGhpcy5zZXRTZXNzaW9uKFN0b3JhZ2VDb25zdGFudHMuYXBwbGljYXRpb25Db2RlLCBhcHBJbmZvLkFwcE5hbWUpO1xuICAgICAgICAvLyB9IGVsc2Uge1xuICAgICAgICAvLyAgICAgdGhpcy5yZW1vdmVTZXNzaW9uKFN0b3JhZ2VDb25zdGFudHMuYXBwbGljYXRpb25Db2RlKTtcbiAgICAgICAgLy8gfVxuXG4gICAgICAgIC8vIFNhdmUgdGhlIGFwcCBpbmZvIHRvIHNlc3Npb24gc3RvcmFnZVxuICAgICAgICB0aGlzLnNldFRvU3RvcmFnZShTdG9yYWdlVHlwZS5TZXNzaW9uLCBTdG9yYWdlQ29uc3RhbnRzLmFwcEluZm8sIGFwcEluZm8pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyB0aGUgZW52aXJvbm1lbnQgaW5mb3JtYXRpb24gZnJvbSBzZXNzaW9uIHN0b3JhZ2UuXG4gICAgICogXG4gICAgICogQHJldHVybnMgVGhlIGVudmlyb25tZW50IGluZm9ybWF0aW9uIG9iamVjdCBvciBudWxsIGlmIGl0IGRvZXNuJ3QgZXhpc3QuXG4gICAgICovXG4gICAgZ2V0RW52aXJvbm1lbnRJbmZvKCk6IGFueSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEZyb21TdG9yYWdlKFN0b3JhZ2VUeXBlLlNlc3Npb24sIFN0b3JhZ2VDb25zdGFudHMuZW52aXJvbm1lbnRJbmZvKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTYXZlcyB0aGUgZW52aXJvbm1lbnQgaW5mb3JtYXRpb24gdG8gc2Vzc2lvbiBzdG9yYWdlLlxuICAgICAqIFxuICAgICAqIEBwYXJhbSBlbnZJbmZvIC0gVGhlIGVudmlyb25tZW50IGluZm9ybWF0aW9uIHRvIHN0b3JlLlxuICAgICAqL1xuICAgIHNldEVudmlyb25tZW50SW5mbyhlbnZJbmZvOiBhbnkpOiB2b2lkIHtcbiAgICAgICAgLy8gU2F2ZSB0aGUgZW52aXJvbm1lbnQgaW5mbyB0byBzZXNzaW9uIHN0b3JhZ2VcbiAgICAgICAgdGhpcy5zZXRUb1N0b3JhZ2UoU3RvcmFnZVR5cGUuU2Vzc2lvbiwgU3RvcmFnZUNvbnN0YW50cy5lbnZpcm9ubWVudEluZm8sIGVudkluZm8pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyB0aGUgdG9rZW4gaW5mb3JtYXRpb24gZnJvbSBzZXNzaW9uIHN0b3JhZ2UuXG4gICAgICogXG4gICAgICogQHJldHVybnMgVGhlIHRva2VuIGluZm9ybWF0aW9uIG9iamVjdCBvciBudWxsIGlmIGl0IGRvZXNuJ3QgZXhpc3QuXG4gICAgICovXG4gICAgZ2V0VG9rZW5JbmZvKCk6IGFueSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEZyb21TdG9yYWdlKFN0b3JhZ2VUeXBlLkxvY2FsLCBTdG9yYWdlQ29uc3RhbnRzLnRva2VuSW5mbyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2F2ZXMgdGhlIHRva2VuIGluZm9ybWF0aW9uIHRvIHNlc3Npb24gc3RvcmFnZS5cbiAgICAgKiBcbiAgICAgKiBAcGFyYW0gdG9rZW5JbmZvIC0gVGhlIHRva2VuIGluZm9ybWF0aW9uIHRvIHN0b3JlLlxuICAgICAqL1xuICAgIHNldFRva2VuSW5mbyh0b2tlbkluZm86IGFueSk6IHZvaWQge1xuICAgICAgICAvLyB0ZW1wIG9uY2UgcmVtb3ZlIGZyb20gZHJvcGRvd24sIHdlIGNhbiByZW1vdmUgdGhpc1xuICAgICAgICAvLyBpZiAodG9rZW5JbmZvPy50b2tlbikge1xuICAgICAgICAvLyAgICAgdGhpcy5zZXRTZXNzaW9uKFN0b3JhZ2VDb25zdGFudHMudG9rZW4sIHRva2VuSW5mbz8udG9rZW4pO1xuICAgICAgICAvLyB9IGVsc2Uge1xuICAgICAgICAvLyAgICAgdGhpcy5yZW1vdmVTZXNzaW9uKFN0b3JhZ2VDb25zdGFudHMudG9rZW4pO1xuICAgICAgICAvLyB9XG5cbiAgICAgICAgLy8gU2F2ZSB0aGUgdG9rZW4gaW5mbyB0byBzZXNzaW9uIHN0b3JhZ2VcbiAgICAgICAgdGhpcy5zZXRUb1N0b3JhZ2UoU3RvcmFnZVR5cGUuTG9jYWwsIFN0b3JhZ2VDb25zdGFudHMudG9rZW5JbmZvLCB0b2tlbkluZm8pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyB0aGUgdXNlciBpbmZvcm1hdGlvbiBmcm9tIGxvY2FsIHN0b3JhZ2UuXG4gICAgICogXG4gICAgICogQHJldHVybnMgVGhlIHVzZXIgaW5mb3JtYXRpb24gb2JqZWN0IG9yIG51bGwgaWYgaXQgZG9lc24ndCBleGlzdC5cbiAgICAgKi9cbiAgICBnZXRVc2VySW5mbygpOiBhbnkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRGcm9tU3RvcmFnZShTdG9yYWdlVHlwZS5Mb2NhbCwgU3RvcmFnZUNvbnN0YW50cy51c2VySW5mbyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgdXNlciBpbmZvcm1hdGlvbiBpbiBsb2NhbCBzdG9yYWdlLlxuICAgICAqIFxuICAgICAqIEBwYXJhbSB1c2VySW5mbyBUaGUgdXNlciBpbmZvcm1hdGlvbiB0byBzdG9yZS5cbiAgICAgKi9cbiAgICBzZXRVc2VySW5mbyh1c2VySW5mbzogYW55KTogdm9pZCB7XG4gICAgICAgIC8vIFNhdmUgdGhlIHVzZXIgaW5mbyB0byBsb2NhbCBzdG9yYWdlXG4gICAgICAgIHRoaXMuc2V0VG9TdG9yYWdlKFN0b3JhZ2VUeXBlLkxvY2FsLCBTdG9yYWdlQ29uc3RhbnRzLnVzZXJJbmZvLCB1c2VySW5mbyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyBhIGtleS12YWx1ZSBwYWlyIGluIGxvY2FsIHN0b3JhZ2UuXG4gICAgICogXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IHRvIHN0b3JlIHRoZSB2YWx1ZSB1bmRlci5cbiAgICAgKiBAcGFyYW0gZGF0YSBUaGUgdmFsdWUgdG8gc3RvcmUuXG4gICAgICovXG4gICAgc2V0TG9jYWwoa2V5OiBzdHJpbmcsIGRhdGE6IGFueSk6IHZvaWQge1xuICAgICAgICB0aGlzLnNldFRvU3RvcmFnZShTdG9yYWdlVHlwZS5Mb2NhbCwga2V5LCBkYXRhKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgYSB2YWx1ZSBmcm9tIGxvY2FsIHN0b3JhZ2UgYnkga2V5LlxuICAgICAqIFxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBhc3NvY2lhdGVkIHdpdGggdGhlIHZhbHVlIHRvIHJldHJpZXZlLlxuICAgICAqIEByZXR1cm5zIFRoZSB2YWx1ZSBzdG9yZWQgaW4gbG9jYWwgc3RvcmFnZSwgb3IgbnVsbCBpZiBpdCBkb2Vzbid0IGV4aXN0LlxuICAgICAqL1xuICAgIGdldExvY2FsKGtleTogc3RyaW5nKTogYW55IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0RnJvbVN0b3JhZ2UoU3RvcmFnZVR5cGUuTG9jYWwsIGtleSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhIGtleS12YWx1ZSBwYWlyIGZyb20gbG9jYWwgc3RvcmFnZS5cbiAgICAgKiBcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgYXNzb2NpYXRlZCB3aXRoIHRoZSB2YWx1ZSB0byByZW1vdmUuXG4gICAgICovXG4gICAgcmVtb3ZlTG9jYWwoa2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgLy8gUmVtb3ZlIHRoZSBrZXkgZnJvbSBsb2NhbCBzdG9yYWdlXG4gICAgICAgIHRoaXMucmVtb3ZlRnJvbVN0b3JhZ2UoU3RvcmFnZVR5cGUuTG9jYWwsIGtleSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2xlYXJzIGFsbCBsb2NhbCBzdG9yYWdlIGRhdGEuXG4gICAgICovXG4gICAgY2xlYXJMb2NhbCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5jbGVhclN0b3JhZ2UoU3RvcmFnZVR5cGUuTG9jYWwpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgYSBrZXktdmFsdWUgcGFpciBpbiBzZXNzaW9uIHN0b3JhZ2UuXG4gICAgICogXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IHRvIHN0b3JlIHRoZSB2YWx1ZSB1bmRlci5cbiAgICAgKiBAcGFyYW0gZGF0YSBUaGUgdmFsdWUgdG8gc3RvcmUuXG4gICAgICovXG4gICAgc2V0U2Vzc2lvbihrZXk6IHN0cmluZywgZGF0YTogYW55KTogdm9pZCB7XG4gICAgICAgIC8vIFNhdmUgZGF0YSB0byBzZXNzaW9uIHN0b3JhZ2UgdW5kZXIgdGhlIHNwZWNpZmllZCBrZXlcbiAgICAgICAgdGhpcy5zZXRUb1N0b3JhZ2UoU3RvcmFnZVR5cGUuU2Vzc2lvbiwga2V5LCBkYXRhKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgYSB2YWx1ZSBmcm9tIHNlc3Npb24gc3RvcmFnZSBieSBrZXkuXG4gICAgICogXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IGFzc29jaWF0ZWQgd2l0aCB0aGUgdmFsdWUgdG8gcmV0cmlldmUuXG4gICAgICogQHJldHVybnMgVGhlIHZhbHVlIHN0b3JlZCBpbiBzZXNzaW9uIHN0b3JhZ2UsIG9yIG51bGwgaWYgaXQgZG9lc24ndCBleGlzdC5cbiAgICAgKi9cbiAgICBnZXRTZXNzaW9uKGtleTogc3RyaW5nKTogYW55IHtcbiAgICAgICAgLy8gUmV0cmlldmUgdGhlIHZhbHVlIGZyb20gc2Vzc2lvbiBzdG9yYWdlXG4gICAgICAgIHJldHVybiB0aGlzLmdldEZyb21TdG9yYWdlKFN0b3JhZ2VUeXBlLlNlc3Npb24sIGtleSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhIGtleS12YWx1ZSBwYWlyIGZyb20gc2Vzc2lvbiBzdG9yYWdlLlxuICAgICAqIFxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBhc3NvY2lhdGVkIHdpdGggdGhlIHZhbHVlIHRvIHJlbW92ZS5cbiAgICAgKi9cbiAgICByZW1vdmVTZXNzaW9uKGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIC8vIFJlbW92ZSB0aGUga2V5IGZyb20gc2Vzc2lvbiBzdG9yYWdlXG4gICAgICAgIHRoaXMucmVtb3ZlRnJvbVN0b3JhZ2UoU3RvcmFnZVR5cGUuU2Vzc2lvbiwga2V5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDbGVhcnMgYWxsIHNlc3Npb24gc3RvcmFnZSBkYXRhLlxuICAgICAqL1xuICAgIGNsZWFyU2Vzc2lvbigpOiB2b2lkIHtcbiAgICAgICAgLy8gUmVtb3ZlIGFsbCBrZXktdmFsdWUgcGFpcnMgZnJvbSBzZXNzaW9uIHN0b3JhZ2VcbiAgICAgICAgdGhpcy5jbGVhclN0b3JhZ2UoU3RvcmFnZVR5cGUuU2Vzc2lvbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2xlYXJzIGFsbCBhdXRoZW50aWNhdGlvbi1yZWxhdGVkIGRhdGEgZnJvbSBsb2NhbCBhbmQgc2Vzc2lvbiBzdG9yYWdlLlxuICAgICAqIFxuICAgICAqIFRoaXMgbWV0aG9kIGlzIHR5cGljYWxseSB1c2VkIGFmdGVyIGEgdXNlciBsb2dzIG91dC5cbiAgICAgKi9cbiAgICBjbGVhckF1dGgoKTogdm9pZCB7XG4gICAgICAgIC8vIFJlbW92ZSB1c2VyIGluZm8gZnJvbSBsb2NhbCBzdG9yYWdlXG4gICAgICAgIHRoaXMucmVtb3ZlRnJvbVN0b3JhZ2UoU3RvcmFnZVR5cGUuTG9jYWwsIFN0b3JhZ2VDb25zdGFudHMudXNlckluZm8pO1xuICAgICAgICAvLyBSZW1vdmUgdG9rZW4gaW5mbyBmcm9tIHNlc3Npb24gc3RvcmFnZVxuICAgICAgICB0aGlzLnJlbW92ZUZyb21TdG9yYWdlKFN0b3JhZ2VUeXBlLkxvY2FsLCBTdG9yYWdlQ29uc3RhbnRzLnRva2VuSW5mbyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJpYyBnZXR0ZXIgbWV0aG9kIGZvciByZXRyaWV2aW5nIGRhdGEgZnJvbSBlaXRoZXIgbG9jYWwgb3Igc2Vzc2lvbiBzdG9yYWdlLlxuICAgICAqIFxuICAgICAqIEBwYXJhbSBzdG9yYWdlIFRoZSB0eXBlIG9mIHN0b3JhZ2UgdG8gcmV0cmlldmUgZnJvbS5cbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgYXNzb2NpYXRlZCB3aXRoIHRoZSBkYXRhIHRvIHJldHJpZXZlLlxuICAgICAqIEByZXR1cm5zIFRoZSByZXRyaWV2ZWQgZGF0YSwgZGVzZXJpYWxpemVkIGZyb20gSlNPTiBpZiBpdCB3YXMgc3RvcmVkIGFzIGEgc3RyaW5nLlxuICAgICAqL1xuICAgIHByaXZhdGUgZ2V0RnJvbVN0b3JhZ2Uoc3RvcmFnZTogU3RvcmFnZVR5cGUsIGtleTogc3RyaW5nKTogYW55IHtcbiAgICAgICAgLy8gUmV0cmlldmUgdGhlIGRhdGEgZnJvbSB0aGUgc3BlY2lmaWVkIHN0b3JhZ2VcbiAgICAgICAgY29uc3QgZGF0YSA9IHN0b3JhZ2UgPT09IFN0b3JhZ2VUeXBlLkxvY2FsXG4gICAgICAgICAgICA/IHRoaXMuX2xvY2FsU3RvcmFnZVNlcnZpY2UuZ2V0TG9jYWxTdG9yYWdlKGtleSlcbiAgICAgICAgICAgIDogdGhpcy5fc2Vzc2lvblN0b3JhZ2VTZXJ2aWNlLmdldFNlc3Npb25TdG9yYWdlKGtleSk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIEF0dGVtcHQgdG8gcGFyc2UgdGhlIGRhdGEgYXMgSlNPTlxuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBkYXRhID09PSAnc3RyaW5nJyA/IEpTT04ucGFyc2UoZGF0YSkgOiBkYXRhO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAvLyBJZiB0aGUgZGF0YSBjYW5ub3QgYmUgcGFyc2VkLCByZXR1cm4gaXQgYXMgaXNcbiAgICAgICAgICAgIHJldHVybiBkYXRhO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyBhIGtleS12YWx1ZSBwYWlyIGluIHRoZSBzcGVjaWZpZWQgc3RvcmFnZSB0eXBlLlxuICAgICAqIFxuICAgICAqIEBwYXJhbSBzdG9yYWdlIFRoZSB0eXBlIG9mIHN0b3JhZ2UgdG8gdXNlIChsb2NhbCBvciBzZXNzaW9uKS5cbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgdW5kZXIgd2hpY2ggdGhlIGRhdGEgc2hvdWxkIGJlIHN0b3JlZC5cbiAgICAgKiBAcGFyYW0gZGF0YSBUaGUgZGF0YSB0byBzdG9yZS5cbiAgICAgKi9cbiAgICBwcml2YXRlIHNldFRvU3RvcmFnZShzdG9yYWdlOiBTdG9yYWdlVHlwZSwga2V5OiBzdHJpbmcsIGRhdGE6IGFueSk6IHZvaWQge1xuICAgICAgICAvLyBDaGVjayBpZiB0aGUgc3RvcmFnZSB0eXBlIGlzIGxvY2FsXG4gICAgICAgIGlmIChzdG9yYWdlID09PSBTdG9yYWdlVHlwZS5Mb2NhbCkge1xuICAgICAgICAgICAgLy8gU2V0IHRoZSBkYXRhIGluIGxvY2FsIHN0b3JhZ2VcbiAgICAgICAgICAgIHRoaXMuX2xvY2FsU3RvcmFnZVNlcnZpY2Uuc2V0TG9jYWxTdG9yYWdlKGtleSwgZGF0YSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBPdGhlcndpc2UsIHNldCB0aGUgZGF0YSBpbiBzZXNzaW9uIHN0b3JhZ2VcbiAgICAgICAgICAgIHRoaXMuX3Nlc3Npb25TdG9yYWdlU2VydmljZS5zZXRTZXNzaW9uU3RvcmFnZShrZXksIGRhdGEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhIGtleS12YWx1ZSBwYWlyIGZyb20gdGhlIHNwZWNpZmllZCBzdG9yYWdlIHR5cGUuXG4gICAgICogXG4gICAgICogVGhpcyBtZXRob2QgcmVtb3ZlcyB0aGUgZ2l2ZW4ga2V5IGZyb20gZWl0aGVyIGxvY2FsIG9yIHNlc3Npb24gc3RvcmFnZSBcbiAgICAgKiBiYXNlZCBvbiB0aGUgc3BlY2lmaWVkIHN0b3JhZ2UgdHlwZS5cbiAgICAgKiBcbiAgICAgKiBAcGFyYW0gc3RvcmFnZSBUaGUgdHlwZSBvZiBzdG9yYWdlIHRvIHJlbW92ZSBmcm9tIChsb2NhbCBvciBzZXNzaW9uKS5cbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgYXNzb2NpYXRlZCB3aXRoIHRoZSB2YWx1ZSB0byByZW1vdmUuXG4gICAgICovXG4gICAgcHJpdmF0ZSByZW1vdmVGcm9tU3RvcmFnZShzdG9yYWdlOiBTdG9yYWdlVHlwZSwga2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgaWYgKHN0b3JhZ2UgPT09IFN0b3JhZ2VUeXBlLkxvY2FsKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgdGhlIGtleSBmcm9tIGxvY2FsIHN0b3JhZ2VcbiAgICAgICAgICAgIHRoaXMuX2xvY2FsU3RvcmFnZVNlcnZpY2UucmVtb3ZlTG9jYWxTdG9yYWdlKGtleSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgdGhlIGtleSBmcm9tIHNlc3Npb24gc3RvcmFnZVxuICAgICAgICAgICAgdGhpcy5fc2Vzc2lvblN0b3JhZ2VTZXJ2aWNlLnJlbW92ZVNlc3Npb25TdG9yYWdlKGtleSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDbGVhcnMgYWxsIGtleS12YWx1ZSBwYWlycyBmcm9tIHRoZSBzcGVjaWZpZWQgc3RvcmFnZSB0eXBlLlxuICAgICAqIFxuICAgICAqIFRoaXMgbWV0aG9kIGNsZWFycyBhbGwga2V5LXZhbHVlIHBhaXJzIGZyb20gZWl0aGVyIGxvY2FsIG9yIHNlc3Npb24gc3RvcmFnZVxuICAgICAqIGJhc2VkIG9uIHRoZSBzcGVjaWZpZWQgc3RvcmFnZSB0eXBlLlxuICAgICAqIFxuICAgICAqIEBwYXJhbSBzdG9yYWdlIFRoZSB0eXBlIG9mIHN0b3JhZ2UgdG8gY2xlYXIgKGxvY2FsIG9yIHNlc3Npb24pLlxuICAgICAqL1xuICAgIHByaXZhdGUgY2xlYXJTdG9yYWdlKHN0b3JhZ2U6IFN0b3JhZ2VUeXBlKTogdm9pZCB7XG4gICAgICAgIGlmIChzdG9yYWdlID09PSBTdG9yYWdlVHlwZS5Mb2NhbCkge1xuICAgICAgICAgICAgLy8gQ2xlYXIgbG9jYWwgc3RvcmFnZVxuICAgICAgICAgICAgdGhpcy5fbG9jYWxTdG9yYWdlU2VydmljZS5jbGVhckxvY2FsU3RvcmFnZSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gQ2xlYXIgc2Vzc2lvbiBzdG9yYWdlXG4gICAgICAgICAgICB0aGlzLl9zZXNzaW9uU3RvcmFnZVNlcnZpY2UuY2xlYXJTZXNzaW9uU3RvcmFnZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIHNjcmVlbiBjb250ZXh0IHdpdGggdGhlIGdpdmVuIGtleSBhbmQgZGF0YS5cbiAgICAgKiBcbiAgICAgKiBUaGUgc2NyZWVuIGNvbnRleHQgaXMgYSBjb2xsZWN0aW9uIG9mIGtleS12YWx1ZSBwYWlycyB0aGF0IGFyZSBzdG9yZWQgaW4gc2Vzc2lvbiBzdG9yYWdlLlxuICAgICAqIFRoZSBrZXkgaXMgdXNlZCB0byBpZGVudGlmeSB0aGUgc2NyZWVuIGNvbnRleHQgYW5kIHRoZSBkYXRhIGlzIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGtleS5cbiAgICAgKiBcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgZm9yIHRoZSBzY3JlZW4gY29udGV4dC5cbiAgICAgKiBAcGFyYW0gZGF0YSBUaGUgZGF0YSB0byBzdG9yZSBpbiB0aGUgc2NyZWVuIGNvbnRleHQuXG4gICAgICovXG4gICAgcHVibGljIGFkZFNjcmVlbkNvbnRleHQoa2V5OiBzdHJpbmcsIGRhdGE6IGFueSk6IHZvaWQge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKCFrZXkgfHwgZGF0YSA9PSBudWxsKSByZXR1cm47XG5cbiAgICAgICAgICAgIGNvbnN0IHNjcmVlbkNvbnRleHQgPSB0aGlzLmdldFNlc3Npb24oU3RvcmFnZUNvbnN0YW50cy5zY3JlZW5Db250ZXh0KSB8fCB7fTtcblxuICAgICAgICAgICAgaWYgKCFzY3JlZW5Db250ZXh0W2tleV0pIHtcbiAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBrZXkgd2l0aCBhbiBlbXB0eSBhcnJheSBpZiBpdCBkb2Vzbid0IGV4aXN0XG4gICAgICAgICAgICAgICAgc2NyZWVuQ29udGV4dFtrZXldID0gW107XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHNjcmVlbkNvbnRleHRba2V5XS5sZW5ndGggPj0gNSkge1xuICAgICAgICAgICAgICAgIC8vIFJlbW92ZSB0aGUgb2xkZXN0IGRhdGEgaWYgdGhlIGFycmF5IGV4Y2VlZHMgNSBlbGVtZW50c1xuICAgICAgICAgICAgICAgIHNjcmVlbkNvbnRleHRba2V5XS5zaGlmdCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBBZGQgdGhlIGRhdGEgdG8gdGhlIGV4aXN0aW5nIGFycmF5XG4gICAgICAgICAgICBzY3JlZW5Db250ZXh0W2tleV0ucHVzaChkYXRhKTtcbiAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgc2NyZWVuIGNvbnRleHQgd2l0aCB0aGUgbmV3IGRhdGFcbiAgICAgICAgICAgIHRoaXMuc2V0U2Vzc2lvbihTdG9yYWdlQ29uc3RhbnRzLnNjcmVlbkNvbnRleHQsIHNjcmVlbkNvbnRleHQpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgYWRkaW5nIHNjcmVlbiBjb250ZXh0OicsIGVycm9yKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyB0aGUgbGF0ZXN0IHNjcmVlbiBjb250ZXh0IGRhdGEgYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBrZXkuXG4gICAgICogXG4gICAgICogVGhlIHNjcmVlbiBjb250ZXh0IGlzIGEgY29sbGVjdGlvbiBvZiBrZXktdmFsdWUgcGFpcnMgdGhhdCBhcmUgc3RvcmVkIGluIHNlc3Npb24gc3RvcmFnZS5cbiAgICAgKiBUaGUga2V5IGlzIHVzZWQgdG8gaWRlbnRpZnkgdGhlIHNjcmVlbiBjb250ZXh0IGFuZCB0aGUgZGF0YSBpcyB0aGUgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBrZXkuXG4gICAgICogXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IGZvciB0aGUgc2NyZWVuIGNvbnRleHQuXG4gICAgICogQHJldHVybnMgVGhlIGxhdGVzdCBzY3JlZW4gY29udGV4dCBkYXRhIGFzc29jaWF0ZWQgd2l0aCB0aGUga2V5LCBvciBudWxsIGlmIHRoZSBrZXkgaXMgbm90IGZvdW5kLlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRTY3JlZW5Db250ZXh0KGtleTogc3RyaW5nKTogYW55IHwgbnVsbCB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAoIWtleSkgcmV0dXJuIG51bGw7XG5cbiAgICAgICAgICAgIGNvbnN0IHNjcmVlbkNvbnRleHQgPSB0aGlzLmdldFNlc3Npb24oU3RvcmFnZUNvbnN0YW50cy5zY3JlZW5Db250ZXh0KTtcbiAgICAgICAgICAgIGlmICghc2NyZWVuQ29udGV4dCB8fCAhc2NyZWVuQ29udGV4dFtrZXldIHx8IHNjcmVlbkNvbnRleHRba2V5XS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUmV0dXJuIHRoZSBsYXRlc3Qgc2NyZWVuIGNvbnRleHQgZGF0YSAoTElGTylcbiAgICAgICAgICAgIHJldHVybiBzY3JlZW5Db250ZXh0W2tleV1bc2NyZWVuQ29udGV4dFtrZXldLmxlbmd0aCAtIDFdO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgZ2V0dGluZyBzY3JlZW4gY29udGV4dDonLCBlcnJvcik7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgdGhlIGxhdGVzdCBzY3JlZW4gY29udGV4dCBkYXRhIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4ga2V5IGZyb20gc2Vzc2lvbiBzdG9yYWdlLlxuICAgICAqIFxuICAgICAqIFRoZSBzY3JlZW4gY29udGV4dCBpcyBhIGNvbGxlY3Rpb24gb2Yga2V5LXZhbHVlIHBhaXJzIHRoYXQgYXJlIHN0b3JlZCBpbiBzZXNzaW9uIHN0b3JhZ2UuXG4gICAgICogVGhlIGtleSBpcyB1c2VkIHRvIGlkZW50aWZ5IHRoZSBzY3JlZW4gY29udGV4dCBhbmQgdGhlIGRhdGEgaXMgdGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUga2V5LlxuICAgICAqIFxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBmb3IgdGhlIHNjcmVlbiBjb250ZXh0LlxuICAgICAqIEByZXR1cm5zIFRoZSByZW1vdmVkIHNjcmVlbiBjb250ZXh0IGRhdGEsIG9yIG51bGwgaWYgdGhlIGtleSBpcyBub3QgZm91bmQgb3IgdGhlIGRhdGEgaXMgbm90IHByZXNlbnQuXG4gICAgICovXG4gICAgcHVibGljIGNsZWFuU2NyZWVuQ29udGV4dChrZXk6IHN0cmluZyk6IGFueSB8IG51bGwge1xuICAgICAgICB0cnkgeyAgICAgICAgICAgIFxuICAgICAgICAgICAgaWYgKCFrZXkpIHJldHVybiBudWxsO1xuXG4gICAgICAgICAgICBjb25zdCBzY3JlZW5Db250ZXh0ID0gdGhpcy5nZXRTZXNzaW9uKFN0b3JhZ2VDb25zdGFudHMuc2NyZWVuQ29udGV4dCk7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGlmICghc2NyZWVuQ29udGV4dCB8fCAhc2NyZWVuQ29udGV4dFtrZXldIHx8IHNjcmVlbkNvbnRleHRba2V5XS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgcmVtb3ZlZERhdGEgPSBzY3JlZW5Db250ZXh0W2tleV0ucG9wKCk7IC8vIFJlbW92ZSBsYXRlc3QgKExJRk8pXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIC8vIEF1dG8tY2xlYW51cDogUmVtb3ZlIGtleSBpZiBhcnJheSBiZWNvbWVzIGVtcHR5XG4gICAgICAgICAgICBpZiAoc2NyZWVuQ29udGV4dFtrZXldLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBzY3JlZW5Db250ZXh0W2tleV07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuc2V0U2Vzc2lvbihTdG9yYWdlQ29uc3RhbnRzLnNjcmVlbkNvbnRleHQsIHNjcmVlbkNvbnRleHQpO1xuICAgICAgICAgICAgcmV0dXJuIHJlbW92ZWREYXRhO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgY2xlYW5pbmcgc2NyZWVuIGNvbnRleHQ6JywgZXJyb3IpO1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICB9XG59Il19
|