@reveldigital/player-client 1.0.13 → 1.0.15

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 (33) hide show
  1. package/README.md +236 -3
  2. package/esm2020/lib/interfaces/client.interface.mjs +1 -1
  3. package/esm2020/lib/interfaces/command.interface.mjs +1 -1
  4. package/esm2020/lib/interfaces/config.interface.mjs +45 -1
  5. package/esm2020/lib/interfaces/device.interface.mjs +1 -1
  6. package/esm2020/lib/interfaces/event-properties.interface.mjs +1 -1
  7. package/esm2020/lib/interfaces/location.interface.mjs +1 -1
  8. package/esm2020/lib/player-client.service.mjs +506 -76
  9. package/esm2020/lib/safe-style.pipe.mjs +3 -2
  10. package/esm2020/lib/version.mjs +2 -2
  11. package/fesm2015/reveldigital-player-client.mjs +509 -80
  12. package/fesm2015/reveldigital-player-client.mjs.map +1 -1
  13. package/fesm2020/reveldigital-player-client.mjs +509 -79
  14. package/fesm2020/reveldigital-player-client.mjs.map +1 -1
  15. package/lib/interfaces/client.interface.d.ts +318 -76
  16. package/lib/interfaces/client.interface.d.ts.map +1 -1
  17. package/lib/interfaces/command.interface.d.ts +66 -6
  18. package/lib/interfaces/command.interface.d.ts.map +1 -1
  19. package/lib/interfaces/config.interface.d.ts +127 -9
  20. package/lib/interfaces/config.interface.d.ts.map +1 -1
  21. package/lib/interfaces/device.interface.d.ts +104 -16
  22. package/lib/interfaces/device.interface.d.ts.map +1 -1
  23. package/lib/interfaces/event-properties.interface.d.ts +127 -3
  24. package/lib/interfaces/event-properties.interface.d.ts.map +1 -1
  25. package/lib/interfaces/location.interface.d.ts +150 -21
  26. package/lib/interfaces/location.interface.d.ts.map +1 -1
  27. package/lib/player-client.service.d.ts +491 -71
  28. package/lib/player-client.service.d.ts.map +1 -1
  29. package/lib/safe-style.pipe.d.ts +2 -1
  30. package/lib/safe-style.pipe.d.ts.map +1 -1
  31. package/lib/version.d.ts +1 -1
  32. package/package.json +3 -2
  33. package/schematics/ng-add/utils/yml2xml.js +2 -1
@@ -3,26 +3,118 @@ import { BehaviorSubject, fromEvent, Subject } from 'rxjs';
3
3
  import { filter, map, share, tap } from 'rxjs/operators';
4
4
  import { version } from './version';
5
5
  import * as i0 from "@angular/core";
6
+ /**
7
+ * Service for interacting with the Revel Digital player client.
8
+ *
9
+ * This service provides a comprehensive interface for gadgets and web applications
10
+ * to communicate with the Revel Digital player environment. It handles device
11
+ * information, commands, events, analytics tracking, and configuration management.
12
+ *
13
+ * The service supports both direct API calls and event-based communication patterns,
14
+ * allowing gadgets to respond to player lifecycle events (start, stop, commands) and
15
+ * send data back to the player or remote devices.
16
+ *
17
+ * ```typescript
18
+ * constructor(private client: PlayerClientService) {
19
+ * // Subscribe to player events
20
+ * this.client.onStart$.subscribe(() => {
21
+ * console.log('Gadget started');
22
+ * });
23
+ *
24
+ * this.client.onCommand$.subscribe(command => {
25
+ * console.log('Received command:', command);
26
+ * });
27
+ * }
28
+ *
29
+ * async ngOnInit() {
30
+ * // Get device information
31
+ * const device = await this.client.getDevice();
32
+ * const deviceTime = await this.client.getDeviceTime();
33
+ *
34
+ * // Track analytics
35
+ * this.client.track('gadget_loaded', { version: '1.0' });
36
+ * }
37
+ * ```
38
+ *
39
+ * @since 1.0.0
40
+ */
6
41
  export class PlayerClientService {
7
42
  /** @ignore */
8
43
  constructor(zone) {
9
44
  /**
10
- * Commands sent to this player.
45
+ * Observable stream of commands sent to this player from the Revel Digital platform.
46
+ * Subscribe to this to handle custom commands sent from templates, playlists, or remote devices.
47
+ *
48
+ * ```typescript
49
+ * this.client.onCommand$.subscribe(command => {
50
+ * if (command.name === 'customAction') {
51
+ * this.handleCustomAction(command.arg);
52
+ * }
53
+ * });
54
+ * ```
11
55
  */
12
56
  this.onCommand$ = new Subject();
13
57
  /**
14
- * Signals the gadget has been loaded and is ready to start.
58
+ * Observable that signals when the gadget has been loaded and is ready to start.
59
+ * Emits `true` when ready, `false` when destroyed.
60
+ *
61
+ * ```typescript
62
+ * this.client.onReady$.subscribe(isReady => {
63
+ * if (isReady) {
64
+ * console.log('Client is ready');
65
+ * this.initializeGadget();
66
+ * }
67
+ * });
68
+ * ```
15
69
  */
16
70
  this.onReady$ = new BehaviorSubject(false);
17
71
  /**
18
- * Signals the gadget has been started by the player.
72
+ * Observable that signals when the gadget has been started by the player.
73
+ * This event occurs when the player begins execution of the gadget content.
74
+ *
75
+ * ```typescript
76
+ * this.client.onStart$.subscribe(() => {
77
+ * console.log('Gadget started');
78
+ * this.startAnimation();
79
+ * });
80
+ * ```
19
81
  */
20
82
  this.onStart$ = new Subject();
21
83
  /**
22
- * Signals the gadgets has been stopped by the player.
84
+ * Observable that signals when the gadget has been stopped by the player.
85
+ * This event occurs when the player stops execution, typically when moving
86
+ * to the next item in a playlist or when the content duration expires.
87
+ *
88
+ * ```typescript
89
+ * this.client.onStop$.subscribe(() => {
90
+ * console.log('Gadget stopped');
91
+ * this.cleanup();
92
+ * });
93
+ * ```
23
94
  */
24
95
  this.onStop$ = new Subject();
96
+ /**
97
+ * Observable that signals when the gadget should open the configuration window.
98
+ * This allows gadgets to respond to configuration requests from the player.
99
+ *
100
+ * ```typescript
101
+ * this.client.onConfig$.subscribe(() => {
102
+ * this.openConfigurationDialog();
103
+ * });
104
+ * ```
105
+ */
25
106
  this.onConfig$ = new Subject();
107
+ /**
108
+ * Observable that signals when the gadget has received a postMessage event from the player.
109
+ * This handles communication between the gadget and player via the postMessage API.
110
+ *
111
+ * ```typescript
112
+ * this.client.onPostMessage$.subscribe(message => {
113
+ * console.log('Received message:', message);
114
+ * this.handlePlayerMessage(message);
115
+ * });
116
+ * ```
117
+ */
26
118
  this.onPostMessage$ = new Subject();
27
119
  /** @ignore */
28
120
  this.onStartEvt$ = fromEvent(window, 'RevelDigital.Start').pipe(share(), tap(this.onStart$));
@@ -84,14 +176,21 @@ export class PlayerClientService {
84
176
  console.log('%c⚙️ Initializing Revel Digital client library', 'background-color:blue; color:yellow;');
85
177
  }
86
178
  /**
179
+ * Sends a callback to player scripting with variable arguments.
180
+ *
87
181
  * This method allows the gadget to communicate with player scripting.
88
- * If the appropriate scripting is in place in the currently running template, calling this method
89
- * will initiate a callback which can be acted upon in player script.
182
+ * If the appropriate scripting is in place in the currently running template,
183
+ * calling this method will initiate a callback which can be acted upon in player script.
184
+ *
185
+ * @param args - Variable number of arguments to pass to the callback (max 5 arguments)
90
186
  *
91
- * @example
92
- * client.callback('test', 'this');
187
+ * ```typescript
188
+ * // Send a simple callback
189
+ * this.client.callback('test', 'data');
93
190
  *
94
- * @param args variable number of arguments
191
+ * // Send multiple parameters
192
+ * this.client.callback('action', 'value1', 'value2', { data: 'object' });
193
+ * ```
95
194
  */
96
195
  callback(...args) {
97
196
  this.getClient().then((client) => {
@@ -118,26 +217,47 @@ export class PlayerClientService {
118
217
  });
119
218
  }
120
219
  /**
121
- * Accessor method for the user preferences interface exposed by the Gadgets API.
220
+ * Gets the user preferences interface exposed by the Google Gadgets API.
122
221
  *
123
- * See {@link https://developers.google.com/gadgets/docs/basic} for more details on the Gadgets API.
222
+ * This method provides access to gadget preferences which can be configured
223
+ * in the Revel Digital CMS. Use this to retrieve user-configurable settings
224
+ * for your gadget.
124
225
  *
125
- * @example
226
+ * @returns The Gadgets API Prefs object for accessing preference values
227
+ *
228
+ * ```typescript
126
229
  * constructor(public client: PlayerClientService) {
127
- * let prefs = client.getPrefs();
128
- * let myString = prefs.getString('myStringPref');
230
+ * const prefs = client.getPrefs();
231
+ * const myString = prefs.getString('myStringPref');
232
+ * const myNumber = prefs.getInt('myNumberPref');
233
+ * const myBool = prefs.getBool('myBoolPref');
129
234
  * }
130
- * @returns {gadgets.Prefs} Gadget API Prefs object
235
+ * ```
236
+ *
237
+ * @see {@link https://developers.google.com/gadgets/docs/basic} Google Gadgets API documentation
131
238
  */
132
239
  getPrefs() {
133
240
  return new window['gadgets']['Prefs']();
134
241
  }
135
242
  /**
136
- * Returns the current device time in ISO8601 format.
243
+ * Gets the current device time in ISO8601 format.
244
+ *
137
245
  * Current device time is determined by the device timezone assigned to the device in the CMS.
246
+ * This is useful for displaying time-sensitive content or scheduling operations based on
247
+ * the device's local time rather than browser time.
138
248
  *
139
- * @param date Optional. If supplied will translate the supplied date/time to device time based on respective timezones.
140
- * @returns Date/time in ISO8601 format
249
+ * @param date - Optional. If supplied, will translate the supplied date/time to device time based on respective timezones
250
+ * @returns Promise resolving to date/time in ISO8601 format
251
+ *
252
+ * ```typescript
253
+ * // Get current device time
254
+ * const currentTime = await this.client.getDeviceTime();
255
+ * console.log('Device time:', currentTime);
256
+ *
257
+ * // Convert a specific date to device time
258
+ * const specificDate = new Date('2023-01-01T12:00:00Z');
259
+ * const deviceTime = await this.client.getDeviceTime(specificDate);
260
+ * ```
141
261
  */
142
262
  async getDeviceTime(date) {
143
263
  const client = await this.getClient();
@@ -147,55 +267,99 @@ export class PlayerClientService {
147
267
  return client.getDeviceTime();
148
268
  }
149
269
  /**
150
- * Returns the timezone name currently assigned to the device.
270
+ * Gets the timezone name currently assigned to the device.
271
+ *
272
+ * @returns Promise resolving to the timezone name (e.g., "America/New_York")
151
273
  *
152
- * @returns Timezone Name
274
+ * ```typescript
275
+ * const timezoneName = await this.client.getDeviceTimeZoneName();
276
+ * console.log('Device timezone:', timezoneName);
277
+ * ```
153
278
  */
154
279
  async getDeviceTimeZoneName() {
155
280
  const client = await this.getClient();
156
281
  return client.getDeviceTimeZoneName();
157
282
  }
158
283
  /**
159
- * Returns the timezone ID currently assigned to the device.
284
+ * Gets the timezone ID currently assigned to the device.
160
285
  *
161
- * @returns Timezone ID
286
+ * @returns Promise resolving to the timezone ID
287
+ *
288
+ * ```typescript
289
+ * const timezoneId = await this.client.getDeviceTimeZoneID();
290
+ * console.log('Device timezone ID:', timezoneId);
291
+ * ```
162
292
  */
163
293
  async getDeviceTimeZoneID() {
164
294
  const client = await this.getClient();
165
295
  return client.getDeviceTimeZoneID();
166
296
  }
167
297
  /**
168
- * Returns the numerical offset from GMT of the timezone currently assigned to the device.
298
+ * Gets the numerical offset from GMT of the timezone currently assigned to the device.
299
+ *
300
+ * @returns Promise resolving to the timezone offset in hours (e.g., -5 for EST)
169
301
  *
170
- * @returns Timezone offset
302
+ * ```typescript
303
+ * const offset = await this.client.getDeviceTimeZoneOffset();
304
+ * console.log('Device timezone offset:', offset, 'hours from GMT');
305
+ * ```
171
306
  */
172
307
  async getDeviceTimeZoneOffset() {
173
308
  const client = await this.getClient();
174
309
  return client.getDeviceTimeZoneOffset();
175
310
  }
176
311
  /**
177
- * Returns the language code of the language currently assigned to the device.
312
+ * Gets the language code of the language currently assigned to the device.
313
+ *
314
+ * @returns Promise resolving to the language code (e.g., "en-US", "fr-FR")
178
315
  *
179
- * @returns Language code
316
+ * ```typescript
317
+ * const languageCode = await this.client.getLanguageCode();
318
+ * console.log('Device language:', languageCode);
319
+ * // Use for localization
320
+ * this.loadLanguageResources(languageCode);
321
+ * ```
180
322
  */
181
323
  async getLanguageCode() {
182
324
  const client = await this.getClient();
183
325
  return client.getLanguageCode();
184
326
  }
185
327
  /**
186
- * Returns the unique Revel Digital device key associated with the device.
328
+ * Gets the unique Revel Digital device key associated with the device.
187
329
  *
188
- * @returns Device key
330
+ * The device key is a unique identifier for this specific player device
331
+ * and can be used for device-specific operations or remote commands.
332
+ *
333
+ * @returns Promise resolving to the device key string
334
+ *
335
+ * ```typescript
336
+ * const deviceKey = await this.client.getDeviceKey();
337
+ * console.log('Device key:', deviceKey);
338
+ * ```
189
339
  */
190
340
  async getDeviceKey() {
191
341
  const client = await this.getClient();
192
342
  return client.getDeviceKey();
193
343
  }
194
344
  /**
195
- * Send a command to the player device.
345
+ * Sends a command to the local player device.
346
+ *
347
+ * Commands can be used to control various aspects of the player or trigger
348
+ * specific behaviors. The command is processed by the local player only.
196
349
  *
197
- * @param name Command name
198
- * @param arg Command argument
350
+ * @param name - The command name/identifier
351
+ * @param arg - The command argument/payload
352
+ *
353
+ * ```typescript
354
+ * // Send a simple command
355
+ * this.client.sendCommand('refresh', '');
356
+ *
357
+ * // Send a command with data
358
+ * this.client.sendCommand('setVolume', '50');
359
+ *
360
+ * // Send a command with JSON data
361
+ * this.client.sendCommand('configure', JSON.stringify({ setting: 'value' }));
362
+ * ```
199
363
  */
200
364
  sendCommand(name, arg) {
201
365
  this.getClient().then((client) => {
@@ -203,12 +367,29 @@ export class PlayerClientService {
203
367
  });
204
368
  }
205
369
  /**
206
- * Send a command to any remote player with the supplied device key(s).
370
+ * Sends a command to remote player devices with the specified device keys.
371
+ *
372
+ * Remote commands allow cross-device communication within the same Revel Digital account.
373
+ * This is useful for synchronized displays, device coordination, or remote control scenarios.
374
+ *
207
375
  * Note: Remote commands can only be delivered to devices within the same account as the sender device.
208
376
  *
209
- * @param deviceKeys Array of remote device keys
210
- * @param name Command name
211
- * @param arg Command arg
377
+ * @param deviceKeys - Array of target device keys to send the command to
378
+ * @param name - The command name/identifier
379
+ * @param arg - The command argument/payload
380
+ *
381
+ * ```typescript
382
+ * // Send command to specific devices
383
+ * const targetDevices = ['device-key-1', 'device-key-2'];
384
+ * this.client.sendRemoteCommand(targetDevices, 'syncAction', 'start');
385
+ *
386
+ * // Broadcast to multiple devices
387
+ * this.client.sendRemoteCommand(
388
+ * ['lobby-display', 'kiosk-1', 'kiosk-2'],
389
+ * 'updateContent',
390
+ * JSON.stringify({ contentId: '12345' })
391
+ * );
392
+ * ```
212
393
  */
213
394
  sendRemoteCommand(deviceKeys, name, arg) {
214
395
  this.getClient().then((client) => {
@@ -216,11 +397,33 @@ export class PlayerClientService {
216
397
  });
217
398
  }
218
399
  /**
219
- * Log an event for use with AdHawk analytics.
220
- * Events are used for tracking various metrics including usage statistics, player condition, state changes, etc.
400
+ * Logs an analytics event for use with AdHawk analytics and reporting.
401
+ *
402
+ * Events are used for tracking various metrics including usage statistics,
403
+ * player condition, state changes, user interactions, and custom business metrics.
404
+ * These events can be viewed in the Revel Digital analytics dashboard.
405
+ *
406
+ * @param eventName - Unique name for this event (should be descriptive and consistent)
407
+ * @param properties - Optional map of user-defined properties to associate with this event
408
+ *
409
+ * ```typescript
410
+ * // Simple event tracking
411
+ * this.client.track('gadget_loaded');
412
+ *
413
+ * // Event with properties
414
+ * this.client.track('user_interaction', {
415
+ * action: 'button_click',
416
+ * button_id: 'start_button',
417
+ * timestamp: new Date().toISOString()
418
+ * });
221
419
  *
222
- * @param eventName Unique name for this event
223
- * @param properties A map of user defined properties to associate with this event
420
+ * // Performance tracking
421
+ * this.client.track('content_displayed', {
422
+ * content_type: 'video',
423
+ * duration: 30,
424
+ * quality: 'HD'
425
+ * });
426
+ * ```
224
427
  */
225
428
  track(eventName, properties) {
226
429
  this.getClient().then((client) => {
@@ -228,13 +431,32 @@ export class PlayerClientService {
228
431
  });
229
432
  }
230
433
  /**
231
- * Method for initiating a timed event.
232
- * Timed events are useful for tracking the duration of an event and must be proceeded with a call to track().
434
+ * Initiates a timed event for duration tracking.
435
+ *
436
+ * Timed events are useful for tracking the duration of operations or user interactions.
437
+ * This method must be followed by a call to track() with the same event name to complete
438
+ * the timing measurement. The duration will be automatically calculated and included
439
+ * in the event properties.
440
+ *
441
+ * @param eventName - Unique name for this timed event (must match the subsequent track() call)
442
+ *
443
+ * ```typescript
444
+ * // Start timing an event
445
+ * this.client.timeEvent('video_playback');
446
+ *
447
+ * // ... video plays for some duration ...
448
+ *
449
+ * // End timing and log the event with duration
450
+ * this.client.track('video_playback', {
451
+ * video_id: 'abc123',
452
+ * quality: 'HD'
453
+ * }); // Duration will be automatically added
233
454
  *
234
- * @example
235
- * client.timeEvent('testEvent');
236
- * client.track("test", { "a": "b" });
237
- * @param eventName Unique name for this event
455
+ * // Example for user interaction timing
456
+ * this.client.timeEvent('form_completion');
457
+ * // ... user fills out form ...
458
+ * this.client.track('form_completion', { form_type: 'contact' });
459
+ * ```
238
460
  */
239
461
  timeEvent(eventName) {
240
462
  this.getClient().then((client) => {
@@ -242,11 +464,33 @@ export class PlayerClientService {
242
464
  });
243
465
  }
244
466
  /**
245
- * A session is a way of grouping events together. Each event has an associated session ID.
246
- * Session ID's are randomly generated and reset by subsequent calls to newEventSession().
467
+ * Creates a new analytics event session for grouping related events.
247
468
  *
248
- * Each call to track() will utilize the same session ID, until another call to newEventSession().
249
- * @param id Optional. User supplied session ID. If not supplied a random session ID will be generated.
469
+ * A session is a way of grouping events together for analysis. Each event tracked
470
+ * after calling this method will have the same session ID until a new session is created.
471
+ * Session IDs are randomly generated unless explicitly provided.
472
+ *
473
+ * This is useful for tracking user journeys, workflow completion, or grouping
474
+ * related interactions within a specific time period.
475
+ *
476
+ * @param id - Optional user-supplied session ID. If not provided, a random session ID will be generated
477
+ *
478
+ * ```typescript
479
+ * // Start a new session with auto-generated ID
480
+ * this.client.newEventSession();
481
+ * this.client.track('session_start');
482
+ * this.client.track('user_action_1');
483
+ * this.client.track('user_action_2');
484
+ *
485
+ * // Start a session with custom ID
486
+ * this.client.newEventSession('user-workflow-12345');
487
+ * this.client.track('workflow_start');
488
+ * this.client.track('step_completed', { step: 1 });
489
+ *
490
+ * // Start a new session for different workflow
491
+ * this.client.newEventSession();
492
+ * this.client.track('different_workflow_start');
493
+ * ```
250
494
  */
251
495
  newEventSession(id) {
252
496
  this.getClient().then((client) => {
@@ -259,26 +503,74 @@ export class PlayerClientService {
259
503
  });
260
504
  }
261
505
  /**
262
- * Returns the root folder utilized by this player device.
506
+ * Gets the root folder path utilized by this player device.
507
+ *
508
+ * This returns the base directory path where the Revel Digital player
509
+ * stores its files and resources on the local device.
263
510
  *
264
- * @returns Path to the root folder
511
+ * @returns Promise resolving to the path of the root folder
512
+ *
513
+ * ```typescript
514
+ * const rootPath = await this.client.getRevelRoot();
515
+ * console.log('Player root directory:', rootPath);
516
+ * // Use for constructing file paths or understanding storage structure
517
+ * ```
265
518
  */
266
519
  async getRevelRoot() {
267
520
  const client = await this.getClient();
268
521
  return client.getRevelRoot();
269
522
  }
270
523
  /**
271
- * Returns a map of commands currently active for this device.
524
+ * Gets a map of commands currently active for this device.
525
+ *
526
+ * This returns the current command configuration that defines how the device
527
+ * responds to various command triggers and remote commands.
528
+ *
529
+ * @returns Promise resolving to a map of currently active commands
272
530
  *
273
- * @returns Map of commands currently active for this device.
531
+ * ```typescript
532
+ * const commandMap = await this.client.getCommandMap();
533
+ * console.log('Active commands:', commandMap);
534
+ *
535
+ * // Check if specific command is available
536
+ * if (commandMap['customCommand']) {
537
+ * console.log('Custom command is available');
538
+ * }
539
+ * ```
274
540
  */
275
541
  async getCommandMap() {
276
542
  const client = await this.getClient();
277
543
  return JSON.parse(await client.getCommandMap());
278
544
  }
279
545
  /**
280
- * Indicate to the player that this gadget has finished it's visualization.
281
- * This allows the player to proceed with the next item in a playlist if applicable.
546
+ * Signals to the player that this gadget has completed its visualization.
547
+ *
548
+ * This method notifies the player that the current gadget has finished its
549
+ * content display or interaction cycle. The player can then proceed with
550
+ * the next item in a playlist if applicable, or handle the completion
551
+ * according to its configuration.
552
+ *
553
+ * Call this method when your gadget has completed its intended function,
554
+ * such as finishing an animation, completing a form, or reaching a natural
555
+ * stopping point.
556
+ *
557
+ * ```typescript
558
+ * // After completing an animation
559
+ * private onAnimationComplete(): void {
560
+ * this.client.finish();
561
+ * }
562
+ *
563
+ * // After user interaction is complete
564
+ * private onFormSubmitted(): void {
565
+ * this.saveFormData();
566
+ * this.client.finish();
567
+ * }
568
+ *
569
+ * // After a timed display period
570
+ * setTimeout(() => {
571
+ * this.client.finish();
572
+ * }, 30000); // 30 seconds
573
+ * ```
282
574
  */
283
575
  finish() {
284
576
  this.getClient().then((client) => {
@@ -286,20 +578,64 @@ export class PlayerClientService {
286
578
  });
287
579
  }
288
580
  /**
289
- * Check is the gadget is running in preview mode. Preview mode is enabled when the gadget is
290
- * being edited in the CMS, or otherwise not running in a normal player environment.
581
+ * Checks if the gadget is running in preview mode.
582
+ *
583
+ * Preview mode is enabled when the gadget is being edited in the Revel Digital CMS,
584
+ * tested in the gadget editor, or otherwise not running in a normal player environment.
585
+ * This is useful for providing different behavior during development/testing versus
586
+ * production deployment.
587
+ *
588
+ * @returns Promise resolving to true if running in preview mode, false if running on actual player
589
+ *
590
+ * ```typescript
591
+ * const isPreview = await this.client.isPreviewMode();
592
+ *
593
+ * if (isPreview) {
594
+ * console.log('Running in preview mode - using mock data');
595
+ * this.loadMockData();
596
+ * } else {
597
+ * console.log('Running on player device - using live data');
598
+ * this.loadLiveData();
599
+ * }
291
600
  *
292
- * @returns True if the gadget is running in preview mode, false otherwise.
601
+ * // Show different UI in preview
602
+ * this.showPreviewIndicator = isPreview;
603
+ * ```
293
604
  */
294
605
  async isPreviewMode() {
295
606
  const client = await this.getClient();
296
607
  return client instanceof NoopClient;
297
608
  }
298
609
  /**
299
- * Returns the device details associated with the player running the gadget or web app.
300
- *
301
- * @returns Device details.
302
- */
610
+ * Gets detailed information about the device running the player.
611
+ *
612
+ * Returns comprehensive device details including name, registration key, type,
613
+ * service date, language, timezone, tags, and location information. This data
614
+ * is configured in the Revel Digital CMS for each device.
615
+ *
616
+ * @returns Promise resolving to device details object, or null if not available
617
+ *
618
+ * ```typescript
619
+ * const device = await this.client.getDevice();
620
+ *
621
+ * if (device) {
622
+ * console.log('Device name:', device.name);
623
+ * console.log('Device type:', device.deviceType);
624
+ * console.log('Location:', device.location.city, device.location.state);
625
+ * console.log('Tags:', device.tags);
626
+ *
627
+ * // Use device info for customization
628
+ * if (device.location.country === 'US') {
629
+ * this.loadUSContent();
630
+ * }
631
+ *
632
+ * // Check device capabilities based on type
633
+ * if (device.deviceType === 'android') {
634
+ * this.enableTouchFeatures();
635
+ * }
636
+ * }
637
+ * ```
638
+ */
303
639
  async getDevice() {
304
640
  const client = await this.getClient();
305
641
  let obj = JSON.parse(await client.getDevice());
@@ -326,41 +662,125 @@ export class PlayerClientService {
326
662
  return device[0];
327
663
  }
328
664
  /**
329
- * Returns the width of the visualization area.
665
+ * Gets the width of the visualization area in pixels.
666
+ *
667
+ * This returns the available width for content display, which may be
668
+ * different from the full screen width depending on player configuration
669
+ * and template layout.
670
+ *
671
+ * @returns Promise resolving to width in pixels, or null if not available
330
672
  *
331
- * @returns Width of the visualization area
673
+ * ```typescript
674
+ * const width = await this.client.getWidth();
675
+ *
676
+ * if (width) {
677
+ * console.log('Available width:', width, 'pixels');
678
+ *
679
+ * // Adapt content layout based on width
680
+ * if (width < 800) {
681
+ * this.enableMobileLayout();
682
+ * } else {
683
+ * this.enableDesktopLayout();
684
+ * }
685
+ * }
686
+ * ```
332
687
  */
333
688
  async getWidth() {
334
689
  const client = await this.getClient();
335
690
  return client.getWidth();
336
691
  }
337
692
  /**
338
- * Returns the height of the visualization area.
693
+ * Gets the height of the visualization area in pixels.
694
+ *
695
+ * This returns the available height for content display, which may be
696
+ * different from the full screen height depending on player configuration
697
+ * and template layout.
698
+ *
699
+ * @returns Promise resolving to height in pixels, or null if not available
700
+ *
701
+ * ```typescript
702
+ * const height = await this.client.getHeight();
339
703
  *
340
- * @returns Height of the visualization area
704
+ * if (height) {
705
+ * console.log('Available height:', height, 'pixels');
706
+ *
707
+ * // Calculate aspect ratio for responsive design
708
+ * const width = await this.client.getWidth();
709
+ * const aspectRatio = width / height;
710
+ * this.adjustContentForAspectRatio(aspectRatio);
711
+ * }
712
+ * ```
341
713
  */
342
714
  async getHeight() {
343
715
  const client = await this.getClient();
344
716
  return client.getHeight();
345
717
  }
346
718
  /**
347
- * Returns the duration of the currently playing source.
348
- * (only applicable when associated with a playlist)
719
+ * Gets the duration of the currently playing content item.
720
+ *
721
+ * This method is only applicable when the gadget is associated with a playlist
722
+ * and returns the duration assigned to the current playlist item. The duration
723
+ * determines how long the content should be displayed before moving to the next item.
724
+ *
725
+ * @returns Promise resolving to duration in milliseconds, or null if not applicable/available
726
+ *
727
+ * ```typescript
728
+ * const duration = await this.client.getDuration();
349
729
  *
350
- * @returns Duration of the current item in milliseconds
730
+ * if (duration) {
731
+ * console.log('Content duration:', duration, 'milliseconds');
732
+ *
733
+ * // Set up auto-finish timer
734
+ * setTimeout(() => {
735
+ * this.client.finish();
736
+ * }, duration);
737
+ *
738
+ * // Show progress indicator
739
+ * this.startProgressIndicator(duration);
740
+ * }
741
+ * ```
351
742
  */
352
743
  async getDuration() {
353
744
  const client = await this.getClient();
354
745
  return client.getDuration();
355
746
  }
356
747
  /**
357
- * Returns the current SDK version.
748
+ * Gets the current version of the Revel Digital SDK.
358
749
  *
359
- * @returns SDK version
750
+ * @returns Promise resolving to the SDK version string
751
+ *
752
+ * ```typescript
753
+ * const version = await this.client.getSdkVersion();
754
+ * console.log('SDK Version:', version);
755
+ *
756
+ * // Use for compatibility checks or logging
757
+ * this.client.track('gadget_loaded', { sdkVersion: version });
758
+ * ```
360
759
  */
361
760
  async getSdkVersion() {
362
761
  return Promise.resolve(version);
363
762
  }
763
+ /**
764
+ * Applies configuration preferences to the gadget (preview mode only).
765
+ *
766
+ * This method is only available when running in preview mode (typically during
767
+ * gadget development or testing in the CMS). It allows applying configuration
768
+ * changes that would normally come from the gadget's preference settings.
769
+ *
770
+ * @param prefs - Dictionary of preference key-value pairs to apply
771
+ *
772
+ * ```typescript
773
+ * if (await this.client.isPreviewMode()) {
774
+ * // Apply test configuration in preview
775
+ * await this.client.applyConfig({
776
+ * 'title': 'Test Title',
777
+ * 'backgroundColor': '#ff0000',
778
+ * 'showBorder': true,
779
+ * 'refreshInterval': 30
780
+ * });
781
+ * }
782
+ * ```
783
+ */
364
784
  async applyConfig(prefs) {
365
785
  if (await this.isPreviewMode()) {
366
786
  const client = await this.getClient();
@@ -417,10 +837,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.12", ngImpo
417
837
  }], ctorParameters: function () { return [{ type: i0.NgZone }]; } });
418
838
  // ----------------------------------------------------------------------------------- //
419
839
  // ----------------------------------------------------------------------------------- //
420
- // I provide a mock API for the 3rd-party script. This just allows the consuming code to
421
- // act as though the library is available even if it failed to load (example, it was
422
- // blocked by an ad-blocker).
423
- /** @ignore */
840
+ /**
841
+ * Mock implementation of the IClient interface.
842
+ *
843
+ * This class provides a no-operation (NOOP) implementation of the client API
844
+ * that allows consuming code to function normally even when the actual player
845
+ * API is not available. This typically occurs during development, testing,
846
+ * or when the player script is blocked by ad-blockers.
847
+ *
848
+ * All methods in this class either return null/empty values or perform no
849
+ * operations, allowing gadgets to function without errors while providing
850
+ * appropriate fallback behavior.
851
+ *
852
+ * @private
853
+ */
424
854
  class NoopClient {
425
855
  constructor() {
426
856
  console.log('%cClient API not available, falling back to mock API', 'background-color:blue; color:yellow;');
@@ -495,4 +925,4 @@ class NoopClient {
495
925
  }
496
926
  }
497
927
  }
498
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxheWVyLWNsaWVudC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvcmV2ZWxkaWdpdGFsL3BsYXllci1jbGllbnQvc3JjL2xpYi9wbGF5ZXItY2xpZW50LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBcUIsTUFBTSxlQUFlLENBQUM7QUFFOUQsT0FBTyxFQUFFLGVBQWUsRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFnQixNQUFNLE1BQU0sQ0FBQztBQUN6RSxPQUFPLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFNekQsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQzs7QUFpQnBDLE1BQU0sT0FBTyxtQkFBbUI7SUF1RzlCLGNBQWM7SUFDZCxZQUFZLElBQVk7UUFuR3hCOztXQUVHO1FBQ0ksZUFBVSxHQUFHLElBQUksT0FBTyxFQUFZLENBQUM7UUFDNUM7O1dBRUc7UUFDSSxhQUFRLEdBQUcsSUFBSSxlQUFlLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDN0M7O1dBRUc7UUFDSSxhQUFRLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUNoQzs7V0FFRztRQUNJLFlBQU8sR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBRXhCLGNBQVMsR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBRTFCLG1CQUFjLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQVV0QyxjQUFjO1FBQ04sZ0JBQVcsR0FBRyxTQUFTLENBQUMsTUFBTSxFQUFFLG9CQUFvQixDQUFDLENBQUMsSUFBSSxDQUNoRSxLQUFLLEVBQUUsRUFDUCxHQUFHLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUNuQixDQUFDO1FBR0YsY0FBYztRQUNOLGVBQVUsR0FBRyxTQUFTLENBQUMsTUFBTSxFQUFF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QUFRLEVBQUUsTUFBTSxDQUFDLE1BQU0sS0FBSyxJQUFJLEVBQUUsQ0FBQztRQUVsRixJQUFJLE1BQU0sQ0FBQyxNQUFNLEVBQUU7WUFDakIsTUFBTSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQ3ZCLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLEVBQ25CLEdBQUcsQ0FDSixDQUFDO1NBQ0g7YUFBTTtZQUNMLE1BQU0sQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUN2QixJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxFQUNuQixHQUFHLENBQ0osQ0FBQztTQUNIO0lBQ0gsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgTmdab25lLCBPbkRlc3Ryb3kgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgZ2FkZ2V0cyB9IGZyb20gJ0ByZXZlbGRpZ2l0YWwvZ2FkZ2V0LXR5cGVzJztcclxuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBmcm9tRXZlbnQsIFN1YmplY3QsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBmaWx0ZXIsIG1hcCwgc2hhcmUsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcclxuaW1wb3J0IHsgSUNsaWVudCB9IGZyb20gJy4vaW50ZXJmYWNlcy9jbGllbnQuaW50ZXJmYWNlJztcclxuaW1wb3J0IHsgSUNvbW1hbmQgfSBmcm9tICcuL2ludGVyZmFjZXMvY29tbWFuZC5pbnRlcmZhY2UnO1xyXG5pbXBvcnQgeyBJRGljdGlvbmFyeSB9IGZyb20gJy4vaW50ZXJmYWNlcy9jb25maWcuaW50ZXJmYWNlJztcclxuaW1wb3J0IHsgSURldmljZSB9IGZyb20gJy4vaW50ZXJmYWNlcy9kZXZpY2UuaW50ZXJmYWNlJztcclxuaW1wb3J0IHsgSUV2ZW50UHJvcGVydGllcyB9IGZyb20gJy4vaW50ZXJmYWNlcy9ldmVudC1wcm9wZXJ0aWVzLmludGVyZmFjZSc7XHJcbmltcG9ydCB7IHZlcnNpb24gfSBmcm9tICcuL3ZlcnNpb24nO1xyXG5cclxuLy9pbXBvcnQgeyB2ZXJzaW9uIH0gZnJvbSAnLi92ZXJzaW9uLmpzJztcclxuXHJcbi8vIFNvIHRoYXQgVHlwZVNjcmlwdCBkb2Vzbid0IGNvbXBsYWluLCB3ZSdyZSBnb2luZyB0byBhdWdtZW50IHRoZSBHTE9CQUwgLyBXSU5ET1cgXHJcbi8vIG5hbWUtc3BhY2UgZGVmaW5pdGlvbiB0byBpbmNsdWRlIHRoZSBUcmFja2VyIEFQSS4gVGhpcyBhbHNvIHByb3ZpZGVzIHVzIHdpdGggYSBwbGFjZVxyXG4vLyB0byBhY3R1YWxseSBET0NVTUVOVCB0aGUgQVBJIHNvIHRoYXQgb3VyIGRldmVsb3BlcnMgYXJlbid0IGd1ZXNzaW5nIGFib3V0IHdoYXQnc1xyXG4vLyBhdmFpbGFibGUgb24gdGhlIGxpYnJhcnkuXHJcblxyXG4vKiogQGlnbm9yZSAqL1xyXG5kZWNsYXJlIGdsb2JhbCB7XHJcbiAgdmFyIENsaWVudDogSUNsaWVudDtcclxufVxyXG5cclxuQEluamVjdGFibGUoe1xyXG4gIHByb3ZpZGVkSW46ICdyb290J1xyXG59KVxyXG5leHBvcnQgY2xhc3MgUGxheWVyQ2xpZW50U2VydmljZSBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XHJcblxyXG4gIC8qKiBAaWdub3JlICovXHJcbiAgcHJpdmF0ZSBjbGllbnRQcm9taXNlOiBQcm9taXNlPElDbGllbnQ+IHwgbnVsbDtcclxuXHJcbiAgLyoqXHJcbiAgICogQ29tbWFuZHMgc2VudCB0byB0aGlzIHBsYXllci5cclxuICAgKi9cclxuICBwdWJsaWMgb25Db21tYW5kJCA9IG5ldyBTdWJqZWN0PElDb21tYW5kPigpO1xyXG4gIC8qKlxyXG4gICAqIFNpZ25hbHMgdGhlIGdhZGdldCBoYXMgYmVlbiBsb2FkZWQgYW5kIGlzIHJlYWR5IHRvIHN0YXJ0LlxyXG4gICAqL1xyXG4gIHB1YmxpYyBvblJlYWR5JCA9IG5ldyBCZWhhdmlvclN1YmplY3QoZmFsc2UpO1xyXG4gIC8qKlxyXG4gICAqIFNpZ25hbHMgdGhlIGdhZGdldCBoYXMgYmVlbiBzdGFydGVkIGJ5IHRoZSBwbGF5ZXIuXHJcbiAgICovXHJcbiAgcHVibGljIG9uU3RhcnQkID0gbmV3IFN1YmplY3QoKTtcclxuICAvKipcclxuICAgKiBTaWduYWxzIHRoZSBnYWRnZXRzIGhhcyBiZWVuIHN0b3BwZWQgYnkgdGhlIHBsYXllci5cclxuICAgKi9cclxuICBwdWJsaWMgb25TdG9wJCA9IG5ldyBTdWJqZWN0KCk7XHJcblxyXG4gIHB1YmxpYyBvbkNvbmZpZyQgPSBuZXcgU3ViamVjdCgpO1xyXG5cclxuICBwdWJsaWMgb25Qb3N0TWVzc2FnZSQgPSBuZXcgU3ViamVjdCgpO1xyXG5cclxuICAvL1xyXG4gIC8vIFR3byBtZXRob2RzIGF2YWlsYWJsZSBmb3IgY2FsbGluZyBpbnRvIHRoZSBsaWJyYXJ5OlxyXG4gIC8vXHJcbiAgLy8gMSkgVXNpbmcgZGlzcGF0Y2hFdmVudCgpIHdpdGggdGhlIGZvbGxvd2luZyBjdXN0b20gZXZlbnRzXHJcbiAgLy8gMikgVXNpbmcgdGhlIHdpbmRvdyBzY29wZWQgUmV2ZWxEaWdpdGFsIG9iamVjdCBhcyBkZWZpbmVkIGluIHRoZSBjb25zdHJ1Y3RvclxyXG4gIC8vXHJcbiAgLyoqIEBpZ25vcmUgKi9cclxuICBwcml2YXRlIG9uU3RhcnRTdWI6IFN1YnNjcmlwdGlvbjtcclxuICAvKiogQGlnbm9yZSAqL1xyXG4gIHByaXZhdGUgb25TdGFydEV2dCQgPSBmcm9tRXZlbnQod2luZG93LCAnUmV2ZWxEaWdpdGFsLlN0YXJ0JykucGlwZShcclxuICAgIHNoYXJlKCksXHJcbiAgICB0YXAodGhpcy5vblN0YXJ0JClcclxuICApO1xyXG4gIC8qKiBAaWdub3JlICovXHJcbiAgcHJpdmF0ZSBvblN0b3BTdWI6IFN1YnNjcmlwdGlvbjtcclxuICAvKiogQGlnbm9yZSAqL1xyXG4gIHByaXZhdGUgb25TdG9wRXZ0JCA9IGZyb21FdmVudCh3aW5kb3csICdSZXZlbERpZ2l0YWwuU3RvcCcpLnBpcGUoXHJcbiAgICBzaGFyZSgpLFxyXG4gICAgdGFwKHRoaXMub25TdG9wJClcclxuICApO1xyXG4gIC8qKiBAaWdub3JlICovXHJcbiAgcHJpdmF0ZSBvbkNvbW1hbmRTdWI6IFN1YnNjcmlwdGlvbjtcclxuICAvKiogQGlnbm9yZSAqL1xyXG4gIHByaXZhdGUgb25Db21tYW5kRXZ0JCA9IGZyb21FdmVudDxJQ29tbWFuZD4od2luZG93LCAnUmV2ZWxEaWdpdGFsLkNvbW1hbmQnKS5waXBlKFxyXG4gICAgbWFwKChlOiBhbnkpID0+IHsgcmV0dXJuIHsgbmFtZTogZS5kZXRhaWwubmFtZSwgYXJnOiBlLmRldGFpbC5hcmcgfSBhcyBJQ29tbWFuZCB9KSxcclxuICAgIHNoYXJlKCksXHJcbiAgICB0YXAodGhpcy5vbkNvbW1hbmQkKVxyXG4gICk7XHJcbiAgLyoqIEBpZ25vcmUgKi9cclxuICAvLyBwcml2YXRlIG9uQ29uZmlnU3ViOiBTdWJzY3JpcHRpb247XHJcbiAgLy8gLyoqIEBpZ25vcmUgKi9cclxuICAvLyBwcml2YXRlIG9uQ29uZmlnRXZ0JCA9IGZyb21FdmVudCh3aW5kb3csICdSZXZlbERpZ2l0YWwuQ29uZmlnJykucGlwZShcclxuICAvLyAgIHNoYXJlKCksXHJcbiAgLy8gICB0YXAoKGU6IEN1c3RvbUV2ZW50KSA9PiB7XHJcbiAgLy8gICAgIGNvbnNvbGUubG9nKGUpO1xyXG5cclxuICAvLyAgICAgaWYgKGUuZGV0YWlsLnR5cGUgPT09ICdhcHBseUNvbmZpZycgJiYgZS5kZXRhaWwuaXNPcGVuZXIpIHtcclxuICAvLyAgICAgICB0aGlzLmFwcGx5Q29uZmlnKGUuZGV0YWlsLmNvbmZpZyk7IC8vIHByb3BhZ2F0ZSBjb25maWcgdG8gaWZyYW1lIHBhcmVudCBmcm9tIHRoZSBwb3B1cCB3aW5kb3dcclxuICAvLyAgICAgfSBlbHNlIHtcclxuICAvLyAgICAgICB0aGlzLm9uQ29uZmlnJC5uZXh0KGUuZGV0YWlsKTtcclxuICAvLyAgICAgfVxyXG4gIC8vICAgfSlcclxuICAvLyApO1xyXG4gIC8vIHByaXZhdGUgb25Qb3N0TWVzc2FnZVN1YjogU3Vic2NyaXB0aW9uO1xyXG4gIC8vIHByaXZhdGUgb25Qb3N0TWVzc2FnZUV2dCQgPSBmcm9tRXZlbnQod2luZG93LCAnbWVzc2FnZScpLnBpcGUoXHJcbiAgLy8gICBmaWx0ZXIoKG1lc3NhZ2VFdmVudDogTWVzc2FnZUV2ZW50KSA9PlxyXG4gIC8vICAgICBtZXNzYWdlRXZlbnQuc291cmNlICE9PSB3aW5kb3cucGFyZW50ICYmXHJcbiAgLy8gICAgIHR5cGVvZiBtZXNzYWdlRXZlbnQuZGF0YSA9PT0gJ3N0cmluZycgJiZcclxuICAvLyAgICAgbWVzc2FnZUV2ZW50LmRhdGEuc3RhcnRzV2l0aCgncmV2ZWxkaWdpdGFsOicpKSxcclxuICAvLyAgIG1hcCgoZTogYW55KSA9PiB7IHJldHVybiBKU09OLnBhcnNlKGUuc3Vic3RyaW5nKDEzKSkgYXMgQ29tbWFuZCB9KSxcclxuICAvLyAgIHNoYXJlKCksXHJcbiAgLy8gICB0YXAodGhpcy5vbkNvbW1hbmQkKVxyXG4gIC8vICk7XHJcblxyXG4gIHByaXZhdGUgb25Qb3N0TWVzc2FnZVN1YjogU3Vic2NyaXB0aW9uO1xyXG4gIHByaXZhdGUgb25Qb3N0TWVzc2FnZUV2dCQgPSBmcm9tRXZlbnQod2luZG93LCAnbWVzc2FnZScpLnBpcGUoXHJcbiAgICBmaWx0ZXIoKG1lc3NhZ2VFdmVudDogTWVzc2FnZUV2ZW50KSA9PlxyXG4gICAgICAvL21lc3NhZ2VFdmVudC5zb3VyY2UgIT09IHdpbmRvdy5wYXJlbnQgJiZcclxuICAgICAgdHlwZW9mIG1lc3NhZ2VFdmVudC5kYXRhID09PSAnc3RyaW5nJyksXHJcbiAgICBtYXAoKGU6IGFueSkgPT4gSlNPTi5wYXJzZShlLmRhdGEpKSxcclxuICAgIHNoYXJlKCksXHJcbiAgICB0YXAoKGU6IGFueSkgPT4ge1xyXG4gICAgICBpZiAoZS50eXBlID09PSAnYXBwbHlDb25maWcnICYmIGUuaXNPcGVuZXIpIHtcclxuICAgICAgICBlLmlzT3BlbmVyID0gZmFsc2U7XHJcbiAgICAgICAgLy8gcHJvcGFnYXRlIGNvbmZpZyB0byBpZnJhbWUgcGFyZW50IGZyb20gdGhlIHBvcHVwIHdpbmRvd1xyXG4gICAgICAgIHdpbmRvdy5wYXJlbnQucG9zdE1lc3NhZ2UoXHJcbiAgICAgICAgICBKU09OLnN0cmluZ2lmeShlKSxcclxuICAgICAgICAgICcqJ1xyXG4gICAgICAgICk7XHJcbiAgICAgIH0gZWxzZSBpZiAoZS50eXBlID09PSAnb3BlbkNvbmZpZycpIHtcclxuICAgICAgICB0aGlzLm9uQ29uZmlnJC5uZXh0KG51bGwpO1xyXG4gICAgICB9XHJcbiAgICB9KSxcclxuICAgIHRhcChlID0+IHRoaXMub25Qb3N0TWVzc2FnZSQubmV4dChlKSlcclxuICApO1xyXG5cclxuXHJcbiAgLyoqIEBpZ25vcmUgKi9cclxuICBjb25zdHJ1Y3Rvcih6b25lOiBOZ1pvbmUpIHtcclxuXHJcbiAgICBsZXQgc2VsZiA9IHRoaXM7XHJcbiAgICAod2luZG93IGFzIGFueSkuUmV2ZWxEaWdpdGFsID0ge1xyXG4gICAgICBDb250cm9sbGVyOiB7XHJcbiAgICAgICAgb25Db21tYW5kOiBmdW5jdGlvbiAobmFtZTogc3RyaW5nLCBhcmc6IHN0cmluZykge1xyXG4gICAgICAgICAgem9uZS5ydW4oKCkgPT4ge1xyXG4gICAgICAgICAgICBzZWxmLm9uQ29tbWFuZCQubmV4dCh7IG5hbWU6IG5hbWUsIGFyZzogYXJnIH0pO1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfSxcclxuICAgICAgICBvblN0YXJ0OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICB6b25lLnJ1bigoKSA9PiB7XHJcbiAgICAgICAgICAgIHNlbGYub25TdGFydCQubmV4dChudWxsKTtcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0sXHJcbiAgICAgICAgb25TdG9wOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICB6b25lLnJ1bigoKSA9PiB7XHJcbiAgICAgICAgICAgIHNlbGYub25TdG9wJC5uZXh0KG51bGwpO1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5vblN0YXJ0U3ViID0gdGhpcy5vblN0YXJ0RXZ0JC5zdWJzY3JpYmUoKCkgPT4geyB9KTtcclxuICAgIHRoaXMub25TdG9wU3ViID0gdGhpcy5vblN0b3BFdnQkLnN1YnNjcmliZSgoKSA9PiB7IH0pO1xyXG4gICAgdGhpcy5vbkNvbW1hbmRTdWIgPSB0aGlzLm9uQ29tbWFuZEV2dCQuc3Vic2NyaWJlKCgpID0+IHsgfSk7XHJcbiAgICAvL3RoaXMub25Db25maWdTdWIgPSB0aGlzLm9uQ29uZmlnRXZ0JC5zdWJzY3JpYmUoKCkgPT4geyB9KTtcclxuICAgIHRoaXMub25Qb3N0TWVzc2FnZVN1YiA9IHRoaXMub25Qb3N0TWVzc2FnZUV2dCQuc3Vic2NyaWJlKCgpID0+IHsgfSk7XHJcblxyXG4gICAgdGhpcy5jbGllbnRQcm9taXNlID0gbnVsbDtcclxuXHJcbiAgICB0aGlzLm9uUmVhZHkkLm5leHQodHJ1ZSk7XHJcbiAgfVxyXG5cclxuICAvKiogQGlnbm9yZSAqL1xyXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xyXG5cclxuICAgIHRoaXMub25TdGFydFN1Yj8udW5zdWJzY3JpYmUoKTtcclxuICAgIHRoaXMub25TdG9wU3ViPy51bnN1YnNjcmliZSgpO1xyXG4gICAgdGhpcy5vbkNvbW1hbmRTdWI/LnVuc3Vic2NyaWJlKCk7XHJcbiAgICAvL3RoaXMub25Db25maWdTdWI/LnVuc3Vic2NyaWJlKCk7XHJcbiAgICB0aGlzLm9uUG9zdE1lc3NhZ2VTdWI/LnVuc3Vic2NyaWJlKCk7XHJcblxyXG4gICAgdGhpcy5vblJlYWR5JC5uZXh0KGZhbHNlKTtcclxuICB9XHJcblxyXG4gIC8qKiBAaWdub3JlICovXHJcbiAgcHVibGljIHN0YXRpYyBpbml0KGRhdGE6IGFueSkge1xyXG5cclxuICAgIGNvbnNvbGUubG9nKFxyXG4gICAgICAnJWPimpnvuI8gSW5pdGlhbGl6aW5nIFJldmVsIERpZ2l0YWwgY2xpZW50IGxpYnJhcnknLFxyXG4gICAgICAnYmFja2dyb3VuZC1jb2xvcjpibHVlOyBjb2xvcjp5ZWxsb3c7J1xyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFRoaXMgbWV0aG9kIGFsbG93cyB0aGUgZ2FkZ2V0IHRvIGNvbW11bmljYXRlIHdpdGggcGxheWVyIHNjcmlwdGluZy5cclxuICAgKiBJZiB0aGUgYXBwcm9wcmlhdGUgc2NyaXB0aW5nIGlzIGluIHBsYWNlIGluIHRoZSBjdXJyZW50bHkgcnVubmluZyB0ZW1wbGF0ZSwgY2FsbGluZyB0aGlzIG1ldGhvZFxyXG4gICAqIHdpbGwgaW5pdGlhdGUgYSBjYWxsYmFjayB3aGljaCBjYW4gYmUgYWN0ZWQgdXBvbiBpbiBwbGF5ZXIgc2NyaXB0LlxyXG4gICAqIFxyXG4gICAqIEBleGFtcGxlXHJcbiAgICogY2xpZW50LmNhbGxiYWNrKCd0ZXN0JywgJ3RoaXMnKTtcclxuICAgKiBcclxuICAgKiBAcGFyYW0gYXJncyB2YXJpYWJsZSBudW1iZXIgb2YgYXJndW1lbnRzXHJcbiAgICovXHJcbiAgcHVibGljIGNhbGxiYWNrKC4uLmFyZ3M6IGFueVtdKTogdm9pZCB7XHJcblxyXG4gICAgdGhpcy5nZXRDbGllbnQoKS50aGVuKChjbGllbnQpID0+IHtcclxuXHJcbiAgICAgIHN3aXRjaCAoYXJncy5sZW5ndGgpIHtcclxuICAgICAgICBjYXNlIDA6XHJcbiAgICAgICAgICBjbGllbnQuY2FsbGJhY2soKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGNhc2UgMTpcclxuICAgICAgICAgIGNsaWVudC5jYWxsYmFjayhhcmdzWzBdKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGNhc2UgMjpcclxuICAgICAgICAgIGNsaWVudC5jYWxsYmFjayhhcmdzWzFdKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGNhc2UgMzpcclxuICAgICAgICAgIGNsaWVudC5jYWxsYmFjayhhcmdzWzJdKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGNhc2UgNDpcclxuICAgICAgICAgIGNsaWVudC5jYWxsYmFjayhhcmdzWzNdKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGNhc2UgNTpcclxuICAgICAgICAgIGNsaWVudC5jYWxsYmFjayhhcmdzWzRdKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICB9XHJcbiAgICB9KVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQWNjZXNzb3IgbWV0aG9kIGZvciB0aGUgdXNlciBwcmVmZXJlbmNlcyBpbnRlcmZhY2UgZXhwb3NlZCBieSB0aGUgR2FkZ2V0cyBBUEkuXHJcbiAgICogXHJcbiAgICogU2VlIHtAbGluayBodHRwczovL2RldmVsb3BlcnMuZ29vZ2xlLmNvbS9nYWRnZXRzL2RvY3MvYmFzaWN9IGZvciBtb3JlIGRldGFpbHMgb24gdGhlIEdhZGdldHMgQVBJLlxyXG4gICAqIFxyXG4gICAqIEBleGFtcGxlXHJcbiAgICogY29uc3RydWN0b3IocHVibGljIGNsaWVudDogUGxheWVyQ2xpZW50U2VydmljZSkge1xyXG4gICAqICAgICAgICAgICAgbGV0IHByZWZzID0gY2xpZW50LmdldFByZWZzKCk7XHJcbiAgICogICAgICAgICAgICBsZXQgbXlTdHJpbmcgPSBwcmVmcy5nZXRTdHJpbmcoJ215U3RyaW5nUHJlZicpO1xyXG4gICAqIH1cclxuICAgKiBAcmV0dXJucyB7Z2FkZ2V0cy5QcmVmc30gR2FkZ2V0IEFQSSBQcmVmcyBvYmplY3RcclxuICAgKi9cclxuICBwdWJsaWMgZ2V0UHJlZnMoKTogZ2FkZ2V0cy5QcmVmcyB7XHJcblxyXG4gICAgcmV0dXJuIG5ldyB3aW5kb3dbJ2dhZGdldHMnXVsnUHJlZnMnXSgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmV0dXJucyB0aGUgY3VycmVudCBkZXZpY2UgdGltZSBpbiBJU084NjAxIGZvcm1hdC5cclxuICAgKiBDdXJyZW50IGRldmljZSB0aW1lIGlzIGRldGVybWluZWQgYnkgdGhlIGRldmljZSB0aW1lem9uZSBhc3NpZ25lZCB0byB0aGUgZGV2aWNlIGluIHRoZSBDTVMuXHJcbiAgICogXHJcbiAgICogQHBhcmFtIGRhdGUgT3B0aW9uYWwuIElmIHN1cHBsaWVkIHdpbGwgdHJhbnNsYXRlIHRoZSBzdXBwbGllZCBkYXRlL3RpbWUgdG8gZGV2aWNlIHRpbWUgYmFzZWQgb24gcmVzcGVjdGl2ZSB0aW1lem9uZXMuXHJcbiAgICogQHJldHVybnMgRGF0ZS90aW1lIGluIElTTzg2MDEgZm9ybWF0XHJcbiAgICovXHJcbiAgcHVibGljIGFzeW5jIGdldERldmljZVRpbWUoZGF0ZT86IERhdGUpOiBQcm9taXNlPHN0cmluZz4ge1xyXG5cclxuICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMuZ2V0Q2xpZW50KCk7XHJcblxyXG4gICAgaWYgKGRhdGUgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICByZXR1cm4gY2xpZW50LmdldERldmljZVRpbWUoZGF0ZSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gY2xpZW50LmdldERldmljZVRpbWUoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJldHVybnMgdGhlIHRpbWV6b25lIG5hbWUgY3VycmVudGx5IGFzc2lnbmVkIHRvIHRoZSBkZXZpY2UuXHJcbiAgICogXHJcbiAgICogQHJldHVybnMgVGltZXpvbmUgTmFtZVxyXG4gICAqL1xyXG4gIHB1YmxpYyBhc3luYyBnZXREZXZpY2VUaW1lWm9uZU5hbWUoKTogUHJvbWlzZTxzdHJpbmc+IHtcclxuXHJcbiAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldENsaWVudCgpO1xyXG5cclxuICAgIHJldHVybiBjbGllbnQuZ2V0RGV2aWNlVGltZVpvbmVOYW1lKCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZXR1cm5zIHRoZSB0aW1lem9uZSBJRCBjdXJyZW50bHkgYXNzaWduZWQgdG8gdGhlIGRldmljZS5cclxuICAgKiBcclxuICAgKiBAcmV0dXJucyBUaW1lem9uZSBJRFxyXG4gICAqL1xyXG4gIHB1YmxpYyBhc3luYyBnZXREZXZpY2VUaW1lWm9uZUlEKCk6IFByb21pc2U8c3RyaW5nPiB7XHJcblxyXG4gICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKTtcclxuXHJcbiAgICByZXR1cm4gY2xpZW50LmdldERldmljZVRpbWVab25lSUQoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJldHVybnMgdGhlIG51bWVyaWNhbCBvZmZzZXQgZnJvbSBHTVQgb2YgdGhlIHRpbWV6b25lIGN1cnJlbnRseSBhc3NpZ25lZCB0byB0aGUgZGV2aWNlLlxyXG4gICAqIFxyXG4gICAqIEByZXR1cm5zIFRpbWV6b25lIG9mZnNldFxyXG4gICAqL1xyXG4gIHB1YmxpYyBhc3luYyBnZXREZXZpY2VUaW1lWm9uZU9mZnNldCgpOiBQcm9taXNlPG51bWJlcj4ge1xyXG5cclxuICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMuZ2V0Q2xpZW50KCk7XHJcblxyXG4gICAgcmV0dXJuIGNsaWVudC5nZXREZXZpY2VUaW1lWm9uZU9mZnNldCgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmV0dXJucyB0aGUgbGFuZ3VhZ2UgY29kZSBvZiB0aGUgbGFuZ3VhZ2UgY3VycmVudGx5IGFzc2lnbmVkIHRvIHRoZSBkZXZpY2UuXHJcbiAgICogXHJcbiAgICogQHJldHVybnMgTGFuZ3VhZ2UgY29kZVxyXG4gICAqL1xyXG4gIHB1YmxpYyBhc3luYyBnZXRMYW5ndWFnZUNvZGUoKTogUHJvbWlzZTxzdHJpbmc+IHtcclxuXHJcbiAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldENsaWVudCgpO1xyXG5cclxuICAgIHJldHVybiBjbGllbnQuZ2V0TGFuZ3VhZ2VDb2RlKCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZXR1cm5zIHRoZSB1bmlxdWUgUmV2ZWwgRGlnaXRhbCBkZXZpY2Uga2V5IGFzc29jaWF0ZWQgd2l0aCB0aGUgZGV2aWNlLlxyXG4gICAqIFxyXG4gICAqIEByZXR1cm5zIERldmljZSBrZXlcclxuICAgKi9cclxuICBwdWJsaWMgYXN5bmMgZ2V0RGV2aWNlS2V5KCk6IFByb21pc2U8c3RyaW5nPiB7XHJcblxyXG4gICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKTtcclxuXHJcbiAgICByZXR1cm4gY2xpZW50LmdldERldmljZUtleSgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2VuZCBhIGNvbW1hbmQgdG8gdGhlIHBsYXllciBkZXZpY2UuXHJcbiAgICogXHJcbiAgICogQHBhcmFtIG5hbWUgQ29tbWFuZCBuYW1lXHJcbiAgICogQHBhcmFtIGFyZyBDb21tYW5kIGFyZ3VtZW50XHJcbiAgICovXHJcbiAgcHVibGljIHNlbmRDb21tYW5kKG5hbWU6IHN0cmluZywgYXJnOiBzdHJpbmcpOiB2b2lkIHtcclxuXHJcbiAgICB0aGlzLmdldENsaWVudCgpLnRoZW4oKGNsaWVudCkgPT4ge1xyXG4gICAgICBjbGllbnQuc2VuZENvbW1hbmQobmFtZSwgYXJnKTtcclxuICAgIH0pXHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTZW5kIGEgY29tbWFuZCB0byBhbnkgcmVtb3RlIHBsYXllciB3aXRoIHRoZSBzdXBwbGllZCBkZXZpY2Uga2V5KHMpLlxyXG4gICAqIE5vdGU6IFJlbW90ZSBjb21tYW5kcyBjYW4gb25seSBiZSBkZWxpdmVyZWQgdG8gZGV2aWNlcyB3aXRoaW4gdGhlIHNhbWUgYWNjb3VudCBhcyB0aGUgc2VuZGVyIGRldmljZS5cclxuICAgKiBcclxuICAgKiBAcGFyYW0gZGV2aWNlS2V5cyBBcnJheSBvZiByZW1vdGUgZGV2aWNlIGtleXNcclxuICAgKiBAcGFyYW0gbmFtZSBDb21tYW5kIG5hbWVcclxuICAgKiBAcGFyYW0gYXJnIENvbW1hbmQgYXJnXHJcbiAgICovXHJcbiAgcHVibGljIHNlbmRSZW1vdGVDb21tYW5kKGRldmljZUtleXM6IHN0cmluZ1tdLCBuYW1lOiBzdHJpbmcsIGFyZzogc3RyaW5nKTogdm9pZCB7XHJcblxyXG4gICAgdGhpcy5nZXRDbGllbnQoKS50aGVuKChjbGllbnQpID0+IHtcclxuICAgICAgY2xpZW50LnNlbmRSZW1vdGVDb21tYW5kKGRldmljZUtleXMsIG5hbWUsIGFyZyk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIExvZyBhbiBldmVudCBmb3IgdXNlIHdpdGggQWRIYXdrIGFuYWx5dGljcy5cclxuICAgKiBFdmVudHMgYXJlIHVzZWQgZm9yIHRyYWNraW5nIHZhcmlvdXMgbWV0cmljcyBpbmNsdWRpbmcgdXNhZ2Ugc3RhdGlzdGljcywgcGxheWVyIGNvbmRpdGlvbiwgc3RhdGUgY2hhbmdlcywgZXRjLlxyXG4gICAqIFxyXG4gICAqIEBwYXJhbSBldmVudE5hbWUgVW5pcXVlIG5hbWUgZm9yIHRoaXMgZXZlbnRcclxuICAgKiBAcGFyYW0gcHJvcGVydGllcyBBIG1hcCBvZiB1c2VyIGRlZmluZWQgcHJvcGVydGllcyB0byBhc3NvY2lhdGUgd2l0aCB0aGlzIGV2ZW50XHJcbiAgICovXHJcbiAgcHVibGljIHRyYWNrKGV2ZW50TmFtZTogc3RyaW5nLCBwcm9wZXJ0aWVzPzogSUV2ZW50UHJvcGVydGllcyk6IHZvaWQge1xyXG5cclxuICAgIHRoaXMuZ2V0Q2xpZW50KCkudGhlbigoY2xpZW50KSA9PiB7XHJcbiAgICAgIGNsaWVudC50cmFjayhldmVudE5hbWUsIEpTT04uc3RyaW5naWZ5KHByb3BlcnRpZXMpKTtcclxuICAgIH0pXHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBNZXRob2QgZm9yIGluaXRpYXRpbmcgYSB0aW1lZCBldmVudC5cclxuICAgKiBUaW1lZCBldmVudHMgYXJlIHVzZWZ1bCBmb3IgdHJhY2tpbmcgdGhlIGR1cmF0aW9uIG9mIGFuIGV2ZW50IGFuZCBtdXN0IGJlIHByb2NlZWRlZCB3aXRoIGEgY2FsbCB0byB0cmFjaygpLlxyXG4gICAqIFxyXG4gICAqIEBleGFtcGxlXHJcbiAgICogY2xpZW50LnRpbWVFdmVudCgndGVzdEV2ZW50Jyk7XHJcbiAgICogY2xpZW50LnRyYWNrKFwidGVzdFwiLCB7IFwiYVwiOiBcImJcIiB9KTtcclxuICAgKiBAcGFyYW0gZXZlbnROYW1lIFVuaXF1ZSBuYW1lIGZvciB0aGlzIGV2ZW50XHJcbiAgICovXHJcbiAgcHVibGljIHRpbWVFdmVudChldmVudE5hbWU6IHN0cmluZyk6IHZvaWQge1xyXG5cclxuICAgIHRoaXMuZ2V0Q2xpZW50KCkudGhlbigoY2xpZW50KSA9PiB7XHJcbiAgICAgIGNsaWVudC50aW1lRXZlbnQoZXZlbnROYW1lKTtcclxuICAgIH0pXHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBBIHNlc3Npb24gaXMgYSB3YXkgb2YgZ3JvdXBpbmcgZXZlbnRzIHRvZ2V0aGVyLiBFYWNoIGV2ZW50IGhhcyBhbiBhc3NvY2lhdGVkIHNlc3Npb24gSUQuXHJcbiAgICogU2Vzc2lvbiBJRCdzIGFyZSByYW5kb21seSBnZW5lcmF0ZWQgYW5kIHJlc2V0IGJ5IHN1YnNlcXVlbnQgY2FsbHMgdG8gbmV3RXZlbnRTZXNzaW9uKCkuXHJcbiAgICogXHJcbiAgICogRWFjaCBjYWxsIHRvIHRyYWNrKCkgd2lsbCB1dGlsaXplIHRoZSBzYW1lIHNlc3Npb24gSUQsIHVudGlsIGFub3RoZXIgY2FsbCB0byBuZXdFdmVudFNlc3Npb24oKS5cclxuICAgKiBAcGFyYW0gaWQgT3B0aW9uYWwuIFVzZXIgc3VwcGxpZWQgc2Vzc2lvbiBJRC4gSWYgbm90IHN1cHBsaWVkIGEgcmFuZG9tIHNlc3Npb24gSUQgd2lsbCBiZSBnZW5lcmF0ZWQuXHJcbiAgICovXHJcbiAgcHVibGljIG5ld0V2ZW50U2Vzc2lvbihpZD86IHN0cmluZyk6IHZvaWQge1xyXG5cclxuICAgIHRoaXMuZ2V0Q2xpZW50KCkudGhlbigoY2xpZW50KSA9PiB7XHJcbiAgICAgIGlmIChpZCAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgY2xpZW50Lm5ld0V2ZW50U2Vzc2lvbigpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGNsaWVudC5uZXdFdmVudFNlc3Npb24oaWQpO1xyXG4gICAgICB9XHJcbiAgICB9KVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmV0dXJucyB0aGUgcm9vdCBmb2xkZXIgdXRpbGl6ZWQgYnkgdGhpcyBwbGF5ZXIgZGV2aWNlLlxyXG4gICAqIFxyXG4gICAqIEByZXR1cm5zIFBhdGggdG8gdGhlIHJvb3QgZm9sZGVyXHJcbiAgICovXHJcbiAgcHVibGljIGFzeW5jIGdldFJldmVsUm9vdCgpOiBQcm9taXNlPHN0cmluZz4ge1xyXG5cclxuICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMuZ2V0Q2xpZW50KCk7XHJcblxyXG4gICAgcmV0dXJuIGNsaWVudC5nZXRSZXZlbFJvb3QoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJldHVybnMgYSBtYXAgb2YgY29tbWFuZHMgY3VycmVudGx5IGFjdGl2ZSBmb3IgdGhpcyBkZXZpY2UuXHJcbiAgICogXHJcbiAgICogQHJldHVybnMgTWFwIG9mIGNvbW1hbmRzIGN1cnJlbnRseSBhY3RpdmUgZm9yIHRoaXMgZGV2aWNlLlxyXG4gICAqL1xyXG4gIHB1YmxpYyBhc3luYyBnZXRDb21tYW5kTWFwKCk6IFByb21pc2U8YW55PiB7XHJcblxyXG4gICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKTtcclxuXHJcbiAgICByZXR1cm4gSlNPTi5wYXJzZShhd2FpdCBjbGllbnQuZ2V0Q29tbWFuZE1hcCgpKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEluZGljYXRlIHRvIHRoZSBwbGF5ZXIgdGhhdCB0aGlzIGdhZGdldCBoYXMgZmluaXNoZWQgaXQncyB2aXN1YWxpemF0aW9uLlxyXG4gICAqIFRoaXMgYWxsb3dzIHRoZSBwbGF5ZXIgdG8gcHJvY2VlZCB3aXRoIHRoZSBuZXh0IGl0ZW0gaW4gYSBwbGF5bGlzdCBpZiBhcHBsaWNhYmxlLlxyXG4gICAqL1xyXG4gIHB1YmxpYyBmaW5pc2goKTogdm9pZCB7XHJcblxyXG4gICAgdGhpcy5nZXRDbGllbnQoKS50aGVuKChjbGllbnQpID0+IHtcclxuXHJcbiAgICAgIGNsaWVudC5maW5pc2goKTtcclxuICAgIH0pXHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDaGVjayBpcyB0aGUgZ2FkZ2V0IGlzIHJ1bm5pbmcgaW4gcHJldmlldyBtb2RlLiBQcmV2aWV3IG1vZGUgaXMgZW5hYmxlZCB3aGVuIHRoZSBnYWRnZXQgaXNcclxuICAgKiBiZWluZyBlZGl0ZWQgaW4gdGhlIENNUywgb3Igb3RoZXJ3aXNlIG5vdCBydW5uaW5nIGluIGEgbm9ybWFsIHBsYXllciBlbnZpcm9ubWVudC5cclxuICAgKiBcclxuICAgKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBnYWRnZXQgaXMgcnVubmluZyBpbiBwcmV2aWV3IG1vZGUsIGZhbHNlIG90aGVyd2lzZS5cclxuICAgKi9cclxuICBwdWJsaWMgYXN5bmMgaXNQcmV2aWV3TW9kZSgpOiBQcm9taXNlPGJvb2xlYW4+IHtcclxuXHJcbiAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldENsaWVudCgpO1xyXG5cclxuICAgIHJldHVybiBjbGllbnQgaW5zdGFuY2VvZiBOb29wQ2xpZW50O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAqIFJldHVybnMgdGhlIGRldmljZSBkZXRhaWxzIGFzc29jaWF0ZWQgd2l0aCB0aGUgcGxheWVyIHJ1bm5pbmcgdGhlIGdhZGdldCBvciB3ZWIgYXBwLlxyXG4gKiBcclxuICogQHJldHVybnMgRGV2aWNlIGRldGFpbHMuXHJcbiAqL1xyXG4gIHB1YmxpYyBhc3luYyBnZXREZXZpY2UoKTogUHJvbWlzZTxJRGV2aWNlIHwgbnVsbD4ge1xyXG5cclxuICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMuZ2V0Q2xpZW50KCk7XHJcblxyXG4gICAgbGV0IG9iajogYW55ID0gSlNPTi5wYXJzZSg8c3RyaW5nPmF3YWl0IGNsaWVudC5nZXREZXZpY2UoKSk7XHJcblxyXG4gICAgY29uc3QgZGV2aWNlOiBJRGV2aWNlW10gPSBbb2JqXS5tYXAoKGRldmljZTogYW55KSA9PiB7XHJcblxyXG4gICAgICByZXR1cm4ge1xyXG4gICAgICAgIG5hbWU6IGRldmljZS5uYW1lLFxyXG4gICAgICAgIHJlZ2lzdHJhdGlvbktleTogZGV2aWNlLmtleSxcclxuICAgICAgICBkZXZpY2VUeXBlOiBkZXZpY2UuZGV2aWNldHlwZSxcclxuICAgICAgICBlbnRlcmVkU2VydmljZTogbmV3IERhdGUoZGV2aWNlLmVudGVyZWRzZXJ2aWNlKSxcclxuICAgICAgICBsYW5nQ29kZTogZGV2aWNlLmxhbmdjb2RlLFxyXG4gICAgICAgIHRpbWVab25lOiBkZXZpY2UudGltZXpvbmUsXHJcbiAgICAgICAgdGFnczogZGV2aWNlLmRlc2NyaXB0aW9uPy5zcGxpdCgnXFxuJyksXHJcbiAgICAgICAgbG9jYXRpb246IHtcclxuICAgICAgICAgIGNpdHk6IGRldmljZS5sb2NhdGlvbj8uY2l0eSxcclxuICAgICAgICAgIHN0YXRlOiBkZXZpY2UubG9jYXRpb24/LnN0YXRlLFxyXG4gICAgICAgICAgY291bnRyeTogZGV2aWNlLmxvY2F0aW9uPy5jb3VudHJ5LFxyXG4gICAgICAgICAgcG9zdGFsQ29kZTogZGV2aWNlLmxvY2F0aW9uPy5wb3N0YWxjb2RlLFxyXG4gICAgICAgICAgYWRkcmVzczogZGV2aWNlLmxvY2F0aW9uPy5hZGRyZXNzLFxyXG4gICAgICAgICAgbGF0aXR1ZGU6IGRldmljZS5sb2NhdGlvbj8ubGF0aXR1ZGUsXHJcbiAgICAgICAgICBsb25naXR1ZGU6IGRldmljZS5sb2NhdGlvbj8ubG9uZ2l0dWRlXHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICAgIHJldHVybiBkZXZpY2VbMF07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZXR1cm5zIHRoZSB3aWR0aCBvZiB0aGUgdmlzdWFsaXphdGlvbiBhcmVhLlxyXG4gICAqIFxyXG4gICAqIEByZXR1cm5zIFdpZHRoIG9mIHRoZSB2aXN1YWxpemF0aW9uIGFyZWFcclxuICAgKi9cclxuICBwdWJsaWMgYXN5bmMgZ2V0V2lkdGgoKTogUHJvbWlzZTxudW1iZXIgfCBudWxsPiB7XHJcblxyXG4gICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKTtcclxuXHJcbiAgICByZXR1cm4gY2xpZW50LmdldFdpZHRoKCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZXR1cm5zIHRoZSBoZWlnaHQgb2YgdGhlIHZpc3VhbGl6YXRpb24gYXJlYS5cclxuICAgKiBcclxuICAgKiBAcmV0dXJucyBIZWlnaHQgb2YgdGhlIHZpc3VhbGl6YXRpb24gYXJlYVxyXG4gICAqL1xyXG4gIHB1YmxpYyBhc3luYyBnZXRIZWlnaHQoKTogUHJvbWlzZTxudW1iZXIgfCBudWxsPiB7XHJcblxyXG4gICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKTtcclxuXHJcbiAgICByZXR1cm4gY2xpZW50LmdldEhlaWdodCgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmV0dXJucyB0aGUgZHVyYXRpb24gb2YgdGhlIGN1cnJlbnRseSBwbGF5aW5nIHNvdXJjZS5cclxuICAgKiAob25seSBhcHBsaWNhYmxlIHdoZW4gYXNzb2NpYXRlZCB3aXRoIGEgcGxheWxpc3QpXHJcbiAgICogXHJcbiAgICogQHJldHVybnMgRHVyYXRpb24gb2YgdGhlIGN1cnJlbnQgaXRlbSBpbiBtaWxsaXNlY29uZHNcclxuICAgKi9cclxuICBwdWJsaWMgYXN5bmMgZ2V0RHVyYXRpb24oKTogUHJvbWlzZTxudW1iZXIgfCBudWxsPiB7XHJcblxyXG4gICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKTtcclxuXHJcbiAgICByZXR1cm4gY2xpZW50LmdldER1cmF0aW9uKCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IFNESyB2ZXJzaW9uLlxyXG4gICAqIFxyXG4gICAqIEByZXR1cm5zIFNESyB2ZXJzaW9uXHJcbiAgICovXHJcbiAgcHVibGljIGFzeW5jIGdldFNka1ZlcnNpb24oKTogUHJvbWlzZTxzdHJpbmc+IHtcclxuXHJcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHZlcnNpb24pO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGFzeW5jIGFwcGx5Q29uZmlnKHByZWZzOiBJRGljdGlvbmFyeTxhbnk+KSB7XHJcblxyXG4gICAgaWYgKGF3YWl0IHRoaXMuaXNQcmV2aWV3TW9kZSgpKSB7XHJcbiAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMuZ2V0Q2xpZW50KCk7XHJcbiAgICAgIGNsaWVudC5hcHBseUNvbmZpZyhwcmVmcyk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBjb25zb2xlLmxvZyhcclxuICAgICAgICAnJWNhcHBseUNvbmZpZygpIGlzIG9ubHkgYXZhaWxhYmxlIGluIHByZXZpZXcgbW9kZS4nLFxyXG4gICAgICAgICdiYWNrZ3JvdW5kLWNvbG9yOmJsdWU7IGNvbG9yOnllbGxvdzsnXHJcbiAgICAgICk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLyAtLS1cclxuICAvLyBQUklWQVRFIE1FVEhPRFMuXHJcbiAgLy8gLS0tXHJcbiAgLyoqIEBpZ25vcmUgKi9cclxuICBwcml2YXRlIGdldENsaWVudCgpOiBQcm9taXNlPElDbGllbnQ+IHtcclxuXHJcbiAgICBpZiAodGhpcy5jbGllbnRQcm9taXNlKSB7XHJcblxyXG4gICAgICByZXR1cm4gKHRoaXMuY2xpZW50UHJvbWlzZSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHdpbmRvdy5DbGllbnQpIHtcclxuXHJcbiAgICAgIHJldHVybiAodGhpcy5jbGllbnRQcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKHdpbmRvdy5DbGllbnQpKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBBIFwiY29tcGxldGVcIiBzdGF0dXMgaW5kaWNhdGVzIHRoYXQgdGhlIFwibG9hZFwiIGV2ZW50IGhhcyBiZWVuIGZpcmVkIG9uIHRoZVxyXG4gICAgLy8gd2luZG93OyBhbmQsIHRoYXQgYWxsIHN1Yi1yZXNvdXJjZXMgc3VjaCBhcyBTY3JpcHRzLCBJbWFnZXMsIGFuZCBGcmFtZXMgaGF2ZVxyXG4gICAgLy8gYmVlbiBsb2FkZWQuXHJcbiAgICBpZiAod2luZG93LmRvY3VtZW50LnJlYWR5U3RhdGUgPT09IFwiY29tcGxldGVcIikge1xyXG5cclxuICAgICAgLy8gSWYgdGhpcyBldmVudCBoYXMgZmlyZWQgQU5EIHRoZSAzcmQtcGFydHkgc2NyaXB0IGlzbid0IGF2YWlsYWJsZSAoc2VlIElGLVxyXG4gICAgICAvLyBjb25kaXRpb24gQkVGT1JFIHRoaXMgb25lKSwgaXQgbWVhbnMgdGhhdCB0aGUgM3JkLXBhcnR5IHNjcmlwdCBlaXRoZXJcclxuICAgICAgLy8gZmFpbGVkIG9uIHRoZSBuZXR3b3JrIG9yIHdhcyBCTE9DS0VEIGJ5IGFuIGFkLWJsb2NrZXIuIEFzIHN1Y2gsIHdlIGhhdmUgdG9cclxuICAgICAgLy8gZmFsbC1iYWNrIHRvIHVzaW5nIGEgbW9jayBBUEkuXHJcbiAgICAgIHJldHVybiAodGhpcy5jbGllbnRQcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKG5ldyBOb29wQ2xpZW50KCkpKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBBU1NFUlQ6IElmIHdlIG1hZGUgaXQgdGhpcyBmYXIsIHRoZSBkb2N1bWVudCBoYXMgbm90IGNvbXBsZXRlZCBsb2FkaW5nIChidXQgaXRcclxuICAgIC8vIG1heSBiZSBpbiBhbiBcImludGVyYWN0aXZlXCIgc3RhdGUgd2hpY2ggaXMgd2hlbiBJIGJlbGlldmUgdGhhdCB0aGUgQW5ndWxhciBhcHBcclxuICAgIC8vIGdldHMgYm9vdHN0cmFwcGVkKS4gQXMgc3VjaCwgd2UgbmVlZCBiaW5kIHRvIHRoZSBMT0FEIGV2ZW50IHRvIHdhaXQgZm9yIG91clxyXG4gICAgLy8gdGhpcmQtcGFydHkgc2NyaXB0cyB0byBsb2FkIChvciBmYWlsIHRvIGxvYWQsIG9yIGJlIGJsb2NrZWQpLlxyXG4gICAgdGhpcy5jbGllbnRQcm9taXNlID0gbmV3IFByb21pc2U8SUNsaWVudD4oXHJcbiAgICAgIChyZXNvbHZlKSA9PiB7XHJcblxyXG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFxyXG4gICAgICAgICAgXCJsb2FkXCIsXHJcbiAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVXaW5kb3dMb2FkKCkge1xyXG5cclxuICAgICAgICAgICAgLy8gQXQgdGhpcyBwb2ludCwgdGhlIDNyZC1wYXJ0eSBsaWJyYXJ5IGlzIGVpdGhlciBhdmFpbGFibGUgb3JcclxuICAgICAgICAgICAgLy8gaXQncyBub3QgLSB0aGVyZSdzIG5vIGZ1cnRoZXIgbG9hZGluZyB0byBkby4gSWYgaXQncyBub3RcclxuICAgICAgICAgICAgLy8gcHJlc2VudCBvbiB0aGUgZ2xvYmFsIHNjb3BlLCB3ZSdyZSBnb2luZyB0byBmYWxsLWJhY2sgdG8gdXNpbmdcclxuICAgICAgICAgICAgLy8gYSBtb2NrIEFQSS5cclxuICAgICAgICAgICAgcmVzb2x2ZSh3aW5kb3cuQ2xpZW50IHx8IG5ldyBOb29wQ2xpZW50KCkpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICk7XHJcblxyXG4gICAgICB9XHJcbiAgICApO1xyXG5cclxuICAgIHJldHVybiAodGhpcy5jbGllbnRQcm9taXNlKTtcclxuICB9XHJcbn1cclxuXHJcblxyXG5cclxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cclxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cclxuXHJcbi8vIEkgcHJvdmlkZSBhIG1vY2sgQVBJIGZvciB0aGUgM3JkLXBhcnR5IHNjcmlwdC4gVGhpcyBqdXN0IGFsbG93cyB0aGUgY29uc3VtaW5nIGNvZGUgdG9cclxuLy8gYWN0IGFzIHRob3VnaCB0aGUgbGlicmFyeSBpcyBhdmFpbGFibGUgZXZlbiBpZiBpdCBmYWlsZWQgdG8gbG9hZCAoZXhhbXBsZSwgaXQgd2FzXHJcbi8vIGJsb2NrZWQgYnkgYW4gYWQtYmxvY2tlcikuXHJcblxyXG4vKiogQGlnbm9yZSAqL1xyXG5jbGFzcyBOb29wQ2xpZW50IGltcGxlbWVudHMgSUNsaWVudCB7XHJcblxyXG4gIGNvbnN0cnVjdG9yKCkge1xyXG5cclxuICAgIGNvbnNvbGUubG9nKFxyXG4gICAgICAnJWNDbGllbnQgQVBJIG5vdCBhdmFpbGFibGUsIGZhbGxpbmcgYmFjayB0byBtb2NrIEFQSScsXHJcbiAgICAgICdiYWNrZ3JvdW5kLWNvbG9yOmJsdWU7IGNvbG9yOnllbGxvdzsnXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGNhbGxiYWNrKC4uLmFyZ3M6IGFueVtdKTogdm9pZCB7XHJcblxyXG4gICAgLy8gTk9PUCBpbXBsZW1lbnQsIG5vdGhpbmcgdG8gZG8uLi4uXHJcbiAgfVxyXG5cclxuICBwdWJsaWMgZ2V0RGV2aWNlVGltZShkYXRlPzogRGF0ZSk6IFByb21pc2U8c3RyaW5nPiB7XHJcblxyXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCkpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGFzeW5jIGdldERldmljZVRpbWVab25lTmFtZSgpOiBQcm9taXNlPHN0cmluZz4ge1xyXG5cclxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobnVsbCk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgZ2V0RGV2aWNlVGltZVpvbmVJRCgpOiBQcm9taXNlPHN0cmluZz4ge1xyXG5cclxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobnVsbCk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgZ2V0RGV2aWNlVGltZVpvbmVPZmZzZXQoKTogUHJvbWlzZTxudW1iZXI+IHtcclxuXHJcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG51bGwpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGFzeW5jIGdldExhbmd1YWdlQ29kZSgpOiBQcm9taXNlPHN0cmluZz4ge1xyXG5cclxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobnVsbCk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgZ2V0RGV2aWNlS2V5KCk6IFByb21pc2U8c3RyaW5nPiB7XHJcblxyXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShudWxsKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBzZW5kQ29tbWFuZChuYW1lOiBzdHJpbmcsIGFyZzogc3RyaW5nKTogdm9pZCB7XHJcblxyXG4gICAgLy8gTk9PUCBpbXBsZW1lbnQsIG5vdGhpbmcgdG8gZG8uLi4uXHJcbiAgfVxyXG5cclxuICBwdWJsaWMgc2VuZFJlbW90ZUNvbW1hbmQoZGV2aWNlS2V5czogc3RyaW5nW10sIG5hbWU6IHN0cmluZywgYXJnOiBzdHJpbmcpIHtcclxuXHJcbiAgICAvLyBOT09QIGltcGxlbWVudCwgbm90aGluZyB0byBkby4uLi5cclxuICB9XHJcblxyXG4gIHB1YmxpYyB0cmFjayhldmVudE5hbWU6IHN0cmluZywgcHJvcGVydGllcz86IHN0cmluZyk6IHZvaWQge1xyXG5cclxuICAgIC8vIE5PT1AgaW1wbGVtZW50LCBub3RoaW5nIHRvIGRvLi4uLlxyXG4gIH1cclxuXHJcbiAgcHVibGljIHRpbWVFdmVudChldmVudE5hbWU6IHN0cmluZyk6IHZvaWQge1xyXG5cclxuICAgIC8vIE5PT1AgaW1wbGVtZW50LCBub3RoaW5nIHRvIGRvLi4uLlxyXG4gIH1cclxuXHJcbiAgcHVibGljIG5ld0V2ZW50U2Vzc2lvbihpZD86IHN0cmluZyk6IHZvaWQge1xyXG5cclxuICAgIC8vIE5PT1AgaW1wbGVtZW50LCBub3RoaW5nIHRvIGRvLi4uLlxyXG4gIH1cclxuXHJcbiAgcHVibGljIGFzeW5jIGdldFJldmVsUm9vdCgpOiBQcm9taXNlPHN0cmluZz4ge1xyXG5cclxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobnVsbCk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgZ2V0Q29tbWFuZE1hcCgpOiBQcm9taXNlPHN0cmluZz4ge1xyXG5cclxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoJ3t9Jyk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgZmluaXNoKCk6IHZvaWQge1xyXG5cclxuICAgIC8vIE5PT1AgaW1wbGVtZW50LCBub3RoaW5nIHRvIGRvLi4uLlxyXG4gIH1cclxuXHJcbiAgcHVibGljIGFzeW5jIGdldERldmljZSgpOiBQcm9taXNlPHN0cmluZyB8IG51bGw+IHtcclxuXHJcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG51bGwpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGFzeW5jIGdldFdpZHRoKCk6IFByb21pc2U8bnVtYmVyIHwgbnVsbD4ge1xyXG5cclxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobnVsbCk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgZ2V0SGVpZ2h0KCk6IFByb21pc2U8bnVtYmVyIHwgbnVsbD4ge1xyXG5cclxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobnVsbCk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgZ2V0RHVyYXRpb24oKTogUHJvbWlzZTxudW1iZXIgfCBudWxsPiB7XHJcblxyXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShudWxsKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBhc3luYyBnZXRTZGtWZXJzaW9uKCk6IFByb21pc2U8c3RyaW5nPiB7XHJcblxyXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh2ZXJzaW9uKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBhcHBseUNvbmZpZyhwcmVmczogSURpY3Rpb25hcnk8YW55Pik6IHZvaWQge1xyXG5cclxuICAgIGxldCBldnQgPSB7IHR5cGU6ICdhcHBseUNvbmZpZycsIHByZWZzOiBwcmVmcywgaXNPcGVuZXI6IHdpbmRvdy5vcGVuZXIgIT09IG51bGwgfTtcclxuXHJcbiAgICBpZiAod2luZG93Lm9wZW5lcikge1xyXG4gICAgICB3aW5kb3cub3BlbmVyLnBvc3RNZXNzYWdlKFxyXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KGV2dCksXHJcbiAgICAgICAgJyonXHJcbiAgICAgICk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB3aW5kb3cucGFyZW50LnBvc3RNZXNzYWdlKFxyXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KGV2dCksXHJcbiAgICAgICAgJyonXHJcbiAgICAgICk7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ==
928
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxheWVyLWNsaWVudC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvcmV2ZWxkaWdpdGFsL3BsYXllci1jbGllbnQvc3JjL2xpYi9wbGF5ZXItY2xpZW50LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBcUIsTUFBTSxlQUFlLENBQUM7QUFFOUQsT0FBTyxFQUFFLGVBQWUsRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFnQixNQUFNLE1BQU0sQ0FBQztBQUN6RSxPQUFPLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFNekQsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQzs7QUFjcEM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FrQ0c7QUFJSCxNQUFNLE9BQU8sbUJBQW1CO0lBbUs5QixjQUFjO0lBQ2QsWUFBWSxJQUFZO1FBL0p4Qjs7Ozs7Ozs7Ozs7V0FXRztRQUNJLGVBQVUsR0FBRyxJQUFJLE9BQU8sRUFBWSxDQUFDO1FBRTVDOzs7Ozs7Ozs7Ozs7V0FZRztRQUNJLGFBQVEsR0FBRyxJQUFJLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUU3Qzs7Ozs7Ozs7OztXQVVHO1FBQ0ksYUFBUSxHQUFHLElBQUksT0FBTyxFQUFFLENBQUM7UUFFaEM7Ozs7Ozs7Ozs7O1dBV0c7UUFDSSxZQUFPLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUUvQjs7Ozs7Ozs7O1dBU0c7UUFDSSxjQUFTLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUVqQzs7Ozs7Ozs7OztXQVVHO1FBQ0ksbUJBQWMsR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBVXRDLGNBQWM7UUFDTixnQkFBVyxHQUFHLFNBQVMsQ0FBQyxNQUFNLEVBQUUsb0JBQW9CLENBQUMs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QUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQy9CLENBQUM7SUFFTSxLQUFLLENBQUMsUUFBUTtRQUVuQixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDL0IsQ0FBQztJQUVNLEtBQUssQ0FBQyxTQUFTO1FBRXBCLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMvQixDQUFDO0lBRU0sS0FBSyxDQUFDLFdBQVc7UUFFdEIsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQy9CLENBQUM7SUFFTSxLQUFLLENBQUMsYUFBYTtRQUV4QixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDbEMsQ0FBQztJQUVNLFdBQVcsQ0FBQyxLQUF1QjtRQUV4QyxJQUFJLEdBQUcsR0FBRyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsTUFBTSxDQUFDLE1BQU0sS0FBSyxJQUFJLEVBQUUsQ0FBQztRQUVsRixJQUFJLE1BQU0sQ0FBQyxNQUFNLEVBQUU7WUFDakIsTUFBTSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQ3ZCLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLEVBQ25CLEdBQUcsQ0FDSixDQUFDO1NBQ0g7YUFBTTtZQUNMLE1BQU0sQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUN2QixJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxFQUNuQixHQUFHLENBQ0osQ0FBQztTQUNIO0lBQ0gsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgTmdab25lLCBPbkRlc3Ryb3kgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgZ2FkZ2V0cyB9IGZyb20gJ0ByZXZlbGRpZ2l0YWwvZ2FkZ2V0LXR5cGVzJztcclxuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBmcm9tRXZlbnQsIFN1YmplY3QsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBmaWx0ZXIsIG1hcCwgc2hhcmUsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcclxuaW1wb3J0IHsgSUNsaWVudCB9IGZyb20gJy4vaW50ZXJmYWNlcy9jbGllbnQuaW50ZXJmYWNlJztcclxuaW1wb3J0IHsgSUNvbW1hbmQgfSBmcm9tICcuL2ludGVyZmFjZXMvY29tbWFuZC5pbnRlcmZhY2UnO1xyXG5pbXBvcnQgeyBJRGljdGlvbmFyeSB9IGZyb20gJy4vaW50ZXJmYWNlcy9jb25maWcuaW50ZXJmYWNlJztcclxuaW1wb3J0IHsgSURldmljZSB9IGZyb20gJy4vaW50ZXJmYWNlcy9kZXZpY2UuaW50ZXJmYWNlJztcclxuaW1wb3J0IHsgSUV2ZW50UHJvcGVydGllcyB9IGZyb20gJy4vaW50ZXJmYWNlcy9ldmVudC1wcm9wZXJ0aWVzLmludGVyZmFjZSc7XHJcbmltcG9ydCB7IHZlcnNpb24gfSBmcm9tICcuL3ZlcnNpb24nO1xyXG5cclxuLy9pbXBvcnQgeyB2ZXJzaW9uIH0gZnJvbSAnLi92ZXJzaW9uLmpzJztcclxuXHJcbi8vIFNvIHRoYXQgVHlwZVNjcmlwdCBkb2Vzbid0IGNvbXBsYWluLCB3ZSdyZSBnb2luZyB0byBhdWdtZW50IHRoZSBHTE9CQUwgLyBXSU5ET1cgXHJcbi8vIG5hbWUtc3BhY2UgZGVmaW5pdGlvbiB0byBpbmNsdWRlIHRoZSBUcmFja2VyIEFQSS4gVGhpcyBhbHNvIHByb3ZpZGVzIHVzIHdpdGggYSBwbGFjZVxyXG4vLyB0byBhY3R1YWxseSBET0NVTUVOVCB0aGUgQVBJIHNvIHRoYXQgb3VyIGRldmVsb3BlcnMgYXJlbid0IGd1ZXNzaW5nIGFib3V0IHdoYXQnc1xyXG4vLyBhdmFpbGFibGUgb24gdGhlIGxpYnJhcnkuXHJcblxyXG4vKiogQGlnbm9yZSAqL1xyXG5kZWNsYXJlIGdsb2JhbCB7XHJcbiAgdmFyIENsaWVudDogSUNsaWVudDtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNlcnZpY2UgZm9yIGludGVyYWN0aW5nIHdpdGggdGhlIFJldmVsIERpZ2l0YWwgcGxheWVyIGNsaWVudC5cclxuICogXHJcbiAqIFRoaXMgc2VydmljZSBwcm92aWRlcyBhIGNvbXByZWhlbnNpdmUgaW50ZXJmYWNlIGZvciBnYWRnZXRzIGFuZCB3ZWIgYXBwbGljYXRpb25zXHJcbiAqIHRvIGNvbW11bmljYXRlIHdpdGggdGhlIFJldmVsIERpZ2l0YWwgcGxheWVyIGVudmlyb25tZW50LiBJdCBoYW5kbGVzIGRldmljZVxyXG4gKiBpbmZvcm1hdGlvbiwgY29tbWFuZHMsIGV2ZW50cywgYW5hbHl0aWNzIHRyYWNraW5nLCBhbmQgY29uZmlndXJhdGlvbiBtYW5hZ2VtZW50LlxyXG4gKiBcclxuICogVGhlIHNlcnZpY2Ugc3VwcG9ydHMgYm90aCBkaXJlY3QgQVBJIGNhbGxzIGFuZCBldmVudC1iYXNlZCBjb21tdW5pY2F0aW9uIHBhdHRlcm5zLFxyXG4gKiBhbGxvd2luZyBnYWRnZXRzIHRvIHJlc3BvbmQgdG8gcGxheWVyIGxpZmVjeWNsZSBldmVudHMgKHN0YXJ0LCBzdG9wLCBjb21tYW5kcykgYW5kXHJcbiAqIHNlbmQgZGF0YSBiYWNrIHRvIHRoZSBwbGF5ZXIgb3IgcmVtb3RlIGRldmljZXMuXHJcbiAqIFxyXG4gKiBgYGB0eXBlc2NyaXB0XHJcbiAqIGNvbnN0cnVjdG9yKHByaXZhdGUgY2xpZW50OiBQbGF5ZXJDbGllbnRTZXJ2aWNlKSB7XHJcbiAqICAgLy8gU3Vic2NyaWJlIHRvIHBsYXllciBldmVudHNcclxuICogICB0aGlzLmNsaWVudC5vblN0YXJ0JC5zdWJzY3JpYmUoKCkgPT4ge1xyXG4gKiAgICAgY29uc29sZS5sb2coJ0dhZGdldCBzdGFydGVkJyk7XHJcbiAqICAgfSk7XHJcbiAqICAgXHJcbiAqICAgdGhpcy5jbGllbnQub25Db21tYW5kJC5zdWJzY3JpYmUoY29tbWFuZCA9PiB7XHJcbiAqICAgICBjb25zb2xlLmxvZygnUmVjZWl2ZWQgY29tbWFuZDonLCBjb21tYW5kKTtcclxuICogICB9KTtcclxuICogfVxyXG4gKiBcclxuICogYXN5bmMgbmdPbkluaXQoKSB7XHJcbiAqICAgLy8gR2V0IGRldmljZSBpbmZvcm1hdGlvblxyXG4gKiAgIGNvbnN0IGRldmljZSA9IGF3YWl0IHRoaXMuY2xpZW50LmdldERldmljZSgpO1xyXG4gKiAgIGNvbnN0IGRldmljZVRpbWUgPSBhd2FpdCB0aGlzLmNsaWVudC5nZXREZXZpY2VUaW1lKCk7XHJcbiAqICAgXHJcbiAqICAgLy8gVHJhY2sgYW5hbHl0aWNzXHJcbiAqICAgdGhpcy5jbGllbnQudHJhY2soJ2dhZGdldF9sb2FkZWQnLCB7IHZlcnNpb246ICcxLjAnIH0pO1xyXG4gKiB9XHJcbiAqIGBgYFxyXG4gKiBcclxuICogQHNpbmNlIDEuMC4wXHJcbiAqL1xyXG5ASW5qZWN0YWJsZSh7XHJcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBQbGF5ZXJDbGllbnRTZXJ2aWNlIGltcGxlbWVudHMgT25EZXN0cm95IHtcclxuXHJcbiAgLyoqIEBpZ25vcmUgKi9cclxuICBwcml2YXRlIGNsaWVudFByb21pc2U6IFByb21pc2U8SUNsaWVudD4gfCBudWxsO1xyXG5cclxuICAvKipcclxuICAgKiBPYnNlcnZhYmxlIHN0cmVhbSBvZiBjb21tYW5kcyBzZW50IHRvIHRoaXMgcGxheWVyIGZyb20gdGhlIFJldmVsIERpZ2l0YWwgcGxhdGZvcm0uXHJcbiAgICogU3Vic2NyaWJlIHRvIHRoaXMgdG8gaGFuZGxlIGN1c3RvbSBjb21tYW5kcyBzZW50IGZyb20gdGVtcGxhdGVzLCBwbGF5bGlzdHMsIG9yIHJlbW90ZSBkZXZpY2VzLlxyXG4gICAqIFxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiB0aGlzLmNsaWVudC5vbkNvbW1hbmQkLnN1YnNjcmliZShjb21tYW5kID0+IHtcclxuICAgKiAgIGlmIChjb21tYW5kLm5hbWUgPT09ICdjdXN0b21BY3Rpb24nKSB7XHJcbiAgICogICAgIHRoaXMuaGFuZGxlQ3VzdG9tQWN0aW9uKGNvbW1hbmQuYXJnKTtcclxuICAgKiAgIH1cclxuICAgKiB9KTtcclxuICAgKiBgYGBcclxuICAgKi9cclxuICBwdWJsaWMgb25Db21tYW5kJCA9IG5ldyBTdWJqZWN0PElDb21tYW5kPigpO1xyXG5cclxuICAvKipcclxuICAgKiBPYnNlcnZhYmxlIHRoYXQgc2lnbmFscyB3aGVuIHRoZSBnYWRnZXQgaGFzIGJlZW4gbG9hZGVkIGFuZCBpcyByZWFkeSB0byBzdGFydC5cclxuICAgKiBFbWl0cyBgdHJ1ZWAgd2hlbiByZWFkeSwgYGZhbHNlYCB3aGVuIGRlc3Ryb3llZC5cclxuICAgKiBcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogdGhpcy5jbGllbnQub25SZWFkeSQuc3Vic2NyaWJlKGlzUmVhZHkgPT4ge1xyXG4gICAqICAgaWYgKGlzUmVhZHkpIHtcclxuICAgKiAgICAgY29uc29sZS5sb2coJ0NsaWVudCBpcyByZWFkeScpO1xyXG4gICAqICAgICB0aGlzLmluaXRpYWxpemVHYWRnZXQoKTtcclxuICAgKiAgIH1cclxuICAgKiB9KTtcclxuICAgKiBgYGBcclxuICAgKi9cclxuICBwdWJsaWMgb25SZWFkeSQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0KGZhbHNlKTtcclxuXHJcbiAgLyoqXHJcbiAgICogT2JzZXJ2YWJsZSB0aGF0IHNpZ25hbHMgd2hlbiB0aGUgZ2FkZ2V0IGhhcyBiZWVuIHN0YXJ0ZWQgYnkgdGhlIHBsYXllci5cclxuICAgKiBUaGlzIGV2ZW50IG9jY3VycyB3aGVuIHRoZSBwbGF5ZXIgYmVnaW5zIGV4ZWN1dGlvbiBvZiB0aGUgZ2FkZ2V0IGNvbnRlbnQuXHJcbiAgICogXHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIHRoaXMuY2xpZW50Lm9uU3RhcnQkLnN1YnNjcmliZSgoKSA9PiB7XHJcbiAgICogICBjb25zb2xlLmxvZygnR2FkZ2V0IHN0YXJ0ZWQnKTtcclxuICAgKiAgIHRoaXMuc3RhcnRBbmltYXRpb24oKTtcclxuICAgKiB9KTtcclxuICAgKiBgYGBcclxuICAgKi9cclxuICBwdWJsaWMgb25TdGFydCQgPSBuZXcgU3ViamVjdCgpO1xyXG5cclxuICAvKipcclxuICAgKiBPYnNlcnZhYmxlIHRoYXQgc2lnbmFscyB3aGVuIHRoZSBnYWRnZXQgaGFzIGJlZW4gc3RvcHBlZCBieSB0aGUgcGxheWVyLlxyXG4gICAqIFRoaXMgZXZlbnQgb2NjdXJzIHdoZW4gdGhlIHBsYXllciBzdG9wcyBleGVjdXRpb24sIHR5cGljYWxseSB3aGVuIG1vdmluZ1xyXG4gICAqIHRvIHRoZSBuZXh0IGl0ZW0gaW4gYSBwbGF5bGlzdCBvciB3aGVuIHRoZSBjb250ZW50IGR1cmF0aW9uIGV4cGlyZXMuXHJcbiAgICogXHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIHRoaXMuY2xpZW50Lm9uU3RvcCQuc3Vic2NyaWJlKCgpID0+IHtcclxuICAgKiAgIGNvbnNvbGUubG9nKCdHYWRnZXQgc3RvcHBlZCcpO1xyXG4gICAqICAgdGhpcy5jbGVhbnVwKCk7XHJcbiAgICogfSk7XHJcbiAgICogYGBgXHJcbiAgICovXHJcbiAgcHVibGljIG9uU3RvcCQgPSBuZXcgU3ViamVjdCgpO1xyXG5cclxuICAvKipcclxuICAgKiBPYnNlcnZhYmxlIHRoYXQgc2lnbmFscyB3aGVuIHRoZSBnYWRnZXQgc2hvdWxkIG9wZW4gdGhlIGNvbmZpZ3VyYXRpb24gd2luZG93LlxyXG4gICAqIFRoaXMgYWxsb3dzIGdhZGdldHMgdG8gcmVzcG9uZCB0byBjb25maWd1cmF0aW9uIHJlcXVlc3RzIGZyb20gdGhlIHBsYXllci5cclxuICAgKiBcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogdGhpcy5jbGllbnQub25Db25maWckLnN1YnNjcmliZSgoKSA9PiB7XHJcbiAgICogICB0aGlzLm9wZW5Db25maWd1cmF0aW9uRGlhbG9nKCk7XHJcbiAgICogfSk7XHJcbiAgICogYGBgXHJcbiAgICovXHJcbiAgcHVibGljIG9uQ29uZmlnJCA9IG5ldyBTdWJqZWN0KCk7XHJcblxyXG4gIC8qKlxyXG4gICAqIE9ic2VydmFibGUgdGhhdCBzaWduYWxzIHdoZW4gdGhlIGdhZGdldCBoYXMgcmVjZWl2ZWQgYSBwb3N0TWVzc2FnZSBldmVudCBmcm9tIHRoZSBwbGF5ZXIuXHJcbiAgICogVGhpcyBoYW5kbGVzIGNvbW11bmljYXRpb24gYmV0d2VlbiB0aGUgZ2FkZ2V0IGFuZCBwbGF5ZXIgdmlhIHRoZSBwb3N0TWVzc2FnZSBBUEkuXHJcbiAgICogXHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIHRoaXMuY2xpZW50Lm9uUG9zdE1lc3NhZ2UkLnN1YnNjcmliZShtZXNzYWdlID0+IHtcclxuICAgKiAgIGNvbnNvbGUubG9nKCdSZWNlaXZlZCBtZXNzYWdlOicsIG1lc3NhZ2UpO1xyXG4gICAqICAgdGhpcy5oYW5kbGVQbGF5ZXJNZXNzYWdlKG1lc3NhZ2UpO1xyXG4gICAqIH0pO1xyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIHB1YmxpYyBvblBvc3RNZXNzYWdlJCA9IG5ldyBTdWJqZWN0KCk7XHJcblxyXG4gIC8vXHJcbiAgLy8gVHdvIG1ldGhvZHMgYXZhaWxhYmxlIGZvciBjYWxsaW5nIGludG8gdGhlIGxpYnJhcnk6XHJcbiAgLy9cclxuICAvLyAxKSBVc2luZyBkaXNwYXRjaEV2ZW50KCkgd2l0aCB0aGUgZm9sbG93aW5nIGN1c3RvbSBldmVudHNcclxuICAvLyAyKSBVc2luZyB0aGUgd2luZG93IHNjb3BlZCBSZXZlbERpZ2l0YWwgb2JqZWN0IGFzIGRlZmluZWQgaW4gdGhlIGNvbnN0cnVjdG9yXHJcbiAgLy9cclxuICAvKiogQGlnbm9yZSAqL1xyXG4gIHByaXZhdGUgb25TdGFydFN1YjogU3Vic2NyaXB0aW9uO1xyXG4gIC8qKiBAaWdub3JlICovXHJcbiAgcHJpdmF0ZSBvblN0YXJ0RXZ0JCA9IGZyb21FdmVudCh3aW5kb3csICdSZXZlbERpZ2l0YWwuU3RhcnQnKS5waXBlKFxyXG4gICAgc2hhcmUoKSxcclxuICAgIHRhcCh0aGlzLm9uU3RhcnQkKVxyXG4gICk7XHJcbiAgLyoqIEBpZ25vcmUgKi9cclxuICBwcml2YXRlIG9uU3RvcFN1YjogU3Vic2NyaXB0aW9uO1xyXG4gIC8qKiBAaWdub3JlICovXHJcbiAgcHJpdmF0ZSBvblN0b3BFdnQkID0gZnJvbUV2ZW50KHdpbmRvdywgJ1JldmVsRGlnaXRhbC5TdG9wJykucGlwZShcclxuICAgIHNoYXJlKCksXHJcbiAgICB0YXAodGhpcy5vblN0b3AkKVxyXG4gICk7XHJcbiAgLyoqIEBpZ25vcmUgKi9cclxuICBwcml2YXRlIG9uQ29tbWFuZFN1YjogU3Vic2NyaXB0aW9uO1xyXG4gIC8qKiBAaWdub3JlICovXHJcbiAgcHJpdmF0ZSBvbkNvbW1hbmRFdnQkID0gZnJvbUV2ZW50PElDb21tYW5kPih3aW5kb3csICdSZXZlbERpZ2l0YWwuQ29tbWFuZCcpLnBpcGUoXHJcbiAgICBtYXAoKGU6IGFueSkgPT4geyByZXR1cm4geyBuYW1lOiBlLmRldGFpbC5uYW1lLCBhcmc6IGUuZGV0YWlsLmFyZyB9IGFzIElDb21tYW5kIH0pLFxyXG4gICAgc2hhcmUoKSxcclxuICAgIHRhcCh0aGlzLm9uQ29tbWFuZCQpXHJcbiAgKTtcclxuICAvKiogQGlnbm9yZSAqL1xyXG4gIC8vIHByaXZhdGUgb25Db25maWdTdWI6IFN1YnNjcmlwdGlvbjtcclxuICAvLyAvKiogQGlnbm9yZSAqL1xyXG4gIC8vIHByaXZhdGUgb25Db25maWdFdnQkID0gZnJvbUV2ZW50KHdpbmRvdywgJ1JldmVsRGlnaXRhbC5Db25maWcnKS5waXBlKFxyXG4gIC8vICAgc2hhcmUoKSxcclxuICAvLyAgIHRhcCgoZTogQ3VzdG9tRXZlbnQpID0+IHtcclxuICAvLyAgICAgY29uc29sZS5sb2coZSk7XHJcblxyXG4gIC8vICAgICBpZiAoZS5kZXRhaWwudHlwZSA9PT0gJ2FwcGx5Q29uZmlnJyAmJiBlLmRldGFpbC5pc09wZW5lcikge1xyXG4gIC8vICAgICAgIHRoaXMuYXBwbHlDb25maWcoZS5kZXRhaWwuY29uZmlnKTsgLy8gcHJvcGFnYXRlIGNvbmZpZyB0byBpZnJhbWUgcGFyZW50IGZyb20gdGhlIHBvcHVwIHdpbmRvd1xyXG4gIC8vICAgICB9IGVsc2Uge1xyXG4gIC8vICAgICAgIHRoaXMub25Db25maWckLm5leHQoZS5kZXRhaWwpO1xyXG4gIC8vICAgICB9XHJcbiAgLy8gICB9KVxyXG4gIC8vICk7XHJcbiAgLy8gcHJpdmF0ZSBvblBvc3RNZXNzYWdlU3ViOiBTdWJzY3JpcHRpb247XHJcbiAgLy8gcHJpdmF0ZSBvblBvc3RNZXNzYWdlRXZ0JCA9IGZyb21FdmVudCh3aW5kb3csICdtZXNzYWdlJykucGlwZShcclxuICAvLyAgIGZpbHRlcigobWVzc2FnZUV2ZW50OiBNZXNzYWdlRXZlbnQpID0+XHJcbiAgLy8gICAgIG1lc3NhZ2VFdmVudC5zb3VyY2UgIT09IHdpbmRvdy5wYXJlbnQgJiZcclxuICAvLyAgICAgdHlwZW9mIG1lc3NhZ2VFdmVudC5kYXRhID09PSAnc3RyaW5nJyAmJlxyXG4gIC8vICAgICBtZXNzYWdlRXZlbnQuZGF0YS5zdGFydHNXaXRoKCdyZXZlbGRpZ2l0YWw6JykpLFxyXG4gIC8vICAgbWFwKChlOiBhbnkpID0+IHsgcmV0dXJuIEpTT04ucGFyc2UoZS5zdWJzdHJpbmcoMTMpKSBhcyBDb21tYW5kIH0pLFxyXG4gIC8vICAgc2hhcmUoKSxcclxuICAvLyAgIHRhcCh0aGlzLm9uQ29tbWFuZCQpXHJcbiAgLy8gKTtcclxuXHJcbiAgcHJpdmF0ZSBvblBvc3RNZXNzYWdlU3ViOiBTdWJzY3JpcHRpb247XHJcbiAgcHJpdmF0ZSBvblBvc3RNZXNzYWdlRXZ0JCA9IGZyb21FdmVudCh3aW5kb3csICdtZXNzYWdlJykucGlwZShcclxuICAgIGZpbHRlcigobWVzc2FnZUV2ZW50OiBNZXNzYWdlRXZlbnQpID0+XHJcbiAgICAgIC8vbWVzc2FnZUV2ZW50LnNvdXJjZSAhPT0gd2luZG93LnBhcmVudCAmJlxyXG4gICAgICB0eXBlb2YgbWVzc2FnZUV2ZW50LmRhdGEgPT09ICdzdHJpbmcnKSxcclxuICAgIG1hcCgoZTogYW55KSA9PiBKU09OLnBhcnNlKGUuZGF0YSkpLFxyXG4gICAgc2hhcmUoKSxcclxuICAgIHRhcCgoZTogYW55KSA9PiB7XHJcbiAgICAgIGlmIChlLnR5cGUgPT09ICdhcHBseUNvbmZpZycgJiYgZS5pc09wZW5lcikge1xyXG4gICAgICAgIGUuaXNPcGVuZXIgPSBmYWxzZTtcclxuICAgICAgICAvLyBwcm9wYWdhdGUgY29uZmlnIHRvIGlmcmFtZSBwYXJlbnQgZnJvbSB0aGUgcG9wdXAgd2luZG93XHJcbiAgICAgICAgd2luZG93LnBhcmVudC5wb3N0TWVzc2FnZShcclxuICAgICAgICAgIEpTT04uc3RyaW5naWZ5KGUpLFxyXG4gICAgICAgICAgJyonXHJcbiAgICAgICAgKTtcclxuICAgICAgfSBlbHNlIGlmIChlLnR5cGUgPT09ICdvcGVuQ29uZmlnJykge1xyXG4gICAgICAgIHRoaXMub25Db25maWckLm5leHQobnVsbCk7XHJcbiAgICAgIH1cclxuICAgIH0pLFxyXG4gICAgdGFwKGUgPT4gdGhpcy5vblBvc3RNZXNzYWdlJC5uZXh0KGUpKVxyXG4gICk7XHJcblxyXG5cclxuICAvKiogQGlnbm9yZSAqL1xyXG4gIGNvbnN0cnVjdG9yKHpvbmU6IE5nWm9uZSkge1xyXG5cclxuICAgIGxldCBzZWxmID0gdGhpcztcclxuICAgICh3aW5kb3cgYXMgYW55KS5SZXZlbERpZ2l0YWwgPSB7XHJcbiAgICAgIENvbnRyb2xsZXI6IHtcclxuICAgICAgICBvbkNvbW1hbmQ6IGZ1bmN0aW9uIChuYW1lOiBzdHJpbmcsIGFyZzogc3RyaW5nKSB7XHJcbiAgICAgICAgICB6b25lLnJ1bigoKSA9PiB7XHJcbiAgICAgICAgICAgIHNlbGYub25Db21tYW5kJC5uZXh0KHsgbmFtZTogbmFtZSwgYXJnOiBhcmcgfSk7XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9LFxyXG4gICAgICAgIG9uU3RhcnQ6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgIHpvbmUucnVuKCgpID0+IHtcclxuICAgICAgICAgICAgc2VsZi5vblN0YXJ0JC5uZXh0KG51bGwpO1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfSxcclxuICAgICAgICBvblN0b3A6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgIHpvbmUucnVuKCgpID0+IHtcclxuICAgICAgICAgICAgc2VsZi5vblN0b3AkLm5leHQobnVsbCk7XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICB0aGlzLm9uU3RhcnRTdWIgPSB0aGlzLm9uU3RhcnRFdnQkLnN1YnNjcmliZSgoKSA9PiB7IH0pO1xyXG4gICAgdGhpcy5vblN0b3BTdWIgPSB0aGlzLm9uU3RvcEV2dCQuc3Vic2NyaWJlKCgpID0+IHsgfSk7XHJcbiAgICB0aGlzLm9uQ29tbWFuZFN1YiA9IHRoaXMub25Db21tYW5kRXZ0JC5zdWJzY3JpYmUoKCkgPT4geyB9KTtcclxuICAgIC8vdGhpcy5vbkNvbmZpZ1N1YiA9IHRoaXMub25Db25maWdFdnQkLnN1YnNjcmliZSgoKSA9PiB7IH0pO1xyXG4gICAgdGhpcy5vblBvc3RNZXNzYWdlU3ViID0gdGhpcy5vblBvc3RNZXNzYWdlRXZ0JC5zdWJzY3JpYmUoKCkgPT4geyB9KTtcclxuXHJcbiAgICB0aGlzLmNsaWVudFByb21pc2UgPSBudWxsO1xyXG5cclxuICAgIHRoaXMub25SZWFkeSQubmV4dCh0cnVlKTtcclxuICB9XHJcblxyXG4gIC8qKiBAaWdub3JlICovXHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcblxyXG4gICAgdGhpcy5vblN0YXJ0U3ViPy51bnN1YnNjcmliZSgpO1xyXG4gICAgdGhpcy5vblN0b3BTdWI/LnVuc3Vic2NyaWJlKCk7XHJcbiAgICB0aGlzLm9uQ29tbWFuZFN1Yj8udW5zdWJzY3JpYmUoKTtcclxuICAgIC8vdGhpcy5vbkNvbmZpZ1N1Yj8udW5zdWJzY3JpYmUoKTtcclxuICAgIHRoaXMub25Qb3N0TWVzc2FnZVN1Yj8udW5zdWJzY3JpYmUoKTtcclxuXHJcbiAgICB0aGlzLm9uUmVhZHkkLm5leHQoZmFsc2UpO1xyXG4gIH1cclxuXHJcbiAgLyoqIEBpZ25vcmUgKi9cclxuICBwdWJsaWMgc3RhdGljIGluaXQoZGF0YTogYW55KSB7XHJcblxyXG4gICAgY29uc29sZS5sb2coXHJcbiAgICAgICclY+Kame+4jyBJbml0aWFsaXppbmcgUmV2ZWwgRGlnaXRhbCBjbGllbnQgbGlicmFyeScsXHJcbiAgICAgICdiYWNrZ3JvdW5kLWNvbG9yOmJsdWU7IGNvbG9yOnllbGxvdzsnXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2VuZHMgYSBjYWxsYmFjayB0byBwbGF5ZXIgc2NyaXB0aW5nIHdpdGggdmFyaWFibGUgYXJndW1lbnRzLlxyXG4gICAqIFxyXG4gICAqIFRoaXMgbWV0aG9kIGFsbG93cyB0aGUgZ2FkZ2V0IHRvIGNvbW11bmljYXRlIHdpdGggcGxheWVyIHNjcmlwdGluZy5cclxuICAgKiBJZiB0aGUgYXBwcm9wcmlhdGUgc2NyaXB0aW5nIGlzIGluIHBsYWNlIGluIHRoZSBjdXJyZW50bHkgcnVubmluZyB0ZW1wbGF0ZSwgXHJcbiAgICogY2FsbGluZyB0aGlzIG1ldGhvZCB3aWxsIGluaXRpYXRlIGEgY2FsbGJhY2sgd2hpY2ggY2FuIGJlIGFjdGVkIHVwb24gaW4gcGxheWVyIHNjcmlwdC5cclxuICAgKiBcclxuICAgKiBAcGFyYW0gYXJncyAtIFZhcmlhYmxlIG51bWJlciBvZiBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgY2FsbGJhY2sgKG1heCA1IGFyZ3VtZW50cylcclxuICAgKiBcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogLy8gU2VuZCBhIHNpbXBsZSBjYWxsYmFja1xyXG4gICAqIHRoaXMuY2xpZW50LmNhbGxiYWNrKCd0ZXN0JywgJ2RhdGEnKTtcclxuICAgKiBcclxuICAgKiAvLyBTZW5kIG11bHRpcGxlIHBhcmFtZXRlcnNcclxuICAgKiB0aGlzLmNsaWVudC5jYWxsYmFjaygnYWN0aW9uJywgJ3ZhbHVlMScsICd2YWx1ZTInLCB7IGRhdGE6ICdvYmplY3QnIH0pO1xyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIHB1YmxpYyBjYWxsYmFjayguLi5hcmdzOiBhbnlbXSk6IHZvaWQge1xyXG5cclxuICAgIHRoaXMuZ2V0Q2xpZW50KCkudGhlbigoY2xpZW50KSA9PiB7XHJcblxyXG4gICAgICBzd2l0Y2ggKGFyZ3MubGVuZ3RoKSB7XHJcbiAgICAgICAgY2FzZSAwOlxyXG4gICAgICAgICAgY2xpZW50LmNhbGxiYWNrKCk7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICBjYXNlIDE6XHJcbiAgICAgICAgICBjbGllbnQuY2FsbGJhY2soYXJnc1swXSk7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICBjYXNlIDI6XHJcbiAgICAgICAgICBjbGllbnQuY2FsbGJhY2soYXJnc1sxXSk7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICBjYXNlIDM6XHJcbiAgICAgICAgICBjbGllbnQuY2FsbGJhY2soYXJnc1syXSk7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICBjYXNlIDQ6XHJcbiAgICAgICAgICBjbGllbnQuY2FsbGJhY2soYXJnc1szXSk7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICBjYXNlIDU6XHJcbiAgICAgICAgICBjbGllbnQuY2FsbGJhY2soYXJnc1s0XSk7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgfVxyXG4gICAgfSlcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldHMgdGhlIHVzZXIgcHJlZmVyZW5jZXMgaW50ZXJmYWNlIGV4cG9zZWQgYnkgdGhlIEdvb2dsZSBHYWRnZXRzIEFQSS5cclxuICAgKiBcclxuICAgKiBUaGlzIG1ldGhvZCBwcm92aWRlcyBhY2Nlc3MgdG8gZ2FkZ2V0IHByZWZlcmVuY2VzIHdoaWNoIGNhbiBiZSBjb25maWd1cmVkXHJcbiAgICogaW4gdGhlIFJldmVsIERpZ2l0YWwgQ01TLiBVc2UgdGhpcyB0byByZXRyaWV2ZSB1c2VyLWNvbmZpZ3VyYWJsZSBzZXR0aW5nc1xyXG4gICAqIGZvciB5b3VyIGdhZGdldC5cclxuICAgKiBcclxuICAgKiBAcmV0dXJucyBUaGUgR2FkZ2V0cyBBUEkgUHJlZnMgb2JqZWN0IGZvciBhY2Nlc3NpbmcgcHJlZmVyZW5jZSB2YWx1ZXNcclxuICAgKiBcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogY29uc3RydWN0b3IocHVibGljIGNsaWVudDogUGxheWVyQ2xpZW50U2VydmljZSkge1xyXG4gICAqICAgY29uc3QgcHJlZnMgPSBjbGllbnQuZ2V0UHJlZnMoKTtcclxuICAgKiAgIGNvbnN0IG15U3RyaW5nID0gcHJlZnMuZ2V0U3RyaW5nKCdteVN0cmluZ1ByZWYnKTtcclxuICAgKiAgIGNvbnN0IG15TnVtYmVyID0gcHJlZnMuZ2V0SW50KCdteU51bWJlclByZWYnKTtcclxuICAgKiAgIGNvbnN0IG15Qm9vbCA9IHByZWZzLmdldEJvb2woJ215Qm9vbFByZWYnKTtcclxuICAgKiB9XHJcbiAgICogYGBgXHJcbiAgICogXHJcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXJzLmdvb2dsZS5jb20vZ2FkZ2V0cy9kb2NzL2Jhc2ljfSBHb29nbGUgR2FkZ2V0cyBBUEkgZG9jdW1lbnRhdGlvblxyXG4gICAqL1xyXG4gIHB1YmxpYyBnZXRQcmVmcygpOiBnYWRnZXRzLlByZWZzIHtcclxuXHJcbiAgICByZXR1cm4gbmV3IHdpbmRvd1snZ2FkZ2V0cyddWydQcmVmcyddKCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXRzIHRoZSBjdXJyZW50IGRldmljZSB0aW1lIGluIElTTzg2MDEgZm9ybWF0LlxyXG4gICAqIFxyXG4gICAqIEN1cnJlbnQgZGV2aWNlIHRpbWUgaXMgZGV0ZXJtaW5lZCBieSB0aGUgZGV2aWNlIHRpbWV6b25lIGFzc2lnbmVkIHRvIHRoZSBkZXZpY2UgaW4gdGhlIENNUy5cclxuICAgKiBUaGlzIGlzIHVzZWZ1bCBmb3IgZGlzcGxheWluZyB0aW1lLXNlbnNpdGl2ZSBjb250ZW50IG9yIHNjaGVkdWxpbmcgb3BlcmF0aW9ucyBiYXNlZCBvblxyXG4gICAqIHRoZSBkZXZpY2UncyBsb2NhbCB0aW1lIHJhdGhlciB0aGFuIGJyb3dzZXIgdGltZS5cclxuICAgKiBcclxuICAgKiBAcGFyYW0gZGF0ZSAtIE9wdGlvbmFsLiBJZiBzdXBwbGllZCwgd2lsbCB0cmFuc2xhdGUgdGhlIHN1cHBsaWVkIGRhdGUvdGltZSB0byBkZXZpY2UgdGltZSBiYXNlZCBvbiByZXNwZWN0aXZlIHRpbWV6b25lc1xyXG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIGRhdGUvdGltZSBpbiBJU084NjAxIGZvcm1hdFxyXG4gICAqIFxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiAvLyBHZXQgY3VycmVudCBkZXZpY2UgdGltZVxyXG4gICAqIGNvbnN0IGN1cnJlbnRUaW1lID0gYXdhaXQgdGhpcy5jbGllbnQuZ2V0RGV2aWNlVGltZSgpO1xyXG4gICAqIGNvbnNvbGUubG9nKCdEZXZpY2UgdGltZTonLCBjdXJyZW50VGltZSk7XHJcbiAgICogXHJcbiAgICogLy8gQ29udmVydCBhIHNwZWNpZmljIGRhdGUgdG8gZGV2aWNlIHRpbWVcclxuICAgKiBjb25zdCBzcGVjaWZpY0RhdGUgPSBuZXcgRGF0ZSgnMjAyMy0wMS0wMVQxMjowMDowMFonKTtcclxuICAgKiBjb25zdCBkZXZpY2VUaW1lID0gYXdhaXQgdGhpcy5jbGllbnQuZ2V0RGV2aWNlVGltZShzcGVjaWZpY0RhdGUpO1xyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIHB1YmxpYyBhc3luYyBnZXREZXZpY2VUaW1lKGRhdGU/OiBEYXRlKTogUHJvbWlzZTxzdHJpbmc+IHtcclxuXHJcbiAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldENsaWVudCgpO1xyXG5cclxuICAgIGlmIChkYXRlICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgcmV0dXJuIGNsaWVudC5nZXREZXZpY2VUaW1lKGRhdGUpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGNsaWVudC5nZXREZXZpY2VUaW1lKCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXRzIHRoZSB0aW1lem9uZSBuYW1lIGN1cnJlbnRseSBhc3NpZ25lZCB0byB0aGUgZGV2aWNlLlxyXG4gICAqIFxyXG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSB0aW1lem9uZSBuYW1lIChlLmcuLCBcIkFtZXJpY2EvTmV3X1lvcmtcIilcclxuICAgKiBcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogY29uc3QgdGltZXpvbmVOYW1lID0gYXdhaXQgdGhpcy5jbGllbnQuZ2V0RGV2aWNlVGltZVpvbmVOYW1lKCk7XHJcbiAgICogY29uc29sZS5sb2coJ0RldmljZSB0aW1lem9uZTonLCB0aW1lem9uZU5hbWUpO1xyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIHB1YmxpYyBhc3luYyBnZXREZXZpY2VUaW1lWm9uZU5hbWUoKTogUHJvbWlzZTxzdHJpbmc+IHtcclxuXHJcbiAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldENsaWVudCgpO1xyXG5cclxuICAgIHJldHVybiBjbGllbnQuZ2V0RGV2aWNlVGltZVpvbmVOYW1lKCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXRzIHRoZSB0aW1lem9uZSBJRCBjdXJyZW50bHkgYXNzaWduZWQgdG8gdGhlIGRldmljZS5cclxuICAgKiBcclxuICAgKiBAcmV0dXJucyBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgdGltZXpvbmUgSURcclxuICAgKiBcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogY29uc3QgdGltZXpvbmVJZCA9IGF3YWl0IHRoaXMuY2xpZW50LmdldERldmljZVRpbWVab25lSUQoKTtcclxuICAgKiBjb25zb2xlLmxvZygnRGV2aWNlIHRpbWV6b25lIElEOicsIHRpbWV6b25lSWQpO1xyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIHB1YmxpYyBhc3luYyBnZXREZXZpY2VUaW1lWm9uZUlEKCk6IFByb21pc2U8c3RyaW5nPiB7XHJcblxyXG4gICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKTtcclxuXHJcbiAgICByZXR1cm4gY2xpZW50LmdldERldmljZVRpbWVab25lSUQoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldHMgdGhlIG51bWVyaWNhbCBvZmZzZXQgZnJvbSBHTVQgb2YgdGhlIHRpbWV6b25lIGN1cnJlbnRseSBhc3NpZ25lZCB0byB0aGUgZGV2aWNlLlxyXG4gICAqIFxyXG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSB0aW1lem9uZSBvZmZzZXQgaW4gaG91cnMgKGUuZy4sIC01IGZvciBFU1QpXHJcbiAgICogXHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIGNvbnN0IG9mZnNldCA9IGF3YWl0IHRoaXMuY2xpZW50LmdldERldmljZVRpbWVab25lT2Zmc2V0KCk7XHJcbiAgICogY29uc29sZS5sb2coJ0RldmljZSB0aW1lem9uZSBvZmZzZXQ6Jywgb2Zmc2V0LCAnaG91cnMgZnJvbSBHTVQnKTtcclxuICAgKiBgYGBcclxuICAgKi9cclxuICBwdWJsaWMgYXN5bmMgZ2V0RGV2aWNlVGltZVpvbmVPZmZzZXQoKTogUHJvbWlzZTxudW1iZXI+IHtcclxuXHJcbiAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldENsaWVudCgpO1xyXG5cclxuICAgIHJldHVybiBjbGllbnQuZ2V0RGV2aWNlVGltZVpvbmVPZmZzZXQoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldHMgdGhlIGxhbmd1YWdlIGNvZGUgb2YgdGhlIGxhbmd1YWdlIGN1cnJlbnRseSBhc3NpZ25lZCB0byB0aGUgZGV2aWNlLlxyXG4gICAqIFxyXG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBsYW5ndWFnZSBjb2RlIChlLmcuLCBcImVuLVVTXCIsIFwiZnItRlJcIilcclxuICAgKiBcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogY29uc3QgbGFuZ3VhZ2VDb2RlID0gYXdhaXQgdGhpcy5jbGllbnQuZ2V0TGFuZ3VhZ2VDb2RlKCk7XHJcbiAgICogY29uc29sZS5sb2coJ0RldmljZSBsYW5ndWFnZTonLCBsYW5ndWFnZUNvZGUpO1xyXG4gICAqIC8vIFVzZSBmb3IgbG9jYWxpemF0aW9uXHJcbiAgICogdGhpcy5sb2FkTGFuZ3VhZ2VSZXNvdXJjZXMobGFuZ3VhZ2VDb2RlKTtcclxuICAgKiBgYGBcclxuICAgKi9cclxuICBwdWJsaWMgYXN5bmMgZ2V0TGFuZ3VhZ2VDb2RlKCk6IFByb21pc2U8c3RyaW5nPiB7XHJcblxyXG4gICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKTtcclxuXHJcbiAgICByZXR1cm4gY2xpZW50LmdldExhbmd1YWdlQ29kZSgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0cyB0aGUgdW5pcXVlIFJldmVsIERpZ2l0YWwgZGV2aWNlIGtleSBhc3NvY2lhdGVkIHdpdGggdGhlIGRldmljZS5cclxuICAgKiBcclxuICAgKiBUaGUgZGV2aWNlIGtleSBpcyBhIHVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGlzIHNwZWNpZmljIHBsYXllciBkZXZpY2VcclxuICAgKiBhbmQgY2FuIGJlIHVzZWQgZm9yIGRldmljZS1zcGVjaWZpYyBvcGVyYXRpb25zIG9yIHJlbW90ZSBjb21tYW5kcy5cclxuICAgKiBcclxuICAgKiBAcmV0dXJucyBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgZGV2aWNlIGtleSBzdHJpbmdcclxuICAgKiBcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogY29uc3QgZGV2aWNlS2V5ID0gYXdhaXQgdGhpcy5jbGllbnQuZ2V0RGV2aWNlS2V5KCk7XHJcbiAgICogY29uc29sZS5sb2coJ0RldmljZSBrZXk6JywgZGV2aWNlS2V5KTtcclxuICAgKiBgYGBcclxuICAgKi9cclxuICBwdWJsaWMgYXN5bmMgZ2V0RGV2aWNlS2V5KCk6IFByb21pc2U8c3RyaW5nPiB7XHJcblxyXG4gICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKTtcclxuXHJcbiAgICByZXR1cm4gY2xpZW50LmdldERldmljZUtleSgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2VuZHMgYSBjb21tYW5kIHRvIHRoZSBsb2NhbCBwbGF5ZXIgZGV2aWNlLlxyXG4gICAqIFxyXG4gICAqIENvbW1hbmRzIGNhbiBiZSB1c2VkIHRvIGNvbnRyb2wgdmFyaW91cyBhc3BlY3RzIG9mIHRoZSBwbGF5ZXIgb3IgdHJpZ2dlclxyXG4gICAqIHNwZWNpZmljIGJlaGF2aW9ycy4gVGhlIGNvbW1hbmQgaXMgcHJvY2Vzc2VkIGJ5IHRoZSBsb2NhbCBwbGF5ZXIgb25seS5cclxuICAgKiBcclxuICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBjb21tYW5kIG5hbWUvaWRlbnRpZmllclxyXG4gICAqIEBwYXJhbSBhcmcgLSBUaGUgY29tbWFuZCBhcmd1bWVudC9wYXlsb2FkXHJcbiAgICogXHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIC8vIFNlbmQgYSBzaW1wbGUgY29tbWFuZFxyXG4gICAqIHRoaXMuY2xpZW50LnNlbmRDb21tYW5kKCdyZWZyZXNoJywgJycpO1xyXG4gICAqIFxyXG4gICAqIC8vIFNlbmQgYSBjb21tYW5kIHdpdGggZGF0YVxyXG4gICAqIHRoaXMuY2xpZW50LnNlbmRDb21tYW5kKCdzZXRWb2x1bWUnLCAnNTAnKTtcclxuICAgKiBcclxuICAgKiAvLyBTZW5kIGEgY29tbWFuZCB3aXRoIEpTT04gZGF0YVxyXG4gICAqIHRoaXMuY2xpZW50LnNlbmRDb21tYW5kKCdjb25maWd1cmUnLCBKU09OLnN0cmluZ2lmeSh7IHNldHRpbmc6ICd2YWx1ZScgfSkpO1xyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIHB1YmxpYyBzZW5kQ29tbWFuZChuYW1lOiBzdHJpbmcsIGFyZzogc3RyaW5nKTogdm9pZCB7XHJcblxyXG4gICAgdGhpcy5nZXRDbGllbnQoKS50aGVuKChjbGllbnQpID0+IHtcclxuICAgICAgY2xpZW50LnNlbmRDb21tYW5kKG5hbWUsIGFyZyk7XHJcbiAgICB9KVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2VuZHMgYSBjb21tYW5kIHRvIHJlbW90ZSBwbGF5ZXIgZGV2aWNlcyB3aXRoIHRoZSBzcGVjaWZpZWQgZGV2aWNlIGtleXMuXHJcbiAgICogXHJcbiAgICogUmVtb3RlIGNvbW1hbmRzIGFsbG93IGNyb3NzLWRldmljZSBjb21tdW5pY2F0aW9uIHdpdGhpbiB0aGUgc2FtZSBSZXZlbCBEaWdpdGFsIGFjY291bnQuXHJcbiAgICogVGhpcyBpcyB1c2VmdWwgZm9yIHN5bmNocm9uaXplZCBkaXNwbGF5cywgZGV2aWNlIGNvb3JkaW5hdGlvbiwgb3IgcmVtb3RlIGNvbnRyb2wgc2NlbmFyaW9zLlxyXG4gICAqIFxyXG4gICAqIE5vdGU6IFJlbW90ZSBjb21tYW5kcyBjYW4gb25seSBiZSBkZWxpdmVyZWQgdG8gZGV2aWNlcyB3aXRoaW4gdGhlIHNhbWUgYWNjb3VudCBhcyB0aGUgc2VuZGVyIGRldmljZS5cclxuICAgKiBcclxuICAgKiBAcGFyYW0gZGV2aWNlS2V5cyAtIEFycmF5IG9mIHRhcmdldCBkZXZpY2Uga2V5cyB0byBzZW5kIHRoZSBjb21tYW5kIHRvXHJcbiAgICogQHBhcmFtIG5hbWUgLSBUaGUgY29tbWFuZCBuYW1lL2lkZW50aWZpZXJcclxuICAgKiBAcGFyYW0gYXJnIC0gVGhlIGNvbW1hbmQgYXJndW1lbnQvcGF5bG9hZFxyXG4gICAqIFxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiAvLyBTZW5kIGNvbW1hbmQgdG8gc3BlY2lmaWMgZGV2aWNlc1xyXG4gICAqIGNvbnN0IHRhcmdldERldmljZXMgPSBbJ2RldmljZS1rZXktMScsICdkZXZpY2Uta2V5LTInXTtcclxuICAgKiB0aGlzLmNsaWVudC5zZW5kUmVtb3RlQ29tbWFuZCh0YXJnZXREZXZpY2VzLCAnc3luY0FjdGlvbicsICdzdGFydCcpO1xyXG4gICAqIFxyXG4gICAqIC8vIEJyb2FkY2FzdCB0byBtdWx0aXBsZSBkZXZpY2VzXHJcbiAgICogdGhpcy5jbGllbnQuc2VuZFJlbW90ZUNvbW1hbmQoXHJcbiAgICogICBbJ2xvYmJ5LWRpc3BsYXknLCAna2lvc2stMScsICdraW9zay0yJ10sIFxyXG4gICAqICAgJ3VwZGF0ZUNvbnRlbnQnLCBcclxuICAgKiAgIEpTT04uc3RyaW5naWZ5KHsgY29udGVudElkOiAnMTIzNDUnIH0pXHJcbiAgICogKTtcclxuICAgKiBgYGBcclxuICAgKi9cclxuICBwdWJsaWMgc2VuZFJlbW90ZUNvbW1hbmQoZGV2aWNlS2V5czogc3RyaW5nW10sIG5hbWU6IHN0cmluZywgYXJnOiBzdHJpbmcpOiB2b2lkIHtcclxuXHJcbiAgICB0aGlzLmdldENsaWVudCgpLnRoZW4oKGNsaWVudCkgPT4ge1xyXG4gICAgICBjbGllbnQuc2VuZFJlbW90ZUNvbW1hbmQoZGV2aWNlS2V5cywgbmFtZSwgYXJnKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTG9ncyBhbiBhbmFseXRpY3MgZXZlbnQgZm9yIHVzZSB3aXRoIEFkSGF3ayBhbmFseXRpY3MgYW5kIHJlcG9ydGluZy5cclxuICAgKiBcclxuICAgKiBFdmVudHMgYXJlIHVzZWQgZm9yIHRyYWNraW5nIHZhcmlvdXMgbWV0cmljcyBpbmNsdWRpbmcgdXNhZ2Ugc3RhdGlzdGljcywgXHJcbiAgICogcGxheWVyIGNvbmRpdGlvbiwgc3RhdGUgY2hhbmdlcywgdXNlciBpbnRlcmFjdGlvbnMsIGFuZCBjdXN0b20gYnVzaW5lc3MgbWV0cmljcy5cclxuICAgKiBUaGVzZSBldmVudHMgY2FuIGJlIHZpZXdlZCBpbiB0aGUgUmV2ZWwgRGlnaXRhbCBhbmFseXRpY3MgZGFzaGJvYXJkLlxyXG4gICAqIFxyXG4gICAqIEBwYXJhbSBldmVudE5hbWUgLSBVbmlxdWUgbmFtZSBmb3IgdGhpcyBldmVudCAoc2hvdWxkIGJlIGRlc2NyaXB0aXZlIGFuZCBjb25zaXN0ZW50KVxyXG4gICAqIEBwYXJhbSBwcm9wZXJ0aWVzIC0gT3B0aW9uYWwgbWFwIG9mIHVzZXItZGVmaW5lZCBwcm9wZXJ0aWVzIHRvIGFzc29jaWF0ZSB3aXRoIHRoaXMgZXZlbnRcclxuICAgKiBcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogLy8gU2ltcGxlIGV2ZW50IHRyYWNraW5nXHJcbiAgICogdGhpcy5jbGllbnQudHJhY2soJ2dhZGdldF9sb2FkZWQnKTtcclxuICAgKiBcclxuICAgKiAvLyBFdmVudCB3aXRoIHByb3BlcnRpZXNcclxuICAgKiB0aGlzLmNsaWVudC50cmFjaygndXNlcl9pbnRlcmFjdGlvbicsIHtcclxuICAgKiAgIGFjdGlvbjogJ2J1dHRvbl9jbGljaycsXHJcbiAgICogICBidXR0b25faWQ6ICdzdGFydF9idXR0b24nLFxyXG4gICAqICAgdGltZXN0YW1wOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKClcclxuICAgKiB9KTtcclxuICAgKiBcclxuICAgKiAvLyBQZXJmb3JtYW5jZSB0cmFja2luZ1xyXG4gICAqIHRoaXMuY2xpZW50LnRyYWNrKCdjb250ZW50X2Rpc3BsYXllZCcsIHtcclxuICAgKiAgIGNvbnRlbnRfdHlwZTogJ3ZpZGVvJyxcclxuICAgKiAgIGR1cmF0aW9uOiAzMCxcclxuICAgKiAgIHF1YWxpdHk6ICdIRCdcclxuICAgKiB9KTtcclxuICAgKiBgYGBcclxuICAgKi9cclxuICBwdWJsaWMgdHJhY2soZXZlbnROYW1lOiBzdHJpbmcsIHByb3BlcnRpZXM/OiBJRXZlbnRQcm9wZXJ0aWVzKTogdm9pZCB7XHJcblxyXG4gICAgdGhpcy5nZXRDbGllbnQoKS50aGVuKChjbGllbnQpID0+IHtcclxuICAgICAgY2xpZW50LnRyYWNrKGV2ZW50TmFtZSwgSlNPTi5zdHJpbmdpZnkocHJvcGVydGllcykpO1xyXG4gICAgfSlcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEluaXRpYXRlcyBhIHRpbWVkIGV2ZW50IGZvciBkdXJhdGlvbiB0cmFja2luZy5cclxuICAgKiBcclxuICAgKiBUaW1lZCBldmVudHMgYXJlIHVzZWZ1bCBmb3IgdHJhY2tpbmcgdGhlIGR1cmF0aW9uIG9mIG9wZXJhdGlvbnMgb3IgdXNlciBpbnRlcmFjdGlvbnMuXHJcbiAgICogVGhpcyBtZXRob2QgbXVzdCBiZSBmb2xsb3dlZCBieSBhIGNhbGwgdG8gdHJhY2soKSB3aXRoIHRoZSBzYW1lIGV2ZW50IG5hbWUgdG8gY29tcGxldGVcclxuICAgKiB0aGUgdGltaW5nIG1lYXN1cmVtZW50LiBUaGUgZHVyYXRpb24gd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGNhbGN1bGF0ZWQgYW5kIGluY2x1ZGVkXHJcbiAgICogaW4gdGhlIGV2ZW50IHByb3BlcnRpZXMuXHJcbiAgICogXHJcbiAgICogQHBhcmFtIGV2ZW50TmFtZSAtIFVuaXF1ZSBuYW1lIGZvciB0aGlzIHRpbWVkIGV2ZW50IChtdXN0IG1hdGNoIHRoZSBzdWJzZXF1ZW50IHRyYWNrKCkgY2FsbClcclxuICAgKiBcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogLy8gU3RhcnQgdGltaW5nIGFuIGV2ZW50XHJcbiAgICogdGhpcy5jbGllbnQudGltZUV2ZW50KCd2aWRlb19wbGF5YmFjaycpO1xyXG4gICAqIFxyXG4gICAqIC8vIC4uLiB2aWRlbyBwbGF5cyBmb3Igc29tZSBkdXJhdGlvbiAuLi5cclxuICAgKiBcclxuICAgKiAvLyBFbmQgdGltaW5nIGFuZCBsb2cgdGhlIGV2ZW50IHdpdGggZHVyYXRpb25cclxuICAgKiB0aGlzLmNsaWVudC50cmFjaygndmlkZW9fcGxheWJhY2snLCB7XHJcbiAgICogICB2aWRlb19pZDogJ2FiYzEyMycsXHJcbiAgICogICBxdWFsaXR5OiAnSEQnXHJcbiAgICogfSk7IC8vIER1cmF0aW9uIHdpbGwgYmUgYXV0b21hdGljYWxseSBhZGRlZFxyXG4gICAqIFxyXG4gICAqIC8vIEV4YW1wbGUgZm9yIHVzZXIgaW50ZXJhY3Rpb24gdGltaW5nXHJcbiAgICogdGhpcy5jbGllbnQudGltZUV2ZW50KCdmb3JtX2NvbXBsZXRpb24nKTtcclxuICAgKiAvLyAuLi4gdXNlciBmaWxscyBvdXQgZm9ybSAuLi5cclxuICAgKiB0aGlzLmNsaWVudC50cmFjaygnZm9ybV9jb21wbGV0aW9uJywgeyBmb3JtX3R5cGU6ICdjb250YWN0JyB9KTtcclxuICAgKiBgYGBcclxuICAgKi9cclxuICBwdWJsaWMgdGltZUV2ZW50KGV2ZW50TmFtZTogc3RyaW5nKTogdm9pZCB7XHJcblxyXG4gICAgdGhpcy5nZXRDbGllbnQoKS50aGVuKChjbGllbnQpID0+IHtcclxuICAgICAgY2xpZW50LnRpbWVFdmVudChldmVudE5hbWUpO1xyXG4gICAgfSlcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENyZWF0ZXMgYSBuZXcgYW5hbHl0aWNzIGV2ZW50IHNlc3Npb24gZm9yIGdyb3VwaW5nIHJlbGF0ZWQgZXZlbnRzLlxyXG4gICAqIFxyXG4gICAqIEEgc2Vzc2lvbiBpcyBhIHdheSBvZiBncm91cGluZyBldmVudHMgdG9nZXRoZXIgZm9yIGFuYWx5c2lzLiBFYWNoIGV2ZW50IHRyYWNrZWRcclxuICAgKiBhZnRlciBjYWxsaW5nIHRoaXMgbWV0aG9kIHdpbGwgaGF2ZSB0aGUgc2FtZSBzZXNzaW9uIElEIHVudGlsIGEgbmV3IHNlc3Npb24gaXMgY3JlYXRlZC5cclxuICAgKiBTZXNzaW9uIElEcyBhcmUgcmFuZG9tbHkgZ2VuZXJhdGVkIHVubGVzcyBleHBsaWNpdGx5IHByb3ZpZGVkLlxyXG4gICAqIFxyXG4gICAqIFRoaXMgaXMgdXNlZnVsIGZvciB0cmFja2luZyB1c2VyIGpvdXJuZXlzLCB3b3JrZmxvdyBjb21wbGV0aW9uLCBvciBncm91cGluZ1xyXG4gICAqIHJlbGF0ZWQgaW50ZXJhY3Rpb25zIHdpdGhpbiBhIHNwZWNpZmljIHRpbWUgcGVyaW9kLlxyXG4gICAqIFxyXG4gICAqIEBwYXJhbSBpZCAtIE9wdGlvbmFsIHVzZXItc3VwcGxpZWQgc2Vzc2lvbiBJRC4gSWYgbm90IHByb3ZpZGVkLCBhIHJhbmRvbSBzZXNzaW9uIElEIHdpbGwgYmUgZ2VuZXJhdGVkXHJcbiAgICogXHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIC8vIFN0YXJ0IGEgbmV3IHNlc3Npb24gd2l0aCBhdXRvLWdlbmVyYXRlZCBJRFxyXG4gICAqIHRoaXMuY2xpZW50Lm5ld0V2ZW50U2Vzc2lvbigpO1xyXG4gICAqIHRoaXMuY2xpZW50LnRyYWNrKCdzZXNzaW9uX3N0YXJ0Jyk7XHJcbiAgICogdGhpcy5jbGllbnQudHJhY2soJ3VzZXJfYWN0aW9uXzEnKTtcclxuICAgKiB0aGlzLmNsaWVudC50cmFjaygndXNlcl9hY3Rpb25fMicpO1xyXG4gICAqIFxyXG4gICAqIC8vIFN0YXJ0IGEgc2Vzc2lvbiB3aXRoIGN1c3RvbSBJRFxyXG4gICAqIHRoaXMuY2xpZW50Lm5ld0V2ZW50U2Vzc2lvbigndXNlci13b3JrZmxvdy0xMjM0NScpO1xyXG4gICAqIHRoaXMuY2xpZW50LnRyYWNrKCd3b3JrZmxvd19zdGFydCcpO1xyXG4gICAqIHRoaXMuY2xpZW50LnRyYWNrKCdzdGVwX2NvbXBsZXRlZCcsIHsgc3RlcDogMSB9KTtcclxuICAgKiBcclxuICAgKiAvLyBTdGFydCBhIG5ldyBzZXNzaW9uIGZvciBkaWZmZXJlbnQgd29ya2Zsb3dcclxuICAgKiB0aGlzLmNsaWVudC5uZXdFdmVudFNlc3Npb24oKTtcclxuICAgKiB0aGlzLmNsaWVudC50cmFjaygnZGlmZmVyZW50X3dvcmtmbG93X3N0YXJ0Jyk7XHJcbiAgICogYGBgXHJcbiAgICovXHJcbiAgcHVibGljIG5ld0V2ZW50U2Vzc2lvbihpZD86IHN0cmluZyk6IHZvaWQge1xyXG5cclxuICAgIHRoaXMuZ2V0Q2xpZW50KCkudGhlbigoY2xpZW50KSA9PiB7XHJcbiAgICAgIGlmIChpZCAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgY2xpZW50Lm5ld0V2ZW50U2Vzc2lvbigpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGNsaWVudC5uZXdFdmVudFNlc3Npb24oaWQpO1xyXG4gICAgICB9XHJcbiAgICB9KVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0cyB0aGUgcm9vdCBmb2xkZXIgcGF0aCB1dGlsaXplZCBieSB0aGlzIHBsYXllciBkZXZpY2UuXHJcbiAgICogXHJcbiAgICogVGhpcyByZXR1cm5zIHRoZSBiYXNlIGRpcmVjdG9yeSBwYXRoIHdoZXJlIHRoZSBSZXZlbCBEaWdpdGFsIHBsYXllclxyXG4gICAqIHN0b3JlcyBpdHMgZmlsZXMgYW5kIHJlc291cmNlcyBvbiB0aGUgbG9jYWwgZGV2aWNlLlxyXG4gICAqIFxyXG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBwYXRoIG9mIHRoZSByb290IGZvbGRlclxyXG4gICAqIFxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiBjb25zdCByb290UGF0aCA9IGF3YWl0IHRoaXMuY2xpZW50LmdldFJldmVsUm9vdCgpO1xyXG4gICAqIGNvbnNvbGUubG9nKCdQbGF5ZXIgcm9vdCBkaXJlY3Rvcnk6Jywgcm9vdFBhdGgpO1xyXG4gICAqIC8vIFVzZSBmb3IgY29uc3RydWN0aW5nIGZpbGUgcGF0aHMgb3IgdW5kZXJzdGFuZGluZyBzdG9yYWdlIHN0cnVjdHVyZVxyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIHB1YmxpYyBhc3luYyBnZXRSZXZlbFJvb3QoKTogUHJvbWlzZTxzdHJpbmc+IHtcclxuXHJcbiAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldENsaWVudCgpO1xyXG5cclxuICAgIHJldHVybiBjbGllbnQuZ2V0UmV2ZWxSb290KCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXRzIGEgbWFwIG9mIGNvbW1hbmRzIGN1cnJlbnRseSBhY3RpdmUgZm9yIHRoaXMgZGV2aWNlLlxyXG4gICAqIFxyXG4gICAqIFRoaXMgcmV0dXJucyB0aGUgY3VycmVudCBjb21tYW5kIGNvbmZpZ3VyYXRpb24gdGhhdCBkZWZpbmVzIGhvdyB0aGUgZGV2aWNlXHJcbiAgICogcmVzcG9uZHMgdG8gdmFyaW91cyBjb21tYW5kIHRyaWdnZXJzIGFuZCByZW1vdGUgY29tbWFuZHMuXHJcbiAgICogXHJcbiAgICogQHJldHVybnMgUHJvbWlzZSByZXNvbHZpbmcgdG8gYSBtYXAgb2YgY3VycmVudGx5IGFjdGl2ZSBjb21tYW5kc1xyXG4gICAqIFxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiBjb25zdCBjb21tYW5kTWFwID0gYXdhaXQgdGhpcy5jbGllbnQuZ2V0Q29tbWFuZE1hcCgpO1xyXG4gICAqIGNvbnNvbGUubG9nKCdBY3RpdmUgY29tbWFuZHM6JywgY29tbWFuZE1hcCk7XHJcbiAgICogXHJcbiAgICogLy8gQ2hlY2sgaWYgc3BlY2lmaWMgY29tbWFuZCBpcyBhdmFpbGFibGVcclxuICAgKiBpZiAoY29tbWFuZE1hcFsnY3VzdG9tQ29tbWFuZCddKSB7XHJcbiAgICogICBjb25zb2xlLmxvZygnQ3VzdG9tIGNvbW1hbmQgaXMgYXZhaWxhYmxlJyk7XHJcbiAgICogfVxyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIHB1YmxpYyBhc3luYyBnZXRDb21tYW5kTWFwKCk6IFByb21pc2U8YW55PiB7XHJcblxyXG4gICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKTtcclxuXHJcbiAgICByZXR1cm4gSlNPTi5wYXJzZShhd2FpdCBjbGllbnQuZ2V0Q29tbWFuZE1hcCgpKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNpZ25hbHMgdG8gdGhlIHBsYXllciB0aGF0IHRoaXMgZ2FkZ2V0IGhhcyBjb21wbGV0ZWQgaXRzIHZpc3VhbGl6YXRpb24uXHJcbiAgICogXHJcbiAgICogVGhpcyBtZXRob2Qgbm90aWZpZXMgdGhlIHBsYXllciB0aGF0IHRoZSBjdXJyZW50IGdhZGdldCBoYXMgZmluaXNoZWQgaXRzXHJcbiAgICogY29udGVudCBkaXNwbGF5IG9yIGludGVyYWN0aW9uIGN5Y2xlLiBUaGUgcGxheWVyIGNhbiB0aGVuIHByb2NlZWQgd2l0aFxyXG4gICAqIHRoZSBuZXh0IGl0ZW0gaW4gYSBwbGF5bGlzdCBpZiBhcHBsaWNhYmxlLCBvciBoYW5kbGUgdGhlIGNvbXBsZXRpb25cclxuICAgKiBhY2NvcmRpbmcgdG8gaXRzIGNvbmZpZ3VyYXRpb24uXHJcbiAgICogXHJcbiAgICogQ2FsbCB0aGlzIG1ldGhvZCB3aGVuIHlvdXIgZ2FkZ2V0IGhhcyBjb21wbGV0ZWQgaXRzIGludGVuZGVkIGZ1bmN0aW9uLFxyXG4gICAqIHN1Y2ggYXMgZmluaXNoaW5nIGFuIGFuaW1hdGlvbiwgY29tcGxldGluZyBhIGZvcm0sIG9yIHJlYWNoaW5nIGEgbmF0dXJhbFxyXG4gICAqIHN0b3BwaW5nIHBvaW50LlxyXG4gICAqIFxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiAvLyBBZnRlciBjb21wbGV0aW5nIGFuIGFuaW1hdGlvblxyXG4gICAqIHByaXZhdGUgb25BbmltYXRpb25Db21wbGV0ZSgpOiB2b2lkIHtcclxuICAgKiAgIHRoaXMuY2xpZW50LmZpbmlzaCgpO1xyXG4gICAqIH1cclxuICAgKiBcclxuICAgKiAvLyBBZnRlciB1c2VyIGludGVyYWN0aW9uIGlzIGNvbXBsZXRlXHJcbiAgICogcHJpdmF0ZSBvbkZvcm1TdWJtaXR0ZWQoKTogdm9pZCB7XHJcbiAgICogICB0aGlzLnNhdmVGb3JtRGF0YSgpO1xyXG4gICAqICAgdGhpcy5jbGllbnQuZmluaXNoKCk7XHJcbiAgICogfVxyXG4gICAqIFxyXG4gICAqIC8vIEFmdGVyIGEgdGltZWQgZGlzcGxheSBwZXJpb2RcclxuICAgKiBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgKiAgIHRoaXMuY2xpZW50LmZpbmlzaCgpO1xyXG4gICAqIH0sIDMwMDAwKTsgLy8gMzAgc2Vjb25kc1xyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIHB1YmxpYyBmaW5pc2goKTogdm9pZCB7XHJcblxyXG4gICAgdGhpcy5nZXRDbGllbnQoKS50aGVuKChjbGllbnQpID0+IHtcclxuXHJcbiAgICAgIGNsaWVudC5maW5pc2goKTtcclxuICAgIH0pXHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDaGVja3MgaWYgdGhlIGdhZGdldCBpcyBydW5uaW5nIGluIHByZXZpZXcgbW9kZS5cclxuICAgKiBcclxuICAgKiBQcmV2aWV3IG1vZGUgaXMgZW5hYmxlZCB3aGVuIHRoZSBnYWRnZXQgaXMgYmVpbmcgZWRpdGVkIGluIHRoZSBSZXZlbCBEaWdpdGFsIENNUyxcclxuICAgKiB0ZXN0ZWQgaW4gdGhlIGdhZGdldCBlZGl0b3IsIG9yIG90aGVyd2lzZSBub3QgcnVubmluZyBpbiBhIG5vcm1hbCBwbGF5ZXIgZW52aXJvbm1lbnQuXHJcbiAgICogVGhpcyBpcyB1c2VmdWwgZm9yIHByb3ZpZGluZyBkaWZmZXJlbnQgYmVoYXZpb3IgZHVyaW5nIGRldmVsb3BtZW50L3Rlc3RpbmcgdmVyc3VzXHJcbiAgICogcHJvZHVjdGlvbiBkZXBsb3ltZW50LlxyXG4gICAqIFxyXG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIHRydWUgaWYgcnVubmluZyBpbiBwcmV2aWV3IG1vZGUsIGZhbHNlIGlmIHJ1bm5pbmcgb24gYWN0dWFsIHBsYXllclxyXG4gICAqIFxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiBjb25zdCBpc1ByZXZpZXcgPSBhd2FpdCB0aGlzLmNsaWVudC5pc1ByZXZpZXdNb2RlKCk7XHJcbiAgICogXHJcbiAgICogaWYgKGlzUHJldmlldykge1xyXG4gICAqICAgY29uc29sZS5sb2coJ1J1bm5pbmcgaW4gcHJldmlldyBtb2RlIC0gdXNpbmcgbW9jayBkYXRhJyk7XHJcbiAgICogICB0aGlzLmxvYWRNb2NrRGF0YSgpO1xyXG4gICAqIH0gZWxzZSB7XHJcbiAgICogICBjb25zb2xlLmxvZygnUnVubmluZyBvbiBwbGF5ZXIgZGV2aWNlIC0gdXNpbmcgbGl2ZSBkYXRhJyk7XHJcbiAgICogICB0aGlzLmxvYWRMaXZlRGF0YSgpO1xyXG4gICAqIH1cclxuICAgKiBcclxuICAgKiAvLyBTaG93IGRpZmZlcmVudCBVSSBpbiBwcmV2aWV3XHJcbiAgICogdGhpcy5zaG93UHJldmlld0luZGljYXRvciA9IGlzUHJldmlldztcclxuICAgKiBgYGBcclxuICAgKi9cclxuICBwdWJsaWMgYXN5bmMgaXNQcmV2aWV3TW9kZSgpOiBQcm9taXNlPGJvb2xlYW4+IHtcclxuXHJcbiAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldENsaWVudCgpO1xyXG5cclxuICAgIHJldHVybiBjbGllbnQgaW5zdGFuY2VvZiBOb29wQ2xpZW50O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0cyBkZXRhaWxlZCBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZGV2aWNlIHJ1bm5pbmcgdGhlIHBsYXllci5cclxuICAgKiBcclxuICAgKiBSZXR1cm5zIGNvbXByZWhlbnNpdmUgZGV2aWNlIGRldGFpbHMgaW5jbHVkaW5nIG5hbWUsIHJlZ2lzdHJhdGlvbiBrZXksIHR5cGUsXHJcbiAgICogc2VydmljZSBkYXRlLCBsYW5ndWFnZSwgdGltZXpvbmUsIHRhZ3MsIGFuZCBsb2NhdGlvbiBpbmZvcm1hdGlvbi4gVGhpcyBkYXRhXHJcbiAgICogaXMgY29uZmlndXJlZCBpbiB0aGUgUmV2ZWwgRGlnaXRhbCBDTVMgZm9yIGVhY2ggZGV2aWNlLlxyXG4gICAqIFxyXG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIGRldmljZSBkZXRhaWxzIG9iamVjdCwgb3IgbnVsbCBpZiBub3QgYXZhaWxhYmxlXHJcbiAgICogXHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIGNvbnN0IGRldmljZSA9IGF3YWl0IHRoaXMuY2xpZW50LmdldERldmljZSgpO1xyXG4gICAqIFxyXG4gICAqIGlmIChkZXZpY2UpIHtcclxuICAgKiAgIGNvbnNvbGUubG9nKCdEZXZpY2UgbmFtZTonLCBkZXZpY2UubmFtZSk7XHJcbiAgICogICBjb25zb2xlLmxvZygnRGV2aWNlIHR5cGU6JywgZGV2aWNlLmRldmljZVR5cGUpO1xyXG4gICAqICAgY29uc29sZS5sb2coJ0xvY2F0aW9uOicsIGRldmljZS5sb2NhdGlvbi5jaXR5LCBkZXZpY2UubG9jYXRpb24uc3RhdGUpO1xyXG4gICAqICAgY29uc29sZS5sb2coJ1RhZ3M6JywgZGV2aWNlLnRhZ3MpO1xyXG4gICAqICAgXHJcbiAgICogICAvLyBVc2UgZGV2aWNlIGluZm8gZm9yIGN1c3RvbWl6YXRpb25cclxuICAgKiAgIGlmIChkZXZpY2UubG9jYXRpb24uY291bnRyeSA9PT0gJ1VTJykge1xyXG4gICAqICAgICB0aGlzLmxvYWRVU0NvbnRlbnQoKTtcclxuICAgKiAgIH1cclxuICAgKiAgIFxyXG4gICAqICAgLy8gQ2hlY2sgZGV2aWNlIGNhcGFiaWxpdGllcyBiYXNlZCBvbiB0eXBlXHJcbiAgICogICBpZiAoZGV2aWNlLmRldmljZVR5cGUgPT09ICdhbmRyb2lkJykge1xyXG4gICAqICAgICB0aGlzLmVuYWJsZVRvdWNoRmVhdHVyZXMoKTtcclxuICAgKiAgIH1cclxuICAgKiB9XHJcbiAgICogYGBgXHJcbiAgICovXHJcbiAgcHVibGljIGFzeW5jIGdldERldmljZSgpOiBQcm9taXNlPElEZXZpY2UgfCBudWxsPiB7XHJcblxyXG4gICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKTtcclxuXHJcbiAgICBsZXQgb2JqOiBhbnkgPSBKU09OLnBhcnNlKDxzdHJpbmc+YXdhaXQgY2xpZW50LmdldERldmljZSgpKTtcclxuXHJcbiAgICBjb25zdCBkZXZpY2U6IElEZXZpY2VbXSA9IFtvYmpdLm1hcCgoZGV2aWNlOiBhbnkpID0+IHtcclxuXHJcbiAgICAgIHJldHVybiB7XHJcbiAgICAgICAgbmFtZTogZGV2aWNlLm5hbWUsXHJcbiAgICAgICAgcmVnaXN0cmF0aW9uS2V5OiBkZXZpY2Uua2V5LFxyXG4gICAgICAgIGRldmljZVR5cGU6IGRldmljZS5kZXZpY2V0eXBlLFxyXG4gICAgICAgIGVudGVyZWRTZXJ2aWNlOiBuZXcgRGF0ZShkZXZpY2UuZW50ZXJlZHNlcnZpY2UpLFxyXG4gICAgICAgIGxhbmdDb2RlOiBkZXZpY2UubGFuZ2NvZGUsXHJcbiAgICAgICAgdGltZVpvbmU6IGRldmljZS50aW1lem9uZSxcclxuICAgICAgICB0YWdzOiBkZXZpY2UuZGVzY3JpcHRpb24/LnNwbGl0KCdcXG4nKSxcclxuICAgICAgICBsb2NhdGlvbjoge1xyXG4gICAgICAgICAgY2l0eTogZGV2aWNlLmxvY2F0aW9uPy5jaXR5LFxyXG4gICAgICAgICAgc3RhdGU6IGRldmljZS5sb2NhdGlvbj8uc3RhdGUsXHJcbiAgICAgICAgICBjb3VudHJ5OiBkZXZpY2UubG9jYXRpb24/LmNvdW50cnksXHJcbiAgICAgICAgICBwb3N0YWxDb2RlOiBkZXZpY2UubG9jYXRpb24/LnBvc3RhbGNvZGUsXHJcbiAgICAgICAgICBhZGRyZXNzOiBkZXZpY2UubG9jYXRpb24/LmFkZHJlc3MsXHJcbiAgICAgICAgICBsYXRpdHVkZTogZGV2aWNlLmxvY2F0aW9uPy5sYXRpdHVkZSxcclxuICAgICAgICAgIGxvbmdpdHVkZTogZGV2aWNlLmxvY2F0aW9uPy5sb25naXR1ZGVcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIGRldmljZVswXTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldHMgdGhlIHdpZHRoIG9mIHRoZSB2aXN1YWxpemF0aW9uIGFyZWEgaW4gcGl4ZWxzLlxyXG4gICAqIFxyXG4gICAqIFRoaXMgcmV0dXJucyB0aGUgYXZhaWxhYmxlIHdpZHRoIGZvciBjb250ZW50IGRpc3BsYXksIHdoaWNoIG1heSBiZVxyXG4gICAqIGRpZmZlcmVudCBmcm9tIHRoZSBmdWxsIHNjcmVlbiB3aWR0aCBkZXBlbmRpbmcgb24gcGxheWVyIGNvbmZpZ3VyYXRpb25cclxuICAgKiBhbmQgdGVtcGxhdGUgbGF5b3V0LlxyXG4gICAqIFxyXG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIHdpZHRoIGluIHBpeGVscywgb3IgbnVsbCBpZiBub3QgYXZhaWxhYmxlXHJcbiAgICogXHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIGNvbnN0IHdpZHRoID0gYXdhaXQgdGhpcy5jbGllbnQuZ2V0V2lkdGgoKTtcclxuICAgKiBcclxuICAgKiBpZiAod2lkdGgpIHtcclxuICAgKiAgIGNvbnNvbGUubG9nKCdBdmFpbGFibGUgd2lkdGg6Jywgd2lkdGgsICdwaXhlbHMnKTtcclxuICAgKiAgIFxyXG4gICAqICAgLy8gQWRhcHQgY29udGVudCBsYXlvdXQgYmFzZWQgb24gd2lkdGhcclxuICAgKiAgIGlmICh3aWR0aCA8IDgwMCkge1xyXG4gICAqICAgICB0aGlzLmVuYWJsZU1vYmlsZUxheW91dCgpO1xyXG4gICAqICAgfSBlbHNlIHtcclxuICAgKiAgICAgdGhpcy5lbmFibGVEZXNrdG9wTGF5b3V0KCk7XHJcbiAgICogICB9XHJcbiAgICogfVxyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIHB1YmxpYyBhc3luYyBnZXRXaWR0aCgpOiBQcm9taXNlPG51bWJlciB8IG51bGw+IHtcclxuXHJcbiAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldENsaWVudCgpO1xyXG5cclxuICAgIHJldHVybiBjbGllbnQuZ2V0V2lkdGgoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldHMgdGhlIGhlaWdodCBvZiB0aGUgdmlzdWFsaXphdGlvbiBhcmVhIGluIHBpeGVscy5cclxuICAgKiBcclxuICAgKiBUaGlzIHJldHVybnMgdGhlIGF2YWlsYWJsZSBoZWlnaHQgZm9yIGNvbnRlbnQgZGlzcGxheSwgd2hpY2ggbWF5IGJlXHJcbiAgICogZGlmZmVyZW50IGZyb20gdGhlIGZ1bGwgc2NyZWVuIGhlaWdodCBkZXBlbmRpbmcgb24gcGxheWVyIGNvbmZpZ3VyYXRpb25cclxuICAgKiBhbmQgdGVtcGxhdGUgbGF5b3V0LlxyXG4gICAqIFxyXG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIGhlaWdodCBpbiBwaXhlbHMsIG9yIG51bGwgaWYgbm90IGF2YWlsYWJsZVxyXG4gICAqIFxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiBjb25zdCBoZWlnaHQgPSBhd2FpdCB0aGlzLmNsaWVudC5nZXRIZWlnaHQoKTtcclxuICAgKiBcclxuICAgKiBpZiAoaGVpZ2h0KSB7XHJcbiAgICogICBjb25zb2xlLmxvZygnQXZhaWxhYmxlIGhlaWdodDonLCBoZWlnaHQsICdwaXhlbHMnKTtcclxuICAgKiAgIFxyXG4gICAqICAgLy8gQ2FsY3VsYXRlIGFzcGVjdCByYXRpbyBmb3IgcmVzcG9uc2l2ZSBkZXNpZ25cclxuICAgKiAgIGNvbnN0IHdpZHRoID0gYXdhaXQgdGhpcy5jbGllbnQuZ2V0V2lkdGgoKTtcclxuICAgKiAgIGNvbnN0IGFzcGVjdFJhdGlvID0gd2lkdGggLyBoZWlnaHQ7XHJcbiAgICogICB0aGlzLmFkanVzdENvbnRlbnRGb3JBc3BlY3RSYXRpbyhhc3BlY3RSYXRpbyk7XHJcbiAgICogfVxyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIHB1YmxpYyBhc3luYyBnZXRIZWlnaHQoKTogUHJvbWlzZTxudW1iZXIgfCBudWxsPiB7XHJcblxyXG4gICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKTtcclxuXHJcbiAgICByZXR1cm4gY2xpZW50LmdldEhlaWdodCgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0cyB0aGUgZHVyYXRpb24gb2YgdGhlIGN1cnJlbnRseSBwbGF5aW5nIGNvbnRlbnQgaXRlbS5cclxuICAgKiBcclxuICAgKiBUaGlzIG1ldGhvZCBpcyBvbmx5IGFwcGxpY2FibGUgd2hlbiB0aGUgZ2FkZ2V0IGlzIGFzc29jaWF0ZWQgd2l0aCBhIHBsYXlsaXN0XHJcbiAgICogYW5kIHJldHVybnMgdGhlIGR1cmF0aW9uIGFzc2lnbmVkIHRvIHRoZSBjdXJyZW50IHBsYXlsaXN0IGl0ZW0uIFRoZSBkdXJhdGlvblxyXG4gICAqIGRldGVybWluZXMgaG93IGxvbmcgdGhlIGNvbnRlbnQgc2hvdWxkIGJlIGRpc3BsYXllZCBiZWZvcmUgbW92aW5nIHRvIHRoZSBuZXh0IGl0ZW0uXHJcbiAgICogXHJcbiAgICogQHJldHVybnMgUHJvbWlzZSByZXNvbHZpbmcgdG8gZHVyYXRpb24gaW4gbWlsbGlzZWNvbmRzLCBvciBudWxsIGlmIG5vdCBhcHBsaWNhYmxlL2F2YWlsYWJsZVxyXG4gICAqIFxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiBjb25zdCBkdXJhdGlvbiA9IGF3YWl0IHRoaXMuY2xpZW50LmdldER1cmF0aW9uKCk7XHJcbiAgICogXHJcbiAgICogaWYgKGR1cmF0aW9uKSB7XHJcbiAgICogICBjb25zb2xlLmxvZygnQ29udGVudCBkdXJhdGlvbjonLCBkdXJhdGlvbiwgJ21pbGxpc2Vjb25kcycpO1xyXG4gICAqICAgXHJcbiAgICogICAvLyBTZXQgdXAgYXV0by1maW5pc2ggdGltZXJcclxuICAgKiAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAqICAgICB0aGlzLmNsaWVudC5maW5pc2goKTtcclxuICAgKiAgIH0sIGR1cmF0aW9uKTtcclxuICAgKiAgIFxyXG4gICAqICAgLy8gU2hvdyBwcm9ncmVzcyBpbmRpY2F0b3JcclxuICAgKiAgIHRoaXMuc3RhcnRQcm9ncmVzc0luZGljYXRvcihkdXJhdGlvbik7XHJcbiAgICogfVxyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIHB1YmxpYyBhc3luYyBnZXREdXJhdGlvbigpOiBQcm9taXNlPG51bWJlciB8IG51bGw+IHtcclxuXHJcbiAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldENsaWVudCgpO1xyXG5cclxuICAgIHJldHVybiBjbGllbnQuZ2V0RHVyYXRpb24oKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldHMgdGhlIGN1cnJlbnQgdmVyc2lvbiBvZiB0aGUgUmV2ZWwgRGlnaXRhbCBTREsuXHJcbiAgICogXHJcbiAgICogQHJldHVybnMgUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIFNESyB2ZXJzaW9uIHN0cmluZ1xyXG4gICAqIFxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiBjb25zdCB2ZXJzaW9uID0gYXdhaXQgdGhpcy5jbGllbnQuZ2V0U2RrVmVyc2lvbigpO1xyXG4gICAqIGNvbnNvbGUubG9nKCdTREsgVmVyc2lvbjonLCB2ZXJzaW9uKTtcclxuICAgKiBcclxuICAgKiAvLyBVc2UgZm9yIGNvbXBhdGliaWxpdHkgY2hlY2tzIG9yIGxvZ2dpbmdcclxuICAgKiB0aGlzLmNsaWVudC50cmFjaygnZ2FkZ2V0X2xvYWRlZCcsIHsgc2RrVmVyc2lvbjogdmVyc2lvbiB9KTtcclxuICAgKiBgYGBcclxuICAgKi9cclxuICBwdWJsaWMgYXN5bmMgZ2V0U2RrVmVyc2lvbigpOiBQcm9taXNlPHN0cmluZz4ge1xyXG5cclxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodmVyc2lvbik7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBBcHBsaWVzIGNvbmZpZ3VyYXRpb24gcHJlZmVyZW5jZXMgdG8gdGhlIGdhZGdldCAocHJldmlldyBtb2RlIG9ubHkpLlxyXG4gICAqIFxyXG4gICAqIFRoaXMgbWV0aG9kIGlzIG9ubHkgYXZhaWxhYmxlIHdoZW4gcnVubmluZyBpbiBwcmV2aWV3IG1vZGUgKHR5cGljYWxseSBkdXJpbmdcclxuICAgKiBnYWRnZXQgZGV2ZWxvcG1lbnQgb3IgdGVzdGluZyBpbiB0aGUgQ01TKS4gSXQgYWxsb3dzIGFwcGx5aW5nIGNvbmZpZ3VyYXRpb25cclxuICAgKiBjaGFuZ2VzIHRoYXQgd291bGQgbm9ybWFsbHkgY29tZSBmcm9tIHRoZSBnYWRnZXQncyBwcmVmZXJlbmNlIHNldHRpbmdzLlxyXG4gICAqIFxyXG4gICAqIEBwYXJhbSBwcmVmcyAtIERpY3Rpb25hcnkgb2YgcHJlZmVyZW5jZSBrZXktdmFsdWUgcGFpcnMgdG8gYXBwbHlcclxuICAgKiBcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogaWYgKGF3YWl0IHRoaXMuY2xpZW50LmlzUHJldmlld01vZGUoKSkge1xyXG4gICAqICAgLy8gQXBwbHkgdGVzdCBjb25maWd1cmF0aW9uIGluIHByZXZpZXdcclxuICAgKiAgIGF3YWl0IHRoaXMuY2xpZW50LmFwcGx5Q29uZmlnKHtcclxuICAgKiAgICAgJ3RpdGxlJzogJ1Rlc3QgVGl0bGUnLFxyXG4gICAqICAgICAnYmFja2dyb3VuZENvbG9yJzogJyNmZjAwMDAnLFxyXG4gICAqICAgICAnc2hvd0JvcmRlcic6IHRydWUsXHJcbiAgICogICAgICdyZWZyZXNoSW50ZXJ2YWwnOiAzMFxyXG4gICAqICAgfSk7XHJcbiAgICogfVxyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIHB1YmxpYyBhc3luYyBhcHBseUNvbmZpZyhwcmVmczogSURpY3Rpb25hcnk8YW55Pikge1xyXG5cclxuICAgIGlmIChhd2FpdCB0aGlzLmlzUHJldmlld01vZGUoKSkge1xyXG4gICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldENsaWVudCgpO1xyXG4gICAgICBjbGllbnQuYXBwbHlDb25maWcocHJlZnMpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgY29uc29sZS5sb2coXHJcbiAgICAgICAgJyVjYXBwbHlDb25maWcoKSBpcyBvbmx5IGF2YWlsYWJsZSBpbiBwcmV2aWV3IG1vZGUuJyxcclxuICAgICAgICAnYmFja2dyb3VuZC1jb2xvcjpibHVlOyBjb2xvcjp5ZWxsb3c7J1xyXG4gICAgICApO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8gLS0tXHJcbiAgLy8gUFJJVkFURSBNRVRIT0RTLlxyXG4gIC8vIC0tLVxyXG4gIC8qKiBAaWdub3JlICovXHJcbiAgcHJpdmF0ZSBnZXRDbGllbnQoKTogUHJvbWlzZTxJQ2xpZW50PiB7XHJcblxyXG4gICAgaWYgKHRoaXMuY2xpZW50UHJvbWlzZSkge1xyXG5cclxuICAgICAgcmV0dXJuICh0aGlzLmNsaWVudFByb21pc2UpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh3aW5kb3cuQ2xpZW50KSB7XHJcblxyXG4gICAgICByZXR1cm4gKHRoaXMuY2xpZW50UHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSh3aW5kb3cuQ2xpZW50KSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQSBcImNvbXBsZXRlXCIgc3RhdHVzIGluZGljYXRlcyB0aGF0IHRoZSBcImxvYWRcIiBldmVudCBoYXMgYmVlbiBmaXJlZCBvbiB0aGVcclxuICAgIC8vIHdpbmRvdzsgYW5kLCB0aGF0IGFsbCBzdWItcmVzb3VyY2VzIHN1Y2ggYXMgU2NyaXB0cywgSW1hZ2VzLCBhbmQgRnJhbWVzIGhhdmVcclxuICAgIC8vIGJlZW4gbG9hZGVkLlxyXG4gICAgaWYgKHdpbmRvdy5kb2N1bWVudC5yZWFkeVN0YXRlID09PSBcImNvbXBsZXRlXCIpIHtcclxuXHJcbiAgICAgIC8vIElmIHRoaXMgZXZlbnQgaGFzIGZpcmVkIEFORCB0aGUgM3JkLXBhcnR5IHNjcmlwdCBpc24ndCBhdmFpbGFibGUgKHNlZSBJRi1cclxuICAgICAgLy8gY29uZGl0aW9uIEJFRk9SRSB0aGlzIG9uZSksIGl0IG1lYW5zIHRoYXQgdGhlIDNyZC1wYXJ0eSBzY3JpcHQgZWl0aGVyXHJcbiAgICAgIC8vIGZhaWxlZCBvbiB0aGUgbmV0d29yayBvciB3YXMgQkxPQ0tFRCBieSBhbiBhZC1ibG9ja2VyLiBBcyBzdWNoLCB3ZSBoYXZlIHRvXHJcbiAgICAgIC8vIGZhbGwtYmFjayB0byB1c2luZyBhIG1vY2sgQVBJLlxyXG4gICAgICByZXR1cm4gKHRoaXMuY2xpZW50UHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZShuZXcgTm9vcENsaWVudCgpKSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQVNTRVJUOiBJZiB3ZSBtYWRlIGl0IHRoaXMgZmFyLCB0aGUgZG9jdW1lbnQgaGFzIG5vdCBjb21wbGV0ZWQgbG9hZGluZyAoYnV0IGl0XHJcbiAgICAvLyBtYXkgYmUgaW4gYW4gXCJpbnRlcmFjdGl2ZVwiIHN0YXRlIHdoaWNoIGlzIHdoZW4gSSBiZWxpZXZlIHRoYXQgdGhlIEFuZ3VsYXIgYXBwXHJcbiAgICAvLyBnZXRzIGJvb3RzdHJhcHBlZCkuIEFzIHN1Y2gsIHdlIG5lZWQgYmluZCB0byB0aGUgTE9BRCBldmVudCB0byB3YWl0IGZvciBvdXJcclxuICAgIC8vIHRoaXJkLXBhcnR5IHNjcmlwdHMgdG8gbG9hZCAob3IgZmFpbCB0byBsb2FkLCBvciBiZSBibG9ja2VkKS5cclxuICAgIHRoaXMuY2xpZW50UHJvbWlzZSA9IG5ldyBQcm9taXNlPElDbGllbnQ+KFxyXG4gICAgICAocmVzb2x2ZSkgPT4ge1xyXG5cclxuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcclxuICAgICAgICAgIFwibG9hZFwiLFxyXG4gICAgICAgICAgZnVuY3Rpb24gaGFuZGxlV2luZG93TG9hZCgpIHtcclxuXHJcbiAgICAgICAgICAgIC8vIEF0IHRoaXMgcG9pbnQsIHRoZSAzcmQtcGFydHkgbGlicmFyeSBpcyBlaXRoZXIgYXZhaWxhYmxlIG9yXHJcbiAgICAgICAgICAgIC8vIGl0J3Mgbm90IC0gdGhlcmUncyBubyBmdXJ0aGVyIGxvYWRpbmcgdG8gZG8uIElmIGl0J3Mgbm90XHJcbiAgICAgICAgICAgIC8vIHByZXNlbnQgb24gdGhlIGdsb2JhbCBzY29wZSwgd2UncmUgZ29pbmcgdG8gZmFsbC1iYWNrIHRvIHVzaW5nXHJcbiAgICAgICAgICAgIC8vIGEgbW9jayBBUEkuXHJcbiAgICAgICAgICAgIHJlc29sdmUod2luZG93LkNsaWVudCB8fCBuZXcgTm9vcENsaWVudCgpKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICApO1xyXG5cclxuICAgICAgfVxyXG4gICAgKTtcclxuXHJcbiAgICByZXR1cm4gKHRoaXMuY2xpZW50UHJvbWlzZSk7XHJcbiAgfVxyXG59XHJcblxyXG5cclxuXHJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXHJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXHJcblxyXG4vKipcclxuICogTW9jayBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgSUNsaWVudCBpbnRlcmZhY2UuXHJcbiAqIFxyXG4gKiBUaGlzIGNsYXNzIHByb3ZpZGVzIGEgbm8tb3BlcmF0aW9uIChOT09QKSBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgY2xpZW50IEFQSVxyXG4gKiB0aGF0IGFsbG93cyBjb25zdW1pbmcgY29kZSB0byBmdW5jdGlvbiBub3JtYWxseSBldmVuIHdoZW4gdGhlIGFjdHVhbCBwbGF5ZXJcclxuICogQVBJIGlzIG5vdCBhdmFpbGFibGUuIFRoaXMgdHlwaWNhbGx5IG9jY3VycyBkdXJpbmcgZGV2ZWxvcG1lbnQsIHRlc3RpbmcsXHJcbiAqIG9yIHdoZW4gdGhlIHBsYXllciBzY3JpcHQgaXMgYmxvY2tlZCBieSBhZC1ibG9ja2Vycy5cclxuICogXHJcbiAqIEFsbCBtZXRob2RzIGluIHRoaXMgY2xhc3MgZWl0aGVyIHJldHVybiBudWxsL2VtcHR5IHZhbHVlcyBvciBwZXJmb3JtIG5vXHJcbiAqIG9wZXJhdGlvbnMsIGFsbG93aW5nIGdhZGdldHMgdG8gZnVuY3Rpb24gd2l0aG91dCBlcnJvcnMgd2hpbGUgcHJvdmlkaW5nXHJcbiAqIGFwcHJvcHJpYXRlIGZhbGxiYWNrIGJlaGF2aW9yLlxyXG4gKiBcclxuICogQHByaXZhdGVcclxuICovXHJcbmNsYXNzIE5vb3BDbGllbnQgaW1wbGVtZW50cyBJQ2xpZW50IHtcclxuXHJcbiAgY29uc3RydWN0b3IoKSB7XHJcblxyXG4gICAgY29uc29sZS5sb2coXHJcbiAgICAgICclY0NsaWVudCBBUEkgbm90IGF2YWlsYWJsZSwgZmFsbGluZyBiYWNrIHRvIG1vY2sgQVBJJyxcclxuICAgICAgJ2JhY2tncm91bmQtY29sb3I6Ymx1ZTsgY29sb3I6eWVsbG93OydcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgY2FsbGJhY2soLi4uYXJnczogYW55W10pOiB2b2lkIHtcclxuXHJcbiAgICAvLyBOT09QIGltcGxlbWVudCwgbm90aGluZyB0byBkby4uLi5cclxuICB9XHJcblxyXG4gIHB1YmxpYyBnZXREZXZpY2VUaW1lKGRhdGU/OiBEYXRlKTogUHJvbWlzZTxzdHJpbmc+IHtcclxuXHJcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgZ2V0RGV2aWNlVGltZVpvbmVOYW1lKCk6IFByb21pc2U8c3RyaW5nPiB7XHJcblxyXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShudWxsKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBhc3luYyBnZXREZXZpY2VUaW1lWm9uZUlEKCk6IFByb21pc2U8c3RyaW5nPiB7XHJcblxyXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShudWxsKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBhc3luYyBnZXREZXZpY2VUaW1lWm9uZU9mZnNldCgpOiBQcm9taXNlPG51bWJlcj4ge1xyXG5cclxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobnVsbCk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgZ2V0TGFuZ3VhZ2VDb2RlKCk6IFByb21pc2U8c3RyaW5nPiB7XHJcblxyXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShudWxsKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBhc3luYyBnZXREZXZpY2VLZXkoKTogUHJvbWlzZTxzdHJpbmc+IHtcclxuXHJcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG51bGwpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHNlbmRDb21tYW5kKG5hbWU6IHN0cmluZywgYXJnOiBzdHJpbmcpOiB2b2lkIHtcclxuXHJcbiAgICAvLyBOT09QIGltcGxlbWVudCwgbm90aGluZyB0byBkby4uLi5cclxuICB9XHJcblxyXG4gIHB1YmxpYyBzZW5kUmVtb3RlQ29tbWFuZChkZXZpY2VLZXlzOiBzdHJpbmdbXSwgbmFtZTogc3RyaW5nLCBhcmc6IHN0cmluZykge1xyXG5cclxuICAgIC8vIE5PT1AgaW1wbGVtZW50LCBub3RoaW5nIHRvIGRvLi4uLlxyXG4gIH1cclxuXHJcbiAgcHVibGljIHRyYWNrKGV2ZW50TmFtZTogc3RyaW5nLCBwcm9wZXJ0aWVzPzogc3RyaW5nKTogdm9pZCB7XHJcblxyXG4gICAgLy8gTk9PUCBpbXBsZW1lbnQsIG5vdGhpbmcgdG8gZG8uLi4uXHJcbiAgfVxyXG5cclxuICBwdWJsaWMgdGltZUV2ZW50KGV2ZW50TmFtZTogc3RyaW5nKTogdm9pZCB7XHJcblxyXG4gICAgLy8gTk9PUCBpbXBsZW1lbnQsIG5vdGhpbmcgdG8gZG8uLi4uXHJcbiAgfVxyXG5cclxuICBwdWJsaWMgbmV3RXZlbnRTZXNzaW9uKGlkPzogc3RyaW5nKTogdm9pZCB7XHJcblxyXG4gICAgLy8gTk9PUCBpbXBsZW1lbnQsIG5vdGhpbmcgdG8gZG8uLi4uXHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgZ2V0UmV2ZWxSb290KCk6IFByb21pc2U8c3RyaW5nPiB7XHJcblxyXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShudWxsKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBhc3luYyBnZXRDb21tYW5kTWFwKCk6IFByb21pc2U8c3RyaW5nPiB7XHJcblxyXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgne30nKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBmaW5pc2goKTogdm9pZCB7XHJcblxyXG4gICAgLy8gTk9PUCBpbXBsZW1lbnQsIG5vdGhpbmcgdG8gZG8uLi4uXHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgZ2V0RGV2aWNlKCk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xyXG5cclxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobnVsbCk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgZ2V0V2lkdGgoKTogUHJvbWlzZTxudW1iZXIgfCBudWxsPiB7XHJcblxyXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShudWxsKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBhc3luYyBnZXRIZWlnaHQoKTogUHJvbWlzZTxudW1iZXIgfCBudWxsPiB7XHJcblxyXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShudWxsKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBhc3luYyBnZXREdXJhdGlvbigpOiBQcm9taXNlPG51bWJlciB8IG51bGw+IHtcclxuXHJcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG51bGwpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGFzeW5jIGdldFNka1ZlcnNpb24oKTogUHJvbWlzZTxzdHJpbmc+IHtcclxuXHJcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHZlcnNpb24pO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGFwcGx5Q29uZmlnKHByZWZzOiBJRGljdGlvbmFyeTxhbnk+KTogdm9pZCB7XHJcblxyXG4gICAgbGV0IGV2dCA9IHsgdHlwZTogJ2FwcGx5Q29uZmlnJywgcHJlZnM6IHByZWZzLCBpc09wZW5lcjogd2luZG93Lm9wZW5lciAhPT0gbnVsbCB9O1xyXG5cclxuICAgIGlmICh3aW5kb3cub3BlbmVyKSB7XHJcbiAgICAgIHdpbmRvdy5vcGVuZXIucG9zdE1lc3NhZ2UoXHJcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkoZXZ0KSxcclxuICAgICAgICAnKidcclxuICAgICAgKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHdpbmRvdy5wYXJlbnQucG9zdE1lc3NhZ2UoXHJcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkoZXZ0KSxcclxuICAgICAgICAnKidcclxuICAgICAgKTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuIl19