@smarterplan/ngx-smarterplan-core 1.4.13 → 1.4.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.
@@ -1,7 +1,8 @@
1
1
  import { Injectable } from '@angular/core';
2
2
  import { BehaviorSubject } from 'rxjs';
3
- import { copyFileInS3 } from './s3.service'; // see s3.service.ts: copyFileInS3 must NOT swallow errors (needed to detect NoSuchKey below)
4
- import { computeRigidTransform, applyRigidTransformToPoint, applyRigidTransformToYRotationDeg } from './utils/matterport-transform.util';
3
+ import { copyFileInS3, copyFileInS3ViaDownload } from './s3.service'; // see s3.service.ts: neither must swallow errors (needed to detect NoSuchKey / signature mismatch below)
4
+ import { downloadBlob } from '../helpers.service';
5
+ import { computeRigidTransform, applyRigidTransformToPoint, applyRigidTransformToDirection, applyRigidTransformToYRotationDeg } from './utils/matterport-transform.util';
5
6
  import { CommentType, PoiType, SpModule } from '../types.service';
6
7
  import * as i0 from "@angular/core";
7
8
  import * as i1 from "./models/navigation.service";
@@ -13,7 +14,11 @@ import * as i6 from "./models/object3D.service";
13
14
  import * as i7 from "./models/feature.service";
14
15
  import * as i8 from "./models/measurement.service";
15
16
  import * as i9 from "./models/comment.service";
16
- import * as i10 from "@ngx-translate/core";
17
+ import * as i10 from "./models/hashtag.service";
18
+ import * as i11 from "./models/mission.service";
19
+ import * as i12 from "./models/operation.service";
20
+ import * as i13 from "./models/domain.service";
21
+ import * as i14 from "@ngx-translate/core";
17
22
  /** Safely extracts a readable message from an unknown catch value, including Amplify's
18
23
  * GraphQL error shape ({ data, errors: [{ errorType, message }] }). */
19
24
  function toErrorMessage(err) {
@@ -65,6 +70,10 @@ export class MatterportTagCopyService {
65
70
  featureService;
66
71
  measurementService;
67
72
  commentService;
73
+ hashtagService;
74
+ missionService;
75
+ operationService;
76
+ domainService;
68
77
  translate;
69
78
  // Emits progress updates during copyTagsFromVisit(); null when idle
70
79
  copyProgress$ = new BehaviorSubject(null);
@@ -72,8 +81,60 @@ export class MatterportTagCopyService {
72
81
  copyLog$ = new BehaviorSubject([]);
73
82
  spModule;
74
83
  log = [];
75
- errorSeq = 0;
76
- constructor(navigationService, userService, poiService, ticketService, equipmentService, object3DService, featureService, measurementService, commentService, translate) {
84
+ /** Unique-id sequence shared by every permanent (non-step) log line — errors and healed-item notices alike. */
85
+ logSeq = 0;
86
+ // ---- Per-run remapping state (reset by resetRunState() at the start of every copy) ----
87
+ /** source element id -> id of its copy in the target space. */
88
+ elementIds = {};
89
+ /** source Comment id -> id of its copy. Needed to remap POI.tagImageID, which is a
90
+ * reference to a Comment record (see the schema: "connection to comment.id"). */
91
+ commentIds = new Map();
92
+ // Hashtags are space-scoped records, so their ids can never be carried over as-is: they
93
+ // are matched by NAME against the target space, and the missing ones are created there.
94
+ // That creation is deliberately lazy — see resolveHashtagIds() — and audited, so an
95
+ // interrupted copy cannot leave keywords behind that no POI references.
96
+ /** source Hashtag id -> its name. */
97
+ sourceHashtagNames = new Map();
98
+ /** normalised hashtag name -> its id in the TARGET space (pre-existing or just created). */
99
+ targetHashtagIdsByName = new Map();
100
+ /** ids of the hashtags this run created in the target space. */
101
+ createdHashtagIds = new Set();
102
+ /** ids of the hashtags actually persisted on a successfully created feature. Anything in
103
+ * createdHashtagIds but absent here is an orphan and is deleted at the end of the run. */
104
+ usedHashtagIds = new Set();
105
+ /** source ids of the elements whose POIs were already created by an element phase.
106
+ * Guards the standalone POI phase against creating a second, impoverished copy. */
107
+ handledElementIds = new Set();
108
+ // Comment authorship: `Comment.ownerID` is a foreign key to a Mission, and a Mission is
109
+ // scoped to ONE space (userID + spaceID). A source comment's ownerID therefore points at
110
+ // nobody in the target space, so it has to be translated to the Mission of the SAME user
111
+ // there — see resolveCommentOwnerID().
112
+ /** source Mission id -> its userID. */
113
+ sourceMissionUserIds = new Map();
114
+ /** userID -> that user's Mission id in the TARGET space (only set when they have one). */
115
+ targetMissionIdsByUserId = new Map();
116
+ // Domain (equipment/ticket/feature/POI category) resolution mirrors the exact rule the
117
+ // edit forms use to populate their own category dropdown —
118
+ // DomainService.getDomainsForOrgForType(type, mission.organisationID,
119
+ // mission.orderedOrganisationID) — keyed to the OPERATOR's own Mission on each space,
120
+ // NOT to the Space's own organisationID. Two spaces in different organisations can
121
+ // still share a domain through that Mission link (an operator whose mission on the
122
+ // target space carries an `orderedOrganisationID` matching the domain's own
123
+ // organisationID sees — and can reuse — it directly). See resolveDomainID().
124
+ /** id -> Domain, for every domain visible from EITHER space's operator mission (its
125
+ * organisationID, its orderedOrganisationID, or generic/no-organisation domains) — a
126
+ * superset covering whatever a source object's domainID could point at. */
127
+ domainsById = new Map();
128
+ /** organisationIDs the TARGET operator's mission can see domains from. A domain whose
129
+ * own organisationID is in this set (or has none at all) is already directly
130
+ * selectable in the target space's own dropdown, so its id is reused unchanged. */
131
+ targetVisibleDomainOrgIds = new Set();
132
+ /** `${type}::${normalised name}` -> that domain's id, among domains visible to the
133
+ * TARGET operator — used to find an equivalent when the exact id isn't reusable. */
134
+ targetDomainIdsByTypeAndName = new Map();
135
+ /** Target space id of the run in progress — used to re-home copied tag icons. */
136
+ targetSpaceId = null;
137
+ constructor(navigationService, userService, poiService, ticketService, equipmentService, object3DService, featureService, measurementService, commentService, hashtagService, missionService, operationService, domainService, translate) {
77
138
  this.navigationService = navigationService;
78
139
  this.userService = userService;
79
140
  this.poiService = poiService;
@@ -83,6 +144,10 @@ export class MatterportTagCopyService {
83
144
  this.featureService = featureService;
84
145
  this.measurementService = measurementService;
85
146
  this.commentService = commentService;
147
+ this.hashtagService = hashtagService;
148
+ this.missionService = missionService;
149
+ this.operationService = operationService;
150
+ this.domainService = domainService;
86
151
  this.translate = translate;
87
152
  this.spModule = userService.getSpModule();
88
153
  }
@@ -91,7 +156,9 @@ export class MatterportTagCopyService {
91
156
  //
92
157
  async copyTagsFromVisit(sourceSpaceId, targetSpaceId, landmarkSourceA, landmarkTargetA, landmarkSourceB, landmarkTargetB) {
93
158
  let errorCount = 0;
159
+ let healedCount = 0;
94
160
  this.resetLog();
161
+ this.resetRunState(targetSpaceId);
95
162
  try {
96
163
  console.log(`Copying Tags from source ${sourceSpaceId} to target ${targetSpaceId}`);
97
164
  this.setStepProgress('collecting', 'collecting', 0);
@@ -99,7 +166,7 @@ export class MatterportTagCopyService {
99
166
  phase: 'collecting',
100
167
  processedInPhase: 0, totalInPhase: 0,
101
168
  processedOverall: 0, totalOverall: 0,
102
- percent: 0, errorCount: 0
169
+ percent: 0, errorCount: 0, healedCount: 0
103
170
  });
104
171
  const targetMission = this.userService.currentMission(targetSpaceId);
105
172
  const targetMissionId = targetMission ? targetMission.id : null;
@@ -116,7 +183,7 @@ export class MatterportTagCopyService {
116
183
  this.buildNavigationPositionMap(sourceSpaceId, sourceSweepIds),
117
184
  this.buildNavigationPositionMap(targetSpaceId, targetSweepIds)
118
185
  ]);
119
- const elementIds = {};
186
+ const elementIds = this.elementIds;
120
187
  let sourceTickets = [];
121
188
  let sourceEquipments = [];
122
189
  let targetTickets = [];
@@ -132,9 +199,31 @@ export class MatterportTagCopyService {
132
199
  this.setStepProgress('collecting', 'collecting', 55);
133
200
  const sourceObjects3D = await this.object3DService.getObjects3DBySpace(sourceSpaceId);
134
201
  const targetObjects3D = await this.object3DService.getObjects3DBySpace(targetSpaceId);
135
- const sourceFeatures = await this.featureService.getFeaturesBySpaceWithoutFiltering(sourceSpaceId);
136
- const targetFeatures = await this.featureService.getFeaturesBySpaceWithoutFiltering(targetSpaceId);
202
+ // Paginated: a space routinely holds more than the 100 features a single AppSync
203
+ // page returns, and the tail was silently dropped.
204
+ //
205
+ // The source list keeps the historical "skip what the operator archived" rule, so
206
+ // the set of copied features does not change — but the check is now null-safe:
207
+ // FeatureService.isArchived() dereferences currentMission(spaceID).id and threw a
208
+ // TypeError when the operator had no mission on the source space (the common case
209
+ // for an archived v1 space), aborting the whole copy.
210
+ // The target list is NOT filtered: it only feeds duplicate detection, and an
211
+ // archived feature is still a feature that exists there.
212
+ const sourceFeatures = (await this.featureService.getAllFeaturesBySpaceRaw(sourceSpaceId))
213
+ .filter(feature => !this.isArchivedForOperator(feature, sourceSpaceId));
214
+ const targetFeatures = await this.featureService.getAllFeaturesBySpaceRaw(targetSpaceId);
137
215
  this.setStepProgress('collecting', 'collecting', 75);
216
+ // Keywords: index both vocabularies now (read-only). The keywords the target space
217
+ // is missing are created later, POI by POI, only for those actually used.
218
+ await this.loadHashtagIndex(sourceSpaceId, targetSpaceId);
219
+ // Missions: index both spaces now (read-only), so copied comments can credit
220
+ // their real author instead of whoever is running the copy.
221
+ await this.loadMissionIndex(sourceSpaceId, targetSpaceId);
222
+ // Domains: index every domain either operator's mission can see (read-only), so
223
+ // a category survives a copy across two DIFFERENT organisations whenever it
224
+ // genuinely would be selectable in the target space's own dropdown — see
225
+ // loadDomainIndex() for why this is keyed to Mission, not to the Space itself.
226
+ await this.loadDomainIndex(sourceSpaceId, targetSpaceId);
138
227
  if (this.spModule == SpModule.IMMO) {
139
228
  sourceMeasurements = await this.measurementService.getMeasurementsForSpaceForUser(sourceSpaceId);
140
229
  targetMeasurements = await this.measurementService.getMeasurementsForSpaceForUser(targetSpaceId);
@@ -142,12 +231,44 @@ export class MatterportTagCopyService {
142
231
  this.setStepProgress('collecting', 'collecting', 90);
143
232
  const sourcePoisAll = await this.poiService.getPoisByMatterportSweeps(sourceSweepIds);
144
233
  const targetPoisAll = await this.poiService.getPoisByMatterportSweeps(targetSweepIds);
234
+ // A POI is "owned" by an element (ticket, equipment, 3D object, feature, measurement)
235
+ // when its elementID points at one. Those POIs are created by their element's phase,
236
+ // which is the only place that knows the element's NEW id — so they must be excluded
237
+ // from the standalone phase, otherwise every feature ends up with two POIs: one
238
+ // correctly linked but stripped of its tag metadata, and one carrying the metadata
239
+ // but still pointing at the source space's element.
240
+ //
241
+ // Ownership is recognised by TWO independent criteria, and either one is enough to
242
+ // keep a POI out of the standalone phase:
243
+ //
244
+ // - its type is one an element phase is responsible for. This is the historical
245
+ // rule and it must be kept: a POI of that type whose element was NOT collected
246
+ // (deleted ticket, equipment outside the current filter, ...) is an orphan, and
247
+ // copying it standalone would recreate it with an elementID still pointing into
248
+ // the source space — an orphan the previous version correctly refused to copy.
249
+ // - its elementID belongs to an element we actually collected. This is the added
250
+ // rule, needed because the type alone is not a reliable discriminator: historical
251
+ // data also holds INFORMATION/ROOM POIs bound to a feature, which the type test
252
+ // lets through and which would end up duplicated.
145
253
  const handledPoiTypes = new Set([
146
254
  PoiType.TICKET, PoiType.EQUIPMENT, PoiType.DATA, PoiType.DESK,
147
255
  PoiType.OBJECT3D, PoiType.MEASURE
148
256
  ]);
149
- const sourcePois = sourcePoisAll.filter(p => !handledPoiTypes.has(p.type));
150
- const targetPois = targetPoisAll.filter(p => !handledPoiTypes.has(p.type));
257
+ for (const owner of [...sourceTickets, ...sourceEquipments, ...sourceObjects3D, ...sourceFeatures]) {
258
+ if (owner?.id) {
259
+ this.handledElementIds.add(owner.id);
260
+ }
261
+ }
262
+ for (const measurement of sourceMeasurements) {
263
+ // a measurement POI is bound to the measurement's Comment, not to the measurement
264
+ if (measurement?.comment?.id) {
265
+ this.handledElementIds.add(measurement.comment.id);
266
+ }
267
+ }
268
+ const isOwnedByAnElement = (poi) => handledPoiTypes.has(poi.type)
269
+ || (!!poi.elementID && this.handledElementIds.has(poi.elementID));
270
+ const sourcePois = sourcePoisAll.filter(p => !isOwnedByAnElement(p));
271
+ const targetPois = targetPoisAll.filter(p => !!p);
151
272
  this.setStepProgress('collecting', 'collecting', 100);
152
273
  const totalOverall = sourceTickets.length + sourceEquipments.length + sourcePois.length
153
274
  + sourceObjects3D.length + sourceFeatures.length + sourceMeasurements.length;
@@ -160,7 +281,7 @@ export class MatterportTagCopyService {
160
281
  processedOverall,
161
282
  totalOverall,
162
283
  percent: totalOverall > 0 ? Math.round((processedOverall / totalOverall) * 100) : 0,
163
- errorCount
284
+ errorCount, healedCount
164
285
  });
165
286
  };
166
287
  if (this.spModule == SpModule.IMMO) {
@@ -168,8 +289,8 @@ export class MatterportTagCopyService {
168
289
  for (let i = 0; i < sourceTickets.length; i++) {
169
290
  const sourceObj = sourceTickets[i];
170
291
  try {
171
- const existsInTarget = this.matchesExisting(sourceObj, targetTickets);
172
- if (!existsInTarget) {
292
+ const existingMatch = this.findExisting(sourceObj, targetTickets, (t) => [t.title, t.description]);
293
+ if (!existingMatch) {
173
294
  const rawSource = sourceObj;
174
295
  const ticketInput = {
175
296
  title: rawSource.title,
@@ -183,28 +304,64 @@ export class MatterportTagCopyService {
183
304
  read: rawSource.read || null,
184
305
  projectID: rawSource.projectID || null,
185
306
  problemCode: rawSource.problemCode || null,
186
- archivedForMissionID: rawSource.archivedForMissionID || null,
307
+ // Missions are per-space: a source mission id designates nobody in
308
+ // the target space. Carrying the list over would look like real data
309
+ // while hiding the item from no one — reset it, as for features.
310
+ archivedForMissionID: null,
187
311
  spaceID: targetSpaceId,
312
+ // Remapped in the second pass below, once every ticket exists.
188
313
  parentID: null,
189
- domainID: null,
314
+ // Reused unchanged in the same organisation, matched by name
315
+ // across two — see resolveDomainID().
316
+ domainID: this.resolveDomainID(rawSource.domainID),
190
317
  ownerMissionID: targetMissionId
191
318
  };
192
319
  const createdObj = await this.ticketService.createTicket(ticketInput);
193
320
  if (createdObj && createdObj.id) {
194
321
  elementIds[sourceObj.id] = createdObj.id;
195
322
  }
196
- if (sourceObj.pois.items && sourceObj.pois.items.length > 0) {
197
- const sourcePoi = sourceObj.pois.items[0];
198
- const targetSweepId = this.findClosestTargetSweepId(sourcePoi.matterportSweepID, sourceNavPositions, targetNavPositions, transform);
199
- const adjustedCoordinate = this.getAdjustedCoordinates(sourcePoi.coordinate, transform);
200
- const poiInput = {
201
- coordinate: JSON.stringify(adjustedCoordinate),
202
- type: sourcePoi.type,
203
- elementID: createdObj.id,
204
- metadata: sourcePoi.metadata,
205
- matterportSweepID: targetSweepId
206
- };
207
- await this.poiService.createPOIForSpaceID(poiInput);
323
+ // Attachments of the ticket (photos of the incident, documents...).
324
+ // They were never copied at all: a duplicated ticket arrived stripped
325
+ // of every piece of evidence attached to it.
326
+ if (createdObj) {
327
+ let sourceComments = [];
328
+ try {
329
+ sourceComments = await this.commentService.getAllCommentsForTicket(sourceObj.id);
330
+ }
331
+ catch (commentsFetchError) {
332
+ console.warn(`Falling back to the embedded comment list for ticket "${rawSource.title}":`, commentsFetchError);
333
+ sourceComments = (sourceObj.comments?.items || []).filter(c => !!c);
334
+ }
335
+ for (const sourceComment of this.orderCommentsForCopy(sourceComments)) {
336
+ try {
337
+ const created = await this.copyCommentForTicket(sourceComment, createdObj.id, targetSpaceId);
338
+ if (created?.id && sourceComment.id) {
339
+ this.commentIds.set(sourceComment.id, created.id);
340
+ }
341
+ }
342
+ catch (attachmentError) {
343
+ console.error(`Error copying attachment "${sourceComment?.title}" for ticket "${sourceObj?.title}":`, attachmentError);
344
+ errorCount++;
345
+ this.logCopyItemError(attachmentError, 'errorFeatureAttachment', sourceComment?.title || sourceComment?.id, {
346
+ feature: rawSource.title || sourceObj.id
347
+ });
348
+ }
349
+ }
350
+ }
351
+ for (const sourcePoi of (sourceObj.pois?.items || []).filter(p => !!p)) {
352
+ await this.createCopiedPoi(sourcePoi, createdObj.id, sourceNavPositions, targetNavPositions, transform);
353
+ }
354
+ }
355
+ else {
356
+ // Same reasoning as the EQUIPMENTS phase (see the comment there):
357
+ // a ticket matching this one already exists in the target space,
358
+ // most likely from an earlier, incomplete run. Fill in whatever
359
+ // identity field it is missing rather than leaving it untouched.
360
+ elementIds[sourceObj.id] = existingMatch.id;
361
+ const healedFields = await this.healTicketIdentity(sourceObj, existingMatch);
362
+ if (healedFields.length > 0) {
363
+ healedCount++;
364
+ this.logHealedItem('ticketHealed', sourceObj?.title || sourceObj?.id, healedFields);
208
365
  }
209
366
  }
210
367
  }
@@ -218,26 +375,76 @@ export class MatterportTagCopyService {
218
375
  const pct = sourceTickets.length > 0 ? Math.round(((i + 1) / sourceTickets.length) * 100) : 100;
219
376
  this.setStepProgress('tickets', 'tickets', pct);
220
377
  }
221
- // EQUIPMENTS (title, POI, PHOTO and NOTES/documents all copied — files physically
222
- // duplicated in S3 first, so the copy stays independent from the source)
378
+ // Second pass: restore the ticket hierarchy. `parentID` had to be nulled during
379
+ // creation (the parent may not have existed yet) and was then never restored, so
380
+ // every sub-ticket came out detached. Same rule as for sub-equipments: a parent
381
+ // with no copied counterpart is dropped rather than left pointing at the source
382
+ // space's ticket.
383
+ for (const sourceObj of sourceTickets) {
384
+ const rawSource = sourceObj;
385
+ const newId = elementIds[sourceObj.id];
386
+ const newParentId = rawSource.parentID ? elementIds[rawSource.parentID] : null;
387
+ if (newId && newParentId) {
388
+ try {
389
+ await this.ticketService.updateTicket({ id: newId, parentID: newParentId });
390
+ }
391
+ catch (parentError) {
392
+ console.error(`Error remapping the parent ticket of "${sourceObj?.title}":`, parentError);
393
+ errorCount++;
394
+ this.logCopyItemError(parentError, 'errorTicket', sourceObj?.title || sourceObj?.id);
395
+ }
396
+ }
397
+ }
398
+ // EQUIPMENTS (identity, POI, PHOTO and NOTES/documents all copied — files
399
+ // physically duplicated in S3 first, so the copy stays independent from the source)
400
+ //
401
+ // CAREFUL: the Equipment model has NO `title` and NO `description` column. It
402
+ // identifies itself with `name` (String! — required) and annotates itself with
403
+ // `annotation`. Reading `rawSource.title` therefore always yielded undefined and
404
+ // the required `name` was never sent, which AppSync rejected with
405
+ // "Variable 'input' has coerced Null value for NonNull type 'String!'".
223
406
  for (let i = 0; i < sourceEquipments.length; i++) {
224
407
  const sourceObj = sourceEquipments[i];
225
408
  try {
226
- const existsInTarget = this.matchesExisting(sourceObj, targetEquipments);
227
- if (!existsInTarget) {
409
+ // Equipment has no `title`/`description`: it identifies itself by name, and by
410
+ // serial number when one is recorded.
411
+ const existingMatch = this.findExisting(sourceObj, targetEquipments, (e) => [e.name, e.serialNumber]);
412
+ if (!existingMatch) {
228
413
  const rawSource = sourceObj;
229
414
  let copiedPhotoKey = null;
230
415
  if (rawSource.photo) {
231
- copiedPhotoKey = await this.copyS3KeyIfPresent(rawSource.photo, `equipment photo "${rawSource.title}"`);
416
+ copiedPhotoKey = await this.copyS3KeyIfPresent(rawSource.photo, `equipment photo "${rawSource.name}"`);
232
417
  }
233
418
  const equipmentInput = {
234
- title: rawSource.title,
419
+ name: rawSource.name,
420
+ // Unlike every other model this file copies, Equipment declares
421
+ // `createdAt` as a plain client-settable field rather than an
422
+ // AppSync-managed timestamp (see schema.graphql) — so, uniquely
423
+ // here, the original commissioning date can actually be kept
424
+ // instead of the copy silently getting today's date.
425
+ createdAt: rawSource.createdAt ?? null,
426
+ annotation: rawSource.annotation ?? null,
235
427
  status: rawSource.status,
236
- description: rawSource.description,
237
- archivedForMissionID: rawSource.archivedForMissionID || null,
428
+ // Full identity of the equipment — all of these were dropped
429
+ family: rawSource.family ?? null,
430
+ sku: rawSource.sku ?? null,
431
+ serialNumber: rawSource.serialNumber ?? null,
432
+ manufacturer: rawSource.manufacturer ?? null,
433
+ installDate: rawSource.installDate ?? null,
434
+ warrantyEndDate: rawSource.warrantyEndDate ?? null,
435
+ metadata: rawSource.metadata ?? null,
436
+ isCreatedByAI: rawSource.isCreatedByAI ?? null,
437
+ // Missions are per-space: a source mission id designates nobody in
438
+ // the target space. Carrying the list over would look like real data
439
+ // while hiding the item from no one — reset it, as for features.
440
+ archivedForMissionID: null,
238
441
  spaceID: targetSpaceId,
239
- domainID: null,
442
+ // Reused unchanged in the same organisation, matched by name
443
+ // across two — see resolveDomainID().
444
+ domainID: this.resolveDomainID(rawSource.domainID),
240
445
  photo: copiedPhotoKey,
446
+ // `subequipmentsIDs` is deliberately absent: it is remapped to the
447
+ // copied equipments in the second pass, once they all exist.
241
448
  };
242
449
  const createdObj = await this.equipmentService.createEquipment(equipmentInput, null, null);
243
450
  if (createdObj && createdObj.id) {
@@ -247,38 +454,59 @@ export class MatterportTagCopyService {
247
454
  if (createdObj && rawSource.notes?.items && rawSource.notes.items.length > 0) {
248
455
  for (const sourceNote of rawSource.notes.items) {
249
456
  try {
250
- if (!sourceNote.attachment) {
251
- continue; // nothing to duplicate for this note
252
- }
253
- const copiedKey = await this.copyS3KeyIfPresent(sourceNote.attachment, `equipment note for "${sourceObj?.title}"`);
254
- await this.equipmentService.createNoteWithExistingAttachment(createdObj.id, copiedKey, sourceNote.type, targetMissionId);
457
+ // A note without a file is still a note: it carries a type
458
+ // and its signature/expiry dates. Skipping it, as was done
459
+ // before, silently dropped those records entirely.
460
+ const copiedKey = sourceNote.attachment
461
+ ? await this.copyS3KeyIfPresent(sourceNote.attachment, `equipment note for "${sourceObj?.name}"`)
462
+ : null;
463
+ await this.equipmentService.createNoteWithExistingAttachment(createdObj.id, copiedKey, sourceNote.type, targetMissionId, {
464
+ signDate: sourceNote.signDate ?? null,
465
+ expirationDate: sourceNote.expirationDate ?? null
466
+ });
255
467
  }
256
468
  catch (noteError) {
257
- console.error(`Error copying note for equipment "${sourceObj?.title}":`, noteError);
469
+ console.error(`Error copying note for equipment "${sourceObj?.name}":`, noteError);
258
470
  errorCount++;
259
- this.logCopyItemError(noteError, 'errorEquipmentNote', sourceObj?.title || sourceObj?.id);
471
+ this.logCopyItemError(noteError, 'errorEquipmentNote', sourceObj?.name || sourceObj?.id, {
472
+ equipment: sourceObj?.name || sourceObj?.id
473
+ });
260
474
  }
261
475
  }
262
476
  }
263
- if (sourceObj.pois.items && sourceObj.pois.items.length > 0) {
264
- const sourcePoi = sourceObj.pois.items[0];
265
- const targetSweepId = this.findClosestTargetSweepId(sourcePoi.matterportSweepID, sourceNavPositions, targetNavPositions, transform);
266
- const adjustedCoordinate = this.getAdjustedCoordinates(sourcePoi.coordinate, transform);
267
- const poiInput = {
268
- coordinate: JSON.stringify(adjustedCoordinate),
269
- type: sourcePoi.type,
270
- elementID: createdObj.id,
271
- metadata: sourcePoi.metadata,
272
- matterportSweepID: targetSweepId
273
- };
274
- await this.poiService.createPOIForSpaceID(poiInput);
477
+ for (const sourcePoi of (sourceObj.pois?.items || []).filter(p => !!p)) {
478
+ await this.createCopiedPoi(sourcePoi, createdObj.id, sourceNavPositions, targetNavPositions, transform);
479
+ }
480
+ }
481
+ else {
482
+ // An equipment matching this one already exists in the target space —
483
+ // most often because a PREVIOUS run of this copy already created it.
484
+ // That earlier run may have been interrupted, or hit a bug that has
485
+ // since been fixed (missing family/manufacturer/domainID/... were once
486
+ // dropped entirely — see the comment above), leaving an equipment with
487
+ // its identity fields empty forever: re-running the copy used to skip
488
+ // it outright, since it already "exists", so the gap could never heal.
489
+ //
490
+ // Re-running the tool must be able to repair that: any identity field
491
+ // the existing target equipment is missing, and the source has, is
492
+ // filled in. Fields the target already carries a value for are left
493
+ // untouched, so a manual edit made in the target space is never
494
+ // overwritten by an older or different source value. Notes and POIs are
495
+ // NOT re-created here: unlike scalar fields they cannot be "missing vs.
496
+ // present" checked the same way, and re-adding them on every re-run of
497
+ // an already-healthy copy would duplicate them.
498
+ elementIds[sourceObj.id] = existingMatch.id;
499
+ const healedFields = await this.healEquipmentIdentity(sourceObj, existingMatch);
500
+ if (healedFields.length > 0) {
501
+ healedCount++;
502
+ this.logHealedItem('equipmentHealed', sourceObj?.name || sourceObj?.id, healedFields);
275
503
  }
276
504
  }
277
505
  }
278
506
  catch (itemError) {
279
- console.error(`Error copying equipment "${sourceObj?.title}" (id: ${sourceObj?.id}):`, itemError);
507
+ console.error(`Error copying equipment "${sourceObj?.name}" (id: ${sourceObj?.id}):`, itemError);
280
508
  errorCount++;
281
- this.logCopyItemError(itemError, 'errorEquipment', sourceObj?.title || sourceObj?.id);
509
+ this.logCopyItemError(itemError, 'errorEquipment', sourceObj?.name || sourceObj?.id);
282
510
  }
283
511
  processedOverall++;
284
512
  emitProgress('equipments', i + 1, sourceEquipments.length);
@@ -301,53 +529,59 @@ export class MatterportTagCopyService {
301
529
  await this.equipmentService.updateEquipment({ id: newId, subequipmentsIDs: remapped });
302
530
  }
303
531
  catch (subEquipError) {
304
- console.error(`Error remapping sub-equipments for "${sourceObj?.title}":`, subEquipError);
532
+ console.error(`Error remapping sub-equipments for "${sourceObj?.name}":`, subEquipError);
305
533
  errorCount++;
306
- this.logCopyItemError(subEquipError, 'errorEquipmentSubEquip', sourceObj?.title || sourceObj?.id);
534
+ this.logCopyItemError(subEquipError, 'errorEquipmentSubEquip', sourceObj?.name || sourceObj?.id, {
535
+ equipment: sourceObj?.name || sourceObj?.id
536
+ });
307
537
  }
308
538
  }
309
539
  }
310
540
  }
311
- }
312
- // POIS (standalone — types already handled above are excluded)
313
- for (let i = 0; i < sourcePois.length; i++) {
314
- const sourcePoi = sourcePois[i];
315
- try {
316
- const existsInTarget = targetPois.some(tp => tp.coordinate === sourcePoi.coordinate && tp.tagDescription === sourcePoi.tagDescription);
317
- if (!existsInTarget) {
318
- const targetSweepId = this.findClosestTargetSweepId(sourcePoi.matterportSweepID, sourceNavPositions, targetNavPositions, transform);
319
- const adjustedCoordinate = this.getAdjustedCoordinates(sourcePoi.coordinate, transform);
320
- let elementID = sourcePoi.elementID;
321
- if (elementID && elementIds[elementID]) {
322
- elementID = elementIds[elementID];
541
+ // OPERATIONS — the Ticket<->Equipment join (drives "Tickets actuels" on the
542
+ // equipment page and the linked-equipment list on the ticket page). Both the
543
+ // TICKETS and EQUIPMENTS phases above copy the record itself, but neither one
544
+ // touches this join table, so every link between a copied ticket and a copied
545
+ // equipment was silently dropped: both sides existed in the target space, but
546
+ // pointing at nobody.
547
+ //
548
+ // Runs after both phases, over every SOURCE ticket that ended up mapped in
549
+ // the target space (freshly created OR healed — elementIds covers both), so a
550
+ // re-run over an already-copied pair of spaces can still pick up links that
551
+ // an earlier, incomplete run never created.
552
+ for (const sourceTicket of sourceTickets) {
553
+ const newTicketId = elementIds[sourceTicket.id];
554
+ if (!newTicketId) {
555
+ continue;
556
+ }
557
+ try {
558
+ const sourceOps = await this.operationService.getOperationsByTicketID(sourceTicket.id);
559
+ if (sourceOps.length === 0) {
560
+ continue;
561
+ }
562
+ // Read what the target ticket is already linked to, so a re-run never
563
+ // creates a duplicate Operation for a link that already exists.
564
+ const targetOps = await this.operationService.getOperationsByTicketID(newTicketId);
565
+ const linkedEquipmentIds = new Set(targetOps.map(op => op.equipmentID));
566
+ for (const sourceOp of sourceOps) {
567
+ const newEquipmentId = sourceOp.equipmentID ? elementIds[sourceOp.equipmentID] : null;
568
+ // No copied counterpart for the source equipment (not collected,
569
+ // outside the current filter, ...) — same rule as everywhere else
570
+ // in this file: drop the link rather than point it at nothing or
571
+ // at the source space's equipment.
572
+ if (!newEquipmentId || linkedEquipmentIds.has(newEquipmentId)) {
573
+ continue;
574
+ }
575
+ await this.operationService.createOperation({ ticketID: newTicketId, equipmentID: newEquipmentId });
576
+ linkedEquipmentIds.add(newEquipmentId);
323
577
  }
324
- const copiedTagIcon = await this.duplicateTagIcon(sourcePoi.tagIcon);
325
- const copiedTagImageID = await this.duplicateTagImageID(sourcePoi.tagImageID);
326
- const newPoi = {
327
- coordinate: JSON.stringify(adjustedCoordinate),
328
- type: sourcePoi.type,
329
- elementID: elementID,
330
- tagDescription: sourcePoi.tagDescription,
331
- tagIcon: copiedTagIcon,
332
- tagImageID: copiedTagImageID,
333
- virtual: sourcePoi.virtual,
334
- xRotation: sourcePoi.xRotation,
335
- yRotation: sourcePoi.yRotation,
336
- metadata: sourcePoi.metadata,
337
- matterportSweepID: targetSweepId
338
- };
339
- await this.poiService.createPOIForSpaceID(newPoi);
578
+ }
579
+ catch (opError) {
580
+ console.error(`Error copying ticket-equipment links for "${sourceTicket?.title}":`, opError);
581
+ errorCount++;
582
+ this.logCopyItemError(opError, 'errorOperation', sourceTicket?.title || sourceTicket?.id);
340
583
  }
341
584
  }
342
- catch (itemError) {
343
- console.error(`Error copying POI (sweep: ${sourcePoi?.matterportSweepID}):`, itemError);
344
- errorCount++;
345
- this.logCopyItemError(itemError, 'errorPoi', sourcePoi?.matterportSweepID);
346
- }
347
- processedOverall++;
348
- emitProgress('pois', i + 1, sourcePois.length);
349
- const pct = sourcePois.length > 0 ? Math.round(((i + 1) / sourcePois.length) * 100) : 100;
350
- this.setStepProgress('pois', 'pois', pct);
351
585
  }
352
586
  // OBJECTS 3D (the 3D model file itself — `path` — is physically duplicated in S3)
353
587
  for (let i = 0; i < sourceObjects3D.length; i++) {
@@ -356,8 +590,16 @@ export class MatterportTagCopyService {
356
590
  const existsInTarget = targetObjects3D.some(targetObj => targetObj.name === sourceObj.name);
357
591
  if (!existsInTarget) {
358
592
  const rawSource = sourceObj;
593
+ // `path` means two different things depending on `s3Bucket`, exactly as the
594
+ // viewer reads it (see viewer.component.ts and matterport-object3d.service.ts):
595
+ // - s3Bucket === true -> a key of a model file uploaded to S3, ours to duplicate;
596
+ // - otherwise -> a reference into the 3D object library shipped with
597
+ // the application ("3DObjects/objects/cube.dae" -> assets/3Dobjects/...),
598
+ // which exists in every space and must be reused verbatim.
599
+ // Copying unconditionally meant every library object failed with NoSuchKey and
600
+ // the whole 3D object was skipped, model AND POI.
359
601
  let copiedPath = rawSource.path;
360
- if (rawSource.path) {
602
+ if (rawSource.path && rawSource.s3Bucket) {
361
603
  copiedPath = await this.copyS3KeyIfPresent(rawSource.path, `3D object "${rawSource.name}"`);
362
604
  }
363
605
  /**
@@ -387,39 +629,65 @@ export class MatterportTagCopyService {
387
629
  // Ensure we return valid numbers
388
630
  return array.map(n => isNaN(n) ? 0 : n);
389
631
  };
632
+ // This service is shared, but the two applications do NOT deploy the same
633
+ // Object3D schema: `viewFrustum` exists only in smarterplan, and `scale`
634
+ // is [Float] there but a plain Float in museum. Sending the smarterplan
635
+ // shape to museum was rejected with "The variables input contains a field
636
+ // that is not defined for input object type 'CreateObject3DInput'".
637
+ //
638
+ // The input therefore MIRRORS the source record instead of imposing a
639
+ // shape: source and target live in the same deployment, so whatever the
640
+ // source carries is exactly what the target accepts.
390
641
  const object3DInput = {
391
642
  path: copiedPath,
643
+ // Tells the viewer how to interpret `path`. Dropping it turned an
644
+ // S3-hosted model into a library reference on the copy, which the
645
+ // viewer then tried to resolve against assets/ and failed to load.
646
+ s3Bucket: !!rawSource.s3Bucket,
392
647
  name: rawSource.name,
393
648
  description: rawSource.description || "",
394
- viewFrustum: !!rawSource.viewFrustum,
395
649
  spaceID: targetSpaceId,
396
650
  position: toFloatArray(rawSource.position, [0, 0, 0]),
397
- rotation: toFloatArray(rawSource.rotation, [0, 0, 0]),
398
- // Enforce scale to be at least 1.0 if it's invalid
399
- scale: toFloatArray(rawSource.scale, [1, 1, 1])
651
+ rotation: toFloatArray(rawSource.rotation, [0, 0, 0])
400
652
  };
401
- // Debugging: Inspect the exact object sent to the mutation
402
- console.log(`[DEBUG] Sending Object3D "${rawSource.name}" to API:`, JSON.stringify(object3DInput));
653
+ if ('viewFrustum' in rawSource) {
654
+ object3DInput.viewFrustum = !!rawSource.viewFrustum;
655
+ }
656
+ // Scale keeps the source's own shape: a list stays a list, a scalar stays
657
+ // a scalar. An absent scale is left unset rather than invented, so the copy
658
+ // renders exactly like the original.
659
+ if (Array.isArray(rawSource.scale)) {
660
+ object3DInput.scale = toFloatArray(rawSource.scale, [1, 1, 1]);
661
+ }
662
+ else if (rawSource.scale !== null && rawSource.scale !== undefined) {
663
+ const scalarScale = parseFloat(rawSource.scale);
664
+ object3DInput.scale = Number.isNaN(scalarScale) ? 1 : scalarScale;
665
+ }
403
666
  const createdObj = await this.object3DService.create(object3DInput);
404
667
  if (createdObj && createdObj.id) {
405
668
  elementIds[sourceObj.id] = createdObj.id;
406
669
  }
407
- if (sourceObj.pois?.items && sourceObj.pois.items.length > 0) {
408
- const sourcePoi = sourceObj.pois.items[0];
409
- const targetSweepId = this.findClosestTargetSweepId(sourcePoi.matterportSweepID, sourceNavPositions, targetNavPositions, transform);
410
- const adjustedCoordinate = this.getAdjustedCoordinates(sourcePoi.coordinate, transform);
411
- const poiInput = {
412
- coordinate: JSON.stringify(adjustedCoordinate),
413
- type: sourcePoi.type,
414
- elementID: createdObj.id,
415
- metadata: sourcePoi.metadata,
416
- matterportSweepID: targetSweepId
417
- };
418
- await this.poiService.createPOIForSpaceID(poiInput);
670
+ for (const sourcePoi of (sourceObj.pois?.items || []).filter(p => !!p)) {
671
+ await this.createCopiedPoi(sourcePoi, createdObj.id, sourceNavPositions, targetNavPositions, transform);
419
672
  }
420
673
  }
421
674
  }
422
675
  catch (itemError) {
676
+ // The backend can deny creation of this whole model to the signed-in account
677
+ // (in MUSEUM, Object3D only grants get/list to userPools). The denial is not
678
+ // per-item, so every remaining object would fail identically: report it once,
679
+ // as a permission problem rather than a copy error, and stop the phase instead
680
+ // of firing one doomed mutation per object.
681
+ if (this.isUnauthorized(itemError)) {
682
+ const remaining = sourceObjects3D.length - i;
683
+ console.warn(`[MatterportTagCopyService] Not allowed to create 3D objects in the target space, skipping ${remaining} of them.`, itemError);
684
+ errorCount++;
685
+ this.logItemError('errorObjects3dNotAllowed', { count: remaining });
686
+ processedOverall += remaining;
687
+ emitProgress('objects3d', sourceObjects3D.length, sourceObjects3D.length);
688
+ this.setStepProgress('objects3d', 'objects3d', 100);
689
+ break;
690
+ }
423
691
  console.error(`Error copying object3D "${sourceObj?.name}":`, itemError);
424
692
  errorCount++;
425
693
  this.logCopyItemError(itemError, 'errorObject3d', sourceObj?.name || sourceObj?.id);
@@ -429,76 +697,98 @@ export class MatterportTagCopyService {
429
697
  const pct = sourceObjects3D.length > 0 ? Math.round(((i + 1) / sourceObjects3D.length) * 100) : 100;
430
698
  this.setStepProgress('objects3d', 'objects3d', pct);
431
699
  }
432
- // FEATURES (title, POI, and attached comments — images/videos/docs/links — all copied,
433
- // each file physically duplicated in S3 first)
700
+ // FEATURES — the "POI" of the MUSEUM module: its own record (title, index, locale,
701
+ // keywords), its media set (one Comment per image/video/audio/document/link/text)
702
+ // and its POI record (the pastille: icon, tag description, cover image).
703
+ // Everything is copied here, files physically duplicated in S3 first.
434
704
  for (let i = 0; i < sourceFeatures.length; i++) {
435
705
  const sourceObj = sourceFeatures[i];
436
706
  try {
437
- const existsInTarget = this.matchesExisting(sourceObj, targetFeatures);
438
- if (!existsInTarget) {
707
+ const existingMatch = this.findExisting(sourceObj, targetFeatures, (f) => [f.title, f.description]);
708
+ if (!existingMatch) {
439
709
  const rawSource = sourceObj;
710
+ // Resolved just before the write: a keyword is only created in the target
711
+ // space when the POI carrying it is about to be created.
712
+ const resolvedHashtags = await this.resolveHashtagIds(rawSource.hashtags, targetSpaceId);
440
713
  const featureInput = {
441
714
  title: rawSource.title,
442
715
  shortDescription: rawSource.shortDescription,
443
716
  level: rawSource.level,
444
717
  type: rawSource.type,
445
- archivedForMissionID: rawSource.archivedForMissionID || null,
718
+ // `index` drives the ordering of the POI in the space's list, in the
719
+ // lateral menu and in the guided tour. Dropping it forced a full manual
720
+ // renumbering of every copied POI.
721
+ index: rawSource.index ?? null,
722
+ // Missions are per-space: source mission ids mean nothing in the target
723
+ // space, so an archive list carried over would hide POIs from nobody
724
+ // while looking like real data. Reset instead.
725
+ archivedForMissionID: null,
446
726
  stripeProductID: rawSource.stripeProductID || null,
447
727
  stripePriceID: rawSource.stripePriceID || null,
448
728
  bookingPriceMetadata: rawSource.bookingPriceMetadata || null,
449
729
  locale: rawSource.locale || null,
450
- hashtags: rawSource.hashtags || null,
730
+ // Hashtags are space-scoped records: the ids must be translated to the
731
+ // equivalent hashtags of the target space (created on demand).
732
+ hashtags: resolvedHashtags,
451
733
  description: rawSource.description || null,
452
- domainID: null,
734
+ // Reused unchanged in the same organisation, matched by name
735
+ // across two — see resolveDomainID().
736
+ domainID: this.resolveDomainID(rawSource.domainID),
453
737
  spaceID: targetSpaceId,
454
738
  ownerMissionID: targetMissionId
455
739
  };
456
740
  const createdObj = await this.featureService.createFeature(featureInput);
457
741
  if (createdObj && createdObj.id) {
458
742
  elementIds[sourceObj.id] = createdObj.id;
743
+ // The feature exists: its keywords are now genuinely referenced and
744
+ // must survive the end-of-run cleanup.
745
+ this.markHashtagsUsed(resolvedHashtags);
459
746
  }
460
- if (createdObj && sourceObj.comments?.items && sourceObj.comments.items.length > 0) {
461
- for (const sourceComment of sourceObj.comments.items) {
747
+ if (createdObj) {
748
+ // Read the media set through its own paginated query: the `comments`
749
+ // connection embedded in FeaturesBySpace is capped at 100 items and its
750
+ // nextToken was never followed, so rich POIs lost attachments silently.
751
+ let sourceComments = [];
752
+ try {
753
+ sourceComments = await this.commentService.getAllCommentsForFeature(sourceObj.id);
754
+ }
755
+ catch (commentsFetchError) {
756
+ console.warn(`Falling back to the embedded comment list for feature "${rawSource.title}":`, commentsFetchError);
757
+ sourceComments = (sourceObj.comments?.items || []).filter(c => !!c);
758
+ }
759
+ for (const sourceComment of this.orderCommentsForCopy(sourceComments)) {
462
760
  try {
463
- const rawComment = sourceComment;
464
- let copiedAnnexe = null;
465
- if (rawComment.annexe) {
466
- copiedAnnexe = await this.copyS3KeyIfPresent(rawComment.annexe, `feature attachment "${rawComment.title}"`);
761
+ const created = await this.copyCommentForFeature(sourceComment, createdObj.id, targetSpaceId);
762
+ if (created?.id && sourceComment.id) {
763
+ this.commentIds.set(sourceComment.id, created.id);
467
764
  }
468
- const commentInput = {
469
- title: rawComment.title,
470
- type: rawComment.type,
471
- annexe: copiedAnnexe,
472
- externalLink: rawComment.externalLink || null,
473
- dimensions: rawComment.dimensions || null,
474
- index: rawComment.index,
475
- shownInTag: rawComment.shownInTag,
476
- isCoverImage: rawComment.isCoverImage,
477
- featureID: createdObj.id,
478
- spaceID: targetSpaceId,
479
- ownerID: targetMissionId
480
- };
481
- await this.commentService.createComment(commentInput);
482
765
  }
483
766
  catch (attachmentError) {
484
767
  console.error(`Error copying attachment "${sourceComment?.title}" for feature "${sourceObj?.title}":`, attachmentError);
485
768
  errorCount++;
486
- this.logCopyItemError(attachmentError, 'errorFeatureAttachment', sourceComment?.title || sourceComment?.id);
769
+ this.logCopyItemError(attachmentError, 'errorFeatureAttachment', sourceComment?.title || sourceComment?.id, {
770
+ feature: rawSource.title || sourceObj.id
771
+ });
487
772
  }
488
773
  }
774
+ // Every POI of the feature, not only the first one: a feature may be
775
+ // pinned at several places, and only this phase knows the new element id.
776
+ const sourceFeaturePois = (sourceObj.pois?.items || []).filter(p => !!p);
777
+ for (const sourcePoi of sourceFeaturePois) {
778
+ await this.createCopiedPoi(sourcePoi, createdObj.id, sourceNavPositions, targetNavPositions, transform);
779
+ }
489
780
  }
490
- if (sourceObj.pois?.items && sourceObj.pois.items.length > 0) {
491
- const sourcePoi = sourceObj.pois.items[0];
492
- const targetSweepId = this.findClosestTargetSweepId(sourcePoi.matterportSweepID, sourceNavPositions, targetNavPositions, transform);
493
- const adjustedCoordinate = this.getAdjustedCoordinates(sourcePoi.coordinate, transform);
494
- const poiInput = {
495
- coordinate: JSON.stringify(adjustedCoordinate),
496
- type: sourcePoi.type,
497
- elementID: createdObj.id,
498
- metadata: sourcePoi.metadata,
499
- matterportSweepID: targetSweepId
500
- };
501
- await this.poiService.createPOIForSpaceID(poiInput);
781
+ }
782
+ else {
783
+ // Same reasoning as the EQUIPMENTS phase (see the comment there): a
784
+ // feature matching this one already exists in the target space, most
785
+ // likely from an earlier, incomplete run. Fill in whatever identity
786
+ // field it is missing rather than leaving it untouched.
787
+ elementIds[sourceObj.id] = existingMatch.id;
788
+ const healedFields = await this.healFeatureIdentity(sourceObj, existingMatch);
789
+ if (healedFields.length > 0) {
790
+ healedCount++;
791
+ this.logHealedItem('featureHealed', sourceObj?.title || sourceObj?.id, healedFields);
502
792
  }
503
793
  }
504
794
  }
@@ -527,12 +817,20 @@ export class MatterportTagCopyService {
527
817
  }
528
818
  const commentInput = {
529
819
  title: rawComment.title,
820
+ description: rawComment.description ?? null,
821
+ metadata: rawComment.metadata ?? null,
530
822
  type: CommentType.MEASURE,
531
823
  dimensions: rawComment.dimensions || null,
532
824
  annexe: copiedAnnexe,
533
825
  spaceID: targetSpaceId,
826
+ // Same authorship rule as every other copied comment — see
827
+ // resolveCommentOwnerID().
828
+ ownerID: this.resolveCommentOwnerID(rawComment.ownerID),
534
829
  };
535
830
  const createdComment = await this.commentService.createComment(commentInput);
831
+ if (createdComment && createdComment.id && rawComment.id) {
832
+ this.commentIds.set(rawComment.id, createdComment.id);
833
+ }
536
834
  if (createdComment && sourceMeasurement.poi) {
537
835
  const targetSweepId = this.findClosestTargetSweepId(sourceMeasurement.poi.matterportSweepID, sourceNavPositions, targetNavPositions, transform);
538
836
  const adjustedPosition = this.getAdjustedPositionOnly(sourceMeasurement.poi.coordinate, transform);
@@ -540,7 +838,9 @@ export class MatterportTagCopyService {
540
838
  coordinate: JSON.stringify(adjustedPosition),
541
839
  type: PoiType.MEASURE,
542
840
  elementID: createdComment.id,
543
- metadata: sourceMeasurement.poi.metadata,
841
+ // Same treatment as any other POI: the source's Matterport tag
842
+ // SID must not travel, and the stem normal has to be rotated.
843
+ metadata: this.getAdjustedPoiMetadata(sourceMeasurement.poi.metadata, transform),
544
844
  matterportSweepID: targetSweepId
545
845
  };
546
846
  await this.poiService.createPOIForSpaceID(poiInput);
@@ -558,15 +858,51 @@ export class MatterportTagCopyService {
558
858
  this.setStepProgress('measurements', 'measurements', pct);
559
859
  }
560
860
  }
861
+ // POIS — standalone ones only: every POI owned by an element was already created by
862
+ // that element's phase, with the element's NEW id.
863
+ //
864
+ // This phase runs LAST on purpose. It used to run third, before 3D objects, features
865
+ // and measurements existed in the target space, so `elementIds` and `commentIds` were
866
+ // still empty when it needed them: elementID stayed pointing at the source space and
867
+ // tagImageID (a reference to a Comment record) could never be resolved.
868
+ for (let i = 0; i < sourcePois.length; i++) {
869
+ const sourcePoi = sourcePois[i];
870
+ try {
871
+ const existsInTarget = targetPois.some(tp => tp.coordinate === sourcePoi.coordinate && tp.tagDescription === sourcePoi.tagDescription);
872
+ if (!existsInTarget) {
873
+ const elementID = sourcePoi.elementID
874
+ ? (elementIds[sourcePoi.elementID] || sourcePoi.elementID)
875
+ : sourcePoi.elementID;
876
+ await this.createCopiedPoi(sourcePoi, elementID, sourceNavPositions, targetNavPositions, transform);
877
+ }
878
+ }
879
+ catch (itemError) {
880
+ console.error(`Error copying POI (sweep: ${sourcePoi?.matterportSweepID}):`, itemError);
881
+ errorCount++;
882
+ this.logCopyItemError(itemError, 'errorPoi', sourcePoi?.matterportSweepID, {
883
+ sweep: sourcePoi?.matterportSweepID
884
+ });
885
+ }
886
+ processedOverall++;
887
+ emitProgress('pois', i + 1, sourcePois.length);
888
+ const pct = sourcePois.length > 0 ? Math.round(((i + 1) / sourcePois.length) * 100) : 100;
889
+ this.setStepProgress('pois', 'pois', pct);
890
+ }
561
891
  this.copyProgress$.next({
562
892
  phase: 'done',
563
893
  processedInPhase: 0, totalInPhase: 0,
564
894
  processedOverall, totalOverall,
565
- percent: 100, errorCount
895
+ percent: 100, errorCount, healedCount
566
896
  });
567
897
  this.setStepLog('done', errorCount > 0
568
898
  ? this.translate.instant('matterportCopy.doneWithErrors', { count: errorCount })
569
899
  : this.translate.instant('matterportCopy.done'));
900
+ // Separate summary line, on top of (not instead of) the done/doneWithErrors one
901
+ // above: healing is orthogonal to success/failure, an already-complete run can
902
+ // still have repaired items left over from an earlier, incomplete attempt.
903
+ if (healedCount > 0) {
904
+ this.setStepLog('healedSummary', this.translate.instant('matterportCopy.healedSummary', { count: healedCount }));
905
+ }
570
906
  return true;
571
907
  }
572
908
  catch (error) {
@@ -575,6 +911,23 @@ export class MatterportTagCopyService {
575
911
  this.copyProgress$.next(null);
576
912
  return false;
577
913
  }
914
+ finally {
915
+ // Every exit path — success, partial success, or general failure — gives back the
916
+ // keywords this run created but no copied POI ended up using. Placed in `finally`
917
+ // so an exception thrown mid-copy cannot leave them behind either.
918
+ await this.cleanupUnusedCreatedHashtags();
919
+ }
920
+ }
921
+ /**
922
+ * Serialises the current copy log (step lines as last emitted, plus every error and
923
+ * healed-item notice) to a plain-text file and triggers a browser download — wired to a
924
+ * "download log" button in the copy UI, so an operator can keep or share the full report
925
+ * of a run rather than only the ~200px scrollable panel showing it.
926
+ */
927
+ downloadLog(filename) {
928
+ const text = this.log.map(entry => entry.text).join('\n');
929
+ const defaultName = `matterport-copy-log-${new Date().toISOString().replace(/[:.]/g, '-')}.txt`;
930
+ downloadBlob(new Blob([text], { type: 'text/plain;charset=utf-8' }), filename || defaultName);
578
931
  }
579
932
  //
580
933
  // ---------- Progress / log helpers ----------
@@ -593,16 +946,41 @@ export class MatterportTagCopyService {
593
946
  }
594
947
  /** Appends a new, permanent log line (never overwritten), then republishes the log. */
595
948
  appendErrorLog(text) {
596
- this.errorSeq++;
597
- this.log.push({ id: `error-${this.errorSeq}`, type: 'error', text });
949
+ this.logSeq++;
950
+ this.log.push({ id: `error-${this.logSeq}`, type: 'error', text });
951
+ this.copyLog$.next([...this.log]);
952
+ }
953
+ /** Appends a permanent log line for an item that was repaired rather than newly
954
+ * created — see healEquipmentIdentity() and its ticket/feature equivalents. */
955
+ appendHealedLog(text) {
956
+ this.logSeq++;
957
+ this.log.push({ id: `healed-${this.logSeq}`, type: 'healed', text });
598
958
  this.copyLog$.next([...this.log]);
599
959
  }
600
960
  /** Resets the log for a new run. */
601
961
  resetLog() {
602
962
  this.log = [];
603
- this.errorSeq = 0;
963
+ this.logSeq = 0;
604
964
  this.copyLog$.next([]);
605
965
  }
966
+ /** Clears every id map carried over from a previous run. The service is a root-level
967
+ * singleton, so leftover mappings would silently link a new copy to records created
968
+ * during the previous one. */
969
+ resetRunState(targetSpaceId) {
970
+ this.elementIds = {};
971
+ this.commentIds = new Map();
972
+ this.sourceHashtagNames = new Map();
973
+ this.targetHashtagIdsByName = new Map();
974
+ this.createdHashtagIds = new Set();
975
+ this.usedHashtagIds = new Set();
976
+ this.handledElementIds = new Set();
977
+ this.sourceMissionUserIds = new Map();
978
+ this.targetMissionIdsByUserId = new Map();
979
+ this.domainsById = new Map();
980
+ this.targetVisibleDomainOrgIds = new Set();
981
+ this.targetDomainIdsByTypeAndName = new Map();
982
+ this.targetSpaceId = targetSpaceId;
983
+ }
606
984
  /** Builds and sets a step's log line as "<translated label>: <percent>%", no step numbering. */
607
985
  setStepProgress(stepId, translationKey, percent) {
608
986
  const label = this.translate.instant(`matterportCopy.${translationKey}`);
@@ -613,31 +991,628 @@ export class MatterportTagCopyService {
613
991
  const text = this.translate.instant(`matterportCopy.${translationKey}`, params);
614
992
  this.appendErrorLog(text);
615
993
  }
994
+ /** Logs a translated line for an item that already existed in the target space and had
995
+ * its missing identity fields filled in, so the operator can tell it apart from a
996
+ * freshly created item in the copy report. */
997
+ logHealedItem(translationKey, itemLabel, healedFields) {
998
+ const text = this.translate.instant(`matterportCopy.${translationKey}`, {
999
+ name: itemLabel,
1000
+ fields: healedFields.join(', ')
1001
+ });
1002
+ this.appendHealedLog(text);
1003
+ }
616
1004
  /** Logs an item-level error, using a specific "missing file / orphaned reference"
617
1005
  * translation key when the cause is a MissingS3FileError, and the generic per-type
618
1006
  * key otherwise. Keeps the copy log readable: a missing file is not a bug to
619
- * investigate the same way a network/permission error is. */
620
- logCopyItemError(error, genericKey, itemLabel) {
1007
+ * investigate the same way a network/permission error is.
1008
+ * `extraParams` carries the placeholders a few keys need on top of {{name}}/{{error}}
1009
+ * (e.g. errorFeatureAttachment's {{feature}}, errorPoi's {{sweep}}), which used to be
1010
+ * rendered as raw "{{feature}}" text in the log. */
1011
+ logCopyItemError(error, genericKey, itemLabel, extraParams = {}) {
621
1012
  if (error instanceof MissingS3FileError) {
622
1013
  this.logItemError('errorMissingS3FileSkipped', {
1014
+ ...extraParams,
623
1015
  name: itemLabel,
624
1016
  file: error.sourceKey
625
1017
  });
626
1018
  }
627
1019
  else {
628
- this.logItemError(genericKey, { name: itemLabel, error: toErrorMessage(error) });
1020
+ this.logItemError(genericKey, { ...extraParams, name: itemLabel, error: toErrorMessage(error) });
1021
+ }
1022
+ }
1023
+ /**
1024
+ * Null-safe equivalent of FeatureService.isArchived(): true when the operator has archived
1025
+ * this feature on that space. "No mission on the space" answers false (nothing archived)
1026
+ * instead of throwing, which is what made a copy from a space the operator is not a member
1027
+ * of fail outright.
1028
+ */
1029
+ isArchivedForOperator(feature, spaceId) {
1030
+ const archivedFor = feature?.archivedForMissionID;
1031
+ if (!archivedFor || archivedFor.length === 0) {
1032
+ return false;
629
1033
  }
1034
+ const mission = this.userService.currentMission(spaceId);
1035
+ return mission?.id ? archivedFor.includes(mission.id) : false;
1036
+ }
1037
+ //
1038
+ // ---------- Cross-space reference remapping ----------
1039
+ //
1040
+ /** Normalised lookup key for a domain: type disambiguates same-named domains used for
1041
+ * different purposes (equipment vs. ticket vs. feature categories, ...). */
1042
+ domainKey(type, name) {
1043
+ return `${type || ''}::${(name || '').trim().toLowerCase()}`;
1044
+ }
1045
+ /**
1046
+ * READ-ONLY indexing of every domain either operator's Mission can see. Creates
1047
+ * nothing — unlike hashtags, a domain is a business taxonomy entry an operator manages
1048
+ * deliberately; this tool only ever reuses an EXISTING equivalent, it never invents one.
1049
+ *
1050
+ * Visibility is keyed to `currentMission(spaceId).organisationID` /
1051
+ * `.orderedOrganisationID` for EACH space — exactly what
1052
+ * `DomainService.getDomainsForOrgForType()` uses to populate the category dropdown on
1053
+ * the equipment/ticket/feature edit forms (see form-equipment.component.ts,
1054
+ * batch-edit-equipment.component.ts, form-feature.component.ts). Comparing the spaces'
1055
+ * OWN `organisationID` instead — the previous approach — missed every domain reachable
1056
+ * only through the operator's `orderedOrganisationID` (set when a mission is created "on
1057
+ * behalf of" another organisation — see form-mission.component.ts), which is exactly how
1058
+ * a domain ends up visible on two spaces that belong to different organisations.
1059
+ */
1060
+ async loadDomainIndex(sourceSpaceId, targetSpaceId) {
1061
+ const sourceMission = this.userService.currentMission(sourceSpaceId);
1062
+ const targetMission = this.userService.currentMission(targetSpaceId);
1063
+ const sourceOrgIds = [sourceMission?.organisationID, sourceMission?.orderedOrganisationID]
1064
+ .filter((id) => !!id);
1065
+ const targetOrgIds = [targetMission?.organisationID, targetMission?.orderedOrganisationID]
1066
+ .filter((id) => !!id);
1067
+ this.targetVisibleDomainOrgIds = new Set(targetOrgIds);
1068
+ const allOrgIds = Array.from(new Set([...sourceOrgIds, ...targetOrgIds]));
1069
+ if (allOrgIds.length === 0) {
1070
+ // The operator has no mission on either space — nothing to resolve against;
1071
+ // every domainID will be dropped, same as an unresolvable lookup elsewhere.
1072
+ return;
1073
+ }
1074
+ try {
1075
+ const domainLists = await Promise.all(allOrgIds.map(orgId => this.domainService.getAllGenericDomainsAndForOrganisation(orgId)));
1076
+ for (const list of domainLists) {
1077
+ for (const domain of list || []) {
1078
+ if (domain?.id) {
1079
+ this.domainsById.set(domain.id, domain);
1080
+ }
1081
+ }
1082
+ }
1083
+ }
1084
+ catch (error) {
1085
+ console.warn('[MatterportTagCopyService] Could not read the domains, cross-organisation categories will be dropped:', error);
1086
+ return;
1087
+ }
1088
+ for (const domain of this.domainsById.values()) {
1089
+ const visibleToTarget = !domain.organisationID || this.targetVisibleDomainOrgIds.has(domain.organisationID);
1090
+ if (visibleToTarget && domain.name) {
1091
+ this.targetDomainIdsByTypeAndName.set(this.domainKey(domain.type, domain.name), domain.id);
1092
+ }
1093
+ }
1094
+ }
1095
+ /**
1096
+ * Resolves a source domainID (equipment/ticket/feature/POI category) for use in the
1097
+ * target space.
1098
+ *
1099
+ * - generic domain (no organisationID of its own — a shared taxonomy entry, e.g. a
1100
+ * standard category created by the platform): reused unchanged, valid everywhere.
1101
+ * - the domain's own organisationID is already one the TARGET operator's mission can
1102
+ * see (its organisationID, or its orderedOrganisationID): reused unchanged too — the
1103
+ * id is directly selectable in the target space's own dropdown as-is.
1104
+ * - otherwise: matched by (type, name) against the domains visible to the TARGET
1105
+ * operator (loadDomainIndex()); dropped when no equivalent exists there.
1106
+ */
1107
+ resolveDomainID(sourceDomainId) {
1108
+ if (!sourceDomainId) {
1109
+ return null;
1110
+ }
1111
+ const domain = this.domainsById.get(sourceDomainId);
1112
+ if (!domain) {
1113
+ // Not visible to either operator's mission (lookup failed, or it belongs to
1114
+ // neither) — unchanged, safest to drop.
1115
+ return null;
1116
+ }
1117
+ if (!domain.organisationID || this.targetVisibleDomainOrgIds.has(domain.organisationID)) {
1118
+ return sourceDomainId;
1119
+ }
1120
+ return this.targetDomainIdsByTypeAndName.get(this.domainKey(domain.type, domain.name)) ?? null;
1121
+ }
1122
+ /** Normalised lookup key for a hashtag name, so "Moyen Âge" and "moyen âge " match. */
1123
+ hashtagKey(name) {
1124
+ return name.trim().toLowerCase();
1125
+ }
1126
+ /**
1127
+ * READ-ONLY indexing of both spaces' hashtags. Creates nothing.
1128
+ *
1129
+ * `Feature.hashtags` stores Hashtag *ids*, and a Hashtag is a per-space record, so the
1130
+ * ids have to be translated by name. The translation table is built here; the missing
1131
+ * keywords are created later, one at a time, only when a POI that actually uses them is
1132
+ * about to be written (see resolveHashtagIds()).
1133
+ */
1134
+ async loadHashtagIndex(sourceSpaceId, targetSpaceId) {
1135
+ let sourceHashtags = [];
1136
+ let targetHashtags = [];
1137
+ try {
1138
+ [sourceHashtags, targetHashtags] = await Promise.all([
1139
+ this.hashtagService.listHashtagsForSpace(sourceSpaceId),
1140
+ this.hashtagService.listHashtagsForSpace(targetSpaceId)
1141
+ ]);
1142
+ }
1143
+ catch (error) {
1144
+ console.warn('[MatterportTagCopyService] Could not read the hashtags, keywords will be dropped:', error);
1145
+ return;
1146
+ }
1147
+ for (const hashtag of sourceHashtags || []) {
1148
+ if (hashtag?.id && hashtag.name) {
1149
+ this.sourceHashtagNames.set(hashtag.id, hashtag.name);
1150
+ }
1151
+ }
1152
+ for (const hashtag of targetHashtags || []) {
1153
+ if (hashtag?.id && hashtag.name) {
1154
+ this.targetHashtagIdsByName.set(this.hashtagKey(hashtag.name), hashtag.id);
1155
+ }
1156
+ }
1157
+ }
1158
+ /**
1159
+ * Translates one feature's hashtag ids into target-space ids, creating on the fly the
1160
+ * keywords the target space does not have yet.
1161
+ *
1162
+ * Creation is LAZY on purpose. Doing it up front, for the whole source vocabulary, meant
1163
+ * that a copy which failed or was closed halfway left behind keywords no POI referenced —
1164
+ * pollution the operator had to clean up by hand. Here a keyword is only ever written
1165
+ * when a POI that carries it is about to be created, so an interrupted copy stops
1166
+ * creating keywords at the same POI it stops creating content.
1167
+ *
1168
+ * The residual window (keyword created, then createFeature fails) is closed by
1169
+ * markHashtagsUsed() + cleanupUnusedCreatedHashtags().
1170
+ *
1171
+ * A keyword that can neither be found nor created is dropped rather than left as a
1172
+ * dangling id.
1173
+ */
1174
+ async resolveHashtagIds(sourceHashtagIds, targetSpaceId) {
1175
+ if (!sourceHashtagIds || sourceHashtagIds.length === 0) {
1176
+ return null;
1177
+ }
1178
+ const resolved = [];
1179
+ for (const sourceId of sourceHashtagIds) {
1180
+ if (!sourceId) {
1181
+ continue;
1182
+ }
1183
+ const name = this.sourceHashtagNames.get(sourceId);
1184
+ if (!name) {
1185
+ // the source id points at a hashtag that no longer exists — nothing to carry over
1186
+ continue;
1187
+ }
1188
+ const key = this.hashtagKey(name);
1189
+ let targetId = this.targetHashtagIdsByName.get(key);
1190
+ if (!targetId) {
1191
+ try {
1192
+ const created = await this.hashtagService.createHashtagForSpace(name, targetSpaceId);
1193
+ targetId = created?.id;
1194
+ if (targetId) {
1195
+ this.targetHashtagIdsByName.set(key, targetId);
1196
+ this.createdHashtagIds.add(targetId);
1197
+ }
1198
+ }
1199
+ catch (error) {
1200
+ console.warn(`[MatterportTagCopyService] Could not create the hashtag "${name}" in the target space:`, error);
1201
+ continue;
1202
+ }
1203
+ }
1204
+ if (targetId && !resolved.includes(targetId)) {
1205
+ resolved.push(targetId);
1206
+ }
1207
+ }
1208
+ return resolved.length > 0 ? resolved : null;
1209
+ }
1210
+ /**
1211
+ * READ-ONLY indexing of both spaces' missions.
1212
+ *
1213
+ * A Mission is scoped to one space (it pairs a userID with a spaceID), so the id a
1214
+ * source comment's `ownerID` points at never designates anyone in the target space.
1215
+ * This builds the two lookup tables resolveCommentOwnerID() needs to translate it:
1216
+ * which user a source Mission id belongs to, and which Mission (if any) that same
1217
+ * user already holds in the target space.
1218
+ */
1219
+ async loadMissionIndex(sourceSpaceId, targetSpaceId) {
1220
+ let sourceMissions = [];
1221
+ let targetMissions = [];
1222
+ try {
1223
+ [sourceMissions, targetMissions] = await Promise.all([
1224
+ this.missionService.getAllMissionsForSpace(sourceSpaceId),
1225
+ this.missionService.getAllMissionsForSpace(targetSpaceId)
1226
+ ]);
1227
+ }
1228
+ catch (error) {
1229
+ console.warn('[MatterportTagCopyService] Could not read the missions, comment authorship will be dropped:', error);
1230
+ return;
1231
+ }
1232
+ for (const mission of sourceMissions || []) {
1233
+ if (mission?.id && mission.userID) {
1234
+ this.sourceMissionUserIds.set(mission.id, mission.userID);
1235
+ }
1236
+ }
1237
+ for (const mission of targetMissions || []) {
1238
+ if (mission?.id && mission.userID && !this.targetMissionIdsByUserId.has(mission.userID)) {
1239
+ this.targetMissionIdsByUserId.set(mission.userID, mission.id);
1240
+ }
1241
+ }
1242
+ }
1243
+ /**
1244
+ * Translates a source comment's `ownerID` (a per-space Mission id) into the Mission of
1245
+ * the SAME user in the target space, so the copy keeps crediting its real author.
1246
+ *
1247
+ * Substituting the current operator's mission — the way `ownerMissionID` legitimately
1248
+ * does for tickets/equipment/features, which really do change owner on a copy — would
1249
+ * misattribute every comment to whoever ran the copy instead of who actually wrote it.
1250
+ *
1251
+ * When the original author has no mission in the target space (never granted access
1252
+ * there), the comment is left with no owner rather than a wrong one: an absent author
1253
+ * is honest, a misattributed one is not.
1254
+ */
1255
+ resolveCommentOwnerID(sourceOwnerID) {
1256
+ if (!sourceOwnerID) {
1257
+ return null;
1258
+ }
1259
+ const userID = this.sourceMissionUserIds.get(sourceOwnerID);
1260
+ if (!userID) {
1261
+ return null;
1262
+ }
1263
+ return this.targetMissionIdsByUserId.get(userID) ?? null;
1264
+ }
1265
+ /** Records that these hashtags are now referenced by a feature that really exists, so
1266
+ * the end-of-run cleanup leaves them alone. */
1267
+ markHashtagsUsed(hashtagIds) {
1268
+ for (const id of hashtagIds || []) {
1269
+ this.usedHashtagIds.add(id);
1270
+ }
1271
+ }
1272
+ /**
1273
+ * Deletes the hashtags this run created that no copied POI ended up referencing.
1274
+ *
1275
+ * Runs on every exit path — success, general failure, or exception — so the target space
1276
+ * never keeps keywords that came from an aborted copy. Only ids created by THIS run are
1277
+ * ever considered: a pre-existing keyword of the target space is never touched, even if
1278
+ * no copied POI uses it.
1279
+ */
1280
+ async cleanupUnusedCreatedHashtags() {
1281
+ const orphans = [...this.createdHashtagIds].filter(id => !this.usedHashtagIds.has(id));
1282
+ if (orphans.length === 0) {
1283
+ return;
1284
+ }
1285
+ console.log(`[MatterportTagCopyService] Removing ${orphans.length} keyword(s) created but left unused by this copy.`);
1286
+ for (const hashtagId of orphans) {
1287
+ try {
1288
+ await this.hashtagService.deleteHashtagById(hashtagId);
1289
+ this.createdHashtagIds.delete(hashtagId);
1290
+ }
1291
+ catch (error) {
1292
+ // Cleanup is best-effort: a leftover keyword is harmless next to a failed copy,
1293
+ // and must never be the reason the whole operation reports a failure.
1294
+ console.warn(`[MatterportTagCopyService] Could not remove the unused keyword "${hashtagId}":`, error);
1295
+ }
1296
+ }
1297
+ }
1298
+ //
1299
+ // ---------- Media content (Comments) ----------
1300
+ //
1301
+ /**
1302
+ * Orders a feature's media set exactly the way the UI will read it back, and repairs
1303
+ * the ordering key when the source data cannot express the user's intended order.
1304
+ *
1305
+ * The viewer sorts each media family on its own (`setImages`, `setVideos`, `setAudio`,
1306
+ * `setDocuments`, ... all do `.sort((a, b) => a.index - b.index)`), so `index` only has
1307
+ * to be consistent WITHIN a CommentType. The attachment form however defaults `index`
1308
+ * to 1 for every new attachment, so a multi-image POI very often holds several images
1309
+ * all sharing index 1 — or null. Sorting those is left to DynamoDB's arbitrary scan
1310
+ * order, which is why the copy came out in a different order than the original.
1311
+ *
1312
+ * Strategy: sort deterministically (index, then creation date, then id — i.e. the
1313
+ * upload order the user actually saw), and only rewrite the indices of a family when
1314
+ * they are ambiguous (null or duplicated). A family whose indices are already unique
1315
+ * is copied untouched, so a deliberate ordering is never overwritten.
1316
+ */
1317
+ orderCommentsForCopy(comments) {
1318
+ const valid = (comments || []).filter(c => !!c);
1319
+ const byType = new Map();
1320
+ for (const comment of valid) {
1321
+ const key = comment.type || 'UNTYPED';
1322
+ if (!byType.has(key)) {
1323
+ byType.set(key, []);
1324
+ }
1325
+ byType.get(key).push(comment);
1326
+ }
1327
+ const ordered = [];
1328
+ for (const family of byType.values()) {
1329
+ family.sort((a, b) => {
1330
+ const ai = this.orderingIndexOf(a);
1331
+ const bi = this.orderingIndexOf(b);
1332
+ if (ai !== bi) {
1333
+ return ai - bi;
1334
+ }
1335
+ const ad = this.creationTimeOf(a);
1336
+ const bd = this.creationTimeOf(b);
1337
+ if (ad !== bd) {
1338
+ return ad - bd;
1339
+ }
1340
+ return String(a.id || '').localeCompare(String(b.id || ''));
1341
+ });
1342
+ const indices = family.map(c => c.index);
1343
+ const isAmbiguous = indices.some(i => i === null || i === undefined)
1344
+ || new Set(indices).size !== indices.length;
1345
+ family.forEach((comment, position) => {
1346
+ comment.__copyIndex = isAmbiguous ? position + 1 : comment.index;
1347
+ });
1348
+ ordered.push(...family);
1349
+ }
1350
+ return ordered;
1351
+ }
1352
+ /** Sort key for a comment's position; a missing index sorts last, not first. */
1353
+ orderingIndexOf(comment) {
1354
+ const index = comment?.index;
1355
+ return index === null || index === undefined || Number.isNaN(Number(index))
1356
+ ? Number.MAX_SAFE_INTEGER
1357
+ : Number(index);
1358
+ }
1359
+ /** Creation timestamp of a comment, used as the tie-breaker: it reflects the order in
1360
+ * which the user uploaded the media, which is the order they saw. */
1361
+ creationTimeOf(comment) {
1362
+ const createdAt = comment?.createdAt;
1363
+ if (!createdAt) {
1364
+ return 0;
1365
+ }
1366
+ const time = new Date(createdAt).getTime();
1367
+ return Number.isNaN(time) ? 0 : time;
1368
+ }
1369
+ /**
1370
+ * Copies ONE media item (image, video, audio, document, text, link, embed, iframe...)
1371
+ * of a feature, duplicating its file in S3 first when it has one.
1372
+ *
1373
+ * Every column of the Comment model is carried over. `description` and `metadata` were
1374
+ * previously dropped, which emptied the captions of images/videos, the body of TEXT
1375
+ * items — where the whole content lives, since a TEXT comment has no file — and any
1376
+ * per-media settings stored in metadata.
1377
+ */
1378
+ async copyCommentForFeature(sourceComment, targetFeatureId, targetSpaceId) {
1379
+ return this.copyComment(sourceComment, targetSpaceId, { featureID: targetFeatureId });
1380
+ }
1381
+ /** Same, for an attachment carried by a ticket rather than by a feature. */
1382
+ async copyCommentForTicket(sourceComment, targetTicketId, targetSpaceId) {
1383
+ return this.copyComment(sourceComment, targetSpaceId, { ticketID: targetTicketId });
1384
+ }
1385
+ /** Shared body of the two above: `owner` carries whichever foreign key links the copy back
1386
+ * to its new parent, everything else is identical. */
1387
+ async copyComment(sourceComment, targetSpaceId, owner) {
1388
+ const rawComment = sourceComment;
1389
+ let copiedAnnexe = null;
1390
+ if (rawComment.annexe) {
1391
+ copiedAnnexe = await this.copyS3KeyIfPresent(rawComment.annexe, `attachment "${rawComment.title}"`);
1392
+ }
1393
+ const commentInput = {
1394
+ title: rawComment.title,
1395
+ description: rawComment.description ?? null,
1396
+ metadata: rawComment.metadata ?? null,
1397
+ type: rawComment.type,
1398
+ annexe: copiedAnnexe,
1399
+ externalLink: rawComment.externalLink || null,
1400
+ dimensions: rawComment.dimensions || null,
1401
+ index: rawComment.__copyIndex ?? rawComment.index ?? null,
1402
+ shownInTag: rawComment.shownInTag,
1403
+ isCoverImage: rawComment.isCoverImage,
1404
+ spaceID: targetSpaceId,
1405
+ // Keeps crediting the ORIGINAL author when they also have a mission in the
1406
+ // target space, and leaves the comment un-owned otherwise — see
1407
+ // resolveCommentOwnerID(). Never the current operator's own mission: that
1408
+ // would silently reassign authorship to whoever happens to run the copy.
1409
+ ownerID: this.resolveCommentOwnerID(rawComment.ownerID),
1410
+ ...owner
1411
+ };
1412
+ return this.commentService.createComment(commentInput);
1413
+ }
1414
+ //
1415
+ // ---------- POI creation ----------
1416
+ //
1417
+ /**
1418
+ * Creates the target-space copy of a source POI, with EVERY column of the POI model.
1419
+ *
1420
+ * Single entry point for all phases: the element phases (ticket, equipment, 3D object,
1421
+ * feature, measurement) used to build their POI inline with only 5 fields — coordinate,
1422
+ * type, elementID, metadata, sweep — which is precisely how museum POIs lost their
1423
+ * pastille: `tagDescription` (the popup text), `tagIcon` (the custom icon) and
1424
+ * `tagImageID` (the pastille's image) never left the source space.
1425
+ */
1426
+ async createCopiedPoi(sourcePoi, elementID, sourceNavPositions, targetNavPositions, transform) {
1427
+ const raw = sourcePoi;
1428
+ const targetSweepId = this.findClosestTargetSweepId(sourcePoi.matterportSweepID, sourceNavPositions, targetNavPositions, transform);
1429
+ const adjustedCoordinate = this.getAdjustedCoordinates(sourcePoi.coordinate, transform);
1430
+ const poiInput = {
1431
+ coordinate: adjustedCoordinate === null || adjustedCoordinate === undefined
1432
+ ? null
1433
+ : JSON.stringify(adjustedCoordinate),
1434
+ type: sourcePoi.type,
1435
+ elementID: elementID ?? null,
1436
+ matterportSweepID: targetSweepId,
1437
+ // --- pastille (tag popup) ---
1438
+ tagDescription: sourcePoi.tagDescription ?? null,
1439
+ tagIcon: await this.duplicateTagIcon(sourcePoi.tagIcon),
1440
+ tagImageID: this.resolveTagImageID(sourcePoi.tagImageID),
1441
+ // --- rendering / visibility flags, carried over verbatim ---
1442
+ specific: raw.specific ?? null,
1443
+ private: raw.private ?? null,
1444
+ global: raw.global ?? null,
1445
+ level: raw.level ?? null,
1446
+ role: raw.role ?? null,
1447
+ category: raw.category ?? null,
1448
+ domainID: this.resolveDomainID(raw.domainID),
1449
+ // --- Matterport anchoring ---
1450
+ metadata: this.getAdjustedPoiMetadata(sourcePoi.metadata, transform)
1451
+ };
1452
+ return this.poiService.createPOIForSpaceID(poiInput);
1453
+ }
1454
+ /**
1455
+ * Adapts a POI's `metadata` (see MattertagData.getMetadataString(): { icon, normal, sid })
1456
+ * to the target space.
1457
+ *
1458
+ * - `sid` is the id of the Mattertag inside the SOURCE Matterport model. Carried over,
1459
+ * the viewer tries to re-create the target's tag with an id belonging to another
1460
+ * model ("already in use"), so the pastille fails to attach. It is dropped: the
1461
+ * viewer then allocates a fresh sid on first render.
1462
+ * - `normal` is the stem direction. It is a direction, so only the rotation applies
1463
+ * (never the translation); without it, a copied pastille points into the wall
1464
+ * whenever the two models are not aligned on the same axis.
1465
+ * - `icon` and anything else is kept as-is.
1466
+ */
1467
+ getAdjustedPoiMetadata(metadata, transform) {
1468
+ if (!metadata) {
1469
+ return metadata ?? null;
1470
+ }
1471
+ try {
1472
+ const parsed = JSON.parse(metadata);
1473
+ if (!parsed || typeof parsed !== 'object') {
1474
+ return metadata;
1475
+ }
1476
+ if (parsed.normal
1477
+ && typeof parsed.normal === 'object'
1478
+ && typeof parsed.normal.x === 'number'
1479
+ && typeof parsed.normal.y === 'number'
1480
+ && typeof parsed.normal.z === 'number') {
1481
+ parsed.normal = applyRigidTransformToDirection(parsed.normal, transform);
1482
+ }
1483
+ delete parsed.sid;
1484
+ return JSON.stringify(parsed);
1485
+ }
1486
+ catch {
1487
+ // Not JSON, or unexpected shape — leave untouched rather than guess.
1488
+ return metadata;
1489
+ }
1490
+ }
1491
+ /**
1492
+ * Resolves a POI's `tagImageID` — which the schema documents as a "connection to
1493
+ * comment.id", i.e. the id of the Comment holding the image shown in the pastille.
1494
+ *
1495
+ * It is NOT an S3 key, so the previous "does it contain a slash?" heuristic never
1496
+ * matched and the value travelled unchanged, leaving every copied pastille pointing at
1497
+ * a Comment of the source space. It is now translated through the comment id map built
1498
+ * while duplicating the media, and dropped when it cannot be resolved (the pastille
1499
+ * then falls back to the feature's cover image instead of a broken reference).
1500
+ */
1501
+ resolveTagImageID(tagImageID) {
1502
+ if (!tagImageID) {
1503
+ return null;
1504
+ }
1505
+ return this.commentIds.get(tagImageID) ?? null;
630
1506
  }
631
1507
  //
632
1508
  // ---------- Duplicate detection ----------
633
1509
  //
634
1510
  /**
635
- * Heuristic duplicate-detection: compares title AND description together instead of
636
- * title alone, to reduce false positives when several source items happen to share
637
- * the same title. Not a perfect guarantee, but meaningfully more robust.
1511
+ * Heuristic duplicate-detection: compares several identifying fields together rather than
1512
+ * a single label, to reduce false positives when items share one of them. Returns the
1513
+ * matched target item (or undefined) rather than a boolean, so the caller can act on the
1514
+ * existing record — heal its missing fields — instead of only skipping it.
1515
+ *
1516
+ * The fields are supplied by the caller because the models do not agree on them. The
1517
+ * previous version hard-coded `title`/`description`, which do not exist on Equipment at
1518
+ * all: both sides read `undefined`, every equipment therefore "matched" every other one,
1519
+ * and a target space holding a single equipment silently caused the whole equipment phase
1520
+ * to copy nothing.
638
1521
  */
639
- matchesExisting(source, targetList) {
640
- return targetList.some(t => t.title === source.title && (t.description || null) === (source.description || null));
1522
+ findExisting(source, targetList, identity) {
1523
+ const sourceKey = this.identityKey(identity(source));
1524
+ return targetList.find(target => this.identityKey(identity(target)) === sourceKey);
1525
+ }
1526
+ /**
1527
+ * Builds a patch of whichever fields in `fields` the existing target record is missing
1528
+ * (`null`/`undefined`/empty array) but the source has, plus `domainID` when requested —
1529
+ * domains are organisation-scoped everywhere in this file, so that one is only ever
1530
+ * healed across the SAME organisation, exactly like at creation time.
1531
+ *
1532
+ * Never overwrites a field the target already carries a value for: a value entered by
1533
+ * hand in the target space since an earlier, incomplete copy must not be clobbered by
1534
+ * an older or different source value.
1535
+ *
1536
+ * Returns both the patch to send and the list of healed field names, so the caller can
1537
+ * both perform the update and describe it in the copy log.
1538
+ */
1539
+ buildHealPatch(sourceObj, existingTarget, fields, includeDomain) {
1540
+ const patch = {};
1541
+ const healedFields = [];
1542
+ const fillIfMissing = (key, sourceValue) => {
1543
+ const currentValue = existingTarget[key];
1544
+ const isMissing = currentValue === null || currentValue === undefined
1545
+ || (Array.isArray(currentValue) && currentValue.length === 0);
1546
+ if (isMissing && sourceValue !== null && sourceValue !== undefined) {
1547
+ patch[key] = sourceValue;
1548
+ healedFields.push(key);
1549
+ }
1550
+ };
1551
+ for (const field of fields) {
1552
+ fillIfMissing(field, sourceObj[field]);
1553
+ }
1554
+ if (includeDomain && (existingTarget.domainID === null || existingTarget.domainID === undefined)) {
1555
+ const resolvedDomainId = this.resolveDomainID(sourceObj.domainID);
1556
+ if (resolvedDomainId) {
1557
+ patch.domainID = resolvedDomainId;
1558
+ healedFields.push('domainID');
1559
+ }
1560
+ }
1561
+ return { patch, healedFields };
1562
+ }
1563
+ /**
1564
+ * Fills in whichever identity field a PRE-EXISTING target equipment is missing but the
1565
+ * source has — see the call site in the EQUIPMENTS phase for why re-running the copy
1566
+ * has to be able to repair a previously-copied equipment, not just skip it again.
1567
+ *
1568
+ * A failed update is left to bubble up to the caller's existing per-item try/catch, the
1569
+ * same as a failed creation — it gets the same visible error line, rather than a silent
1570
+ * console warning.
1571
+ *
1572
+ * Returns the list of fields that were actually healed (empty if nothing was missing).
1573
+ */
1574
+ async healEquipmentIdentity(sourceObj, existingTarget) {
1575
+ const { patch, healedFields } = this.buildHealPatch(sourceObj, existingTarget, ['status', 'annotation', 'family', 'sku', 'manufacturer', 'installDate', 'warrantyEndDate', 'metadata', 'isCreatedByAI'], true);
1576
+ if (!existingTarget.photo && sourceObj.photo) {
1577
+ patch.photo = await this.copyS3KeyIfPresent(sourceObj.photo, `equipment photo "${sourceObj.name}"`);
1578
+ healedFields.push('photo');
1579
+ }
1580
+ if (healedFields.length === 0) {
1581
+ return healedFields;
1582
+ }
1583
+ patch.id = existingTarget.id;
1584
+ await this.equipmentService.updateEquipment(patch);
1585
+ return healedFields;
1586
+ }
1587
+ /**
1588
+ * Same idea as healEquipmentIdentity(), for a pre-existing ticket. `title`/`description`
1589
+ * are the pair findExisting() matched on to find this ticket in the first place, so they
1590
+ * are never part of the heal — by construction, they already agree with the source.
1591
+ */
1592
+ async healTicketIdentity(sourceObj, existingTarget) {
1593
+ const { patch, healedFields } = this.buildHealPatch(sourceObj, existingTarget, ['friendlyLabel', 'status', 'type', 'priority', 'level', 'metadata', 'read', 'projectID', 'problemCode'], true);
1594
+ if (healedFields.length === 0) {
1595
+ return healedFields;
1596
+ }
1597
+ patch.id = existingTarget.id;
1598
+ await this.ticketService.updateTicket(patch);
1599
+ return healedFields;
1600
+ }
1601
+ /** Same idea, for a pre-existing feature. Keywords, media and POIs are not healed here
1602
+ * for the same reason notes/POIs are not healed on equipment — see healEquipmentIdentity(). */
1603
+ async healFeatureIdentity(sourceObj, existingTarget) {
1604
+ const { patch, healedFields } = this.buildHealPatch(sourceObj, existingTarget, ['shortDescription', 'level', 'type', 'index', 'stripeProductID', 'stripePriceID', 'bookingPriceMetadata', 'locale'], true);
1605
+ if (healedFields.length === 0) {
1606
+ return healedFields;
1607
+ }
1608
+ patch.id = existingTarget.id;
1609
+ await this.featureService.updateFeature(patch);
1610
+ return healedFields;
1611
+ }
1612
+ /** Serialises the identifying fields unambiguously, so that ["a", "b"] and ["ab", ""]
1613
+ * can never produce the same key. */
1614
+ identityKey(parts) {
1615
+ return JSON.stringify(parts.map(part => part ?? ''));
641
1616
  }
642
1617
  //
643
1618
  // ---------- Sweep positions / rigid transform ----------
@@ -731,10 +1706,12 @@ export class MatterportTagCopyService {
731
1706
  /**
732
1707
  * Builds a new S3 key for a copied attachment and sanitizes the filename
733
1708
  * to prevent AWS Amplify SignatureDoesNotMatch errors.
1709
+ * `folderOverride` re-homes the copy into another prefix — used for tag icons, which
1710
+ * are stored per space (`icons-tags/<spaceId>/`) and must follow the target space.
734
1711
  */
735
- buildCopiedAttachmentKey(sourceAnnexe) {
1712
+ buildCopiedAttachmentKey(sourceAnnexe, folderOverride = null) {
736
1713
  const lastSlash = sourceAnnexe.lastIndexOf('/');
737
- const folder = sourceAnnexe.substring(0, lastSlash + 1);
1714
+ const folder = folderOverride ?? sourceAnnexe.substring(0, lastSlash + 1);
738
1715
  let filename = sourceAnnexe.substring(lastSlash + 1);
739
1716
  // Strip a leading "<8 hex chars>_" id prefix if present
740
1717
  const prefixMatch = filename.match(/^[0-9a-fA-F-]{8}_(.+)$/);
@@ -754,12 +1731,12 @@ export class MatterportTagCopyService {
754
1731
  * skip the whole item entirely, rather than creating a record with a broken file link.
755
1732
  * - Any other kind of failure (permissions, network, etc.) still throws a generic Error.
756
1733
  */
757
- async copyS3KeyIfPresent(key, contextLabel) {
1734
+ async copyS3KeyIfPresent(key, contextLabel, folderOverride = null) {
758
1735
  if (!key) {
759
1736
  return null;
760
1737
  }
761
1738
  const sourceKey = this.extractS3KeyFromValue(key);
762
- const destKey = this.buildCopiedAttachmentKey(sourceKey);
1739
+ const destKey = this.buildCopiedAttachmentKey(sourceKey, folderOverride);
763
1740
  // Log the source key to ensure it matches the real S3 object path
764
1741
  console.log(`[DEBUG] Attempting S3 copy from source: "${sourceKey}" to dest: "${destKey}"`);
765
1742
  try {
@@ -770,49 +1747,101 @@ export class MatterportTagCopyService {
770
1747
  return copied;
771
1748
  }
772
1749
  catch (error) {
773
- const isMissingFile = error instanceof MissingS3FileError
774
- || error?.code === 'NoSuchKey'
775
- || /NoSuchKey|does not exist/i.test(toErrorMessage(error));
776
- if (isMissingFile) {
1750
+ if (this.isMissingS3File(error)) {
777
1751
  console.warn(`[MatterportTagCopyService] Orphaned S3 reference, skipping item: "${sourceKey}" (${contextLabel})`);
778
1752
  throw new MissingS3FileError(sourceKey, contextLabel);
779
1753
  }
1754
+ // Storage.copy() cannot handle a key holding a space, an accent or a parenthesis:
1755
+ // it puts the key unencoded into `x-amz-copy-source`, which then disagrees with the
1756
+ // signed request. Those files are perfectly readable — only that header is broken —
1757
+ // so fall back to downloading and re-uploading them.
1758
+ if (this.isSignatureMismatch(error)) {
1759
+ console.warn(`[MatterportTagCopyService] Storage.copy() signature mismatch on "${sourceKey}", falling back to download + re-upload.`);
1760
+ try {
1761
+ const copied = await copyFileInS3ViaDownload(sourceKey, destKey);
1762
+ if (!copied) {
1763
+ throw new MissingS3FileError(sourceKey, contextLabel);
1764
+ }
1765
+ return copied;
1766
+ }
1767
+ catch (fallbackError) {
1768
+ if (this.isMissingS3File(fallbackError)) {
1769
+ throw new MissingS3FileError(sourceKey, contextLabel);
1770
+ }
1771
+ throw fallbackError;
1772
+ }
1773
+ }
780
1774
  throw error;
781
1775
  }
782
1776
  }
1777
+ /** True when the failure means the source object simply is not on S3 (orphaned reference). */
1778
+ isMissingS3File(error) {
1779
+ return error instanceof MissingS3FileError
1780
+ || error?.code === 'NoSuchKey'
1781
+ || error?.name === 'NoSuchKey'
1782
+ || /NoSuchKey|does not exist|NotFound/i.test(toErrorMessage(error));
1783
+ }
1784
+ /** True when AppSync refused the operation for lack of permission, as opposed to failing it.
1785
+ * Nothing can be retried or worked around client-side: the account simply is not allowed
1786
+ * to write that model, which is a backend authorisation rule (@auth) to change. */
1787
+ isUnauthorized(error) {
1788
+ const message = toErrorMessage(error);
1789
+ return error?.errorType === 'Unauthorized'
1790
+ || /Unauthorized|Not Authorized to access/i.test(message);
1791
+ }
1792
+ /** True for the SigV4 mismatch Storage.copy() raises on keys with special characters. */
1793
+ isSignatureMismatch(error) {
1794
+ return error?.code === 'SignatureDoesNotMatch'
1795
+ || error?.name === 'SignatureDoesNotMatch'
1796
+ || /signature we calculated does not match|SignatureDoesNotMatch/i.test(toErrorMessage(error));
1797
+ }
783
1798
  /**
784
1799
  * Duplicates the file referenced by a POI's tagIcon (a JSON string shaped like
785
- * { src, opacity }, per form-feature.component.ts). If the JSON can't be parsed or
786
- * has no `src`, the value is returned unchanged rather than risk corrupting it.
1800
+ * { src, opacity }, per form-feature.component.ts).
1801
+ *
1802
+ * Two behaviours matter here:
1803
+ * - the copy is re-homed under the TARGET space's icon folder
1804
+ * (`icons-tags/<targetSpaceId>/`, the layout form-feature.component.ts uploads to).
1805
+ * Keeping the source folder produced a target space whose icons all lived under
1806
+ * another space's prefix, so cleaning up the source space broke the copy's icons.
1807
+ * - a missing icon file is NOT fatal. It used to bubble up as a MissingS3FileError and
1808
+ * abort the whole POI — losing the pastille, its text and its media because of a
1809
+ * decorative file. The POI is now created with the icon reference dropped, which
1810
+ * renders the module's default icon, and a log line reports it.
787
1811
  */
788
1812
  async duplicateTagIcon(tagIconRaw) {
789
1813
  if (!tagIconRaw) {
790
- return tagIconRaw;
1814
+ return tagIconRaw ?? null;
791
1815
  }
1816
+ let parsed;
792
1817
  try {
793
- const parsed = JSON.parse(tagIconRaw);
794
- if (parsed && parsed.src) {
795
- parsed.src = await this.copyS3KeyIfPresent(parsed.src, 'tag icon');
796
- }
797
- return JSON.stringify(parsed);
1818
+ parsed = JSON.parse(tagIconRaw);
798
1819
  }
799
1820
  catch {
800
- // Not JSON, or unexpected shape — leave untouched rather than guess.
1821
+ // Not JSON — leave untouched rather than guess.
801
1822
  return tagIconRaw;
802
1823
  }
803
- }
804
- /**
805
- * Duplicates tagImageID if it looks like a reference to a file (contains a path
806
- * separator, whether raw key or pre-signed URL). UNCONFIRMED ASSUMPTION: this
807
- * field's exact semantics weren't verified — if it's actually an opaque reference
808
- * to another DB record rather than a file, this heuristic may incorrectly attempt
809
- * a copy. Confirm the real structure to tighten this if it causes issues.
810
- */
811
- async duplicateTagImageID(tagImageID) {
812
- if (!tagImageID || !tagImageID.includes('/')) {
813
- return tagImageID;
1824
+ if (!parsed || typeof parsed !== 'object' || !parsed.src) {
1825
+ return tagIconRaw;
1826
+ }
1827
+ try {
1828
+ parsed.src = await this.copyS3KeyIfPresent(parsed.src, 'tag icon', this.buildTargetIconFolder());
1829
+ }
1830
+ catch (iconError) {
1831
+ if (!(iconError instanceof MissingS3FileError)) {
1832
+ // A real failure (permissions, network, ...) still aborts the POI: it means
1833
+ // the copy cannot be trusted, unlike a file that is simply already gone.
1834
+ throw iconError;
1835
+ }
1836
+ console.warn(`[MatterportTagCopyService] Tag icon missing on S3, falling back to the default icon: "${iconError.sourceKey}"`);
1837
+ this.logItemError('warningTagIconMissing', { file: iconError.sourceKey });
1838
+ delete parsed.src;
814
1839
  }
815
- return this.copyS3KeyIfPresent(tagImageID, 'tag image');
1840
+ return JSON.stringify(parsed);
1841
+ }
1842
+ /** Icon folder of the space being copied into, matching what the feature form uploads to. */
1843
+ buildTargetIconFolder() {
1844
+ return this.targetSpaceId ? `icons-tags/${this.targetSpaceId}/` : null;
816
1845
  }
817
1846
  /**
818
1847
  * Extracts and normalizes the raw S3 key from a stored value (which may be a full URL
@@ -855,11 +1884,11 @@ export class MatterportTagCopyService {
855
1884
  // for the CopySource header. Do NOT re-encode it here.
856
1885
  return extracted;
857
1886
  }
858
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportTagCopyService, deps: [{ token: i1.NavigationService }, { token: i2.BaseUserService }, { token: i3.PoiService }, { token: i4.TicketsService }, { token: i5.EquipmentService }, { token: i6.Object3DService }, { token: i7.FeatureService }, { token: i8.MeasurementService }, { token: i9.CommentService }, { token: i10.TranslateService }], target: i0.ɵɵFactoryTarget.Injectable });
1887
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportTagCopyService, deps: [{ token: i1.NavigationService }, { token: i2.BaseUserService }, { token: i3.PoiService }, { token: i4.TicketsService }, { token: i5.EquipmentService }, { token: i6.Object3DService }, { token: i7.FeatureService }, { token: i8.MeasurementService }, { token: i9.CommentService }, { token: i10.HashtagService }, { token: i11.MissionService }, { token: i12.OperationService }, { token: i13.DomainService }, { token: i14.TranslateService }], target: i0.ɵɵFactoryTarget.Injectable });
859
1888
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportTagCopyService, providedIn: 'root' });
860
1889
  }
861
1890
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportTagCopyService, decorators: [{
862
1891
  type: Injectable,
863
1892
  args: [{ providedIn: 'root' }]
864
- }], ctorParameters: () => [{ type: i1.NavigationService }, { type: i2.BaseUserService }, { type: i3.PoiService }, { type: i4.TicketsService }, { type: i5.EquipmentService }, { type: i6.Object3DService }, { type: i7.FeatureService }, { type: i8.MeasurementService }, { type: i9.CommentService }, { type: i10.TranslateService }] });
865
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0dGVycG9ydC10YWctY29weS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWNvcmUvc3JjL2xpYi9zZXJ2aWNlcy9tYXR0ZXJwb3J0LXRhZy1jb3B5LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBWXZDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxjQUFjLENBQUMsQ0FBQyw2RkFBNkY7QUFDMUksT0FBTyxFQUNILHFCQUFxQixFQUFFLDBCQUEwQixFQUNqRCxpQ0FBaUMsRUFDcEMsTUFBTSxtQ0FBbUMsQ0FBQztBQUMzQyxPQUFPLEVBQTJDLFdBQVcsRUFBRSxPQUFPLEVBQWEsUUFBUSxFQUFVLE1BQU0sa0JBQWtCLENBQUM7Ozs7Ozs7Ozs7OztBQW9COUg7d0VBQ3dFO0FBQ3hFLFNBQVMsY0FBYyxDQUFDLEdBQVk7SUFDaEMsSUFBSSxHQUFHLElBQUksT0FBTyxHQUFHLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDakMsTUFBTSxNQUFNLEdBQUcsR0FBVSxDQUFDO1FBQzFCLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDM0QsT0FBTyxNQUFNLENBQUMsTUFBTTtpQkFDZixHQUFHLENBQUMsQ0FBQyxDQUFNLEVBQUUsRUFBRTtnQkFDWixNQUFNLEtBQUssR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUNwRCxPQUFPLEdBQUcsS0FBSyxHQUFHLENBQUMsQ0FB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QVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN0RCxDQUFDO1FBRUQsK0VBQStFO1FBQy9FLHVEQUF1RDtRQUN2RCxPQUFPLFNBQVMsQ0FBQztJQUNyQixDQUFDO3dHQTM2QlEsd0JBQXdCOzRHQUF4Qix3QkFBd0IsY0FEWCxNQUFNOzs0RkFDbkIsd0JBQXdCO2tCQURwQyxVQUFVO21CQUFDLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0IH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IFRyYW5zbGF0ZVNlcnZpY2UgfSBmcm9tICdAbmd4LXRyYW5zbGF0ZS9jb3JlJztcclxuaW1wb3J0IHsgUE9JIH0gZnJvbSAnLi4vdHlwZXMuc2VydmljZSc7XHJcbmltcG9ydCB7IE5hdmlnYXRpb25TZXJ2aWNlIH0gZnJvbSAnLi9tb2RlbHMvbmF2aWdhdGlvbi5zZXJ2aWNlJztcclxuaW1wb3J0IHsgUG9pU2VydmljZSB9IGZyb20gJy4vbW9kZWxzL3BvaS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgVGlja2V0c1NlcnZpY2UgfSBmcm9tICcuL21vZGVscy90aWNrZXQuc2VydmljZSc7XHJcbmltcG9ydCB7IEVxdWlwbWVudFNlcnZpY2UgfSBmcm9tICcuL21vZGVscy9lcXVpcG1lbnQuc2VydmljZSc7XHJcbmltcG9ydCB7IE9iamVjdDNEU2VydmljZSB9IGZyb20gJy4vbW9kZWxzL29iamVjdDNELnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBGZWF0dXJlU2VydmljZSB9IGZyb20gJy4vbW9kZWxzL2ZlYXR1cmUuc2VydmljZSc7XHJcbmltcG9ydCB7IE1lYXN1cmVtZW50U2VydmljZSB9IGZyb20gJy4vbW9kZWxzL21lYXN1cmVtZW50LnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBDb21tZW50U2VydmljZSB9IGZyb20gJy4vbW9kZWxzL2NvbW1lbnQuc2VydmljZSc7XHJcbmltcG9ydCB7IEJhc2VVc2VyU2VydmljZSB9IGZyb20gJy4vdXNlci5zZXJ2aWNlJztcclxuaW1wb3J0IHsgY29weUZpbGVJblMzIH0gZnJvbSAnLi9zMy5zZXJ2aWNlJzsgLy8gc2VlIHMzLnNlcnZpY2UudHM6IGNvcHlGaWxlSW5TMyBtdXN0IE5PVCBzd2FsbG93IGVycm9ycyAobmVlZGVkIHRvIGRldGVjdCBOb1N1Y2hLZXkgYmVsb3cpXHJcbmltcG9ydCB7XHJcbiAgICBjb21wdXRlUmlnaWRUcmFuc2Zvcm0sIGFwcGx5UmlnaWRUcmFuc2Zvcm1Ub1BvaW50LFxyXG4gICAgYXBwbHlSaWdpZFRyYW5zZm9ybVRvWVJvdGF0aW9uRGVnLCBSaWdpZFRyYW5zZm9ybSwgVmVjM1xyXG59IGZyb20gJy4vdXRpbHMvbWF0dGVycG9ydC10cmFuc2Zvcm0udXRpbCc7XHJcbmltcG9ydCB7IE9iamVjdDNELCBGZWF0dXJlLCBNZWFzdXJlbWVudCwgQ29tbWVudCwgQ29tbWVudFR5cGUsIFBvaVR5cGUsIEVxdWlwbWVudCwgU3BNb2R1bGUsIFRpY2tldCB9IGZyb20gJy4uL3R5cGVzLnNlcnZpY2UnO1xyXG5cclxuLyoqIFByb2dyZXNzIHNuYXBzaG90IGVtaXR0ZWQgZHVyaW5nIGNvcHlUYWdzRnJvbVZpc2l0KCksIHNvIHRoZSBVSSBjYW4gc2hvdyBhIGxpdmUgc3RhdHVzLiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIENvcHlQcm9ncmVzcyB7XHJcbiAgICBwaGFzZTogJ2NvbGxlY3RpbmcnIHwgJ3RpY2tldHMnIHwgJ2VxdWlwbWVudHMnIHwgJ3BvaXMnIHwgJ29iamVjdHMzZCcgfCAnZmVhdHVyZXMnIHwgJ21lYXN1cmVtZW50cycgfCAnZG9uZSc7XHJcbiAgICBwcm9jZXNzZWRJblBoYXNlOiBudW1iZXI7XHJcbiAgICB0b3RhbEluUGhhc2U6IG51bWJlcjtcclxuICAgIHByb2Nlc3NlZE92ZXJhbGw6IG51bWJlcjtcclxuICAgIHRvdGFsT3ZlcmFsbDogbnVtYmVyO1xyXG4gICAgcGVyY2VudDogbnVtYmVyO1xyXG4gICAgZXJyb3JDb3VudDogbnVtYmVyO1xyXG59XHJcblxyXG4vKiogQSBzaW5nbGUgbGluZSBpbiB0aGUgY29weSBsb2cg4oCUIGVpdGhlciBhIHN0ZXAgc3RhdHVzICh1cGRhdGVkIGluIHBsYWNlKSBvciBhbiBlcnJvciAoYXBwZW5kZWQgb25jZSkuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgQ29weUxvZ0VudHJ5IHtcclxuICAgIGlkOiBzdHJpbmc7ICAgICAgIC8vIHN0YWJsZSBpZCBmb3Igc3RlcCBsaW5lcyAoc28gdGhleSB1cGRhdGUgaW4gcGxhY2UpLCB1bmlxdWUgZm9yIGVycm9yIGxpbmVzXHJcbiAgICB0eXBlOiAnc3RlcCcgfCAnZXJyb3InO1xyXG4gICAgdGV4dDogc3RyaW5nO1xyXG59XHJcblxyXG4vKiogU2FmZWx5IGV4dHJhY3RzIGEgcmVhZGFibGUgbWVzc2FnZSBmcm9tIGFuIHVua25vd24gY2F0Y2ggdmFsdWUsIGluY2x1ZGluZyBBbXBsaWZ5J3NcclxuICogIEdyYXBoUUwgZXJyb3Igc2hhcGUgKHsgZGF0YSwgZXJyb3JzOiBbeyBlcnJvclR5cGUsIG1lc3NhZ2UgfV0gfSkuICovXHJcbmZ1bmN0aW9uIHRvRXJyb3JNZXNzYWdlKGVycjogdW5rbm93bik6IHN0cmluZyB7XHJcbiAgICBpZiAoZXJyICYmIHR5cGVvZiBlcnIgPT09ICdvYmplY3QnKSB7XHJcbiAgICAgICAgY29uc3QgYW55RXJyID0gZXJyIGFzIGFueTtcclxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShhbnlFcnIuZXJyb3JzKSAmJiBhbnlFcnIuZXJyb3JzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgcmV0dXJuIGFueUVyci5lcnJvcnNcclxuICAgICAgICAgICAgICAgIC5tYXAoKGU6IGFueSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRpdGxlID0gZS5lcnJvclR5cGUgPyBgJHtlLmVycm9yVHlwZX06IGAgOiAnJztcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYCR7dGl0bGV9JHtlLm1lc3NhZ2UgfHwgJ1Vua25vd24gZXJyb3InfWA7XHJcbiAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAgICAgLmpvaW4oJyB8ICcpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoZXJyIGluc3RhbmNlb2YgRXJyb3IpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGVyci5tZXNzYWdlO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIGlmICh0eXBlb2YgZXJyID09PSAnc3RyaW5nJykge1xyXG4gICAgICAgIHJldHVybiBlcnI7XHJcbiAgICB9XHJcbiAgICB0cnkge1xyXG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShlcnIpO1xyXG4gICAgfSBjYXRjaCB7XHJcbiAgICAgICAgcmV0dXJuIFN0cmluZyhlcnIpO1xyXG4gICAgfVxyXG59XHJcblxyXG4vKiogVGhyb3duIHdoZW4gdGhlIHJlZmVyZW5jZWQgUzMgc291cmNlIGZpbGUgZG9lc24ndCBleGlzdCAob3JwaGFuZWQgREIgcmVmZXJlbmNlIOKAlFxyXG4gKiAgZS5nLiB0aGUgZmlsZSB3YXMgZGVsZXRlZCBvciByZW5hbWVkIG9uIFMzIHdpdGhvdXQgdXBkYXRpbmcgdGhlIGRhdGFiYXNlKS5cclxuICogIEtlcHQgZGlzdGluY3QgZnJvbSBvdGhlciBjb3B5IGZhaWx1cmVzIHNvIHRoZSBjYWxsaW5nIGxvb3AgY2FuIGxvZyBhIGNsZWFyLFxyXG4gKiAgc3BlY2lmaWMgbWVzc2FnZSBhbmQgc2tpcCB0aGUgd2hvbGUgaXRlbSBpbnN0ZWFkIG9mIGEgZ2VuZXJpYyBlcnJvci4gKi9cclxuY2xhc3MgTWlzc2luZ1MzRmlsZUVycm9yIGV4dGVuZHMgRXJyb3Ige1xyXG4gICAgY29uc3RydWN0b3IocHVibGljIHJlYWRvbmx5IHNvdXJjZUtleTogc3RyaW5nLCBwdWJsaWMgcmVhZG9ubHkgY29udGV4dExhYmVsOiBzdHJpbmcpIHtcclxuICAgICAgICBzdXBlcihgU291cmNlIGZpbGUgbWlzc2luZyBvbiBTMzogXCIke3NvdXJjZUtleX1cIiAoJHtjb250ZXh0TGFiZWx9KWApO1xyXG4gICAgICAgIHRoaXMubmFtZSA9ICdNaXNzaW5nUzNGaWxlRXJyb3InO1xyXG4gICAgfVxyXG59XHJcblxyXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxyXG5leHBvcnQgY2xhc3MgTWF0dGVycG9ydFRhZ0NvcHlTZXJ2aWNlIHtcclxuXHJcbiAgICAvLyBFbWl0cyBwcm9ncmVzcyB1cGRhdGVzIGR1cmluZyBjb3B5VGFnc0Zyb21WaXNpdCgpOyBudWxsIHdoZW4gaWRsZVxyXG4gICAgcHVibGljIGNvcHlQcm9ncmVzcyQ6IEJlaGF2aW9yU3ViamVjdDxDb3B5UHJvZ3Jlc3MgfCBudWxsPiA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Q29weVByb2dyZXNzIHwgbnVsbD4obnVsbCk7XHJcblxyXG4gICAgLy8gRW1pdHMgdGhlIGFjY3VtdWxhdGVkIGxvZyBsaW5lcyBkdXJpbmcgY29weVRhZ3NGcm9tVmlzaXQoKTsgW10gd2hlbiBpZGxlXHJcbiAgICBwdWJsaWMgY29weUxvZyQ6IEJlaGF2aW9yU3ViamVjdDxDb3B5TG9nRW50cnlbXT4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0PENvcHlMb2dFbnRyeVtdPihbXSk7XHJcblxyXG4gICAgcHJpdmF0ZSBzcE1vZHVsZTogU3BNb2R1bGU7XHJcbiAgICBwcml2YXRlIGxvZzogQ29weUxvZ0VudHJ5W10gPSBbXTtcclxuICAgIHByaXZhdGUgZXJyb3JTZXEgPSAwO1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKFxyXG4gICAgICAgIHByaXZhdGUgbmF2aWdhdGlvblNlcnZpY2U6IE5hdmlnYXRpb25TZXJ2aWNlLFxyXG4gICAgICAgIHByaXZhdGUgdXNlclNlcnZpY2U6IEJhc2VVc2VyU2VydmljZSxcclxuICAgICAgICBwcml2YXRlIHBvaVNlcnZpY2U6IFBvaVNlcnZpY2UsXHJcbiAgICAgICAgcHJpdmF0ZSB0aWNrZXRTZXJ2aWNlOiBUaWNrZXRzU2VydmljZSxcclxuICAgICAgICBwcml2YXRlIGVxdWlwbWVudFNlcnZpY2U6IEVxdWlwbWVudFNlcnZpY2UsXHJcbiAgICAgICAgcHJpdmF0ZSBvYmplY3QzRFNlcnZpY2U6IE9iamVjdDNEU2VydmljZSxcclxuICAgICAgICBwcml2YXRlIGZlYXR1cmVTZXJ2aWNlOiBGZWF0dXJlU2VydmljZSxcclxuICAgICAgICBwcml2YXRlIG1lYXN1cmVtZW50U2VydmljZTogTWVhc3VyZW1lbnRTZXJ2aWNlLFxyXG4gICAgICAgIHByaXZhdGUgY29tbWVudFNlcnZpY2U6IENvbW1lbnRTZXJ2aWNlLFxyXG4gICAgICAgIHByaXZhdGUgdHJhbnNsYXRlOiBUcmFuc2xhdGVTZXJ2aWNlXHJcbiAgICApIHtcclxuICAgICAgICB0aGlzLnNwTW9kdWxlID0gdXNlclNlcnZpY2UuZ2V0U3BNb2R1bGUoKTtcclxuICAgIH1cclxuXHJcbiAgICAvL1xyXG4gICAgLy8gLS0tLS0tLS0tLSBQdWJsaWMgQVBJIC0tLS0tLS0tLS1cclxuICAgIC8vXHJcblxyXG4gICAgYXN5bmMgY29weVRhZ3NGcm9tVmlzaXQoXHJcbiAgICAgICAgc291cmNlU3BhY2VJZDogc3RyaW5nLFxyXG4gICAgICAgIHRhcmdldFNwYWNlSWQ6IHN0cmluZyxcclxuICAgICAgICBsYW5kbWFya1NvdXJjZUE6IFZlYzMsIGxhbmRtYXJrVGFyZ2V0QTogVmVjMyxcclxuICAgICAgICBsYW5kbWFya1NvdXJjZUI6IFZlYzMsIGxhbmRtYXJrVGFyZ2V0QjogVmVjM1xyXG4gICAgKTogUHJvbWlzZTxib29sZWFuPiB7XHJcbiAgICAgICAgbGV0IGVycm9yQ291bnQgPSAwO1xyXG4gICAgICAgIHRoaXMucmVzZXRMb2coKTtcclxuXHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgY29uc29sZS5sb2coYENvcHlpbmcgVGFncyBmcm9tIHNvdXJjZSAke3NvdXJjZVNwYWNlSWR9IHRvIHRhcmdldCAke3RhcmdldFNwYWNlSWR9YCk7XHJcblxyXG4gICAgICAgICAgICB0aGlzLnNldFN0ZXBQcm9ncmVzcygnY29sbGVjdGluZycsICdjb2xsZWN0aW5nJywgMCk7XHJcbiAgICAgICAgICAgIHRoaXMuY29weVByb2dyZXNzJC5uZXh0KHtcclxuICAgICAgICAgICAgICAgIHBoYXNlOiAnY29sbGVjdGluZycsXHJcbiAgICAgICAgICAgICAgICBwcm9jZXNzZWRJblBoYXNlOiAwLCB0b3RhbEluUGhhc2U6IDAsXHJcbiAgICAgICAgICAgICAgICBwcm9jZXNzZWRPdmVyYWxsOiAwLCB0b3RhbE92ZXJhbGw6IDAsXHJcbiAgICAgICAgICAgICAgICBwZXJjZW50OiAwLCBlcnJvckNvdW50OiAwXHJcbiAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgY29uc3QgdGFyZ2V0TWlzc2lvbiA9IHRoaXMudXNlclNlcnZpY2UuY3VycmVudE1pc3Npb24odGFyZ2V0U3BhY2VJZCk7XHJcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldE1pc3Npb25JZCA9IHRhcmdldE1pc3Npb24gPyB0YXJnZXRNaXNzaW9uLmlkIDogbnVsbDtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IHRyYW5zZm9ybTogUmlnaWRUcmFuc2Zvcm0gPSBjb21wdXRlUmlnaWRUcmFuc2Zvcm0oXHJcbiAgICAgICAgICAgICAgICBsYW5kbWFya1NvdXJjZUEsIGxhbmRtYXJrVGFyZ2V0QSxcclxuICAgICAgICAgICAgICAgIGxhbmRtYXJrU291cmNlQiwgbGFuZG1hcmtUYXJnZXRCXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdSaWdpZCB0cmFuc2Zvcm0gY29tcHV0ZWQ6Jywge1xyXG4gICAgICAgICAgICAgICAgcm90YXRpb25ZRGVnOiB0cmFuc2Zvcm0ucm90YXRpb25ZUmFkICogKDE4MCAvIE1hdGguUEkpLFxyXG4gICAgICAgICAgICAgICAgcmVmU291cmNlOiB0cmFuc2Zvcm0ucmVmU291cmNlLFxyXG4gICAgICAgICAgICAgICAgcmVmVGFyZ2V0OiB0cmFuc2Zvcm0ucmVmVGFyZ2V0XHJcbiAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgY29uc3Qgc291cmNlU3dlZXBJZHMgPSBhd2FpdCB0aGlzLm5hdmlnYXRpb25TZXJ2aWNlLmdldEFsbG93ZWRTd2VlcHNJRHNGb3JVc2VySW5TcGFjZShzb3VyY2VTcGFjZUlkKTtcclxuICAgICAgICAgICAgY29uc3QgdGFyZ2V0U3dlZXBJZHMgPSBhd2FpdCB0aGlzLm5hdmlnYXRpb25TZXJ2aWNlLmdldEFsbG93ZWRTd2VlcHNJRHNGb3JVc2VySW5TcGFjZSh0YXJnZXRTcGFjZUlkKTtcclxuXHJcbiAgICAgICAgICAgIHRoaXMuc2V0U3RlcFByb2dyZXNzKCdjb2xsZWN0aW5nJywgJ2NvbGxlY3RpbmcnLCAzMCk7XHJcblxyXG4gICAgICAgICAgICBjb25zdCBbc291cmNlTmF2UG9zaXRpb25zLCB0YXJnZXROYXZQb3NpdGlvbnNdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xyXG4gICAgICAgICAgICAgICAgdGhpcy5idWlsZE5hdmlnYXRpb25Qb3NpdGlvbk1hcChzb3VyY2VTcGFjZUlkLCBzb3VyY2VTd2VlcElkcyksXHJcbiAgICAgICAgICAgICAgICB0aGlzLmJ1aWxkTmF2aWdhdGlvblBvc2l0aW9uTWFwKHRhcmdldFNwYWNlSWQsIHRhcmdldFN3ZWVwSWRzKVxyXG4gICAgICAgICAgICBdKTtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGVsZW1lbnRJZHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcclxuXHJcbiAgICAgICAgICAgIGxldCBzb3VyY2VUaWNrZXRzOiBUaWNrZXRbXSA9IFtdO1xyXG4gICAgICAgICAgICBsZXQgc291cmNlRXF1aXBtZW50czogRXF1aXBtZW50W10gPSBbXTtcclxuICAgICAgICAgICAgbGV0IHRhcmdldFRpY2tldHM6IFRpY2tldFtdID0gW107XHJcbiAgICAgICAgICAgIGxldCB0YXJnZXRFcXVpcG1lbnRzOiBFcXVpcG1lbnRbXSA9IFtdO1xyXG4gICAgICAgICAgICBsZXQgc291cmNlTWVhc3VyZW1lbnRzOiBNZWFzdXJlbWVudFtdID0gW107XHJcbiAgICAgICAgICAgIGxldCB0YXJnZXRNZWFzdXJlbWVudHM6IE1lYXN1cmVtZW50W10gPSBbXTtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLnNwTW9kdWxlID09IFNwTW9kdWxlLklNTU8pIHtcclxuICAgICAgICAgICAgICAgIHNvdXJjZVRpY2tldHMgPSBhd2FpdCB0aGlzLnRpY2tldFNlcnZpY2UuZ2V0VGlja2V0c0J5U3BhY2Uoc291cmNlU3BhY2VJZCk7XHJcbiAgICAgICAgICAgICAgICBzb3VyY2VFcXVpcG1lbnRzID0gYXdhaXQgdGhpcy5lcXVpcG1lbnRTZXJ2aWNlLmdldEVxdWlwbWVudHNGb3JTcGFjZShzb3VyY2VTcGFjZUlkKTtcclxuICAgICAgICAgICAgICAgIHRhcmdldFRpY2tldHMgPSBhd2FpdCB0aGlzLnRpY2tldFNlcnZpY2UuZ2V0VGlja2V0c0J5U3BhY2UodGFyZ2V0U3BhY2VJZCk7XHJcbiAgICAgICAgICAgICAgICB0YXJnZXRFcXVpcG1lbnRzID0gYXdhaXQgdGhpcy5lcXVpcG1lbnRTZXJ2aWNlLmdldEVxdWlwbWVudHNGb3JTcGFjZSh0YXJnZXRTcGFjZUlkKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgdGhpcy5zZXRTdGVwUHJvZ3Jlc3MoJ2NvbGxlY3RpbmcnLCAnY29sbGVjdGluZycsIDU1KTtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IHNvdXJjZU9iamVjdHMzRCA9IGF3YWl0IHRoaXMub2JqZWN0M0RTZXJ2aWNlLmdldE9iamVjdHMzREJ5U3BhY2Uoc291cmNlU3BhY2VJZCk7XHJcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldE9iamVjdHMzRCA9IGF3YWl0IHRoaXMub2JqZWN0M0RTZXJ2aWNlLmdldE9iamVjdHMzREJ5U3BhY2UodGFyZ2V0U3BhY2VJZCk7XHJcblxyXG4gICAgICAgICAgICBjb25zdCBzb3VyY2VGZWF0dXJlcyA9IGF3YWl0IHRoaXMuZmVhdHVyZVNlcnZpY2UuZ2V0RmVhdHVyZXNCeVNwYWNlV2l0aG91dEZpbHRlcmluZyhzb3VyY2VTcGFjZUlkKTtcclxuICAgICAgICAgICAgY29uc3QgdGFyZ2V0RmVhdHVyZXMgPSBhd2FpdCB0aGlzLmZlYXR1cmVTZXJ2aWNlLmdldEZlYXR1cmVzQnlTcGFjZVdpdGhvdXRGaWx0ZXJpbmcodGFyZ2V0U3BhY2VJZCk7XHJcblxyXG4gICAgICAgICAgICB0aGlzLnNldFN0ZXBQcm9ncmVzcygnY29sbGVjdGluZycsICdjb2xsZWN0aW5nJywgNzUpO1xyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMuc3BNb2R1bGUgPT0gU3BNb2R1bGUuSU1NTykge1xyXG4gICAgICAgICAgICAgICAgc291cmNlTWVhc3VyZW1lbnRzID0gYXdhaXQgdGhpcy5tZWFzdXJlbWVudFNlcnZpY2UuZ2V0TWVhc3VyZW1lbnRzRm9yU3BhY2VGb3JVc2VyKHNvdXJjZVNwYWNlSWQpO1xyXG4gICAgICAgICAgICAgICAgdGFyZ2V0TWVhc3VyZW1lbnRzID0gYXdhaXQgdGhpcy5tZWFzdXJlbWVudFNlcnZpY2UuZ2V0TWVhc3VyZW1lbnRzRm9yU3BhY2VGb3JVc2VyKHRhcmdldFNwYWNlSWQpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICB0aGlzLnNldFN0ZXBQcm9ncmVzcygnY29sbGVjdGluZycsICdjb2xsZWN0aW5nJywgOTApO1xyXG5cclxuICAgICAgICAgICAgY29uc3Qgc291cmNlUG9pc0FsbCA9IGF3YWl0IHRoaXMucG9pU2VydmljZS5nZXRQb2lzQnlNYXR0ZXJwb3J0U3dlZXBzKHNvdXJjZVN3ZWVwSWRzKTtcclxuICAgICAgICAgICAgY29uc3QgdGFyZ2V0UG9pc0FsbCA9IGF3YWl0IHRoaXMucG9pU2VydmljZS5nZXRQb2lzQnlNYXR0ZXJwb3J0U3dlZXBzKHRhcmdldFN3ZWVwSWRzKTtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGhhbmRsZWRQb2lUeXBlcyA9IG5ldyBTZXQ8c3RyaW5nPihbXHJcbiAgICAgICAgICAgICAgICBQb2lUeXBlLlRJQ0tFVCwgUG9pVHlwZS5FUVVJUE1FTlQsIFBvaVR5cGUuREFUQSwgUG9pVHlwZS5ERVNLLFxyXG4gICAgICAgICAgICAgICAgUG9pVHlwZS5PQkpFQ1QzRCwgUG9pVHlwZS5NRUFTVVJFXHJcbiAgICAgICAgICAgIF0pO1xyXG4gICAgICAgICAgICBjb25zdCBzb3VyY2VQb2lzID0gc291cmNlUG9pc0FsbC5maWx0ZXIocCA9PiAhaGFuZGxlZFBvaVR5cGVzLmhhcyhwLnR5cGUgYXMgc3RyaW5nKSk7XHJcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldFBvaXMgPSB0YXJnZXRQb2lzQWxsLmZpbHRlcihwID0+ICFoYW5kbGVkUG9pVHlwZXMuaGFzKHAudHlwZSBhcyBzdHJpbmcpKTtcclxuXHJcbiAgICAgICAgICAgIHRoaXMuc2V0U3RlcFByb2dyZXNzKCdjb2xsZWN0aW5nJywgJ2NvbGxlY3RpbmcnLCAxMDApO1xyXG5cclxuICAgICAgICAgICAgY29uc3QgdG90YWxPdmVyYWxsID0gc291cmNlVGlja2V0cy5sZW5ndGggKyBzb3VyY2VFcXVpcG1lbnRzLmxlbmd0aCArIHNvdXJjZVBvaXMubGVuZ3RoXHJcbiAgICAgICAgICAgICAgICArIHNvdXJjZU9iamVjdHMzRC5sZW5ndGggKyBzb3VyY2VGZWF0dXJlcy5sZW5ndGggKyBzb3VyY2VNZWFzdXJlbWVudHMubGVuZ3RoO1xyXG4gICAgICAgICAgICBsZXQgcHJvY2Vzc2VkT3ZlcmFsbCA9IDA7XHJcblxyXG4gICAgICAgICAgICBjb25zdCBlbWl0UHJvZ3Jlc3MgPSAocGhhc2U6IENvcHlQcm9ncmVzc1sncGhhc2UnXSwgcHJvY2Vzc2VkSW5QaGFzZTogbnVtYmVyLCB0b3RhbEluUGhhc2U6IG51bWJlcikgPT4ge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jb3B5UHJvZ3Jlc3MkLm5leHQoe1xyXG4gICAgICAgICAgICAgICAgICAgIHBoYXNlLFxyXG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3NlZEluUGhhc2UsXHJcbiAgICAgICAgICAgICAgICAgICAgdG90YWxJblBoYXNlLFxyXG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3NlZE92ZXJhbGwsXHJcbiAgICAgICAgICAgICAgICAgICAgdG90YWxPdmVyYWxsLFxyXG4gICAgICAgICAgICAgICAgICAgIHBlcmNlbnQ6IHRvdGFsT3ZlcmFsbCA+IDAgPyBNYXRoLnJvdW5kKChwcm9jZXNzZWRPdmVyYWxsIC8gdG90YWxPdmVyYWxsKSAqIDEwMCkgOiAwLFxyXG4gICAgICAgICAgICAgICAgICAgIGVycm9yQ291bnRcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMuc3BNb2R1bGUgPT0gU3BNb2R1bGUuSU1NTykge1xyXG4gICAgICAgICAgICAgICAgLy8gVElDS0VUU1xyXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzb3VyY2VUaWNrZXRzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc291cmNlT2JqID0gc291cmNlVGlja2V0c1tpXTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXhpc3RzSW5UYXJnZXQgPSB0aGlzLm1hdGNoZXNFeGlzdGluZyhzb3VyY2VPYmogYXMgYW55LCB0YXJnZXRUaWNrZXRzIGFzIGFueSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWV4aXN0c0luVGFyZ2V0KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByYXdTb3VyY2UgPSBzb3VyY2VPYmogYXMgYW55O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRpY2tldElucHV0OiBhbnkgPSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGU6IHJhd1NvdXJjZS50aXRsZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcmllbmRseUxhYmVsOiByYXdTb3VyY2UuZnJpZW5kbHlMYWJlbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0dXM6IHJhd1NvdXJjZS5zdGF0dXMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogcmF3U291cmNlLnR5cGUsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3JpdHk6IHJhd1NvdXJjZS5wcmlvcml0eSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogcmF3U291cmNlLmRlc2NyaXB0aW9uLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsOiByYXdTb3VyY2UubGV2ZWwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGE6IHJhd1NvdXJjZS5tZXRhZGF0YSB8fCBudWxsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYWQ6IHJhd1NvdXJjZS5yZWFkIHx8IG51bGwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvamVjdElEOiByYXdTb3VyY2UucHJvamVjdElEIHx8IG51bGwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYmxlbUNvZGU6IHJhd1NvdXJjZS5wcm9ibGVtQ29kZSB8fCBudWxsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyY2hpdmVkRm9yTWlzc2lvbklEOiByYXdTb3VyY2UuYXJjaGl2ZWRGb3JNaXNzaW9uSUQgfHwgbnVsbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGFjZUlEOiB0YXJnZXRTcGFjZUlkLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudElEOiBudWxsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbWFpbklEOiBudWxsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG93bmVyTWlzc2lvbklEOiB0YXJnZXRNaXNzaW9uSWRcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3JlYXRlZE9iaiA9IGF3YWl0IHRoaXMudGlja2V0U2VydmljZS5jcmVhdGVUaWNrZXQodGlja2V0SW5wdXQpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjcmVhdGVkT2JqICYmIGNyZWF0ZWRPYmouaWQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50SWRzW3NvdXJjZU9iai5pZF0gPSBjcmVhdGVkT2JqLmlkO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzb3VyY2VPYmoucG9pcy5pdGVtcyAmJiBzb3VyY2VPYmoucG9pcy5pdGVtcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc291cmNlUG9pID0gc291cmNlT2JqLnBvaXMuaXRlbXNbMF07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGFyZ2V0U3dlZXBJZCA9IHRoaXMuZmluZENsb3Nlc3RUYXJnZXRTd2VlcElkKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VQb2kubWF0dGVycG9ydFN3ZWVwSUQsIHNvdXJjZU5hdlBvc2l0aW9ucywgdGFyZ2V0TmF2UG9zaXRpb25zLCB0cmFuc2Zvcm1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFkanVzdGVkQ29vcmRpbmF0ZSA9IHRoaXMuZ2V0QWRqdXN0ZWRDb29yZGluYXRlcyhzb3VyY2VQb2kuY29vcmRpbmF0ZSwgdHJhbnNmb3JtKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwb2lJbnB1dDogUE9JID0ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZGluYXRlOiBKU09OLnN0cmluZ2lmeShhZGp1c3RlZENvb3JkaW5hdGUpLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBzb3VyY2VQb2kudHlwZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudElEOiBjcmVhdGVkT2JqLmlkLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogc291cmNlUG9pLm1ldGFkYXRhLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXR0ZXJwb3J0U3dlZXBJRDogdGFyZ2V0U3dlZXBJZFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wb2lTZXJ2aWNlLmNyZWF0ZVBPSUZvclNwYWNlSUQocG9pSW5wdXQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoaXRlbUVycm9yKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIGNvcHlpbmcgdGlja2V0IFwiJHtzb3VyY2VPYmo/LnRpdGxlfVwiIChpZDogJHtzb3VyY2VPYmo/LmlkfSk6YCwgaXRlbUVycm9yKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDb3VudCsrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZ0NvcHlJdGVtRXJyb3IoaXRlbUVycm9yLCAnZXJyb3JUaWNrZXQnLCBzb3VyY2VPYmo/LnRpdGxlIHx8IHNvdXJjZU9iaj8uaWQpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc2VkT3ZlcmFsbCsrO1xyXG4gICAgICAgICAgICAgICAgICAgIGVtaXRQcm9ncmVzcygndGlja2V0cycsIGkgKyAxLCBzb3VyY2VUaWNrZXRzLmxlbmd0aCk7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGN0ID0gc291cmNlVGlja2V0cy5sZW5ndGggPiAwID8gTWF0aC5yb3VuZCgoKGkgKyAxKSAvIHNvdXJjZVRpY2tldHMubGVuZ3RoKSAqIDEwMCkgOiAxMDA7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRTdGVwUHJvZ3Jlc3MoJ3RpY2tldHMnLCAndGlja2V0cycsIHBjdCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gRVFVSVBNRU5UUyAodGl0bGUsIFBPSSwgUEhPVE8gYW5kIE5PVEVTL2RvY3VtZW50cyBhbGwgY29waWVkIOKAlCBmaWxlcyBwaHlzaWNhbGx5XHJcbiAgICAgICAgICAgICAgICAvLyBkdXBsaWNhdGVkIGluIFMzIGZpcnN0LCBzbyB0aGUgY29weSBzdGF5cyBpbmRlcGVuZGVudCBmcm9tIHRoZSBzb3VyY2UpXHJcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNvdXJjZUVxdWlwbWVudHMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzb3VyY2VPYmogPSBzb3VyY2VFcXVpcG1lbnRzW2ldO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleGlzdHNJblRhcmdldCA9IHRoaXMubWF0Y2hlc0V4aXN0aW5nKHNvdXJjZU9iaiBhcyBhbnksIHRhcmdldEVxdWlwbWVudHMgYXMgYW55KTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZXhpc3RzSW5UYXJnZXQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJhd1NvdXJjZSA9IHNvdXJjZU9iaiBhcyBhbnk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNvcGllZFBob3RvS2V5OiBzdHJpbmcgfCBudWxsID0gbnVsbDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyYXdTb3VyY2UucGhvdG8pIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3BpZWRQaG90b0tleSA9IGF3YWl0IHRoaXMuY29weVMzS2V5SWZQcmVzZW50KHJhd1NvdXJjZS5waG90bywgYGVxdWlwbWVudCBwaG90byBcIiR7cmF3U291cmNlLnRpdGxlfVwiYCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXF1aXBtZW50SW5wdXQ6IGFueSA9IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZTogcmF3U291cmNlLnRpdGxlLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXR1czogcmF3U291cmNlLnN0YXR1cyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogcmF3U291cmNlLmRlc2NyaXB0aW9uLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyY2hpdmVkRm9yTWlzc2lvbklEOiByYXdTb3VyY2UuYXJjaGl2ZWRGb3JNaXNzaW9uSUQgfHwgbnVsbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGFjZUlEOiB0YXJnZXRTcGFjZUlkLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbWFpbklEOiBudWxsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBob3RvOiBjb3BpZWRQaG90b0tleSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3JlYXRlZE9iajogYW55ID0gYXdhaXQgdGhpcy5lcXVpcG1lbnRTZXJ2aWNlLmNyZWF0ZUVxdWlwbWVudChlcXVpcG1lbnRJbnB1dCwgbnVsbCwgbnVsbCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNyZWF0ZWRPYmogJiYgY3JlYXRlZE9iai5pZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnRJZHNbc291cmNlT2JqLmlkXSA9IGNyZWF0ZWRPYmouaWQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ29weSBub3RlcyAoZG9jdW1lbnRzLCB0ZWNobmljYWwvZmluYW5jaWFsL290aGVyL2NvbnRyYWN0dWFsL2ltYWdlIG5vdGVzKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNyZWF0ZWRPYmogJiYgcmF3U291cmNlLm5vdGVzPy5pdGVtcyAmJiByYXdTb3VyY2Uubm90ZXMuaXRlbXMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgc291cmNlTm90ZSBvZiByYXdTb3VyY2Uubm90ZXMuaXRlbXMpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc291cmNlTm90ZS5hdHRhY2htZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7IC8vIG5vdGhpbmcgdG8gZHVwbGljYXRlIGZvciB0aGlzIG5vdGVcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvcGllZEtleSA9IGF3YWl0IHRoaXMuY29weVMzS2V5SWZQcmVzZW50KHNvdXJjZU5vdGUuYXR0YWNobWVudCwgYGVxdWlwbWVudCBub3RlIGZvciBcIiR7c291cmNlT2JqPy50aXRsZX1cImApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5lcXVpcG1lbnRTZXJ2aWNlLmNyZWF0ZU5vdGVXaXRoRXhpc3RpbmdBdHRhY2htZW50KFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZWRPYmouaWQsIGNvcGllZEtleSwgc291cmNlTm90ZS50eXBlLCB0YXJnZXRNaXNzaW9uSWRcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKG5vdGVFcnJvcikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgRXJyb3IgY29weWluZyBub3RlIGZvciBlcXVpcG1lbnQgXCIke3NvdXJjZU9iaj8udGl0bGV9XCI6YCwgbm90ZUVycm9yKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ291bnQrKztcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9nQ29weUl0ZW1FcnJvcihub3RlRXJyb3IsICdlcnJvckVxdWlwbWVudE5vdGUnLCBzb3VyY2VPYmo/LnRpdGxlIHx8IHNvdXJjZU9iaj8uaWQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzb3VyY2VPYmoucG9pcy5pdGVtcyAmJiBzb3VyY2VPYmoucG9pcy5pdGVtcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc291cmNlUG9pID0gc291cmNlT2JqLnBvaXMuaXRlbXNbMF07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGFyZ2V0U3dlZXBJZCA9IHRoaXMuZmluZENsb3Nlc3RUYXJnZXRTd2VlcElkKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VQb2kubWF0dGVycG9ydFN3ZWVwSUQsIHNvdXJjZU5hdlBvc2l0aW9ucywgdGFyZ2V0TmF2UG9zaXRpb25zLCB0cmFuc2Zvcm1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFkanVzdGVkQ29vcmRpbmF0ZSA9IHRoaXMuZ2V0QWRqdXN0ZWRDb29yZGluYXRlcyhzb3VyY2VQb2kuY29vcmRpbmF0ZSwgdHJhbnNmb3JtKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwb2lJbnB1dDogUE9JID0ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZGluYXRlOiBKU09OLnN0cmluZ2lmeShhZGp1c3RlZENvb3JkaW5hdGUpLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBzb3VyY2VQb2kudHlwZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudElEOiBjcmVhdGVkT2JqLmlkLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogc291cmNlUG9pLm1ldGFkYXRhLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXR0ZXJwb3J0U3dlZXBJRDogdGFyZ2V0U3dlZXBJZFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wb2lTZXJ2aWNlLmNyZWF0ZVBPSUZvclNwYWNlSUQocG9pSW5wdXQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoaXRlbUVycm9yKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIGNvcHlpbmcgZXF1aXBtZW50IFwiJHtzb3VyY2VPYmo/LnRpdGxlfVwiIChpZDogJHtzb3VyY2VPYmo/LmlkfSk6YCwgaXRlbUVycm9yKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDb3VudCsrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZ0NvcHlJdGVtRXJyb3IoaXRlbUVycm9yLCAnZXJyb3JFcXVpcG1lbnQnLCBzb3VyY2VPYmo/LnRpdGxlIHx8IHNvdXJjZU9iaj8uaWQpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc2VkT3ZlcmFsbCsrO1xyXG4gICAgICAgICAgICAgICAgICAgIGVtaXRQcm9ncmVzcygnZXF1aXBtZW50cycsIGkgKyAxLCBzb3VyY2VFcXVpcG1lbnRzLmxlbmd0aCk7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGN0ID0gc291cmNlRXF1aXBtZW50cy5sZW5ndGggPiAwID8gTWF0aC5yb3VuZCgoKGkgKyAxKSAvIHNvdXJjZUVxdWlwbWVudHMubGVuZ3RoKSAqIDEwMCkgOiAxMDA7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRTdGVwUHJvZ3Jlc3MoJ2VxdWlwbWVudHMnLCAnZXF1aXBtZW50cycsIHBjdCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gU2Vjb25kIHBhc3M6IHJlbWFwIHN1YmVxdWlwbWVudHNJRHMgb24gbmV3bHkgY3JlYXRlZCBlcXVpcG1lbnRzIHRvIHBvaW50IHRvXHJcbiAgICAgICAgICAgICAgICAvLyB0aGVpciBjb3BpZWQgY291bnRlcnBhcnRzLiBJRHMgd2l0aCBubyBjb3BpZWQgY291bnRlcnBhcnQgKHNvdXJjZSBlcXVpcG1lbnRcclxuICAgICAgICAgICAgICAgIC8vIHdhc24ndCBjb3BpZWQg4oCUIGUuZy4gaXQgYWxyZWFkeSBleGlzdGVkIGluIHRhcmdldCwgb3Igd2FzIHNraXBwZWQpIGFyZSBkcm9wcGVkXHJcbiAgICAgICAgICAgICAgICAvLyByYXRoZXIgdGhhbiBsZWZ0IGRhbmdsaW5nIG9yIHBvaW50aW5nIGJhY2sgYXQgdGhlIHNvdXJjZSBzcGFjZSdzIGVxdWlwbWVudC5cclxuICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgc291cmNlT2JqIG9mIHNvdXJjZUVxdWlwbWVudHMpIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCByYXdTb3VyY2UgPSBzb3VyY2VPYmogYXMgYW55O1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld0lkID0gZWxlbWVudElkc1tzb3VyY2VPYmouaWRdO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdJZCAmJiByYXdTb3VyY2Uuc3ViZXF1aXBtZW50c0lEcyAmJiByYXdTb3VyY2Uuc3ViZXF1aXBtZW50c0lEcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlbWFwcGVkID0gcmF3U291cmNlLnN1YmVxdWlwbWVudHNJRHNcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5tYXAoKHN1YklkOiBzdHJpbmcpID0+IGVsZW1lbnRJZHNbc3ViSWRdKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmZpbHRlcigoaWQ6IHN0cmluZyB8IHVuZGVmaW5lZCkgPT4gISFpZCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVtYXBwZWQubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmVxdWlwbWVudFNlcnZpY2UudXBkYXRlRXF1aXBtZW50KHsgaWQ6IG5ld0lkLCBzdWJlcXVpcG1lbnRzSURzOiByZW1hcHBlZCB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKHN1YkVxdWlwRXJyb3IpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciByZW1hcHBpbmcgc3ViLWVxdWlwbWVudHMgZm9yIFwiJHtzb3VyY2VPYmo/LnRpdGxlfVwiOmAsIHN1YkVxdWlwRXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ291bnQrKztcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZ0NvcHlJdGVtRXJyb3Ioc3ViRXF1aXBFcnJvciwgJ2Vycm9yRXF1aXBtZW50U3ViRXF1aXAnLCBzb3VyY2VPYmo/LnRpdGxlIHx8IHNvdXJjZU9iaj8uaWQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBQT0lTIChzdGFuZGFsb25lIOKAlCB0eXBlcyBhbHJlYWR5IGhhbmRsZWQgYWJvdmUgYXJlIGV4Y2x1ZGVkKVxyXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNvdXJjZVBvaXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHNvdXJjZVBvaSA9IHNvdXJjZVBvaXNbaV07XHJcblxyXG4gICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBleGlzdHNJblRhcmdldCA9IHRhcmdldFBvaXMuc29tZShcclxuICAgICAgICAgICAgICAgICAgICAgICAgdHAgPT4gdHAuY29vcmRpbmF0ZSA9PT0gc291cmNlUG9pLmNvb3JkaW5hdGUgJiYgdHAudGFnRGVzY3JpcHRpb24gPT09IHNvdXJjZVBvaS50YWdEZXNjcmlwdGlvblxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmICghZXhpc3RzSW5UYXJnZXQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGFyZ2V0U3dlZXBJZCA9IHRoaXMuZmluZENsb3Nlc3RUYXJnZXRTd2VlcElkKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlUG9pLm1hdHRlcnBvcnRTd2VlcElELCBzb3VyY2VOYXZQb3NpdGlvbnMsIHRhcmdldE5hdlBvc2l0aW9ucywgdHJhbnNmb3JtXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFkanVzdGVkQ29vcmRpbmF0ZSA9IHRoaXMuZ2V0QWRqdXN0ZWRDb29yZGluYXRlcyhzb3VyY2VQb2kuY29vcmRpbmF0ZSwgdHJhbnNmb3JtKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlbGVtZW50SUQgPSBzb3VyY2VQb2kuZWxlbWVudElEO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudElEICYmIGVsZW1lbnRJZHNbZWxlbWVudElEXSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudElEID0gZWxlbWVudElkc1tlbGVtZW50SURdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb3BpZWRUYWdJY29uID0gYXdhaXQgdGhpcy5kdXBsaWNhdGVUYWdJY29uKHNvdXJjZVBvaS50YWdJY29uKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29waWVkVGFnSW1hZ2VJRCA9IGF3YWl0IHRoaXMuZHVwbGljYXRlVGFnSW1hZ2VJRChzb3VyY2VQb2kudGFnSW1hZ2VJRCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdQb2k6IFBPSSA9IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkaW5hdGU6IEpTT04uc3RyaW5naWZ5KGFkanVzdGVkQ29vcmRpbmF0ZSksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBzb3VyY2VQb2kudHlwZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnRJRDogZWxlbWVudElELFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFnRGVzY3JpcHRpb246IHNvdXJjZVBvaS50YWdEZXNjcmlwdGlvbixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ0ljb246IGNvcGllZFRhZ0ljb24sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YWdJbWFnZUlEOiBjb3BpZWRUYWdJbWFnZUlELFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlydHVhbDogc291cmNlUG9pLnZpcnR1YWwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB4Um90YXRpb246IHNvdXJjZVBvaS54Um90YXRpb24sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB5Um90YXRpb246IHNvdXJjZVBvaS55Um90YXRpb24sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogc291cmNlUG9pLm1ldGFkYXRhLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0dGVycG9ydFN3ZWVwSUQ6IHRhcmdldFN3ZWVwSWRcclxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wb2lTZXJ2aWNlLmNyZWF0ZVBPSUZvclNwYWNlSUQobmV3UG9pKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChpdGVtRXJyb3IpIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBjb3B5aW5nIFBPSSAoc3dlZXA6ICR7c291cmNlUG9pPy5tYXR0ZXJwb3J0U3dlZXBJRH0pOmAsIGl0ZW1FcnJvcik7XHJcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JDb3VudCsrO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMubG9nQ29weUl0ZW1FcnJvcihpdGVtRXJyb3IsICdlcnJvclBvaScsIHNvdXJjZVBvaT8ubWF0dGVycG9ydFN3ZWVwSUQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIHByb2Nlc3NlZE92ZXJhbGwrKztcclxuICAgICAgICAgICAgICAgIGVtaXRQcm9ncmVzcygncG9pcycsIGkgKyAxLCBzb3VyY2VQb2lzLmxlbmd0aCk7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBwY3QgPSBzb3VyY2VQb2lzLmxlbmd0aCA+IDAgPyBNYXRoLnJvdW5kKCgoaSArIDEpIC8gc291cmNlUG9pcy5sZW5ndGgpICogMTAwKSA6IDEwMDtcclxuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RlcFByb2dyZXNzKCdwb2lzJywgJ3BvaXMnLCBwY3QpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBPQkpFQ1RTIDNEICh0aGUgM0QgbW9kZWwgZmlsZSBpdHNlbGYg4oCUIGBwYXRoYCDigJQgaXMgcGh5c2ljYWxseSBkdXBsaWNhdGVkIGluIFMzKVxyXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNvdXJjZU9iamVjdHMzRC5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgY29uc3Qgc291cmNlT2JqID0gc291cmNlT2JqZWN0czNEW2ldO1xyXG5cclxuICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZXhpc3RzSW5UYXJnZXQgPSB0YXJnZXRPYmplY3RzM0Quc29tZSh0YXJnZXRPYmogPT4gdGFyZ2V0T2JqLm5hbWUgPT09IHNvdXJjZU9iai5uYW1lKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFleGlzdHNJblRhcmdldCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByYXdTb3VyY2UgPSBzb3VyY2VPYmogYXMgYW55O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNvcGllZFBhdGggPSByYXdTb3VyY2UucGF0aDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJhd1NvdXJjZS5wYXRoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3BpZWRQYXRoID0gYXdhaXQgdGhpcy5jb3B5UzNLZXlJZlByZXNlbnQocmF3U291cmNlLnBhdGgsIGAzRCBvYmplY3QgXCIke3Jhd1NvdXJjZS5uYW1lfVwiYCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgKiBTdHJpY3QgcGFyc2VyIHRvIGVuc3VyZSBbZmxvYXQsIGZsb2F0LCBmbG9hdF0gZm9ybWF0IGZvciBHcmFwaFFMLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgKiBGb3JjZXMgbnVtYmVycywgaGFuZGxlcyBwb3RlbnRpYWwgRHluYW1vREIgb2JqZWN0IHN0cnVjdHVyZXMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAqIGFuZCBlbnN1cmVzIHdlIG5ldmVyIHNlbmQgWzAsMCwwXSBmb3Igc2NhbGUuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0b0Zsb2F0QXJyYXkgPSAodmFsOiBhbnksIGRlZmF1bHRWYWw6IG51bWJlcltdID0gWzAsIDAsIDBdKTogbnVtYmVyW10gPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGFycmF5OiBudW1iZXJbXSA9IFtdO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbCkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiBEQiBmb3JtYXQgWyB7TjogXCIxXCJ9LCAuLi4gXVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWwubGVuZ3RoID4gMCAmJiB0eXBlb2YgdmFsWzBdID09PSAnb2JqZWN0JyAmJiAnTicgaW4gdmFsWzBdKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5ID0gdmFsLm1hcChpdGVtID0+IHBhcnNlRmxvYXQoaXRlbS5OKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIGFscmVhZHkgc3RhbmRhcmQgYXJyYXkgWzEsIDEsIDFdXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5ID0gdmFsLm1hcChpdGVtID0+IHBhcnNlRmxvYXQoaXRlbSkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIG9iamVjdCB7eCwgeSwgen1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHZhbCAmJiB0eXBlb2YgdmFsID09PSAnb2JqZWN0Jykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5ID0gW3BhcnNlRmxvYXQodmFsLngpLCBwYXJzZUZsb2F0KHZhbC55KSwgcGFyc2VGbG9hdCh2YWwueildO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGVmYXVsdFZhbDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBFbnN1cmUgd2UgcmV0dXJuIHZhbGlkIG51bWJlcnNcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhcnJheS5tYXAobiA9PiBpc05hTihuKSA/IDAgOiBuKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9iamVjdDNESW5wdXQ6IGFueSA9IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGg6IGNvcGllZFBhdGgsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiByYXdTb3VyY2UubmFtZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiByYXdTb3VyY2UuZGVzY3JpcHRpb24gfHwgXCJcIixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZXdGcnVzdHVtOiAhIXJhd1NvdXJjZS52aWV3RnJ1c3R1bSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwYWNlSUQ6IHRhcmdldFNwYWNlSWQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbjogdG9GbG9hdEFycmF5KHJhd1NvdXJjZS5wb3NpdGlvbiwgWzAsIDAsIDBdKSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdGF0aW9uOiB0b0Zsb2F0QXJyYXkocmF3U291cmNlLnJvdGF0aW9uLCBbMCwgMCwgMF0pLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRW5mb3JjZSBzY2FsZSB0byBiZSBhdCBsZWFzdCAxLjAgaWYgaXQncyBpbnZhbGlkXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZTogdG9GbG9hdEFycmF5KHJhd1NvdXJjZS5zY2FsZSwgWzEsIDEsIDFdKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRGVidWdnaW5nOiBJbnNwZWN0IHRoZSBleGFjdCBvYmplY3Qgc2VudCB0byB0aGUgbXV0YXRpb25cclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coYFtERUJVR10gU2VuZGluZyBPYmplY3QzRCBcIiR7cmF3U291cmNlLm5hbWV9XCIgdG8gQVBJOmAsIEpTT04uc3RyaW5naWZ5KG9iamVjdDNESW5wdXQpKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNyZWF0ZWRPYmogPSBhd2FpdCB0aGlzLm9iamVjdDNEU2VydmljZS5jcmVhdGUob2JqZWN0M0RJbnB1dCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3JlYXRlZE9iaiAmJiBjcmVhdGVkT2JqLmlkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50SWRzW3NvdXJjZU9iai5pZF0gPSBjcmVhdGVkT2JqLmlkO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc291cmNlT2JqLnBvaXM/Lml0ZW1zICYmIHNvdXJjZU9iai5wb2lzLml0ZW1zLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNvdXJjZVBvaSA9IHNvdXJjZU9iai5wb2lzLml0ZW1zWzBdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGFyZ2V0U3dlZXBJZCA9IHRoaXMuZmluZENsb3Nlc3RUYXJnZXRTd2VlcElkKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZVBvaS5tYXR0ZXJwb3J0U3dlZXBJRCwgc291cmNlTmF2UG9zaXRpb25zLCB0YXJnZXROYXZQb3NpdGlvbnMsIHRyYW5zZm9ybVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFkanVzdGVkQ29vcmRpbmF0ZSA9IHRoaXMuZ2V0QWRqdXN0ZWRDb29yZGluYXRlcyhzb3VyY2VQb2kuY29vcmRpbmF0ZSwgdHJhbnNmb3JtKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBvaUlucHV0OiBQT0kgPSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRpbmF0ZTogSlNPTi5zdHJpbmdpZnkoYWRqdXN0ZWRDb29yZGluYXRlKSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBzb3VyY2VQb2kudHlwZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50SUQ6IGNyZWF0ZWRPYmouaWQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGE6IHNvdXJjZVBvaS5tZXRhZGF0YSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXR0ZXJwb3J0U3dlZXBJRDogdGFyZ2V0U3dlZXBJZFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucG9pU2VydmljZS5jcmVhdGVQT0lGb3JTcGFjZUlEKHBvaUlucHV0KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGl0ZW1FcnJvcikge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIGNvcHlpbmcgb2JqZWN0M0QgXCIke3NvdXJjZU9iaj8ubmFtZX1cIjpgLCBpdGVtRXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgIGVycm9yQ291bnQrKztcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZ0NvcHlJdGVtRXJyb3IoaXRlbUVycm9yLCAnZXJyb3JPYmplY3QzZCcsIHNvdXJjZU9iaj8ubmFtZSB8fCBzb3VyY2VPYmo/LmlkKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBwcm9jZXNzZWRPdmVyYWxsKys7XHJcbiAgICAgICAgICAgICAgICBlbWl0UHJvZ3Jlc3MoJ29iamVjdHMzZCcsIGkgKyAxLCBzb3VyY2VPYmplY3RzM0QubGVuZ3RoKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHBjdCA9IHNvdXJjZU9iamVjdHMzRC5sZW5ndGggPiAwID8gTWF0aC5yb3VuZCgoKGkgKyAxKSAvIHNvdXJjZU9iamVjdHMzRC5sZW5ndGgpICogMTAwKSA6IDEwMDtcclxuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RlcFByb2dyZXNzKCdvYmplY3RzM2QnLCAnb2JqZWN0czNkJywgcGN0KTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gRkVBVFVSRVMgKHRpdGxlLCBQT0ksIGFuZCBhdHRhY2hlZCBjb21tZW50cyDigJQgaW1hZ2VzL3ZpZGVvcy9kb2NzL2xpbmtzIOKAlCBhbGwgY29waWVkLFxyXG4gICAgICAgICAgICAvLyBlYWNoIGZpbGUgcGh5c2ljYWxseSBkdXBsaWNhdGVkIGluIFMzIGZpcnN0KVxyXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNvdXJjZUZlYXR1cmVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBzb3VyY2VPYmogPSBzb3VyY2VGZWF0dXJlc1tpXTtcclxuXHJcbiAgICAgICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4aXN0c0luVGFyZ2V0ID0gdGhpcy5tYXRjaGVzRXhpc3Rpbmcoc291cmNlT2JqIGFzIGFueSwgdGFyZ2V0RmVhdHVyZXMgYXMgYW55KTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFleGlzdHNJblRhcmdldCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByYXdTb3VyY2UgPSBzb3VyY2VPYmogYXMgYW55O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmVhdHVyZUlucHV0OiBhbnkgPSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZTogcmF3U291cmNlLnRpdGxlLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvcnREZXNjcmlwdGlvbjogcmF3U291cmNlLnNob3J0RGVzY3JpcHRpb24sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbDogcmF3U291cmNlLmxldmVsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogcmF3U291cmNlLnR5cGUsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmNoaXZlZEZvck1pc3Npb25JRDogcmF3U291cmNlLmFyY2hpdmVkRm9yTWlzc2lvbklEIHx8IG51bGwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpcGVQcm9kdWN0SUQ6IHJhd1NvdXJjZS5zdHJpcGVQcm9kdWN0SUQgfHwgbnVsbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmlwZVByaWNlSUQ6IHJhd1NvdXJjZS5zdHJpcGVQcmljZUlEIHx8IG51bGwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBib29raW5nUHJpY2VNZXRhZGF0YTogcmF3U291cmNlLmJvb2tpbmdQcmljZU1ldGFkYXRhIHx8IG51bGwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhbGU6IHJhd1NvdXJjZS5sb2NhbGUgfHwgbnVsbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc2h0YWdzOiByYXdTb3VyY2UuaGFzaHRhZ3MgfHwgbnVsbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiByYXdTb3VyY2UuZGVzY3JpcHRpb24gfHwgbnVsbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbWFpbklEOiBudWxsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BhY2VJRDogdGFyZ2V0U3BhY2VJZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG93bmVyTWlzc2lvbklEOiB0YXJnZXRNaXNzaW9uSWRcclxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNyZWF0ZWRPYmogPSBhd2FpdCB0aGlzLmZlYXR1cmVTZXJ2aWNlLmNyZWF0ZUZlYXR1cmUoZmVhdHVyZUlucHV0KTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjcmVhdGVkT2JqICYmIGNyZWF0ZWRPYmouaWQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnRJZHNbc291cmNlT2JqLmlkXSA9IGNyZWF0ZWRPYmouaWQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjcmVhdGVkT2JqICYmIHNvdXJjZU9iai5jb21tZW50cz8uaXRlbXMgJiYgc291cmNlT2JqLmNvbW1lbnRzLml0ZW1zLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgc291cmNlQ29tbWVudCBvZiBzb3VyY2VPYmouY29tbWVudHMuaXRlbXMpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByYXdDb21tZW50ID0gc291cmNlQ29tbWVudCBhcyBhbnk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgY29waWVkQW5uZXhlOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJhd0NvbW1lbnQuYW5uZXhlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3BpZWRBbm5leGUgPSBhd2FpdCB0aGlzLmNvcHlTM0tleUlmUHJlc2VudChyYXdDb21tZW50LmFubmV4ZSwgYGZlYXR1cmUgYXR0YWNobWVudCBcIiR7cmF3Q29tbWVudC50aXRsZX1cImApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb21tZW50SW5wdXQ6IGFueSA9IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlOiByYXdDb21tZW50LnRpdGxlLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogcmF3Q29tbWVudC50eXBlLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5uZXhlOiBjb3BpZWRBbm5leGUsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHRlcm5hbExpbms6IHJhd0NvbW1lbnQuZXh0ZXJuYWxMaW5rIHx8IG51bGwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1lbnNpb25zOiByYXdDb21tZW50LmRpbWVuc2lvbnMgfHwgbnVsbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4OiByYXdDb21tZW50LmluZGV4LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvd25JblRhZzogcmF3Q29tbWVudC5zaG93bkluVGFnLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNDb3ZlckltYWdlOiByYXdDb21tZW50LmlzQ292ZXJJbWFnZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVJRDogY3JlYXRlZE9iai5pZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwYWNlSUQ6IHRhcmdldFNwYWNlSWQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvd25lcklEOiB0YXJnZXRNaXNzaW9uSWRcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuY29tbWVudFNlcnZpY2UuY3JlYXRlQ29tbWVudChjb21tZW50SW5wdXQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGF0dGFjaG1lbnRFcnJvcikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBjb3B5aW5nIGF0dGFjaG1lbnQgXCIke3NvdXJjZUNvbW1lbnQ/LnRpdGxlfVwiIGZvciBmZWF0dXJlIFwiJHtzb3VyY2VPYmo/LnRpdGxlfVwiOmAsIGF0dGFjaG1lbnRFcnJvcik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ291bnQrKztcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2dDb3B5SXRlbUVycm9yKGF0dGFjaG1lbnRFcnJvciwgJ2Vycm9yRmVhdHVyZUF0dGFjaG1lbnQnLCBzb3VyY2VDb21tZW50Py50aXRsZSB8fCBzb3VyY2VDb21tZW50Py5pZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc291cmNlT2JqLnBvaXM/Lml0ZW1zICYmIHNvdXJjZU9iai5wb2lzLml0ZW1zLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNvdXJjZVBvaSA9IHNvdXJjZU9iai5wb2lzLml0ZW1zWzBdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGFyZ2V0U3dlZXBJZCA9IHRoaXMuZmluZENsb3Nlc3RUYXJnZXRTd2VlcElkKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZVBvaS5tYXR0ZXJwb3J0U3dlZXBJRCwgc291cmNlTmF2UG9zaXRpb25zLCB0YXJnZXROYXZQb3NpdGlvbnMsIHRyYW5zZm9ybVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFkanVzdGVkQ29vcmRpbmF0ZSA9IHRoaXMuZ2V0QWRqdXN0ZWRDb29yZGluYXRlcyhzb3VyY2VQb2kuY29vcmRpbmF0ZSwgdHJhbnNmb3JtKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBvaUlucHV0OiBQT0kgPSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRpbmF0ZTogSlNPTi5zdHJpbmdpZnkoYWRqdXN0ZWRDb29yZGluYXRlKSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBzb3VyY2VQb2kudHlwZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50SUQ6IGNyZWF0ZWRPYmouaWQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGE6IHNvdXJjZVBvaS5tZXRhZGF0YSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXR0ZXJwb3J0U3dlZXBJRDogdGFyZ2V0U3dlZXBJZFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucG9pU2VydmljZS5jcmVhdGVQT0lGb3JTcGFjZUlEKHBvaUlucHV0KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGl0ZW1FcnJvcikge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIGNvcHlpbmcgZmVhdHVyZSBcIiR7c291cmNlT2JqPy50aXRsZX1cIiAoaWQ6ICR7c291cmNlT2JqPy5pZH0pOmAsIGl0ZW1FcnJvcik7XHJcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JDb3VudCsrO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMubG9nQ29weUl0ZW1FcnJvcihpdGVtRXJyb3IsICdlcnJvckZlYXR1cmUnLCBzb3VyY2VPYmo/LnRpdGxlIHx8IHNvdXJjZU9iaj8uaWQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIHByb2Nlc3NlZE92ZXJhbGwrKztcclxuICAgICAgICAgICAgICAgIGVtaXRQcm9ncmVzcygnZmVhdHVyZXMnLCBpICsgMSwgc291cmNlRmVhdHVyZXMubGVuZ3RoKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHBjdCA9IHNvdXJjZUZlYXR1cmVzLmxlbmd0aCA+IDAgPyBNYXRoLnJvdW5kKCgoaSArIDEpIC8gc291cmNlRmVhdHVyZXMubGVuZ3RoKSAqIDEwMCkgOiAxMDA7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnNldFN0ZXBQcm9ncmVzcygnZmVhdHVyZXMnLCAnZmVhdHVyZXMnLCBwY3QpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBNRUFTVVJFTUVOVFMgKElNTU8gb25seSDigJQgYSBDb21tZW50ICsgYSBwb3NpdGlvbmFsLW9ubHkgUE9JLCBubyByb3RhdGlvbjtcclxuICAgICAgICAgICAgLy8gdGhlIHNjcmVlbnNob3QgZmlsZSBpcyBwaHlzaWNhbGx5IGR1cGxpY2F0ZWQgaW4gUzMgZmlyc3QpXHJcbiAgICAgICAgICAgIGlmICh0aGlzLnNwTW9kdWxlID09IFNwTW9kdWxlLklNTU8pIHtcclxuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc291cmNlTWVhc3VyZW1lbnRzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc291cmNlTWVhc3VyZW1lbnQgPSBzb3VyY2VNZWFzdXJlbWVudHNbaV07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4aXN0c0luVGFyZ2V0ID0gdGFyZ2V0TWVhc3VyZW1lbnRzLnNvbWUoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bSA9PiB0bS5jb21tZW50LnRpdGxlID09PSBzb3VyY2VNZWFzdXJlbWVudC5jb21tZW50LnRpdGxlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWV4aXN0c0luVGFyZ2V0KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByYXdDb21tZW50ID0gc291cmNlTWVhc3VyZW1lbnQuY29tbWVudCBhcyBhbnk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNvcGllZEFubmV4ZTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmF3Q29tbWVudC5hbm5leGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3BpZWRBbm5leGUgPSBhd2FpdCB0aGlzLmNvcHlTM0tleUlmUHJlc2VudChyYXdDb21tZW50LmFubmV4ZSwgYG1lYXN1cmVtZW50IHNjcmVlbnNob3QgXCIke3Jhd0NvbW1lbnQudGl0bGV9XCJgKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb21tZW50SW5wdXQ6IGFueSA9IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZTogcmF3Q29tbWVudC50aXRsZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBDb21tZW50VHlwZS5NRUFTVVJFLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbWVuc2lvbnM6IHJhd0NvbW1lbnQuZGltZW5zaW9ucyB8fCBudWxsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFubmV4ZTogY29waWVkQW5uZXhlLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwYWNlSUQ6IHRhcmdldFNwYWNlSWQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNyZWF0ZWRDb21tZW50OiBDb21tZW50ID0gYXdhaXQgdGhpcy5jb21tZW50U2VydmljZS5jcmVhdGVDb21tZW50KGNvbW1lbnRJbnB1dCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNyZWF0ZWRDb21tZW50ICYmIHNvdXJjZU1lYXN1cmVtZW50LnBvaSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRhcmdldFN3ZWVwSWQgPSB0aGlzLmZpbmRDbG9zZXN0VGFyZ2V0U3dlZXBJZChcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlTWVhc3VyZW1lbnQucG9pLm1hdHRlcnBvcnRTd2VlcElELCBzb3VyY2VOYXZQb3NpdGlvbnMsIHRhcmdldE5hdlBvc2l0aW9ucywgdHJhbnNmb3JtXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhZGp1c3RlZFBvc2l0aW9uID0gdGhpcy5nZXRBZGp1c3RlZFBvc2l0aW9uT25seShzb3VyY2VNZWFzdXJlbWVudC5wb2kuY29vcmRpbmF0ZSwgdHJhbnNmb3JtKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwb2lJbnB1dDogUE9JID0ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZGluYXRlOiBKU09OLnN0cmluZ2lmeShhZGp1c3RlZFBvc2l0aW9uKSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogUG9pVHlwZS5NRUFTVVJFLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50SUQ6IChjcmVhdGVkQ29tbWVudCBhcyBhbnkpLmlkLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogc291cmNlTWVhc3VyZW1lbnQucG9pLm1ldGFkYXRhLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXR0ZXJwb3J0U3dlZXBJRDogdGFyZ2V0U3dlZXBJZFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wb2lTZXJ2aWNlLmNyZWF0ZVBPSUZvclNwYWNlSUQocG9pSW5wdXQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoaXRlbUVycm9yKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIGNvcHlpbmcgbWVhc3VyZW1lbnQgXCIke3NvdXJjZU1lYXN1cmVtZW50Py5jb21tZW50Py50aXRsZX1cIjpgLCBpdGVtRXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNvdW50Kys7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9nQ29weUl0ZW1FcnJvcihpdGVtRXJyb3IsICdlcnJvck1lYXN1cmVtZW50Jywgc291cmNlTWVhc3VyZW1lbnQ/LmNvbW1lbnQ/LnRpdGxlIHx8IHNvdXJjZU1lYXN1cmVtZW50Py5pZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzZWRPdmVyYWxsKys7XHJcbiAgICAgICAgICAgICAgICAgICAgZW1pdFByb2dyZXNzKCdtZWFzdXJlbWVudHMnLCBpICsgMSwgc291cmNlTWVhc3VyZW1lbnRzLmxlbmd0aCk7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGN0ID0gc291cmNlTWVhc3VyZW1lbnRzLmxlbmd0aCA+IDAgPyBNYXRoLnJvdW5kKCgoaSArIDEpIC8gc291cmNlTWVhc3VyZW1lbnRzLmxlbmd0aCkgKiAxMDApIDogMTAwO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RlcFByb2dyZXNzKCdtZWFzdXJlbWVudHMnLCAnbWVhc3VyZW1lbnRzJywgcGN0KTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgdGhpcy5jb3B5UHJvZ3Jlc3MkLm5leHQoe1xyXG4gICAgICAgICAgICAgICAgcGhhc2U6ICdkb25lJyxcclxuICAgICAgICAgICAgICAgIHByb2Nlc3NlZEluUGhhc2U6IDAsIHRvdGFsSW5QaGFzZTogMCxcclxuICAgICAgICAgICAgICAgIHByb2Nlc3NlZE92ZXJhbGwsIHRvdGFsT3ZlcmFsbCxcclxuICAgICAgICAgICAgICAgIHBlcmNlbnQ6IDEwMCwgZXJyb3JDb3VudFxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgdGhpcy5zZXRTdGVwTG9nKCdkb25lJywgZXJyb3JDb3VudCA+IDBcclxuICAgICAgICAgICAgICAgID8gdGhpcy50cmFuc2xhdGUuaW5zdGFudCgnbWF0dGVycG9ydENvcHkuZG9uZVdpdGhFcnJvcnMnLCB7IGNvdW50OiBlcnJvckNvdW50IH0pXHJcbiAgICAgICAgICAgICAgICA6IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoJ21hdHRlcnBvcnRDb3B5LmRvbmUnKSk7XHJcblxyXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBjb3B5aW5nIFBPSXM6JywgZXJyb3IpO1xyXG4gICAgICAgICAgICB0aGlzLmFwcGVuZEVycm9yTG9nKHRoaXMudHJhbnNsYXRlLmluc3RhbnQoJ21hdHRlcnBvcnRDb3B5LmVycm9yR2VuZXJhbCcsIHsgZXJyb3I6IHRvRXJyb3JNZXNzYWdlKGVycm9yKSB9KSk7XHJcbiAgICAgICAgICAgIHRoaXMuY29weVByb2dyZXNzJC5uZXh0KG51bGwpO1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vXHJcbiAgICAvLyAtLS0tLS0tLS0tIFByb2dyZXNzIC8gbG9nIGhlbHBlcnMgLS0tLS0tLS0tLVxyXG4gICAgLy9cclxuXHJcbiAgICAvKiogQWRkcyBvciB1cGRhdGVzIGEgc3RlcCBsaW5lIChpZGVudGlmaWVkIGJ5IHN0ZXBJZCkgd2l0aCBuZXcgdGV4dCwgdGhlbiByZXB1Ymxpc2hlcyB0aGUgbG9nLiAqL1xyXG4gICAgcHJpdmF0ZSBzZXRTdGVwTG9nKHN0ZXBJZDogc3RyaW5nLCB0ZXh0OiBzdHJpbmcpIHtcclxuICAgICAgICBjb25zdCBleGlzdGluZ0luZGV4ID0gdGhpcy5sb2cuZmluZEluZGV4KGUgPT4gZS50eXBlID09PSAnc3RlcCcgJiYgZS5pZCA9PT0gc3RlcElkKTtcclxuICAgICAgICBjb25zdCBlbnRyeTogQ29weUxvZ0VudHJ5ID0geyBpZDogc3RlcElkLCB0eXBlOiAnc3RlcCcsIHRleHQgfTtcclxuICAgICAgICBpZiAoZXhpc3RpbmdJbmRleCA+PSAwKSB7XHJcbiAgICAgICAgICAgIHRoaXMubG9nW2V4aXN0aW5nSW5kZXhdID0gZW50cnk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGhpcy5sb2cucHVzaChlbnRyeSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuY29weUxvZyQubmV4dChbLi4udGhpcy5sb2ddKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogQXBwZW5kcyBhIG5ldywgcGVybWFuZW50IGxvZyBsaW5lIChuZXZlciBvdmVyd3JpdHRlbiksIHRoZW4gcmVwdWJsaXNoZXMgdGhlIGxvZy4gKi9cclxuICAgIHByaXZhdGUgYXBwZW5kRXJyb3JMb2codGV4dDogc3RyaW5nKSB7XHJcbiAgICAgICAgdGhpcy5lcnJvclNlcSsrO1xyXG4gICAgICAgIHRoaXMubG9nLnB1c2goeyBpZDogYGVycm9yLSR7dGhpcy5lcnJvclNlcX1gLCB0eXBlOiAnZXJyb3InLCB0ZXh0IH0pO1xyXG4gICAgICAgIHRoaXMuY29weUxvZyQubmV4dChbLi4udGhpcy5sb2ddKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogUmVzZXRzIHRoZSBsb2cgZm9yIGEgbmV3IHJ1bi4gKi9cclxuICAgIHByaXZhdGUgcmVzZXRMb2coKSB7XHJcbiAgICAgICAgdGhpcy5sb2cgPSBbXTtcclxuICAgICAgICB0aGlzLmVycm9yU2VxID0gMDtcclxuICAgICAgICB0aGlzLmNvcHlMb2ckLm5leHQoW10pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBCdWlsZHMgYW5kIHNldHMgYSBzdGVwJ3MgbG9nIGxpbmUgYXMgXCI8dHJhbnNsYXRlZCBsYWJlbD46IDxwZXJjZW50PiVcIiwgbm8gc3RlcCBudW1iZXJpbmcuICovXHJcbiAgICBwcml2YXRlIHNldFN0ZXBQcm9ncmVzcyhzdGVwSWQ6IHN0cmluZywgdHJhbnNsYXRpb25LZXk6IHN0cmluZywgcGVyY2VudDogbnVtYmVyKSB7XHJcbiAgICAgICAgY29uc3QgbGFiZWwgPSB0aGlzLnRyYW5zbGF0ZS5pbnN0YW50KGBtYXR0ZXJwb3J0Q29weS4ke3RyYW5zbGF0aW9uS2V5fWApO1xyXG4gICAgICAgIHRoaXMuc2V0U3RlcExvZyhzdGVwSWQsIGAke2xhYmVsfTogJHtwZXJjZW50fSVgKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogTG9ncyBhIHRyYW5zbGF0ZWQsIHBhcmFtZXRlcml6ZWQgZXJyb3IgbGluZSBmb3IgYSBzaW5nbGUgZmFpbGVkIGl0ZW0uICovXHJcbiAgICBwcml2YXRlIGxvZ0l0ZW1FcnJvcih0cmFuc2xhdGlvbktleTogc3RyaW5nLCBwYXJhbXM6IFJlY29yZDxzdHJpbmcsIGFueT4pIHtcclxuICAgICAgICBjb25zdCB0ZXh0ID0gdGhpcy50cmFuc2xhdGUuaW5zdGFudChgbWF0dGVycG9ydENvcHkuJHt0cmFuc2xhdGlvbktleX1gLCBwYXJhbXMpO1xyXG4gICAgICAgIHRoaXMuYXBwZW5kRXJyb3JMb2codGV4dCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIExvZ3MgYW4gaXRlbS1sZXZlbCBlcnJvciwgdXNpbmcgYSBzcGVjaWZpYyBcIm1pc3NpbmcgZmlsZSAvIG9ycGhhbmVkIHJlZmVyZW5jZVwiXHJcbiAgICAgKiAgdHJhbnNsYXRpb24ga2V5IHdoZW4gdGhlIGNhdXNlIGlzIGEgTWlzc2luZ1MzRmlsZUVycm9yLCBhbmQgdGhlIGdlbmVyaWMgcGVyLXR5cGVcclxuICAgICAqICBrZXkgb3RoZXJ3aXNlLiBLZWVwcyB0aGUgY29weSBsb2cgcmVhZGFibGU6IGEgbWlzc2luZyBmaWxlIGlzIG5vdCBhIGJ1ZyB0b1xyXG4gICAgICogIGludmVzdGlnYXRlIHRoZSBzYW1lIHdheSBhIG5ldHdvcmsvcGVybWlzc2lvbiBlcnJvciBpcy4gKi9cclxuICAgIHByaXZhdGUgbG9nQ29weUl0ZW1FcnJvcihlcnJvcjogdW5rbm93biwgZ2VuZXJpY0tleTogc3RyaW5nLCBpdGVtTGFiZWw6IHN0cmluZykge1xyXG4gICAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIE1pc3NpbmdTM0ZpbGVFcnJvcikge1xyXG4gICAgICAgICAgICB0aGlzLmxvZ0l0ZW1FcnJvcignZXJyb3JNaXNzaW5nUzNGaWxlU2tpcHBlZCcsIHtcclxuICAgICAgICAgICAgICAgIG5hbWU6IGl0ZW1MYWJlbCxcclxuICAgICAgICAgICAgICAgIGZpbGU6IGVycm9yLnNvdXJjZUtleVxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aGlzLmxvZ0l0ZW1FcnJvcihnZW5lcmljS2V5LCB7IG5hbWU6IGl0ZW1MYWJlbCwgZXJyb3I6IHRvRXJyb3JNZXNzYWdlKGVycm9yKSB9KTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy9cclxuICAgIC8vIC0tLS0tLS0tLS0gRHVwbGljYXRlIGRldGVjdGlvbiAtLS0tLS0tLS0tXHJcbiAgICAvL1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSGV1cmlzdGljIGR1cGxpY2F0ZS1kZXRlY3Rpb246IGNvbXBhcmVzIHRpdGxlIEFORCBkZXNjcmlwdGlvbiB0b2dldGhlciBpbnN0ZWFkIG9mXHJcbiAgICAgKiB0aXRsZSBhbG9uZSwgdG8gcmVkdWNlIGZhbHNlIHBvc2l0aXZlcyB3aGVuIHNldmVyYWwgc291cmNlIGl0ZW1zIGhhcHBlbiB0byBzaGFyZVxyXG4gICAgICogdGhlIHNhbWUgdGl0bGUuIE5vdCBhIHBlcmZlY3QgZ3VhcmFudGVlLCBidXQgbWVhbmluZ2Z1bGx5IG1vcmUgcm9idXN0LlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIG1hdGNoZXNFeGlzdGluZzxUIGV4dGVuZHMgeyB0aXRsZT86IHN0cmluZzsgZGVzY3JpcHRpb24/OiBzdHJpbmcgfT4oc291cmNlOiBULCB0YXJnZXRMaXN0OiBUW10pOiBib29sZWFuIHtcclxuICAgICAgICByZXR1cm4gdGFyZ2V0TGlzdC5zb21lKHQgPT5cclxuICAgICAgICAgICAgdC50aXRsZSA9PT0gc291cmNlLnRpdGxlICYmICh0LmRlc2NyaXB0aW9uIHx8IG51bGwpID09PSAoc291cmNlLmRlc2NyaXB0aW9uIHx8IG51bGwpXHJcbiAgICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICAvL1xyXG4gICAgLy8gLS0tLS0tLS0tLSBTd2VlcCBwb3NpdGlvbnMgLyByaWdpZCB0cmFuc2Zvcm0gLS0tLS0tLS0tLVxyXG4gICAgLy9cclxuXHJcbiAgICAvKipcclxuICAgICAqIEZldGNoZXMgdGhlIHBvc2l0aW9uIG9mIGV2ZXJ5IHN3ZWVwIGluIGEgc3BhY2UgYW5kIHJldHVybnMgaXQgYXMgYSBNYXAgZm9yIE8oMSkgbG9va3VwLlxyXG4gICAgICogVXNlcyBhbGxTZXR0bGVkIHNvIGEgc2luZ2xlIGZhaWxpbmcgc3dlZXAgbG9va3VwIGRvZXNuJ3QgYWJvcnQgdGhlIHdob2xlIG1hcCDigJRcclxuICAgICAqIHRoYXQgc3dlZXAgaXMgc2ltcGx5IGFic2VudCBmcm9tIHRoZSByZXN1bHRpbmcgbWFwIChhbmQgc2tpcHBlZCBsYXRlcikuXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgYXN5bmMgYnVpbGROYXZpZ2F0aW9uUG9zaXRpb25NYXAoc3BhY2VJZDogc3RyaW5nLCBzd2VlcElkczogc3RyaW5nW10pOiBQcm9taXNlPE1hcDxzdHJpbmcsIFZlYzM+PiB7XHJcbiAgICAgICAgY29uc3QgbWFwID0gbmV3IE1hcDxzdHJpbmcsIFZlYzM+KCk7XHJcblxyXG4gICAgICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoXHJcbiAgICAgICAgICAgIHN3ZWVwSWRzLm1hcChhc3luYyAoc2lkKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBuYXZzID0gYXdhaXQgdGhpcy5uYXZpZ2F0aW9uU2VydmljZS5nZXROYXZpZ2F0aW9uc0Zvck1hdHRlcnBvcnRJREZvclNwYWNlKHNpZCwgc3BhY2VJZCk7XHJcbiAgICAgICAgICAgICAgICBpZiAobmF2cyAmJiBuYXZzLmxlbmd0aCA+IDAgJiYgbmF2c1swXS5wb3NpdGlvbikge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7IHNpZCwgcG9zaXRpb246IEpTT04ucGFyc2UobmF2c1swXS5wb3NpdGlvbikgYXMgVmVjMyB9O1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgKTtcclxuXHJcbiAgICAgICAgZm9yIChjb25zdCByZXN1bHQgb2YgcmVzdWx0cykge1xyXG4gICAgICAgICAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gJ2Z1bGZpbGxlZCcgJiYgcmVzdWx0LnZhbHVlKSB7XHJcbiAgICAgICAgICAgICAgICBtYXAuc2V0KHJlc3VsdC52YWx1ZS5zaWQsIHJlc3VsdC52YWx1ZS5wb3NpdGlvbik7XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocmVzdWx0LnN0YXR1cyA9PT0gJ3JlamVjdGVkJykge1xyXG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdGYWlsZWQgdG8gZmV0Y2ggYSBzd2VlcCBwb3NpdGlvbiwgc2tpcHBpbmcgaXQ6JywgcmVzdWx0LnJlYXNvbik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBtYXA7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEFwcGxpZXMgdGhlIHJpZ2lkIHRyYW5zZm9ybSB0byBhIFBPSSBjb29yZGluYXRlIChwb3NpdGlvbiArIG9yaWVudGF0aW9uKS4gKi9cclxuICAgIHByaXZhdGUgZ2V0QWRqdXN0ZWRDb29yZGluYXRlcyhjb29yZGluYXRlOiBzdHJpbmcsIHRyYW5zZm9ybTogUmlnaWRUcmFuc2Zvcm0pOiBhbnkge1xyXG4gICAgICAgIGlmIChjb29yZGluYXRlID09PSBcIm51bGxcIikge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKCFjb29yZGluYXRlIHx8IHR5cGVvZiBjb29yZGluYXRlICE9PSAnc3RyaW5nJykge1xyXG4gICAgICAgICAgICByZXR1cm4gY29vcmRpbmF0ZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2UoY29vcmRpbmF0ZSk7XHJcbiAgICAgICAgY29uc3Qgcm90YXRlZFBvcyA9IGFwcGx5UmlnaWRUcmFuc2Zvcm1Ub1BvaW50KFxyXG4gICAgICAgICAgICB7IHg6IHBhcnNlZC54LCB5OiBwYXJzZWQueSwgejogcGFyc2VkLnogfSxcclxuICAgICAgICAgICAgdHJhbnNmb3JtXHJcbiAgICAgICAgKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgeDogcm90YXRlZFBvcy54LFxyXG4gICAgICAgICAgICB5OiByb3RhdGVkUG9zLnksXHJcbiAgICAgICAgICAgIHo6IHJvdGF0ZWRQb3MueixcclxuICAgICAgICAgICAgeFJvdGF0aW9uOiBwYXJzZWQueFJvdGF0aW9uLFxyXG4gICAgICAgICAgICB5Um90YXRpb246IGFwcGx5UmlnaWRUcmFuc2Zvcm1Ub1lSb3RhdGlvbkRlZyhwYXJzZWQueVJvdGF0aW9uLCB0cmFuc2Zvcm0pXHJcbiAgICAgICAgfTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEFwcGxpZXMgdGhlIHJpZ2lkIHRyYW5zZm9ybSdzIHRyYW5zbGF0aW9uK3JvdGF0aW9uIHRvIGEgcGxhaW4ge3gseSx6fSBwb3NpdGlvbixcclxuICAgICAqIFdJVEhPVVQgYWRkaW5nIHhSb3RhdGlvbi95Um90YXRpb24ga2V5cy4gVXNlZCBmb3IgbWVhc3VyZW1lbnRzLCB3aG9zZSBzdG9yZWRcclxuICAgICAqIGNvb3JkaW5hdGUgaXMgYSBiYXJlIHBvc2l0aW9uIChubyBvcmllbnRhdGlvbiksIHVubGlrZSBvdGhlciBQT0kgdHlwZXMuXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZ2V0QWRqdXN0ZWRQb3NpdGlvbk9ubHkoY29vcmRpbmF0ZTogc3RyaW5nLCB0cmFuc2Zvcm06IFJpZ2lkVHJhbnNmb3JtKTogYW55IHtcclxuICAgICAgICBpZiAoIWNvb3JkaW5hdGUgfHwgdHlwZW9mIGNvb3JkaW5hdGUgIT09ICdzdHJpbmcnIHx8IGNvb3JkaW5hdGUgPT09ICdudWxsJykge1xyXG4gICAgICAgICAgICByZXR1cm4gY29vcmRpbmF0ZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgY29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZShjb29yZGluYXRlKTtcclxuICAgICAgICByZXR1cm4gYXBwbHlSaWdpZFRyYW5zZm9ybVRvUG9pbnQoeyB4OiBwYXJzZWQueCwgeTogcGFyc2VkLnksIHo6IHBhcnNlZC56IH0sIHRyYW5zZm9ybSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBGaW5kcyB0aGUgY2xvc2VzdCB0YXJnZXQgc3dlZXAsIGNvbXBhcmluZyBwb3NpdGlvbnMgaW4gdGhlIFNBTUUgY29vcmRpbmF0ZSBmcmFtZS5cclxuICAgICAqIFB1cmUgaW4tbWVtb3J5IGxvb2t1cCDigJQgbm8gbmV0d29yayBjYWxsLCB0aGFua3MgdG8gdGhlIHByZS1idWlsdCBwb3NpdGlvbiBtYXBzLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGZpbmRDbG9zZXN0VGFyZ2V0U3dlZXBJZChcclxuICAgICAgICBzb3VyY2VTd2VlcElEOiBzdHJpbmcsXHJcbiAgICAgICAgc291cmNlTmF2UG9zaXRpb25zOiBNYXA8c3RyaW5nLCBWZWMzPixcclxuICAgICAgICB0YXJnZXROYXZQb3NpdGlvbnM6IE1hcDxzdHJpbmcsIFZlYzM+LFxyXG4gICAgICAgIHRyYW5zZm9ybTogUmlnaWRUcmFuc2Zvcm1cclxuICAgICk6IHN0cmluZyB8IG51bGwge1xyXG4gICAgICAgIGlmICghc291cmNlU3dlZXBJRCkgcmV0dXJuIG51bGw7XHJcblxyXG4gICAgICAgIGNvbnN0IHNvdXJjZVBvcyA9IHNvdXJjZU5hdlBvc2l0aW9ucy5nZXQoc291cmNlU3dlZXBJRCk7XHJcbiAgICAgICAgaWYgKCFzb3VyY2VQb3MpIHJldHVybiBudWxsO1xyXG5cclxuICAgICAgICBjb25zdCBzb3VyY2VQb3NJblRhcmdldEZyYW1lID0gYXBwbHlSaWdpZFRyYW5zZm9ybVRvUG9pbnQoc291cmNlUG9zLCB0cmFuc2Zvcm0pO1xyXG5cclxuICAgICAgICBsZXQgY2xvc2VzdFN3ZWVwSUQ6IHN0cmluZyB8IG51bGwgPSBudWxsO1xyXG4gICAgICAgIGxldCBtaW5EaXN0YW5jZSA9IEluZmluaXR5O1xyXG5cclxuICAgICAgICBmb3IgKGNvbnN0IFt0YXJnZXRTd2VlcElkLCB0YXJnZXRQb3NdIG9mIHRhcmdldE5hdlBvc2l0aW9ucy5lbnRyaWVzKCkpIHtcclxuICAgICAgICAgICAgY29uc3QgZHggPSB0YXJnZXRQb3MueCAtIHNvdXJjZVBvc0luVGFyZ2V0RnJhbWUueDtcclxuICAgICAgICAgICAgY29uc3QgZHkgPSB0YXJnZXRQb3MueSAtIHNvdXJjZVBvc0luVGFyZ2V0RnJhbWUueTtcclxuICAgICAgICAgICAgY29uc3QgZHogPSB0YXJnZXRQb3MueiAtIHNvdXJjZVBvc0luVGFyZ2V0RnJhbWUuejtcclxuICAgICAgICAgICAgY29uc3QgZGlzdCA9IE1hdGguc3FydChkeCAqIGR4ICsgZHkgKiBkeSArIGR6ICogZHopO1xyXG5cclxuICAgICAgICAgICAgaWYgKGRpc3QgPCBtaW5EaXN0YW5jZSkge1xyXG4gICAgICAgICAgICAgICAgbWluRGlzdGFuY2UgPSBkaXN0O1xyXG4gICAgICAgICAgICAgICAgY2xvc2VzdFN3ZWVwSUQgPSB0YXJnZXRTd2VlcElkO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gY2xvc2VzdFN3ZWVwSUQ7XHJcbiAgICB9XHJcblxyXG4gICAgLy9cclxuICAgIC8vIC0tLS0tLS0tLS0gUzMgZmlsZSBkdXBsaWNhdGlvbiAtLS0tLS0tLS0tXHJcbiAgICAvL1xyXG5cclxuICAgIC8qKiBHZW5lcmF0ZXMgYSBzaG9ydCByYW5kb20gaWQsIHVzZWQgdG8gZ2l2ZSBlYWNoIGNvcGllZCBTMyBmaWxlIGEgZnJlc2gsIGNvbGxpc2lvbi1zYWZlIGtleS4gKi9cclxuICAgIHByaXZhdGUgZ2VuZXJhdGVTaG9ydElkKCk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIE1hdGgucmFuZG9tKCkudG9TdHJpbmcoMzYpLnNsaWNlKDIsIDEwKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEJ1aWxkcyBhIG5ldyBTMyBrZXkgZm9yIGEgY29waWVkIGF0dGFjaG1lbnQgYW5kIHNhbml0aXplcyB0aGUgZmlsZW5hbWVcclxuICAgICAqIHRvIHByZXZlbnQgQVdTIEFtcGxpZnkgU2lnbmF0dXJlRG9lc05vdE1hdGNoIGVycm9ycy5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBidWlsZENvcGllZEF0dGFjaG1lbnRLZXkoc291cmNlQW5uZXhlOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgICAgIGNvbnN0IGxhc3RTbGFzaCA9IHNvdXJjZUFubmV4ZS5sYXN0SW5kZXhPZignLycpO1xyXG4gICAgICAgIGNvbnN0IGZvbGRlciA9IHNvdXJjZUFubmV4ZS5zdWJzdHJpbmcoMCwgbGFzdFNsYXNoICsgMSk7XHJcbiAgICAgICAgbGV0IGZpbGVuYW1lID0gc291cmNlQW5uZXhlLnN1YnN0cmluZyhsYXN0U2xhc2ggKyAxKTtcclxuXHJcbiAgICAgICAgLy8gU3RyaXAgYSBsZWFkaW5nIFwiPDggaGV4IGNoYXJzPl9cIiBpZCBwcmVmaXggaWYgcHJlc2VudFxyXG4gICAgICAgIGNvbnN0IHByZWZpeE1hdGNoID0gZmlsZW5hbWUubWF0Y2goL15bMC05YS1mQS1GLV17OH1fKC4rKSQvKTtcclxuICAgICAgICBpZiAocHJlZml4TWF0Y2gpIHtcclxuICAgICAgICAgICAgZmlsZW5hbWUgPSBwcmVmaXhNYXRjaFsxXTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIFNBTklUSVpBVElPTjogUmVwbGFjZSBzcGFjZXMsIHBhcmVudGhlc2VzLCBhbmQgYWNjZW50cyB3aXRoIHVuZGVyc2NvcmVzXHJcbiAgICAgICAgLy8gQ3J1Y2lhbCB0byBwcmV2ZW50IEFtcGxpZnkncyBTdG9yYWdlLmNvcHkgZnJvbSBmYWlsaW5nIHRoZSBzaWduYXR1cmUgY2FsY3VsYXRpb25cclxuICAgICAgICBmaWxlbmFtZSA9IGZpbGVuYW1lLnJlcGxhY2UoL1teYS16QS1aMC05LlxcLV9dL2csICdfJyk7XHJcblxyXG4gICAgICAgIGNvbnN0IG5ld1ByZWZpeCA9IGAke3RoaXMuZ2VuZXJhdGVTaG9ydElkKCl9X2A7XHJcbiAgICAgICAgcmV0dXJuIGAke2ZvbGRlcn0ke25ld1ByZWZpeH0ke2ZpbGVuYW1lfWA7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEdXBsaWNhdGVzIGFuIFMzIG9iamVjdCBpZiBhIGtleSBpcyBwcmVzZW50LlxyXG4gICAgICogLSBJZiB0aGUgc291cmNlIGZpbGUgaXMgZ2VudWluZWx5IG1pc3NpbmcgZnJvbSBTMyAoTm9TdWNoS2V5IC8gb3JwaGFuZWQgREIgcmVmZXJlbmNlKSxcclxuICAgICAqICAgdGhyb3dzIGEgTWlzc2luZ1MzRmlsZUVycm9yIHNvIHRoZSBjYWxsZXIgY2FuIGxvZyBhIGNsZWFyLCBzcGVjaWZpYyBtZXNzYWdlIGFuZFxyXG4gICAgICogICBza2lwIHRoZSB3aG9sZSBpdGVtIGVudGlyZWx5LCByYXRoZXIgdGhhbiBjcmVhdGluZyBhIHJlY29yZCB3aXRoIGEgYnJva2VuIGZpbGUgbGluay5cclxuICAgICAqIC0gQW55IG90aGVyIGtpbmQgb2YgZmFpbHVyZSAocGVybWlzc2lvbnMsIG5ldHdvcmssIGV0Yy4pIHN0aWxsIHRocm93cyBhIGdlbmVyaWMgRXJyb3IuXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgYXN5bmMgY29weVMzS2V5SWZQcmVzZW50KGtleTogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCwgY29udGV4dExhYmVsOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZyB8IG51bGw+IHtcclxuICAgICAgICBpZiAoIWtleSkge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9XHJcbiAgICAgICAgY29uc3Qgc291cmNlS2V5ID0gdGhpcy5leHRyYWN0UzNLZXlGcm9tVmFsdWUoa2V5KTtcclxuICAgICAgICBjb25zdCBkZXN0S2V5ID0gdGhpcy5idWlsZENvcGllZEF0dGFjaG1lbnRLZXkoc291cmNlS2V5KTtcclxuXHJcbiAgICAgICAgLy8gTG9nIHRoZSBzb3VyY2Uga2V5IHRvIGVuc3VyZSBpdCBtYXRjaGVzIHRoZSByZWFsIFMzIG9iamVjdCBwYXRoXHJcbiAgICAgICAgY29uc29sZS5sb2coYFtERUJVR10gQXR0ZW1wdGluZyBTMyBjb3B5IGZyb20gc291cmNlOiBcIiR7c291cmNlS2V5fVwiIHRvIGRlc3Q6IFwiJHtkZXN0S2V5fVwiYCk7XHJcblxyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGNvcGllZCA9IGF3YWl0IGNvcHlGaWxlSW5TMyhzb3VyY2VLZXksIGRlc3RLZXkpO1xyXG4gICAgICAgICAgICBpZiAoIWNvcGllZCkge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE1pc3NpbmdTM0ZpbGVFcnJvcihzb3VyY2VLZXksIGNvbnRleHRMYWJlbCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIGNvcGllZDtcclxuICAgICAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGlzTWlzc2luZ0ZpbGUgPSBlcnJvciBpbnN0YW5jZW9mIE1pc3NpbmdTM0ZpbGVFcnJvclxyXG4gICAgICAgICAgICAgICAgfHwgZXJyb3I/LmNvZGUgPT09ICdOb1N1Y2hLZXknXHJcbiAgICAgICAgICAgICAgICB8fCAvTm9TdWNoS2V5fGRvZXMgbm90IGV4aXN0L2kudGVzdCh0b0Vycm9yTWVzc2FnZShlcnJvcikpO1xyXG4gICAgICAgICAgICBpZiAoaXNNaXNzaW5nRmlsZSkge1xyXG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBbTWF0dGVycG9ydFRhZ0NvcHlTZXJ2aWNlXSBPcnBoYW5lZCBTMyByZWZlcmVuY2UsIHNraXBwaW5nIGl0ZW06IFwiJHtzb3VyY2VLZXl9XCIgKCR7Y29udGV4dExhYmVsfSlgKTtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBNaXNzaW5nUzNGaWxlRXJyb3Ioc291cmNlS2V5LCBjb250ZXh0TGFiZWwpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIER1cGxpY2F0ZXMgdGhlIGZpbGUgcmVmZXJlbmNlZCBieSBhIFBPSSdzIHRhZ0ljb24gKGEgSlNPTiBzdHJpbmcgc2hhcGVkIGxpa2VcclxuICAgICAqIHsgc3JjLCBvcGFjaXR5IH0sIHBlciBmb3JtLWZlYXR1cmUuY29tcG9uZW50LnRzKS4gSWYgdGhlIEpTT04gY2FuJ3QgYmUgcGFyc2VkIG9yXHJcbiAgICAgKiBoYXMgbm8gYHNyY2AsIHRoZSB2YWx1ZSBpcyByZXR1cm5lZCB1bmNoYW5nZWQgcmF0aGVyIHRoYW4gcmlzayBjb3JydXB0aW5nIGl0LlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGFzeW5jIGR1cGxpY2F0ZVRhZ0ljb24odGFnSWNvblJhdzogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCk6IFByb21pc2U8c3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZD4ge1xyXG4gICAgICAgIGlmICghdGFnSWNvblJhdykge1xyXG4gICAgICAgICAgICByZXR1cm4gdGFnSWNvblJhdztcclxuICAgICAgICB9XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgY29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZSh0YWdJY29uUmF3KTtcclxuICAgICAgICAgICAgaWYgKHBhcnNlZCAmJiBwYXJzZWQuc3JjKSB7XHJcbiAgICAgICAgICAgICAgICBwYXJzZWQuc3JjID0gYXdhaXQgdGhpcy5jb3B5UzNLZXlJZlByZXNlbnQocGFyc2VkLnNyYywgJ3RhZyBpY29uJyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHBhcnNlZCk7XHJcbiAgICAgICAgfSBjYXRjaCB7XHJcbiAgICAgICAgICAgIC8vIE5vdCBKU09OLCBvciB1bmV4cGVjdGVkIHNoYXBlIOKAlCBsZWF2ZSB1bnRvdWNoZWQgcmF0aGVyIHRoYW4gZ3Vlc3MuXHJcbiAgICAgICAgICAgIHJldHVybiB0YWdJY29uUmF3O1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIER1cGxpY2F0ZXMgdGFnSW1hZ2VJRCBpZiBpdCBsb29rcyBsaWtlIGEgcmVmZXJlbmNlIHRvIGEgZmlsZSAoY29udGFpbnMgYSBwYXRoXHJcbiAgICAgKiBzZXBhcmF0b3IsIHdoZXRoZXIgcmF3IGtleSBvciBwcmUtc2lnbmVkIFVSTCkuIFVOQ09ORklSTUVEIEFTU1VNUFRJT046IHRoaXNcclxuICAgICAqIGZpZWxkJ3MgZXhhY3Qgc2VtYW50aWNzIHdlcmVuJ3QgdmVyaWZpZWQg4oCUIGlmIGl0J3MgYWN0dWFsbHkgYW4gb3BhcXVlIHJlZmVyZW5jZVxyXG4gICAgICogdG8gYW5vdGhlciBEQiByZWNvcmQgcmF0aGVyIHRoYW4gYSBmaWxlLCB0aGlzIGhldXJpc3RpYyBtYXkgaW5jb3JyZWN0bHkgYXR0ZW1wdFxyXG4gICAgICogYSBjb3B5LiBDb25maXJtIHRoZSByZWFsIHN0cnVjdHVyZSB0byB0aWdodGVuIHRoaXMgaWYgaXQgY2F1c2VzIGlzc3Vlcy5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBhc3luYyBkdXBsaWNhdGVUYWdJbWFnZUlEKHRhZ0ltYWdlSUQ6IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQpOiBQcm9taXNlPHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQ+IHtcclxuICAgICAgICBpZiAoIXRhZ0ltYWdlSUQgfHwgIXRhZ0ltYWdlSUQuaW5jbHVkZXMoJy8nKSkge1xyXG4gICAgICAgICAgICByZXR1cm4gdGFnSW1hZ2VJRDtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuY29weVMzS2V5SWZQcmVzZW50KHRhZ0ltYWdlSUQsICd0YWcgaW1hZ2UnKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEV4dHJhY3RzIGFuZCBub3JtYWxpemVzIHRoZSByYXcgUzMga2V5IGZyb20gYSBzdG9yZWQgdmFsdWUgKHdoaWNoIG1heSBiZSBhIGZ1bGwgVVJMXHJcbiAgICAgKiBvciBhbHJlYWR5IGEgcmF3IGtleSkuXHJcbiAgICAgKiBJTVBPUlRBTlQ6IHRoaXMgbXVzdCByZXR1cm4gdGhlIFJBVyAoZGVjb2RlZCwgbm9uIFVSTC1lbmNvZGVkKSBrZXkuIEFtcGxpZnknc1xyXG4gICAgICogU3RvcmFnZS5jb3B5KCkgYWxyZWFkeSBidWlsZHMgYW5kIGVuY29kZXMgdGhlICd4LWFtei1jb3B5LXNvdXJjZScgaGVhZGVyIGludGVybmFsbHlcclxuICAgICAqIGZyb20gdGhlIGtleSB3ZSBnaXZlIGl0LiBQcmUtZW5jb2RpbmcgaXQgaGVyZSBjYXVzZWQgYSBkb3VibGUtZW5jb2RpbmcgYnVnIChlLmcuIGFcclxuICAgICAqIHNwYWNlIGJlY2FtZSBcIiUyNTIwXCIgaW5zdGVhZCBvZiBcIiUyMFwiKSwgc28gU3RvcmFnZS5jb3B5KCkgbG9va2VkIGZvciBhIGtleSB0aGF0IG5ldmVyXHJcbiAgICAgKiBleGlzdGVkIG9uIFMzLCByZXN1bHRpbmcgaW4gYSBOb1N1Y2hLZXkgZXJyb3IuXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZXh0cmFjdFMzS2V5RnJvbVZhbHVlKHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgICAgIGlmICghdmFsdWUpIHtcclxuICAgICAgICAgICAgcmV0dXJuICcnO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbGV0IGV4dHJhY3RlZCA9IHZhbHVlO1xyXG5cclxuICAgICAgICAvLyAxLiBFeHRyYWN0IHBhdGggZnJvbSBVUkwgYW5kIGRyb3AgcXVlcnkgcGFyYW1zXHJcbiAgICAgICAgaWYgKHZhbHVlLnN0YXJ0c1dpdGgoJ2h0dHA6Ly8nKSB8fCB2YWx1ZS5zdGFydHNXaXRoKCdodHRwczovLycpKSB7XHJcbiAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCB1cmwgPSBuZXcgVVJMKHZhbHVlKTtcclxuICAgICAgICAgICAgICAgIGV4dHJhY3RlZCA9IGRlY29kZVVSSUNvbXBvbmVudCh1cmwucGF0aG5hbWUpO1xyXG4gICAgICAgICAgICB9IGNhdGNoIHtcclxuICAgICAgICAgICAgICAgIGV4dHJhY3RlZCA9IHZhbHVlLnNwbGl0KCc/JylbMF07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBleHRyYWN0ZWQgPSB2YWx1ZS5zcGxpdCgnPycpWzBdO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gMi4gUmVtb3ZlIGxlYWRpbmcgc2xhc2hcclxuICAgICAgICBpZiAoZXh0cmFjdGVkLnN0YXJ0c1dpdGgoJy8nKSkge1xyXG4gICAgICAgICAgICBleHRyYWN0ZWQgPSBleHRyYWN0ZWQuc3Vic3RyaW5nKDEpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gMy4gUmVtb3ZlICdwdWJsaWMvJyBwcmVmaXhcclxuICAgICAgICAvLyBBbXBsaWZ5IHByZXBlbmRzIHRoaXMgYXV0b21hdGljYWxseTsgd2UgbXVzdCBzdHJpcCBpdCBmcm9tIHRoZSBpbnB1dFxyXG4gICAgICAgIC8vIHRvIGF2b2lkIHRoZSAncHVibGljL3B1YmxpYy8nIGRvdWJsZS1wcmVmaXggaXNzdWUuXHJcbiAgICAgICAgaWYgKGV4dHJhY3RlZC5zdGFydHNXaXRoKCdwdWJsaWMvJykpIHtcclxuICAgICAgICAgICAgZXh0cmFjdGVkID0gZXh0cmFjdGVkLnN1YnN0cmluZygncHVibGljLycubGVuZ3RoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIFJldHVybiB0aGUgcmF3IGtleSBhcy1pcyDigJQgU3RvcmFnZS5jb3B5KCkgdGFrZXMgY2FyZSBvZiBwcm9wZXJseSBlbmNvZGluZyBpdFxyXG4gICAgICAgIC8vIGZvciB0aGUgQ29weVNvdXJjZSBoZWFkZXIuIERvIE5PVCByZS1lbmNvZGUgaXQgaGVyZS5cclxuICAgICAgICByZXR1cm4gZXh0cmFjdGVkO1xyXG4gICAgfVxyXG59Il19
1893
+ }], ctorParameters: () => [{ type: i1.NavigationService }, { type: i2.BaseUserService }, { type: i3.PoiService }, { type: i4.TicketsService }, { type: i5.EquipmentService }, { type: i6.Object3DService }, { type: i7.FeatureService }, { type: i8.MeasurementService }, { type: i9.CommentService }, { type: i10.HashtagService }, { type: i11.MissionService }, { type: i12.OperationService }, { type: i13.DomainService }, { type: i14.TranslateService }] });
1894
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0dGVycG9ydC10YWctY29weS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWNvcmUvc3JjL2xpYi9zZXJ2aWNlcy9tYXR0ZXJwb3J0LXRhZy1jb3B5LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBZ0J2QyxPQUFPLEVBQUUsWUFBWSxFQUFFLHVCQUF1QixFQUFFLE1BQU0sY0FBYyxDQUFDLENBQUMseUdBQXlHO0FBQy9LLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNsRCxPQUFPLEVBQ0gscUJBQXFCLEVBQUUsMEJBQTBCLEVBQUUsOEJBQThCLEVBQ2pGLGlDQUFpQyxFQUNwQyxNQUFNLG1DQUFtQyxDQUFDO0FBQzNDLE9BQU8sRUFBMkMsV0FBVyxFQUFFLE9BQU8sRUFBYSxRQUFRLEVBQStDLE1BQU0sa0JBQWtCLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7QUF5Qm5LO3dFQUN3RTtBQUN4RSxTQUFTLGNBQWMsQ0FBQyxHQUFZO0lBQ2hDLElBQUksR0FBRyxJQUFJLE9BQU8sR0FBRyxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQ2pDLE1BQU0sTUFBTSxHQUFHLEdBQVUsQ0FBQztRQUMxQixJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQzNELE9BQU8sTUFBTSxDQUFDLE1BQU07aUJBQ2YsR0FBRyxDQUFDLENBQUMsQ0FBTSxFQUFFLEVBQUU7Z0JBQ1osTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENB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QUMsRUFBRSxDQUFDO1lBQ2xDLFNBQVMsR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN0RCxDQUFDO1FBRUQsK0VBQStFO1FBQy9FLHVEQUF1RDtRQUN2RCxPQUFPLFNBQVMsQ0FBQztJQUNyQixDQUFDO3dHQXZsRVEsd0JBQXdCOzRHQUF4Qix3QkFBd0IsY0FEWCxNQUFNOzs0RkFDbkIsd0JBQXdCO2tCQURwQyxVQUFVO21CQUFDLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0IH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IFRyYW5zbGF0ZVNlcnZpY2UgfSBmcm9tICdAbmd4LXRyYW5zbGF0ZS9jb3JlJztcclxuaW1wb3J0IHsgUE9JIH0gZnJvbSAnLi4vdHlwZXMuc2VydmljZSc7XHJcbmltcG9ydCB7IE5hdmlnYXRpb25TZXJ2aWNlIH0gZnJvbSAnLi9tb2RlbHMvbmF2aWdhdGlvbi5zZXJ2aWNlJztcclxuaW1wb3J0IHsgUG9pU2VydmljZSB9IGZyb20gJy4vbW9kZWxzL3BvaS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgVGlja2V0c1NlcnZpY2UgfSBmcm9tICcuL21vZGVscy90aWNrZXQuc2VydmljZSc7XHJcbmltcG9ydCB7IEVxdWlwbWVudFNlcnZpY2UgfSBmcm9tICcuL21vZGVscy9lcXVpcG1lbnQuc2VydmljZSc7XHJcbmltcG9ydCB7IE9iamVjdDNEU2VydmljZSB9IGZyb20gJy4vbW9kZWxzL29iamVjdDNELnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBGZWF0dXJlU2VydmljZSB9IGZyb20gJy4vbW9kZWxzL2ZlYXR1cmUuc2VydmljZSc7XHJcbmltcG9ydCB7IE1lYXN1cmVtZW50U2VydmljZSB9IGZyb20gJy4vbW9kZWxzL21lYXN1cmVtZW50LnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBDb21tZW50U2VydmljZSB9IGZyb20gJy4vbW9kZWxzL2NvbW1lbnQuc2VydmljZSc7XHJcbmltcG9ydCB7IEhhc2h0YWdTZXJ2aWNlIH0gZnJvbSAnLi9tb2RlbHMvaGFzaHRhZy5zZXJ2aWNlJztcclxuaW1wb3J0IHsgTWlzc2lvblNlcnZpY2UgfSBmcm9tICcuL21vZGVscy9taXNzaW9uLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBPcGVyYXRpb25TZXJ2aWNlIH0gZnJvbSAnLi9tb2RlbHMvb3BlcmF0aW9uLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBEb21haW5TZXJ2aWNlIH0gZnJvbSAnLi9tb2RlbHMvZG9tYWluLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBCYXNlVXNlclNlcnZpY2UgfSBmcm9tICcuL3VzZXIuc2VydmljZSc7XHJcbmltcG9ydCB7IGNvcHlGaWxlSW5TMywgY29weUZpbGVJblMzVmlhRG93bmxvYWQgfSBmcm9tICcuL3MzLnNlcnZpY2UnOyAvLyBzZWUgczMuc2VydmljZS50czogbmVpdGhlciBtdXN0IHN3YWxsb3cgZXJyb3JzIChuZWVkZWQgdG8gZGV0ZWN0IE5vU3VjaEtleSAvIHNpZ25hdHVyZSBtaXNtYXRjaCBiZWxvdylcclxuaW1wb3J0IHsgZG93bmxvYWRCbG9iIH0gZnJvbSAnLi4vaGVscGVycy5zZXJ2aWNlJztcclxuaW1wb3J0IHtcclxuICAgIGNvbXB1dGVSaWdpZFRyYW5zZm9ybSwgYXBwbHlSaWdpZFRyYW5zZm9ybVRvUG9pbnQsIGFwcGx5UmlnaWRUcmFuc2Zvcm1Ub0RpcmVjdGlvbixcclxuICAgIGFwcGx5UmlnaWRUcmFuc2Zvcm1Ub1lSb3RhdGlvbkRlZywgUmlnaWRUcmFuc2Zvcm0sIFZlYzNcclxufSBmcm9tICcuL3V0aWxzL21hdHRlcnBvcnQtdHJhbnNmb3JtLnV0aWwnO1xyXG5pbXBvcnQgeyBPYmplY3QzRCwgRmVhdHVyZSwgTWVhc3VyZW1lbnQsIENvbW1lbnQsIENvbW1lbnRUeXBlLCBQb2lUeXBlLCBFcXVpcG1lbnQsIFNwTW9kdWxlLCBUaWNrZXQsIEhhc2h0YWcsIE1pc3Npb24sIE9wZXJhdGlvbiwgRG9tYWluIH0gZnJvbSAnLi4vdHlwZXMuc2VydmljZSc7XHJcblxyXG4vKiogUHJvZ3Jlc3Mgc25hcHNob3QgZW1pdHRlZCBkdXJpbmcgY29weVRhZ3NGcm9tVmlzaXQoKSwgc28gdGhlIFVJIGNhbiBzaG93IGEgbGl2ZSBzdGF0dXMuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgQ29weVByb2dyZXNzIHtcclxuICAgIHBoYXNlOiAnY29sbGVjdGluZycgfCAndGlja2V0cycgfCAnZXF1aXBtZW50cycgfCAncG9pcycgfCAnb2JqZWN0czNkJyB8ICdmZWF0dXJlcycgfCAnbWVhc3VyZW1lbnRzJyB8ICdkb25lJztcclxuICAgIHByb2Nlc3NlZEluUGhhc2U6IG51bWJlcjtcclxuICAgIHRvdGFsSW5QaGFzZTogbnVtYmVyO1xyXG4gICAgcHJvY2Vzc2VkT3ZlcmFsbDogbnVtYmVyO1xyXG4gICAgdG90YWxPdmVyYWxsOiBudW1iZXI7XHJcbiAgICBwZXJjZW50OiBudW1iZXI7XHJcbiAgICBlcnJvckNvdW50OiBudW1iZXI7XHJcbiAgICAvKiogSXRlbXMgdGhhdCBhbHJlYWR5IGV4aXN0ZWQgaW4gdGhlIHRhcmdldCBzcGFjZSBhbmQgaGFkIG1pc3NpbmcgaWRlbnRpdHkgZmllbGRzXHJcbiAgICAgKiAgZmlsbGVkIGluLCByYXRoZXIgdGhhbiBiZWluZyBuZXdseSBjcmVhdGVkIOKAlCBzZWUgaGVhbEVxdWlwbWVudElkZW50aXR5KCkgYW5kIGl0c1xyXG4gICAgICogIHRpY2tldC9mZWF0dXJlIGVxdWl2YWxlbnRzLiAqL1xyXG4gICAgaGVhbGVkQ291bnQ6IG51bWJlcjtcclxufVxyXG5cclxuLyoqIEEgc2luZ2xlIGxpbmUgaW4gdGhlIGNvcHkgbG9nIOKAlCBhIHN0ZXAgc3RhdHVzICh1cGRhdGVkIGluIHBsYWNlKSwgb3IgYW4gZXJyb3IgLyBoZWFsZWRcclxuICogIGl0ZW0gbm90aWNlIChhcHBlbmRlZCBvbmNlLCBwZXJtYW5lbnQpLiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIENvcHlMb2dFbnRyeSB7XHJcbiAgICBpZDogc3RyaW5nOyAgICAgICAvLyBzdGFibGUgaWQgZm9yIHN0ZXAgbGluZXMgKHNvIHRoZXkgdXBkYXRlIGluIHBsYWNlKSwgdW5pcXVlIGZvciBlcnJvci9oZWFsZWQgbGluZXNcclxuICAgIHR5cGU6ICdzdGVwJyB8ICdlcnJvcicgfCAnaGVhbGVkJztcclxuICAgIHRleHQ6IHN0cmluZztcclxufVxyXG5cclxuLyoqIFNhZmVseSBleHRyYWN0cyBhIHJlYWRhYmxlIG1lc3NhZ2UgZnJvbSBhbiB1bmtub3duIGNhdGNoIHZhbHVlLCBpbmNsdWRpbmcgQW1wbGlmeSdzXHJcbiAqICBHcmFwaFFMIGVycm9yIHNoYXBlICh7IGRhdGEsIGVycm9yczogW3sgZXJyb3JUeXBlLCBtZXNzYWdlIH1dIH0pLiAqL1xyXG5mdW5jdGlvbiB0b0Vycm9yTWVzc2FnZShlcnI6IHVua25vd24pOiBzdHJpbmcge1xyXG4gICAgaWYgKGVyciAmJiB0eXBlb2YgZXJyID09PSAnb2JqZWN0Jykge1xyXG4gICAgICAgIGNvbnN0IGFueUVyciA9IGVyciBhcyBhbnk7XHJcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoYW55RXJyLmVycm9ycykgJiYgYW55RXJyLmVycm9ycy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBhbnlFcnIuZXJyb3JzXHJcbiAgICAgICAgICAgICAgICAubWFwKChlOiBhbnkpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCB0aXRsZSA9IGUuZXJyb3JUeXBlID8gYCR7ZS5lcnJvclR5cGV9OiBgIDogJyc7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGAke3RpdGxlfSR7ZS5tZXNzYWdlIHx8ICdVbmtub3duIGVycm9yJ31gO1xyXG4gICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgICAgIC5qb2luKCcgfCAnKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIEVycm9yKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBlcnIubWVzc2FnZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICBpZiAodHlwZW9mIGVyciA9PT0gJ3N0cmluZycpIHtcclxuICAgICAgICByZXR1cm4gZXJyO1xyXG4gICAgfVxyXG4gICAgdHJ5IHtcclxuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoZXJyKTtcclxuICAgIH0gY2F0Y2gge1xyXG4gICAgICAgIHJldHVybiBTdHJpbmcoZXJyKTtcclxuICAgIH1cclxufVxyXG5cclxuLyoqIFRocm93biB3aGVuIHRoZSByZWZlcmVuY2VkIFMzIHNvdXJjZSBmaWxlIGRvZXNuJ3QgZXhpc3QgKG9ycGhhbmVkIERCIHJlZmVyZW5jZSDigJRcclxuICogIGUuZy4gdGhlIGZpbGUgd2FzIGRlbGV0ZWQgb3IgcmVuYW1lZCBvbiBTMyB3aXRob3V0IHVwZGF0aW5nIHRoZSBkYXRhYmFzZSkuXHJcbiAqICBLZXB0IGRpc3RpbmN0IGZyb20gb3RoZXIgY29weSBmYWlsdXJlcyBzbyB0aGUgY2FsbGluZyBsb29wIGNhbiBsb2cgYSBjbGVhcixcclxuICogIHNwZWNpZmljIG1lc3NhZ2UgYW5kIHNraXAgdGhlIHdob2xlIGl0ZW0gaW5zdGVhZCBvZiBhIGdlbmVyaWMgZXJyb3IuICovXHJcbmNsYXNzIE1pc3NpbmdTM0ZpbGVFcnJvciBleHRlbmRzIEVycm9yIHtcclxuICAgIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSBzb3VyY2VLZXk6IHN0cmluZywgcHVibGljIHJlYWRvbmx5IGNvbnRleHRMYWJlbDogc3RyaW5nKSB7XHJcbiAgICAgICAgc3VwZXIoYFNvdXJjZSBmaWxlIG1pc3Npbmcgb24gUzM6IFwiJHtzb3VyY2VLZXl9XCIgKCR7Y29udGV4dExhYmVsfSlgKTtcclxuICAgICAgICB0aGlzLm5hbWUgPSAnTWlzc2luZ1MzRmlsZUVycm9yJztcclxuICAgIH1cclxufVxyXG5cclxuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiAncm9vdCcgfSlcclxuZXhwb3J0IGNsYXNzIE1hdHRlcnBvcnRUYWdDb3B5U2VydmljZSB7XHJcblxyXG4gICAgLy8gRW1pdHMgcHJvZ3Jlc3MgdXBkYXRlcyBkdXJpbmcgY29weVRhZ3NGcm9tVmlzaXQoKTsgbnVsbCB3aGVuIGlkbGVcclxuICAgIHB1YmxpYyBjb3B5UHJvZ3Jlc3MkOiBCZWhhdmlvclN1YmplY3Q8Q29weVByb2dyZXNzIHwgbnVsbD4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0PENvcHlQcm9ncmVzcyB8IG51bGw+KG51bGwpO1xyXG5cclxuICAgIC8vIEVtaXRzIHRoZSBhY2N1bXVsYXRlZCBsb2cgbGluZXMgZHVyaW5nIGNvcHlUYWdzRnJvbVZpc2l0KCk7IFtdIHdoZW4gaWRsZVxyXG4gICAgcHVibGljIGNvcHlMb2ckOiBCZWhhdmlvclN1YmplY3Q8Q29weUxvZ0VudHJ5W10+ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxDb3B5TG9nRW50cnlbXT4oW10pO1xyXG5cclxuICAgIHByaXZhdGUgc3BNb2R1bGU6IFNwTW9kdWxlO1xyXG4gICAgcHJpdmF0ZSBsb2c6IENvcHlMb2dFbnRyeVtdID0gW107XHJcbiAgICAvKiogVW5pcXVlLWlkIHNlcXVlbmNlIHNoYXJlZCBieSBldmVyeSBwZXJtYW5lbnQgKG5vbi1zdGVwKSBsb2cgbGluZSDigJQgZXJyb3JzIGFuZCBoZWFsZWQtaXRlbSBub3RpY2VzIGFsaWtlLiAqL1xyXG4gICAgcHJpdmF0ZSBsb2dTZXEgPSAwO1xyXG5cclxuICAgIC8vIC0tLS0gUGVyLXJ1biByZW1hcHBpbmcgc3RhdGUgKHJlc2V0IGJ5IHJlc2V0UnVuU3RhdGUoKSBhdCB0aGUgc3RhcnQgb2YgZXZlcnkgY29weSkgLS0tLVxyXG5cclxuICAgIC8qKiBzb3VyY2UgZWxlbWVudCBpZCAtPiBpZCBvZiBpdHMgY29weSBpbiB0aGUgdGFyZ2V0IHNwYWNlLiAqL1xyXG4gICAgcHJpdmF0ZSBlbGVtZW50SWRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XHJcblxyXG4gICAgLyoqIHNvdXJjZSBDb21tZW50IGlkIC0+IGlkIG9mIGl0cyBjb3B5LiBOZWVkZWQgdG8gcmVtYXAgUE9JLnRhZ0ltYWdlSUQsIHdoaWNoIGlzIGFcclxuICAgICAqICByZWZlcmVuY2UgdG8gYSBDb21tZW50IHJlY29yZCAoc2VlIHRoZSBzY2hlbWE6IFwiY29ubmVjdGlvbiB0byBjb21tZW50LmlkXCIpLiAqL1xyXG4gICAgcHJpdmF0ZSBjb21tZW50SWRzOiBNYXA8c3RyaW5nLCBzdHJpbmc+ID0gbmV3IE1hcCgpO1xyXG5cclxuICAgIC8vIEhhc2h0YWdzIGFyZSBzcGFjZS1zY29wZWQgcmVjb3Jkcywgc28gdGhlaXIgaWRzIGNhbiBuZXZlciBiZSBjYXJyaWVkIG92ZXIgYXMtaXM6IHRoZXlcclxuICAgIC8vIGFyZSBtYXRjaGVkIGJ5IE5BTUUgYWdhaW5zdCB0aGUgdGFyZ2V0IHNwYWNlLCBhbmQgdGhlIG1pc3Npbmcgb25lcyBhcmUgY3JlYXRlZCB0aGVyZS5cclxuICAgIC8vIFRoYXQgY3JlYXRpb24gaXMgZGVsaWJlcmF0ZWx5IGxhenkg4oCUIHNlZSByZXNvbHZlSGFzaHRhZ0lkcygpIOKAlCBhbmQgYXVkaXRlZCwgc28gYW5cclxuICAgIC8vIGludGVycnVwdGVkIGNvcHkgY2Fubm90IGxlYXZlIGtleXdvcmRzIGJlaGluZCB0aGF0IG5vIFBPSSByZWZlcmVuY2VzLlxyXG5cclxuICAgIC8qKiBzb3VyY2UgSGFzaHRhZyBpZCAtPiBpdHMgbmFtZS4gKi9cclxuICAgIHByaXZhdGUgc291cmNlSGFzaHRhZ05hbWVzOiBNYXA8c3RyaW5nLCBzdHJpbmc+ID0gbmV3IE1hcCgpO1xyXG5cclxuICAgIC8qKiBub3JtYWxpc2VkIGhhc2h0YWcgbmFtZSAtPiBpdHMgaWQgaW4gdGhlIFRBUkdFVCBzcGFjZSAocHJlLWV4aXN0aW5nIG9yIGp1c3QgY3JlYXRlZCkuICovXHJcbiAgICBwcml2YXRlIHRhcmdldEhhc2h0YWdJZHNCeU5hbWU6IE1hcDxzdHJpbmcsIHN0cmluZz4gPSBuZXcgTWFwKCk7XHJcblxyXG4gICAgLyoqIGlkcyBvZiB0aGUgaGFzaHRhZ3MgdGhpcyBydW4gY3JlYXRlZCBpbiB0aGUgdGFyZ2V0IHNwYWNlLiAqL1xyXG4gICAgcHJpdmF0ZSBjcmVhdGVkSGFzaHRhZ0lkczogU2V0PHN0cmluZz4gPSBuZXcgU2V0KCk7XHJcblxyXG4gICAgLyoqIGlkcyBvZiB0aGUgaGFzaHRhZ3MgYWN0dWFsbHkgcGVyc2lzdGVkIG9uIGEgc3VjY2Vzc2Z1bGx5IGNyZWF0ZWQgZmVhdHVyZS4gQW55dGhpbmcgaW5cclxuICAgICAqICBjcmVhdGVkSGFzaHRhZ0lkcyBidXQgYWJzZW50IGhlcmUgaXMgYW4gb3JwaGFuIGFuZCBpcyBkZWxldGVkIGF0IHRoZSBlbmQgb2YgdGhlIHJ1bi4gKi9cclxuICAgIHByaXZhdGUgdXNlZEhhc2h0YWdJZHM6IFNldDxzdHJpbmc+ID0gbmV3IFNldCgpO1xyXG5cclxuICAgIC8qKiBzb3VyY2UgaWRzIG9mIHRoZSBlbGVtZW50cyB3aG9zZSBQT0lzIHdlcmUgYWxyZWFkeSBjcmVhdGVkIGJ5IGFuIGVsZW1lbnQgcGhhc2UuXHJcbiAgICAgKiAgR3VhcmRzIHRoZSBzdGFuZGFsb25lIFBPSSBwaGFzZSBhZ2FpbnN0IGNyZWF0aW5nIGEgc2Vjb25kLCBpbXBvdmVyaXNoZWQgY29weS4gKi9cclxuICAgIHByaXZhdGUgaGFuZGxlZEVsZW1lbnRJZHM6IFNldDxzdHJpbmc+ID0gbmV3IFNldCgpO1xyXG5cclxuICAgIC8vIENvbW1lbnQgYXV0aG9yc2hpcDogYENvbW1lbnQub3duZXJJRGAgaXMgYSBmb3JlaWduIGtleSB0byBhIE1pc3Npb24sIGFuZCBhIE1pc3Npb24gaXNcclxuICAgIC8vIHNjb3BlZCB0byBPTkUgc3BhY2UgKHVzZXJJRCArIHNwYWNlSUQpLiBBIHNvdXJjZSBjb21tZW50J3Mgb3duZXJJRCB0aGVyZWZvcmUgcG9pbnRzIGF0XHJcbiAgICAvLyBub2JvZHkgaW4gdGhlIHRhcmdldCBzcGFjZSwgc28gaXQgaGFzIHRvIGJlIHRyYW5zbGF0ZWQgdG8gdGhlIE1pc3Npb24gb2YgdGhlIFNBTUUgdXNlclxyXG4gICAgLy8gdGhlcmUg4oCUIHNlZSByZXNvbHZlQ29tbWVudE93bmVySUQoKS5cclxuXHJcbiAgICAvKiogc291cmNlIE1pc3Npb24gaWQgLT4gaXRzIHVzZXJJRC4gKi9cclxuICAgIHByaXZhdGUgc291cmNlTWlzc2lvblVzZXJJZHM6IE1hcDxzdHJpbmcsIHN0cmluZz4gPSBuZXcgTWFwKCk7XHJcblxyXG4gICAgLyoqIHVzZXJJRCAtPiB0aGF0IHVzZXIncyBNaXNzaW9uIGlkIGluIHRoZSBUQVJHRVQgc3BhY2UgKG9ubHkgc2V0IHdoZW4gdGhleSBoYXZlIG9uZSkuICovXHJcbiAgICBwcml2YXRlIHRhcmdldE1pc3Npb25JZHNCeVVzZXJJZDogTWFwPHN0cmluZywgc3RyaW5nPiA9IG5ldyBNYXAoKTtcclxuXHJcbiAgICAvLyBEb21haW4gKGVxdWlwbWVudC90aWNrZXQvZmVhdHVyZS9QT0kgY2F0ZWdvcnkpIHJlc29sdXRpb24gbWlycm9ycyB0aGUgZXhhY3QgcnVsZSB0aGVcclxuICAgIC8vIGVkaXQgZm9ybXMgdXNlIHRvIHBvcHVsYXRlIHRoZWlyIG93biBjYXRlZ29yeSBkcm9wZG93biDigJRcclxuICAgIC8vIERvbWFpblNlcnZpY2UuZ2V0RG9tYWluc0Zvck9yZ0ZvclR5cGUodHlwZSwgbWlzc2lvbi5vcmdhbmlzYXRpb25JRCxcclxuICAgIC8vIG1pc3Npb24ub3JkZXJlZE9yZ2FuaXNhdGlvbklEKSDigJQga2V5ZWQgdG8gdGhlIE9QRVJBVE9SJ3Mgb3duIE1pc3Npb24gb24gZWFjaCBzcGFjZSxcclxuICAgIC8vIE5PVCB0byB0aGUgU3BhY2UncyBvd24gb3JnYW5pc2F0aW9uSUQuIFR3byBzcGFjZXMgaW4gZGlmZmVyZW50IG9yZ2FuaXNhdGlvbnMgY2FuXHJcbiAgICAvLyBzdGlsbCBzaGFyZSBhIGRvbWFpbiB0aHJvdWdoIHRoYXQgTWlzc2lvbiBsaW5rIChhbiBvcGVyYXRvciB3aG9zZSBtaXNzaW9uIG9uIHRoZVxyXG4gICAgLy8gdGFyZ2V0IHNwYWNlIGNhcnJpZXMgYW4gYG9yZGVyZWRPcmdhbmlzYXRpb25JRGAgbWF0Y2hpbmcgdGhlIGRvbWFpbidzIG93blxyXG4gICAgLy8gb3JnYW5pc2F0aW9uSUQgc2VlcyDigJQgYW5kIGNhbiByZXVzZSDigJQgaXQgZGlyZWN0bHkpLiBTZWUgcmVzb2x2ZURvbWFpbklEKCkuXHJcblxyXG4gICAgLyoqIGlkIC0+IERvbWFpbiwgZm9yIGV2ZXJ5IGRvbWFpbiB2aXNpYmxlIGZyb20gRUlUSEVSIHNwYWNlJ3Mgb3BlcmF0b3IgbWlzc2lvbiAoaXRzXHJcbiAgICAgKiAgb3JnYW5pc2F0aW9uSUQsIGl0cyBvcmRlcmVkT3JnYW5pc2F0aW9uSUQsIG9yIGdlbmVyaWMvbm8tb3JnYW5pc2F0aW9uIGRvbWFpbnMpIOKAlCBhXHJcbiAgICAgKiAgc3VwZXJzZXQgY292ZXJpbmcgd2hhdGV2ZXIgYSBzb3VyY2Ugb2JqZWN0J3MgZG9tYWluSUQgY291bGQgcG9pbnQgYXQuICovXHJcbiAgICBwcml2YXRlIGRvbWFpbnNCeUlkOiBNYXA8c3RyaW5nLCBEb21haW4+ID0gbmV3IE1hcCgpO1xyXG5cclxuICAgIC8qKiBvcmdhbmlzYXRpb25JRHMgdGhlIFRBUkdFVCBvcGVyYXRvcidzIG1pc3Npb24gY2FuIHNlZSBkb21haW5zIGZyb20uIEEgZG9tYWluIHdob3NlXHJcbiAgICAgKiAgb3duIG9yZ2FuaXNhdGlvbklEIGlzIGluIHRoaXMgc2V0IChvciBoYXMgbm9uZSBhdCBhbGwpIGlzIGFscmVhZHkgZGlyZWN0bHlcclxuICAgICAqICBzZWxlY3RhYmxlIGluIHRoZSB0YXJnZXQgc3BhY2UncyBvd24gZHJvcGRvd24sIHNvIGl0cyBpZCBpcyByZXVzZWQgdW5jaGFuZ2VkLiAqL1xyXG4gICAgcHJpdmF0ZSB0YXJnZXRWaXNpYmxlRG9tYWluT3JnSWRzOiBTZXQ8c3RyaW5nPiA9IG5ldyBTZXQoKTtcclxuXHJcbiAgICAvKiogYCR7dHlwZX06OiR7bm9ybWFsaXNlZCBuYW1lfWAgLT4gdGhhdCBkb21haW4ncyBpZCwgYW1vbmcgZG9tYWlucyB2aXNpYmxlIHRvIHRoZVxyXG4gICAgICogIFRBUkdFVCBvcGVyYXRvciDigJQgdXNlZCB0byBmaW5kIGFuIGVxdWl2YWxlbnQgd2hlbiB0aGUgZXhhY3QgaWQgaXNuJ3QgcmV1c2FibGUuICovXHJcbiAgICBwcml2YXRlIHRhcmdldERvbWFpbklkc0J5VHlwZUFuZE5hbWU6IE1hcDxzdHJpbmcsIHN0cmluZz4gPSBuZXcgTWFwKCk7XHJcblxyXG4gICAgLyoqIFRhcmdldCBzcGFjZSBpZCBvZiB0aGUgcnVuIGluIHByb2dyZXNzIOKAlCB1c2VkIHRvIHJlLWhvbWUgY29waWVkIHRhZyBpY29ucy4gKi9cclxuICAgIHByaXZhdGUgdGFyZ2V0U3BhY2VJZDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XHJcblxyXG4gICAgY29uc3RydWN0b3IoXHJcbiAgICAgICAgcHJpdmF0ZSBuYXZpZ2F0aW9uU2VydmljZTogTmF2aWdhdGlvblNlcnZpY2UsXHJcbiAgICAgICAgcHJpdmF0ZSB1c2VyU2VydmljZTogQmFzZVVzZXJTZXJ2aWNlLFxyXG4gICAgICAgIHByaXZhdGUgcG9pU2VydmljZTogUG9pU2VydmljZSxcclxuICAgICAgICBwcml2YXRlIHRpY2tldFNlcnZpY2U6IFRpY2tldHNTZXJ2aWNlLFxyXG4gICAgICAgIHByaXZhdGUgZXF1aXBtZW50U2VydmljZTogRXF1aXBtZW50U2VydmljZSxcclxuICAgICAgICBwcml2YXRlIG9iamVjdDNEU2VydmljZTogT2JqZWN0M0RTZXJ2aWNlLFxyXG4gICAgICAgIHByaXZhdGUgZmVhdHVyZVNlcnZpY2U6IEZlYXR1cmVTZXJ2aWNlLFxyXG4gICAgICAgIHByaXZhdGUgbWVhc3VyZW1lbnRTZXJ2aWNlOiBNZWFzdXJlbWVudFNlcnZpY2UsXHJcbiAgICAgICAgcHJpdmF0ZSBjb21tZW50U2VydmljZTogQ29tbWVudFNlcnZpY2UsXHJcbiAgICAgICAgcHJpdmF0ZSBoYXNodGFnU2VydmljZTogSGFzaHRhZ1NlcnZpY2UsXHJcbiAgICAgICAgcHJpdmF0ZSBtaXNzaW9uU2VydmljZTogTWlzc2lvblNlcnZpY2UsXHJcbiAgICAgICAgcHJpdmF0ZSBvcGVyYXRpb25TZXJ2aWNlOiBPcGVyYXRpb25TZXJ2aWNlLFxyXG4gICAgICAgIHByaXZhdGUgZG9tYWluU2VydmljZTogRG9tYWluU2VydmljZSxcclxuICAgICAgICBwcml2YXRlIHRyYW5zbGF0ZTogVHJhbnNsYXRlU2VydmljZVxyXG4gICAgKSB7XHJcbiAgICAgICAgdGhpcy5zcE1vZHVsZSA9IHVzZXJTZXJ2aWNlLmdldFNwTW9kdWxlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLy9cclxuICAgIC8vIC0tLS0tLS0tLS0gUHVibGljIEFQSSAtLS0tLS0tLS0tXHJcbiAgICAvL1xyXG5cclxuICAgIGFzeW5jIGNvcHlUYWdzRnJvbVZpc2l0KFxyXG4gICAgICAgIHNvdXJjZVNwYWNlSWQ6IHN0cmluZyxcclxuICAgICAgICB0YXJnZXRTcGFjZUlkOiBzdHJpbmcsXHJcbiAgICAgICAgbGFuZG1hcmtTb3VyY2VBOiBWZWMzLCBsYW5kbWFya1RhcmdldEE6IFZlYzMsXHJcbiAgICAgICAgbGFuZG1hcmtTb3VyY2VCOiBWZWMzLCBsYW5kbWFya1RhcmdldEI6IFZlYzNcclxuICAgICk6IFByb21pc2U8Ym9vbGVhbj4ge1xyXG4gICAgICAgIGxldCBlcnJvckNvdW50ID0gMDtcclxuICAgICAgICBsZXQgaGVhbGVkQ291bnQgPSAwO1xyXG4gICAgICAgIHRoaXMucmVzZXRMb2coKTtcclxuICAgICAgICB0aGlzLnJlc2V0UnVuU3RhdGUodGFyZ2V0U3BhY2VJZCk7XHJcblxyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBDb3B5aW5nIFRhZ3MgZnJvbSBzb3VyY2UgJHtzb3VyY2VTcGFjZUlkfSB0byB0YXJnZXQgJHt0YXJnZXRTcGFjZUlkfWApO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5zZXRTdGVwUHJvZ3Jlc3MoJ2NvbGxlY3RpbmcnLCAnY29sbGVjdGluZycsIDApO1xyXG4gICAgICAgICAgICB0aGlzLmNvcHlQcm9ncmVzcyQubmV4dCh7XHJcbiAgICAgICAgICAgICAgICBwaGFzZTogJ2NvbGxlY3RpbmcnLFxyXG4gICAgICAgICAgICAgICAgcHJvY2Vzc2VkSW5QaGFzZTogMCwgdG90YWxJblBoYXNlOiAwLFxyXG4gICAgICAgICAgICAgICAgcHJvY2Vzc2VkT3ZlcmFsbDogMCwgdG90YWxPdmVyYWxsOiAwLFxyXG4gICAgICAgICAgICAgICAgcGVyY2VudDogMCwgZXJyb3JDb3VudDogMCwgaGVhbGVkQ291bnQ6IDBcclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICBjb25zdCB0YXJnZXRNaXNzaW9uID0gdGhpcy51c2VyU2VydmljZS5jdXJyZW50TWlzc2lvbih0YXJnZXRTcGFjZUlkKTtcclxuICAgICAgICAgICAgY29uc3QgdGFyZ2V0TWlzc2lvbklkID0gdGFyZ2V0TWlzc2lvbiA/IHRhcmdldE1pc3Npb24uaWQgOiBudWxsO1xyXG5cclxuICAgICAgICAgICAgY29uc3QgdHJhbnNmb3JtOiBSaWdpZFRyYW5zZm9ybSA9IGNvbXB1dGVSaWdpZFRyYW5zZm9ybShcclxuICAgICAgICAgICAgICAgIGxhbmRtYXJrU291cmNlQSwgbGFuZG1hcmtUYXJnZXRBLFxyXG4gICAgICAgICAgICAgICAgbGFuZG1hcmtTb3VyY2VCLCBsYW5kbWFya1RhcmdldEJcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgY29uc29sZS5sb2coJ1JpZ2lkIHRyYW5zZm9ybSBjb21wdXRlZDonLCB7XHJcbiAgICAgICAgICAgICAgICByb3RhdGlvbllEZWc6IHRyYW5zZm9ybS5yb3RhdGlvbllSYWQgKiAoMTgwIC8gTWF0aC5QSSksXHJcbiAgICAgICAgICAgICAgICByZWZTb3VyY2U6IHRyYW5zZm9ybS5yZWZTb3VyY2UsXHJcbiAgICAgICAgICAgICAgICByZWZUYXJnZXQ6IHRyYW5zZm9ybS5yZWZUYXJnZXRcclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICBjb25zdCBzb3VyY2VTd2VlcElkcyA9IGF3YWl0IHRoaXMubmF2aWdhdGlvblNlcnZpY2UuZ2V0QWxsb3dlZFN3ZWVwc0lEc0ZvclVzZXJJblNwYWNlKHNvdXJjZVNwYWNlSWQpO1xyXG4gICAgICAgICAgICBjb25zdCB0YXJnZXRTd2VlcElkcyA9IGF3YWl0IHRoaXMubmF2aWdhdGlvblNlcnZpY2UuZ2V0QWxsb3dlZFN3ZWVwc0lEc0ZvclVzZXJJblNwYWNlKHRhcmdldFNwYWNlSWQpO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5zZXRTdGVwUHJvZ3Jlc3MoJ2NvbGxlY3RpbmcnLCAnY29sbGVjdGluZycsIDMwKTtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IFtzb3VyY2VOYXZQb3NpdGlvbnMsIHRhcmdldE5hdlBvc2l0aW9uc10gPSBhd2FpdCBQcm9taXNlLmFsbChbXHJcbiAgICAgICAgICAgICAgICB0aGlzLmJ1aWxkTmF2aWdhdGlvblBvc2l0aW9uTWFwKHNvdXJjZVNwYWNlSWQsIHNvdXJjZVN3ZWVwSWRzKSxcclxuICAgICAgICAgICAgICAgIHRoaXMuYnVpbGROYXZpZ2F0aW9uUG9zaXRpb25NYXAodGFyZ2V0U3BhY2VJZCwgdGFyZ2V0U3dlZXBJZHMpXHJcbiAgICAgICAgICAgIF0pO1xyXG5cclxuICAgICAgICAgICAgY29uc3QgZWxlbWVudElkcyA9IHRoaXMuZWxlbWVudElkcztcclxuXHJcbiAgICAgICAgICAgIGxldCBzb3VyY2VUaWNrZXRzOiBUaWNrZXRbXSA9IFtdO1xyXG4gICAgICAgICAgICBsZXQgc291cmNlRXF1aXBtZW50czogRXF1aXBtZW50W10gPSBbXTtcclxuICAgICAgICAgICAgbGV0IHRhcmdldFRpY2tldHM6IFRpY2tldFtdID0gW107XHJcbiAgICAgICAgICAgIGxldCB0YXJnZXRFcXVpcG1lbnRzOiBFcXVpcG1lbnRbXSA9IFtdO1xyXG4gICAgICAgICAgICBsZXQgc291cmNlTWVhc3VyZW1lbnRzOiBNZWFzdXJlbWVudFtdID0gW107XHJcbiAgICAgICAgICAgIGxldCB0YXJnZXRNZWFzdXJlbWVudHM6IE1lYXN1cmVtZW50W10gPSBbXTtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLnNwTW9kdWxlID09IFNwTW9kdWxlLklNTU8pIHtcclxuICAgICAgICAgICAgICAgIHNvdXJjZVRpY2tldHMgPSBhd2FpdCB0aGlzLnRpY2tldFNlcnZpY2UuZ2V0VGlja2V0c0J5U3BhY2Uoc291cmNlU3BhY2VJZCk7XHJcbiAgICAgICAgICAgICAgICBzb3VyY2VFcXVpcG1lbnRzID0gYXdhaXQgdGhpcy5lcXVpcG1lbnRTZXJ2aWNlLmdldEVxdWlwbWVudHNGb3JTcGFjZShzb3VyY2VTcGFjZUlkKTtcclxuICAgICAgICAgICAgICAgIHRhcmdldFRpY2tldHMgPSBhd2FpdCB0aGlzLnRpY2tldFNlcnZpY2UuZ2V0VGlja2V0c0J5U3BhY2UodGFyZ2V0U3BhY2VJZCk7XHJcbiAgICAgICAgICAgICAgICB0YXJnZXRFcXVpcG1lbnRzID0gYXdhaXQgdGhpcy5lcXVpcG1lbnRTZXJ2aWNlLmdldEVxdWlwbWVudHNGb3JTcGFjZSh0YXJnZXRTcGFjZUlkKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgdGhpcy5zZXRTdGVwUHJvZ3Jlc3MoJ2NvbGxlY3RpbmcnLCAnY29sbGVjdGluZycsIDU1KTtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IHNvdXJjZU9iamVjdHMzRCA9IGF3YWl0IHRoaXMub2JqZWN0M0RTZXJ2aWNlLmdldE9iamVjdHMzREJ5U3BhY2Uoc291cmNlU3BhY2VJZCk7XHJcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldE9iamVjdHMzRCA9IGF3YWl0IHRoaXMub2JqZWN0M0RTZXJ2aWNlLmdldE9iamVjdHMzREJ5U3BhY2UodGFyZ2V0U3BhY2VJZCk7XHJcblxyXG4gICAgICAgICAgICAvLyBQYWdpbmF0ZWQ6IGEgc3BhY2Ugcm91dGluZWx5IGhvbGRzIG1vcmUgdGhhbiB0aGUgMTAwIGZlYXR1cmVzIGEgc2luZ2xlIEFwcFN5bmNcclxuICAgICAgICAgICAgLy8gcGFnZSByZXR1cm5zLCBhbmQgdGhlIHRhaWwgd2FzIHNpbGVudGx5IGRyb3BwZWQuXHJcbiAgICAgICAgICAgIC8vXHJcbiAgICAgICAgICAgIC8vIFRoZSBzb3VyY2UgbGlzdCBrZWVwcyB0aGUgaGlzdG9yaWNhbCBcInNraXAgd2hhdCB0aGUgb3BlcmF0b3IgYXJjaGl2ZWRcIiBydWxlLCBzb1xyXG4gICAgICAgICAgICAvLyB0aGUgc2V0IG9mIGNvcGllZCBmZWF0dXJlcyBkb2VzIG5vdCBjaGFuZ2Ug4oCUIGJ1dCB0aGUgY2hlY2sgaXMgbm93IG51bGwtc2FmZTpcclxuICAgICAgICAgICAgLy8gRmVhdHVyZVNlcnZpY2UuaXNBcmNoaXZlZCgpIGRlcmVmZXJlbmNlcyBjdXJyZW50TWlzc2lvbihzcGFjZUlEKS5pZCBhbmQgdGhyZXcgYVxyXG4gICAgICAgICAgICAvLyBUeXBlRXJyb3Igd2hlbiB0aGUgb3BlcmF0b3IgaGFkIG5vIG1pc3Npb24gb24gdGhlIHNvdXJjZSBzcGFjZSAodGhlIGNvbW1vbiBjYXNlXHJcbiAgICAgICAgICAgIC8vIGZvciBhbiBhcmNoaXZlZCB2MSBzcGFjZSksIGFib3J0aW5nIHRoZSB3aG9sZSBjb3B5LlxyXG4gICAgICAgICAgICAvLyBUaGUgdGFyZ2V0IGxpc3QgaXMgTk9UIGZpbHRlcmVkOiBpdCBvbmx5IGZlZWRzIGR1cGxpY2F0ZSBkZXRlY3Rpb24sIGFuZCBhblxyXG4gICAgICAgICAgICAvLyBhcmNoaXZlZCBmZWF0dXJlIGlzIHN0aWxsIGEgZmVhdHVyZSB0aGF0IGV4aXN0cyB0aGVyZS5cclxuICAgICAgICAgICAgY29uc3Qgc291cmNlRmVhdHVyZXMgPSAoYXdhaXQgdGhpcy5mZWF0dXJlU2VydmljZS5nZXRBbGxGZWF0dXJlc0J5U3BhY2VSYXcoc291cmNlU3BhY2VJZCkpXHJcbiAgICAgICAgICAgICAgICAuZmlsdGVyKGZlYXR1cmUgPT4gIXRoaXMuaXNBcmNoaXZlZEZvck9wZXJhdG9yKGZlYXR1cmUsIHNvdXJjZVNwYWNlSWQpKTtcclxuICAgICAgICAgICAgY29uc3QgdGFyZ2V0RmVhdHVyZXMgPSBhd2FpdCB0aGlzLmZlYXR1cmVTZXJ2aWNlLmdldEFsbEZlYXR1cmVzQnlTcGFjZVJhdyh0YXJnZXRTcGFjZUlkKTtcclxuXHJcbiAgICAgICAgICAgIHRoaXMuc2V0U3RlcFByb2dyZXNzKCdjb2xsZWN0aW5nJywgJ2NvbGxlY3RpbmcnLCA3NSk7XHJcblxyXG4gICAgICAgICAgICAvLyBLZXl3b3JkczogaW5kZXggYm90aCB2b2NhYnVsYXJpZXMgbm93IChyZWFkLW9ubHkpLiBUaGUga2V5d29yZHMgdGhlIHRhcmdldCBzcGFjZVxyXG4gICAgICAgICAgICAvLyBpcyBtaXNzaW5nIGFyZSBjcmVhdGVkIGxhdGVyLCBQT0kgYnkgUE9JLCBvbmx5IGZvciB0aG9zZSBhY3R1YWxseSB1c2VkLlxyXG4gICAgICAgICAgICBhd2FpdCB0aGlzLmxvYWRIYXNodGFnSW5kZXgoc291cmNlU3BhY2VJZCwgdGFyZ2V0U3BhY2VJZCk7XHJcblxyXG4gICAgICAgICAgICAvLyBNaXNzaW9uczogaW5kZXggYm90aCBzcGFjZXMgbm93IChyZWFkLW9ubHkpLCBzbyBjb3BpZWQgY29tbWVudHMgY2FuIGNyZWRpdFxyXG4gICAgICAgICAgICAvLyB0aGVpciByZWFsIGF1dGhvciBpbnN0ZWFkIG9mIHdob2V2ZXIgaXMgcnVubmluZyB0aGUgY29weS5cclxuICAgICAgICAgICAgYXdhaXQgdGhpcy5sb2FkTWlzc2lvbkluZGV4KHNvdXJjZVNwYWNlSWQsIHRhcmdldFNwYWNlSWQpO1xyXG5cclxuICAgICAgICAgICAgLy8gRG9tYWluczogaW5kZXggZXZlcnkgZG9tYWluIGVpdGhlciBvcGVyYXRvcidzIG1pc3Npb24gY2FuIHNlZSAocmVhZC1vbmx5KSwgc29cclxuICAgICAgICAgICAgLy8gYSBjYXRlZ29yeSBzdXJ2aXZlcyBhIGNvcHkgYWNyb3NzIHR3byBESUZGRVJFTlQgb3JnYW5pc2F0aW9ucyB3aGVuZXZlciBpdFxyXG4gICAgICAgICAgICAvLyBnZW51aW5lbHkgd291bGQgYmUgc2VsZWN0YWJsZSBpbiB0aGUgdGFyZ2V0IHNwYWNlJ3Mgb3duIGRyb3Bkb3duIOKAlCBzZWVcclxuICAgICAgICAgICAgLy8gbG9hZERvbWFpbkluZGV4KCkgZm9yIHdoeSB0aGlzIGlzIGtleWVkIHRvIE1pc3Npb24sIG5vdCB0byB0aGUgU3BhY2UgaXRzZWxmLlxyXG4gICAgICAgICAgICBhd2FpdCB0aGlzLmxvYWREb21haW5JbmRleChzb3VyY2VTcGFjZUlkLCB0YXJnZXRTcGFjZUlkKTtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLnNwTW9kdWxlID09IFNwTW9kdWxlLklNTU8pIHtcclxuICAgICAgICAgICAgICAgIHNvdXJjZU1lYXN1cmVtZW50cyA9IGF3YWl0IHRoaXMubWVhc3VyZW1lbnRTZXJ2aWNlLmdldE1lYXN1cmVtZW50c0ZvclNwYWNlRm9yVXNlcihzb3VyY2VTcGFjZUlkKTtcclxuICAgICAgICAgICAgICAgIHRhcmdldE1lYXN1cmVtZW50cyA9IGF3YWl0IHRoaXMubWVhc3VyZW1lbnRTZXJ2aWNlLmdldE1lYXN1cmVtZW50c0ZvclNwYWNlRm9yVXNlcih0YXJnZXRTcGFjZUlkKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgdGhpcy5zZXRTdGVwUHJvZ3Jlc3MoJ2NvbGxlY3RpbmcnLCAnY29sbGVjdGluZycsIDkwKTtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IHNvdXJjZVBvaXNBbGwgPSBhd2FpdCB0aGlzLnBvaVNlcnZpY2UuZ2V0UG9pc0J5TWF0dGVycG9ydFN3ZWVwcyhzb3VyY2VTd2VlcElkcyk7XHJcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldFBvaXNBbGwgPSBhd2FpdCB0aGlzLnBvaVNlcnZpY2UuZ2V0UG9pc0J5TWF0dGVycG9ydFN3ZWVwcyh0YXJnZXRTd2VlcElkcyk7XHJcblxyXG4gICAgICAgICAgICAvLyBBIFBPSSBpcyBcIm93bmVkXCIgYnkgYW4gZWxlbWVudCAodGlja2V0LCBlcXVpcG1lbnQsIDNEIG9iamVjdCwgZmVhdHVyZSwgbWVhc3VyZW1lbnQpXHJcbiAgICAgICAgICAgIC8vIHdoZW4gaXRzIGVsZW1lbnRJRCBwb2ludHMgYXQgb25lLiBUaG9zZSBQT0lzIGFyZSBjcmVhdGVkIGJ5IHRoZWlyIGVsZW1lbnQncyBwaGFzZSxcclxuICAgICAgICAgICAgLy8gd2hpY2ggaXMgdGhlIG9ubHkgcGxhY2UgdGhhdCBrbm93cyB0aGUgZWxlbWVudCdzIE5FVyBpZCDigJQgc28gdGhleSBtdXN0IGJlIGV4Y2x1ZGVkXHJcbiAgICAgICAgICAgIC8vIGZyb20gdGhlIHN0YW5kYWxvbmUgcGhhc2UsIG90aGVyd2lzZSBldmVyeSBmZWF0dXJlIGVuZHMgdXAgd2l0aCB0d28gUE9Jczogb25lXHJcbiAgICAgICAgICAgIC8vIGNvcnJlY3RseSBsaW5rZWQgYnV0IHN0cmlwcGVkIG9mIGl0cyB0YWcgbWV0YWRhdGEsIGFuZCBvbmUgY2FycnlpbmcgdGhlIG1ldGFkYXRhXHJcbiAgICAgICAgICAgIC8vIGJ1dCBzdGlsbCBwb2ludGluZyBhdCB0aGUgc291cmNlIHNwYWNlJ3MgZWxlbWVudC5cclxuICAgICAgICAgICAgLy9cclxuICAgICAgICAgICAgLy8gT3duZXJzaGlwIGlzIHJlY29nbmlzZWQgYnkgVFdPIGluZGVwZW5kZW50IGNyaXRlcmlhLCBhbmQgZWl0aGVyIG9uZSBpcyBlbm91Z2ggdG9cclxuICAgICAgICAgICAgLy8ga2VlcCBhIFBPSSBvdXQgb2YgdGhlIHN0YW5kYWxvbmUgcGhhc2U6XHJcbiAgICAgICAgICAgIC8vXHJcbiAgICAgICAgICAgIC8vICAtIGl0cyB0eXBlIGlzIG9uZSBhbiBlbGVtZW50IHBoYXNlIGlzIHJlc3BvbnNpYmxlIGZvci4gVGhpcyBpcyB0aGUgaGlzdG9yaWNhbFxyXG4gICAgICAgICAgICAvLyAgICBydWxlIGFuZCBpdCBtdXN0IGJlIGtlcHQ6IGEgUE9JIG9mIHRoYXQgdHlwZSB3aG9zZSBlbGVtZW50IHdhcyBOT1QgY29sbGVjdGVkXHJcbiAgICAgICAgICAgIC8vICAgIChkZWxldGVkIHRpY2tldCwgZXF1aXBtZW50IG91dHNpZGUgdGhlIGN1cnJlbnQgZmlsdGVyLCAuLi4pIGlzIGFuIG9ycGhhbiwgYW5kXHJcbiAgICAgICAgICAgIC8vICAgIGNvcHlpbmcgaXQgc3RhbmRhbG9uZSB3b3VsZCByZWNyZWF0ZSBpdCB3aXRoIGFuIGVsZW1lbnRJRCBzdGlsbCBwb2ludGluZyBpbnRvXHJcbiAgICAgICAgICAgIC8vICAgIHRoZSBzb3VyY2Ugc3BhY2Ug4oCUIGFuIG9ycGhhbiB0aGUgcHJldmlvdXMgdmVyc2lvbiBjb3JyZWN0bHkgcmVmdXNlZCB0byBjb3B5LlxyXG4gICAgICAgICAgICAvLyAgLSBpdHMgZWxlbWVudElEIGJlbG9uZ3MgdG8gYW4gZWxlbWVudCB3ZSBhY3R1YWxseSBjb2xsZWN0ZWQuIFRoaXMgaXMgdGhlIGFkZGVkXHJcbiAgICAgICAgICAgIC8vICAgIHJ1bGUsIG5lZWRlZCBiZWNhdXNlIHRoZSB0eXBlIGFsb25lIGlzIG5vdCBhIHJlbGlhYmxlIGRpc2NyaW1pbmF0b3I6IGhpc3RvcmljYWxcclxuICAgICAgICAgICAgLy8gICAgZGF0YSBhbHNvIGhvbGRzIElORk9STUFUSU9OL1JPT00gUE9JcyBib3VuZCB0byBhIGZlYXR1cmUsIHdoaWNoIHRoZSB0eXBlIHRlc3RcclxuICAgICAgICAgICAgLy8gICAgbGV0cyB0aHJvdWdoIGFuZCB3aGljaCB3b3VsZCBlbmQgdXAgZHVwbGljYXRlZC5cclxuICAgICAgICAgICAgY29uc3QgaGFuZGxlZFBvaVR5cGVzID0gbmV3IFNldDxzdHJpbmc+KFtcclxuICAgICAgICAgICAgICAgIFBvaVR5cGUuVElDS0VULCBQb2lUeXBlLkVRVUlQTUVOVCwgUG9pVHlwZS5EQVRBLCBQb2lUeXBlLkRFU0ssXHJcbiAgICAgICAgICAgICAgICBQb2lUeXBlLk9CSkVDVDNELCBQb2lUeXBlLk1FQVNVUkVcclxuICAgICAgICAgICAgXSk7XHJcblxyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IG93bmVyIG9mIFsuLi5zb3VyY2VUaWNrZXRzLCAuLi5zb3VyY2VFcXVpcG1lbnRzLCAuLi5zb3VyY2VPYmplY3RzM0QsIC4uLnNvdXJjZUZlYXR1cmVzXSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKG93bmVyPy5pZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaGFuZGxlZEVsZW1lbnRJZHMuYWRkKG93bmVyLmlkKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IG1lYXN1cmVtZW50IG9mIHNvdXJjZU1lYXN1cmVtZW50cykge1xyXG4gICAgICAgICAgICAgICAgLy8gYSBtZWFzdXJlbWVudCBQT0kgaXMgYm91bmQgdG8gdGhlIG1lYXN1cmVtZW50J3MgQ29tbWVudCwgbm90IHRvIHRoZSBtZWFzdXJlbWVudFxyXG4gICAgICAgICAgICAgICAgaWYgKG1lYXN1cmVtZW50Py5jb21tZW50Py5pZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaGFuZGxlZEVsZW1lbnRJZHMuYWRkKG1lYXN1cmVtZW50LmNvbW1lbnQuaWQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCBpc093bmVkQnlBbkVsZW1lbnQgPSAocG9pOiBQT0kpID0+XHJcbiAgICAgICAgICAgICAgICBoYW5kbGVkUG9pVHlwZXMuaGFzKHBvaS50eXBlIGFzIHN0cmluZylcclxuICAgICAgICAgICAgICAgIHx8ICghIXBvaS5lbGVtZW50SUQgJiYgdGhpcy5oYW5kbGVkRWxlbWVudElkcy5oYXMocG9pLmVsZW1lbnRJRCkpO1xyXG5cclxuICAgICAgICAgICAgY29uc3Qgc291cmNlUG9pcyA9IHNvdXJjZVBvaXNBbGwuZmlsdGVyKHAgPT4gIWlzT3duZWRCeUFuRWxlbWVudChwKSk7XHJcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldFBvaXMgPSB0YXJnZXRQb2lzQWxsLmZpbHRlcihwID0+ICEhcCk7XHJcblxyXG4gICAgICAgICAgICB0aGlzLnNldFN0ZXBQcm9ncmVzcygnY29sbGVjdGluZycsICdjb2xsZWN0aW5nJywgMTAwKTtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IHRvdGFsT3ZlcmFsbCA9IHNvdXJjZVRpY2tldHMubGVuZ3RoICsgc291cmNlRXF1aXBtZW50cy5sZW5ndGggKyBzb3VyY2VQb2lzLmxlbmd0aFxyXG4gICAgICAgICAgICAgICAgKyBzb3VyY2VPYmplY3RzM0QubGVuZ3RoICsgc291cmNlRmVhdHVyZXMubGVuZ3RoICsgc291cmNlTWVhc3VyZW1lbnRzLmxlbmd0aDtcclxuICAgICAgICAgICAgbGV0IHByb2Nlc3NlZE92ZXJhbGwgPSAwO1xyXG5cclxuICAgICAgICAgICAgY29uc3QgZW1pdFByb2dyZXNzID0gKHBoYXNlOiBDb3B5UHJvZ3Jlc3NbJ3BoYXNlJ10sIHByb2Nlc3NlZEluUGhhc2U6IG51bWJlciwgdG90YWxJblBoYXNlOiBudW1iZXIpID0+IHtcclxuICAgICAgICAgICAgICAgIHRoaXMuY29weVByb2dyZXNzJC5uZXh0KHtcclxuICAgICAgICAgICAgICAgICAgICBwaGFzZSxcclxuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzZWRJblBoYXNlLFxyXG4gICAgICAgICAgICAgICAgICAgIHRvdGFsSW5QaGFzZSxcclxuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzZWRPdmVyYWxsLFxyXG4gICAgICAgICAgICAgICAgICAgIHRvdGFsT3ZlcmFsbCxcclxuICAgICAgICAgICAgICAgICAgICBwZXJjZW50OiB0b3RhbE92ZXJhbGwgPiAwID8gTWF0aC5yb3VuZCgocHJvY2Vzc2VkT3ZlcmFsbCAvIHRvdGFsT3ZlcmFsbCkgKiAxMDApIDogMCxcclxuICAgICAgICAgICAgICAgICAgICBlcnJvckNvdW50LCBoZWFsZWRDb3VudFxyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5zcE1vZHVsZSA9PSBTcE1vZHVsZS5JTU1PKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBUSUNLRVRTXHJcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNvdXJjZVRpY2tldHMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzb3VyY2VPYmogPSBzb3VyY2VUaWNrZXRzW2ldO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleGlzdGluZ01hdGNoID0gdGhpcy5maW5kRXhpc3RpbmcoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VPYmogYXMgYW55LCB0YXJnZXRUaWNrZXRzIGFzIGFueSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICh0OiBhbnkpID0+IFt0LnRpdGxlLCB0LmRlc2NyaXB0aW9uXVxyXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFleGlzdGluZ01hdGNoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByYXdTb3VyY2UgPSBzb3VyY2VPYmogYXMgYW55O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRpY2tldElucHV0OiBhbnkgPSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGU6IHJhd1NvdXJjZS50aXRsZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcmllbmRseUxhYmVsOiByYXdTb3VyY2UuZnJpZW5kbHlMYWJlbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0dXM6IHJhd1NvdXJjZS5zdGF0dXMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogcmF3U291cmNlLnR5cGUsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3JpdHk6IHJhd1NvdXJjZS5wcmlvcml0eSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogcmF3U291cmNlLmRlc2NyaXB0aW9uLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsOiByYXdTb3VyY2UubGV2ZWwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGE6IHJhd1NvdXJjZS5tZXRhZGF0YSB8fCBudWxsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYWQ6IHJhd1NvdXJjZS5yZWFkIHx8IG51bGwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvamVjdElEOiByYXdTb3VyY2UucHJvamVjdElEIHx8IG51bGwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYmxlbUNvZGU6IHJhd1NvdXJjZS5wcm9ibGVtQ29kZSB8fCBudWxsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1pc3Npb25zIGFyZSBwZXItc3BhY2U6IGEgc291cmNlIG1pc3Npb24gaWQgZGVzaWduYXRlcyBub2JvZHkgaW5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgdGFyZ2V0IHNwYWNlLiBDYXJyeWluZyB0aGUgbGlzdCBvdmVyIHdvdWxkIGxvb2sgbGlrZSByZWFsIGRhdGFcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB3aGlsZSBoaWRpbmcgdGhlIGl0ZW0gZnJvbSBubyBvbmUg4oCUIHJlc2V0IGl0LCBhcyBmb3IgZmVhdHVyZXMuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJjaGl2ZWRGb3JNaXNzaW9uSUQ6IG51bGwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BhY2VJRDogdGFyZ2V0U3BhY2VJZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1hcHBlZCBpbiB0aGUgc2Vjb25kIHBhc3MgYmVsb3csIG9uY2UgZXZlcnkgdGlja2V0IGV4aXN0cy5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRJRDogbnVsbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZXVzZWQgdW5jaGFuZ2VkIGluIHRoZSBzYW1lIG9yZ2FuaXNhdGlvbiwgbWF0Y2hlZCBieSBuYW1lXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWNyb3NzIHR3byDigJQgc2VlIHJlc29sdmVEb21haW5JRCgpLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbWFpbklEOiB0aGlzLnJlc29sdmVEb21haW5JRChyYXdTb3VyY2UuZG9tYWluSUQpLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG93bmVyTWlzc2lvbklEOiB0YXJnZXRNaXNzaW9uSWRcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3JlYXRlZE9iaiA9IGF3YWl0IHRoaXMudGlja2V0U2VydmljZS5jcmVhdGVUaWNrZXQodGlja2V0SW5wdXQpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjcmVhdGVkT2JqICYmIGNyZWF0ZWRPYmouaWQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50SWRzW3NvdXJjZU9iai5pZF0gPSBjcmVhdGVkT2JqLmlkO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEF0dGFjaG1lbnRzIG9mIHRoZSB0aWNrZXQgKHBob3RvcyBvZiB0aGUgaW5jaWRlbnQsIGRvY3VtZW50cy4uLikuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGV5IHdlcmUgbmV2ZXIgY29waWVkIGF0IGFsbDogYSBkdXBsaWNhdGVkIHRpY2tldCBhcnJpdmVkIHN0cmlwcGVkXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBvZiBldmVyeSBwaWVjZSBvZiBldmlkZW5jZSBhdHRhY2hlZCB0byBpdC5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjcmVhdGVkT2JqKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHNvdXJjZUNvbW1lbnRzOiBDb21tZW50W10gPSBbXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VDb21tZW50cyA9IGF3YWl0IHRoaXMuY29tbWVudFNlcnZpY2UuZ2V0QWxsQ29tbWVudHNGb3JUaWNrZXQoc291cmNlT2JqLmlkKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChjb21tZW50c0ZldGNoRXJyb3IpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBGYWxsaW5nIGJhY2sgdG8gdGhlIGVtYmVkZGVkIGNvbW1lbnQgbGlzdCBmb3IgdGlja2V0IFwiJHtyYXdTb3VyY2UudGl0bGV9XCI6YCwgY29tbWVudHNGZXRjaEVycm9yKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlQ29tbWVudHMgPSAoc291cmNlT2JqLmNvbW1lbnRzPy5pdGVtcyB8fCBbXSkuZmlsdGVyKGMgPT4gISFjKSBhcyBDb21tZW50W107XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHNvdXJjZUNvbW1lbnQgb2YgdGhpcy5vcmRlckNvbW1lbnRzRm9yQ29weShzb3VyY2VDb21tZW50cykpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNyZWF0ZWQgPSBhd2FpdCB0aGlzLmNvcHlDb21tZW50Rm9yVGlja2V0KFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZUNvbW1lbnQsIGNyZWF0ZWRPYmouaWQsIHRhcmdldFNwYWNlSWRcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3JlYXRlZD8uaWQgJiYgKHNvdXJjZUNvbW1lbnQgYXMgYW55KS5pZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tbWVudElkcy5zZXQoKHNvdXJjZUNvbW1lbnQgYXMgYW55KS5pZCwgY3JlYXRlZC5pZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGF0dGFjaG1lbnRFcnJvcikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgRXJyb3IgY29weWluZyBhdHRhY2htZW50IFwiJHtzb3VyY2VDb21tZW50Py50aXRsZX1cIiBmb3IgdGlja2V0IFwiJHtzb3VyY2VPYmo/LnRpdGxlfVwiOmAsIGF0dGFjaG1lbnRFcnJvcik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNvdW50Kys7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZ0NvcHlJdGVtRXJyb3IoYXR0YWNobWVudEVycm9yLCAnZXJyb3JGZWF0dXJlQXR0YWNobWVudCcsIHNvdXJjZUNvbW1lbnQ/LnRpdGxlIHx8IChzb3VyY2VDb21tZW50IGFzIGFueSk/LmlkLCB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZTogcmF3U291cmNlLnRpdGxlIHx8IHNvdXJjZU9iai5pZFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBzb3VyY2VQb2kgb2YgKHNvdXJjZU9iai5wb2lzPy5pdGVtcyB8fCBbXSkuZmlsdGVyKHAgPT4gISFwKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuY3JlYXRlQ29waWVkUG9pKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VQb2ksIGNyZWF0ZWRPYmouaWQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZU5hdlBvc2l0aW9ucywgdGFyZ2V0TmF2UG9zaXRpb25zLCB0cmFuc2Zvcm1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2FtZSByZWFzb25pbmcgYXMgdGhlIEVRVUlQTUVOVFMgcGhhc2UgKHNlZSB0aGUgY29tbWVudCB0aGVyZSk6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhIHRpY2tldCBtYXRjaGluZyB0aGlzIG9uZSBhbHJlYWR5IGV4aXN0cyBpbiB0aGUgdGFyZ2V0IHNwYWNlLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbW9zdCBsaWtlbHkgZnJvbSBhbiBlYXJsaWVyLCBpbmNvbXBsZXRlIHJ1bi4gRmlsbCBpbiB3aGF0ZXZlclxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWRlbnRpdHkgZmllbGQgaXQgaXMgbWlzc2luZyByYXRoZXIgdGhhbiBsZWF2aW5nIGl0IHVudG91Y2hlZC5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnRJZHNbc291cmNlT2JqLmlkXSA9IGV4aXN0aW5nTWF0Y2guaWQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBoZWFsZWRGaWVsZHMgPSBhd2FpdCB0aGlzLmhlYWxUaWNrZXRJZGVudGl0eShzb3VyY2VPYmogYXMgYW55LCBleGlzdGluZ01hdGNoIGFzIGFueSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaGVhbGVkRmllbGRzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFsZWRDb3VudCsrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9nSGVhbGVkSXRlbSgndGlja2V0SGVhbGVkJywgKHNvdXJjZU9iaiBhcyBhbnkpPy50aXRsZSB8fCBzb3VyY2VPYmo/LmlkLCBoZWFsZWRGaWVsZHMpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoaXRlbUVycm9yKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIGNvcHlpbmcgdGlja2V0IFwiJHtzb3VyY2VPYmo/LnRpdGxlfVwiIChpZDogJHtzb3VyY2VPYmo/LmlkfSk6YCwgaXRlbUVycm9yKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDb3VudCsrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZ0NvcHlJdGVtRXJyb3IoaXRlbUVycm9yLCAnZXJyb3JUaWNrZXQnLCBzb3VyY2VPYmo/LnRpdGxlIHx8IHNvdXJjZU9iaj8uaWQpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc2VkT3ZlcmFsbCsrO1xyXG4gICAgICAgICAgICAgICAgICAgIGVtaXRQcm9ncmVzcygndGlja2V0cycsIGkgKyAxLCBzb3VyY2VUaWNrZXRzLmxlbmd0aCk7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGN0ID0gc291cmNlVGlja2V0cy5sZW5ndGggPiAwID8gTWF0aC5yb3VuZCgoKGkgKyAxKSAvIHNvdXJjZVRpY2tldHMubGVuZ3RoKSAqIDEwMCkgOiAxMDA7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRTdGVwUHJvZ3Jlc3MoJ3RpY2tldHMnLCAndGlja2V0cycsIHBjdCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gU2Vjb25kIHBhc3M6IHJlc3RvcmUgdGhlIHRpY2tldCBoaWVyYXJjaHkuIGBwYXJlbnRJRGAgaGFkIHRvIGJlIG51bGxlZCBkdXJpbmdcclxuICAgICAgICAgICAgICAgIC8vIGNyZWF0aW9uICh0aGUgcGFyZW50IG1heSBub3QgaGF2ZSBleGlzdGVkIHlldCkgYW5kIHdhcyB0aGVuIG5ldmVyIHJlc3RvcmVkLCBzb1xyXG4gICAgICAgICAgICAgICAgLy8gZXZlcnkgc3ViLXRpY2tldCBjYW1lIG91dCBkZXRhY2hlZC4gU2FtZSBydWxlIGFzIGZvciBzdWItZXF1aXBtZW50czogYSBwYXJlbnRcclxuICAgICAgICAgICAgICAgIC8vIHdpdGggbm8gY29waWVkIGNvdW50ZXJwYXJ0IGlzIGRyb3BwZWQgcmF0aGVyIHRoYW4gbGVmdCBwb2ludGluZyBhdCB0aGUgc291cmNlXHJcbiAgICAgICAgICAgICAgICAvLyBzcGFjZSdzIHRpY2tldC5cclxuICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgc291cmNlT2JqIG9mIHNvdXJjZVRpY2tldHMpIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCByYXdTb3VyY2UgPSBzb3VyY2VPYmogYXMgYW55O1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld0lkID0gZWxlbWVudElkc1tzb3VyY2VPYmouaWRdO1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld1BhcmVudElkID0gcmF3U291cmNlLnBhcmVudElEID8gZWxlbWVudElkc1tyYXdTb3VyY2UucGFyZW50SURdIDogbnVsbDtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0lkICYmIG5ld1BhcmVudElkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnRpY2tldFNlcnZpY2UudXBkYXRlVGlja2V0KHsgaWQ6IG5ld0lkLCBwYXJlbnRJRDogbmV3UGFyZW50SWQgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKHBhcmVudEVycm9yKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciByZW1hcHBpbmcgdGhlIHBhcmVudCB0aWNrZXQgb2YgXCIke3NvdXJjZU9iaj8udGl0bGV9XCI6YCwgcGFyZW50RXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDb3VudCsrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2dDb3B5SXRlbUVycm9yKHBhcmVudEVycm9yLCAnZXJyb3JUaWNrZXQnLCBzb3VyY2VPYmo/LnRpdGxlIHx8IHNvdXJjZU9iaj8uaWQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIC8vIEVRVUlQTUVOVFMgKGlkZW50aXR5LCBQT0ksIFBIT1RPIGFuZCBOT1RFUy9kb2N1bWVudHMgYWxsIGNvcGllZCDigJQgZmlsZXNcclxuICAgICAgICAgICAgICAgIC8vIHBoeXNpY2FsbHkgZHVwbGljYXRlZCBpbiBTMyBmaXJzdCwgc28gdGhlIGNvcHkgc3RheXMgaW5kZXBlbmRlbnQgZnJvbSB0aGUgc291cmNlKVxyXG4gICAgICAgICAgICAgICAgLy9cclxuICAgICAgICAgICAgICAgIC8vIENBUkVGVUw6IHRoZSBFcXVpcG1lbnQgbW9kZWwgaGFzIE5PIGB0aXRsZWAgYW5kIE5PIGBkZXNjcmlwdGlvbmAgY29sdW1uLiBJdFxyXG4gICAgICAgICAgICAgICAgLy8gaWRlbnRpZmllcyBpdHNlbGYgd2l0aCBgbmFtZWAgKFN0cmluZyEg4oCUIHJlcXVpcmVkKSBhbmQgYW5ub3RhdGVzIGl0c2VsZiB3aXRoXHJcbiAgICAgICAgICAgICAgICAvLyBgYW5ub3RhdGlvbmAuIFJlYWRpbmcgYHJhd1NvdXJjZS50aXRsZWAgdGhlcmVmb3JlIGFsd2F5cyB5aWVsZGVkIHVuZGVmaW5lZCBhbmRcclxuICAgICAgICAgICAgICAgIC8vIHRoZSByZXF1aXJlZCBgbmFtZWAgd2FzIG5ldmVyIHNlbnQsIHdoaWNoIEFwcFN5bmMgcmVqZWN0ZWQgd2l0aFxyXG4gICAgICAgICAgICAgICAgLy8gXCJWYXJpYWJsZSAnaW5wdXQnIGhhcyBjb2VyY2VkIE51bGwgdmFsdWUgZm9yIE5vbk51bGwgdHlwZSAnU3RyaW5nISdcIi5cclxuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc291cmNlRXF1aXBtZW50cy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNvdXJjZU9iaiA9IHNvdXJjZUVxdWlwbWVudHNbaV07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEVxdWlwbWVudCBoYXMgbm8gYHRpdGxlYC9gZGVzY3JpcHRpb25gOiBpdCBpZGVudGlmaWVzIGl0c2VsZiBieSBuYW1lLCBhbmQgYnlcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2VyaWFsIG51bWJlciB3aGVuIG9uZSBpcyByZWNvcmRlZC5cclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXhpc3RpbmdNYXRjaCA9IHRoaXMuZmluZEV4aXN0aW5nKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlT2JqIGFzIGFueSwgdGFyZ2V0RXF1aXBtZW50cyBhcyBhbnksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZTogYW55KSA9PiBbZS5uYW1lLCBlLnNlcmlhbE51bWJlcl1cclxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZXhpc3RpbmdNYXRjaCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmF3U291cmNlID0gc291cmNlT2JqIGFzIGFueTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgY29waWVkUGhvdG9LZXk6IHN0cmluZyB8IG51bGwgPSBudWxsO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJhd1NvdXJjZS5waG90bykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcGllZFBob3RvS2V5ID0gYXdhaXQgdGhpcy5jb3B5UzNLZXlJZlByZXNlbnQocmF3U291cmNlLnBob3RvLCBgZXF1aXBtZW50IHBob3RvIFwiJHtyYXdTb3VyY2UubmFtZX1cImApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVxdWlwbWVudElucHV0OiBhbnkgPSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogcmF3U291cmNlLm5hbWUsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVW5saWtlIGV2ZXJ5IG90aGVyIG1vZGVsIHRoaXMgZmlsZSBjb3BpZXMsIEVxdWlwbWVudCBkZWNsYXJlc1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBjcmVhdGVkQXRgIGFzIGEgcGxhaW4gY2xpZW50LXNldHRhYmxlIGZpZWxkIHJhdGhlciB0aGFuIGFuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXBwU3luYy1tYW5hZ2VkIHRpbWVzdGFtcCAoc2VlIHNjaGVtYS5ncmFwaHFsKSDigJQgc28sIHVuaXF1ZWx5XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaGVyZSwgdGhlIG9yaWdpbmFsIGNvbW1pc3Npb25pbmcgZGF0ZSBjYW4gYWN0dWFsbHkgYmUga2VwdFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluc3RlYWQgb2YgdGhlIGNvcHkgc2lsZW50bHkgZ2V0dGluZyB0b2RheSdzIGRhdGUuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3JlYXRlZEF0OiByYXdTb3VyY2UuY3JlYXRlZEF0ID8/IG51bGwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbjogcmF3U291cmNlLmFubm90YXRpb24gPz8gbnVsbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0dXM6IHJhd1NvdXJjZS5zdGF0dXMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRnVsbCBpZGVudGl0eSBvZiB0aGUgZXF1aXBtZW50IOKAlCBhbGwgb2YgdGhlc2Ugd2VyZSBkcm9wcGVkXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFtaWx5OiByYXdTb3VyY2UuZmFtaWx5ID8/IG51bGwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2t1OiByYXdTb3VyY2Uuc2t1ID8/IG51bGwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VyaWFsTnVtYmVyOiByYXdTb3VyY2Uuc2VyaWFsTnVtYmVyID8/IG51bGwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFudWZhY3R1cmVyOiByYXdTb3VyY2UubWFudWZhY3R1cmVyID8/IG51bGwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zdGFsbERhdGU6IHJhd1NvdXJjZS5pbnN0YWxsRGF0ZSA/PyBudWxsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcnJhbnR5RW5kRGF0ZTogcmF3U291cmNlLndhcnJhbnR5RW5kRGF0ZSA/PyBudWxsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiByYXdTb3VyY2UubWV0YWRhdGEgPz8gbnVsbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0NyZWF0ZWRCeUFJOiByYXdTb3VyY2UuaXNDcmVhdGVkQnlBSSA/PyBudWxsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1pc3Npb25zIGFyZSBwZXItc3BhY2U6IGEgc291cmNlIG1pc3Npb24gaWQgZGVzaWduYXRlcyBub2JvZHkgaW5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgdGFyZ2V0IHNwYWNlLiBDYXJyeWluZyB0aGUgbGlzdCBvdmVyIHdvdWxkIGxvb2sgbGlrZSByZWFsIGRhdGFcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB3aGlsZSBoaWRpbmcgdGhlIGl0ZW0gZnJvbSBubyBvbmUg4oCUIHJlc2V0IGl0LCBhcyBmb3IgZmVhdHVyZXMuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJjaGl2ZWRGb3JNaXNzaW9uSUQ6IG51bGwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BhY2VJRDogdGFyZ2V0U3BhY2VJZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZXVzZWQgdW5jaGFuZ2VkIGluIHRoZSBzYW1lIG9yZ2FuaXNhdGlvbiwgbWF0Y2hlZCBieSBuYW1lXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWNyb3NzIHR3byDigJQgc2VlIHJlc29sdmVEb21haW5JRCgpLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbWFpbklEOiB0aGlzLnJlc29sdmVEb21haW5JRChyYXdTb3VyY2UuZG9tYWluSUQpLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBob3RvOiBjb3BpZWRQaG90b0tleSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBgc3ViZXF1aXBtZW50c0lEc2AgaXMgZGVsaWJlcmF0ZWx5IGFic2VudDogaXQgaXMgcmVtYXBwZWQgdG8gdGhlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY29waWVkIGVxdWlwbWVudHMgaW4gdGhlIHNlY29uZCBwYXNzLCBvbmNlIHRoZXkgYWxsIGV4aXN0LlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjcmVhdGVkT2JqOiBhbnkgPSBhd2FpdCB0aGlzLmVxdWlwbWVudFNlcnZpY2UuY3JlYXRlRXF1aXBtZW50KGVxdWlwbWVudElucHV0LCBudWxsLCBudWxsKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3JlYXRlZE9iaiAmJiBjcmVhdGVkT2JqLmlkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudElkc1tzb3VyY2VPYmouaWRdID0gY3JlYXRlZE9iai5pZDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDb3B5IG5vdGVzIChkb2N1bWVudHMsIHRlY2huaWNhbC9maW5hbmNpYWwvb3RoZXIvY29udHJhY3R1YWwvaW1hZ2Ugbm90ZXMpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3JlYXRlZE9iaiAmJiByYXdTb3VyY2Uubm90ZXM/Lml0ZW1zICYmIHJhd1NvdXJjZS5ub3Rlcy5pdGVtcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBzb3VyY2VOb3RlIG9mIHJhd1NvdXJjZS5ub3Rlcy5pdGVtcykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQSBub3RlIHdpdGhvdXQgYSBmaWxlIGlzIHN0aWxsIGEgbm90ZTogaXQgY2FycmllcyBhIHR5cGVcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFuZCBpdHMgc2lnbmF0dXJlL2V4cGlyeSBkYXRlcy4gU2tpcHBpbmcgaXQsIGFzIHdhcyBkb25lXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBiZWZvcmUsIHNpbGVudGx5IGRyb3BwZWQgdGhvc2UgcmVjb3JkcyBlbnRpcmVseS5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvcGllZEtleSA9IHNvdXJjZU5vdGUuYXR0YWNobWVudFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gYXdhaXQgdGhpcy5jb3B5UzNLZXlJZlByZXNlbnQoc291cmNlTm90ZS5hdHRhY2htZW50LCBgZXF1aXBtZW50IG5vdGUgZm9yIFwiJHtzb3VyY2VPYmo/Lm5hbWV9XCJgKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogbnVsbDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuZXF1aXBtZW50U2VydmljZS5jcmVhdGVOb3RlV2l0aEV4aXN0aW5nQXR0YWNobWVudChcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcmVhdGVkT2JqLmlkLCBjb3BpZWRLZXksIHNvdXJjZU5vdGUudHlwZSwgdGFyZ2V0TWlzc2lvbklkLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2lnbkRhdGU6IHNvdXJjZU5vdGUuc2lnbkRhdGUgPz8gbnVsbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwaXJhdGlvbkRhdGU6IHNvdXJjZU5vdGUuZXhwaXJhdGlvbkRhdGUgPz8gbnVsbFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKG5vdGVFcnJvcikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgRXJyb3IgY29weWluZyBub3RlIGZvciBlcXVpcG1lbnQgXCIke3NvdXJjZU9iaj8ubmFtZX1cIjpgLCBub3RlRXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDb3VudCsrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2dDb3B5SXRlbUVycm9yKG5vdGVFcnJvciwgJ2Vycm9yRXF1aXBtZW50Tm90ZScsIHNvdXJjZU9iaj8ubmFtZSB8fCBzb3VyY2VPYmo/LmlkLCB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXF1aXBtZW50OiBzb3VyY2VPYmo/Lm5hbWUgfHwgc291cmNlT2JqPy5pZFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBzb3VyY2VQb2kgb2YgKHNvdXJjZU9iai5wb2lzPy5pdGVtcyB8fCBbXSkuZmlsdGVyKHAgPT4gISFwKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuY3JlYXRlQ29waWVkUG9pKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VQb2ksIGNyZWF0ZWRPYmouaWQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZU5hdlBvc2l0aW9ucywgdGFyZ2V0TmF2UG9zaXRpb25zLCB0cmFuc2Zvcm1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQW4gZXF1aXBtZW50IG1hdGNoaW5nIHRoaXMgb25lIGFscmVhZHkgZXhpc3RzIGluIHRoZSB0YXJnZXQgc3BhY2Ug4oCUXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtb3N0IG9mdGVuIGJlY2F1c2UgYSBQUkVWSU9VUyBydW4gb2YgdGhpcyBjb3B5IGFscmVhZHkgY3JlYXRlZCBpdC5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoYXQgZWFybGllciBydW4gbWF5IGhhdmUgYmVlbiBpbnRlcnJ1cHRlZCwgb3IgaGl0IGEgYnVnIHRoYXQgaGFzXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBzaW5jZSBiZWVuIGZpeGVkIChtaXNzaW5nIGZhbWlseS9tYW51ZmFjdHVyZXIvZG9tYWluSUQvLi4uIHdlcmUgb25jZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZHJvcHBlZCBlbnRpcmVseSDigJQgc2VlIHRoZSBjb21tZW50IGFib3ZlKSwgbGVhdmluZyBhbiBlcXVpcG1lbnQgd2l0aFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXRzIGlkZW50aXR5IGZpZWxkcyBlbXB0eSBmb3JldmVyOiByZS1ydW5uaW5nIHRoZSBjb3B5IHVzZWQgdG8gc2tpcFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXQgb3V0cmlnaHQsIHNpbmNlIGl0IGFscmVhZHkgXCJleGlzdHNcIiwgc28gdGhlIGdhcCBjb3VsZCBuZXZlciBoZWFsLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlLXJ1bm5pbmcgdGhlIHRvb2wgbXVzdCBiZSBhYmxlIHRvIHJlcGFpciB0aGF0OiBhbnkgaWRlbnRpdHkgZmllbGRcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBleGlzdGluZyB0YXJnZXQgZXF1aXBtZW50IGlzIG1pc3NpbmcsIGFuZCB0aGUgc291cmNlIGhhcywgaXNcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZpbGxlZCBpbi4gRmllbGRzIHRoZSB0YXJnZXQgYWxyZWFkeSBjYXJyaWVzIGEgdmFsdWUgZm9yIGFyZSBsZWZ0XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB1bnRvdWNoZWQsIHNvIGEgbWFudWFsIGVkaXQgbWFkZSBpbiB0aGUgdGFyZ2V0IHNwYWNlIGlzIG5ldmVyXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBvdmVyd3JpdHRlbiBieSBhbiBvbGRlciBvciBkaWZmZXJlbnQgc291cmNlIHZhbHVlLiBOb3RlcyBhbmQgUE9JcyBhcmVcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5PVCByZS1jcmVhdGVkIGhlcmU6IHVubGlrZSBzY2FsYXIgZmllbGRzIHRoZXkgY2Fubm90IGJlIFwibWlzc2luZyB2cy5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHByZXNlbnRcIiBjaGVja2VkIHRoZSBzYW1lIHdheSwgYW5kIHJlLWFkZGluZyB0aGVtIG9uIGV2ZXJ5IHJlLXJ1biBvZlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYW4gYWxyZWFkeS1oZWFsdGh5IGNvcHkgd291bGQgZHVwbGljYXRlIHRoZW0uXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50SWRzW3NvdXJjZU9iai5pZF0gPSBleGlzdGluZ01hdGNoLmlkO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaGVhbGVkRmllbGRzID0gYXdhaXQgdGhpcy5oZWFsRXF1aXBtZW50SWRlbnRpdHkoc291cmNlT2JqIGFzIGFueSwgZXhpc3RpbmdNYXRjaCBhcyBhbnkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGhlYWxlZEZpZWxkcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhbGVkQ291bnQrKztcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZ0hlYWxlZEl0ZW0oJ2VxdWlwbWVudEhlYWxlZCcsIChzb3VyY2VPYmogYXMgYW55KT8ubmFtZSB8fCBzb3VyY2VPYmo/LmlkLCBoZWFsZWRGaWVsZHMpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoaXRlbUVycm9yKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIGNvcHlpbmcgZXF1aXBtZW50IFwiJHtzb3VyY2VPYmo/Lm5hbWV9XCIgKGlkOiAke3NvdXJjZU9iaj8uaWR9KTpgLCBpdGVtRXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNvdW50Kys7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9nQ29weUl0ZW1FcnJvcihpdGVtRXJyb3IsICdlcnJvckVxdWlwbWVudCcsIHNvdXJjZU9iaj8ubmFtZSB8fCBzb3VyY2VPYmo/LmlkKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3NlZE92ZXJhbGwrKztcclxuICAgICAgICAgICAgICAgICAgICBlbWl0UHJvZ3Jlc3MoJ2VxdWlwbWVudHMnLCBpICsgMSwgc291cmNlRXF1aXBtZW50cy5sZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBjdCA9IHNvdXJjZUVxdWlwbWVudHMubGVuZ3RoID4gMCA/IE1hdGgucm91bmQoKChpICsgMSkgLyBzb3VyY2VFcXVpcG1lbnRzLmxlbmd0aCkgKiAxMDApIDogMTAwO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RlcFByb2dyZXNzKCdlcXVpcG1lbnRzJywgJ2VxdWlwbWVudHMnLCBwY3QpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIC8vIFNlY29uZCBwYXNzOiByZW1hcCBzdWJlcXVpcG1lbnRzSURzIG9uIG5ld2x5IGNyZWF0ZWQgZXF1aXBtZW50cyB0byBwb2ludCB0b1xyXG4gICAgICAgICAgICAgICAgLy8gdGhlaXIgY29waWVkIGNvdW50ZXJwYXJ0cy4gSURzIHdpdGggbm8gY29waWVkIGNvdW50ZXJwYXJ0IChzb3VyY2UgZXF1aXBtZW50XHJcbiAgICAgICAgICAgICAgICAvLyB3YXNuJ3QgY29waWVkIOKAlCBlLmcuIGl0IGFscmVhZHkgZXhpc3RlZCBpbiB0YXJnZXQsIG9yIHdhcyBza2lwcGVkKSBhcmUgZHJvcHBlZFxyXG4gICAgICAgICAgICAgICAgLy8gcmF0aGVyIHRoYW4gbGVmdCBkYW5nbGluZyBvciBwb2ludGluZyBiYWNrIGF0IHRoZSBzb3VyY2Ugc3BhY2UncyBlcXVpcG1lbnQuXHJcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHNvdXJjZU9iaiBvZiBzb3VyY2VFcXVpcG1lbnRzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmF3U291cmNlID0gc291cmNlT2JqIGFzIGFueTtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdJZCA9IGVsZW1lbnRJZHNbc291cmNlT2JqLmlkXTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAobmV3SWQgJiYgcmF3U291cmNlLnN1YmVxdWlwbWVudHNJRHMgJiYgcmF3U291cmNlLnN1YmVxdWlwbWVudHNJRHMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZW1hcHBlZCA9IHJhd1NvdXJjZS5zdWJlcXVpcG1lbnRzSURzXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAubWFwKChzdWJJZDogc3RyaW5nKSA9PiBlbGVtZW50SWRzW3N1YklkXSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5maWx0ZXIoKGlkOiBzdHJpbmcgfCB1bmRlZmluZWQpID0+ICEhaWQpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlbWFwcGVkLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5lcXVpcG1lbnRTZXJ2aWNlLnVwZGF0ZUVxdWlwbWVudCh7IGlkOiBuZXdJZCwgc3ViZXF1aXBtZW50c0lEczogcmVtYXBwZWQgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChzdWJFcXVpcEVycm9yKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgRXJyb3IgcmVtYXBwaW5nIHN1Yi1lcXVpcG1lbnRzIGZvciBcIiR7c291cmNlT2JqPy5uYW1lfVwiOmAsIHN1YkVxdWlwRXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ291bnQrKztcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZ0NvcHlJdGVtRXJyb3Ioc3ViRXF1aXBFcnJvciwgJ2Vycm9yRXF1aXBtZW50U3ViRXF1aXAnLCBzb3VyY2VPYmo/Lm5hbWUgfHwgc291cmNlT2JqPy5pZCwge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcXVpcG1lbnQ6IHNvdXJjZU9iaj8ubmFtZSB8fCBzb3VyY2VPYmo/LmlkXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gT1BFUkFUSU9OUyDigJQgdGhlIFRpY2tldDwtPkVxdWlwbWVudCBqb2luIChkcml2ZXMgXCJUaWNrZXRzIGFjdHVlbHNcIiBvbiB0aGVcclxuICAgICAgICAgICAgICAgIC8vIGVxdWlwbWVudCBwYWdlIGFuZCB0aGUgbGlua2VkLWVxdWlwbWVudCBsaXN0IG9uIHRoZSB0aWNrZXQgcGFnZSkuIEJvdGggdGhlXHJcbiAgICAgICAgICAgICAgICAvLyBUSUNLRVRTIGFuZCBFUVVJUE1FTlRTIHBoYXNlcyBhYm92ZSBjb3B5IHRoZSByZWNvcmQgaXRzZWxmLCBidXQgbmVpdGhlciBvbmVcclxuICAgICAgICAgICAgICAgIC8vIHRvdWNoZXMgdGhpcyBqb2luIHRhYmxlLCBzbyBldmVyeSBsaW5rIGJldHdlZW4gYSBjb3BpZWQgdGlja2V0IGFuZCBhIGNvcGllZFxyXG4gICAgICAgICAgICAgICAgLy8gZXF1aXBtZW50IHdhcyBzaWxlbnRseSBkcm9wcGVkOiBib3RoIHNpZGVzIGV4aXN0ZWQgaW4gdGhlIHRhcmdldCBzcGFjZSwgYnV0XHJcbiAgICAgICAgICAgICAgICAvLyBwb2ludGluZyBhdCBub2JvZHkuXHJcbiAgICAgICAgICAgICAgICAvL1xyXG4gICAgICAgICAgICAgICAgLy8gUnVucyBhZnRlciBib3RoIHBoYXNlcywgb3ZlciBldmVyeSBTT1VSQ0UgdGlja2V0IHRoYXQgZW5kZWQgdXAgbWFwcGVkIGluXHJcbiAgICAgICAgICAgICAgICAvLyB0aGUgdGFyZ2V0IHNwYWNlIChmcmVzaGx5IGNyZWF0ZWQgT1IgaGVhbGVkIOKAlCBlbGVtZW50SWRzIGNvdmVycyBib3RoKSwgc28gYVxyXG4gICAgICAgICAgICAgICAgLy8gcmUtcnVuIG92ZXIgYW4gYWxyZWFkeS1jb3BpZWQgcGFpciBvZiBzcGFjZXMgY2FuIHN0aWxsIHBpY2sgdXAgbGlua3MgdGhhdFxyXG4gICAgICAgICAgICAgICAgLy8gYW4gZWFybGllciwgaW5jb21wbGV0ZSBydW4gbmV2ZXIgY3JlYXRlZC5cclxuICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgc291cmNlVGlja2V0IG9mIHNvdXJjZVRpY2tldHMpIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdUaWNrZXRJZCA9IGVsZW1lbnRJZHNbc291cmNlVGlja2V0LmlkXTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoIW5ld1RpY2tldElkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc291cmNlT3BzID0gYXdhaXQgdGhpcy5vcGVyYXRpb25TZXJ2aWNlLmdldE9wZXJhdGlvbnNCeVRpY2tldElEKHNvdXJjZVRpY2tldC5pZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzb3VyY2VPcHMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVhZCB3aGF0IHRoZSB0YXJnZXQgdGlja2V0IGlzIGFscmVhZHkgbGlua2VkIHRvLCBzbyBhIHJlLXJ1biBuZXZlclxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjcmVhdGVzIGEgZHVwbGljYXRlIE9wZXJhdGlvbiBmb3IgYSBsaW5rIHRoYXQgYWxyZWFkeSBleGlzdHMuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRhcmdldE9wcyA9IGF3YWl0IHRoaXMub3BlcmF0aW9uU2VydmljZS5nZXRPcGVyYXRpb25zQnlUaWNrZXRJRChuZXdUaWNrZXRJZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxpbmtlZEVxdWlwbWVudElkcyA9IG5ldyBTZXQodGFyZ2V0T3BzLm1hcChvcCA9PiBvcC5lcXVpcG1lbnRJRCkpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBzb3VyY2VPcCBvZiBzb3VyY2VPcHMpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld0VxdWlwbWVudElkID0gc291cmNlT3AuZXF1aXBtZW50SUQgPyBlbGVtZW50SWRzW3NvdXJjZU9wLmVxdWlwbWVudElEXSA6IG51bGw7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBObyBjb3BpZWQgY291bnRlcnBhcnQgZm9yIHRoZSBzb3VyY2UgZXF1aXBtZW50IChub3QgY29sbGVjdGVkLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb3V0c2lkZSB0aGUgY3VycmVudCBmaWx0ZXIsIC4uLikg4oCUIHNhbWUgcnVsZSBhcyBldmVyeXdoZXJlIGVsc2VcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluIHRoaXMgZmlsZTogZHJvcCB0aGUgbGluayByYXRoZXIgdGhhbiBwb2ludCBpdCBhdCBub3RoaW5nIG9yXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhdCB0aGUgc291cmNlIHNwYWNlJ3MgZXF1aXBtZW50LlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFuZXdFcXVpcG1lbnRJZCB8fCBsaW5rZWRFcXVpcG1lbnRJZHMuaGFzKG5ld0VxdWlwbWVudElkKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5vcGVyYXRpb25TZXJ2aWNlLmNyZWF0ZU9wZXJhdGlvbih7IHRpY2tldElEOiBuZXdUaWNrZXRJZCwgZXF1aXBtZW50SUQ6IG5ld0VxdWlwbWVudElkIH0gYXMgT3BlcmF0aW9uKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmtlZEVxdWlwbWVudElkcy5hZGQobmV3RXF1aXBtZW50SWQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAob3BFcnJvcikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBjb3B5aW5nIHRpY2tldC1lcXVpcG1lbnQgbGlua3MgZm9yIFwiJHtzb3VyY2VUaWNrZXQ/LnRpdGxlfVwiOmAsIG9wRXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNvdW50Kys7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9nQ29weUl0ZW1FcnJvcihvcEVycm9yLCAnZXJyb3JPcGVyYXRpb24nLCBzb3VyY2VUaWNrZXQ/LnRpdGxlIHx8IHNvdXJjZVRpY2tldD8uaWQpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gT0JKRUNUUyAzRCAodGhlIDNEIG1vZGVsIGZpbGUgaXRzZWxmIOKAlCBgcGF0aGAg4oCUIGlzIHBoeXNpY2FsbHkgZHVwbGljYXRlZCBpbiBTMylcclxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzb3VyY2VPYmplY3RzM0QubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHNvdXJjZU9iaiA9IHNvdXJjZU9iamVjdHMzRFtpXTtcclxuXHJcbiAgICAgICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4aXN0c0luVGFyZ2V0ID0gdGFyZ2V0T2JqZWN0czNELnNvbWUodGFyZ2V0T2JqID0+IHRhcmdldE9iai5uYW1lID09PSBzb3VyY2VPYmoubmFtZSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmICghZXhpc3RzSW5UYXJnZXQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmF3U291cmNlID0gc291cmNlT2JqIGFzIGFueTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBwYXRoYCBtZWFucyB0d28gZGlmZmVyZW50IHRoaW5ncyBkZXBlbmRpbmcgb24gYHMzQnVja2V0YCwgZXhhY3RseSBhcyB0aGVcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdmlld2VyIHJlYWRzIGl0IChzZWUgdmlld2VyLmNvbXBvbmVudC50cyBhbmQgbWF0dGVycG9ydC1vYmplY3QzZC5zZXJ2aWNlLnRzKTpcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gIC0gczNCdWNrZXQgPT09IHRydWUgIC0+IGEga2V5IG9mIGEgbW9kZWwgZmlsZSB1cGxvYWRlZCB0byBTMywgb3VycyB0byBkdXBsaWNhdGU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAtIG90aGVyd2lzZSAgICAgICAgICAtPiBhIHJlZmVyZW5jZSBpbnRvIHRoZSAzRCBvYmplY3QgbGlicmFyeSBzaGlwcGVkIHdpdGhcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgdGhlIGFwcGxpY2F0aW9uIChcIjNET2JqZWN0cy9vYmplY3RzL2N1YmUuZGFlXCIgLT4gYXNzZXRzLzNEb2JqZWN0cy8uLi4pLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICB3aGljaCBleGlzdHMgaW4gZXZlcnkgc3BhY2UgYW5kIG11c3QgYmUgcmV1c2VkIHZlcmJhdGltLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBDb3B5aW5nIHVuY29uZGl0aW9uYWxseSBtZWFudCBldmVyeSBsaWJyYXJ5IG9iamVjdCBmYWlsZWQgd2l0aCBOb1N1Y2hLZXkgYW5kXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSB3aG9sZSAzRCBvYmplY3Qgd2FzIHNraXBwZWQsIG1vZGVsIEFORCBQT0kuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjb3BpZWRQYXRoID0gcmF3U291cmNlLnBhdGg7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyYXdTb3VyY2UucGF0aCAmJiByYXdTb3VyY2UuczNCdWNrZXQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcGllZFBhdGggPSBhd2FpdCB0aGlzLmNvcHlTM0tleUlmUHJlc2VudChyYXdTb3VyY2UucGF0aCwgYDNEIG9iamVjdCBcIiR7cmF3U291cmNlLm5hbWV9XCJgKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAqIFN0cmljdCBwYXJzZXIgdG8gZW5zdXJlIFtmbG9hdCwgZmxvYXQsIGZsb2F0XSBmb3JtYXQgZm9yIEdyYXBoUUwuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAqIEZvcmNlcyBudW1iZXJzLCBoYW5kbGVzIHBvdGVudGlhbCBEeW5hbW9EQiBvYmplY3Qgc3RydWN0dXJlcyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICogYW5kIGVuc3VyZXMgd2UgbmV2ZXIgc2VuZCBbMCwwLDBdIGZvciBzY2FsZS5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRvRmxvYXRBcnJheSA9ICh2YWw6IGFueSwgZGVmYXVsdFZhbDogbnVtYmVyW10gPSBbMCwgMCwgMF0pOiBudW1iZXJbXSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgYXJyYXk6IG51bWJlcltdID0gW107XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmFsKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIERCIGZvcm1hdCBbIHtOOiBcIjFcIn0sIC4uLiBdXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbC5sZW5ndGggPiAwICYmIHR5cGVvZiB2YWxbMF0gPT09ICdvYmplY3QnICYmICdOJyBpbiB2YWxbMF0pIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJyYXkgPSB2YWwubWFwKGl0ZW0gPT4gcGFyc2VGbG9hdChpdGVtLk4pKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgYWxyZWFkeSBzdGFuZGFyZCBhcnJheSBbMSwgMSwgMV1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJyYXkgPSB2YWwubWFwKGl0ZW0gPT4gcGFyc2VGbG9hdChpdGVtKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgb2JqZWN0IHt4LCB5LCB6fVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodmFsICYmIHR5cGVvZiB2YWwgPT09ICdvYmplY3QnKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJyYXkgPSBbcGFyc2VGbG9hdCh2YWwueCksIHBhcnNlRmxvYXQodmFsLnkpLCBwYXJzZUZsb2F0KHZhbC56KV07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkZWZhdWx0VmFsO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEVuc3VyZSB3ZSByZXR1cm4gdmFsaWQgbnVtYmVyc1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFycmF5Lm1hcChuID0+IGlzTmFOKG4pID8gMCA6IG4pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBzZXJ2aWNlIGlzIHNoYXJlZCwgYnV0IHRoZSB0d28gYXBwbGljYXRpb25zIGRvIE5PVCBkZXBsb3kgdGhlIHNhbWVcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gT2JqZWN0M0Qgc2NoZW1hOiBgdmlld0ZydXN0dW1gIGV4aXN0cyBvbmx5IGluIHNtYXJ0ZXJwbGFuLCBhbmQgYHNjYWxlYFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpcyBbRmxvYXRdIHRoZXJlIGJ1dCBhIHBsYWluIEZsb2F0IGluIG11c2V1bS4gU2VuZGluZyB0aGUgc21hcnRlcnBsYW5cclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2hhcGUgdG8gbXVzZXVtIHdhcyByZWplY3RlZCB3aXRoIFwiVGhlIHZhcmlhYmxlcyBpbnB1dCBjb250YWlucyBhIGZpZWxkXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoYXQgaXMgbm90IGRlZmluZWQgZm9yIGlucHV0IG9iamVjdCB0eXBlICdDcmVhdGVPYmplY3QzRElucHV0J1wiLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvL1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgaW5wdXQgdGhlcmVmb3JlIE1JUlJPUlMgdGhlIHNvdXJjZSByZWNvcmQgaW5zdGVhZCBvZiBpbXBvc2luZyBhXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNoYXBlOiBzb3VyY2UgYW5kIHRhcmdldCBsaXZlIGluIHRoZSBzYW1lIGRlcGxveW1lbnQsIHNvIHdoYXRldmVyIHRoZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzb3VyY2UgY2FycmllcyBpcyBleGFjdGx5IHdoYXQgdGhlIHRhcmdldCBhY2NlcHRzLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvYmplY3QzRElucHV0OiBhbnkgPSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRoOiBjb3BpZWRQYXRoLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGVsbHMgdGhlIHZpZXdlciBob3cgdG8gaW50ZXJwcmV0IGBwYXRoYC4gRHJvcHBpbmcgaXQgdHVybmVkIGFuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTMy1ob3N0ZWQgbW9kZWwgaW50byBhIGxpYnJhcnkgcmVmZXJlbmNlIG9uIHRoZSBjb3B5LCB3aGljaCB0aGVcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHZpZXdlciB0aGVuIHRyaWVkIHRvIHJlc29sdmUgYWdhaW5zdCBhc3NldHMvIGFuZCBmYWlsZWQgdG8gbG9hZC5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHMzQnVja2V0OiAhIXJhd1NvdXJjZS5zM0J1Y2tldCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6IHJhd1NvdXJjZS5uYW1lLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb246IHJhd1NvdXJjZS5kZXNjcmlwdGlvbiB8fCBcIlwiLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BhY2VJRDogdGFyZ2V0U3BhY2VJZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uOiB0b0Zsb2F0QXJyYXkocmF3U291cmNlLnBvc2l0aW9uLCBbMCwgMCwgMF0pLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRpb246IHRvRmxvYXRBcnJheShyYXdTb3VyY2Uucm90YXRpb24sIFswLCAwLCAwXSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgndmlld0ZydXN0dW0nIGluIHJhd1NvdXJjZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0M0RJbnB1dC52aWV3RnJ1c3R1bSA9ICEhcmF3U291cmNlLnZpZXdGcnVzdHVtO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBTY2FsZSBrZWVwcyB0aGUgc291cmNlJ3Mgb3duIHNoYXBlOiBhIGxpc3Qgc3RheXMgYSBsaXN0LCBhIHNjYWxhciBzdGF5c1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIHNjYWxhci4gQW4gYWJzZW50IHNjYWxlIGlzIGxlZnQgdW5zZXQgcmF0aGVyIHRoYW4gaW52ZW50ZWQsIHNvIHRoZSBjb3B5XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJlbmRlcnMgZXhhY3RseSBsaWtlIHRoZSBvcmlnaW5hbC5cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocmF3U291cmNlLnNjYWxlKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0M0RJbnB1dC5zY2FsZSA9IHRvRmxvYXRBcnJheShyYXdTb3VyY2Uuc2NhbGUsIFsxLCAxLCAxXSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocmF3U291cmNlLnNjYWxlICE9PSBudWxsICYmIHJhd1NvdXJjZS5zY2FsZSAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzY2FsYXJTY2FsZSA9IHBhcnNlRmxvYXQocmF3U291cmNlLnNjYWxlKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdDNESW5wdXQuc2NhbGUgPSBOdW1iZXIuaXNOYU4oc2NhbGFyU2NhbGUpID8gMSA6IHNjYWxhclNjYWxlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjcmVhdGVkT2JqID0gYXdhaXQgdGhpcy5vYmplY3QzRFNlcnZpY2UuY3JlYXRlKG9iamVjdDNESW5wdXQpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNyZWF0ZWRPYmogJiYgY3JlYXRlZE9iai5pZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudElkc1tzb3VyY2VPYmouaWRdID0gY3JlYXRlZE9iai5pZDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBzb3VyY2VQb2kgb2YgKHNvdXJjZU9iai5wb2lzPy5pdGVtcyB8fCBbXSkuZmlsdGVyKHAgPT4gISFwKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5jcmVhdGVDb3BpZWRQb2koXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlUG9pLCBjcmVhdGVkT2JqLmlkLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZU5hdlBvc2l0aW9ucywgdGFyZ2V0TmF2UG9zaXRpb25zLCB0cmFuc2Zvcm1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChpdGVtRXJyb3IpIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBUaGUgYmFja2VuZCBjYW4gZGVueSBjcmVhdGlvbiBvZiB0aGlzIHdob2xlIG1vZGVsIHRvIHRoZSBzaWduZWQtaW4gYWNjb3VudFxyXG4gICAgICAgICAgICAgICAgICAgIC8vIChpbiBNVVNFVU0sIE9iamVjdDNEIG9ubHkgZ3JhbnRzIGdldC9saXN0IHRvIHVzZXJQb29scykuIFRoZSBkZW5pYWwgaXMgbm90XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gcGVyLWl0ZW0sIHNvIGV2ZXJ5IHJlbWFpbmluZyBvYmplY3Qgd291bGQgZmFpbCBpZGVudGljYWxseTogcmVwb3J0IGl0IG9uY2UsXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gYXMgYSBwZXJtaXNzaW9uIHByb2JsZW0gcmF0aGVyIHRoYW4gYSBjb3B5IGVycm9yLCBhbmQgc3RvcCB0aGUgcGhhc2UgaW5zdGVhZFxyXG4gICAgICAgICAgICAgICAgICAgIC8vIG9mIGZpcmluZyBvbmUgZG9vbWVkIG11dGF0aW9uIHBlciBvYmplY3QuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNVbmF1dGhvcml6ZWQoaXRlbUVycm9yKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZW1haW5pbmcgPSBzb3VyY2VPYmplY3RzM0QubGVuZ3RoIC0gaTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBbTWF0dGVycG9ydFRhZ0NvcHlTZXJ2aWNlXSBOb3QgYWxsb3dlZCB0byBjcmVhdGUgM0Qgb2JqZWN0cyBpbiB0aGUgdGFyZ2V0IHNwYWNlLCBza2lwcGluZyAke3JlbWFpbmluZ30gb2YgdGhlbS5gLCBpdGVtRXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNvdW50Kys7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9nSXRlbUVycm9yKCdlcnJvck9iamVjdHMzZE5vdEFsbG93ZWQnLCB7IGNvdW50OiByZW1haW5pbmcgfSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzZWRPdmVyYWxsICs9IHJlbWFpbmluZztcclxuICAgICAgICAgICAgICAgICAgICAgICAgZW1pdFByb2dyZXNzKCdvYmplY3RzM2QnLCBzb3VyY2VPYmplY3RzM0QubGVuZ3RoLCBzb3VyY2VPYmplY3RzM0QubGVuZ3RoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRTdGVwUHJvZ3Jlc3MoJ29iamVjdHMzZCcsICdvYmplY3RzM2QnLCAxMDApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIGNvcHlpbmcgb2JqZWN0M0QgXCIke3NvdXJjZU9iaj8ubmFtZX1cIjpgLCBpdGVtRXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgIGVycm9yQ291bnQrKztcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZ0NvcHlJdGVtRXJyb3IoaXRlbUVycm9yLCAnZXJyb3JPYmplY3QzZCcsIHNvdXJjZU9iaj8ubmFtZSB8fCBzb3VyY2VPYmo/LmlkKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBwcm9jZXNzZWRPdmVyYWxsKys7XHJcbiAgICAgICAgICAgICAgICBlbWl0UHJvZ3Jlc3MoJ29iamVjdHMzZCcsIGkgKyAxLCBzb3VyY2VPYmplY3RzM0QubGVuZ3RoKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHBjdCA9IHNvdXJjZU9iamVjdHMzRC5sZW5ndGggPiAwID8gTWF0aC5yb3VuZCgoKGkgKyAxKSAvIHNvdXJjZU9iamVjdHMzRC5sZW5ndGgpICogMTAwKSA6IDEwMDtcclxuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RlcFByb2dyZXNzKCdvYmplY3RzM2QnLCAnb2JqZWN0czNkJywgcGN0KTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gRkVBVFVSRVMg4oCUIHRoZSBcIlBPSVwiIG9mIHRoZSBNVVNFVU0gbW9kdWxlOiBpdHMgb3duIHJlY29yZCAodGl0bGUsIGluZGV4LCBsb2NhbGUsXHJcbiAgICAgICAgICAgIC8vIGtleXdvcmRzKSwgaXRzIG1lZGlhIHNldCAob25lIENvbW1lbnQgcGVyIGltYWdlL3ZpZGVvL2F1ZGlvL2RvY3VtZW50L2xpbmsvdGV4dClcclxuICAgICAgICAgICAgLy8gYW5kIGl0cyBQT0kgcmVjb3JkICh0aGUgcGFzdGlsbGU6IGljb24sIHRhZyBkZXNjcmlwdGlvbiwgY292ZXIgaW1hZ2UpLlxyXG4gICAgICAgICAgICAvLyBFdmVyeXRoaW5nIGlzIGNvcGllZCBoZXJlLCBmaWxlcyBwaHlzaWNhbGx5IGR1cGxpY2F0ZWQgaW4gUzMgZmlyc3QuXHJcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc291cmNlRmVhdHVyZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHNvdXJjZU9iaiA9IHNvdXJjZUZlYXR1cmVzW2ldO1xyXG5cclxuICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZXhpc3RpbmdNYXRjaCA9IHRoaXMuZmluZEV4aXN0aW5nKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VPYmogYXMgYW55LCB0YXJnZXRGZWF0dXJlcyBhcyBhbnksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIChmOiBhbnkpID0+IFtmLnRpdGxlLCBmLmRlc2NyaXB0aW9uXVxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmICghZXhpc3RpbmdNYXRjaCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByYXdTb3VyY2UgPSBzb3VyY2VPYmogYXMgYW55O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVzb2x2ZWQganVzdCBiZWZvcmUgdGhlIHdyaXRlOiBhIGtleXdvcmQgaXMgb25seSBjcmVhdGVkIGluIHRoZSB0YXJnZXRcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3BhY2Ugd2hlbiB0aGUgUE9JIGNhcnJ5aW5nIGl0IGlzIGFib3V0IHRvIGJlIGNyZWF0ZWQuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc29sdmVkSGFzaHRhZ3MgPSBhd2FpdCB0aGlzLnJlc29sdmVIYXNodGFnSWRzKHJhd1NvdXJjZS5oYXNodGFncywgdGFyZ2V0U3BhY2VJZCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmZWF0dXJlSW5wdXQ6IGFueSA9IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlOiByYXdTb3VyY2UudGl0bGUsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaG9ydERlc2NyaXB0aW9uOiByYXdTb3VyY2Uuc2hvcnREZXNjcmlwdGlvbixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsOiByYXdTb3VyY2UubGV2ZWwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiByYXdTb3VyY2UudHlwZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBpbmRleGAgZHJpdmVzIHRoZSBvcmRlcmluZyBvZiB0aGUgUE9JIGluIHRoZSBzcGFjZSdzIGxpc3QsIGluIHRoZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbGF0ZXJhbCBtZW51IGFuZCBpbiB0aGUgZ3VpZGVkIHRvdXIuIERyb3BwaW5nIGl0IGZvcmNlZCBhIGZ1bGwgbWFudWFsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyByZW51bWJlcmluZyBvZiBldmVyeSBjb3BpZWQgUE9JLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXg6IHJhd1NvdXJjZS5pbmRleCA/PyBudWxsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWlzc2lvbnMgYXJlIHBlci1zcGFjZTogc291cmNlIG1pc3Npb24gaWRzIG1lYW4gbm90aGluZyBpbiB0aGUgdGFyZ2V0XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBzcGFjZSwgc28gYW4gYXJjaGl2ZSBsaXN0IGNhcnJpZWQgb3ZlciB3b3VsZCBoaWRlIFBPSXMgZnJvbSBub2JvZHlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdoaWxlIGxvb2tpbmcgbGlrZSByZWFsIGRhdGEuIFJlc2V0IGluc3RlYWQuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmNoaXZlZEZvck1pc3Npb25JRDogbnVsbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmlwZVByb2R1Y3RJRDogcmF3U291cmNlLnN0cmlwZVByb2R1Y3RJRCB8fCBudWxsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaXBlUHJpY2VJRDogcmF3U291cmNlLnN0cmlwZVByaWNlSUQgfHwgbnVsbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJvb2tpbmdQcmljZU1ldGFkYXRhOiByYXdTb3VyY2UuYm9va2luZ1ByaWNlTWV0YWRhdGEgfHwgbnVsbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsZTogcmF3U291cmNlLmxvY2FsZSB8fCBudWxsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSGFzaHRhZ3MgYXJlIHNwYWNlLXNjb3BlZCByZWNvcmRzOiB0aGUgaWRzIG11c3QgYmUgdHJhbnNsYXRlZCB0byB0aGVcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGVxdWl2YWxlbnQgaGFzaHRhZ3Mgb2YgdGhlIHRhcmdldCBzcGFjZSAoY3JlYXRlZCBvbiBkZW1hbmQpLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzaHRhZ3M6IHJlc29sdmVkSGFzaHRhZ3MsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogcmF3U291cmNlLmRlc2NyaXB0aW9uIHx8IG51bGwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZXVzZWQgdW5jaGFuZ2VkIGluIHRoZSBzYW1lIG9yZ2FuaXNhdGlvbiwgbWF0Y2hlZCBieSBuYW1lXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhY3Jvc3MgdHdvIOKAlCBzZWUgcmVzb2x2ZURvbWFpbklEKCkuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb21haW5JRDogdGhpcy5yZXNvbHZlRG9tYWluSUQocmF3U291cmNlLmRvbWFpbklEKSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwYWNlSUQ6IHRhcmdldFNwYWNlSWQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvd25lck1pc3Npb25JRDogdGFyZ2V0TWlzc2lvbklkXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjcmVhdGVkT2JqID0gYXdhaXQgdGhpcy5mZWF0dXJlU2VydmljZS5jcmVhdGVGZWF0dXJlKGZlYXR1cmVJbnB1dCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3JlYXRlZE9iaiAmJiBjcmVhdGVkT2JqLmlkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50SWRzW3NvdXJjZU9iai5pZF0gPSBjcmVhdGVkT2JqLmlkO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlIGZlYXR1cmUgZXhpc3RzOiBpdHMga2V5d29yZHMgYXJlIG5vdyBnZW51aW5lbHkgcmVmZXJlbmNlZCBhbmRcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG11c3Qgc3Vydml2ZSB0aGUgZW5kLW9mLXJ1biBjbGVhbnVwLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXJrSGFzaHRhZ3NVc2VkKHJlc29sdmVkSGFzaHRhZ3MpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3JlYXRlZE9iaikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVhZCB0aGUgbWVkaWEgc2V0IHRocm91Z2ggaXRzIG93biBwYWdpbmF0ZWQgcXVlcnk6IHRoZSBgY29tbWVudHNgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjb25uZWN0aW9uIGVtYmVkZGVkIGluIEZlYXR1cmVzQnlTcGFjZSBpcyBjYXBwZWQgYXQgMTAwIGl0ZW1zIGFuZCBpdHNcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5leHRUb2tlbiB3YXMgbmV2ZXIgZm9sbG93ZWQsIHNvIHJpY2ggUE9JcyBsb3N0IGF0dGFjaG1lbnRzIHNpbGVudGx5LlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHNvdXJjZUNvbW1lbnRzOiBDb21tZW50W10gPSBbXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlQ29tbWVudHMgPSBhd2FpdCB0aGlzLmNvbW1lbnRTZXJ2aWNlLmdldEFsbENvbW1lbnRzRm9yRmVhdHVyZShzb3VyY2VPYmouaWQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoY29tbWVudHNGZXRjaEVycm9yKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBGYWxsaW5nIGJhY2sgdG8gdGhlIGVtYmVkZGVkIGNvbW1lbnQgbGlzdCBmb3IgZmVhdHVyZSBcIiR7cmF3U291cmNlLnRpdGxlfVwiOmAsIGNvbW1lbnRzRmV0Y2hFcnJvcik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlQ29tbWVudHMgPSAoc291cmNlT2JqLmNvbW1lbnRzPy5pdGVtcyB8fCBbXSkuZmlsdGVyKGMgPT4gISFjKSBhcyBDb21tZW50W107XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBzb3VyY2VDb21tZW50IG9mIHRoaXMub3JkZXJDb21tZW50c0ZvckNvcHkoc291cmNlQ29tbWVudHMpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3JlYXRlZCA9IGF3YWl0IHRoaXMuY29weUNvbW1lbnRGb3JGZWF0dXJlKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlQ29tbWVudCwgY3JlYXRlZE9iai5pZCwgdGFyZ2V0U3BhY2VJZFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3JlYXRlZD8uaWQgJiYgKHNvdXJjZUNvbW1lbnQgYXMgYW55KS5pZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21tZW50SWRzLnNldCgoc291cmNlQ29tbWVudCBhcyBhbnkpLmlkLCBjcmVhdGVkLmlkKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGF0dGFjaG1lbnRFcnJvcikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBjb3B5aW5nIGF0dGFjaG1lbnQgXCIke3NvdXJjZUNvbW1lbnQ/LnRpdGxlfVwiIGZvciBmZWF0dXJlIFwiJHtzb3VyY2VPYmo/LnRpdGxlfVwiOmAsIGF0dGFjaG1lbnRFcnJvcik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ291bnQrKztcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2dDb3B5SXRlbUVycm9yKGF0dGFjaG1lbnRFcnJvciwgJ2Vycm9yRmVhdHVyZUF0dGFjaG1lbnQnLCBzb3VyY2VDb21tZW50Py50aXRsZSB8fCAoc291cmNlQ29tbWVudCBhcyBhbnkpPy5pZCwge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZTogcmF3U291cmNlLnRpdGxlIHx8IHNvdXJjZU9iai5pZFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXZlcnkgUE9JIG9mIHRoZSBmZWF0dXJlLCBub3Qgb25seSB0aGUgZmlyc3Qgb25lOiBhIGZlYXR1cmUgbWF5IGJlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBwaW5uZWQgYXQgc2V2ZXJhbCBwbGFjZXMsIGFuZCBvbmx5IHRoaXMgcGhhc2Uga25vd3MgdGhlIG5ldyBlbGVtZW50IGlkLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc291cmNlRmVhdHVyZVBvaXMgPSAoc291cmNlT2JqLnBvaXM/Lml0ZW1zIHx8IFtdKS5maWx0ZXIocCA9PiAhIXApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBzb3VyY2VQb2kgb2Ygc291cmNlRmVhdHVyZVBvaXMpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmNyZWF0ZUNvcGllZFBvaShcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlUG9pLCBjcmVhdGVkT2JqLmlkLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VOYXZQb3NpdGlvbnMsIHRhcmdldE5hdlBvc2l0aW9ucywgdHJhbnNmb3JtXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNhbWUgcmVhc29uaW5nIGFzIHRoZSBFUVVJUE1FTlRTIHBoYXNlIChzZWUgdGhlIGNvbW1lbnQgdGhlcmUpOiBhXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZlYXR1cmUgbWF0Y2hpbmcgdGhpcyBvbmUgYWxyZWFkeSBleGlzdHMgaW4gdGhlIHRhcmdldCBzcGFjZSwgbW9zdFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBsaWtlbHkgZnJvbSBhbiBlYXJsaWVyLCBpbmNvbXBsZXRlIHJ1bi4gRmlsbCBpbiB3aGF0ZXZlciBpZGVudGl0eVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBmaWVsZCBpdCBpcyBtaXNzaW5nIHJhdGhlciB0aGFuIGxlYXZpbmcgaXQgdW50b3VjaGVkLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50SWRzW3NvdXJjZU9iai5pZF0gPSBleGlzdGluZ01hdGNoLmlkO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBoZWFsZWRGaWVsZHMgPSBhd2FpdCB0aGlzLmhlYWxGZWF0dXJlSWRlbnRpdHkoc291cmNlT2JqIGFzIGFueSwgZXhpc3RpbmdNYXRjaCBhcyBhbnkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaGVhbGVkRmllbGRzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlYWxlZENvdW50Kys7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZ0hlYWxlZEl0ZW0oJ2ZlYXR1cmVIZWFsZWQnLCAoc291cmNlT2JqIGFzIGFueSk/LnRpdGxlIHx8IHNvdXJjZU9iaj8uaWQsIGhlYWxlZEZpZWxkcyk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChpdGVtRXJyb3IpIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBjb3B5aW5nIGZlYXR1cmUgXCIke3NvdXJjZU9iaj8udGl0bGV9XCIgKGlkOiAke3NvdXJjZU9iaj8uaWR9KTpgLCBpdGVtRXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgIGVycm9yQ291bnQrKztcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZ0NvcHlJdGVtRXJyb3IoaXRlbUVycm9yLCAnZXJyb3JGZWF0dXJlJywgc291cmNlT2JqPy50aXRsZSB8fCBzb3VyY2VPYmo/LmlkKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBwcm9jZXNzZWRPdmVyYWxsKys7XHJcbiAgICAgICAgICAgICAgICBlbWl0UHJvZ3Jlc3MoJ2ZlYXR1cmVzJywgaSArIDEsIHNvdXJjZUZlYXR1cmVzLmxlbmd0aCk7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBwY3QgPSBzb3VyY2VGZWF0dXJlcy5sZW5ndGggPiAwID8gTWF0aC5yb3VuZCgoKGkgKyAxKSAvIHNvdXJjZUZlYXR1cmVzLmxlbmd0aCkgKiAxMDApIDogMTAwO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTdGVwUHJvZ3Jlc3MoJ2ZlYXR1cmVzJywgJ2ZlYXR1cmVzJywgcGN0KTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gTUVBU1VSRU1FTlRTIChJTU1PIG9ubHkg4oCUIGEgQ29tbWVudCArIGEgcG9zaXRpb25hbC1vbmx5IFBPSSwgbm8gcm90YXRpb247XHJcbiAgICAgICAgICAgIC8vIHRoZSBzY3JlZW5zaG90IGZpbGUgaXMgcGh5c2ljYWxseSBkdXBsaWNhdGVkIGluIFMzIGZpcnN0KVxyXG4gICAgICAgICAgICBpZiAodGhpcy5zcE1vZHVsZSA9PSBTcE1vZHVsZS5JTU1PKSB7XHJcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNvdXJjZU1lYXN1cmVtZW50cy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNvdXJjZU1lYXN1cmVtZW50ID0gc291cmNlTWVhc3VyZW1lbnRzW2ldO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleGlzdHNJblRhcmdldCA9IHRhcmdldE1lYXN1cmVtZW50cy5zb21lKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdG0gPT4gdG0uY29tbWVudC50aXRsZSA9PT0gc291cmNlTWVhc3VyZW1lbnQuY29tbWVudC50aXRsZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFleGlzdHNJblRhcmdldCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmF3Q29tbWVudCA9IHNvdXJjZU1lYXN1cmVtZW50LmNvbW1lbnQgYXMgYW55O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjb3BpZWRBbm5leGU6IHN0cmluZyB8IG51bGwgPSBudWxsO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJhd0NvbW1lbnQuYW5uZXhlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29waWVkQW5uZXhlID0gYXdhaXQgdGhpcy5jb3B5UzNLZXlJZlByZXNlbnQocmF3Q29tbWVudC5hbm5leGUsIGBtZWFzdXJlbWVudCBzY3JlZW5zaG90IFwiJHtyYXdDb21tZW50LnRpdGxlfVwiYCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29tbWVudElucHV0OiBhbnkgPSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGU6IHJhd0NvbW1lbnQudGl0bGUsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb246IHJhd0NvbW1lbnQuZGVzY3JpcHRpb24gPz8gbnVsbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogcmF3Q29tbWVudC5tZXRhZGF0YSA/PyBudWxsLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IENvbW1lbnRUeXBlLk1FQVNVUkUsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltZW5zaW9uczogcmF3Q29tbWVudC5kaW1lbnNpb25zIHx8IG51bGwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5uZXhlOiBjb3BpZWRBbm5leGUsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BhY2VJRDogdGFyZ2V0U3BhY2VJZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYW1lIGF1dGhvcnNoaXAgcnVsZSBhcyBldmVyeSBvdGhlciBjb3BpZWQgY29tbWVudCDigJQgc2VlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmVzb2x2ZUNvbW1lbnRPd25lcklEKCkuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3duZXJJRDogdGhpcy5yZXNvbHZlQ29tbWVudE93bmVySUQocmF3Q29tbWVudC5vd25lcklEKSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3JlYXRlZENvbW1lbnQ6IENvbW1lbnQgPSBhd2FpdCB0aGlzLmNvbW1lbnRTZXJ2aWNlLmNyZWF0ZUNvbW1lbnQoY29tbWVudElucHV0KTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3JlYXRlZENvbW1lbnQgJiYgKGNyZWF0ZWRDb21tZW50IGFzIGFueSkuaWQgJiYgcmF3Q29tbWVudC5pZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tbWVudElkcy5zZXQocmF3Q29tbWVudC5pZCwgKGNyZWF0ZWRDb21tZW50IGFzIGFueSkuaWQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjcmVhdGVkQ29tbWVudCAmJiBzb3VyY2VNZWFzdXJlbWVudC5wb2kpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0YXJnZXRTd2VlcElkID0gdGhpcy5maW5kQ2xvc2VzdFRhcmdldFN3ZWVwSWQoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZU1lYXN1cmVtZW50LnBvaS5tYXR0ZXJwb3J0U3dlZXBJRCwgc291cmNlTmF2UG9zaXRpb25zLCB0YXJnZXROYXZQb3NpdGlvbnMsIHRyYW5zZm9ybVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYWRqdXN0ZWRQb3NpdGlvbiA9IHRoaXMuZ2V0QWRqdXN0ZWRQb3NpdGlvbk9ubHkoc291cmNlTWVhc3VyZW1lbnQucG9pLmNvb3JkaW5hdGUsIHRyYW5zZm9ybSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcG9pSW5wdXQ6IFBPSSA9IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRpbmF0ZTogSlNPTi5zdHJpbmdpZnkoYWRqdXN0ZWRQb3NpdGlvbiksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFBvaVR5cGUuTUVBU1VSRSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudElEOiAoY3JlYXRlZENvbW1lbnQgYXMgYW55KS5pZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2FtZSB0cmVhdG1lbnQgYXMgYW55IG90aGVyIFBPSTogdGhlIHNvdXJjZSdzIE1hdHRlcnBvcnQgdGFnXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNJRCBtdXN0IG5vdCB0cmF2ZWwsIGFuZCB0aGUgc3RlbSBub3JtYWwgaGFzIHRvIGJlIHJvdGF0ZWQuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiB0aGlzLmdldEFkanVzdGVkUG9pTWV0YWRhdGEoc291cmNlTWVhc3VyZW1lbnQucG9pLm1ldGFkYXRhLCB0cmFuc2Zvcm0pLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXR0ZXJwb3J0U3dlZXBJRDogdGFyZ2V0U3dlZXBJZFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wb2lTZXJ2aWNlLmNyZWF0ZVBPSUZvclNwYWNlSUQocG9pSW5wdXQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoaXRlbUVycm9yKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIGNvcHlpbmcgbWVhc3VyZW1lbnQgXCIke3NvdXJjZU1lYXN1cmVtZW50Py5jb21tZW50Py50aXRsZX1cIjpgLCBpdGVtRXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNvdW50Kys7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9nQ29weUl0ZW1FcnJvcihpdGVtRXJyb3IsICdlcnJvck1lYXN1cmVtZW50Jywgc291cmNlTWVhc3VyZW1lbnQ/LmNvbW1lbnQ/LnRpdGxlIHx8IHNvdXJjZU1lYXN1cmVtZW50Py5pZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzZWRPdmVyYWxsKys7XHJcbiAgICAgICAgICAgICAgICAgICAgZW1pdFByb2dyZXNzKCdtZWFzdXJlbWVudHMnLCBpICsgMSwgc291cmNlTWVhc3VyZW1lbnRzLmxlbmd0aCk7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGN0ID0gc291cmNlTWVhc3VyZW1lbnRzLmxlbmd0aCA+IDAgPyBNYXRoLnJvdW5kKCgoaSArIDEpIC8gc291cmNlTWVhc3VyZW1lbnRzLmxlbmd0aCkgKiAxMDApIDogMTAwO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RlcFByb2dyZXNzKCdtZWFzdXJlbWVudHMnLCAnbWVhc3VyZW1lbnRzJywgcGN0KTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gUE9JUyDigJQgc3RhbmRhbG9uZSBvbmVzIG9ubHk6IGV2ZXJ5IFBPSSBvd25lZCBieSBhbiBlbGVtZW50IHdhcyBhbHJlYWR5IGNyZWF0ZWQgYnlcclxuICAgICAgICAgICAgLy8gdGhhdCBlbGVtZW50J3MgcGhhc2UsIHdpdGggdGhlIGVsZW1lbnQncyBORVcgaWQuXHJcbiAgICAgICAgICAgIC8vXHJcbiAgICAgICAgICAgIC8vIFRoaXMgcGhhc2UgcnVucyBMQVNUIG9uIHB1cnBvc2UuIEl0IHVzZWQgdG8gcnVuIHRoaXJkLCBiZWZvcmUgM0Qgb2JqZWN0cywgZmVhdHVyZXNcclxuICAgICAgICAgICAgLy8gYW5kIG1lYXN1cmVtZW50cyBleGlzdGVkIGluIHRoZSB0YXJnZXQgc3BhY2UsIHNvIGBlbGVtZW50SWRzYCBhbmQgYGNvbW1lbnRJZHNgIHdlcmVcclxuICAgICAgICAgICAgLy8gc3RpbGwgZW1wdHkgd2hlbiBpdCBuZWVkZWQgdGhlbTogZWxlbWVudElEIHN0YXllZCBwb2ludGluZyBhdCB0aGUgc291cmNlIHNwYWNlIGFuZFxyXG4gICAgICAgICAgICAvLyB0YWdJbWFnZUlEIChhIHJlZmVyZW5jZSB0byBhIENvbW1lbnQgcmVjb3JkKSBjb3VsZCBuZXZlciBiZSByZXNvbHZlZC5cclxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzb3VyY2VQb2lzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBzb3VyY2VQb2kgPSBzb3VyY2VQb2lzW2ldO1xyXG5cclxuICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZXhpc3RzSW5UYXJnZXQgPSB0YXJnZXRQb2lzLnNvbWUoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRwID0+IHRwLmNvb3JkaW5hdGUgPT09IHNvdXJjZVBvaS5jb29yZGluYXRlICYmIHRwLnRhZ0Rlc2NyaXB0aW9uID09PSBzb3VyY2VQb2kudGFnRGVzY3JpcHRpb25cclxuICAgICAgICAgICAgICAgICAgICApO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBpZiAoIWV4aXN0c0luVGFyZ2V0KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVsZW1lbnRJRCA9IHNvdXJjZVBvaS5lbGVtZW50SURcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gKGVsZW1lbnRJZHNbc291cmNlUG9pLmVsZW1lbnRJRF0gfHwgc291cmNlUG9pLmVsZW1lbnRJRClcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogc291cmNlUG9pLmVsZW1lbnRJRDtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuY3JlYXRlQ29waWVkUG9pKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlUG9pLCBlbGVtZW50SUQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VOYXZQb3NpdGlvbnMsIHRhcmdldE5hdlBvc2l0aW9ucywgdHJhbnNmb3JtXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoaXRlbUVycm9yKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgRXJyb3IgY29weWluZyBQT0kgKHN3ZWVwOiAke3NvdXJjZVBvaT8ubWF0dGVycG9ydFN3ZWVwSUR9KTpgLCBpdGVtRXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgIGVycm9yQ291bnQrKztcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZ0NvcHlJdGVtRXJyb3IoaXRlbUVycm9yLCAnZXJyb3JQb2knLCBzb3VyY2VQb2k/Lm1hdHRlcnBvcnRTd2VlcElELCB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHN3ZWVwOiBzb3VyY2VQb2k/Lm1hdHRlcnBvcnRTd2VlcElEXHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgcHJvY2Vzc2VkT3ZlcmFsbCsrO1xyXG4gICAgICAgICAgICAgICAgZW1pdFByb2dyZXNzKCdwb2lzJywgaSArIDEsIHNvdXJjZVBvaXMubGVuZ3RoKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHBjdCA9IHNvdXJjZVBvaXMubGVuZ3RoID4gMCA/IE1hdGgucm91bmQoKChpICsgMSkgLyBzb3VyY2VQb2lzLmxlbmd0aCkgKiAxMDApIDogMTAwO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTdGVwUHJvZ3Jlc3MoJ3BvaXMnLCAncG9pcycsIHBjdCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHRoaXMuY29weVByb2dyZXNzJC5uZXh0KHtcclxuICAgICAgICAgICAgICAgIHBoYXNlOiAnZG9uZScsXHJcbiAgICAgICAgICAgICAgICBwcm9jZXNzZWRJblBoYXNlOiAwLCB0b3RhbEluUGhhc2U6IDAsXHJcbiAgICAgICAgICAgICAgICBwcm9jZXNzZWRPdmVyYWxsLCB0b3RhbE92ZXJhbGwsXHJcbiAgICAgICAgICAgICAgICBwZXJjZW50OiAxMDAsIGVycm9yQ291bnQsIGhlYWxlZENvdW50XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB0aGlzLnNldFN0ZXBMb2coJ2RvbmUnLCBlcnJvckNvdW50ID4gMFxyXG4gICAgICAgICAgICAgICAgPyB0aGlzLnRyYW5zbGF0ZS5pbnN0YW50KCdtYXR0ZXJwb3J0Q29weS5kb25lV2l0aEVycm9ycycsIHsgY291bnQ6IGVycm9yQ291bnQgfSlcclxuICAgICAgICAgICAgICAgIDogdGhpcy50cmFuc2xhdGUuaW5zdGFudCgnbWF0dGVycG9ydENvcHkuZG9uZScpKTtcclxuICAgICAgICAgICAgLy8gU2VwYXJhdGUgc3VtbWFyeSBsaW5lLCBvbiB0b3Agb2YgKG5vdCBpbnN0ZWFkIG9mKSB0aGUgZG9uZS9kb25lV2l0aEVycm9ycyBvbmVcclxuICAgICAgICAgICAgLy8gYWJvdmU6IGhlYWxpbmcgaXMgb3J0aG9nb25hbCB0byBzdWNjZXNzL2ZhaWx1cmUsIGFuIGFscmVhZHktY29tcGxldGUgcnVuIGNhblxyXG4gICAgICAgICAgICAvLyBzdGlsbCBoYXZlIHJlcGFpcmVkIGl0ZW1zIGxlZnQgb3ZlciBmcm9tIGFuIGVhcmxpZXIsIGluY29tcGxldGUgYXR0ZW1wdC5cclxuICAgICAgICAgICAgaWYgKGhlYWxlZENvdW50ID4gMCkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTdGVwTG9nKCdoZWFsZWRTdW1tYXJ5JywgdGhpcy50cmFuc2xhdGUuaW5zdGFudCgnbWF0dGVycG9ydENvcHkuaGVhbGVkU3VtbWFyeScsIHsgY291bnQ6IGhlYWxlZENvdW50IH0pKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgY29weWluZyBQT0lzOicsIGVycm9yKTtcclxuICAgICAgICAgICAgdGhpcy5hcHBlbmRFcnJvckxvZyh0aGlzLnRyYW5zbGF0ZS5pbnN0YW50KCdtYXR0ZXJwb3J0Q29weS5lcnJvckdlbmVyYWwnLCB7IGVycm9yOiB0b0Vycm9yTWVzc2FnZShlcnJvcikgfSkpO1xyXG4gICAgICAgICAgICB0aGlzLmNvcHlQcm9ncmVzcyQubmV4dChudWxsKTtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH0gZmluYWxseSB7XHJcbiAgICAgICAgICAgIC8vIEV2ZXJ5IGV4aXQgcGF0aCDigJQgc3VjY2VzcywgcGFydGlhbCBzdWNjZXNzLCBvciBnZW5lcmFsIGZhaWx1cmUg4oCUIGdpdmVzIGJhY2sgdGhlXHJcbiAgICAgICAgICAgIC8vIGtleXdvcmRzIHRoaXMgcnVuIGNyZWF0ZWQgYnV0IG5vIGNvcGllZCBQT0kgZW5kZWQgdXAgdXNpbmcuIFBsYWNlZCBpbiBgZmluYWxseWBcclxuICAgICAgICAgICAgLy8gc28gYW4gZXhjZXB0aW9uIHRocm93biBtaWQtY29weSBjYW5ub3QgbGVhdmUgdGhlbSBiZWhpbmQgZWl0aGVyLlxyXG4gICAgICAgICAgICBhd2FpdCB0aGlzLmNsZWFudXBVbnVzZWRDcmVhdGVkSGFzaHRhZ3MoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTZXJpYWxpc2VzIHRoZSBjdXJyZW50IGNvcHkgbG9nIChzdGVwIGxpbmVzIGFzIGxhc3QgZW1pdHRlZCwgcGx1cyBldmVyeSBlcnJvciBhbmRcclxuICAgICAqIGhlYWxlZC1pdGVtIG5vdGljZSkgdG8gYSBwbGFpbi10ZXh0IGZpbGUgYW5kIHRyaWdnZXJzIGEgYnJvd3NlciBkb3dubG9hZCDigJQgd2lyZWQgdG8gYVxyXG4gICAgICogXCJkb3dubG9hZCBsb2dcIiBidXR0b24gaW4gdGhlIGNvcHkgVUksIHNvIGFuIG9wZXJhdG9yIGNhbiBrZWVwIG9yIHNoYXJlIHRoZSBmdWxsIHJlcG9ydFxyXG4gICAgICogb2YgYSBydW4gcmF0aGVyIHRoYW4gb25seSB0aGUgfjIwMHB4IHNjcm9sbGFibGUgcGFuZWwgc2hvd2luZyBpdC5cclxuICAgICAqL1xyXG4gICAgZG93bmxvYWRMb2coZmlsZW5hbWU/OiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCB0ZXh0ID0gdGhpcy5sb2cubWFwKGVudHJ5ID0+IGVudHJ5LnRleHQpLmpvaW4oJ1xcbicpO1xyXG4gICAgICAgIGNvbnN0IGRlZmF1bHROYW1lID0gYG1hdHRlcnBvcnQtY29weS1sb2ctJHtuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCkucmVwbGFjZSgvWzouXS9nLCAnLScpfS50eHRgO1xyXG4gICAgICAgIGRvd25sb2FkQmxvYihuZXcgQmxvYihbdGV4dF0sIHsgdHlwZTogJ3RleHQvcGxhaW47Y2hhcnNldD11dGYtOCcgfSksIGZpbGVuYW1lIHx8IGRlZmF1bHROYW1lKTtcclxuICAgIH1cclxuXHJcbiAgICAvL1xyXG4gICAgLy8gLS0tLS0tLS0tLSBQcm9ncmVzcyAvIGxvZyBoZWxwZXJzIC0tLS0tLS0tLS1cclxuICAgIC8vXHJcblxyXG4gICAgLyoqIEFkZHMgb3IgdXBkYXRlcyBhIHN0ZXAgbGluZSAoaWRlbnRpZmllZCBieSBzdGVwSWQpIHdpdGggbmV3IHRleHQsIHRoZW4gcmVwdWJsaXNoZXMgdGhlIGxvZy4gKi9cclxuICAgIHByaXZhdGUgc2V0U3RlcExvZyhzdGVwSWQ6IHN0cmluZywgdGV4dDogc3RyaW5nKSB7XHJcbiAgICAgICAgY29uc3QgZXhpc3RpbmdJbmRleCA9IHRoaXMubG9nLmZpbmRJbmRleChlID0+IGUudHlwZSA9PT0gJ3N0ZXAnICYmIGUuaWQgPT09IHN0ZXBJZCk7XHJcbiAgICAgICAgY29uc3QgZW50cnk6IENvcHlMb2dFbnRyeSA9IHsgaWQ6IHN0ZXBJZCwgdHlwZTogJ3N0ZXAnLCB0ZXh0IH07XHJcbiAgICAgICAgaWYgKGV4aXN0aW5nSW5kZXggPj0gMCkge1xyXG4gICAgICAgICAgICB0aGlzLmxvZ1tleGlzdGluZ0luZGV4XSA9IGVudHJ5O1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRoaXMubG9nLnB1c2goZW50cnkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLmNvcHlMb2ckLm5leHQoWy4uLnRoaXMubG9nXSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEFwcGVuZHMgYSBuZXcsIHBlcm1hbmVudCBsb2cgbGluZSAobmV2ZXIgb3ZlcndyaXR0ZW4pLCB0aGVuIHJlcHVibGlzaGVzIHRoZSBsb2cuICovXHJcbiAgICBwcml2YXRlIGFwcGVuZEVycm9yTG9nKHRleHQ6IHN0cmluZykge1xyXG4gICAgICAgIHRoaXMubG9nU2VxKys7XHJcbiAgICAgICAgdGhpcy5sb2cucHVzaCh7IGlkOiBgZXJyb3ItJHt0aGlzLmxvZ1NlcX1gLCB0eXBlOiAnZXJyb3InLCB0ZXh0IH0pO1xyXG4gICAgICAgIHRoaXMuY29weUxvZyQubmV4dChbLi4udGhpcy5sb2ddKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogQXBwZW5kcyBhIHBlcm1hbmVudCBsb2cgbGluZSBmb3IgYW4gaXRlbSB0aGF0IHdhcyByZXBhaXJlZCByYXRoZXIgdGhhbiBuZXdseVxyXG4gICAgICogIGNyZWF0ZWQg4oCUIHNlZSBoZWFsRXF1aXBtZW50SWRlbnRpdHkoKSBhbmQgaXRzIHRpY2tldC9mZWF0dXJlIGVxdWl2YWxlbnRzLiAqL1xyXG4gICAgcHJpdmF0ZSBhcHBlbmRIZWFsZWRMb2codGV4dDogc3RyaW5nKSB7XHJcbiAgICAgICAgdGhpcy5sb2dTZXErKztcclxuICAgICAgICB0aGlzLmxvZy5wdXNoKHsgaWQ6IGBoZWFsZWQtJHt0aGlzLmxvZ1NlcX1gLCB0eXBlOiAnaGVhbGVkJywgdGV4dCB9KTtcclxuICAgICAgICB0aGlzLmNvcHlMb2ckLm5leHQoWy4uLnRoaXMubG9nXSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIFJlc2V0cyB0aGUgbG9nIGZvciBhIG5ldyBydW4uICovXHJcbiAgICBwcml2YXRlIHJlc2V0TG9nKCkge1xyXG4gICAgICAgIHRoaXMubG9nID0gW107XHJcbiAgICAgICAgdGhpcy5sb2dTZXEgPSAwO1xyXG4gICAgICAgIHRoaXMuY29weUxvZyQubmV4dChbXSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIENsZWFycyBldmVyeSBpZCBtYXAgY2FycmllZCBvdmVyIGZyb20gYSBwcmV2aW91cyBydW4uIFRoZSBzZXJ2aWNlIGlzIGEgcm9vdC1sZXZlbFxyXG4gICAgICogIHNpbmdsZXRvbiwgc28gbGVmdG92ZXIgbWFwcGluZ3Mgd291bGQgc2lsZW50bHkgbGluayBhIG5ldyBjb3B5IHRvIHJlY29yZHMgY3JlYXRlZFxyXG4gICAgICogIGR1cmluZyB0aGUgcHJldmlvdXMgb25lLiAqL1xyXG4gICAgcHJpdmF0ZSByZXNldFJ1blN0YXRlKHRhcmdldFNwYWNlSWQ6IHN0cmluZykge1xyXG4gICAgICAgIHRoaXMuZWxlbWVudElkcyA9IHt9O1xyXG4gICAgICAgIHRoaXMuY29tbWVudElkcyA9IG5ldyBNYXAoKTtcclxuICAgICAgICB0aGlzLnNvdXJjZUhhc2h0YWdOYW1lcyA9IG5ldyBNYXAoKTtcclxuICAgICAgICB0aGlzLnRhcmdldEhhc2h0YWdJZHNCeU5hbWUgPSBuZXcgTWFwKCk7XHJcbiAgICAgICAgdGhpcy5jcmVhdGVkSGFzaHRhZ0lkcyA9IG5ldyBTZXQoKTtcclxuICAgICAgICB0aGlzLnVzZWRIYXNodGFnSWRzID0gbmV3IFNldCgpO1xyXG4gICAgICAgIHRoaXMuaGFuZGxlZEVsZW1lbnRJZHMgPSBuZXcgU2V0KCk7XHJcbiAgICAgICAgdGhpcy5zb3VyY2VNaXNzaW9uVXNlcklkcyA9IG5ldyBNYXAoKTtcclxuICAgICAgICB0aGlzLnRhcmdldE1pc3Npb25JZHNCeVVzZXJJZCA9IG5ldyBNYXAoKTtcclxuICAgICAgICB0aGlzLmRvbWFpbnNCeUlkID0gbmV3IE1hcCgpO1xyXG4gICAgICAgIHRoaXMudGFyZ2V0VmlzaWJsZURvbWFpbk9yZ0lkcyA9IG5ldyBTZXQoKTtcclxuICAgICAgICB0aGlzLnRhcmdldERvbWFpbklkc0J5VHlwZUFuZE5hbWUgPSBuZXcgTWFwKCk7XHJcbiAgICAgICAgdGhpcy50YXJnZXRTcGFjZUlkID0gdGFyZ2V0U3BhY2VJZDtcclxuICAgIH1cclxuXHJcbiAgICAvKiogQnVpbGRzIGFuZCBzZXRzIGEgc3RlcCdzIGxvZyBsaW5lIGFzIFwiPHRyYW5zbGF0ZWQgbGFiZWw+OiA8cGVyY2VudD4lXCIsIG5vIHN0ZXAgbnVtYmVyaW5nLiAqL1xyXG4gICAgcHJpdmF0ZSBzZXRTdGVwUHJvZ3Jlc3Moc3RlcElkOiBzdHJpbmcsIHRyYW5zbGF0aW9uS2V5OiBzdHJpbmcsIHBlcmNlbnQ6IG51bWJlcikge1xyXG4gICAgICAgIGNvbnN0IGxhYmVsID0gdGhpcy50cmFuc2xhdGUuaW5zdGFudChgbWF0dGVycG9ydENvcHkuJHt0cmFuc2xhdGlvbktleX1gKTtcclxuICAgICAgICB0aGlzLnNldFN0ZXBMb2coc3RlcElkLCBgJHtsYWJlbH06ICR7cGVyY2VudH0lYCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIExvZ3MgYSB0cmFuc2xhdGVkLCBwYXJhbWV0ZXJpemVkIGVycm9yIGxpbmUgZm9yIGEgc2luZ2xlIGZhaWxlZCBpdGVtLiAqL1xyXG4gICAgcHJpdmF0ZSBsb2dJdGVtRXJyb3IodHJhbnNsYXRpb25LZXk6IHN0cmluZywgcGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KSB7XHJcbiAgICAgICAgY29uc3QgdGV4dCA9IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoYG1hdHRlcnBvcnRDb3B5LiR7dHJhbnNsYXRpb25LZXl9YCwgcGFyYW1zKTtcclxuICAgICAgICB0aGlzLmFwcGVuZEVycm9yTG9nKHRleHQpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBMb2dzIGEgdHJhbnNsYXRlZCBsaW5lIGZvciBhbiBpdGVtIHRoYXQgYWxyZWFkeSBleGlzdGVkIGluIHRoZSB0YXJnZXQgc3BhY2UgYW5kIGhhZFxyXG4gICAgICogIGl0cyBtaXNzaW5nIGlkZW50aXR5IGZpZWxkcyBmaWxsZWQgaW4sIHNvIHRoZSBvcGVyYXRvciBjYW4gdGVsbCBpdCBhcGFydCBmcm9tIGFcclxuICAgICAqICBmcmVzaGx5IGNyZWF0ZWQgaXRlbSBpbiB0aGUgY29weSByZXBvcnQuICovXHJcbiAgICBwcml2YXRlIGxvZ0hlYWxlZEl0ZW0odHJhbnNsYXRpb25LZXk6IHN0cmluZywgaXRlbUxhYmVsOiBzdHJpbmcsIGhlYWxlZEZpZWxkczogc3RyaW5nW10pOiB2b2lkIHtcclxuICAgICAgICBjb25zdCB0ZXh0ID0gdGhpcy50cmFuc2xhdGUuaW5zdGFudChgbWF0dGVycG9ydENvcHkuJHt0cmFuc2xhdGlvbktleX1gLCB7XHJcbiAgICAgICAgICAgIG5hbWU6IGl0ZW1MYWJlbCxcclxuICAgICAgICAgICAgZmllbGRzOiBoZWFsZWRGaWVsZHMuam9pbignLCAnKVxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIHRoaXMuYXBwZW5kSGVhbGVkTG9nKHRleHQpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBMb2dzIGFuIGl0ZW0tbGV2ZWwgZXJyb3IsIHVzaW5nIGEgc3BlY2lmaWMgXCJtaXNzaW5nIGZpbGUgLyBvcnBoYW5lZCByZWZlcmVuY2VcIlxyXG4gICAgICogIHRyYW5zbGF0aW9uIGtleSB3aGVuIHRoZSBjYXVzZSBpcyBhIE1pc3NpbmdTM0ZpbGVFcnJvciwgYW5kIHRoZSBnZW5lcmljIHBlci10eXBlXHJcbiAgICAgKiAga2V5IG90aGVyd2lzZS4gS2VlcHMgdGhlIGNvcHkgbG9nIHJlYWRhYmxlOiBhIG1pc3NpbmcgZmlsZSBpcyBub3QgYSBidWcgdG9cclxuICAgICAqICBpbnZlc3RpZ2F0ZSB0aGUgc2FtZSB3YXkgYSBuZXR3b3JrL3Blcm1pc3Npb24gZXJyb3IgaXMuXHJcbiAgICAgKiAgYGV4dHJhUGFyYW1zYCBjYXJyaWVzIHRoZSBwbGFjZWhvbGRlcnMgYSBmZXcga2V5cyBuZWVkIG9uIHRvcCBvZiB7e25hbWV9fS97e2Vycm9yfX1cclxuICAgICAqICAoZS5nLiBlcnJvckZlYXR1cmVBdHRhY2htZW50J3Mge3tmZWF0dXJlfX0sIGVycm9yUG9pJ3Mge3tzd2VlcH19KSwgd2hpY2ggdXNlZCB0byBiZVxyXG4gICAgICogIHJlbmRlcmVkIGFzIHJhdyBcInt7ZmVhdHVyZX19XCIgdGV4dCBpbiB0aGUgbG9nLiAqL1xyXG4gICAgcHJpdmF0ZSBsb2dDb3B5SXRlbUVycm9yKFxyXG4gICAgICAgIGVycm9yOiB1bmtub3duLFxyXG4gICAgICAgIGdlbmVyaWNLZXk6IHN0cmluZyxcclxuICAgICAgICBpdGVtTGFiZWw6IHN0cmluZyxcclxuICAgICAgICBleHRyYVBhcmFtczogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9XHJcbiAgICApIHtcclxuICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBNaXNzaW5nUzNGaWxlRXJyb3IpIHtcclxuICAgICAgICAgICAgdGhpcy5sb2dJdGVtRXJyb3IoJ2Vycm9yTWlzc2luZ1MzRmlsZVNraXBwZWQnLCB7XHJcbiAgICAgICAgICAgICAgICAuLi5leHRyYVBhcmFtcyxcclxuICAgICAgICAgICAgICAgIG5hbWU6IGl0ZW1MYWJlbCxcclxuICAgICAgICAgICAgICAgIGZpbGU6IGVycm9yLnNvdXJjZUtleVxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aGlzLmxvZ0l0ZW1FcnJvcihnZW5lcmljS2V5LCB7IC4uLmV4dHJhUGFyYW1zLCBuYW1lOiBpdGVtTGFiZWwsIGVycm9yOiB0b0Vycm9yTWVzc2FnZShlcnJvcikgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTnVsbC1zYWZlIGVxdWl2YWxlbnQgb2YgRmVhdHVyZVNlcnZpY2UuaXNBcmNoaXZlZCgpOiB0cnVlIHdoZW4gdGhlIG9wZXJhdG9yIGhhcyBhcmNoaXZlZFxyXG4gICAgICogdGhpcyBmZWF0dXJlIG9uIHRoYXQgc3BhY2UuIFwiTm8gbWlzc2lvbiBvbiB0aGUgc3BhY2VcIiBhbnN3ZXJzIGZhbHNlIChub3RoaW5nIGFyY2hpdmVkKVxyXG4gICAgICogaW5zdGVhZCBvZiB0aHJvd2luZywgd2hpY2ggaXMgd2hhdCBtYWRlIGEgY29weSBmcm9tIGEgc3BhY2UgdGhlIG9wZXJhdG9yIGlzIG5vdCBhIG1lbWJlclxyXG4gICAgICogb2YgZmFpbCBvdXRyaWdodC5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBpc0FyY2hpdmVkRm9yT3BlcmF0b3IoZmVhdHVyZTogRmVhdHVyZSwgc3BhY2VJZDogc3RyaW5nKTogYm9vbGVhbiB7XHJcbiAgICAgICAgY29uc3QgYXJjaGl2ZWRGb3IgPSBmZWF0dXJlPy5hcmNoaXZlZEZvck1pc3Npb25JRDtcclxuICAgICAgICBpZiAoIWFyY2hpdmVkRm9yIHx8IGFyY2hpdmVkRm9yLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNvbnN0IG1pc3Npb24gPSB0aGlzLnVzZXJTZXJ2aWNlLmN1cnJlbnRNaXNzaW9uKHNwYWNlSWQpO1xyXG4gICAgICAgIHJldHVybiBtaXNzaW9uPy5pZCA/IGFyY2hpdmVkRm9yLmluY2x1ZGVzKG1pc3Npb24uaWQpIDogZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgLy9cclxuICAgIC8vIC0tLS0tLS0tLS0gQ3Jvc3Mtc3BhY2UgcmVmZXJlbmNlIHJlbWFwcGluZyAtLS0tLS0tLS0tXHJcbiAgICAvL1xyXG5cclxuICAgIC8qKiBOb3JtYWxpc2VkIGxvb2t1cCBrZXkgZm9yIGEgZG9tYWluOiB0eXBlIGRpc2FtYmlndWF0ZXMgc2FtZS1uYW1lZCBkb21haW5zIHVzZWQgZm9yXHJcbiAgICAgKiAgZGlmZmVyZW50IHB1cnBvc2VzIChlcXVpcG1lbnQgdnMuIHRpY2tldCB2cy4gZmVhdHVyZSBjYXRlZ29yaWVzLCAuLi4pLiAqL1xyXG4gICAgcHJpdmF0ZSBkb21haW5LZXkodHlwZTogYW55LCBuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgICAgIHJldHVybiBgJHt0eXBlIHx8ICcnfTo6JHsobmFtZSB8fCAnJykudHJpbSgpLnRvTG93ZXJDYXNlKCl9YDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJFQUQtT05MWSBpbmRleGluZyBvZiBldmVyeSBkb21haW4gZWl0aGVyIG9wZXJhdG9yJ3MgTWlzc2lvbiBjYW4gc2VlLiBDcmVhdGVzXHJcbiAgICAgKiBub3RoaW5nIOKAlCB1bmxpa2UgaGFzaHRhZ3MsIGEgZG9tYWluIGlzIGEgYnVzaW5lc3MgdGF4b25vbXkgZW50cnkgYW4gb3BlcmF0b3IgbWFuYWdlc1xyXG4gICAgICogZGVsaWJlcmF0ZWx5OyB0aGlzIHRvb2wgb25seSBldmVyIHJldXNlcyBhbiBFWElTVElORyBlcXVpdmFsZW50LCBpdCBuZXZlciBpbnZlbnRzIG9uZS5cclxuICAgICAqXHJcbiAgICAgKiBWaXNpYmlsaXR5IGlzIGtleWVkIHRvIGBjdXJyZW50TWlzc2lvbihzcGFjZUlkKS5vcmdhbmlzYXRpb25JRGAgL1xyXG4gICAgICogYC5vcmRlcmVkT3JnYW5pc2F0aW9uSURgIGZvciBFQUNIIHNwYWNlIOKAlCBleGFjdGx5IHdoYXRcclxuICAgICAqIGBEb21haW5TZXJ2aWNlLmdldERvbWFpbnNGb3JPcmdGb3JUeXBlKClgIHVzZXMgdG8gcG9wdWxhdGUgdGhlIGNhdGVnb3J5IGRyb3Bkb3duIG9uXHJcbiAgICAgKiB0aGUgZXF1aXBtZW50L3RpY2tldC9mZWF0dXJlIGVkaXQgZm9ybXMgKHNlZSBmb3JtLWVxdWlwbWVudC5jb21wb25lbnQudHMsXHJcbiAgICAgKiBiYXRjaC1lZGl0LWVxdWlwbWVudC5jb21wb25lbnQudHMsIGZvcm0tZmVhdHVyZS5jb21wb25lbnQudHMpLiBDb21wYXJpbmcgdGhlIHNwYWNlcydcclxuICAgICAqIE9XTiBgb3JnYW5pc2F0aW9uSURgIGluc3RlYWQg4oCUIHRoZSBwcmV2aW91cyBhcHByb2FjaCDigJQgbWlzc2VkIGV2ZXJ5IGRvbWFpbiByZWFjaGFibGVcclxuICAgICAqIG9ubHkgdGhyb3VnaCB0aGUgb3BlcmF0b3IncyBgb3JkZXJlZE9yZ2FuaXNhdGlvbklEYCAoc2V0IHdoZW4gYSBtaXNzaW9uIGlzIGNyZWF0ZWQgXCJvblxyXG4gICAgICogYmVoYWxmIG9mXCIgYW5vdGhlciBvcmdhbmlzYXRpb24g4oCUIHNlZSBmb3JtLW1pc3Npb24uY29tcG9uZW50LnRzKSwgd2hpY2ggaXMgZXhhY3RseSBob3dcclxuICAgICAqIGEgZG9tYWluIGVuZHMgdXAgdmlzaWJsZSBvbiB0d28gc3BhY2VzIHRoYXQgYmVsb25nIHRvIGRpZmZlcmVudCBvcmdhbmlzYXRpb25zLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGFzeW5jIGxvYWREb21haW5JbmRleChzb3VyY2VTcGFjZUlkOiBzdHJpbmcsIHRhcmdldFNwYWNlSWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgICAgIGNvbnN0IHNvdXJjZU1pc3Npb24gPSB0aGlzLnVzZXJTZXJ2aWNlLmN1cnJlbnRNaXNzaW9uKHNvdXJjZVNwYWNlSWQpO1xyXG4gICAgICAgIGNvbnN0IHRhcmdldE1pc3Npb24gPSB0aGlzLnVzZXJTZXJ2aWNlLmN1cnJlbnRNaXNzaW9uKHRhcmdldFNwYWNlSWQpO1xyXG5cclxuICAgICAgICBjb25zdCBzb3VyY2VPcmdJZHMgPSBbc291cmNlTWlzc2lvbj8ub3JnYW5pc2F0aW9uSUQsIHNvdXJjZU1pc3Npb24/Lm9yZGVyZWRPcmdhbmlzYXRpb25JRF1cclxuICAgICAgICAgICAgLmZpbHRlcigoaWQpOiBpZCBpcyBzdHJpbmcgPT4gISFpZCk7XHJcbiAgICAgICAgY29uc3QgdGFyZ2V0T3JnSWRzID0gW3RhcmdldE1pc3Npb24/Lm9yZ2FuaXNhdGlvbklELCB0YXJnZXRNaXNzaW9uPy5vcmRlcmVkT3JnYW5pc2F0aW9uSURdXHJcbiAgICAgICAgICAgIC5maWx0ZXIoKGlkKTogaWQgaXMgc3RyaW5nID0+ICEhaWQpO1xyXG4gICAgICAgIHRoaXMudGFyZ2V0VmlzaWJsZURvbWFpbk9yZ0lkcyA9IG5ldyBTZXQodGFyZ2V0T3JnSWRzKTtcclxuXHJcbiAgICAgICAgY29uc3QgYWxsT3JnSWRzID0gQXJyYXkuZnJvbShuZXcgU2V0KFsuLi5zb3VyY2VPcmdJZHMsIC4uLnRhcmdldE9yZ0lkc10pKTtcclxuICAgICAgICBpZiAoYWxsT3JnSWRzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAvLyBUaGUgb3BlcmF0b3IgaGFzIG5vIG1pc3Npb24gb24gZWl0aGVyIHNwYWNlIOKAlCBub3RoaW5nIHRvIHJlc29sdmUgYWdhaW5zdDtcclxuICAgICAgICAgICAgLy8gZXZlcnkgZG9tYWluSUQgd2lsbCBiZSBkcm9wcGVkLCBzYW1lIGFzIGFuIHVucmVzb2x2YWJsZSBsb29rdXAgZWxzZXdoZXJlLlxyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBjb25zdCBkb21haW5MaXN0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxyXG4gICAgICAgICAgICAgICAgYWxsT3JnSWRzLm1hcChvcmdJZCA9PiB0aGlzLmRvbWFpblNlcnZpY2UuZ2V0QWxsR2VuZXJpY0RvbWFpbnNBbmRGb3JPcmdhbmlzYXRpb24ob3JnSWQpKVxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGxpc3Qgb2YgZG9tYWluTGlzdHMpIHtcclxuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZG9tYWluIG9mIGxpc3QgfHwgW10pIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tYWluPy5pZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRvbWFpbnNCeUlkLnNldChkb21haW4uaWQsIGRvbWFpbik7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdbTWF0dGVycG9ydFRhZ0NvcHlTZXJ2aWNlXSBDb3VsZCBub3QgcmVhZCB0aGUgZG9tYWlucywgY3Jvc3Mtb3JnYW5pc2F0aW9uIGNhdGVnb3JpZXMgd2lsbCBiZSBkcm9wcGVkOicsIGVycm9yKTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZm9yIChjb25zdCBkb21haW4gb2YgdGhpcy5kb21haW5zQnlJZC52YWx1ZXMoKSkge1xyXG4gICAgICAgICAgICBjb25zdCB2aXNpYmxlVG9UYXJnZXQgPSAhZG9tYWluLm9yZ2FuaXNhdGlvbklEIHx8IHRoaXMudGFyZ2V0VmlzaWJsZURvbWFpbk9yZ0lkcy5oYXMoZG9tYWluLm9yZ2FuaXNhdGlvbklEKTtcclxuICAgICAgICAgICAgaWYgKHZpc2libGVUb1RhcmdldCAmJiBkb21haW4ubmFtZSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy50YXJnZXREb21haW5JZHNCeVR5cGVBbmROYW1lLnNldCh0aGlzLmRvbWFpbktleShkb21haW4udHlwZSwgZG9tYWluLm5hbWUpLCBkb21haW4uaWQpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmVzb2x2ZXMgYSBzb3VyY2UgZG9tYWluSUQgKGVxdWlwbWVudC90aWNrZXQvZmVhdHVyZS9QT0kgY2F0ZWdvcnkpIGZvciB1c2UgaW4gdGhlXHJcbiAgICAgKiB0YXJnZXQgc3BhY2UuXHJcbiAgICAgKlxyXG4gICAgICogIC0gZ2VuZXJpYyBkb21haW4gKG5vIG9yZ2FuaXNhdGlvbklEIG9mIGl0cyBvd24g4oCUIGEgc2hhcmVkIHRheG9ub215IGVudHJ5LCBlLmcuIGFcclxuICAgICAqICAgIHN0YW5kYXJkIGNhdGVnb3J5IGNyZWF0ZWQgYnkgdGhlIHBsYXRmb3JtKTogcmV1c2VkIHVuY2hhbmdlZCwgdmFsaWQgZXZlcnl3aGVyZS5cclxuICAgICAqICAtIHRoZSBkb21haW4ncyBvd24gb3JnYW5pc2F0aW9uSUQgaXMgYWxyZWFkeSBvbmUgdGhlIFRBUkdFVCBvcGVyYXRvcidzIG1pc3Npb24gY2FuXHJcbiAgICAgKiAgICBzZWUgKGl0cyBvcmdhbmlzYXRpb25JRCwgb3IgaXRzIG9yZGVyZWRPcmdhbmlzYXRpb25JRCk6IHJldXNlZCB1bmNoYW5nZWQgdG9vIOKAlCB0aGVcclxuICAgICAqICAgIGlkIGlzIGRpcmVjdGx5IHNlbGVjdGFibGUgaW4gdGhlIHRhcmdldCBzcGFjZSdzIG93biBkcm9wZG93biBhcy1pcy5cclxuICAgICAqICAtIG90aGVyd2lzZTogbWF0Y2hlZCBieSAodHlwZSwgbmFtZSkgYWdhaW5zdCB0aGUgZG9tYWlucyB2aXNpYmxlIHRvIHRoZSBUQVJHRVRcclxuICAgICAqICAgIG9wZXJhdG9yIChsb2FkRG9tYWluSW5kZXgoKSk7IGRyb3BwZWQgd2hlbiBubyBlcXVpdmFsZW50IGV4aXN0cyB0aGVyZS5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSByZXNvbHZlRG9tYWluSUQoc291cmNlRG9tYWluSWQ6IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQpOiBzdHJpbmcgfCBudWxsIHtcclxuICAgICAgICBpZiAoIXNvdXJjZURvbWFpbklkKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgZG9tYWluID0gdGhpcy5kb21haW5zQnlJZC5nZXQoc291cmNlRG9tYWluSWQpO1xyXG4gICAgICAgIGlmICghZG9tYWluKSB7XHJcbiAgICAgICAgICAgIC8vIE5vdCB2aXNpYmxlIHRvIGVpdGhlciBvcGVyYXRvcidzIG1pc3Npb24gKGxvb2t1cCBmYWlsZWQsIG9yIGl0IGJlbG9uZ3MgdG9cclxuICAgICAgICAgICAgLy8gbmVpdGhlcikg4oCUIHVuY2hhbmdlZCwgc2FmZXN0IHRvIGRyb3AuXHJcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoIWRvbWFpbi5vcmdhbmlzYXRpb25JRCB8fCB0aGlzLnRhcmdldFZpc2libGVEb21haW5PcmdJZHMuaGFzKGRvbWFpbi5vcmdhbmlzYXRpb25JRCkpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHNvdXJjZURvbWFpbklkO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdGhpcy50YXJnZXREb21haW5JZHNCeVR5cGVBbmROYW1lLmdldCh0aGlzLmRvbWFpbktleShkb21haW4udHlwZSwgZG9tYWluLm5hbWUpKSA/PyBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBOb3JtYWxpc2VkIGxvb2t1cCBrZXkgZm9yIGEgaGFzaHRhZyBuYW1lLCBzbyBcIk1veWVuIMOCZ2VcIiBhbmQgXCJtb3llbiDDomdlIFwiIG1hdGNoLiAqL1xyXG4gICAgcHJpdmF0ZSBoYXNodGFnS2V5KG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIG5hbWUudHJpbSgpLnRvTG93ZXJDYXNlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSRUFELU9OTFkgaW5kZXhpbmcgb2YgYm90aCBzcGFjZXMnIGhhc2h0YWdzLiBDcmVhdGVzIG5vdGhpbmcuXHJcbiAgICAgKlxyXG4gICAgICogYEZlYXR1cmUuaGFzaHRhZ3NgIHN0b3JlcyBIYXNodGFnICppZHMqLCBhbmQgYSBIYXNodGFnIGlzIGEgcGVyLXNwYWNlIHJlY29yZCwgc28gdGhlXHJcbiAgICAgKiBpZHMgaGF2ZSB0byBiZSB0cmFuc2xhdGVkIGJ5IG5hbWUuIFRoZSB0cmFuc2xhdGlvbiB0YWJsZSBpcyBidWlsdCBoZXJlOyB0aGUgbWlzc2luZ1xyXG4gICAgICoga2V5d29yZHMgYXJlIGNyZWF0ZWQgbGF0ZXIsIG9uZSBhdCBhIHRpbWUsIG9ubHkgd2hlbiBhIFBPSSB0aGF0IGFjdHVhbGx5IHVzZXMgdGhlbSBpc1xyXG4gICAgICogYWJvdXQgdG8gYmUgd3JpdHRlbiAoc2VlIHJlc29sdmVIYXNodGFnSWRzKCkpLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGFzeW5jIGxvYWRIYXNodGFnSW5kZXgoc291cmNlU3BhY2VJZDogc3RyaW5nLCB0YXJnZXRTcGFjZUlkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICBsZXQgc291cmNlSGFzaHRhZ3M6IEhhc2h0YWdbXSA9IFtdO1xyXG4gICAgICAgIGxldCB0YXJnZXRIYXNodGFnczogSGFzaHRhZ1tdID0gW107XHJcblxyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIFtzb3VyY2VIYXNodGFncywgdGFyZ2V0SGFzaHRhZ3NdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xyXG4gICAgICAgICAgICAgICAgdGhpcy5oYXNodGFnU2VydmljZS5saXN0SGFzaHRhZ3NGb3JTcGFjZShzb3VyY2VTcGFjZUlkKSxcclxuICAgICAgICAgICAgICAgIHRoaXMuaGFzaHRhZ1NlcnZpY2UubGlzdEhhc2h0YWdzRm9yU3BhY2UodGFyZ2V0U3BhY2VJZClcclxuICAgICAgICAgICAgXSk7XHJcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdbTWF0dGVycG9ydFRhZ0NvcHlTZXJ2aWNlXSBDb3VsZCBub3QgcmVhZCB0aGUgaGFzaHRhZ3MsIGtleXdvcmRzIHdpbGwgYmUgZHJvcHBlZDonLCBlcnJvcik7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGZvciAoY29uc3QgaGFzaHRhZyBvZiBzb3VyY2VIYXNodGFncyB8fCBbXSkge1xyXG4gICAgICAgICAgICBpZiAoaGFzaHRhZz8uaWQgJiYgaGFzaHRhZy5uYW1lKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnNvdXJjZUhhc2h0YWdOYW1lcy5zZXQoaGFzaHRhZy5pZCwgaGFzaHRhZy5uYW1lKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBmb3IgKGNvbnN0IGhhc2h0YWcgb2YgdGFyZ2V0SGFzaHRhZ3MgfHwgW10pIHtcclxuICAgICAgICAgICAgaWYgKGhhc2h0YWc/LmlkICYmIGhhc2h0YWcubmFtZSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy50YXJnZXRIYXNodGFnSWRzQnlOYW1lLnNldCh0aGlzLmhhc2h0YWdLZXkoaGFzaHRhZy5uYW1lKSwgaGFzaHRhZy5pZCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUcmFuc2xhdGVzIG9uZSBmZWF0dXJlJ3MgaGFzaHRhZyBpZHMgaW50byB0YXJnZXQtc3BhY2UgaWRzLCBjcmVhdGluZyBvbiB0aGUgZmx5IHRoZVxyXG4gICAgICoga2V5d29yZHMgdGhlIHRhcmdldCBzcGFjZSBkb2VzIG5vdCBoYXZlIHlldC5cclxuICAgICAqXHJcbiAgICAgKiBDcmVhdGlvbiBpcyBMQVpZIG9uIHB1cnBvc2UuIERvaW5nIGl0IHVwIGZyb250LCBmb3IgdGhlIHdob2xlIHNvdXJjZSB2b2NhYnVsYXJ5LCBtZWFudFxyXG4gICAgICogdGhhdCBhIGNvcHkgd2hpY2ggZmFpbGVkIG9yIHdhcyBjbG9zZWQgaGFsZndheSBsZWZ0IGJlaGluZCBrZXl3b3JkcyBubyBQT0kgcmVmZXJlbmNlZCDigJRcclxuICAgICAqIHBvbGx1dGlvbiB0aGUgb3BlcmF0b3IgaGFkIHRvIGNsZWFuIHVwIGJ5IGhhbmQuIEhlcmUgYSBrZXl3b3JkIGlzIG9ubHkgZXZlciB3cml0dGVuXHJcbiAgICAgKiB3aGVuIGEgUE9JIHRoYXQgY2FycmllcyBpdCBpcyBhYm91dCB0byBiZSBjcmVhdGVkLCBzbyBhbiBpbnRlcnJ1cHRlZCBjb3B5IHN0b3BzXHJcbiAgICAgKiBjcmVhdGluZyBrZXl3b3JkcyBhdCB0aGUgc2FtZSBQT0kgaXQgc3RvcHMgY3JlYXRpbmcgY29udGVudC5cclxuICAgICAqXHJcbiAgICAgKiBUaGUgcmVzaWR1YWwgd2luZG93IChrZXl3b3JkIGNyZWF0ZWQsIHRoZW4gY3JlYXRlRmVhdHVyZSBmYWlscykgaXMgY2xvc2VkIGJ5XHJcbiAgICAgKiBtYXJrSGFzaHRhZ3NVc2VkKCkgKyBjbGVhbnVwVW51c2VkQ3JlYXRlZEhhc2h0YWdzKCkuXHJcbiAgICAgKlxyXG4gICAgICogQSBrZXl3b3JkIHRoYXQgY2FuIG5laXRoZXIgYmUgZm91bmQgbm9yIGNyZWF0ZWQgaXMgZHJvcHBlZCByYXRoZXIgdGhhbiBsZWZ0IGFzIGFcclxuICAgICAqIGRhbmdsaW5nIGlkLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGFzeW5jIHJlc29sdmVIYXNodGFnSWRzKFxyXG4gICAgICAgIHNvdXJjZUhhc2h0YWdJZHM6IEFycmF5PHN0cmluZyB8IG51bGw+IHwgbnVsbCB8IHVuZGVmaW5lZCxcclxuICAgICAgICB0YXJnZXRTcGFjZUlkOiBzdHJpbmdcclxuICAgICk6IFByb21pc2U8c3RyaW5nW10gfCBudWxsPiB7XHJcbiAgICAgICAgaWYgKCFzb3VyY2VIYXNodGFnSWRzIHx8IHNvdXJjZUhhc2h0YWdJZHMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgcmVzb2x2ZWQ6IHN0cmluZ1tdID0gW107XHJcblxyXG4gICAgICAgIGZvciAoY29uc3Qgc291cmNlSWQgb2Ygc291cmNlSGFzaHRhZ0lkcykge1xyXG4gICAgICAgICAgICBpZiAoIXNvdXJjZUlkKSB7XHJcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBjb25zdCBuYW1lID0gdGhpcy5zb3VyY2VIYXNodGFnTmFtZXMuZ2V0KHNvdXJjZUlkKTtcclxuICAgICAgICAgICAgaWYgKCFuYW1lKSB7XHJcbiAgICAgICAgICAgICAgICAvLyB0aGUgc291cmNlIGlkIHBvaW50cyBhdCBhIGhhc2h0YWcgdGhhdCBubyBsb25nZXIgZXhpc3RzIOKAlCBub3RoaW5nIHRvIGNhcnJ5IG92ZXJcclxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCBrZXkgPSB0aGlzLmhhc2h0YWdLZXkobmFtZSk7XHJcbiAgICAgICAgICAgIGxldCB0YXJnZXRJZCA9IHRoaXMudGFyZ2V0SGFzaHRhZ0lkc0J5TmFtZS5nZXQoa2V5KTtcclxuXHJcbiAgICAgICAgICAgIGlmICghdGFyZ2V0SWQpIHtcclxuICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY3JlYXRlZCA9IGF3YWl0IHRoaXMuaGFzaHRhZ1NlcnZpY2UuY3JlYXRlSGFzaHRhZ0ZvclNwYWNlKG5hbWUsIHRhcmdldFNwYWNlSWQpO1xyXG4gICAgICAgICAgICAgICAgICAgIHRhcmdldElkID0gY3JlYXRlZD8uaWQ7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRhcmdldElkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudGFyZ2V0SGFzaHRhZ0lkc0J5TmFtZS5zZXQoa2V5LCB0YXJnZXRJZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3JlYXRlZEhhc2h0YWdJZHMuYWRkKHRhcmdldElkKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihgW01hdHRlcnBvcnRUYWdDb3B5U2VydmljZV0gQ291bGQgbm90IGNyZWF0ZSB0aGUgaGFzaHRhZyBcIiR7bmFtZX1cIiBpbiB0aGUgdGFyZ2V0IHNwYWNlOmAsIGVycm9yKTtcclxuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKHRhcmdldElkICYmICFyZXNvbHZlZC5pbmNsdWRlcyh0YXJnZXRJZCkpIHtcclxuICAgICAgICAgICAgICAgIHJlc29sdmVkLnB1c2godGFyZ2V0SWQpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gcmVzb2x2ZWQubGVuZ3RoID4gMCA/IHJlc29sdmVkIDogbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJFQUQtT05MWSBpbmRleGluZyBvZiBib3RoIHNwYWNlcycgbWlzc2lvbnMuXHJcbiAgICAgKlxyXG4gICAgICogQSBNaXNzaW9uIGlzIHNjb3BlZCB0byBvbmUgc3BhY2UgKGl0IHBhaXJzIGEgdXNlcklEIHdpdGggYSBzcGFjZUlEKSwgc28gdGhlIGlkIGFcclxuICAgICAqIHNvdXJjZSBjb21tZW50J3MgYG93bmVySURgIHBvaW50cyBhdCBuZXZlciBkZXNpZ25hdGVzIGFueW9uZSBpbiB0aGUgdGFyZ2V0IHNwYWNlLlxyXG4gICAgICogVGhpcyBidWlsZHMgdGhlIHR3byBsb29rdXAgdGFibGVzIHJlc29sdmVDb21tZW50T3duZXJJRCgpIG5lZWRzIHRvIHRyYW5zbGF0ZSBpdDpcclxuICAgICAqIHdoaWNoIHVzZXIgYSBzb3VyY2UgTWlzc2lvbiBpZCBiZWxvbmdzIHRvLCBhbmQgd2hpY2ggTWlzc2lvbiAoaWYgYW55KSB0aGF0IHNhbWVcclxuICAgICAqIHVzZXIgYWxyZWFkeSBob2xkcyBpbiB0aGUgdGFyZ2V0IHNwYWNlLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGFzeW5jIGxvYWRNaXNzaW9uSW5kZXgoc291cmNlU3BhY2VJZDogc3RyaW5nLCB0YXJnZXRTcGFjZUlkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICBsZXQgc291cmNlTWlzc2lvbnM6IE1pc3Npb25bXSA9IFtdO1xyXG4gICAgICAgIGxldCB0YXJnZXRNaXNzaW9uczogTWlzc2lvbltdID0gW107XHJcblxyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIFtzb3VyY2VNaXNzaW9ucywgdGFyZ2V0TWlzc2lvbnNdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xyXG4gICAgICAgICAgICAgICAgdGhpcy5taXNzaW9uU2VydmljZS5nZXRBbGxNaXNzaW9uc0ZvclNwYWNlKHNvdXJjZVNwYWNlSWQpLFxyXG4gICAgICAgICAgICAgICAgdGhpcy5taXNzaW9uU2VydmljZS5nZXRBbGxNaXNzaW9uc0ZvclNwYWNlKHRhcmdldFNwYWNlSWQpXHJcbiAgICAgICAgICAgIF0pO1xyXG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignW01hdHRlcnBvcnRUYWdDb3B5U2VydmljZV0gQ291bGQgbm90IHJlYWQgdGhlIG1pc3Npb25zLCBjb21tZW50IGF1dGhvcnNoaXAgd2lsbCBiZSBkcm9wcGVkOicsIGVycm9yKTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZm9yIChjb25zdCBtaXNzaW9uIG9mIHNvdXJjZU1pc3Npb25zIHx8IFtdKSB7XHJcbiAgICAgICAgICAgIGlmIChtaXNzaW9uPy5pZCAmJiBtaXNzaW9uLnVzZXJJRCkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5zb3VyY2VNaXNzaW9uVXNlcklkcy5zZXQobWlzc2lvbi5pZCwgbWlzc2lvbi51c2VySUQpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGZvciAoY29uc3QgbWlzc2lvbiBvZiB0YXJnZXRNaXNzaW9ucyB8fCBbXSkge1xyXG4gICAgICAgICAgICBpZiAobWlzc2lvbj8uaWQgJiYgbWlzc2lvbi51c2VySUQgJiYgIXRoaXMudGFyZ2V0TWlzc2lvbklkc0J5VXNlcklkLmhhcyhtaXNzaW9uLnVzZXJJRCkpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMudGFyZ2V0TWlzc2lvbklkc0J5VXNlcklkLnNldChtaXNzaW9uLnVzZXJJRCwgbWlzc2lvbi5pZCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUcmFuc2xhdGVzIGEgc291cmNlIGNvbW1lbnQncyBgb3duZXJJRGAgKGEgcGVyLXNwYWNlIE1pc3Npb24gaWQpIGludG8gdGhlIE1pc3Npb24gb2ZcclxuICAgICAqIHRoZSBTQU1FIHVzZXIgaW4gdGhlIHRhcmdldCBzcGFjZSwgc28gdGhlIGNvcHkga2VlcHMgY3JlZGl0aW5nIGl0cyByZWFsIGF1dGhvci5cclxuICAgICAqXHJcbiAgICAgKiBTdWJzdGl0dXRpbmcgdGhlIGN1cnJlbnQgb3BlcmF0b3IncyBtaXNzaW9uIOKAlCB0aGUgd2F5IGBvd25lck1pc3Npb25JRGAgbGVnaXRpbWF0ZWx5XHJcbiAgICAgKiBkb2VzIGZvciB0aWNrZXRzL2VxdWlwbWVudC9mZWF0dXJlcywgd2hpY2ggcmVhbGx5IGRvIGNoYW5nZSBvd25lciBvbiBhIGNvcHkg4oCUIHdvdWxkXHJcbiAgICAgKiBtaXNhdHRyaWJ1dGUgZXZlcnkgY29tbWVudCB0byB3aG9ldmVyIHJhbiB0aGUgY29weSBpbnN0ZWFkIG9mIHdobyBhY3R1YWxseSB3cm90ZSBpdC5cclxuICAgICAqXHJcbiAgICAgKiBXaGVuIHRoZSBvcmlnaW5hbCBhdXRob3IgaGFzIG5vIG1pc3Npb24gaW4gdGhlIHRhcmdldCBzcGFjZSAobmV2ZXIgZ3JhbnRlZCBhY2Nlc3NcclxuICAgICAqIHRoZXJlKSwgdGhlIGNvbW1lbnQgaXMgbGVmdCB3aXRoIG5vIG93bmVyIHJhdGhlciB0aGFuIGEgd3Jvbmcgb25lOiBhbiBhYnNlbnQgYXV0aG9yXHJcbiAgICAgKiBpcyBob25lc3QsIGEgbWlzYXR0cmlidXRlZCBvbmUgaXMgbm90LlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHJlc29sdmVDb21tZW50T3duZXJJRChzb3VyY2VPd25lcklEOiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkKTogc3RyaW5nIHwgbnVsbCB7XHJcbiAgICAgICAgaWYgKCFzb3VyY2VPd25lcklEKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjb25zdCB1c2VySUQgPSB0aGlzLnNvdXJjZU1pc3Npb25Vc2VySWRzLmdldChzb3VyY2VPd25lcklEKTtcclxuICAgICAgICBpZiAoIXVzZXJJRCkge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXMudGFyZ2V0TWlzc2lvbklkc0J5VXNlcklkLmdldCh1c2VySUQpID8/IG51bGw7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIFJlY29yZHMgdGhhdCB0aGVzZSBoYXNodGFncyBhcmUgbm93IHJlZmVyZW5jZWQgYnkgYSBmZWF0dXJlIHRoYXQgcmVhbGx5IGV4aXN0cywgc29cclxuICAgICAqICB0aGUgZW5kLW9mLXJ1biBjbGVhbnVwIGxlYXZlcyB0aGVtIGFsb25lLiAqL1xyXG4gICAgcHJpdmF0ZSBtYXJrSGFzaHRhZ3NVc2VkKGhhc2h0YWdJZHM6IHN0cmluZ1tdIHwgbnVsbCk6IHZvaWQge1xyXG4gICAgICAgIGZvciAoY29uc3QgaWQgb2YgaGFzaHRhZ0lkcyB8fCBbXSkge1xyXG4gICAgICAgICAgICB0aGlzLnVzZWRIYXNodGFnSWRzLmFkZChpZCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGVsZXRlcyB0aGUgaGFzaHRhZ3MgdGhpcyBydW4gY3JlYXRlZCB0aGF0IG5vIGNvcGllZCBQT0kgZW5kZWQgdXAgcmVmZXJlbmNpbmcuXHJcbiAgICAgKlxyXG4gICAgICogUnVucyBvbiBldmVyeSBleGl0IHBhdGgg4oCUIHN1Y2Nlc3MsIGdlbmVyYWwgZmFpbHVyZSwgb3IgZXhjZXB0aW9uIOKAlCBzbyB0aGUgdGFyZ2V0IHNwYWNlXHJcbiAgICAgKiBuZXZlciBrZWVwcyBrZXl3b3JkcyB0aGF0IGNhbWUgZnJvbSBhbiBhYm9ydGVkIGNvcHkuIE9ubHkgaWRzIGNyZWF0ZWQgYnkgVEhJUyBydW4gYXJlXHJcbiAgICAgKiBldmVyIGNvbnNpZGVyZWQ6IGEgcHJlLWV4aXN0aW5nIGtleXdvcmQgb2YgdGhlIHRhcmdldCBzcGFjZSBpcyBuZXZlciB0b3VjaGVkLCBldmVuIGlmXHJcbiAgICAgKiBubyBjb3BpZWQgUE9JIHVzZXMgaXQuXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgYXN5bmMgY2xlYW51cFVudXNlZENyZWF0ZWRIYXNodGFncygpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICBjb25zdCBvcnBoYW5zID0gWy4uLnRoaXMuY3JlYXRlZEhhc2h0YWdJZHNdLmZpbHRlcihpZCA9PiAhdGhpcy51c2VkSGFzaHRhZ0lkcy5oYXMoaWQpKTtcclxuICAgICAgICBpZiAob3JwaGFucy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc29sZS5sb2coYFtNYXR0ZXJwb3J0VGFnQ29weVNlcnZpY2VdIFJlbW92aW5nICR7b3JwaGFucy5sZW5ndGh9IGtleXdvcmQocykgY3JlYXRlZCBidXQgbGVmdCB1bnVzZWQgYnkgdGhpcyBjb3B5LmApO1xyXG5cclxuICAgICAgICBmb3IgKGNvbnN0IGhhc2h0YWdJZCBvZiBvcnBoYW5zKSB7XHJcbiAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmhhc2h0YWdTZXJ2aWNlLmRlbGV0ZUhhc2h0YWdCeUlkKGhhc2h0YWdJZCk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmNyZWF0ZWRIYXNodGFnSWRzLmRlbGV0ZShoYXNodGFnSWQpO1xyXG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICAgICAgICAgICAgLy8gQ2xlYW51cCBpcyBiZXN0LWVmZm9ydDogYSBsZWZ0b3ZlciBrZXl3b3JkIGlzIGhhcm1sZXNzIG5leHQgdG8gYSBmYWlsZWQgY29weSxcclxuICAgICAgICAgICAgICAgIC8vIGFuZCBtdXN0IG5ldmVyIGJlIHRoZSByZWFzb24gdGhlIHdob2xlIG9wZXJhdGlvbiByZXBvcnRzIGEgZmFpbHVyZS5cclxuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihgW01hdHRlcnBvcnRUYWdDb3B5U2VydmljZV0gQ291bGQgbm90IHJlbW92ZSB0aGUgdW51c2VkIGtleXdvcmQgXCIke2hhc2h0YWdJZH1cIjpgLCBlcnJvcik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy9cclxuICAgIC8vIC0tLS0tLS0tLS0gTWVkaWEgY29udGVudCAoQ29tbWVudHMpIC0tLS0tLS0tLS1cclxuICAgIC8vXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBPcmRlcnMgYSBmZWF0dXJlJ3MgbWVkaWEgc2V0IGV4YWN0bHkgdGhlIHdheSB0aGUgVUkgd2lsbCByZWFkIGl0IGJhY2ssIGFuZCByZXBhaXJzXHJcbiAgICAgKiB0aGUgb3JkZXJpbmcga2V5IHdoZW4gdGhlIHNvdXJjZSBkYXRhIGNhbm5vdCBleHByZXNzIHRoZSB1c2VyJ3MgaW50ZW5kZWQgb3JkZXIuXHJcbiAgICAgKlxyXG4gICAgICogVGhlIHZpZXdlciBzb3J0cyBlYWNoIG1lZGlhIGZhbWlseSBvbiBpdHMgb3duIChgc2V0SW1hZ2VzYCwgYHNldFZpZGVvc2AsIGBzZXRBdWRpb2AsXHJcbiAgICAgKiBgc2V0RG9jdW1lbnRzYCwgLi4uIGFsbCBkbyBgLnNvcnQoKGEsIGIpID0+IGEuaW5kZXggLSBiLmluZGV4KWApLCBzbyBgaW5kZXhgIG9ubHkgaGFzXHJcbiAgICAgKiB0byBiZSBjb25zaXN0ZW50IFdJVEhJTiBhIENvbW1lbnRUeXBlLiBUaGUgYXR0YWNobWVudCBmb3JtIGhvd2V2ZXIgZGVmYXVsdHMgYGluZGV4YFxyXG4gICAgICogdG8gMSBmb3IgZXZlcnkgbmV3IGF0dGFjaG1lbnQsIHNvIGEgbXVsdGktaW1hZ2UgUE9JIHZlcnkgb2Z0ZW4gaG9sZHMgc2V2ZXJhbCBpbWFnZXNcclxuICAgICAqIGFsbCBzaGFyaW5nIGluZGV4IDEg4oCUIG9yIG51bGwuIFNvcnRpbmcgdGhvc2UgaXMgbGVmdCB0byBEeW5hbW9EQidzIGFyYml0cmFyeSBzY2FuXHJcbiAgICAgKiBvcmRlciwgd2hpY2ggaXMgd2h5IHRoZSBjb3B5IGNhbWUgb3V0IGluIGEgZGlmZmVyZW50IG9yZGVyIHRoYW4gdGhlIG9yaWdpbmFsLlxyXG4gICAgICpcclxuICAgICAqIFN0cmF0ZWd5OiBzb3J0IGRldGVybWluaXN0aWNhbGx5IChpbmRleCwgdGhlbiBjcmVhdGlvbiBkYXRlLCB0aGVuIGlkIOKAlCBpLmUuIHRoZVxyXG4gICAgICogdXBsb2FkIG9yZGVyIHRoZSB1c2VyIGFjdHVhbGx5IHNhdyksIGFuZCBvbmx5IHJld3JpdGUgdGhlIGluZGljZXMgb2YgYSBmYW1pbHkgd2hlblxyXG4gICAgICogdGhleSBhcmUgYW1iaWd1b3VzIChudWxsIG9yIGR1cGxpY2F0ZWQpLiBBIGZhbWlseSB3aG9zZSBpbmRpY2VzIGFyZSBhbHJlYWR5IHVuaXF1ZVxyXG4gICAgICogaXMgY29waWVkIHVudG91Y2hlZCwgc28gYSBkZWxpYmVyYXRlIG9yZGVyaW5nIGlzIG5ldmVyIG92ZXJ3cml0dGVuLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIG9yZGVyQ29tbWVudHNGb3JDb3B5KGNvbW1lbnRzOiBDb21tZW50W10pOiBDb21tZW50W10ge1xyXG4gICAgICAgIGNvbnN0IHZhbGlkID0gKGNvbW1lbnRzIHx8IFtdKS5maWx0ZXIoYyA9PiAhIWMpO1xyXG5cclxuICAgICAgICBjb25zdCBieVR5cGUgPSBuZXcgTWFwPHN0cmluZywgQ29tbWVudFtdPigpO1xyXG4gICAgICAgIGZvciAoY29uc3QgY29tbWVudCBvZiB2YWxpZCkge1xyXG4gICAgICAgICAgICBjb25zdCBrZXkgPSAoY29tbWVudC50eXBlIGFzIHN0cmluZykgfHwgJ1VOVFlQRUQnO1xyXG4gICAgICAgICAgICBpZiAoIWJ5VHlwZS5oYXMoa2V5KSkge1xyXG4gICAgICAgICAgICAgICAgYnlUeXBlLnNldChrZXksIFtdKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBieVR5cGUuZ2V0KGtleSkucHVzaChjb21tZW50KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IG9yZGVyZWQ6IENvbW1lbnRbXSA9IFtdO1xyXG5cclxuICAgICAgICBmb3IgKGNvbnN0IGZhbWlseSBvZiBieVR5cGUudmFsdWVzKCkpIHtcclxuICAgICAgICAgICAgZmFtaWx5LnNvcnQoKGEsIGIpID0+IHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGFpID0gdGhpcy5vcmRlcmluZ0luZGV4T2YoYSk7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBiaSA9IHRoaXMub3JkZXJpbmdJbmRleE9mKGIpO1xyXG4gICAgICAgICAgICAgICAgaWYgKGFpICE9PSBiaSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhaSAtIGJpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgY29uc3QgYWQgPSB0aGlzLmNyZWF0aW9uVGltZU9mKGEpO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgYmQgPSB0aGlzLmNyZWF0aW9uVGltZU9mKGIpO1xyXG4gICAgICAgICAgICAgICAgaWYgKGFkICE9PSBiZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhZCAtIGJkO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFN0cmluZygoYSBhcyBhbnkpLmlkIHx8ICcnKS5sb2NhbGVDb21wYXJlKFN0cmluZygoYiBhcyBhbnkpLmlkIHx8ICcnKSk7XHJcbiAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgY29uc3QgaW5kaWNlcyA9IGZhbWlseS5tYXAoYyA9PiBjLmluZGV4KTtcclxuICAgICAgICAgICAgY29uc3QgaXNBbWJpZ3VvdXMgPSBpbmRpY2VzLnNvbWUoaSA9PiBpID09PSBudWxsIHx8IGkgPT09IHVuZGVmaW5lZClcclxuICAgICAgICAgICAgICAgIHx8IG5ldyBTZXQoaW5kaWNlcykuc2l6ZSAhPT0gaW5kaWNlcy5sZW5ndGg7XHJcblxyXG4gICAgICAgICAgICBmYW1pbHkuZm9yRWFjaCgoY29tbWVudCwgcG9zaXRpb24pID0+IHtcclxuICAgICAgICAgICAgICAgIChjb21tZW50IGFzIGFueSkuX19jb3B5SW5kZXggPSBpc0FtYmlndW91cyA/IHBvc2l0aW9uICsgMSA6IGNvbW1lbnQuaW5kZXg7XHJcbiAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgb3JkZXJlZC5wdXNoKC4uLmZhbWlseSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gb3JkZXJlZDtcclxuICAgIH1cclxuXHJcbiAgICAvKiogU29ydCBrZXkgZm9yIGEgY29tbWVudCdzIHBvc2l0aW9uOyBhIG1pc3NpbmcgaW5kZXggc29ydHMgbGFzdCwgbm90IGZpcnN0LiAqL1xyXG4gICAgcHJpdmF0ZSBvcmRlcmluZ0luZGV4T2YoY29tbWVudDogQ29tbWVudCk6IG51bWJlciB7XHJcbiAgICAgICAgY29uc3QgaW5kZXggPSBjb21tZW50Py5pbmRleDtcclxuICAgICAgICByZXR1cm4gaW5kZXggPT09IG51bGwgfHwgaW5kZXggPT09IHVuZGVmaW5lZCB8fCBOdW1iZXIuaXNOYU4oTnVtYmVyKGluZGV4KSlcclxuICAgICAgICAgICAgPyBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUlxyXG4gICAgICAgICAgICA6IE51bWJlcihpbmRleCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIENyZWF0aW9uIHRpbWVzdGFtcCBvZiBhIGNvbW1lbnQsIHVzZWQgYXMgdGhlIHRpZS1icmVha2VyOiBpdCByZWZsZWN0cyB0aGUgb3JkZXIgaW5cclxuICAgICAqICB3aGljaCB0aGUgdXNlciB1cGxvYWRlZCB0aGUgbWVkaWEsIHdoaWNoIGlzIHRoZSBvcmRlciB0aGV5IHNhdy4gKi9cclxuICAgIHByaXZhdGUgY3JlYXRpb25UaW1lT2YoY29tbWVudDogQ29tbWVudCk6IG51bWJlciB7XHJcbiAgICAgICAgY29uc3QgY3JlYXRlZEF0ID0gKGNvbW1lbnQgYXMgYW55KT8uY3JlYXRlZEF0O1xyXG4gICAgICAgIGlmICghY3JlYXRlZEF0KSB7XHJcbiAgICAgICAgICAgIHJldHVybiAwO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjb25zdCB0aW1lID0gbmV3IERhdGUoY3JlYXRlZEF0KS5nZXRUaW1lKCk7XHJcbiAgICAgICAgcmV0dXJuIE51bWJlci5pc05hTih0aW1lKSA/IDAgOiB0aW1lO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ29waWVzIE9ORSBtZWRpYSBpdGVtIChpbWFnZSwgdmlkZW8sIGF1ZGlvLCBkb2N1bWVudCwgdGV4dCwgbGluaywgZW1iZWQsIGlmcmFtZS4uLilcclxuICAgICAqIG9mIGEgZmVhdHVyZSwgZHVwbGljYXRpbmcgaXRzIGZpbGUgaW4gUzMgZmlyc3Qgd2hlbiBpdCBoYXMgb25lLlxyXG4gICAgICpcclxuICAgICAqIEV2ZXJ5IGNvbHVtbiBvZiB0aGUgQ29tbWVudCBtb2RlbCBpcyBjYXJyaWVkIG92ZXIuIGBkZXNjcmlwdGlvbmAgYW5kIGBtZXRhZGF0YWAgd2VyZVxyXG4gICAgICogcHJldmlvdXNseSBkcm9wcGVkLCB3aGljaCBlbXB0aWVkIHRoZSBjYXB0aW9ucyBvZiBpbWFnZXMvdmlkZW9zLCB0aGUgYm9keSBvZiBURVhUXHJcbiAgICAgKiBpdGVtcyDigJQgd2hlcmUgdGhlIHdob2xlIGNvbnRlbnQgbGl2ZXMsIHNpbmNlIGEgVEVYVCBjb21tZW50IGhhcyBubyBmaWxlIOKAlCBhbmQgYW55XHJcbiAgICAgKiBwZXItbWVkaWEgc2V0dGluZ3Mgc3RvcmVkIGluIG1ldGFkYXRhLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGFzeW5jIGNvcHlDb21tZW50Rm9yRmVhdHVyZShcclxuICAgICAgICBzb3VyY2VDb21tZW50OiBDb21tZW50LFxyXG4gICAgICAgIHRhcmdldEZlYXR1cmVJZDogc3RyaW5nLFxyXG4gICAgICAgIHRhcmdldFNwYWNlSWQ6IHN0cmluZ1xyXG4gICAgKTogUHJvbWlzZTxDb21tZW50PiB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuY29weUNvbW1lbnQoc291cmNlQ29tbWVudCwgdGFyZ2V0U3BhY2VJZCwgeyBmZWF0dXJlSUQ6IHRhcmdldEZlYXR1cmVJZCB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogU2FtZSwgZm9yIGFuIGF0dGFjaG1lbnQgY2FycmllZCBieSBhIHRpY2tldCByYXRoZXIgdGhhbiBieSBhIGZlYXR1cmUuICovXHJcbiAgICBwcml2YXRlIGFzeW5jIGNvcHlDb21tZW50Rm9yVGlja2V0KFxyXG4gICAgICAgIHNvdXJjZUNvbW1lbnQ6IENvbW1lbnQsXHJcbiAgICAgICAgdGFyZ2V0VGlja2V0SWQ6IHN0cmluZyxcclxuICAgICAgICB0YXJnZXRTcGFjZUlkOiBzdHJpbmdcclxuICAgICk6IFByb21pc2U8Q29tbWVudD4ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmNvcHlDb21tZW50KHNvdXJjZUNvbW1lbnQsIHRhcmdldFNwYWNlSWQsIHsgdGlja2V0SUQ6IHRhcmdldFRpY2tldElkIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBTaGFyZWQgYm9keSBvZiB0aGUgdHdvIGFib3ZlOiBgb3duZXJgIGNhcnJpZXMgd2hpY2hldmVyIGZvcmVpZ24ga2V5IGxpbmtzIHRoZSBjb3B5IGJhY2tcclxuICAgICAqICB0byBpdHMgbmV3IHBhcmVudCwgZXZlcnl0aGluZyBlbHNlIGlzIGlkZW50aWNhbC4gKi9cclxuICAgIHByaXZhdGUgYXN5bmMgY29weUNvbW1lbnQoXHJcbiAgICAgICAgc291cmNlQ29tbWVudDogQ29tbWVudCxcclxuICAgICAgICB0YXJnZXRTcGFjZUlkOiBzdHJpbmcsXHJcbiAgICAgICAgb3duZXI6IHsgZmVhdHVyZUlEPzogc3RyaW5nOyB0aWNrZXRJRD86IHN0cmluZyB9XHJcbiAgICApOiBQcm9taXNlPENvbW1lbnQ+IHtcclxuICAgICAgICBjb25zdCByYXdDb21tZW50ID0gc291cmNlQ29tbWVudCBhcyBhbnk7XHJcblxyXG4gICAgICAgIGxldCBjb3BpZWRBbm5leGU6IHN0cmluZyB8IG51bGwgPSBudWxsO1xyXG4gICAgICAgIGlmIChyYXdDb21tZW50LmFubmV4ZSkge1xyXG4gICAgICAgICAgICBjb3BpZWRBbm5leGUgPSBhd2FpdCB0aGlzLmNvcHlTM0tleUlmUHJlc2VudChyYXdDb21tZW50LmFubmV4ZSwgYGF0dGFjaG1lbnQgXCIke3Jhd0NvbW1lbnQudGl0bGV9XCJgKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGNvbW1lbnRJbnB1dDogYW55ID0ge1xyXG4gICAgICAgICAgICB0aXRsZTogcmF3Q29tbWVudC50aXRsZSxcclxuICAgICAgICAgICAgZGVzY3JpcHRpb246IHJhd0NvbW1lbnQuZGVzY3JpcHRpb24gPz8gbnVsbCxcclxuICAgICAgICAgICAgbWV0YWRhdGE6IHJhd0NvbW1lbnQubWV0YWRhdGEgPz8gbnVsbCxcclxuICAgICAgICAgICAgdHlwZTogcmF3Q29tbWVudC50eXBlLFxyXG4gICAgICAgICAgICBhbm5leGU6IGNvcGllZEFubmV4ZSxcclxuICAgICAgICAgICAgZXh0ZXJuYWxMaW5rOiByYXdDb21tZW50LmV4dGVybmFsTGluayB8fCBudWxsLFxyXG4gICAgICAgICAgICBkaW1lbnNpb25zOiByYXdDb21tZW50LmRpbWVuc2lvbnMgfHwgbnVsbCxcclxuICAgICAgICAgICAgaW5kZXg6IHJhd0NvbW1lbnQuX19jb3B5SW5kZXggPz8gcmF3Q29tbWVudC5pbmRleCA/PyBudWxsLFxyXG4gICAgICAgICAgICBzaG93bkluVGFnOiByYXdDb21tZW50LnNob3duSW5UYWcsXHJcbiAgICAgICAgICAgIGlzQ292ZXJJbWFnZTogcmF3Q29tbWVudC5pc0NvdmVySW1hZ2UsXHJcbiAgICAgICAgICAgIHNwYWNlSUQ6IHRhcmdldFNwYWNlSWQsXHJcbiAgICAgICAgICAgIC8vIEtlZXBzIGNyZWRpdGluZyB0aGUgT1JJR0lOQUwgYXV0aG9yIHdoZW4gdGhleSBhbHNvIGhhdmUgYSBtaXNzaW9uIGluIHRoZVxyXG4gICAgICAgICAgICAvLyB0YXJnZXQgc3BhY2UsIGFuZCBsZWF2ZXMgdGhlIGNvbW1lbnQgdW4tb3duZWQgb3RoZXJ3aXNlIOKAlCBzZWVcclxuICAgICAgICAgICAgLy8gcmVzb2x2ZUNvbW1lbnRPd25lcklEKCkuIE5ldmVyIHRoZSBjdXJyZW50IG9wZXJhdG9yJ3Mgb3duIG1pc3Npb246IHRoYXRcclxuICAgICAgICAgICAgLy8gd291bGQgc2lsZW50bHkgcmVhc3NpZ24gYXV0aG9yc2hpcCB0byB3aG9ldmVyIGhhcHBlbnMgdG8gcnVuIHRoZSBjb3B5LlxyXG4gICAgICAgICAgICBvd25lcklEOiB0aGlzLnJlc29sdmVDb21tZW50T3duZXJJRChyYXdDb21tZW50Lm93bmVySUQpLFxyXG4gICAgICAgICAgICAuLi5vd25lclxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzLmNvbW1lbnRTZXJ2aWNlLmNyZWF0ZUNvbW1lbnQoY29tbWVudElucHV0KTtcclxuICAgIH1cclxuXHJcbiAgICAvL1xyXG4gICAgLy8gLS0tLS0tLS0tLSBQT0kgY3JlYXRpb24gLS0tLS0tLS0tLVxyXG4gICAgLy9cclxuXHJcbiAgICAvKipcclxuICAgICAqIENyZWF0ZXMgdGhlIHRhcmdldC1zcGFjZSBjb3B5IG9mIGEgc291cmNlIFBPSSwgd2l0aCBFVkVSWSBjb2x1bW4gb2YgdGhlIFBPSSBtb2RlbC5cclxuICAgICAqXHJcbiAgICAgKiBTaW5nbGUgZW50cnkgcG9pbnQgZm9yIGFsbCBwaGFzZXM6IHRoZSBlbGVtZW50IHBoYXNlcyAodGlja2V0LCBlcXVpcG1lbnQsIDNEIG9iamVjdCxcclxuICAgICAqIGZlYXR1cmUsIG1lYXN1cmVtZW50KSB1c2VkIHRvIGJ1aWxkIHRoZWlyIFBPSSBpbmxpbmUgd2l0aCBvbmx5IDUgZmllbGRzIOKAlCBjb29yZGluYXRlLFxyXG4gICAgICogdHlwZSwgZWxlbWVudElELCBtZXRhZGF0YSwgc3dlZXAg4oCUIHdoaWNoIGlzIHByZWNpc2VseSBob3cgbXVzZXVtIFBPSXMgbG9zdCB0aGVpclxyXG4gICAgICogcGFzdGlsbGU6IGB0YWdEZXNjcmlwdGlvbmAgKHRoZSBwb3B1cCB0ZXh0KSwgYHRhZ0ljb25gICh0aGUgY3VzdG9tIGljb24pIGFuZFxyXG4gICAgICogYHRhZ0ltYWdlSURgICh0aGUgcGFzdGlsbGUncyBpbWFnZSkgbmV2ZXIgbGVmdCB0aGUgc291cmNlIHNwYWNlLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGFzeW5jIGNyZWF0ZUNvcGllZFBvaShcclxuICAgICAgICBzb3VyY2VQb2k6IFBPSSxcclxuICAgICAgICBlbGVtZW50SUQ6IHN0cmluZyB8IG51bGwsXHJcbiAgICAgICAgc291cmNlTmF2UG9zaXRpb25zOiBNYXA8c3RyaW5nLCBWZWMzPixcclxuICAgICAgICB0YXJnZXROYXZQb3NpdGlvbnM6IE1hcDxzdHJpbmcsIFZlYzM+LFxyXG4gICAgICAgIHRyYW5zZm9ybTogUmlnaWRUcmFuc2Zvcm1cclxuICAgICk6IFByb21pc2U8UE9JPiB7XHJcbiAgICAgICAgY29uc3QgcmF3ID0gc291cmNlUG9pIGFzIGFueTtcclxuXHJcbiAgICAgICAgY29uc3QgdGFyZ2V0U3dlZXBJZCA9IHRoaXMuZmluZENsb3Nlc3RUYXJnZXRTd2VlcElkKFxyXG4gICAgICAgICAgICBzb3VyY2VQb2kubWF0dGVycG9ydFN3ZWVwSUQsIHNvdXJjZU5hdlBvc2l0aW9ucywgdGFyZ2V0TmF2UG9zaXRpb25zLCB0cmFuc2Zvcm1cclxuICAgICAgICApO1xyXG4gICAgICAgIGNvbnN0IGFkanVzdGVkQ29vcmRpbmF0ZSA9IHRoaXMuZ2V0QWRqdXN0ZWRDb29yZGluYXRlcyhzb3VyY2VQb2kuY29vcmRpbmF0ZSwgdHJhbnNmb3JtKTtcclxuXHJcbiAgICAgICAgY29uc3QgcG9pSW5wdXQ6IGFueSA9IHtcclxuICAgICAgICAgICAgY29vcmRpbmF0ZTogYWRqdXN0ZWRDb29yZGluYXRlID09PSBudWxsIHx8IGFkanVzdGVkQ29vcmRpbmF0ZSA9PT0gdW5kZWZpbmVkXHJcbiAgICAgICAgICAgICAgICA/IG51bGxcclxuICAgICAgICAgICAgICAgIDogSlNPTi5zdHJpbmdpZnkoYWRqdXN0ZWRDb29yZGluYXRlKSxcclxuICAgICAgICAgICAgdHlwZTogc291cmNlUG9pLnR5cGUsXHJcbiAgICAgICAgICAgIGVsZW1lbnRJRDogZWxlbWVudElEID8/IG51bGwsXHJcbiAgICAgICAgICAgIG1hdHRlcnBvcnRTd2VlcElEOiB0YXJnZXRTd2VlcElkLFxyXG5cclxuICAgICAgICAgICAgLy8gLS0tIHBhc3RpbGxlICh0YWcgcG9wdXApIC0tLVxyXG4gICAgICAgICAgICB0YWdEZXNjcmlwdGlvbjogc291cmNlUG9pLnRhZ0Rlc2NyaXB0aW9uID8/IG51bGwsXHJcbiAgICAgICAgICAgIHRhZ0ljb246IGF3YWl0IHRoaXMuZHVwbGljYXRlVGFnSWNvbihzb3VyY2VQb2kudGFnSWNvbiksXHJcbiAgICAgICAgICAgIHRhZ0ltYWdlSUQ6IHRoaXMucmVzb2x2ZVRhZ0ltYWdlSUQoc291cmNlUG9pLnRhZ0ltYWdlSUQpLFxyXG5cclxuICAgICAgICAgICAgLy8gLS0tIHJlbmRlcmluZyAvIHZpc2liaWxpdHkgZmxhZ3MsIGNhcnJpZWQgb3ZlciB2ZXJiYXRpbSAtLS1cclxuICAgICAgICAgICAgc3BlY2lmaWM6IHJhdy5zcGVjaWZpYyA/PyBudWxsLFxyXG4gICAgICAgICAgICBwcml2YXRlOiByYXcucHJpdmF0ZSA/PyBudWxsLFxyXG4gICAgICAgICAgICBnbG9iYWw6IHJhdy5nbG9iYWwgPz8gbnVsbCxcclxuICAgICAgICAgICAgbGV2ZWw6IHJhdy5sZXZlbCA/PyBudWxsLFxyXG4gICAgICAgICAgICByb2xlOiByYXcucm9sZSA/PyBudWxsLFxyXG4gICAgICAgICAgICBjYXRlZ29yeTogcmF3LmNhdGVnb3J5ID8/IG51bGwsXHJcbiAgICAgICAgICAgIGRvbWFpbklEOiB0aGlzLnJlc29sdmVEb21haW5JRChyYXcuZG9tYWluSUQpLFxyXG5cclxuICAgICAgICAgICAgLy8gLS0tIE1hdHRlcnBvcnQgYW5jaG9yaW5nIC0tLVxyXG4gICAgICAgICAgICBtZXRhZGF0YTogdGhpcy5nZXRBZGp1c3RlZFBvaU1ldGFkYXRhKHNvdXJjZVBvaS5tZXRhZGF0YSwgdHJhbnNmb3JtKVxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzLnBvaVNlcnZpY2UuY3JlYXRlUE9JRm9yU3BhY2VJRChwb2lJbnB1dCBhcyBQT0kpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQWRhcHRzIGEgUE9JJ3MgYG1ldGFkYXRhYCAoc2VlIE1hdHRlcnRhZ0RhdGEuZ2V0TWV0YWRhdGFTdHJpbmcoKTogeyBpY29uLCBub3JtYWwsIHNpZCB9KVxyXG4gICAgICogdG8gdGhlIHRhcmdldCBzcGFjZS5cclxuICAgICAqXHJcbiAgICAgKiAgLSBgc2lkYCBpcyB0aGUgaWQgb2YgdGhlIE1hdHRlcnRhZyBpbnNpZGUgdGhlIFNPVVJDRSBNYXR0ZXJwb3J0IG1vZGVsLiBDYXJyaWVkIG92ZXIsXHJcbiAgICAgKiAgICB0aGUgdmlld2VyIHRyaWVzIHRvIHJlLWNyZWF0ZSB0aGUgdGFyZ2V0J3MgdGFnIHdpdGggYW4gaWQgYmVsb25naW5nIHRvIGFub3RoZXJcclxuICAgICAqICAgIG1vZGVsIChcImFscmVhZHkgaW4gdXNlXCIpLCBzbyB0aGUgcGFzdGlsbGUgZmFpbHMgdG8gYXR0YWNoLiBJdCBpcyBkcm9wcGVkOiB0aGVcclxuICAgICAqICAgIHZpZXdlciB0aGVuIGFsbG9jYXRlcyBhIGZyZXNoIHNpZCBvbiBmaXJzdCByZW5kZXIuXHJcbiAgICAgKiAgLSBgbm9ybWFsYCBpcyB0aGUgc3RlbSBkaXJlY3Rpb24uIEl0IGlzIGEgZGlyZWN0aW9uLCBzbyBvbmx5IHRoZSByb3RhdGlvbiBhcHBsaWVzXHJcbiAgICAgKiAgICAobmV2ZXIgdGhlIHRyYW5zbGF0aW9uKTsgd2l0aG91dCBpdCwgYSBjb3BpZWQgcGFzdGlsbGUgcG9pbnRzIGludG8gdGhlIHdhbGxcclxuICAgICAqICAgIHdoZW5ldmVyIHRoZSB0d28gbW9kZWxzIGFyZSBub3QgYWxpZ25lZCBvbiB0aGUgc2FtZSBheGlzLlxyXG4gICAgICogIC0gYGljb25gIGFuZCBhbnl0aGluZyBlbHNlIGlzIGtlcHQgYXMtaXMuXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZ2V0QWRqdXN0ZWRQb2lNZXRhZGF0YShtZXRhZGF0YTogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCwgdHJhbnNmb3JtOiBSaWdpZFRyYW5zZm9ybSk6IHN0cmluZyB8IG51bGwge1xyXG4gICAgICAgIGlmICghbWV0YWRhdGEpIHtcclxuICAgICAgICAgICAgcmV0dXJuIG1ldGFkYXRhID8/IG51bGw7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2UobWV0YWRhdGEpO1xyXG4gICAgICAgICAgICBpZiAoIXBhcnNlZCB8fCB0eXBlb2YgcGFyc2VkICE9PSAnb2JqZWN0Jykge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG1ldGFkYXRhO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAocGFyc2VkLm5vcm1hbFxyXG4gICAgICAgICAgICAgICAgJiYgdHlwZW9mIHBhcnNlZC5ub3JtYWwgPT09ICdvYmplY3QnXHJcbiAgICAgICAgICAgICAgICAmJiB0eXBlb2YgcGFyc2VkLm5vcm1hbC54ID09PSAnbnVtYmVyJ1xyXG4gICAgICAgICAgICAgICAgJiYgdHlwZW9mIHBhcnNlZC5ub3JtYWwueSA9PT0gJ251bWJlcidcclxuICAgICAgICAgICAgICAgICYmIHR5cGVvZiBwYXJzZWQubm9ybWFsLnogPT09ICdudW1iZXInKSB7XHJcbiAgICAgICAgICAgICAgICBwYXJzZWQubm9ybWFsID0gYXBwbHlSaWdpZFRyYW5zZm9ybVRvRGlyZWN0aW9uKHBhcnNlZC5ub3JtYWwsIHRyYW5zZm9ybSk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGRlbGV0ZSBwYXJzZWQuc2lkO1xyXG5cclxuICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHBhcnNlZCk7XHJcbiAgICAgICAgfSBjYXRjaCB7XHJcbiAgICAgICAgICAgIC8vIE5vdCBKU09OLCBvciB1bmV4cGVjdGVkIHNoYXBlIOKAlCBsZWF2ZSB1bnRvdWNoZWQgcmF0aGVyIHRoYW4gZ3Vlc3MuXHJcbiAgICAgICAgICAgIHJldHVybiBtZXRhZGF0YTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXNvbHZlcyBhIFBPSSdzIGB0YWdJbWFnZUlEYCDigJQgd2hpY2ggdGhlIHNjaGVtYSBkb2N1bWVudHMgYXMgYSBcImNvbm5lY3Rpb24gdG9cclxuICAgICAqIGNvbW1lbnQuaWRcIiwgaS5lLiB0aGUgaWQgb2YgdGhlIENvbW1lbnQgaG9sZGluZyB0aGUgaW1hZ2Ugc2hvd24gaW4gdGhlIHBhc3RpbGxlLlxyXG4gICAgICpcclxuICAgICAqIEl0IGlzIE5PVCBhbiBTMyBrZXksIHNvIHRoZSBwcmV2aW91cyBcImRvZXMgaXQgY29udGFpbiBhIHNsYXNoP1wiIGhldXJpc3RpYyBuZXZlclxyXG4gICAgICogbWF0Y2hlZCBhbmQgdGhlIHZhbHVlIHRyYXZlbGxlZCB1bmNoYW5nZWQsIGxlYXZpbmcgZXZlcnkgY29waWVkIHBhc3RpbGxlIHBvaW50aW5nIGF0XHJcbiAgICAgKiBhIENvbW1lbnQgb2YgdGhlIHNvdXJjZSBzcGFjZS4gSXQgaXMgbm93IHRyYW5zbGF0ZWQgdGhyb3VnaCB0aGUgY29tbWVudCBpZCBtYXAgYnVpbHRcclxuICAgICAqIHdoaWxlIGR1cGxpY2F0aW5nIHRoZSBtZWRpYSwgYW5kIGRyb3BwZWQgd2hlbiBpdCBjYW5ub3QgYmUgcmVzb2x2ZWQgKHRoZSBwYXN0aWxsZVxyXG4gICAgICogdGhlbiBmYWxscyBiYWNrIHRvIHRoZSBmZWF0dXJlJ3MgY292ZXIgaW1hZ2UgaW5zdGVhZCBvZiBhIGJyb2tlbiByZWZlcmVuY2UpLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHJlc29sdmVUYWdJbWFnZUlEKHRhZ0ltYWdlSUQ6IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQpOiBzdHJpbmcgfCBudWxsIHtcclxuICAgICAgICBpZiAoIXRhZ0ltYWdlSUQpIHtcclxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0aGlzLmNvbW1lbnRJZHMuZ2V0KHRhZ0ltYWdlSUQpID8/IG51bGw7XHJcbiAgICB9XHJcblxyXG4gICAgLy9cclxuICAgIC8vIC0tLS0tLS0tLS0gRHVwbGljYXRlIGRldGVjdGlvbiAtLS0tLS0tLS0tXHJcbiAgICAvL1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSGV1cmlzdGljIGR1cGxpY2F0ZS1kZXRlY3Rpb246IGNvbXBhcmVzIHNldmVyYWwgaWRlbnRpZnlpbmcgZmllbGRzIHRvZ2V0aGVyIHJhdGhlciB0aGFuXHJcbiAgICAgKiBhIHNpbmdsZSBsYWJlbCwgdG8gcmVkdWNlIGZhbHNlIHBvc2l0aXZlcyB3aGVuIGl0ZW1zIHNoYXJlIG9uZSBvZiB0aGVtLiBSZXR1cm5zIHRoZVxyXG4gICAgICogbWF0Y2hlZCB0YXJnZXQgaXRlbSAob3IgdW5kZWZpbmVkKSByYXRoZXIgdGhhbiBhIGJvb2xlYW4sIHNvIHRoZSBjYWxsZXIgY2FuIGFjdCBvbiB0aGVcclxuICAgICAqIGV4aXN0aW5nIHJlY29yZCDigJQgaGVhbCBpdHMgbWlzc2luZyBmaWVsZHMg4oCUIGluc3RlYWQgb2Ygb25seSBza2lwcGluZyBpdC5cclxuICAgICAqXHJcbiAgICAgKiBUaGUgZmllbGRzIGFyZSBzdXBwbGllZCBieSB0aGUgY2FsbGVyIGJlY2F1c2UgdGhlIG1vZGVscyBkbyBub3QgYWdyZWUgb24gdGhlbS4gVGhlXHJcbiAgICAgKiBwcmV2aW91cyB2ZXJzaW9uIGhhcmQtY29kZWQgYHRpdGxlYC9gZGVzY3JpcHRpb25gLCB3aGljaCBkbyBub3QgZXhpc3Qgb24gRXF1aXBtZW50IGF0XHJcbiAgICAgKiBhbGw6IGJvdGggc2lkZXMgcmVhZCBgdW5kZWZpbmVkYCwgZXZlcnkgZXF1aXBtZW50IHRoZXJlZm9yZSBcIm1hdGNoZWRcIiBldmVyeSBvdGhlciBvbmUsXHJcbiAgICAgKiBhbmQgYSB0YXJnZXQgc3BhY2UgaG9sZGluZyBhIHNpbmdsZSBlcXVpcG1lbnQgc2lsZW50bHkgY2F1c2VkIHRoZSB3aG9sZSBlcXVpcG1lbnQgcGhhc2VcclxuICAgICAqIHRvIGNvcHkgbm90aGluZy5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBmaW5kRXhpc3Rpbmc8VD4oXHJcbiAgICAgICAgc291cmNlOiBULFxyXG4gICAgICAgIHRhcmdldExpc3Q6IFRbXSxcclxuICAgICAgICBpZGVudGl0eTogKGl0ZW06IFQpID0+IEFycmF5PHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQ+XHJcbiAgICApOiBUIHwgdW5kZWZpbmVkIHtcclxuICAgICAgICBjb25zdCBzb3VyY2VLZXkgPSB0aGlzLmlkZW50aXR5S2V5KGlkZW50aXR5KHNvdXJjZSkpO1xyXG4gICAgICAgIHJldHVybiB0YXJnZXRMaXN0LmZpbmQodGFyZ2V0ID0+IHRoaXMuaWRlbnRpdHlLZXkoaWRlbnRpdHkodGFyZ2V0KSkgPT09IHNvdXJjZUtleSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBCdWlsZHMgYSBwYXRjaCBvZiB3aGljaGV2ZXIgZmllbGRzIGluIGBmaWVsZHNgIHRoZSBleGlzdGluZyB0YXJnZXQgcmVjb3JkIGlzIG1pc3NpbmdcclxuICAgICAqIChgbnVsbGAvYHVuZGVmaW5lZGAvZW1wdHkgYXJyYXkpIGJ1dCB0aGUgc291cmNlIGhhcywgcGx1cyBgZG9tYWluSURgIHdoZW4gcmVxdWVzdGVkIOKAlFxyXG4gICAgICogZG9tYWlucyBhcmUgb3JnYW5pc2F0aW9uLXNjb3BlZCBldmVyeXdoZXJlIGluIHRoaXMgZmlsZSwgc28gdGhhdCBvbmUgaXMgb25seSBldmVyXHJcbiAgICAgKiBoZWFsZWQgYWNyb3NzIHRoZSBTQU1FIG9yZ2FuaXNhdGlvbiwgZXhhY3RseSBsaWtlIGF0IGNyZWF0aW9uIHRpbWUuXHJcbiAgICAgKlxyXG4gICAgICogTmV2ZXIgb3ZlcndyaXRlcyBhIGZpZWxkIHRoZSB0YXJnZXQgYWxyZWFkeSBjYXJyaWVzIGEgdmFsdWUgZm9yOiBhIHZhbHVlIGVudGVyZWQgYnlcclxuICAgICAqIGhhbmQgaW4gdGhlIHRhcmdldCBzcGFjZSBzaW5jZSBhbiBlYXJsaWVyLCBpbmNvbXBsZXRlIGNvcHkgbXVzdCBub3QgYmUgY2xvYmJlcmVkIGJ5XHJcbiAgICAgKiBhbiBvbGRlciBvciBkaWZmZXJlbnQgc291cmNlIHZhbHVlLlxyXG4gICAgICpcclxuICAgICAqIFJldHVybnMgYm90aCB0aGUgcGF0Y2ggdG8gc2VuZCBhbmQgdGhlIGxpc3Qgb2YgaGVhbGVkIGZpZWxkIG5hbWVzLCBzbyB0aGUgY2FsbGVyIGNhblxyXG4gICAgICogYm90aCBwZXJmb3JtIHRoZSB1cGRhdGUgYW5kIGRlc2NyaWJlIGl0IGluIHRoZSBjb3B5IGxvZy5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBidWlsZEhlYWxQYXRjaChcclxuICAgICAgICBzb3VyY2VPYmo6IGFueSxcclxuICAgICAgICBleGlzdGluZ1RhcmdldDogYW55LFxyXG4gICAgICAgIGZpZWxkczogc3RyaW5nW10sXHJcbiAgICAgICAgaW5jbHVkZURvbWFpbjogYm9vbGVhblxyXG4gICAgKTogeyBwYXRjaDogYW55OyBoZWFsZWRGaWVsZHM6IHN0cmluZ1tdIH0ge1xyXG4gICAgICAgIGNvbnN0IHBhdGNoOiBhbnkgPSB7fTtcclxuICAgICAgICBjb25zdCBoZWFsZWRGaWVsZHM6IHN0cmluZ1tdID0gW107XHJcblxyXG4gICAgICAgIGNvbnN0IGZpbGxJZk1pc3NpbmcgPSAoa2V5OiBzdHJpbmcsIHNvdXJjZVZhbHVlOiBhbnkpID0+IHtcclxuICAgICAgICAgICAgY29uc3QgY3VycmVudFZhbHVlID0gZXhpc3RpbmdUYXJnZXRba2V5XTtcclxuICAgICAgICAgICAgY29uc3QgaXNNaXNzaW5nID0gY3VycmVudFZhbHVlID09PSBudWxsIHx8IGN1cnJlbnRWYWx1ZSA9PT0gdW5kZWZpbmVkXHJcbiAgICAgICAgICAgICAgICB8fCAoQXJyYXkuaXNBcnJheShjdXJyZW50VmFsdWUpICYmIGN1cnJlbnRWYWx1ZS5sZW5ndGggPT09IDApO1xyXG4gICAgICAgICAgICBpZiAoaXNNaXNzaW5nICYmIHNvdXJjZVZhbHVlICE9PSBudWxsICYmIHNvdXJjZVZhbHVlICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgICAgIHBhdGNoW2tleV0gPSBzb3VyY2VWYWx1ZTtcclxuICAgICAgICAgICAgICAgIGhlYWxlZEZpZWxkcy5wdXNoKGtleSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIGZpZWxkcykge1xyXG4gICAgICAgICAgICBmaWxsSWZNaXNzaW5nKGZpZWxkLCBzb3VyY2VPYmpbZmllbGRdKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGluY2x1ZGVEb21haW4gJiYgKGV4aXN0aW5nVGFyZ2V0LmRvbWFpbklEID09PSBudWxsIHx8IGV4aXN0aW5nVGFyZ2V0LmRvbWFpbklEID09PSB1bmRlZmluZWQpKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHJlc29sdmVkRG9tYWluSWQgPSB0aGlzLnJlc29sdmVEb21haW5JRChzb3VyY2VPYmouZG9tYWluSUQpO1xyXG4gICAgICAgICAgICBpZiAocmVzb2x2ZWREb21haW5JZCkge1xyXG4gICAgICAgICAgICAgICAgcGF0Y2guZG9tYWluSUQgPSByZXNvbHZlZERvbWFpbklkO1xyXG4gICAgICAgICAgICAgICAgaGVhbGVkRmllbGRzLnB1c2goJ2RvbWFpbklEJyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB7IHBhdGNoLCBoZWFsZWRGaWVsZHMgfTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEZpbGxzIGluIHdoaWNoZXZlciBpZGVudGl0eSBmaWVsZCBhIFBSRS1FWElTVElORyB0YXJnZXQgZXF1aXBtZW50IGlzIG1pc3NpbmcgYnV0IHRoZVxyXG4gICAgICogc291cmNlIGhhcyDigJQgc2VlIHRoZSBjYWxsIHNpdGUgaW4gdGhlIEVRVUlQTUVOVFMgcGhhc2UgZm9yIHdoeSByZS1ydW5uaW5nIHRoZSBjb3B5XHJcbiAgICAgKiBoYXMgdG8gYmUgYWJsZSB0byByZXBhaXIgYSBwcmV2aW91c2x5LWNvcGllZCBlcXVpcG1lbnQsIG5vdCBqdXN0IHNraXAgaXQgYWdhaW4uXHJcbiAgICAgKlxyXG4gICAgICogQSBmYWlsZWQgdXBkYXRlIGlzIGxlZnQgdG8gYnViYmxlIHVwIHRvIHRoZSBjYWxsZXIncyBleGlzdGluZyBwZXItaXRlbSB0cnkvY2F0Y2gsIHRoZVxyXG4gICAgICogc2FtZSBhcyBhIGZhaWxlZCBjcmVhdGlvbiDigJQgaXQgZ2V0cyB0aGUgc2FtZSB2aXNpYmxlIGVycm9yIGxpbmUsIHJhdGhlciB0aGFuIGEgc2lsZW50XHJcbiAgICAgKiBjb25zb2xlIHdhcm5pbmcuXHJcbiAgICAgKlxyXG4gICAgICogUmV0dXJucyB0aGUgbGlzdCBvZiBmaWVsZHMgdGhhdCB3ZXJlIGFjdHVhbGx5IGhlYWxlZCAoZW1wdHkgaWYgbm90aGluZyB3YXMgbWlzc2luZykuXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgYXN5bmMgaGVhbEVxdWlwbWVudElkZW50aXR5KHNvdXJjZU9iajogYW55LCBleGlzdGluZ1RhcmdldDogYW55KTogUHJvbWlzZTxzdHJpbmdbXT4ge1xyXG4gICAgICAgIGNvbnN0IHsgcGF0Y2gsIGhlYWxlZEZpZWxkcyB9ID0gdGhpcy5idWlsZEhlYWxQYXRjaChcclxuICAgICAgICAgICAgc291cmNlT2JqLCBleGlzdGluZ1RhcmdldCxcclxuICAgICAgICAgICAgWydzdGF0dXMnLCAnYW5ub3RhdGlvbicsICdmYW1pbHknLCAnc2t1JywgJ21hbnVmYWN0dXJlcicsICdpbnN0YWxsRGF0ZScsICd3YXJyYW50eUVuZERhdGUnLCAnbWV0YWRhdGEnLCAnaXNDcmVhdGVkQnlBSSddLFxyXG4gICAgICAgICAgICB0cnVlXHJcbiAgICAgICAgKTtcclxuXHJcbiAgICAgICAgaWYgKCFleGlzdGluZ1RhcmdldC5waG90byAmJiBzb3VyY2VPYmoucGhvdG8pIHtcclxuICAgICAgICAgICAgcGF0Y2gucGhvdG8gPSBhd2FpdCB0aGlzLmNvcHlTM0tleUlmUHJlc2VudChzb3VyY2VPYmoucGhvdG8sIGBlcXVpcG1lbnQgcGhvdG8gXCIke3NvdXJjZU9iai5uYW1lfVwiYCk7XHJcbiAgICAgICAgICAgIGhlYWxlZEZpZWxkcy5wdXNoKCdwaG90bycpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGhlYWxlZEZpZWxkcy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgcmV0dXJuIGhlYWxlZEZpZWxkcztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHBhdGNoLmlkID0gZXhpc3RpbmdUYXJnZXQuaWQ7XHJcbiAgICAgICAgYXdhaXQgdGhpcy5lcXVpcG1lbnRTZXJ2aWNlLnVwZGF0ZUVxdWlwbWVudChwYXRjaCk7XHJcbiAgICAgICAgcmV0dXJuIGhlYWxlZEZpZWxkcztcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFNhbWUgaWRlYSBhcyBoZWFsRXF1aXBtZW50SWRlbnRpdHkoKSwgZm9yIGEgcHJlLWV4aXN0aW5nIHRpY2tldC4gYHRpdGxlYC9gZGVzY3JpcHRpb25gXHJcbiAgICAgKiBhcmUgdGhlIHBhaXIgZmluZEV4aXN0aW5nKCkgbWF0Y2hlZCBvbiB0byBmaW5kIHRoaXMgdGlja2V0IGluIHRoZSBmaXJzdCBwbGFjZSwgc28gdGhleVxyXG4gICAgICogYXJlIG5ldmVyIHBhcnQgb2YgdGhlIGhlYWwg4oCUIGJ5IGNvbnN0cnVjdGlvbiwgdGhleSBhbHJlYWR5IGFncmVlIHdpdGggdGhlIHNvdXJjZS5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBhc3luYyBoZWFsVGlja2V0SWRlbnRpdHkoc291cmNlT2JqOiBhbnksIGV4aXN0aW5nVGFyZ2V0OiBhbnkpOiBQcm9taXNlPHN0cmluZ1tdPiB7XHJcbiAgICAgICAgY29uc3QgeyBwYXRjaCwgaGVhbGVkRmllbGRzIH0gPSB0aGlzLmJ1aWxkSGVhbFBhdGNoKFxyXG4gICAgICAgICAgICBzb3VyY2VPYmosIGV4aXN0aW5nVGFyZ2V0LFxyXG4gICAgICAgICAgICBbJ2ZyaWVuZGx5TGFiZWwnLCAnc3RhdHVzJywgJ3R5cGUnLCAncHJpb3JpdHknLCAnbGV2ZWwnLCAnbWV0YWRhdGEnLCAncmVhZCcsICdwcm9qZWN0SUQnLCAncHJvYmxlbUNvZGUnXSxcclxuICAgICAgICAgICAgdHJ1ZVxyXG4gICAgICAgICk7XHJcblxyXG4gICAgICAgIGlmIChoZWFsZWRGaWVsZHMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBoZWFsZWRGaWVsZHM7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBwYXRjaC5pZCA9IGV4aXN0aW5nVGFyZ2V0LmlkO1xyXG4gICAgICAgIGF3YWl0IHRoaXMudGlja2V0U2VydmljZS51cGRhdGVUaWNrZXQocGF0Y2gpO1xyXG4gICAgICAgIHJldHVybiBoZWFsZWRGaWVsZHM7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIFNhbWUgaWRlYSwgZm9yIGEgcHJlLWV4aXN0aW5nIGZlYXR1cmUuIEtleXdvcmRzLCBtZWRpYSBhbmQgUE9JcyBhcmUgbm90IGhlYWxlZCBoZXJlXHJcbiAgICAgKiAgZm9yIHRoZSBzYW1lIHJlYXNvbiBub3Rlcy9QT0lzIGFyZSBub3QgaGVhbGVkIG9uIGVxdWlwbWVudCDigJQgc2VlIGhlYWxFcXVpcG1lbnRJZGVudGl0eSgpLiAqL1xyXG4gICAgcHJpdmF0ZSBhc3luYyBoZWFsRmVhdHVyZUlkZW50aXR5KHNvdXJjZU9iajogYW55LCBleGlzdGluZ1RhcmdldDogYW55KTogUHJvbWlzZTxzdHJpbmdbXT4ge1xyXG4gICAgICAgIGNvbnN0IHsgcGF0Y2gsIGhlYWxlZEZpZWxkcyB9ID0gdGhpcy5idWlsZEhlYWxQYXRjaChcclxuICAgICAgICAgICAgc291cmNlT2JqLCBleGlzdGluZ1RhcmdldCxcclxuICAgICAgICAgICAgWydzaG9ydERlc2NyaXB0aW9uJywgJ2xldmVsJywgJ3R5cGUnLCAnaW5kZXgnLCAnc3RyaXBlUHJvZHVjdElEJywgJ3N0cmlwZVByaWNlSUQnLCAnYm9va2luZ1ByaWNlTWV0YWRhdGEnLCAnbG9jYWxlJ10sXHJcbiAgICAgICAgICAgIHRydWVcclxuICAgICAgICApO1xyXG5cclxuICAgICAgICBpZiAoaGVhbGVkRmllbGRzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICByZXR1cm4gaGVhbGVkRmllbGRzO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcGF0Y2guaWQgPSBleGlzdGluZ1RhcmdldC5pZDtcclxuICAgICAgICBhd2FpdCB0aGlzLmZlYXR1cmVTZXJ2aWNlLnVwZGF0ZUZlYXR1cmUocGF0Y2gpO1xyXG4gICAgICAgIHJldHVybiBoZWFsZWRGaWVsZHM7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIFNlcmlhbGlzZXMgdGhlIGlkZW50aWZ5aW5nIGZpZWxkcyB1bmFtYmlndW91c2x5LCBzbyB0aGF0IFtcImFcIiwgXCJiXCJdIGFuZCBbXCJhYlwiLCBcIlwiXVxyXG4gICAgICogIGNhbiBuZXZlciBwcm9kdWNlIHRoZSBzYW1lIGtleS4gKi9cclxuICAgIHByaXZhdGUgaWRlbnRpdHlLZXkocGFydHM6IEFycmF5PHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQ+KTogc3RyaW5nIHtcclxuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocGFydHMubWFwKHBhcnQgPT4gcGFydCA/PyAnJykpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vXHJcbiAgICAvLyAtLS0tLS0tLS0tIFN3ZWVwIHBvc2l0aW9ucyAvIHJpZ2lkIHRyYW5zZm9ybSAtLS0tLS0tLS0tXHJcbiAgICAvL1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogRmV0Y2hlcyB0aGUgcG9zaXRpb24gb2YgZXZlcnkgc3dlZXAgaW4gYSBzcGFjZSBhbmQgcmV0dXJucyBpdCBhcyBhIE1hcCBmb3IgTygxKSBsb29rdXAuXHJcbiAgICAgKiBVc2VzIGFsbFNldHRsZWQgc28gYSBzaW5nbGUgZmFpbGluZyBzd2VlcCBsb29rdXAgZG9lc24ndCBhYm9ydCB0aGUgd2hvbGUgbWFwIOKAlFxyXG4gICAgICogdGhhdCBzd2VlcCBpcyBzaW1wbHkgYWJzZW50IGZyb20gdGhlIHJlc3VsdGluZyBtYXAgKGFuZCBza2lwcGVkIGxhdGVyKS5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBhc3luYyBidWlsZE5hdmlnYXRpb25Qb3NpdGlvbk1hcChzcGFjZUlkOiBzdHJpbmcsIHN3ZWVwSWRzOiBzdHJpbmdbXSk6IFByb21pc2U8TWFwPHN0cmluZywgVmVjMz4+IHtcclxuICAgICAgICBjb25zdCBtYXAgPSBuZXcgTWFwPHN0cmluZywgVmVjMz4oKTtcclxuXHJcbiAgICAgICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChcclxuICAgICAgICAgICAgc3dlZXBJZHMubWFwKGFzeW5jIChzaWQpID0+IHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IG5hdnMgPSBhd2FpdCB0aGlzLm5hdmlnYXRpb25TZXJ2aWNlLmdldE5hdmlnYXRpb25zRm9yTWF0dGVycG9ydElERm9yU3BhY2Uoc2lkLCBzcGFjZUlkKTtcclxuICAgICAgICAgICAgICAgIGlmIChuYXZzICYmIG5hdnMubGVuZ3RoID4gMCAmJiBuYXZzWzBdLnBvc2l0aW9uKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgc2lkLCBwb3NpdGlvbjogSlNPTi5wYXJzZShuYXZzWzBdLnBvc2l0aW9uKSBhcyBWZWMzIH07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICAgICAgfSlcclxuICAgICAgICApO1xyXG5cclxuICAgICAgICBmb3IgKGNvbnN0IHJlc3VsdCBvZiByZXN1bHRzKSB7XHJcbiAgICAgICAgICAgIGlmIChyZXN1bHQuc3RhdHVzID09PSAnZnVsZmlsbGVkJyAmJiByZXN1bHQudmFsdWUpIHtcclxuICAgICAgICAgICAgICAgIG1hcC5zZXQocmVzdWx0LnZhbHVlLnNpZCwgcmVzdWx0LnZhbHVlLnBvc2l0aW9uKTtcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChyZXN1bHQuc3RhdHVzID09PSAncmVqZWN0ZWQnKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0ZhaWxlZCB0byBmZXRjaCBhIHN3ZWVwIHBvc2l0aW9uLCBza2lwcGluZyBpdDonLCByZXN1bHQucmVhc29uKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIG1hcDtcclxuICAgIH1cclxuXHJcbiAgICAvKiogQXBwbGllcyB0aGUgcmlnaWQgdHJhbnNmb3JtIHRvIGEgUE9JIGNvb3JkaW5hdGUgKHBvc2l0aW9uICsgb3JpZW50YXRpb24pLiAqL1xyXG4gICAgcHJpdmF0ZSBnZXRBZGp1c3RlZENvb3JkaW5hdGVzKGNvb3JkaW5hdGU6IHN0cmluZywgdHJhbnNmb3JtOiBSaWdpZFRyYW5zZm9ybSk6IGFueSB7XHJcbiAgICAgICAgaWYgKGNvb3JkaW5hdGUgPT09IFwibnVsbFwiKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoIWNvb3JkaW5hdGUgfHwgdHlwZW9mIGNvb3JkaW5hdGUgIT09ICdzdHJpbmcnKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBjb29yZGluYXRlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZShjb29yZGluYXRlKTtcclxuICAgICAgICBjb25zdCByb3RhdGVkUG9zID0gYXBwbHlSaWdpZFRyYW5zZm9ybVRvUG9pbnQoXHJcbiAgICAgICAgICAgIHsgeDogcGFyc2VkLngsIHk6IHBhcnNlZC55LCB6OiBwYXJzZWQueiB9LFxyXG4gICAgICAgICAgICB0cmFuc2Zvcm1cclxuICAgICAgICApO1xyXG5cclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICB4OiByb3RhdGVkUG9zLngsXHJcbiAgICAgICAgICAgIHk6IHJvdGF0ZWRQb3MueSxcclxuICAgICAgICAgICAgejogcm90YXRlZFBvcy56LFxyXG4gICAgICAgICAgICB4Um90YXRpb246IHBhcnNlZC54Um90YXRpb24sXHJcbiAgICAgICAgICAgIHlSb3RhdGlvbjogYXBwbHlSaWdpZFRyYW5zZm9ybVRvWVJvdGF0aW9uRGVnKHBhcnNlZC55Um90YXRpb24sIHRyYW5zZm9ybSlcclxuICAgICAgICB9O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQXBwbGllcyB0aGUgcmlnaWQgdHJhbnNmb3JtJ3MgdHJhbnNsYXRpb24rcm90YXRpb24gdG8gYSBwbGFpbiB7eCx5LHp9IHBvc2l0aW9uLFxyXG4gICAgICogV0lUSE9VVCBhZGRpbmcgeFJvdGF0aW9uL3lSb3RhdGlvbiBrZXlzLiBVc2VkIGZvciBtZWFzdXJlbWVudHMsIHdob3NlIHN0b3JlZFxyXG4gICAgICogY29vcmRpbmF0ZSBpcyBhIGJhcmUgcG9zaXRpb24gKG5vIG9yaWVudGF0aW9uKSwgdW5saWtlIG90aGVyIFBPSSB0eXBlcy5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBnZXRBZGp1c3RlZFBvc2l0aW9uT25seShjb29yZGluYXRlOiBzdHJpbmcsIHRyYW5zZm9ybTogUmlnaWRUcmFuc2Zvcm0pOiBhbnkge1xyXG4gICAgICAgIGlmICghY29vcmRpbmF0ZSB8fCB0eXBlb2YgY29vcmRpbmF0ZSAhPT0gJ3N0cmluZycgfHwgY29vcmRpbmF0ZSA9PT0gJ251bGwnKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBjb29yZGluYXRlO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKGNvb3JkaW5hdGUpO1xyXG4gICAgICAgIHJldHVybiBhcHBseVJpZ2lkVHJhbnNmb3JtVG9Qb2ludCh7IHg6IHBhcnNlZC54LCB5OiBwYXJzZWQueSwgejogcGFyc2VkLnogfSwgdHJhbnNmb3JtKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEZpbmRzIHRoZSBjbG9zZXN0IHRhcmdldCBzd2VlcCwgY29tcGFyaW5nIHBvc2l0aW9ucyBpbiB0aGUgU0FNRSBjb29yZGluYXRlIGZyYW1lLlxyXG4gICAgICogUHVyZSBpbi1tZW1vcnkgbG9va3VwIOKAlCBubyBuZXR3b3JrIGNhbGwsIHRoYW5rcyB0byB0aGUgcHJlLWJ1aWx0IHBvc2l0aW9uIG1hcHMuXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZmluZENsb3Nlc3RUYXJnZXRTd2VlcElkKFxyXG4gICAgICAgIHNvdXJjZVN3ZWVwSUQ6IHN0cmluZyxcclxuICAgICAgICBzb3VyY2VOYXZQb3NpdGlvbnM6IE1hcDxzdHJpbmcsIFZlYzM+LFxyXG4gICAgICAgIHRhcmdldE5hdlBvc2l0aW9uczogTWFwPHN0cmluZywgVmVjMz4sXHJcbiAgICAgICAgdHJhbnNmb3JtOiBSaWdpZFRyYW5zZm9ybVxyXG4gICAgKTogc3RyaW5nIHwgbnVsbCB7XHJcbiAgICAgICAgaWYgKCFzb3VyY2VTd2VlcElEKSByZXR1cm4gbnVsbDtcclxuXHJcbiAgICAgICAgY29uc3Qgc291cmNlUG9zID0gc291cmNlTmF2UG9zaXRpb25zLmdldChzb3VyY2VTd2VlcElEKTtcclxuICAgICAgICBpZiAoIXNvdXJjZVBvcykgcmV0dXJuIG51bGw7XHJcblxyXG4gICAgICAgIGNvbnN0IHNvdXJjZVBvc0luVGFyZ2V0RnJhbWUgPSBhcHBseVJpZ2lkVHJhbnNmb3JtVG9Qb2ludChzb3VyY2VQb3MsIHRyYW5zZm9ybSk7XHJcblxyXG4gICAgICAgIGxldCBjbG9zZXN0U3dlZXBJRDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XHJcbiAgICAgICAgbGV0IG1pbkRpc3RhbmNlID0gSW5maW5pdHk7XHJcblxyXG4gICAgICAgIGZvciAoY29uc3QgW3RhcmdldFN3ZWVwSWQsIHRhcmdldFBvc10gb2YgdGFyZ2V0TmF2UG9zaXRpb25zLmVudHJpZXMoKSkge1xyXG4gICAgICAgICAgICBjb25zdCBkeCA9IHRhcmdldFBvcy54IC0gc291cmNlUG9zSW5UYXJnZXRGcmFtZS54O1xyXG4gICAgICAgICAgICBjb25zdCBkeSA9IHRhcmdldFBvcy55IC0gc291cmNlUG9zSW5UYXJnZXRGcmFtZS55O1xyXG4gICAgICAgICAgICBjb25zdCBkeiA9IHRhcmdldFBvcy56IC0gc291cmNlUG9zSW5UYXJnZXRGcmFtZS56O1xyXG4gICAgICAgICAgICBjb25zdCBkaXN0ID0gTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5ICsgZHogKiBkeik7XHJcblxyXG4gICAgICAgICAgICBpZiAoZGlzdCA8IG1pbkRpc3RhbmNlKSB7XHJcbiAgICAgICAgICAgICAgICBtaW5EaXN0YW5jZSA9IGRpc3Q7XHJcbiAgICAgICAgICAgICAgICBjbG9zZXN0U3dlZXBJRCA9IHRhcmdldFN3ZWVwSWQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBjbG9zZXN0U3dlZXBJRDtcclxuICAgIH1cclxuXHJcbiAgICAvL1xyXG4gICAgLy8gLS0tLS0tLS0tLSBTMyBmaWxlIGR1cGxpY2F0aW9uIC0tLS0tLS0tLS1cclxuICAgIC8vXHJcblxyXG4gICAgLyoqIEdlbmVyYXRlcyBhIHNob3J0IHJhbmRvbSBpZCwgdXNlZCB0byBnaXZlIGVhY2ggY29waWVkIFMzIGZpbGUgYSBmcmVzaCwgY29sbGlzaW9uLXNhZmUga2V5LiAqL1xyXG4gICAgcHJpdmF0ZSBnZW5lcmF0ZVNob3J0SWQoKTogc3RyaW5nIHtcclxuICAgICAgICByZXR1cm4gTWF0aC5yYW5kb20oKS50b1N0cmluZygzNikuc2xpY2UoMiwgMTApO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQnVpbGRzIGEgbmV3IFMzIGtleSBmb3IgYSBjb3BpZWQgYXR0YWNobWVudCBhbmQgc2FuaXRpemVzIHRoZSBmaWxlbmFtZVxyXG4gICAgICogdG8gcHJldmVudCBBV1MgQW1wbGlmeSBTaWduYXR1cmVEb2VzTm90TWF0Y2ggZXJyb3JzLlxyXG4gICAgICogYGZvbGRlck92ZXJyaWRlYCByZS1ob21lcyB0aGUgY29weSBpbnRvIGFub3RoZXIgcHJlZml4IOKAlCB1c2VkIGZvciB0YWcgaWNvbnMsIHdoaWNoXHJcbiAgICAgKiBhcmUgc3RvcmVkIHBlciBzcGFjZSAoYGljb25zLXRhZ3MvPHNwYWNlSWQ+L2ApIGFuZCBtdXN0IGZvbGxvdyB0aGUgdGFyZ2V0IHNwYWNlLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGJ1aWxkQ29waWVkQXR0YWNobWVudEtleShzb3VyY2VBbm5leGU6IHN0cmluZywgZm9sZGVyT3ZlcnJpZGU6IHN0cmluZyB8IG51bGwgPSBudWxsKTogc3RyaW5nIHtcclxuICAgICAgICBjb25zdCBsYXN0U2xhc2ggPSBzb3VyY2VBbm5leGUubGFzdEluZGV4T2YoJy8nKTtcclxuICAgICAgICBjb25zdCBmb2xkZXIgPSBmb2xkZXJPdmVycmlkZSA/PyBzb3VyY2VBbm5leGUuc3Vic3RyaW5nKDAsIGxhc3RTbGFzaCArIDEpO1xyXG4gICAgICAgIGxldCBmaWxlbmFtZSA9IHNvdXJjZUFubmV4ZS5zdWJzdHJpbmcobGFzdFNsYXNoICsgMSk7XHJcblxyXG4gICAgICAgIC8vIFN0cmlwIGEgbGVhZGluZyBcIjw4IGhleCBjaGFycz5fXCIgaWQgcHJlZml4IGlmIHByZXNlbnRcclxuICAgICAgICBjb25zdCBwcmVmaXhNYXRjaCA9IGZpbGVuYW1lLm1hdGNoKC9eWzAtOWEtZkEtRi1dezh9XyguKykkLyk7XHJcbiAgICAgICAgaWYgKHByZWZpeE1hdGNoKSB7XHJcbiAgICAgICAgICAgIGZpbGVuYW1lID0gcHJlZml4TWF0Y2hbMV07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBTQU5JVElaQVRJT046IFJlcGxhY2Ugc3BhY2VzLCBwYXJlbnRoZXNlcywgYW5kIGFjY2VudHMgd2l0aCB1bmRlcnNjb3Jlc1xyXG4gICAgICAgIC8vIENydWNpYWwgdG8gcHJldmVudCBBbXBsaWZ5J3MgU3RvcmFnZS5jb3B5IGZyb20gZmFpbGluZyB0aGUgc2lnbmF0dXJlIGNhbGN1bGF0aW9uXHJcbiAgICAgICAgZmlsZW5hbWUgPSBmaWxlbmFtZS5yZXBsYWNlKC9bXmEtekEtWjAtOS5cXC1fXS9nLCAnXycpO1xyXG5cclxuICAgICAgICBjb25zdCBuZXdQcmVmaXggPSBgJHt0aGlzLmdlbmVyYXRlU2hvcnRJZCgpfV9gO1xyXG4gICAgICAgIHJldHVybiBgJHtmb2xkZXJ9JHtuZXdQcmVmaXh9JHtmaWxlbmFtZX1gO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRHVwbGljYXRlcyBhbiBTMyBvYmplY3QgaWYgYSBrZXkgaXMgcHJlc2VudC5cclxuICAgICAqIC0gSWYgdGhlIHNvdXJjZSBmaWxlIGlzIGdlbnVpbmVseSBtaXNzaW5nIGZyb20gUzMgKE5vU3VjaEtleSAvIG9ycGhhbmVkIERCIHJlZmVyZW5jZSksXHJcbiAgICAgKiAgIHRocm93cyBhIE1pc3NpbmdTM0ZpbGVFcnJvciBzbyB0aGUgY2FsbGVyIGNhbiBsb2cgYSBjbGVhciwgc3BlY2lmaWMgbWVzc2FnZSBhbmRcclxuICAgICAqICAgc2tpcCB0aGUgd2hvbGUgaXRlbSBlbnRpcmVseSwgcmF0aGVyIHRoYW4gY3JlYXRpbmcgYSByZWNvcmQgd2l0aCBhIGJyb2tlbiBmaWxlIGxpbmsuXHJcbiAgICAgKiAtIEFueSBvdGhlciBraW5kIG9mIGZhaWx1cmUgKHBlcm1pc3Npb25zLCBuZXR3b3JrLCBldGMuKSBzdGlsbCB0aHJvd3MgYSBnZW5lcmljIEVycm9yLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGFzeW5jIGNvcHlTM0tleUlmUHJlc2VudChcclxuICAgICAgICBrZXk6IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQsXHJcbiAgICAgICAgY29udGV4dExhYmVsOiBzdHJpbmcsXHJcbiAgICAgICAgZm9sZGVyT3ZlcnJpZGU6IHN0cmluZyB8IG51bGwgPSBudWxsXHJcbiAgICApOiBQcm9taXNlPHN0cmluZyB8IG51bGw+IHtcclxuICAgICAgICBpZiAoIWtleSkge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9XHJcbiAgICAgICAgY29uc3Qgc291cmNlS2V5ID0gdGhpcy5leHRyYWN0UzNLZXlGcm9tVmFsdWUoa2V5KTtcclxuICAgICAgICBjb25zdCBkZXN0S2V5ID0gdGhpcy5idWlsZENvcGllZEF0dGFjaG1lbnRLZXkoc291cmNlS2V5LCBmb2xkZXJPdmVycmlkZSk7XHJcblxyXG4gICAgICAgIC8vIExvZyB0aGUgc291cmNlIGtleSB0byBlbnN1cmUgaXQgbWF0Y2hlcyB0aGUgcmVhbCBTMyBvYmplY3QgcGF0aFxyXG4gICAgICAgIGNvbnNvbGUubG9nKGBbREVCVUddIEF0dGVtcHRpbmcgUzMgY29weSBmcm9tIHNvdXJjZTogXCIke3NvdXJjZUtleX1cIiB0byBkZXN0OiBcIiR7ZGVzdEtleX1cImApO1xyXG5cclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBjb25zdCBjb3BpZWQgPSBhd2FpdCBjb3B5RmlsZUluUzMoc291cmNlS2V5LCBkZXN0S2V5KTtcclxuICAgICAgICAgICAgaWYgKCFjb3BpZWQpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBNaXNzaW5nUzNGaWxlRXJyb3Ioc291cmNlS2V5LCBjb250ZXh0TGFiZWwpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiBjb3BpZWQ7XHJcbiAgICAgICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5pc01pc3NpbmdTM0ZpbGUoZXJyb3IpKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYFtNYXR0ZXJwb3J0VGFnQ29weVNlcnZpY2VdIE9ycGhhbmVkIFMzIHJlZmVyZW5jZSwgc2tpcHBpbmcgaXRlbTogXCIke3NvdXJjZUtleX1cIiAoJHtjb250ZXh0TGFiZWx9KWApO1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE1pc3NpbmdTM0ZpbGVFcnJvcihzb3VyY2VLZXksIGNvbnRleHRMYWJlbCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIFN0b3JhZ2UuY29weSgpIGNhbm5vdCBoYW5kbGUgYSBrZXkgaG9sZGluZyBhIHNwYWNlLCBhbiBhY2NlbnQgb3IgYSBwYXJlbnRoZXNpczpcclxuICAgICAgICAgICAgLy8gaXQgcHV0cyB0aGUga2V5IHVuZW5jb2RlZCBpbnRvIGB4LWFtei1jb3B5LXNvdXJjZWAsIHdoaWNoIHRoZW4gZGlzYWdyZWVzIHdpdGggdGhlXHJcbiAgICAgICAgICAgIC8vIHNpZ25lZCByZXF1ZXN0LiBUaG9zZSBmaWxlcyBhcmUgcGVyZmVjdGx5IHJlYWRhYmxlIOKAlCBvbmx5IHRoYXQgaGVhZGVyIGlzIGJyb2tlbiDigJRcclxuICAgICAgICAgICAgLy8gc28gZmFsbCBiYWNrIHRvIGRvd25sb2FkaW5nIGFuZCByZS11cGxvYWRpbmcgdGhlbS5cclxuICAgICAgICAgICAgaWYgKHRoaXMuaXNTaWduYXR1cmVNaXNtYXRjaChlcnJvcikpIHtcclxuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihgW01hdHRlcnBvcnRUYWdDb3B5U2VydmljZV0gU3RvcmFnZS5jb3B5KCkgc2lnbmF0dXJlIG1pc21hdGNoIG9uIFwiJHtzb3VyY2VLZXl9XCIsIGZhbGxpbmcgYmFjayB0byBkb3dubG9hZCArIHJlLXVwbG9hZC5gKTtcclxuICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29waWVkID0gYXdhaXQgY29weUZpbGVJblMzVmlhRG93bmxvYWQoc291cmNlS2V5LCBkZXN0S2V5KTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvcGllZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTWlzc2luZ1MzRmlsZUVycm9yKHNvdXJjZUtleSwgY29udGV4dExhYmVsKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNvcGllZDtcclxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGZhbGxiYWNrRXJyb3I6IGFueSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzTWlzc2luZ1MzRmlsZShmYWxsYmFja0Vycm9yKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTWlzc2luZ1MzRmlsZUVycm9yKHNvdXJjZUtleSwgY29udGV4dExhYmVsKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgZmFsbGJhY2tFcnJvcjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKiBUcnVlIHdoZW4gdGhlIGZhaWx1cmUgbWVhbnMgdGhlIHNvdXJjZSBvYmplY3Qgc2ltcGx5IGlzIG5vdCBvbiBTMyAob3JwaGFuZWQgcmVmZXJlbmNlKS4gKi9cclxuICAgIHByaXZhdGUgaXNNaXNzaW5nUzNGaWxlKGVycm9yOiBhbnkpOiBib29sZWFuIHtcclxuICAgICAgICByZXR1cm4gZXJyb3IgaW5zdGFuY2VvZiBNaXNzaW5nUzNGaWxlRXJyb3JcclxuICAgICAgICAgICAgfHwgZXJyb3I/LmNvZGUgPT09ICdOb1N1Y2hLZXknXHJcbiAgICAgICAgICAgIHx8IGVycm9yPy5uYW1lID09PSAnTm9TdWNoS2V5J1xyXG4gICAgICAgICAgICB8fCAvTm9TdWNoS2V5fGRvZXMgbm90IGV4aXN0fE5vdEZvdW5kL2kudGVzdCh0b0Vycm9yTWVzc2FnZShlcnJvcikpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBUcnVlIHdoZW4gQXBwU3luYyByZWZ1c2VkIHRoZSBvcGVyYXRpb24gZm9yIGxhY2sgb2YgcGVybWlzc2lvbiwgYXMgb3Bwb3NlZCB0byBmYWlsaW5nIGl0LlxyXG4gICAgICogIE5vdGhpbmcgY2FuIGJlIHJldHJpZWQgb3Igd29ya2VkIGFyb3VuZCBjbGllbnQtc2lkZTogdGhlIGFjY291bnQgc2ltcGx5IGlzIG5vdCBhbGxvd2VkXHJcbiAgICAgKiAgdG8gd3JpdGUgdGhhdCBtb2RlbCwgd2hpY2ggaXMgYSBiYWNrZW5kIGF1dGhvcmlzYXRpb24gcnVsZSAoQGF1dGgpIHRvIGNoYW5nZS4gKi9cclxuICAgIHByaXZhdGUgaXNVbmF1dGhvcml6ZWQoZXJyb3I6IGFueSk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGNvbnN0IG1lc3NhZ2UgPSB0b0Vycm9yTWVzc2FnZShlcnJvcik7XHJcbiAgICAgICAgcmV0dXJuIGVycm9yPy5lcnJvclR5cGUgPT09ICdVbmF1dGhvcml6ZWQnXHJcbiAgICAgICAgICAgIHx8IC9VbmF1dGhvcml6ZWR8Tm90IEF1dGhvcml6ZWQgdG8gYWNjZXNzL2kudGVzdChtZXNzYWdlKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogVHJ1ZSBmb3IgdGhlIFNpZ1Y0IG1pc21hdGNoIFN0b3JhZ2UuY29weSgpIHJhaXNlcyBvbiBrZXlzIHdpdGggc3BlY2lhbCBjaGFyYWN0ZXJzLiAqL1xyXG4gICAgcHJpdmF0ZSBpc1NpZ25hdHVyZU1pc21hdGNoKGVycm9yOiBhbnkpOiBib29sZWFuIHtcclxuICAgICAgICByZXR1cm4gZXJyb3I/LmNvZGUgPT09ICdTaWduYXR1cmVEb2VzTm90TWF0Y2gnXHJcbiAgICAgICAgICAgIHx8IGVycm9yPy5uYW1lID09PSAnU2lnbmF0dXJlRG9lc05vdE1hdGNoJ1xyXG4gICAgICAgICAgICB8fCAvc2lnbmF0dXJlIHdlIGNhbGN1bGF0ZWQgZG9lcyBub3QgbWF0Y2h8U2lnbmF0dXJlRG9lc05vdE1hdGNoL2kudGVzdCh0b0Vycm9yTWVzc2FnZShlcnJvcikpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRHVwbGljYXRlcyB0aGUgZmlsZSByZWZlcmVuY2VkIGJ5IGEgUE9JJ3MgdGFnSWNvbiAoYSBKU09OIHN0cmluZyBzaGFwZWQgbGlrZVxyXG4gICAgICogeyBzcmMsIG9wYWNpdHkgfSwgcGVyIGZvcm0tZmVhdHVyZS5jb21wb25lbnQudHMpLlxyXG4gICAgICpcclxuICAgICAqIFR3byBiZWhhdmlvdXJzIG1hdHRlciBoZXJlOlxyXG4gICAgICogIC0gdGhlIGNvcHkgaXMgcmUtaG9tZWQgdW5kZXIgdGhlIFRBUkdFVCBzcGFjZSdzIGljb24gZm9sZGVyXHJcbiAgICAgKiAgICAoYGljb25zLXRhZ3MvPHRhcmdldFNwYWNlSWQ+L2AsIHRoZSBsYXlvdXQgZm9ybS1mZWF0dXJlLmNvbXBvbmVudC50cyB1cGxvYWRzIHRvKS5cclxuICAgICAqICAgIEtlZXBpbmcgdGhlIHNvdXJjZSBmb2xkZXIgcHJvZHVjZWQgYSB0YXJnZXQgc3BhY2Ugd2hvc2UgaWNvbnMgYWxsIGxpdmVkIHVuZGVyXHJcbiAgICAgKiAgICBhbm90aGVyIHNwYWNlJ3MgcHJlZml4LCBzbyBjbGVhbmluZyB1cCB0aGUgc291cmNlIHNwYWNlIGJyb2tlIHRoZSBjb3B5J3MgaWNvbnMuXHJcbiAgICAgKiAgLSBhIG1pc3NpbmcgaWNvbiBmaWxlIGlzIE5PVCBmYXRhbC4gSXQgdXNlZCB0byBidWJibGUgdXAgYXMgYSBNaXNzaW5nUzNGaWxlRXJyb3IgYW5kXHJcbiAgICAgKiAgICBhYm9ydCB0aGUgd2hvbGUgUE9JIOKAlCBsb3NpbmcgdGhlIHBhc3RpbGxlLCBpdHMgdGV4dCBhbmQgaXRzIG1lZGlhIGJlY2F1c2Ugb2YgYVxyXG4gICAgICogICAgZGVjb3JhdGl2ZSBmaWxlLiBUaGUgUE9JIGlzIG5vdyBjcmVhdGVkIHdpdGggdGhlIGljb24gcmVmZXJlbmNlIGRyb3BwZWQsIHdoaWNoXHJcbiAgICAgKiAgICByZW5kZXJzIHRoZSBtb2R1bGUncyBkZWZhdWx0IGljb24sIGFuZCBhIGxvZyBsaW5lIHJlcG9ydHMgaXQuXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgYXN5bmMgZHVwbGljYXRlVGFnSWNvbih0YWdJY29uUmF3OiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkPiB7XHJcbiAgICAgICAgaWYgKCF0YWdJY29uUmF3KSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0YWdJY29uUmF3ID8/IG51bGw7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBsZXQgcGFyc2VkOiBhbnk7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgcGFyc2VkID0gSlNPTi5wYXJzZSh0YWdJY29uUmF3KTtcclxuICAgICAgICB9IGNhdGNoIHtcclxuICAgICAgICAgICAgLy8gTm90IEpTT04g4oCUIGxlYXZlIHVudG91Y2hlZCByYXRoZXIgdGhhbiBndWVzcy5cclxuICAgICAgICAgICAgcmV0dXJuIHRhZ0ljb25SYXc7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoIXBhcnNlZCB8fCB0eXBlb2YgcGFyc2VkICE9PSAnb2JqZWN0JyB8fCAhcGFyc2VkLnNyYykge1xyXG4gICAgICAgICAgICByZXR1cm4gdGFnSWNvblJhdztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIHBhcnNlZC5zcmMgPSBhd2FpdCB0aGlzLmNvcHlTM0tleUlmUHJlc2VudChcclxuICAgICAgICAgICAgICAgIHBhcnNlZC5zcmMsICd0YWcgaWNvbicsIHRoaXMuYnVpbGRUYXJnZXRJY29uRm9sZGVyKClcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICB9IGNhdGNoIChpY29uRXJyb3IpIHtcclxuICAgICAgICAgICAgaWYgKCEoaWNvbkVycm9yIGluc3RhbmNlb2YgTWlzc2luZ1MzRmlsZUVycm9yKSkge1xyXG4gICAgICAgICAgICAgICAgLy8gQSByZWFsIGZhaWx1cmUgKHBlcm1pc3Npb25zLCBuZXR3b3JrLCAuLi4pIHN0aWxsIGFib3J0cyB0aGUgUE9JOiBpdCBtZWFuc1xyXG4gICAgICAgICAgICAgICAgLy8gdGhlIGNvcHkgY2Fubm90IGJlIHRydXN0ZWQsIHVubGlrZSBhIGZpbGUgdGhhdCBpcyBzaW1wbHkgYWxyZWFkeSBnb25lLlxyXG4gICAgICAgICAgICAgICAgdGhyb3cgaWNvbkVycm9yO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihgW01hdHRlcnBvcnRUYWdDb3B5U2VydmljZV0gVGFnIGljb24gbWlzc2luZyBvbiBTMywgZmFsbGluZyBiYWNrIHRvIHRoZSBkZWZhdWx0IGljb246IFwiJHtpY29uRXJyb3Iuc291cmNlS2V5fVwiYCk7XHJcbiAgICAgICAgICAgIHRoaXMubG9nSXRlbUVycm9yKCd3YXJuaW5nVGFnSWNvbk1pc3NpbmcnLCB7IGZpbGU6IGljb25FcnJvci5zb3VyY2VLZXkgfSk7XHJcbiAgICAgICAgICAgIGRlbGV0ZSBwYXJzZWQuc3JjO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHBhcnNlZCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEljb24gZm9sZGVyIG9mIHRoZSBzcGFjZSBiZWluZyBjb3BpZWQgaW50bywgbWF0Y2hpbmcgd2hhdCB0aGUgZmVhdHVyZSBmb3JtIHVwbG9hZHMgdG8uICovXHJcbiAgICBwcml2YXRlIGJ1aWxkVGFyZ2V0SWNvbkZvbGRlcigpOiBzdHJpbmcgfCBudWxsIHtcclxuICAgICAgICByZXR1cm4gdGhpcy50YXJnZXRTcGFjZUlkID8gYGljb25zLXRhZ3MvJHt0aGlzLnRhcmdldFNwYWNlSWR9L2AgOiBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRXh0cmFjdHMgYW5kIG5vcm1hbGl6ZXMgdGhlIHJhdyBTMyBrZXkgZnJvbSBhIHN0b3JlZCB2YWx1ZSAod2hpY2ggbWF5IGJlIGEgZnVsbCBVUkxcclxuICAgICAqIG9yIGFscmVhZHkgYSByYXcga2V5KS5cclxuICAgICAqIElNUE9SVEFOVDogdGhpcyBtdXN0IHJldHVybiB0aGUgUkFXIChkZWNvZGVkLCBub24gVVJMLWVuY29kZWQpIGtleS4gQW1wbGlmeSdzXHJcbiAgICAgKiBTdG9yYWdlLmNvcHkoKSBhbHJlYWR5IGJ1aWxkcyBhbmQgZW5jb2RlcyB0aGUgJ3gtYW16LWNvcHktc291cmNlJyBoZWFkZXIgaW50ZXJuYWxseVxyXG4gICAgICogZnJvbSB0aGUga2V5IHdlIGdpdmUgaXQuIFByZS1lbmNvZGluZyBpdCBoZXJlIGNhdXNlZCBhIGRvdWJsZS1lbmNvZGluZyBidWcgKGUuZy4gYVxyXG4gICAgICogc3BhY2UgYmVjYW1lIFwiJTI1MjBcIiBpbnN0ZWFkIG9mIFwiJTIwXCIpLCBzbyBTdG9yYWdlLmNvcHkoKSBsb29rZWQgZm9yIGEga2V5IHRoYXQgbmV2ZXJcclxuICAgICAqIGV4aXN0ZWQgb24gUzMsIHJlc3VsdGluZyBpbiBhIE5vU3VjaEtleSBlcnJvci5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBleHRyYWN0UzNLZXlGcm9tVmFsdWUodmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICAgICAgaWYgKCF2YWx1ZSkge1xyXG4gICAgICAgICAgICByZXR1cm4gJyc7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBsZXQgZXh0cmFjdGVkID0gdmFsdWU7XHJcblxyXG4gICAgICAgIC8vIDEuIEV4dHJhY3QgcGF0aCBmcm9tIFVSTCBhbmQgZHJvcCBxdWVyeSBwYXJhbXNcclxuICAgICAgICBpZiAodmFsdWUuc3RhcnRzV2l0aCgnaHR0cDovLycpIHx8IHZhbHVlLnN0YXJ0c1dpdGgoJ2h0dHBzOi8vJykpIHtcclxuICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwodmFsdWUpO1xyXG4gICAgICAgICAgICAgICAgZXh0cmFjdGVkID0gZGVjb2RlVVJJQ29tcG9uZW50KHVybC5wYXRobmFtZSk7XHJcbiAgICAgICAgICAgIH0gY2F0Y2gge1xyXG4gICAgICAgICAgICAgICAgZXh0cmFjdGVkID0gdmFsdWUuc3BsaXQoJz8nKVswXTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGV4dHJhY3RlZCA9IHZhbHVlLnNwbGl0KCc/JylbMF07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyAyLiBSZW1vdmUgbGVhZGluZyBzbGFzaFxyXG4gICAgICAgIGlmIChleHRyYWN0ZWQuc3RhcnRzV2l0aCgnLycpKSB7XHJcbiAgICAgICAgICAgIGV4dHJhY3RlZCA9IGV4dHJhY3RlZC5zdWJzdHJpbmcoMSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyAzLiBSZW1vdmUgJ3B1YmxpYy8nIHByZWZpeFxyXG4gICAgICAgIC8vIEFtcGxpZnkgcHJlcGVuZHMgdGhpcyBhdXRvbWF0aWNhbGx5OyB3ZSBtdXN0IHN0cmlwIGl0IGZyb20gdGhlIGlucHV0XHJcbiAgICAgICAgLy8gdG8gYXZvaWQgdGhlICdwdWJsaWMvcHVibGljLycgZG91YmxlLXByZWZpeCBpc3N1ZS5cclxuICAgICAgICBpZiAoZXh0cmFjdGVkLnN0YXJ0c1dpdGgoJ3B1YmxpYy8nKSkge1xyXG4gICAgICAgICAgICBleHRyYWN0ZWQgPSBleHRyYWN0ZWQuc3Vic3RyaW5nKCdwdWJsaWMvJy5sZW5ndGgpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gUmV0dXJuIHRoZSByYXcga2V5IGFzLWlzIOKAlCBTdG9yYWdlLmNvcHkoKSB0YWtlcyBjYXJlIG9mIHByb3Blcmx5IGVuY29kaW5nIGl0XHJcbiAgICAgICAgLy8gZm9yIHRoZSBDb3B5U291cmNlIGhlYWRlci4gRG8gTk9UIHJlLWVuY29kZSBpdCBoZXJlLlxyXG4gICAgICAgIHJldHVybiBleHRyYWN0ZWQ7XHJcbiAgICB9XHJcbn0iXX0=