@smarterplan/ngx-smarterplan-core 1.4.13 → 1.4.14

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,7 @@
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 { computeRigidTransform, applyRigidTransformToPoint, applyRigidTransformToDirection, applyRigidTransformToYRotationDeg } from './utils/matterport-transform.util';
5
5
  import { CommentType, PoiType, SpModule } from '../types.service';
6
6
  import * as i0 from "@angular/core";
7
7
  import * as i1 from "./models/navigation.service";
@@ -13,7 +13,9 @@ import * as i6 from "./models/object3D.service";
13
13
  import * as i7 from "./models/feature.service";
14
14
  import * as i8 from "./models/measurement.service";
15
15
  import * as i9 from "./models/comment.service";
16
- import * as i10 from "@ngx-translate/core";
16
+ import * as i10 from "./models/hashtag.service";
17
+ import * as i11 from "./models/space.service";
18
+ import * as i12 from "@ngx-translate/core";
17
19
  /** Safely extracts a readable message from an unknown catch value, including Amplify's
18
20
  * GraphQL error shape ({ data, errors: [{ errorType, message }] }). */
19
21
  function toErrorMessage(err) {
@@ -65,6 +67,8 @@ export class MatterportTagCopyService {
65
67
  featureService;
66
68
  measurementService;
67
69
  commentService;
70
+ hashtagService;
71
+ spaceService;
68
72
  translate;
69
73
  // Emits progress updates during copyTagsFromVisit(); null when idle
70
74
  copyProgress$ = new BehaviorSubject(null);
@@ -73,7 +77,34 @@ export class MatterportTagCopyService {
73
77
  spModule;
74
78
  log = [];
75
79
  errorSeq = 0;
76
- constructor(navigationService, userService, poiService, ticketService, equipmentService, object3DService, featureService, measurementService, commentService, translate) {
80
+ // ---- Per-run remapping state (reset by resetRunState() at the start of every copy) ----
81
+ /** source element id -> id of its copy in the target space. */
82
+ elementIds = {};
83
+ /** source Comment id -> id of its copy. Needed to remap POI.tagImageID, which is a
84
+ * reference to a Comment record (see the schema: "connection to comment.id"). */
85
+ commentIds = new Map();
86
+ // Hashtags are space-scoped records, so their ids can never be carried over as-is: they
87
+ // are matched by NAME against the target space, and the missing ones are created there.
88
+ // That creation is deliberately lazy — see resolveHashtagIds() — and audited, so an
89
+ // interrupted copy cannot leave keywords behind that no POI references.
90
+ /** source Hashtag id -> its name. */
91
+ sourceHashtagNames = new Map();
92
+ /** normalised hashtag name -> its id in the TARGET space (pre-existing or just created). */
93
+ targetHashtagIdsByName = new Map();
94
+ /** ids of the hashtags this run created in the target space. */
95
+ createdHashtagIds = new Set();
96
+ /** ids of the hashtags actually persisted on a successfully created feature. Anything in
97
+ * createdHashtagIds but absent here is an orphan and is deleted at the end of the run. */
98
+ usedHashtagIds = new Set();
99
+ /** source ids of the elements whose POIs were already created by an element phase.
100
+ * Guards the standalone POI phase against creating a second, impoverished copy. */
101
+ handledElementIds = new Set();
102
+ /** true when source and target spaces belong to the same organisation. Domains are
103
+ * organisation-scoped (no spaceID), so domainID survives the copy only in that case. */
104
+ sameOrganisation = false;
105
+ /** Target space id of the run in progress — used to re-home copied tag icons. */
106
+ targetSpaceId = null;
107
+ constructor(navigationService, userService, poiService, ticketService, equipmentService, object3DService, featureService, measurementService, commentService, hashtagService, spaceService, translate) {
77
108
  this.navigationService = navigationService;
78
109
  this.userService = userService;
79
110
  this.poiService = poiService;
@@ -83,6 +114,8 @@ export class MatterportTagCopyService {
83
114
  this.featureService = featureService;
84
115
  this.measurementService = measurementService;
85
116
  this.commentService = commentService;
117
+ this.hashtagService = hashtagService;
118
+ this.spaceService = spaceService;
86
119
  this.translate = translate;
87
120
  this.spModule = userService.getSpModule();
88
121
  }
@@ -92,6 +125,7 @@ export class MatterportTagCopyService {
92
125
  async copyTagsFromVisit(sourceSpaceId, targetSpaceId, landmarkSourceA, landmarkTargetA, landmarkSourceB, landmarkTargetB) {
93
126
  let errorCount = 0;
94
127
  this.resetLog();
128
+ this.resetRunState(targetSpaceId);
95
129
  try {
96
130
  console.log(`Copying Tags from source ${sourceSpaceId} to target ${targetSpaceId}`);
97
131
  this.setStepProgress('collecting', 'collecting', 0);
@@ -109,6 +143,9 @@ export class MatterportTagCopyService {
109
143
  refSource: transform.refSource,
110
144
  refTarget: transform.refTarget
111
145
  });
146
+ // Domains are organisation-scoped, hashtags are space-scoped: both need to know
147
+ // whether we stay inside the same organisation before anything is remapped.
148
+ this.sameOrganisation = await this.spacesShareOrganisation(sourceSpaceId, targetSpaceId);
112
149
  const sourceSweepIds = await this.navigationService.getAllowedSweepsIDsForUserInSpace(sourceSpaceId);
113
150
  const targetSweepIds = await this.navigationService.getAllowedSweepsIDsForUserInSpace(targetSpaceId);
114
151
  this.setStepProgress('collecting', 'collecting', 30);
@@ -116,7 +153,7 @@ export class MatterportTagCopyService {
116
153
  this.buildNavigationPositionMap(sourceSpaceId, sourceSweepIds),
117
154
  this.buildNavigationPositionMap(targetSpaceId, targetSweepIds)
118
155
  ]);
119
- const elementIds = {};
156
+ const elementIds = this.elementIds;
120
157
  let sourceTickets = [];
121
158
  let sourceEquipments = [];
122
159
  let targetTickets = [];
@@ -132,9 +169,23 @@ export class MatterportTagCopyService {
132
169
  this.setStepProgress('collecting', 'collecting', 55);
133
170
  const sourceObjects3D = await this.object3DService.getObjects3DBySpace(sourceSpaceId);
134
171
  const targetObjects3D = await this.object3DService.getObjects3DBySpace(targetSpaceId);
135
- const sourceFeatures = await this.featureService.getFeaturesBySpaceWithoutFiltering(sourceSpaceId);
136
- const targetFeatures = await this.featureService.getFeaturesBySpaceWithoutFiltering(targetSpaceId);
172
+ // Paginated: a space routinely holds more than the 100 features a single AppSync
173
+ // page returns, and the tail was silently dropped.
174
+ //
175
+ // The source list keeps the historical "skip what the operator archived" rule, so
176
+ // the set of copied features does not change — but the check is now null-safe:
177
+ // FeatureService.isArchived() dereferences currentMission(spaceID).id and threw a
178
+ // TypeError when the operator had no mission on the source space (the common case
179
+ // for an archived v1 space), aborting the whole copy.
180
+ // The target list is NOT filtered: it only feeds duplicate detection, and an
181
+ // archived feature is still a feature that exists there.
182
+ const sourceFeatures = (await this.featureService.getAllFeaturesBySpaceRaw(sourceSpaceId))
183
+ .filter(feature => !this.isArchivedForOperator(feature, sourceSpaceId));
184
+ const targetFeatures = await this.featureService.getAllFeaturesBySpaceRaw(targetSpaceId);
137
185
  this.setStepProgress('collecting', 'collecting', 75);
186
+ // Keywords: index both vocabularies now (read-only). The keywords the target space
187
+ // is missing are created later, POI by POI, only for those actually used.
188
+ await this.loadHashtagIndex(sourceSpaceId, targetSpaceId);
138
189
  if (this.spModule == SpModule.IMMO) {
139
190
  sourceMeasurements = await this.measurementService.getMeasurementsForSpaceForUser(sourceSpaceId);
140
191
  targetMeasurements = await this.measurementService.getMeasurementsForSpaceForUser(targetSpaceId);
@@ -142,12 +193,44 @@ export class MatterportTagCopyService {
142
193
  this.setStepProgress('collecting', 'collecting', 90);
143
194
  const sourcePoisAll = await this.poiService.getPoisByMatterportSweeps(sourceSweepIds);
144
195
  const targetPoisAll = await this.poiService.getPoisByMatterportSweeps(targetSweepIds);
196
+ // A POI is "owned" by an element (ticket, equipment, 3D object, feature, measurement)
197
+ // when its elementID points at one. Those POIs are created by their element's phase,
198
+ // which is the only place that knows the element's NEW id — so they must be excluded
199
+ // from the standalone phase, otherwise every feature ends up with two POIs: one
200
+ // correctly linked but stripped of its tag metadata, and one carrying the metadata
201
+ // but still pointing at the source space's element.
202
+ //
203
+ // Ownership is recognised by TWO independent criteria, and either one is enough to
204
+ // keep a POI out of the standalone phase:
205
+ //
206
+ // - its type is one an element phase is responsible for. This is the historical
207
+ // rule and it must be kept: a POI of that type whose element was NOT collected
208
+ // (deleted ticket, equipment outside the current filter, ...) is an orphan, and
209
+ // copying it standalone would recreate it with an elementID still pointing into
210
+ // the source space — an orphan the previous version correctly refused to copy.
211
+ // - its elementID belongs to an element we actually collected. This is the added
212
+ // rule, needed because the type alone is not a reliable discriminator: historical
213
+ // data also holds INFORMATION/ROOM POIs bound to a feature, which the type test
214
+ // lets through and which would end up duplicated.
145
215
  const handledPoiTypes = new Set([
146
216
  PoiType.TICKET, PoiType.EQUIPMENT, PoiType.DATA, PoiType.DESK,
147
217
  PoiType.OBJECT3D, PoiType.MEASURE
148
218
  ]);
149
- const sourcePois = sourcePoisAll.filter(p => !handledPoiTypes.has(p.type));
150
- const targetPois = targetPoisAll.filter(p => !handledPoiTypes.has(p.type));
219
+ for (const owner of [...sourceTickets, ...sourceEquipments, ...sourceObjects3D, ...sourceFeatures]) {
220
+ if (owner?.id) {
221
+ this.handledElementIds.add(owner.id);
222
+ }
223
+ }
224
+ for (const measurement of sourceMeasurements) {
225
+ // a measurement POI is bound to the measurement's Comment, not to the measurement
226
+ if (measurement?.comment?.id) {
227
+ this.handledElementIds.add(measurement.comment.id);
228
+ }
229
+ }
230
+ const isOwnedByAnElement = (poi) => handledPoiTypes.has(poi.type)
231
+ || (!!poi.elementID && this.handledElementIds.has(poi.elementID));
232
+ const sourcePois = sourcePoisAll.filter(p => !isOwnedByAnElement(p));
233
+ const targetPois = targetPoisAll.filter(p => !!p);
151
234
  this.setStepProgress('collecting', 'collecting', 100);
152
235
  const totalOverall = sourceTickets.length + sourceEquipments.length + sourcePois.length
153
236
  + sourceObjects3D.length + sourceFeatures.length + sourceMeasurements.length;
@@ -168,7 +251,7 @@ export class MatterportTagCopyService {
168
251
  for (let i = 0; i < sourceTickets.length; i++) {
169
252
  const sourceObj = sourceTickets[i];
170
253
  try {
171
- const existsInTarget = this.matchesExisting(sourceObj, targetTickets);
254
+ const existsInTarget = this.matchesExisting(sourceObj, targetTickets, (t) => [t.title, t.description]);
172
255
  if (!existsInTarget) {
173
256
  const rawSource = sourceObj;
174
257
  const ticketInput = {
@@ -183,28 +266,51 @@ export class MatterportTagCopyService {
183
266
  read: rawSource.read || null,
184
267
  projectID: rawSource.projectID || null,
185
268
  problemCode: rawSource.problemCode || null,
186
- archivedForMissionID: rawSource.archivedForMissionID || null,
269
+ // Missions are per-space: a source mission id designates nobody in
270
+ // the target space. Carrying the list over would look like real data
271
+ // while hiding the item from no one — reset it, as for features.
272
+ archivedForMissionID: null,
187
273
  spaceID: targetSpaceId,
274
+ // Remapped in the second pass below, once every ticket exists.
188
275
  parentID: null,
189
- domainID: null,
276
+ // Domains are organisation-scoped, like for equipments and features.
277
+ domainID: this.sameOrganisation ? (rawSource.domainID || null) : null,
190
278
  ownerMissionID: targetMissionId
191
279
  };
192
280
  const createdObj = await this.ticketService.createTicket(ticketInput);
193
281
  if (createdObj && createdObj.id) {
194
282
  elementIds[sourceObj.id] = createdObj.id;
195
283
  }
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);
284
+ // Attachments of the ticket (photos of the incident, documents...).
285
+ // They were never copied at all: a duplicated ticket arrived stripped
286
+ // of every piece of evidence attached to it.
287
+ if (createdObj) {
288
+ let sourceComments = [];
289
+ try {
290
+ sourceComments = await this.commentService.getAllCommentsForTicket(sourceObj.id);
291
+ }
292
+ catch (commentsFetchError) {
293
+ console.warn(`Falling back to the embedded comment list for ticket "${rawSource.title}":`, commentsFetchError);
294
+ sourceComments = (sourceObj.comments?.items || []).filter(c => !!c);
295
+ }
296
+ for (const sourceComment of this.orderCommentsForCopy(sourceComments)) {
297
+ try {
298
+ const created = await this.copyCommentForTicket(sourceComment, createdObj.id, targetSpaceId, targetMissionId);
299
+ if (created?.id && sourceComment.id) {
300
+ this.commentIds.set(sourceComment.id, created.id);
301
+ }
302
+ }
303
+ catch (attachmentError) {
304
+ console.error(`Error copying attachment "${sourceComment?.title}" for ticket "${sourceObj?.title}":`, attachmentError);
305
+ errorCount++;
306
+ this.logCopyItemError(attachmentError, 'errorFeatureAttachment', sourceComment?.title || sourceComment?.id, {
307
+ feature: rawSource.title || sourceObj.id
308
+ });
309
+ }
310
+ }
311
+ }
312
+ for (const sourcePoi of (sourceObj.pois?.items || []).filter(p => !!p)) {
313
+ await this.createCopiedPoi(sourcePoi, createdObj.id, sourceNavPositions, targetNavPositions, transform);
208
314
  }
209
315
  }
210
316
  }
@@ -218,26 +324,69 @@ export class MatterportTagCopyService {
218
324
  const pct = sourceTickets.length > 0 ? Math.round(((i + 1) / sourceTickets.length) * 100) : 100;
219
325
  this.setStepProgress('tickets', 'tickets', pct);
220
326
  }
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)
327
+ // Second pass: restore the ticket hierarchy. `parentID` had to be nulled during
328
+ // creation (the parent may not have existed yet) and was then never restored, so
329
+ // every sub-ticket came out detached. Same rule as for sub-equipments: a parent
330
+ // with no copied counterpart is dropped rather than left pointing at the source
331
+ // space's ticket.
332
+ for (const sourceObj of sourceTickets) {
333
+ const rawSource = sourceObj;
334
+ const newId = elementIds[sourceObj.id];
335
+ const newParentId = rawSource.parentID ? elementIds[rawSource.parentID] : null;
336
+ if (newId && newParentId) {
337
+ try {
338
+ await this.ticketService.updateTicket({ id: newId, parentID: newParentId });
339
+ }
340
+ catch (parentError) {
341
+ console.error(`Error remapping the parent ticket of "${sourceObj?.title}":`, parentError);
342
+ errorCount++;
343
+ this.logCopyItemError(parentError, 'errorTicket', sourceObj?.title || sourceObj?.id);
344
+ }
345
+ }
346
+ }
347
+ // EQUIPMENTS (identity, POI, PHOTO and NOTES/documents all copied — files
348
+ // physically duplicated in S3 first, so the copy stays independent from the source)
349
+ //
350
+ // CAREFUL: the Equipment model has NO `title` and NO `description` column. It
351
+ // identifies itself with `name` (String! — required) and annotates itself with
352
+ // `annotation`. Reading `rawSource.title` therefore always yielded undefined and
353
+ // the required `name` was never sent, which AppSync rejected with
354
+ // "Variable 'input' has coerced Null value for NonNull type 'String!'".
223
355
  for (let i = 0; i < sourceEquipments.length; i++) {
224
356
  const sourceObj = sourceEquipments[i];
225
357
  try {
226
- const existsInTarget = this.matchesExisting(sourceObj, targetEquipments);
358
+ // Equipment has no `title`/`description`: it identifies itself by name, and by
359
+ // serial number when one is recorded.
360
+ const existsInTarget = this.matchesExisting(sourceObj, targetEquipments, (e) => [e.name, e.serialNumber]);
227
361
  if (!existsInTarget) {
228
362
  const rawSource = sourceObj;
229
363
  let copiedPhotoKey = null;
230
364
  if (rawSource.photo) {
231
- copiedPhotoKey = await this.copyS3KeyIfPresent(rawSource.photo, `equipment photo "${rawSource.title}"`);
365
+ copiedPhotoKey = await this.copyS3KeyIfPresent(rawSource.photo, `equipment photo "${rawSource.name}"`);
232
366
  }
233
367
  const equipmentInput = {
234
- title: rawSource.title,
368
+ name: rawSource.name,
369
+ annotation: rawSource.annotation ?? null,
235
370
  status: rawSource.status,
236
- description: rawSource.description,
237
- archivedForMissionID: rawSource.archivedForMissionID || null,
371
+ // Full identity of the equipment — all of these were dropped
372
+ family: rawSource.family ?? null,
373
+ sku: rawSource.sku ?? null,
374
+ serialNumber: rawSource.serialNumber ?? null,
375
+ manufacturer: rawSource.manufacturer ?? null,
376
+ installDate: rawSource.installDate ?? null,
377
+ warrantyEndDate: rawSource.warrantyEndDate ?? null,
378
+ metadata: rawSource.metadata ?? null,
379
+ isCreatedByAI: rawSource.isCreatedByAI ?? null,
380
+ // Missions are per-space: a source mission id designates nobody in
381
+ // the target space. Carrying the list over would look like real data
382
+ // while hiding the item from no one — reset it, as for features.
383
+ archivedForMissionID: null,
238
384
  spaceID: targetSpaceId,
239
- domainID: null,
385
+ // Domains are organisation-scoped, like for features and POIs.
386
+ domainID: this.sameOrganisation ? (rawSource.domainID || null) : null,
240
387
  photo: copiedPhotoKey,
388
+ // `subequipmentsIDs` is deliberately absent: it is remapped to the
389
+ // copied equipments in the second pass, once they all exist.
241
390
  };
242
391
  const createdObj = await this.equipmentService.createEquipment(equipmentInput, null, null);
243
392
  if (createdObj && createdObj.id) {
@@ -247,38 +396,35 @@ export class MatterportTagCopyService {
247
396
  if (createdObj && rawSource.notes?.items && rawSource.notes.items.length > 0) {
248
397
  for (const sourceNote of rawSource.notes.items) {
249
398
  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);
399
+ // A note without a file is still a note: it carries a type
400
+ // and its signature/expiry dates. Skipping it, as was done
401
+ // before, silently dropped those records entirely.
402
+ const copiedKey = sourceNote.attachment
403
+ ? await this.copyS3KeyIfPresent(sourceNote.attachment, `equipment note for "${sourceObj?.name}"`)
404
+ : null;
405
+ await this.equipmentService.createNoteWithExistingAttachment(createdObj.id, copiedKey, sourceNote.type, targetMissionId, {
406
+ signDate: sourceNote.signDate ?? null,
407
+ expirationDate: sourceNote.expirationDate ?? null
408
+ });
255
409
  }
256
410
  catch (noteError) {
257
- console.error(`Error copying note for equipment "${sourceObj?.title}":`, noteError);
411
+ console.error(`Error copying note for equipment "${sourceObj?.name}":`, noteError);
258
412
  errorCount++;
259
- this.logCopyItemError(noteError, 'errorEquipmentNote', sourceObj?.title || sourceObj?.id);
413
+ this.logCopyItemError(noteError, 'errorEquipmentNote', sourceObj?.name || sourceObj?.id, {
414
+ equipment: sourceObj?.name || sourceObj?.id
415
+ });
260
416
  }
261
417
  }
262
418
  }
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);
419
+ for (const sourcePoi of (sourceObj.pois?.items || []).filter(p => !!p)) {
420
+ await this.createCopiedPoi(sourcePoi, createdObj.id, sourceNavPositions, targetNavPositions, transform);
275
421
  }
276
422
  }
277
423
  }
278
424
  catch (itemError) {
279
- console.error(`Error copying equipment "${sourceObj?.title}" (id: ${sourceObj?.id}):`, itemError);
425
+ console.error(`Error copying equipment "${sourceObj?.name}" (id: ${sourceObj?.id}):`, itemError);
280
426
  errorCount++;
281
- this.logCopyItemError(itemError, 'errorEquipment', sourceObj?.title || sourceObj?.id);
427
+ this.logCopyItemError(itemError, 'errorEquipment', sourceObj?.name || sourceObj?.id);
282
428
  }
283
429
  processedOverall++;
284
430
  emitProgress('equipments', i + 1, sourceEquipments.length);
@@ -301,54 +447,16 @@ export class MatterportTagCopyService {
301
447
  await this.equipmentService.updateEquipment({ id: newId, subequipmentsIDs: remapped });
302
448
  }
303
449
  catch (subEquipError) {
304
- console.error(`Error remapping sub-equipments for "${sourceObj?.title}":`, subEquipError);
450
+ console.error(`Error remapping sub-equipments for "${sourceObj?.name}":`, subEquipError);
305
451
  errorCount++;
306
- this.logCopyItemError(subEquipError, 'errorEquipmentSubEquip', sourceObj?.title || sourceObj?.id);
452
+ this.logCopyItemError(subEquipError, 'errorEquipmentSubEquip', sourceObj?.name || sourceObj?.id, {
453
+ equipment: sourceObj?.name || sourceObj?.id
454
+ });
307
455
  }
308
456
  }
309
457
  }
310
458
  }
311
459
  }
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];
323
- }
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);
340
- }
341
- }
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
- }
352
460
  // OBJECTS 3D (the 3D model file itself — `path` — is physically duplicated in S3)
353
461
  for (let i = 0; i < sourceObjects3D.length; i++) {
354
462
  const sourceObj = sourceObjects3D[i];
@@ -356,8 +464,16 @@ export class MatterportTagCopyService {
356
464
  const existsInTarget = targetObjects3D.some(targetObj => targetObj.name === sourceObj.name);
357
465
  if (!existsInTarget) {
358
466
  const rawSource = sourceObj;
467
+ // `path` means two different things depending on `s3Bucket`, exactly as the
468
+ // viewer reads it (see viewer.component.ts and matterport-object3d.service.ts):
469
+ // - s3Bucket === true -> a key of a model file uploaded to S3, ours to duplicate;
470
+ // - otherwise -> a reference into the 3D object library shipped with
471
+ // the application ("3DObjects/objects/cube.dae" -> assets/3Dobjects/...),
472
+ // which exists in every space and must be reused verbatim.
473
+ // Copying unconditionally meant every library object failed with NoSuchKey and
474
+ // the whole 3D object was skipped, model AND POI.
359
475
  let copiedPath = rawSource.path;
360
- if (rawSource.path) {
476
+ if (rawSource.path && rawSource.s3Bucket) {
361
477
  copiedPath = await this.copyS3KeyIfPresent(rawSource.path, `3D object "${rawSource.name}"`);
362
478
  }
363
479
  /**
@@ -387,39 +503,65 @@ export class MatterportTagCopyService {
387
503
  // Ensure we return valid numbers
388
504
  return array.map(n => isNaN(n) ? 0 : n);
389
505
  };
506
+ // This service is shared, but the two applications do NOT deploy the same
507
+ // Object3D schema: `viewFrustum` exists only in smarterplan, and `scale`
508
+ // is [Float] there but a plain Float in museum. Sending the smarterplan
509
+ // shape to museum was rejected with "The variables input contains a field
510
+ // that is not defined for input object type 'CreateObject3DInput'".
511
+ //
512
+ // The input therefore MIRRORS the source record instead of imposing a
513
+ // shape: source and target live in the same deployment, so whatever the
514
+ // source carries is exactly what the target accepts.
390
515
  const object3DInput = {
391
516
  path: copiedPath,
517
+ // Tells the viewer how to interpret `path`. Dropping it turned an
518
+ // S3-hosted model into a library reference on the copy, which the
519
+ // viewer then tried to resolve against assets/ and failed to load.
520
+ s3Bucket: !!rawSource.s3Bucket,
392
521
  name: rawSource.name,
393
522
  description: rawSource.description || "",
394
- viewFrustum: !!rawSource.viewFrustum,
395
523
  spaceID: targetSpaceId,
396
524
  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])
525
+ rotation: toFloatArray(rawSource.rotation, [0, 0, 0])
400
526
  };
401
- // Debugging: Inspect the exact object sent to the mutation
402
- console.log(`[DEBUG] Sending Object3D "${rawSource.name}" to API:`, JSON.stringify(object3DInput));
527
+ if ('viewFrustum' in rawSource) {
528
+ object3DInput.viewFrustum = !!rawSource.viewFrustum;
529
+ }
530
+ // Scale keeps the source's own shape: a list stays a list, a scalar stays
531
+ // a scalar. An absent scale is left unset rather than invented, so the copy
532
+ // renders exactly like the original.
533
+ if (Array.isArray(rawSource.scale)) {
534
+ object3DInput.scale = toFloatArray(rawSource.scale, [1, 1, 1]);
535
+ }
536
+ else if (rawSource.scale !== null && rawSource.scale !== undefined) {
537
+ const scalarScale = parseFloat(rawSource.scale);
538
+ object3DInput.scale = Number.isNaN(scalarScale) ? 1 : scalarScale;
539
+ }
403
540
  const createdObj = await this.object3DService.create(object3DInput);
404
541
  if (createdObj && createdObj.id) {
405
542
  elementIds[sourceObj.id] = createdObj.id;
406
543
  }
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);
544
+ for (const sourcePoi of (sourceObj.pois?.items || []).filter(p => !!p)) {
545
+ await this.createCopiedPoi(sourcePoi, createdObj.id, sourceNavPositions, targetNavPositions, transform);
419
546
  }
420
547
  }
421
548
  }
422
549
  catch (itemError) {
550
+ // The backend can deny creation of this whole model to the signed-in account
551
+ // (in MUSEUM, Object3D only grants get/list to userPools). The denial is not
552
+ // per-item, so every remaining object would fail identically: report it once,
553
+ // as a permission problem rather than a copy error, and stop the phase instead
554
+ // of firing one doomed mutation per object.
555
+ if (this.isUnauthorized(itemError)) {
556
+ const remaining = sourceObjects3D.length - i;
557
+ console.warn(`[MatterportTagCopyService] Not allowed to create 3D objects in the target space, skipping ${remaining} of them.`, itemError);
558
+ errorCount++;
559
+ this.logItemError('errorObjects3dNotAllowed', { count: remaining });
560
+ processedOverall += remaining;
561
+ emitProgress('objects3d', sourceObjects3D.length, sourceObjects3D.length);
562
+ this.setStepProgress('objects3d', 'objects3d', 100);
563
+ break;
564
+ }
423
565
  console.error(`Error copying object3D "${sourceObj?.name}":`, itemError);
424
566
  errorCount++;
425
567
  this.logCopyItemError(itemError, 'errorObject3d', sourceObj?.name || sourceObj?.id);
@@ -429,76 +571,86 @@ export class MatterportTagCopyService {
429
571
  const pct = sourceObjects3D.length > 0 ? Math.round(((i + 1) / sourceObjects3D.length) * 100) : 100;
430
572
  this.setStepProgress('objects3d', 'objects3d', pct);
431
573
  }
432
- // FEATURES (title, POI, and attached comments — images/videos/docs/links — all copied,
433
- // each file physically duplicated in S3 first)
574
+ // FEATURES — the "POI" of the MUSEUM module: its own record (title, index, locale,
575
+ // keywords), its media set (one Comment per image/video/audio/document/link/text)
576
+ // and its POI record (the pastille: icon, tag description, cover image).
577
+ // Everything is copied here, files physically duplicated in S3 first.
434
578
  for (let i = 0; i < sourceFeatures.length; i++) {
435
579
  const sourceObj = sourceFeatures[i];
436
580
  try {
437
- const existsInTarget = this.matchesExisting(sourceObj, targetFeatures);
581
+ const existsInTarget = this.matchesExisting(sourceObj, targetFeatures, (f) => [f.title, f.description]);
438
582
  if (!existsInTarget) {
439
583
  const rawSource = sourceObj;
584
+ // Resolved just before the write: a keyword is only created in the target
585
+ // space when the POI carrying it is about to be created.
586
+ const resolvedHashtags = await this.resolveHashtagIds(rawSource.hashtags, targetSpaceId);
440
587
  const featureInput = {
441
588
  title: rawSource.title,
442
589
  shortDescription: rawSource.shortDescription,
443
590
  level: rawSource.level,
444
591
  type: rawSource.type,
445
- archivedForMissionID: rawSource.archivedForMissionID || null,
592
+ // `index` drives the ordering of the POI in the space's list, in the
593
+ // lateral menu and in the guided tour. Dropping it forced a full manual
594
+ // renumbering of every copied POI.
595
+ index: rawSource.index ?? null,
596
+ // Missions are per-space: source mission ids mean nothing in the target
597
+ // space, so an archive list carried over would hide POIs from nobody
598
+ // while looking like real data. Reset instead.
599
+ archivedForMissionID: null,
446
600
  stripeProductID: rawSource.stripeProductID || null,
447
601
  stripePriceID: rawSource.stripePriceID || null,
448
602
  bookingPriceMetadata: rawSource.bookingPriceMetadata || null,
449
603
  locale: rawSource.locale || null,
450
- hashtags: rawSource.hashtags || null,
604
+ // Hashtags are space-scoped records: the ids must be translated to the
605
+ // equivalent hashtags of the target space (created on demand).
606
+ hashtags: resolvedHashtags,
451
607
  description: rawSource.description || null,
452
- domainID: null,
608
+ // Domains are organisation-scoped, so the category survives a copy
609
+ // inside one organisation and only has to be dropped across two.
610
+ domainID: this.sameOrganisation ? (rawSource.domainID || null) : null,
453
611
  spaceID: targetSpaceId,
454
612
  ownerMissionID: targetMissionId
455
613
  };
456
614
  const createdObj = await this.featureService.createFeature(featureInput);
457
615
  if (createdObj && createdObj.id) {
458
616
  elementIds[sourceObj.id] = createdObj.id;
617
+ // The feature exists: its keywords are now genuinely referenced and
618
+ // must survive the end-of-run cleanup.
619
+ this.markHashtagsUsed(resolvedHashtags);
459
620
  }
460
- if (createdObj && sourceObj.comments?.items && sourceObj.comments.items.length > 0) {
461
- for (const sourceComment of sourceObj.comments.items) {
621
+ if (createdObj) {
622
+ // Read the media set through its own paginated query: the `comments`
623
+ // connection embedded in FeaturesBySpace is capped at 100 items and its
624
+ // nextToken was never followed, so rich POIs lost attachments silently.
625
+ let sourceComments = [];
626
+ try {
627
+ sourceComments = await this.commentService.getAllCommentsForFeature(sourceObj.id);
628
+ }
629
+ catch (commentsFetchError) {
630
+ console.warn(`Falling back to the embedded comment list for feature "${rawSource.title}":`, commentsFetchError);
631
+ sourceComments = (sourceObj.comments?.items || []).filter(c => !!c);
632
+ }
633
+ for (const sourceComment of this.orderCommentsForCopy(sourceComments)) {
462
634
  try {
463
- const rawComment = sourceComment;
464
- let copiedAnnexe = null;
465
- if (rawComment.annexe) {
466
- copiedAnnexe = await this.copyS3KeyIfPresent(rawComment.annexe, `feature attachment "${rawComment.title}"`);
635
+ const created = await this.copyCommentForFeature(sourceComment, createdObj.id, targetSpaceId, targetMissionId);
636
+ if (created?.id && sourceComment.id) {
637
+ this.commentIds.set(sourceComment.id, created.id);
467
638
  }
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
639
  }
483
640
  catch (attachmentError) {
484
641
  console.error(`Error copying attachment "${sourceComment?.title}" for feature "${sourceObj?.title}":`, attachmentError);
485
642
  errorCount++;
486
- this.logCopyItemError(attachmentError, 'errorFeatureAttachment', sourceComment?.title || sourceComment?.id);
643
+ this.logCopyItemError(attachmentError, 'errorFeatureAttachment', sourceComment?.title || sourceComment?.id, {
644
+ feature: rawSource.title || sourceObj.id
645
+ });
487
646
  }
488
647
  }
489
- }
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);
648
+ // Every POI of the feature, not only the first one: a feature may be
649
+ // pinned at several places, and only this phase knows the new element id.
650
+ const sourceFeaturePois = (sourceObj.pois?.items || []).filter(p => !!p);
651
+ for (const sourcePoi of sourceFeaturePois) {
652
+ await this.createCopiedPoi(sourcePoi, createdObj.id, sourceNavPositions, targetNavPositions, transform);
653
+ }
502
654
  }
503
655
  }
504
656
  }
@@ -527,12 +679,17 @@ export class MatterportTagCopyService {
527
679
  }
528
680
  const commentInput = {
529
681
  title: rawComment.title,
682
+ description: rawComment.description ?? null,
683
+ metadata: rawComment.metadata ?? null,
530
684
  type: CommentType.MEASURE,
531
685
  dimensions: rawComment.dimensions || null,
532
686
  annexe: copiedAnnexe,
533
687
  spaceID: targetSpaceId,
534
688
  };
535
689
  const createdComment = await this.commentService.createComment(commentInput);
690
+ if (createdComment && createdComment.id && rawComment.id) {
691
+ this.commentIds.set(rawComment.id, createdComment.id);
692
+ }
536
693
  if (createdComment && sourceMeasurement.poi) {
537
694
  const targetSweepId = this.findClosestTargetSweepId(sourceMeasurement.poi.matterportSweepID, sourceNavPositions, targetNavPositions, transform);
538
695
  const adjustedPosition = this.getAdjustedPositionOnly(sourceMeasurement.poi.coordinate, transform);
@@ -540,7 +697,9 @@ export class MatterportTagCopyService {
540
697
  coordinate: JSON.stringify(adjustedPosition),
541
698
  type: PoiType.MEASURE,
542
699
  elementID: createdComment.id,
543
- metadata: sourceMeasurement.poi.metadata,
700
+ // Same treatment as any other POI: the source's Matterport tag
701
+ // SID must not travel, and the stem normal has to be rotated.
702
+ metadata: this.getAdjustedPoiMetadata(sourceMeasurement.poi.metadata, transform),
544
703
  matterportSweepID: targetSweepId
545
704
  };
546
705
  await this.poiService.createPOIForSpaceID(poiInput);
@@ -558,6 +717,36 @@ export class MatterportTagCopyService {
558
717
  this.setStepProgress('measurements', 'measurements', pct);
559
718
  }
560
719
  }
720
+ // POIS — standalone ones only: every POI owned by an element was already created by
721
+ // that element's phase, with the element's NEW id.
722
+ //
723
+ // This phase runs LAST on purpose. It used to run third, before 3D objects, features
724
+ // and measurements existed in the target space, so `elementIds` and `commentIds` were
725
+ // still empty when it needed them: elementID stayed pointing at the source space and
726
+ // tagImageID (a reference to a Comment record) could never be resolved.
727
+ for (let i = 0; i < sourcePois.length; i++) {
728
+ const sourcePoi = sourcePois[i];
729
+ try {
730
+ const existsInTarget = targetPois.some(tp => tp.coordinate === sourcePoi.coordinate && tp.tagDescription === sourcePoi.tagDescription);
731
+ if (!existsInTarget) {
732
+ const elementID = sourcePoi.elementID
733
+ ? (elementIds[sourcePoi.elementID] || sourcePoi.elementID)
734
+ : sourcePoi.elementID;
735
+ await this.createCopiedPoi(sourcePoi, elementID, sourceNavPositions, targetNavPositions, transform);
736
+ }
737
+ }
738
+ catch (itemError) {
739
+ console.error(`Error copying POI (sweep: ${sourcePoi?.matterportSweepID}):`, itemError);
740
+ errorCount++;
741
+ this.logCopyItemError(itemError, 'errorPoi', sourcePoi?.matterportSweepID, {
742
+ sweep: sourcePoi?.matterportSweepID
743
+ });
744
+ }
745
+ processedOverall++;
746
+ emitProgress('pois', i + 1, sourcePois.length);
747
+ const pct = sourcePois.length > 0 ? Math.round(((i + 1) / sourcePois.length) * 100) : 100;
748
+ this.setStepProgress('pois', 'pois', pct);
749
+ }
561
750
  this.copyProgress$.next({
562
751
  phase: 'done',
563
752
  processedInPhase: 0, totalInPhase: 0,
@@ -575,6 +764,12 @@ export class MatterportTagCopyService {
575
764
  this.copyProgress$.next(null);
576
765
  return false;
577
766
  }
767
+ finally {
768
+ // Every exit path — success, partial success, or general failure — gives back the
769
+ // keywords this run created but no copied POI ended up using. Placed in `finally`
770
+ // so an exception thrown mid-copy cannot leave them behind either.
771
+ await this.cleanupUnusedCreatedHashtags();
772
+ }
578
773
  }
579
774
  //
580
775
  // ---------- Progress / log helpers ----------
@@ -603,6 +798,20 @@ export class MatterportTagCopyService {
603
798
  this.errorSeq = 0;
604
799
  this.copyLog$.next([]);
605
800
  }
801
+ /** Clears every id map carried over from a previous run. The service is a root-level
802
+ * singleton, so leftover mappings would silently link a new copy to records created
803
+ * during the previous one. */
804
+ resetRunState(targetSpaceId) {
805
+ this.elementIds = {};
806
+ this.commentIds = new Map();
807
+ this.sourceHashtagNames = new Map();
808
+ this.targetHashtagIdsByName = new Map();
809
+ this.createdHashtagIds = new Set();
810
+ this.usedHashtagIds = new Set();
811
+ this.handledElementIds = new Set();
812
+ this.sameOrganisation = false;
813
+ this.targetSpaceId = targetSpaceId;
814
+ }
606
815
  /** Builds and sets a step's log line as "<translated label>: <percent>%", no step numbering. */
607
816
  setStepProgress(stepId, translationKey, percent) {
608
817
  const label = this.translate.instant(`matterportCopy.${translationKey}`);
@@ -616,28 +825,408 @@ export class MatterportTagCopyService {
616
825
  /** Logs an item-level error, using a specific "missing file / orphaned reference"
617
826
  * translation key when the cause is a MissingS3FileError, and the generic per-type
618
827
  * 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) {
828
+ * investigate the same way a network/permission error is.
829
+ * `extraParams` carries the placeholders a few keys need on top of {{name}}/{{error}}
830
+ * (e.g. errorFeatureAttachment's {{feature}}, errorPoi's {{sweep}}), which used to be
831
+ * rendered as raw "{{feature}}" text in the log. */
832
+ logCopyItemError(error, genericKey, itemLabel, extraParams = {}) {
621
833
  if (error instanceof MissingS3FileError) {
622
834
  this.logItemError('errorMissingS3FileSkipped', {
835
+ ...extraParams,
623
836
  name: itemLabel,
624
837
  file: error.sourceKey
625
838
  });
626
839
  }
627
840
  else {
628
- this.logItemError(genericKey, { name: itemLabel, error: toErrorMessage(error) });
841
+ this.logItemError(genericKey, { ...extraParams, name: itemLabel, error: toErrorMessage(error) });
629
842
  }
630
843
  }
844
+ /**
845
+ * Null-safe equivalent of FeatureService.isArchived(): true when the operator has archived
846
+ * this feature on that space. "No mission on the space" answers false (nothing archived)
847
+ * instead of throwing, which is what made a copy from a space the operator is not a member
848
+ * of fail outright.
849
+ */
850
+ isArchivedForOperator(feature, spaceId) {
851
+ const archivedFor = feature?.archivedForMissionID;
852
+ if (!archivedFor || archivedFor.length === 0) {
853
+ return false;
854
+ }
855
+ const mission = this.userService.currentMission(spaceId);
856
+ return mission?.id ? archivedFor.includes(mission.id) : false;
857
+ }
858
+ //
859
+ // ---------- Cross-space reference remapping ----------
860
+ //
861
+ /**
862
+ * True when both spaces belong to the same organisation.
863
+ * Domains (POI/Feature categories) are organisation-scoped records with no spaceID, so
864
+ * a domainID stays meaningful inside one organisation and only becomes a dangling
865
+ * reference across two. A failed lookup answers "no": dropping a category is recoverable,
866
+ * pointing at another organisation's domain is not.
867
+ */
868
+ async spacesShareOrganisation(sourceSpaceId, targetSpaceId) {
869
+ try {
870
+ const [sourceSpace, targetSpace] = await Promise.all([
871
+ this.spaceService.getSpace(sourceSpaceId),
872
+ this.spaceService.getSpace(targetSpaceId)
873
+ ]);
874
+ const sourceOrg = sourceSpace?.organisationID;
875
+ const targetOrg = targetSpace?.organisationID;
876
+ return !!sourceOrg && !!targetOrg && sourceOrg === targetOrg;
877
+ }
878
+ catch (error) {
879
+ console.warn('[MatterportTagCopyService] Could not compare the spaces\' organisations, categories will be dropped:', error);
880
+ return false;
881
+ }
882
+ }
883
+ /** Normalised lookup key for a hashtag name, so "Moyen Âge" and "moyen âge " match. */
884
+ hashtagKey(name) {
885
+ return name.trim().toLowerCase();
886
+ }
887
+ /**
888
+ * READ-ONLY indexing of both spaces' hashtags. Creates nothing.
889
+ *
890
+ * `Feature.hashtags` stores Hashtag *ids*, and a Hashtag is a per-space record, so the
891
+ * ids have to be translated by name. The translation table is built here; the missing
892
+ * keywords are created later, one at a time, only when a POI that actually uses them is
893
+ * about to be written (see resolveHashtagIds()).
894
+ */
895
+ async loadHashtagIndex(sourceSpaceId, targetSpaceId) {
896
+ let sourceHashtags = [];
897
+ let targetHashtags = [];
898
+ try {
899
+ [sourceHashtags, targetHashtags] = await Promise.all([
900
+ this.hashtagService.listHashtagsForSpace(sourceSpaceId),
901
+ this.hashtagService.listHashtagsForSpace(targetSpaceId)
902
+ ]);
903
+ }
904
+ catch (error) {
905
+ console.warn('[MatterportTagCopyService] Could not read the hashtags, keywords will be dropped:', error);
906
+ return;
907
+ }
908
+ for (const hashtag of sourceHashtags || []) {
909
+ if (hashtag?.id && hashtag.name) {
910
+ this.sourceHashtagNames.set(hashtag.id, hashtag.name);
911
+ }
912
+ }
913
+ for (const hashtag of targetHashtags || []) {
914
+ if (hashtag?.id && hashtag.name) {
915
+ this.targetHashtagIdsByName.set(this.hashtagKey(hashtag.name), hashtag.id);
916
+ }
917
+ }
918
+ }
919
+ /**
920
+ * Translates one feature's hashtag ids into target-space ids, creating on the fly the
921
+ * keywords the target space does not have yet.
922
+ *
923
+ * Creation is LAZY on purpose. Doing it up front, for the whole source vocabulary, meant
924
+ * that a copy which failed or was closed halfway left behind keywords no POI referenced —
925
+ * pollution the operator had to clean up by hand. Here a keyword is only ever written
926
+ * when a POI that carries it is about to be created, so an interrupted copy stops
927
+ * creating keywords at the same POI it stops creating content.
928
+ *
929
+ * The residual window (keyword created, then createFeature fails) is closed by
930
+ * markHashtagsUsed() + cleanupUnusedCreatedHashtags().
931
+ *
932
+ * A keyword that can neither be found nor created is dropped rather than left as a
933
+ * dangling id.
934
+ */
935
+ async resolveHashtagIds(sourceHashtagIds, targetSpaceId) {
936
+ if (!sourceHashtagIds || sourceHashtagIds.length === 0) {
937
+ return null;
938
+ }
939
+ const resolved = [];
940
+ for (const sourceId of sourceHashtagIds) {
941
+ if (!sourceId) {
942
+ continue;
943
+ }
944
+ const name = this.sourceHashtagNames.get(sourceId);
945
+ if (!name) {
946
+ // the source id points at a hashtag that no longer exists — nothing to carry over
947
+ continue;
948
+ }
949
+ const key = this.hashtagKey(name);
950
+ let targetId = this.targetHashtagIdsByName.get(key);
951
+ if (!targetId) {
952
+ try {
953
+ const created = await this.hashtagService.createHashtagForSpace(name, targetSpaceId);
954
+ targetId = created?.id;
955
+ if (targetId) {
956
+ this.targetHashtagIdsByName.set(key, targetId);
957
+ this.createdHashtagIds.add(targetId);
958
+ }
959
+ }
960
+ catch (error) {
961
+ console.warn(`[MatterportTagCopyService] Could not create the hashtag "${name}" in the target space:`, error);
962
+ continue;
963
+ }
964
+ }
965
+ if (targetId && !resolved.includes(targetId)) {
966
+ resolved.push(targetId);
967
+ }
968
+ }
969
+ return resolved.length > 0 ? resolved : null;
970
+ }
971
+ /** Records that these hashtags are now referenced by a feature that really exists, so
972
+ * the end-of-run cleanup leaves them alone. */
973
+ markHashtagsUsed(hashtagIds) {
974
+ for (const id of hashtagIds || []) {
975
+ this.usedHashtagIds.add(id);
976
+ }
977
+ }
978
+ /**
979
+ * Deletes the hashtags this run created that no copied POI ended up referencing.
980
+ *
981
+ * Runs on every exit path — success, general failure, or exception — so the target space
982
+ * never keeps keywords that came from an aborted copy. Only ids created by THIS run are
983
+ * ever considered: a pre-existing keyword of the target space is never touched, even if
984
+ * no copied POI uses it.
985
+ */
986
+ async cleanupUnusedCreatedHashtags() {
987
+ const orphans = [...this.createdHashtagIds].filter(id => !this.usedHashtagIds.has(id));
988
+ if (orphans.length === 0) {
989
+ return;
990
+ }
991
+ console.log(`[MatterportTagCopyService] Removing ${orphans.length} keyword(s) created but left unused by this copy.`);
992
+ for (const hashtagId of orphans) {
993
+ try {
994
+ await this.hashtagService.deleteHashtagById(hashtagId);
995
+ this.createdHashtagIds.delete(hashtagId);
996
+ }
997
+ catch (error) {
998
+ // Cleanup is best-effort: a leftover keyword is harmless next to a failed copy,
999
+ // and must never be the reason the whole operation reports a failure.
1000
+ console.warn(`[MatterportTagCopyService] Could not remove the unused keyword "${hashtagId}":`, error);
1001
+ }
1002
+ }
1003
+ }
1004
+ //
1005
+ // ---------- Media content (Comments) ----------
1006
+ //
1007
+ /**
1008
+ * Orders a feature's media set exactly the way the UI will read it back, and repairs
1009
+ * the ordering key when the source data cannot express the user's intended order.
1010
+ *
1011
+ * The viewer sorts each media family on its own (`setImages`, `setVideos`, `setAudio`,
1012
+ * `setDocuments`, ... all do `.sort((a, b) => a.index - b.index)`), so `index` only has
1013
+ * to be consistent WITHIN a CommentType. The attachment form however defaults `index`
1014
+ * to 1 for every new attachment, so a multi-image POI very often holds several images
1015
+ * all sharing index 1 — or null. Sorting those is left to DynamoDB's arbitrary scan
1016
+ * order, which is why the copy came out in a different order than the original.
1017
+ *
1018
+ * Strategy: sort deterministically (index, then creation date, then id — i.e. the
1019
+ * upload order the user actually saw), and only rewrite the indices of a family when
1020
+ * they are ambiguous (null or duplicated). A family whose indices are already unique
1021
+ * is copied untouched, so a deliberate ordering is never overwritten.
1022
+ */
1023
+ orderCommentsForCopy(comments) {
1024
+ const valid = (comments || []).filter(c => !!c);
1025
+ const byType = new Map();
1026
+ for (const comment of valid) {
1027
+ const key = comment.type || 'UNTYPED';
1028
+ if (!byType.has(key)) {
1029
+ byType.set(key, []);
1030
+ }
1031
+ byType.get(key).push(comment);
1032
+ }
1033
+ const ordered = [];
1034
+ for (const family of byType.values()) {
1035
+ family.sort((a, b) => {
1036
+ const ai = this.orderingIndexOf(a);
1037
+ const bi = this.orderingIndexOf(b);
1038
+ if (ai !== bi) {
1039
+ return ai - bi;
1040
+ }
1041
+ const ad = this.creationTimeOf(a);
1042
+ const bd = this.creationTimeOf(b);
1043
+ if (ad !== bd) {
1044
+ return ad - bd;
1045
+ }
1046
+ return String(a.id || '').localeCompare(String(b.id || ''));
1047
+ });
1048
+ const indices = family.map(c => c.index);
1049
+ const isAmbiguous = indices.some(i => i === null || i === undefined)
1050
+ || new Set(indices).size !== indices.length;
1051
+ family.forEach((comment, position) => {
1052
+ comment.__copyIndex = isAmbiguous ? position + 1 : comment.index;
1053
+ });
1054
+ ordered.push(...family);
1055
+ }
1056
+ return ordered;
1057
+ }
1058
+ /** Sort key for a comment's position; a missing index sorts last, not first. */
1059
+ orderingIndexOf(comment) {
1060
+ const index = comment?.index;
1061
+ return index === null || index === undefined || Number.isNaN(Number(index))
1062
+ ? Number.MAX_SAFE_INTEGER
1063
+ : Number(index);
1064
+ }
1065
+ /** Creation timestamp of a comment, used as the tie-breaker: it reflects the order in
1066
+ * which the user uploaded the media, which is the order they saw. */
1067
+ creationTimeOf(comment) {
1068
+ const createdAt = comment?.createdAt;
1069
+ if (!createdAt) {
1070
+ return 0;
1071
+ }
1072
+ const time = new Date(createdAt).getTime();
1073
+ return Number.isNaN(time) ? 0 : time;
1074
+ }
1075
+ /**
1076
+ * Copies ONE media item (image, video, audio, document, text, link, embed, iframe...)
1077
+ * of a feature, duplicating its file in S3 first when it has one.
1078
+ *
1079
+ * Every column of the Comment model is carried over. `description` and `metadata` were
1080
+ * previously dropped, which emptied the captions of images/videos, the body of TEXT
1081
+ * items — where the whole content lives, since a TEXT comment has no file — and any
1082
+ * per-media settings stored in metadata.
1083
+ */
1084
+ async copyCommentForFeature(sourceComment, targetFeatureId, targetSpaceId, targetMissionId) {
1085
+ return this.copyComment(sourceComment, targetSpaceId, targetMissionId, { featureID: targetFeatureId });
1086
+ }
1087
+ /** Same, for an attachment carried by a ticket rather than by a feature. */
1088
+ async copyCommentForTicket(sourceComment, targetTicketId, targetSpaceId, targetMissionId) {
1089
+ return this.copyComment(sourceComment, targetSpaceId, targetMissionId, { ticketID: targetTicketId });
1090
+ }
1091
+ /** Shared body of the two above: `owner` carries whichever foreign key links the copy back
1092
+ * to its new parent, everything else is identical. */
1093
+ async copyComment(sourceComment, targetSpaceId, targetMissionId, owner) {
1094
+ const rawComment = sourceComment;
1095
+ let copiedAnnexe = null;
1096
+ if (rawComment.annexe) {
1097
+ copiedAnnexe = await this.copyS3KeyIfPresent(rawComment.annexe, `attachment "${rawComment.title}"`);
1098
+ }
1099
+ const commentInput = {
1100
+ title: rawComment.title,
1101
+ description: rawComment.description ?? null,
1102
+ metadata: rawComment.metadata ?? null,
1103
+ type: rawComment.type,
1104
+ annexe: copiedAnnexe,
1105
+ externalLink: rawComment.externalLink || null,
1106
+ dimensions: rawComment.dimensions || null,
1107
+ index: rawComment.__copyIndex ?? rawComment.index ?? null,
1108
+ shownInTag: rawComment.shownInTag,
1109
+ isCoverImage: rawComment.isCoverImage,
1110
+ spaceID: targetSpaceId,
1111
+ ownerID: targetMissionId,
1112
+ ...owner
1113
+ };
1114
+ return this.commentService.createComment(commentInput);
1115
+ }
1116
+ //
1117
+ // ---------- POI creation ----------
1118
+ //
1119
+ /**
1120
+ * Creates the target-space copy of a source POI, with EVERY column of the POI model.
1121
+ *
1122
+ * Single entry point for all phases: the element phases (ticket, equipment, 3D object,
1123
+ * feature, measurement) used to build their POI inline with only 5 fields — coordinate,
1124
+ * type, elementID, metadata, sweep — which is precisely how museum POIs lost their
1125
+ * pastille: `tagDescription` (the popup text), `tagIcon` (the custom icon) and
1126
+ * `tagImageID` (the pastille's image) never left the source space.
1127
+ */
1128
+ async createCopiedPoi(sourcePoi, elementID, sourceNavPositions, targetNavPositions, transform) {
1129
+ const raw = sourcePoi;
1130
+ const targetSweepId = this.findClosestTargetSweepId(sourcePoi.matterportSweepID, sourceNavPositions, targetNavPositions, transform);
1131
+ const adjustedCoordinate = this.getAdjustedCoordinates(sourcePoi.coordinate, transform);
1132
+ const poiInput = {
1133
+ coordinate: adjustedCoordinate === null || adjustedCoordinate === undefined
1134
+ ? null
1135
+ : JSON.stringify(adjustedCoordinate),
1136
+ type: sourcePoi.type,
1137
+ elementID: elementID ?? null,
1138
+ matterportSweepID: targetSweepId,
1139
+ // --- pastille (tag popup) ---
1140
+ tagDescription: sourcePoi.tagDescription ?? null,
1141
+ tagIcon: await this.duplicateTagIcon(sourcePoi.tagIcon),
1142
+ tagImageID: this.resolveTagImageID(sourcePoi.tagImageID),
1143
+ // --- rendering / visibility flags, carried over verbatim ---
1144
+ specific: raw.specific ?? null,
1145
+ private: raw.private ?? null,
1146
+ global: raw.global ?? null,
1147
+ level: raw.level ?? null,
1148
+ role: raw.role ?? null,
1149
+ category: raw.category ?? null,
1150
+ domainID: this.sameOrganisation ? (raw.domainID || null) : null,
1151
+ // --- Matterport anchoring ---
1152
+ metadata: this.getAdjustedPoiMetadata(sourcePoi.metadata, transform)
1153
+ };
1154
+ return this.poiService.createPOIForSpaceID(poiInput);
1155
+ }
1156
+ /**
1157
+ * Adapts a POI's `metadata` (see MattertagData.getMetadataString(): { icon, normal, sid })
1158
+ * to the target space.
1159
+ *
1160
+ * - `sid` is the id of the Mattertag inside the SOURCE Matterport model. Carried over,
1161
+ * the viewer tries to re-create the target's tag with an id belonging to another
1162
+ * model ("already in use"), so the pastille fails to attach. It is dropped: the
1163
+ * viewer then allocates a fresh sid on first render.
1164
+ * - `normal` is the stem direction. It is a direction, so only the rotation applies
1165
+ * (never the translation); without it, a copied pastille points into the wall
1166
+ * whenever the two models are not aligned on the same axis.
1167
+ * - `icon` and anything else is kept as-is.
1168
+ */
1169
+ getAdjustedPoiMetadata(metadata, transform) {
1170
+ if (!metadata) {
1171
+ return metadata ?? null;
1172
+ }
1173
+ try {
1174
+ const parsed = JSON.parse(metadata);
1175
+ if (!parsed || typeof parsed !== 'object') {
1176
+ return metadata;
1177
+ }
1178
+ if (parsed.normal
1179
+ && typeof parsed.normal === 'object'
1180
+ && typeof parsed.normal.x === 'number'
1181
+ && typeof parsed.normal.y === 'number'
1182
+ && typeof parsed.normal.z === 'number') {
1183
+ parsed.normal = applyRigidTransformToDirection(parsed.normal, transform);
1184
+ }
1185
+ delete parsed.sid;
1186
+ return JSON.stringify(parsed);
1187
+ }
1188
+ catch {
1189
+ // Not JSON, or unexpected shape — leave untouched rather than guess.
1190
+ return metadata;
1191
+ }
1192
+ }
1193
+ /**
1194
+ * Resolves a POI's `tagImageID` — which the schema documents as a "connection to
1195
+ * comment.id", i.e. the id of the Comment holding the image shown in the pastille.
1196
+ *
1197
+ * It is NOT an S3 key, so the previous "does it contain a slash?" heuristic never
1198
+ * matched and the value travelled unchanged, leaving every copied pastille pointing at
1199
+ * a Comment of the source space. It is now translated through the comment id map built
1200
+ * while duplicating the media, and dropped when it cannot be resolved (the pastille
1201
+ * then falls back to the feature's cover image instead of a broken reference).
1202
+ */
1203
+ resolveTagImageID(tagImageID) {
1204
+ if (!tagImageID) {
1205
+ return null;
1206
+ }
1207
+ return this.commentIds.get(tagImageID) ?? null;
1208
+ }
631
1209
  //
632
1210
  // ---------- Duplicate detection ----------
633
1211
  //
634
1212
  /**
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.
1213
+ * Heuristic duplicate-detection: compares several identifying fields together rather than
1214
+ * a single label, to reduce false positives when items share one of them.
1215
+ *
1216
+ * The fields are supplied by the caller because the models do not agree on them. The
1217
+ * previous version hard-coded `title`/`description`, which do not exist on Equipment at
1218
+ * all: both sides read `undefined`, every equipment therefore "matched" every other one,
1219
+ * and a target space holding a single equipment silently caused the whole equipment phase
1220
+ * to copy nothing.
638
1221
  */
639
- matchesExisting(source, targetList) {
640
- return targetList.some(t => t.title === source.title && (t.description || null) === (source.description || null));
1222
+ matchesExisting(source, targetList, identity) {
1223
+ const sourceKey = this.identityKey(identity(source));
1224
+ return targetList.some(target => this.identityKey(identity(target)) === sourceKey);
1225
+ }
1226
+ /** Serialises the identifying fields unambiguously, so that ["a", "b"] and ["ab", ""]
1227
+ * can never produce the same key. */
1228
+ identityKey(parts) {
1229
+ return JSON.stringify(parts.map(part => part ?? ''));
641
1230
  }
642
1231
  //
643
1232
  // ---------- Sweep positions / rigid transform ----------
@@ -731,10 +1320,12 @@ export class MatterportTagCopyService {
731
1320
  /**
732
1321
  * Builds a new S3 key for a copied attachment and sanitizes the filename
733
1322
  * to prevent AWS Amplify SignatureDoesNotMatch errors.
1323
+ * `folderOverride` re-homes the copy into another prefix — used for tag icons, which
1324
+ * are stored per space (`icons-tags/<spaceId>/`) and must follow the target space.
734
1325
  */
735
- buildCopiedAttachmentKey(sourceAnnexe) {
1326
+ buildCopiedAttachmentKey(sourceAnnexe, folderOverride = null) {
736
1327
  const lastSlash = sourceAnnexe.lastIndexOf('/');
737
- const folder = sourceAnnexe.substring(0, lastSlash + 1);
1328
+ const folder = folderOverride ?? sourceAnnexe.substring(0, lastSlash + 1);
738
1329
  let filename = sourceAnnexe.substring(lastSlash + 1);
739
1330
  // Strip a leading "<8 hex chars>_" id prefix if present
740
1331
  const prefixMatch = filename.match(/^[0-9a-fA-F-]{8}_(.+)$/);
@@ -754,12 +1345,12 @@ export class MatterportTagCopyService {
754
1345
  * skip the whole item entirely, rather than creating a record with a broken file link.
755
1346
  * - Any other kind of failure (permissions, network, etc.) still throws a generic Error.
756
1347
  */
757
- async copyS3KeyIfPresent(key, contextLabel) {
1348
+ async copyS3KeyIfPresent(key, contextLabel, folderOverride = null) {
758
1349
  if (!key) {
759
1350
  return null;
760
1351
  }
761
1352
  const sourceKey = this.extractS3KeyFromValue(key);
762
- const destKey = this.buildCopiedAttachmentKey(sourceKey);
1353
+ const destKey = this.buildCopiedAttachmentKey(sourceKey, folderOverride);
763
1354
  // Log the source key to ensure it matches the real S3 object path
764
1355
  console.log(`[DEBUG] Attempting S3 copy from source: "${sourceKey}" to dest: "${destKey}"`);
765
1356
  try {
@@ -770,49 +1361,101 @@ export class MatterportTagCopyService {
770
1361
  return copied;
771
1362
  }
772
1363
  catch (error) {
773
- const isMissingFile = error instanceof MissingS3FileError
774
- || error?.code === 'NoSuchKey'
775
- || /NoSuchKey|does not exist/i.test(toErrorMessage(error));
776
- if (isMissingFile) {
1364
+ if (this.isMissingS3File(error)) {
777
1365
  console.warn(`[MatterportTagCopyService] Orphaned S3 reference, skipping item: "${sourceKey}" (${contextLabel})`);
778
1366
  throw new MissingS3FileError(sourceKey, contextLabel);
779
1367
  }
1368
+ // Storage.copy() cannot handle a key holding a space, an accent or a parenthesis:
1369
+ // it puts the key unencoded into `x-amz-copy-source`, which then disagrees with the
1370
+ // signed request. Those files are perfectly readable — only that header is broken —
1371
+ // so fall back to downloading and re-uploading them.
1372
+ if (this.isSignatureMismatch(error)) {
1373
+ console.warn(`[MatterportTagCopyService] Storage.copy() signature mismatch on "${sourceKey}", falling back to download + re-upload.`);
1374
+ try {
1375
+ const copied = await copyFileInS3ViaDownload(sourceKey, destKey);
1376
+ if (!copied) {
1377
+ throw new MissingS3FileError(sourceKey, contextLabel);
1378
+ }
1379
+ return copied;
1380
+ }
1381
+ catch (fallbackError) {
1382
+ if (this.isMissingS3File(fallbackError)) {
1383
+ throw new MissingS3FileError(sourceKey, contextLabel);
1384
+ }
1385
+ throw fallbackError;
1386
+ }
1387
+ }
780
1388
  throw error;
781
1389
  }
782
1390
  }
1391
+ /** True when the failure means the source object simply is not on S3 (orphaned reference). */
1392
+ isMissingS3File(error) {
1393
+ return error instanceof MissingS3FileError
1394
+ || error?.code === 'NoSuchKey'
1395
+ || error?.name === 'NoSuchKey'
1396
+ || /NoSuchKey|does not exist|NotFound/i.test(toErrorMessage(error));
1397
+ }
1398
+ /** True when AppSync refused the operation for lack of permission, as opposed to failing it.
1399
+ * Nothing can be retried or worked around client-side: the account simply is not allowed
1400
+ * to write that model, which is a backend authorisation rule (@auth) to change. */
1401
+ isUnauthorized(error) {
1402
+ const message = toErrorMessage(error);
1403
+ return error?.errorType === 'Unauthorized'
1404
+ || /Unauthorized|Not Authorized to access/i.test(message);
1405
+ }
1406
+ /** True for the SigV4 mismatch Storage.copy() raises on keys with special characters. */
1407
+ isSignatureMismatch(error) {
1408
+ return error?.code === 'SignatureDoesNotMatch'
1409
+ || error?.name === 'SignatureDoesNotMatch'
1410
+ || /signature we calculated does not match|SignatureDoesNotMatch/i.test(toErrorMessage(error));
1411
+ }
783
1412
  /**
784
1413
  * 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.
1414
+ * { src, opacity }, per form-feature.component.ts).
1415
+ *
1416
+ * Two behaviours matter here:
1417
+ * - the copy is re-homed under the TARGET space's icon folder
1418
+ * (`icons-tags/<targetSpaceId>/`, the layout form-feature.component.ts uploads to).
1419
+ * Keeping the source folder produced a target space whose icons all lived under
1420
+ * another space's prefix, so cleaning up the source space broke the copy's icons.
1421
+ * - a missing icon file is NOT fatal. It used to bubble up as a MissingS3FileError and
1422
+ * abort the whole POI — losing the pastille, its text and its media because of a
1423
+ * decorative file. The POI is now created with the icon reference dropped, which
1424
+ * renders the module's default icon, and a log line reports it.
787
1425
  */
788
1426
  async duplicateTagIcon(tagIconRaw) {
789
1427
  if (!tagIconRaw) {
790
- return tagIconRaw;
1428
+ return tagIconRaw ?? null;
791
1429
  }
1430
+ let parsed;
792
1431
  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);
1432
+ parsed = JSON.parse(tagIconRaw);
798
1433
  }
799
1434
  catch {
800
- // Not JSON, or unexpected shape — leave untouched rather than guess.
1435
+ // Not JSON — leave untouched rather than guess.
801
1436
  return tagIconRaw;
802
1437
  }
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;
1438
+ if (!parsed || typeof parsed !== 'object' || !parsed.src) {
1439
+ return tagIconRaw;
1440
+ }
1441
+ try {
1442
+ parsed.src = await this.copyS3KeyIfPresent(parsed.src, 'tag icon', this.buildTargetIconFolder());
814
1443
  }
815
- return this.copyS3KeyIfPresent(tagImageID, 'tag image');
1444
+ catch (iconError) {
1445
+ if (!(iconError instanceof MissingS3FileError)) {
1446
+ // A real failure (permissions, network, ...) still aborts the POI: it means
1447
+ // the copy cannot be trusted, unlike a file that is simply already gone.
1448
+ throw iconError;
1449
+ }
1450
+ console.warn(`[MatterportTagCopyService] Tag icon missing on S3, falling back to the default icon: "${iconError.sourceKey}"`);
1451
+ this.logItemError('warningTagIconMissing', { file: iconError.sourceKey });
1452
+ delete parsed.src;
1453
+ }
1454
+ return JSON.stringify(parsed);
1455
+ }
1456
+ /** Icon folder of the space being copied into, matching what the feature form uploads to. */
1457
+ buildTargetIconFolder() {
1458
+ return this.targetSpaceId ? `icons-tags/${this.targetSpaceId}/` : null;
816
1459
  }
817
1460
  /**
818
1461
  * Extracts and normalizes the raw S3 key from a stored value (which may be a full URL
@@ -855,11 +1498,11 @@ export class MatterportTagCopyService {
855
1498
  // for the CopySource header. Do NOT re-encode it here.
856
1499
  return extracted;
857
1500
  }
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 });
1501
+ 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.SpaceService }, { token: i12.TranslateService }], target: i0.ɵɵFactoryTarget.Injectable });
859
1502
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportTagCopyService, providedIn: 'root' });
860
1503
  }
861
1504
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportTagCopyService, decorators: [{
862
1505
  type: Injectable,
863
1506
  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
1507
+ }], 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.SpaceService }, { type: i12.TranslateService }] });
1508
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0dGVycG9ydC10YWctY29weS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWNvcmUvc3JjL2xpYi9zZXJ2aWNlcy9tYXR0ZXJwb3J0LXRhZy1jb3B5LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBY3ZDLE9BQU8sRUFBRSxZQUFZLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxjQUFjLENBQUMsQ0FBQyx5R0FBeUc7QUFDL0ssT0FBTyxFQUNILHFCQUFxQixFQUFFLDBCQUEwQixFQUFFLDhCQUE4QixFQUNqRixpQ0FBaUMsRUFDcEMsTUFBTSxtQ0FBbUMsQ0FBQztBQUMzQyxPQUFPLEVBQTJDLFdBQVcsRUFBRSxPQUFPLEVBQWEsUUFBUSxFQUFtQixNQUFNLGtCQUFrQixDQUFDOzs7Ozs7Ozs7Ozs7OztBQW9Cdkk7d0VBQ3dFO0FBQ3hFLFNBQVMsY0FBYyxDQUFDLEdBQVk7SUFDaEMsSUFBSSxHQUFHLElBQUksT0FBTyxHQUFHLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDakMsTUFBTSxNQUFNLEdBQUcsR0FBVSxDQUFDO1FBQzFCLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDM0QsT0FBTyxNQUFNLENBQUMsTUFBTTtpQkFDZixHQUFHLENBQUMsQ0FBQyxDQUFNLEVBQUUsRUFBRTtnQkFDWixNQUFNLEtBQUssR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUNwRCxP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QUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ2pELENBQUM7WUFBQyxNQUFNLENBQUM7Z0JBQ0wsU0FBUyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDcEMsQ0FBQztRQUNMLENBQUM7YUFBTSxDQUFDO1lBQ0osU0FBUyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDcEMsQ0FBQztRQUVELDBCQUEwQjtRQUMxQixJQUFJLFNBQVMsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUM1QixTQUFTLEdBQUcsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN2QyxDQUFDO1FBRUQsNkJBQTZCO1FBQzdCLHVFQUF1RTtRQUN2RSxxREFBcUQ7UUFDckQsSUFBSSxTQUFTLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7WUFDbEMsU0FBUyxHQUFHLFNBQVMsQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RELENBQUM7UUFFRCwrRUFBK0U7UUFDL0UsdURBQXVEO1FBQ3ZELE9BQU8sU0FBUyxDQUFDO0lBQ3JCLENBQUM7d0dBeHFEUSx3QkFBd0I7NEdBQXhCLHdCQUF3QixjQURYLE1BQU07OzRGQUNuQix3QkFBd0I7a0JBRHBDLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBUcmFuc2xhdGVTZXJ2aWNlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5pbXBvcnQgeyBQT0kgfSBmcm9tICcuLi90eXBlcy5zZXJ2aWNlJztcbmltcG9ydCB7IE5hdmlnYXRpb25TZXJ2aWNlIH0gZnJvbSAnLi9tb2RlbHMvbmF2aWdhdGlvbi5zZXJ2aWNlJztcbmltcG9ydCB7IFBvaVNlcnZpY2UgfSBmcm9tICcuL21vZGVscy9wb2kuc2VydmljZSc7XG5pbXBvcnQgeyBUaWNrZXRzU2VydmljZSB9IGZyb20gJy4vbW9kZWxzL3RpY2tldC5zZXJ2aWNlJztcbmltcG9ydCB7IEVxdWlwbWVudFNlcnZpY2UgfSBmcm9tICcuL21vZGVscy9lcXVpcG1lbnQuc2VydmljZSc7XG5pbXBvcnQgeyBPYmplY3QzRFNlcnZpY2UgfSBmcm9tICcuL21vZGVscy9vYmplY3QzRC5zZXJ2aWNlJztcbmltcG9ydCB7IEZlYXR1cmVTZXJ2aWNlIH0gZnJvbSAnLi9tb2RlbHMvZmVhdHVyZS5zZXJ2aWNlJztcbmltcG9ydCB7IE1lYXN1cmVtZW50U2VydmljZSB9IGZyb20gJy4vbW9kZWxzL21lYXN1cmVtZW50LnNlcnZpY2UnO1xuaW1wb3J0IHsgQ29tbWVudFNlcnZpY2UgfSBmcm9tICcuL21vZGVscy9jb21tZW50LnNlcnZpY2UnO1xuaW1wb3J0IHsgSGFzaHRhZ1NlcnZpY2UgfSBmcm9tICcuL21vZGVscy9oYXNodGFnLnNlcnZpY2UnO1xuaW1wb3J0IHsgU3BhY2VTZXJ2aWNlIH0gZnJvbSAnLi9tb2RlbHMvc3BhY2Uuc2VydmljZSc7XG5pbXBvcnQgeyBCYXNlVXNlclNlcnZpY2UgfSBmcm9tICcuL3VzZXIuc2VydmljZSc7XG5pbXBvcnQgeyBjb3B5RmlsZUluUzMsIGNvcHlGaWxlSW5TM1ZpYURvd25sb2FkIH0gZnJvbSAnLi9zMy5zZXJ2aWNlJzsgLy8gc2VlIHMzLnNlcnZpY2UudHM6IG5laXRoZXIgbXVzdCBzd2FsbG93IGVycm9ycyAobmVlZGVkIHRvIGRldGVjdCBOb1N1Y2hLZXkgLyBzaWduYXR1cmUgbWlzbWF0Y2ggYmVsb3cpXG5pbXBvcnQge1xuICAgIGNvbXB1dGVSaWdpZFRyYW5zZm9ybSwgYXBwbHlSaWdpZFRyYW5zZm9ybVRvUG9pbnQsIGFwcGx5UmlnaWRUcmFuc2Zvcm1Ub0RpcmVjdGlvbixcbiAgICBhcHBseVJpZ2lkVHJhbnNmb3JtVG9ZUm90YXRpb25EZWcsIFJpZ2lkVHJhbnNmb3JtLCBWZWMzXG59IGZyb20gJy4vdXRpbHMvbWF0dGVycG9ydC10cmFuc2Zvcm0udXRpbCc7XG5pbXBvcnQgeyBPYmplY3QzRCwgRmVhdHVyZSwgTWVhc3VyZW1lbnQsIENvbW1lbnQsIENvbW1lbnRUeXBlLCBQb2lUeXBlLCBFcXVpcG1lbnQsIFNwTW9kdWxlLCBUaWNrZXQsIEhhc2h0YWcgfSBmcm9tICcuLi90eXBlcy5zZXJ2aWNlJztcblxuLyoqIFByb2dyZXNzIHNuYXBzaG90IGVtaXR0ZWQgZHVyaW5nIGNvcHlUYWdzRnJvbVZpc2l0KCksIHNvIHRoZSBVSSBjYW4gc2hvdyBhIGxpdmUgc3RhdHVzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBDb3B5UHJvZ3Jlc3Mge1xuICAgIHBoYXNlOiAnY29sbGVjdGluZycgfCAndGlja2V0cycgfCAnZXF1aXBtZW50cycgfCAncG9pcycgfCAnb2JqZWN0czNkJyB8ICdmZWF0dXJlcycgfCAnbWVhc3VyZW1lbnRzJyB8ICdkb25lJztcbiAgICBwcm9jZXNzZWRJblBoYXNlOiBudW1iZXI7XG4gICAgdG90YWxJblBoYXNlOiBudW1iZXI7XG4gICAgcHJvY2Vzc2VkT3ZlcmFsbDogbnVtYmVyO1xuICAgIHRvdGFsT3ZlcmFsbDogbnVtYmVyO1xuICAgIHBlcmNlbnQ6IG51bWJlcjtcbiAgICBlcnJvckNvdW50OiBudW1iZXI7XG59XG5cbi8qKiBBIHNpbmdsZSBsaW5lIGluIHRoZSBjb3B5IGxvZyDigJQgZWl0aGVyIGEgc3RlcCBzdGF0dXMgKHVwZGF0ZWQgaW4gcGxhY2UpIG9yIGFuIGVycm9yIChhcHBlbmRlZCBvbmNlKS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ29weUxvZ0VudHJ5IHtcbiAgICBpZDogc3RyaW5nOyAgICAgICAvLyBzdGFibGUgaWQgZm9yIHN0ZXAgbGluZXMgKHNvIHRoZXkgdXBkYXRlIGluIHBsYWNlKSwgdW5pcXVlIGZvciBlcnJvciBsaW5lc1xuICAgIHR5cGU6ICdzdGVwJyB8ICdlcnJvcic7XG4gICAgdGV4dDogc3RyaW5nO1xufVxuXG4vKiogU2FmZWx5IGV4dHJhY3RzIGEgcmVhZGFibGUgbWVzc2FnZSBmcm9tIGFuIHVua25vd24gY2F0Y2ggdmFsdWUsIGluY2x1ZGluZyBBbXBsaWZ5J3NcbiAqICBHcmFwaFFMIGVycm9yIHNoYXBlICh7IGRhdGEsIGVycm9yczogW3sgZXJyb3JUeXBlLCBtZXNzYWdlIH1dIH0pLiAqL1xuZnVuY3Rpb24gdG9FcnJvck1lc3NhZ2UoZXJyOiB1bmtub3duKTogc3RyaW5nIHtcbiAgICBpZiAoZXJyICYmIHR5cGVvZiBlcnIgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIGNvbnN0IGFueUVyciA9IGVyciBhcyBhbnk7XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KGFueUVyci5lcnJvcnMpICYmIGFueUVyci5lcnJvcnMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgcmV0dXJuIGFueUVyci5lcnJvcnNcbiAgICAgICAgICAgICAgICAubWFwKChlOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGl0bGUgPSBlLmVycm9yVHlwZSA/IGAke2UuZXJyb3JUeXBlfTogYCA6ICcnO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYCR7dGl0bGV9JHtlLm1lc3NhZ2UgfHwgJ1Vua25vd24gZXJyb3InfWA7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuam9pbignIHwgJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gZXJyLm1lc3NhZ2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKHR5cGVvZiBlcnIgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBlcnI7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShlcnIpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gU3RyaW5nKGVycik7XG4gICAgfVxufVxuXG4vKiogVGhyb3duIHdoZW4gdGhlIHJlZmVyZW5jZWQgUzMgc291cmNlIGZpbGUgZG9lc24ndCBleGlzdCAob3JwaGFuZWQgREIgcmVmZXJlbmNlIOKAlFxuICogIGUuZy4gdGhlIGZpbGUgd2FzIGRlbGV0ZWQgb3IgcmVuYW1lZCBvbiBTMyB3aXRob3V0IHVwZGF0aW5nIHRoZSBkYXRhYmFzZSkuXG4gKiAgS2VwdCBkaXN0aW5jdCBmcm9tIG90aGVyIGNvcHkgZmFpbHVyZXMgc28gdGhlIGNhbGxpbmcgbG9vcCBjYW4gbG9nIGEgY2xlYXIsXG4gKiAgc3BlY2lmaWMgbWVzc2FnZSBhbmQgc2tpcCB0aGUgd2hvbGUgaXRlbSBpbnN0ZWFkIG9mIGEgZ2VuZXJpYyBlcnJvci4gKi9cbmNsYXNzIE1pc3NpbmdTM0ZpbGVFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgICBjb25zdHJ1Y3RvcihwdWJsaWMgcmVhZG9ubHkgc291cmNlS2V5OiBzdHJpbmcsIHB1YmxpYyByZWFkb25seSBjb250ZXh0TGFiZWw6IHN0cmluZykge1xuICAgICAgICBzdXBlcihgU291cmNlIGZpbGUgbWlzc2luZyBvbiBTMzogXCIke3NvdXJjZUtleX1cIiAoJHtjb250ZXh0TGFiZWx9KWApO1xuICAgICAgICB0aGlzLm5hbWUgPSAnTWlzc2luZ1MzRmlsZUVycm9yJztcbiAgICB9XG59XG5cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgTWF0dGVycG9ydFRhZ0NvcHlTZXJ2aWNlIHtcblxuICAgIC8vIEVtaXRzIHByb2dyZXNzIHVwZGF0ZXMgZHVyaW5nIGNvcHlUYWdzRnJvbVZpc2l0KCk7IG51bGwgd2hlbiBpZGxlXG4gICAgcHVibGljIGNvcHlQcm9ncmVzcyQ6IEJlaGF2aW9yU3ViamVjdDxDb3B5UHJvZ3Jlc3MgfCBudWxsPiA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Q29weVByb2dyZXNzIHwgbnVsbD4obnVsbCk7XG5cbiAgICAvLyBFbWl0cyB0aGUgYWNjdW11bGF0ZWQgbG9nIGxpbmVzIGR1cmluZyBjb3B5VGFnc0Zyb21WaXNpdCgpOyBbXSB3aGVuIGlkbGVcbiAgICBwdWJsaWMgY29weUxvZyQ6IEJlaGF2aW9yU3ViamVjdDxDb3B5TG9nRW50cnlbXT4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0PENvcHlMb2dFbnRyeVtdPihbXSk7XG5cbiAgICBwcml2YXRlIHNwTW9kdWxlOiBTcE1vZHVsZTtcbiAgICBwcml2YXRlIGxvZzogQ29weUxvZ0VudHJ5W10gPSBbXTtcbiAgICBwcml2YXRlIGVycm9yU2VxID0gMDtcblxuICAgIC8vIC0tLS0gUGVyLXJ1biByZW1hcHBpbmcgc3RhdGUgKHJlc2V0IGJ5IHJlc2V0UnVuU3RhdGUoKSBhdCB0aGUgc3RhcnQgb2YgZXZlcnkgY29weSkgLS0tLVxuXG4gICAgLyoqIHNvdXJjZSBlbGVtZW50IGlkIC0+IGlkIG9mIGl0cyBjb3B5IGluIHRoZSB0YXJnZXQgc3BhY2UuICovXG4gICAgcHJpdmF0ZSBlbGVtZW50SWRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG5cbiAgICAvKiogc291cmNlIENvbW1lbnQgaWQgLT4gaWQgb2YgaXRzIGNvcHkuIE5lZWRlZCB0byByZW1hcCBQT0kudGFnSW1hZ2VJRCwgd2hpY2ggaXMgYVxuICAgICAqICByZWZlcmVuY2UgdG8gYSBDb21tZW50IHJlY29yZCAoc2VlIHRoZSBzY2hlbWE6IFwiY29ubmVjdGlvbiB0byBjb21tZW50LmlkXCIpLiAqL1xuICAgIHByaXZhdGUgY29tbWVudElkczogTWFwPHN0cmluZywgc3RyaW5nPiA9IG5ldyBNYXAoKTtcblxuICAgIC8vIEhhc2h0YWdzIGFyZSBzcGFjZS1zY29wZWQgcmVjb3Jkcywgc28gdGhlaXIgaWRzIGNhbiBuZXZlciBiZSBjYXJyaWVkIG92ZXIgYXMtaXM6IHRoZXlcbiAgICAvLyBhcmUgbWF0Y2hlZCBieSBOQU1FIGFnYWluc3QgdGhlIHRhcmdldCBzcGFjZSwgYW5kIHRoZSBtaXNzaW5nIG9uZXMgYXJlIGNyZWF0ZWQgdGhlcmUuXG4gICAgLy8gVGhhdCBjcmVhdGlvbiBpcyBkZWxpYmVyYXRlbHkgbGF6eSDigJQgc2VlIHJlc29sdmVIYXNodGFnSWRzKCkg4oCUIGFuZCBhdWRpdGVkLCBzbyBhblxuICAgIC8vIGludGVycnVwdGVkIGNvcHkgY2Fubm90IGxlYXZlIGtleXdvcmRzIGJlaGluZCB0aGF0IG5vIFBPSSByZWZlcmVuY2VzLlxuXG4gICAgLyoqIHNvdXJjZSBIYXNodGFnIGlkIC0+IGl0cyBuYW1lLiAqL1xuICAgIHByaXZhdGUgc291cmNlSGFzaHRhZ05hbWVzOiBNYXA8c3RyaW5nLCBzdHJpbmc+ID0gbmV3IE1hcCgpO1xuXG4gICAgLyoqIG5vcm1hbGlzZWQgaGFzaHRhZyBuYW1lIC0+IGl0cyBpZCBpbiB0aGUgVEFSR0VUIHNwYWNlIChwcmUtZXhpc3Rpbmcgb3IganVzdCBjcmVhdGVkKS4gKi9cbiAgICBwcml2YXRlIHRhcmdldEhhc2h0YWdJZHNCeU5hbWU6IE1hcDxzdHJpbmcsIHN0cmluZz4gPSBuZXcgTWFwKCk7XG5cbiAgICAvKiogaWRzIG9mIHRoZSBoYXNodGFncyB0aGlzIHJ1biBjcmVhdGVkIGluIHRoZSB0YXJnZXQgc3BhY2UuICovXG4gICAgcHJpdmF0ZSBjcmVhdGVkSGFzaHRhZ0lkczogU2V0PHN0cmluZz4gPSBuZXcgU2V0KCk7XG5cbiAgICAvKiogaWRzIG9mIHRoZSBoYXNodGFncyBhY3R1YWxseSBwZXJzaXN0ZWQgb24gYSBzdWNjZXNzZnVsbHkgY3JlYXRlZCBmZWF0dXJlLiBBbnl0aGluZyBpblxuICAgICAqICBjcmVhdGVkSGFzaHRhZ0lkcyBidXQgYWJzZW50IGhlcmUgaXMgYW4gb3JwaGFuIGFuZCBpcyBkZWxldGVkIGF0IHRoZSBlbmQgb2YgdGhlIHJ1bi4gKi9cbiAgICBwcml2YXRlIHVzZWRIYXNodGFnSWRzOiBTZXQ8c3RyaW5nPiA9IG5ldyBTZXQoKTtcblxuICAgIC8qKiBzb3VyY2UgaWRzIG9mIHRoZSBlbGVtZW50cyB3aG9zZSBQT0lzIHdlcmUgYWxyZWFkeSBjcmVhdGVkIGJ5IGFuIGVsZW1lbnQgcGhhc2UuXG4gICAgICogIEd1YXJkcyB0aGUgc3RhbmRhbG9uZSBQT0kgcGhhc2UgYWdhaW5zdCBjcmVhdGluZyBhIHNlY29uZCwgaW1wb3ZlcmlzaGVkIGNvcHkuICovXG4gICAgcHJpdmF0ZSBoYW5kbGVkRWxlbWVudElkczogU2V0PHN0cmluZz4gPSBuZXcgU2V0KCk7XG5cbiAgICAvKiogdHJ1ZSB3aGVuIHNvdXJjZSBhbmQgdGFyZ2V0IHNwYWNlcyBiZWxvbmcgdG8gdGhlIHNhbWUgb3JnYW5pc2F0aW9uLiBEb21haW5zIGFyZVxuICAgICAqICBvcmdhbmlzYXRpb24tc2NvcGVkIChubyBzcGFjZUlEKSwgc28gZG9tYWluSUQgc3Vydml2ZXMgdGhlIGNvcHkgb25seSBpbiB0aGF0IGNhc2UuICovXG4gICAgcHJpdmF0ZSBzYW1lT3JnYW5pc2F0aW9uID0gZmFsc2U7XG5cbiAgICAvKiogVGFyZ2V0IHNwYWNlIGlkIG9mIHRoZSBydW4gaW4gcHJvZ3Jlc3Mg4oCUIHVzZWQgdG8gcmUtaG9tZSBjb3BpZWQgdGFnIGljb25zLiAqL1xuICAgIHByaXZhdGUgdGFyZ2V0U3BhY2VJZDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHJpdmF0ZSBuYXZpZ2F0aW9uU2VydmljZTogTmF2aWdhdGlvblNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgdXNlclNlcnZpY2U6IEJhc2VVc2VyU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBwb2lTZXJ2aWNlOiBQb2lTZXJ2aWNlLFxuICAgICAgICBwcml2YXRlIHRpY2tldFNlcnZpY2U6IFRpY2tldHNTZXJ2aWNlLFxuICAgICAgICBwcml2YXRlIGVxdWlwbWVudFNlcnZpY2U6IEVxdWlwbWVudFNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgb2JqZWN0M0RTZXJ2aWNlOiBPYmplY3QzRFNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgZmVhdHVyZVNlcnZpY2U6IEZlYXR1cmVTZXJ2aWNlLFxuICAgICAgICBwcml2YXRlIG1lYXN1cmVtZW50U2VydmljZTogTWVhc3VyZW1lbnRTZXJ2aWNlLFxuICAgICAgICBwcml2YXRlIGNvbW1lbnRTZXJ2aWNlOiBDb21tZW50U2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBoYXNodGFnU2VydmljZTogSGFzaHRhZ1NlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgc3BhY2VTZXJ2aWNlOiBTcGFjZVNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgdHJhbnNsYXRlOiBUcmFuc2xhdGVTZXJ2aWNlXG4gICAgKSB7XG4gICAgICAgIHRoaXMuc3BNb2R1bGUgPSB1c2VyU2VydmljZS5nZXRTcE1vZHVsZSgpO1xuICAgIH1cblxuICAgIC8vXG4gICAgLy8gLS0tLS0tLS0tLSBQdWJsaWMgQVBJIC0tLS0tLS0tLS1cbiAgICAvL1xuXG4gICAgYXN5bmMgY29weVRhZ3NGcm9tVmlzaXQoXG4gICAgICAgIHNvdXJjZVNwYWNlSWQ6IHN0cmluZyxcbiAgICAgICAgdGFyZ2V0U3BhY2VJZDogc3RyaW5nLFxuICAgICAgICBsYW5kbWFya1NvdXJjZUE6IFZlYzMsIGxhbmRtYXJrVGFyZ2V0QTogVmVjMyxcbiAgICAgICAgbGFuZG1hcmtTb3VyY2VCOiBWZWMzLCBsYW5kbWFya1RhcmdldEI6IFZlYzNcbiAgICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgbGV0IGVycm9yQ291bnQgPSAwO1xuICAgICAgICB0aGlzLnJlc2V0TG9nKCk7XG4gICAgICAgIHRoaXMucmVzZXRSdW5TdGF0ZSh0YXJnZXRTcGFjZUlkKTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc29sZS5sb2coYENvcHlpbmcgVGFncyBmcm9tIHNvdXJjZSAke3NvdXJjZVNwYWNlSWR9IHRvIHRhcmdldCAke3RhcmdldFNwYWNlSWR9YCk7XG5cbiAgICAgICAgICAgIHRoaXMuc2V0U3RlcFByb2dyZXNzKCdjb2xsZWN0aW5nJywgJ2NvbGxlY3RpbmcnLCAwKTtcbiAgICAgICAgICAgIHRoaXMuY29weVByb2dyZXNzJC5uZXh0KHtcbiAgICAgICAgICAgICAgICBwaGFzZTogJ2NvbGxlY3RpbmcnLFxuICAgICAgICAgICAgICAgIHByb2Nlc3NlZEluUGhhc2U6IDAsIHRvdGFsSW5QaGFzZTogMCxcbiAgICAgICAgICAgICAgICBwcm9jZXNzZWRPdmVyYWxsOiAwLCB0b3RhbE92ZXJhbGw6IDAsXG4gICAgICAgICAgICAgICAgcGVyY2VudDogMCwgZXJyb3JDb3VudDogMFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGNvbnN0IHRhcmdldE1pc3Npb24gPSB0aGlzLnVzZXJTZXJ2aWNlLmN1cnJlbnRNaXNzaW9uKHRhcmdldFNwYWNlSWQpO1xuICAgICAgICAgICAgY29uc3QgdGFyZ2V0TWlzc2lvbklkID0gdGFyZ2V0TWlzc2lvbiA/IHRhcmdldE1pc3Npb24uaWQgOiBudWxsO1xuXG4gICAgICAgICAgICBjb25zdCB0cmFuc2Zvcm06IFJpZ2lkVHJhbnNmb3JtID0gY29tcHV0ZVJpZ2lkVHJhbnNmb3JtKFxuICAgICAgICAgICAgICAgIGxhbmRtYXJrU291cmNlQSwgbGFuZG1hcmtUYXJnZXRBLFxuICAgICAgICAgICAgICAgIGxhbmRtYXJrU291cmNlQiwgbGFuZG1hcmtUYXJnZXRCXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ1JpZ2lkIHRyYW5zZm9ybSBjb21wdXRlZDonLCB7XG4gICAgICAgICAgICAgICAgcm90YXRpb25ZRGVnOiB0cmFuc2Zvcm0ucm90YXRpb25ZUmFkICogKDE4MCAvIE1hdGguUEkpLFxuICAgICAgICAgICAgICAgIHJlZlNvdXJjZTogdHJhbnNmb3JtLnJlZlNvdXJjZSxcbiAgICAgICAgICAgICAgICByZWZUYXJnZXQ6IHRyYW5zZm9ybS5yZWZUYXJnZXRcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBEb21haW5zIGFyZSBvcmdhbmlzYXRpb24tc2NvcGVkLCBoYXNodGFncyBhcmUgc3BhY2Utc2NvcGVkOiBib3RoIG5lZWQgdG8ga25vd1xuICAgICAgICAgICAgLy8gd2hldGhlciB3ZSBzdGF5IGluc2lkZSB0aGUgc2FtZSBvcmdhbmlzYXRpb24gYmVmb3JlIGFueXRoaW5nIGlzIHJlbWFwcGVkLlxuICAgICAgICAgICAgdGhpcy5zYW1lT3JnYW5pc2F0aW9uID0gYXdhaXQgdGhpcy5zcGFjZXNTaGFyZU9yZ2FuaXNhdGlvbihzb3VyY2VTcGFjZUlkLCB0YXJnZXRTcGFjZUlkKTtcblxuICAgICAgICAgICAgY29uc3Qgc291cmNlU3dlZXBJZHMgPSBhd2FpdCB0aGlzLm5hdmlnYXRpb25TZXJ2aWNlLmdldEFsbG93ZWRTd2VlcHNJRHNGb3JVc2VySW5TcGFjZShzb3VyY2VTcGFjZUlkKTtcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldFN3ZWVwSWRzID0gYXdhaXQgdGhpcy5uYXZpZ2F0aW9uU2VydmljZS5nZXRBbGxvd2VkU3dlZXBzSURzRm9yVXNlckluU3BhY2UodGFyZ2V0U3BhY2VJZCk7XG5cbiAgICAgICAgICAgIHRoaXMuc2V0U3RlcFByb2dyZXNzKCdjb2xsZWN0aW5nJywgJ2NvbGxlY3RpbmcnLCAzMCk7XG5cbiAgICAgICAgICAgIGNvbnN0IFtzb3VyY2VOYXZQb3NpdGlvbnMsIHRhcmdldE5hdlBvc2l0aW9uc10gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgICAgICAgICAgdGhpcy5idWlsZE5hdmlnYXRpb25Qb3NpdGlvbk1hcChzb3VyY2VTcGFjZUlkLCBzb3VyY2VTd2VlcElkcyksXG4gICAgICAgICAgICAgICAgdGhpcy5idWlsZE5hdmlnYXRpb25Qb3NpdGlvbk1hcCh0YXJnZXRTcGFjZUlkLCB0YXJnZXRTd2VlcElkcylcbiAgICAgICAgICAgIF0pO1xuXG4gICAgICAgICAgICBjb25zdCBlbGVtZW50SWRzID0gdGhpcy5lbGVtZW50SWRzO1xuXG4gICAgICAgICAgICBsZXQgc291cmNlVGlja2V0czogVGlja2V0W10gPSBbXTtcbiAgICAgICAgICAgIGxldCBzb3VyY2VFcXVpcG1lbnRzOiBFcXVpcG1lbnRbXSA9IFtdO1xuICAgICAgICAgICAgbGV0IHRhcmdldFRpY2tldHM6IFRpY2tldFtdID0gW107XG4gICAgICAgICAgICBsZXQgdGFyZ2V0RXF1aXBtZW50czogRXF1aXBtZW50W10gPSBbXTtcbiAgICAgICAgICAgIGxldCBzb3VyY2VNZWFzdXJlbWVudHM6IE1lYXN1cmVtZW50W10gPSBbXTtcbiAgICAgICAgICAgIGxldCB0YXJnZXRNZWFzdXJlbWVudHM6IE1lYXN1cmVtZW50W10gPSBbXTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuc3BNb2R1bGUgPT0gU3BNb2R1bGUuSU1NTykge1xuICAgICAgICAgICAgICAgIHNvdXJjZVRpY2tldHMgPSBhd2FpdCB0aGlzLnRpY2tldFNlcnZpY2UuZ2V0VGlja2V0c0J5U3BhY2Uoc291cmNlU3BhY2VJZCk7XG4gICAgICAgICAgICAgICAgc291cmNlRXF1aXBtZW50cyA9IGF3YWl0IHRoaXMuZXF1aXBtZW50U2VydmljZS5nZXRFcXVpcG1lbnRzRm9yU3BhY2Uoc291cmNlU3BhY2VJZCk7XG4gICAgICAgICAgICAgICAgdGFyZ2V0VGlja2V0cyA9IGF3YWl0IHRoaXMudGlja2V0U2VydmljZS5nZXRUaWNrZXRzQnlTcGFjZSh0YXJnZXRTcGFjZUlkKTtcbiAgICAgICAgICAgICAgICB0YXJnZXRFcXVpcG1lbnRzID0gYXdhaXQgdGhpcy5lcXVpcG1lbnRTZXJ2aWNlLmdldEVxdWlwbWVudHNGb3JTcGFjZSh0YXJnZXRTcGFjZUlkKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5zZXRTdGVwUHJvZ3Jlc3MoJ2NvbGxlY3RpbmcnLCAnY29sbGVjdGluZycsIDU1KTtcblxuICAgICAgICAgICAgY29uc3Qgc291cmNlT2JqZWN0czNEID0gYXdhaXQgdGhpcy5vYmplY3QzRFNlcnZpY2UuZ2V0T2JqZWN0czNEQnlTcGFjZShzb3VyY2VTcGFjZUlkKTtcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldE9iamVjdHMzRCA9IGF3YWl0IHRoaXMub2JqZWN0M0RTZXJ2aWNlLmdldE9iamVjdHMzREJ5U3BhY2UodGFyZ2V0U3BhY2VJZCk7XG5cbiAgICAgICAgICAgIC8vIFBhZ2luYXRlZDogYSBzcGFjZSByb3V0aW5lbHkgaG9sZHMgbW9yZSB0aGFuIHRoZSAxMDAgZmVhdHVyZXMgYSBzaW5nbGUgQXBwU3luY1xuICAgICAgICAgICAgLy8gcGFnZSByZXR1cm5zLCBhbmQgdGhlIHRhaWwgd2FzIHNpbGVudGx5IGRyb3BwZWQuXG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gVGhlIHNvdXJjZSBsaXN0IGtlZXBzIHRoZSBoaXN0b3JpY2FsIFwic2tpcCB3aGF0IHRoZSBvcGVyYXRvciBhcmNoaXZlZFwiIHJ1bGUsIHNvXG4gICAgICAgICAgICAvLyB0aGUgc2V0IG9mIGNvcGllZCBmZWF0dXJlcyBkb2VzIG5vdCBjaGFuZ2Ug4oCUIGJ1dCB0aGUgY2hlY2sgaXMgbm93IG51bGwtc2FmZTpcbiAgICAgICAgICAgIC8vIEZlYXR1cmVTZXJ2aWNlLmlzQXJjaGl2ZWQoKSBkZXJlZmVyZW5jZXMgY3VycmVudE1pc3Npb24oc3BhY2VJRCkuaWQgYW5kIHRocmV3IGFcbiAgICAgICAgICAgIC8vIFR5cGVFcnJvciB3aGVuIHRoZSBvcGVyYXRvciBoYWQgbm8gbWlzc2lvbiBvbiB0aGUgc291cmNlIHNwYWNlICh0aGUgY29tbW9uIGNhc2VcbiAgICAgICAgICAgIC8vIGZvciBhbiBhcmNoaXZlZCB2MSBzcGFjZSksIGFib3J0aW5nIHRoZSB3aG9sZSBjb3B5LlxuICAgICAgICAgICAgLy8gVGhlIHRhcmdldCBsaXN0IGlzIE5PVCBmaWx0ZXJlZDogaXQgb25seSBmZWVkcyBkdXBsaWNhdGUgZGV0ZWN0aW9uLCBhbmQgYW5cbiAgICAgICAgICAgIC8vIGFyY2hpdmVkIGZlYXR1cmUgaXMgc3RpbGwgYSBmZWF0dXJlIHRoYXQgZXhpc3RzIHRoZXJlLlxuICAgICAgICAgICAgY29uc3Qgc291cmNlRmVhdHVyZXMgPSAoYXdhaXQgdGhpcy5mZWF0dXJlU2VydmljZS5nZXRBbGxGZWF0dXJlc0J5U3BhY2VSYXcoc291cmNlU3BhY2VJZCkpXG4gICAgICAgICAgICAgICAgLmZpbHRlcihmZWF0dXJlID0+ICF0aGlzLmlzQXJjaGl2ZWRGb3JPcGVyYXRvcihmZWF0dXJlLCBzb3VyY2VTcGFjZUlkKSk7XG4gICAgICAgICAgICBjb25zdCB0YXJnZXRGZWF0dXJlcyA9IGF3YWl0IHRoaXMuZmVhdHVyZVNlcnZpY2UuZ2V0QWxsRmVhdHVyZXNCeVNwYWNlUmF3KHRhcmdldFNwYWNlSWQpO1xuXG4gICAgICAgICAgICB0aGlzLnNldFN0ZXBQcm9ncmVzcygnY29sbGVjdGluZycsICdjb2xsZWN0aW5nJywgNzUpO1xuXG4gICAgICAgICAgICAvLyBLZXl3b3JkczogaW5kZXggYm90aCB2b2NhYnVsYXJpZXMgbm93IChyZWFkLW9ubHkpLiBUaGUga2V5d29yZHMgdGhlIHRhcmdldCBzcGFjZVxuICAgICAgICAgICAgLy8gaXMgbWlzc2luZyBhcmUgY3JlYXRlZCBsYXRlciwgUE9JIGJ5IFBPSSwgb25seSBmb3IgdGhvc2UgYWN0dWFsbHkgdXNlZC5cbiAgICAgICAgICAgIGF3YWl0IHRoaXMubG9hZEhhc2h0YWdJbmRleChzb3VyY2VTcGFjZUlkLCB0YXJnZXRTcGFjZUlkKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuc3BNb2R1bGUgPT0gU3BNb2R1bGUuSU1NTykge1xuICAgICAgICAgICAgICAgIHNvdXJjZU1lYXN1cmVtZW50cyA9IGF3YWl0IHRoaXMubWVhc3VyZW1lbnRTZXJ2aWNlLmdldE1lYXN1cmVtZW50c0ZvclNwYWNlRm9yVXNlcihzb3VyY2VTcGFjZUlkKTtcbiAgICAgICAgICAgICAgICB0YXJnZXRNZWFzdXJlbWVudHMgPSBhd2FpdCB0aGlzLm1lYXN1cmVtZW50U2VydmljZS5nZXRNZWFzdXJlbWVudHNGb3JTcGFjZUZvclVzZXIodGFyZ2V0U3BhY2VJZCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuc2V0U3RlcFByb2dyZXNzKCdjb2xsZWN0aW5nJywgJ2NvbGxlY3RpbmcnLCA5MCk7XG5cbiAgICAgICAgICAgIGNvbnN0IHNvdXJjZVBvaXNBbGwgPSBhd2FpdCB0aGlzLnBvaVNlcnZpY2UuZ2V0UG9pc0J5TWF0dGVycG9ydFN3ZWVwcyhzb3VyY2VTd2VlcElkcyk7XG4gICAgICAgICAgICBjb25zdCB0YXJnZXRQb2lzQWxsID0gYXdhaXQgdGhpcy5wb2lTZXJ2aWNlLmdldFBvaXNCeU1hdHRlcnBvcnRTd2VlcHModGFyZ2V0U3dlZXBJZHMpO1xuXG4gICAgICAgICAgICAvLyBBIFBPSSBpcyBcIm93bmVkXCIgYnkgYW4gZWxlbWVudCAodGlja2V0LCBlcXVpcG1lbnQsIDNEIG9iamVjdCwgZmVhdHVyZSwgbWVhc3VyZW1lbnQpXG4gICAgICAgICAgICAvLyB3aGVuIGl0cyBlbGVtZW50SUQgcG9pbnRzIGF0IG9uZS4gVGhvc2UgUE9JcyBhcmUgY3JlYXRlZCBieSB0aGVpciBlbGVtZW50J3MgcGhhc2UsXG4gICAgICAgICAgICAvLyB3aGljaCBpcyB0aGUgb25seSBwbGFjZSB0aGF0IGtub3dzIHRoZSBlbGVtZW50J3MgTkVXIGlkIOKAlCBzbyB0aGV5IG11c3QgYmUgZXhjbHVkZWRcbiAgICAgICAgICAgIC8vIGZyb20gdGhlIHN0YW5kYWxvbmUgcGhhc2UsIG90aGVyd2lzZSBldmVyeSBmZWF0dXJlIGVuZHMgdXAgd2l0aCB0d28gUE9Jczogb25lXG4gICAgICAgICAgICAvLyBjb3JyZWN0bHkgbGlua2VkIGJ1dCBzdHJpcHBlZCBvZiBpdHMgdGFnIG1ldGFkYXRhLCBhbmQgb25lIGNhcnJ5aW5nIHRoZSBtZXRhZGF0YVxuICAgICAgICAgICAgLy8gYnV0IHN0aWxsIHBvaW50aW5nIGF0IHRoZSBzb3VyY2Ugc3BhY2UncyBlbGVtZW50LlxuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIC8vIE93bmVyc2hpcCBpcyByZWNvZ25pc2VkIGJ5IFRXTyBpbmRlcGVuZGVudCBjcml0ZXJpYSwgYW5kIGVpdGhlciBvbmUgaXMgZW5vdWdoIHRvXG4gICAgICAgICAgICAvLyBrZWVwIGEgUE9JIG91dCBvZiB0aGUgc3RhbmRhbG9uZSBwaGFzZTpcbiAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAvLyAgLSBpdHMgdHlwZSBpcyBvbmUgYW4gZWxlbWVudCBwaGFzZSBpcyByZXNwb25zaWJsZSBmb3IuIFRoaXMgaXMgdGhlIGhpc3RvcmljYWxcbiAgICAgICAgICAgIC8vICAgIHJ1bGUgYW5kIGl0IG11c3QgYmUga2VwdDogYSBQT0kgb2YgdGhhdCB0eXBlIHdob3NlIGVsZW1lbnQgd2FzIE5PVCBjb2xsZWN0ZWRcbiAgICAgICAgICAgIC8vICAgIChkZWxldGVkIHRpY2tldCwgZXF1aXBtZW50IG91dHNpZGUgdGhlIGN1cnJlbnQgZmlsdGVyLCAuLi4pIGlzIGFuIG9ycGhhbiwgYW5kXG4gICAgICAgICAgICAvLyAgICBjb3B5aW5nIGl0IHN0YW5kYWxvbmUgd291bGQgcmVjcmVhdGUgaXQgd2l0aCBhbiBlbGVtZW50SUQgc3RpbGwgcG9pbnRpbmcgaW50b1xuICAgICAgICAgICAgLy8gICAgdGhlIHNvdXJjZSBzcGFjZSDigJQgYW4gb3JwaGFuIHRoZSBwcmV2aW91cyB2ZXJzaW9uIGNvcnJlY3RseSByZWZ1c2VkIHRvIGNvcHkuXG4gICAgICAgICAgICAvLyAgLSBpdHMgZWxlbWVudElEIGJlbG9uZ3MgdG8gYW4gZWxlbWVudCB3ZSBhY3R1YWxseSBjb2xsZWN0ZWQuIFRoaXMgaXMgdGhlIGFkZGVkXG4gICAgICAgICAgICAvLyAgICBydWxlLCBuZWVkZWQgYmVjYXVzZSB0aGUgdHlwZSBhbG9uZSBpcyBub3QgYSByZWxpYWJsZSBkaXNjcmltaW5hdG9yOiBoaXN0b3JpY2FsXG4gICAgICAgICAgICAvLyAgICBkYXRhIGFsc28gaG9sZHMgSU5GT1JNQVRJT04vUk9PTSBQT0lzIGJvdW5kIHRvIGEgZmVhdHVyZSwgd2hpY2ggdGhlIHR5cGUgdGVzdFxuICAgICAgICAgICAgLy8gICAgbGV0cyB0aHJvdWdoIGFuZCB3aGljaCB3b3VsZCBlbmQgdXAgZHVwbGljYXRlZC5cbiAgICAgICAgICAgIGNvbnN0IGhhbmRsZWRQb2lUeXBlcyA9IG5ldyBTZXQ8c3RyaW5nPihbXG4gICAgICAgICAgICAgICAgUG9pVHlwZS5USUNLRVQsIFBvaVR5cGUuRVFVSVBNRU5ULCBQb2lUeXBlLkRBVEEsIFBvaVR5cGUuREVTSyxcbiAgICAgICAgICAgICAgICBQb2lUeXBlLk9CSkVDVDNELCBQb2lUeXBlLk1FQVNVUkVcbiAgICAgICAgICAgIF0pO1xuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IG93bmVyIG9mIFsuLi5zb3VyY2VUaWNrZXRzLCAuLi5zb3VyY2VFcXVpcG1lbnRzLCAuLi5zb3VyY2VPYmplY3RzM0QsIC4uLnNvdXJjZUZlYXR1cmVzXSkge1xuICAgICAgICAgICAgICAgIGlmIChvd25lcj8uaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVkRWxlbWVudElkcy5hZGQob3duZXIuaWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAoY29uc3QgbWVhc3VyZW1lbnQgb2Ygc291cmNlTWVhc3VyZW1lbnRzKSB7XG4gICAgICAgICAgICAgICAgLy8gYSBtZWFzdXJlbWVudCBQT0kgaXMgYm91bmQgdG8gdGhlIG1lYXN1cmVtZW50J3MgQ29tbWVudCwgbm90IHRvIHRoZSBtZWFzdXJlbWVudFxuICAgICAgICAgICAgICAgIGlmIChtZWFzdXJlbWVudD8uY29tbWVudD8uaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVkRWxlbWVudElkcy5hZGQobWVhc3VyZW1lbnQuY29tbWVudC5pZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBpc093bmVkQnlBbkVsZW1lbnQgPSAocG9pOiBQT0kpID0+XG4gICAgICAgICAgICAgICAgaGFuZGxlZFBvaVR5cGVzLmhhcyhwb2kudHlwZSBhcyBzdHJpbmcpXG4gICAgICAgICAgICAgICAgfHwgKCEhcG9pLmVsZW1lbnRJRCAmJiB0aGlzLmhhbmRsZWRFbGVtZW50SWRzLmhhcyhwb2kuZWxlbWVudElEKSk7XG5cbiAgICAgICAgICAgIGNvbnN0IHNvdXJjZVBvaXMgPSBzb3VyY2VQb2lzQWxsLmZpbHRlcihwID0+ICFpc093bmVkQnlBbkVsZW1lbnQocCkpO1xuICAgICAgICAgICAgY29uc3QgdGFyZ2V0UG9pcyA9IHRhcmdldFBvaXNBbGwuZmlsdGVyKHAgPT4gISFwKTtcblxuICAgICAgICAgICAgdGhpcy5zZXRTdGVwUHJvZ3Jlc3MoJ2NvbGxlY3RpbmcnLCAnY29sbGVjdGluZycsIDEwMCk7XG5cbiAgICAgICAgICAgIGNvbnN0IHRvdGFsT3ZlcmFsbCA9IHNvdXJjZVRpY2tldHMubGVuZ3RoICsgc291cmNlRXF1aXBtZW50cy5sZW5ndGggKyBzb3VyY2VQb2lzLmxlbmd0aFxuICAgICAgICAgICAgICAgICsgc291cmNlT2JqZWN0czNELmxlbmd0aCArIHNvdXJjZUZlYXR1cmVzLmxlbmd0aCArIHNvdXJjZU1lYXN1cmVtZW50cy5sZW5ndGg7XG4gICAgICAgICAgICBsZXQgcHJvY2Vzc2VkT3ZlcmFsbCA9IDA7XG5cbiAgICAgICAgICAgIGNvbnN0IGVtaXRQcm9ncmVzcyA9IChwaGFzZTogQ29weVByb2dyZXNzWydwaGFzZSddLCBwcm9jZXNzZWRJblBoYXNlOiBudW1iZXIsIHRvdGFsSW5QaGFzZTogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb3B5UHJvZ3Jlc3MkLm5leHQoe1xuICAgICAgICAgICAgICAgICAgICBwaGFzZSxcbiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc2VkSW5QaGFzZSxcbiAgICAgICAgICAgICAgICAgICAgdG90YWxJblBoYXNlLFxuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzZWRPdmVyYWxsLFxuICAgICAgICAgICAgICAgICAgICB0b3RhbE92ZXJhbGwsXG4gICAgICAgICAgICAgICAgICAgIHBlcmNlbnQ6IHRvdGFsT3ZlcmFsbCA+IDAgPyBNYXRoLnJvdW5kKChwcm9jZXNzZWRPdmVyYWxsIC8gdG90YWxPdmVyYWxsKSAqIDEwMCkgOiAwLFxuICAgICAgICAgICAgICAgICAgICBlcnJvckNvdW50XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBpZiAodGhpcy5zcE1vZHVsZSA9PSBTcE1vZHVsZS5JTU1PKSB7XG4gICAgICAgICAgICAgICAgLy8gVElDS0VUU1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc291cmNlVGlja2V0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzb3VyY2VPYmogPSBzb3VyY2VUaWNrZXRzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleGlzdHNJblRhcmdldCA9IHRoaXMubWF0Y2hlc0V4aXN0aW5nKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZU9iaiBhcyBhbnksIHRhcmdldFRpY2tldHMgYXMgYW55LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICh0OiBhbnkpID0+IFt0LnRpdGxlLCB0LmRlc2NyaXB0aW9uXVxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFleGlzdHNJblRhcmdldCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJhd1NvdXJjZSA9IHNvdXJjZU9iaiBhcyBhbnk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0aWNrZXRJbnB1dDogYW55ID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZTogcmF3U291cmNlLnRpdGxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcmllbmRseUxhYmVsOiByYXdTb3VyY2UuZnJpZW5kbHlMYWJlbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdHVzOiByYXdTb3VyY2Uuc3RhdHVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiByYXdTb3VyY2UudHlwZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3JpdHk6IHJhd1NvdXJjZS5wcmlvcml0eSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb246IHJhd1NvdXJjZS5kZXNjcmlwdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw6IHJhd1NvdXJjZS5sZXZlbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGE6IHJhd1NvdXJjZS5tZXRhZGF0YSB8fCBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkOiByYXdTb3VyY2UucmVhZCB8fCBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9qZWN0SUQ6IHJhd1NvdXJjZS5wcm9qZWN0SUQgfHwgbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYmxlbUNvZGU6IHJhd1NvdXJjZS5wcm9ibGVtQ29kZSB8fCBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNaXNzaW9ucyBhcmUgcGVyLXNwYWNlOiBhIHNvdXJjZSBtaXNzaW9uIGlkIGRlc2lnbmF0ZXMgbm9ib2R5IGluXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSB0YXJnZXQgc3BhY2UuIENhcnJ5aW5nIHRoZSBsaXN0IG92ZXIgd291bGQgbG9vayBsaWtlIHJlYWwgZGF0YVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB3aGlsZSBoaWRpbmcgdGhlIGl0ZW0gZnJvbSBubyBvbmUg4oCUIHJlc2V0IGl0LCBhcyBmb3IgZmVhdHVyZXMuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyY2hpdmVkRm9yTWlzc2lvbklEOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGFjZUlEOiB0YXJnZXRTcGFjZUlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1hcHBlZCBpbiB0aGUgc2Vjb25kIHBhc3MgYmVsb3csIG9uY2UgZXZlcnkgdGlja2V0IGV4aXN0cy5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50SUQ6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIERvbWFpbnMgYXJlIG9yZ2FuaXNhdGlvbi1zY29wZWQsIGxpa2UgZm9yIGVxdWlwbWVudHMgYW5kIGZlYXR1cmVzLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb21haW5JRDogdGhpcy5zYW1lT3JnYW5pc2F0aW9uID8gKHJhd1NvdXJjZS5kb21haW5JRCB8fCBudWxsKSA6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG93bmVyTWlzc2lvbklEOiB0YXJnZXRNaXNzaW9uSWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3JlYXRlZE9iaiA9IGF3YWl0IHRoaXMudGlja2V0U2VydmljZS5jcmVhdGVUaWNrZXQodGlja2V0SW5wdXQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNyZWF0ZWRPYmogJiYgY3JlYXRlZE9iai5pZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50SWRzW3NvdXJjZU9iai5pZF0gPSBjcmVhdGVkT2JqLmlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEF0dGFjaG1lbnRzIG9mIHRoZSB0aWNrZXQgKHBob3RvcyBvZiB0aGUgaW5jaWRlbnQsIGRvY3VtZW50cy4uLikuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhleSB3ZXJlIG5ldmVyIGNvcGllZCBhdCBhbGw6IGEgZHVwbGljYXRlZCB0aWNrZXQgYXJyaXZlZCBzdHJpcHBlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9mIGV2ZXJ5IHBpZWNlIG9mIGV2aWRlbmNlIGF0dGFjaGVkIHRvIGl0LlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjcmVhdGVkT2JqKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzb3VyY2VDb21tZW50czogQ29tbWVudFtdID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VDb21tZW50cyA9IGF3YWl0IHRoaXMuY29tbWVudFNlcnZpY2UuZ2V0QWxsQ29tbWVudHNGb3JUaWNrZXQoc291cmNlT2JqLmlkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoY29tbWVudHNGZXRjaEVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYEZhbGxpbmcgYmFjayB0byB0aGUgZW1iZWRkZWQgY29tbWVudCBsaXN0IGZvciB0aWNrZXQgXCIke3Jhd1NvdXJjZS50aXRsZX1cIjpgLCBjb21tZW50c0ZldGNoRXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlQ29tbWVudHMgPSAoc291cmNlT2JqLmNvbW1lbnRzPy5pdGVtcyB8fCBbXSkuZmlsdGVyKGMgPT4gISFjKSBhcyBDb21tZW50W107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHNvdXJjZUNvbW1lbnQgb2YgdGhpcy5vcmRlckNvbW1lbnRzRm9yQ29weShzb3VyY2VDb21tZW50cykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3JlYXRlZCA9IGF3YWl0IHRoaXMuY29weUNvbW1lbnRGb3JUaWNrZXQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZUNvbW1lbnQsIGNyZWF0ZWRPYmouaWQsIHRhcmdldFNwYWNlSWQsIHRhcmdldE1pc3Npb25JZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNyZWF0ZWQ/LmlkICYmIChzb3VyY2VDb21tZW50IGFzIGFueSkuaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21tZW50SWRzLnNldCgoc291cmNlQ29tbWVudCBhcyBhbnkpLmlkLCBjcmVhdGVkLmlkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChhdHRhY2htZW50RXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBjb3B5aW5nIGF0dGFjaG1lbnQgXCIke3NvdXJjZUNvbW1lbnQ/LnRpdGxlfVwiIGZvciB0aWNrZXQgXCIke3NvdXJjZU9iaj8udGl0bGV9XCI6YCwgYXR0YWNobWVudEVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNvdW50Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2dDb3B5SXRlbUVycm9yKGF0dGFjaG1lbnRFcnJvciwgJ2Vycm9yRmVhdHVyZUF0dGFjaG1lbnQnLCBzb3VyY2VDb21tZW50Py50aXRsZSB8fCAoc291cmNlQ29tbWVudCBhcyBhbnkpPy5pZCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlOiByYXdTb3VyY2UudGl0bGUgfHwgc291cmNlT2JqLmlkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHNvdXJjZVBvaSBvZiAoc291cmNlT2JqLnBvaXM/Lml0ZW1zIHx8IFtdKS5maWx0ZXIocCA9PiAhIXApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuY3JlYXRlQ29waWVkUG9pKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlUG9pLCBjcmVhdGVkT2JqLmlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlTmF2UG9zaXRpb25zLCB0YXJnZXROYXZQb3NpdGlvbnMsIHRyYW5zZm9ybVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoaXRlbUVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBjb3B5aW5nIHRpY2tldCBcIiR7c291cmNlT2JqPy50aXRsZX1cIiAoaWQ6ICR7c291cmNlT2JqPy5pZH0pOmAsIGl0ZW1FcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNvdW50Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZ0NvcHlJdGVtRXJyb3IoaXRlbUVycm9yLCAnZXJyb3JUaWNrZXQnLCBzb3VyY2VPYmo/LnRpdGxlIHx8IHNvdXJjZU9iaj8uaWQpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc2VkT3ZlcmFsbCsrO1xuICAgICAgICAgICAgICAgICAgICBlbWl0UHJvZ3Jlc3MoJ3RpY2tldHMnLCBpICsgMSwgc291cmNlVGlja2V0cy5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwY3QgPSBzb3VyY2VUaWNrZXRzLmxlbmd0aCA+IDAgPyBNYXRoLnJvdW5kKCgoaSArIDEpIC8gc291cmNlVGlja2V0cy5sZW5ndGgpICogMTAwKSA6IDEwMDtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRTdGVwUHJvZ3Jlc3MoJ3RpY2tldHMnLCAndGlja2V0cycsIHBjdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gU2Vjb25kIHBhc3M6IHJlc3RvcmUgdGhlIHRpY2tldCBoaWVyYXJjaHkuIGBwYXJlbnRJRGAgaGFkIHRvIGJlIG51bGxlZCBkdXJpbmdcbiAgICAgICAgICAgICAgICAvLyBjcmVhdGlvbiAodGhlIHBhcmVudCBtYXkgbm90IGhhdmUgZXhpc3RlZCB5ZXQpIGFuZCB3YXMgdGhlbiBuZXZlciByZXN0b3JlZCwgc29cbiAgICAgICAgICAgICAgICAvLyBldmVyeSBzdWItdGlja2V0IGNhbWUgb3V0IGRldGFjaGVkLiBTYW1lIHJ1bGUgYXMgZm9yIHN1Yi1lcXVpcG1lbnRzOiBhIHBhcmVudFxuICAgICAgICAgICAgICAgIC8vIHdpdGggbm8gY29waWVkIGNvdW50ZXJwYXJ0IGlzIGRyb3BwZWQgcmF0aGVyIHRoYW4gbGVmdCBwb2ludGluZyBhdCB0aGUgc291cmNlXG4gICAgICAgICAgICAgICAgLy8gc3BhY2UncyB0aWNrZXQuXG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBzb3VyY2VPYmogb2Ygc291cmNlVGlja2V0cykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByYXdTb3VyY2UgPSBzb3VyY2VPYmogYXMgYW55O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdJZCA9IGVsZW1lbnRJZHNbc291cmNlT2JqLmlkXTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV3UGFyZW50SWQgPSByYXdTb3VyY2UucGFyZW50SUQgPyBlbGVtZW50SWRzW3Jhd1NvdXJjZS5wYXJlbnRJRF0gOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdJZCAmJiBuZXdQYXJlbnRJZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnRpY2tldFNlcnZpY2UudXBkYXRlVGlja2V0KHsgaWQ6IG5ld0lkLCBwYXJlbnRJRDogbmV3UGFyZW50SWQgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChwYXJlbnRFcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIHJlbWFwcGluZyB0aGUgcGFyZW50IHRpY2tldCBvZiBcIiR7c291cmNlT2JqPy50aXRsZX1cIjpgLCBwYXJlbnRFcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDb3VudCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9nQ29weUl0ZW1FcnJvcihwYXJlbnRFcnJvciwgJ2Vycm9yVGlja2V0Jywgc291cmNlT2JqPy50aXRsZSB8fCBzb3VyY2VPYmo/LmlkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIEVRVUlQTUVOVFMgKGlkZW50aXR5LCBQT0ksIFBIT1RPIGFuZCBOT1RFUy9kb2N1bWVudHMgYWxsIGNvcGllZCDigJQgZmlsZXNcbiAgICAgICAgICAgICAgICAvLyBwaHlzaWNhbGx5IGR1cGxpY2F0ZWQgaW4gUzMgZmlyc3QsIHNvIHRoZSBjb3B5IHN0YXlzIGluZGVwZW5kZW50IGZyb20gdGhlIHNvdXJjZSlcbiAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgIC8vIENBUkVGVUw6IHRoZSBFcXVpcG1lbnQgbW9kZWwgaGFzIE5PIGB0aXRsZWAgYW5kIE5PIGBkZXNjcmlwdGlvbmAgY29sdW1uLiBJdFxuICAgICAgICAgICAgICAgIC8vIGlkZW50aWZpZXMgaXRzZWxmIHdpdGggYG5hbWVgIChTdHJpbmchIOKAlCByZXF1aXJlZCkgYW5kIGFubm90YXRlcyBpdHNlbGYgd2l0aFxuICAgICAgICAgICAgICAgIC8vIGBhbm5vdGF0aW9uYC4gUmVhZGluZyBgcmF3U291cmNlLnRpdGxlYCB0aGVyZWZvcmUgYWx3YXlzIHlpZWxkZWQgdW5kZWZpbmVkIGFuZFxuICAgICAgICAgICAgICAgIC8vIHRoZSByZXF1aXJlZCBgbmFtZWAgd2FzIG5ldmVyIHNlbnQsIHdoaWNoIEFwcFN5bmMgcmVqZWN0ZWQgd2l0aFxuICAgICAgICAgICAgICAgIC8vIFwiVmFyaWFibGUgJ2lucHV0JyBoYXMgY29lcmNlZCBOdWxsIHZhbHVlIGZvciBOb25OdWxsIHR5cGUgJ1N0cmluZyEnXCIuXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzb3VyY2VFcXVpcG1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNvdXJjZU9iaiA9IHNvdXJjZUVxdWlwbWVudHNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEVxdWlwbWVudCBoYXMgbm8gYHRpdGxlYC9gZGVzY3JpcHRpb25gOiBpdCBpZGVudGlmaWVzIGl0c2VsZiBieSBuYW1lLCBhbmQgYnlcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNlcmlhbCBudW1iZXIgd2hlbiBvbmUgaXMgcmVjb3JkZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleGlzdHNJblRhcmdldCA9IHRoaXMubWF0Y2hlc0V4aXN0aW5nKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZU9iaiBhcyBhbnksIHRhcmdldEVxdWlwbWVudHMgYXMgYW55LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChlOiBhbnkpID0+IFtlLm5hbWUsIGUuc2VyaWFsTnVtYmVyXVxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFleGlzdHNJblRhcmdldCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJhd1NvdXJjZSA9IHNvdXJjZU9iaiBhcyBhbnk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgY29waWVkUGhvdG9LZXk6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyYXdTb3VyY2UucGhvdG8pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29waWVkUGhvdG9LZXkgPSBhd2FpdCB0aGlzLmNvcHlTM0tleUlmUHJlc2VudChyYXdTb3VyY2UucGhvdG8sIGBlcXVpcG1lbnQgcGhvdG8gXCIke3Jhd1NvdXJjZS5uYW1lfVwiYCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXF1aXBtZW50SW5wdXQ6IGFueSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogcmF3U291cmNlLm5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFubm90YXRpb246IHJhd1NvdXJjZS5hbm5vdGF0aW9uID8/IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXR1czogcmF3U291cmNlLnN0YXR1cyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRnVsbCBpZGVudGl0eSBvZiB0aGUgZXF1aXBtZW50IOKAlCBhbGwgb2YgdGhlc2Ugd2VyZSBkcm9wcGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbWlseTogcmF3U291cmNlLmZhbWlseSA/PyBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBza3U6IHJhd1NvdXJjZS5za3UgPz8gbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VyaWFsTnVtYmVyOiByYXdTb3VyY2Uuc2VyaWFsTnVtYmVyID8/IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hbnVmYWN0dXJlcjogcmF3U291cmNlLm1hbnVmYWN0dXJlciA/PyBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnN0YWxsRGF0ZTogcmF3U291cmNlLmluc3RhbGxEYXRlID8/IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcnJhbnR5RW5kRGF0ZTogcmF3U291cmNlLndhcnJhbnR5RW5kRGF0ZSA/PyBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogcmF3U291cmNlLm1ldGFkYXRhID8/IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzQ3JlYXRlZEJ5QUk6IHJhd1NvdXJjZS5pc0NyZWF0ZWRCeUFJID8/IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1pc3Npb25zIGFyZSBwZXItc3BhY2U6IGEgc291cmNlIG1pc3Npb24gaWQgZGVzaWduYXRlcyBub2JvZHkgaW5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHRhcmdldCBzcGFjZS4gQ2FycnlpbmcgdGhlIGxpc3Qgb3ZlciB3b3VsZCBsb29rIGxpa2UgcmVhbCBkYXRhXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdoaWxlIGhpZGluZyB0aGUgaXRlbSBmcm9tIG5vIG9uZSDigJQgcmVzZXQgaXQsIGFzIGZvciBmZWF0dXJlcy5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJjaGl2ZWRGb3JNaXNzaW9uSUQ6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwYWNlSUQ6IHRhcmdldFNwYWNlSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIERvbWFpbnMgYXJlIG9yZ2FuaXNhdGlvbi1zY29wZWQsIGxpa2UgZm9yIGZlYXR1cmVzIGFuZCBQT0lzLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb21haW5JRDogdGhpcy5zYW1lT3JnYW5pc2F0aW9uID8gKHJhd1NvdXJjZS5kb21haW5JRCB8fCBudWxsKSA6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBob3RvOiBjb3BpZWRQaG90b0tleSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYHN1YmVxdWlwbWVudHNJRHNgIGlzIGRlbGliZXJhdGVseSBhYnNlbnQ6IGl0IGlzIHJlbWFwcGVkIHRvIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjb3BpZWQgZXF1aXBtZW50cyBpbiB0aGUgc2Vjb25kIHBhc3MsIG9uY2UgdGhleSBhbGwgZXhpc3QuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNyZWF0ZWRPYmo6IGFueSA9IGF3YWl0IHRoaXMuZXF1aXBtZW50U2VydmljZS5jcmVhdGVFcXVpcG1lbnQoZXF1aXBtZW50SW5wdXQsIG51bGwsIG51bGwpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNyZWF0ZWRPYmogJiYgY3JlYXRlZE9iai5pZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50SWRzW3NvdXJjZU9iai5pZF0gPSBjcmVhdGVkT2JqLmlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIENvcHkgbm90ZXMgKGRvY3VtZW50cywgdGVjaG5pY2FsL2ZpbmFuY2lhbC9vdGhlci9jb250cmFjdHVhbC9pbWFnZSBub3RlcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3JlYXRlZE9iaiAmJiByYXdTb3VyY2Uubm90ZXM/Lml0ZW1zICYmIHJhd1NvdXJjZS5ub3Rlcy5pdGVtcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgc291cmNlTm90ZSBvZiByYXdTb3VyY2Uubm90ZXMuaXRlbXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQSBub3RlIHdpdGhvdXQgYSBmaWxlIGlzIHN0aWxsIGEgbm90ZTogaXQgY2FycmllcyBhIHR5cGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhbmQgaXRzIHNpZ25hdHVyZS9leHBpcnkgZGF0ZXMuIFNraXBwaW5nIGl0LCBhcyB3YXMgZG9uZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGJlZm9yZSwgc2lsZW50bHkgZHJvcHBlZCB0aG9zZSByZWNvcmRzIGVudGlyZWx5LlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvcGllZEtleSA9IHNvdXJjZU5vdGUuYXR0YWNobWVudFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IGF3YWl0IHRoaXMuY29weVMzS2V5SWZQcmVzZW50KHNvdXJjZU5vdGUuYXR0YWNobWVudCwgYGVxdWlwbWVudCBub3RlIGZvciBcIiR7c291cmNlT2JqPy5uYW1lfVwiYClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuZXF1aXBtZW50U2VydmljZS5jcmVhdGVOb3RlV2l0aEV4aXN0aW5nQXR0YWNobWVudChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3JlYXRlZE9iai5pZCwgY29waWVkS2V5LCBzb3VyY2VOb3RlLnR5cGUsIHRhcmdldE1pc3Npb25JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2lnbkRhdGU6IHNvdXJjZU5vdGUuc2lnbkRhdGUgPz8gbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cGlyYXRpb25EYXRlOiBzb3VyY2VOb3RlLmV4cGlyYXRpb25EYXRlID8/IG51bGxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChub3RlRXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBjb3B5aW5nIG5vdGUgZm9yIGVxdWlwbWVudCBcIiR7c291cmNlT2JqPy5uYW1lfVwiOmAsIG5vdGVFcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDb3VudCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9nQ29weUl0ZW1FcnJvcihub3RlRXJyb3IsICdlcnJvckVxdWlwbWVudE5vdGUnLCBzb3VyY2VPYmo/Lm5hbWUgfHwgc291cmNlT2JqPy5pZCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcXVpcG1lbnQ6IHNvdXJjZU9iaj8ubmFtZSB8fCBzb3VyY2VPYmo/LmlkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHNvdXJjZVBvaSBvZiAoc291cmNlT2JqLnBvaXM/Lml0ZW1zIHx8IFtdKS5maWx0ZXIocCA9PiAhIXApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuY3JlYXRlQ29waWVkUG9pKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlUG9pLCBjcmVhdGVkT2JqLmlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlTmF2UG9zaXRpb25zLCB0YXJnZXROYXZQb3NpdGlvbnMsIHRyYW5zZm9ybVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoaXRlbUVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBjb3B5aW5nIGVxdWlwbWVudCBcIiR7c291cmNlT2JqPy5uYW1lfVwiIChpZDogJHtzb3VyY2VPYmo/LmlkfSk6YCwgaXRlbUVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ291bnQrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9nQ29weUl0ZW1FcnJvcihpdGVtRXJyb3IsICdlcnJvckVxdWlwbWVudCcsIHNvdXJjZU9iaj8ubmFtZSB8fCBzb3VyY2VPYmo/LmlkKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3NlZE92ZXJhbGwrKztcbiAgICAgICAgICAgICAgICAgICAgZW1pdFByb2dyZXNzKCdlcXVpcG1lbnRzJywgaSArIDEsIHNvdXJjZUVxdWlwbWVudHMubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGN0ID0gc291cmNlRXF1aXBtZW50cy5sZW5ndGggPiAwID8gTWF0aC5yb3VuZCgoKGkgKyAxKSAvIHNvdXJjZUVxdWlwbWVudHMubGVuZ3RoKSAqIDEwMCkgOiAxMDA7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RlcFByb2dyZXNzKCdlcXVpcG1lbnRzJywgJ2VxdWlwbWVudHMnLCBwY3QpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIFNlY29uZCBwYXNzOiByZW1hcCBzdWJlcXVpcG1lbnRzSURzIG9uIG5ld2x5IGNyZWF0ZWQgZXF1aXBtZW50cyB0byBwb2ludCB0b1xuICAgICAgICAgICAgICAgIC8vIHRoZWlyIGNvcGllZCBjb3VudGVycGFydHMuIElEcyB3aXRoIG5vIGNvcGllZCBjb3VudGVycGFydCAoc291cmNlIGVxdWlwbWVudFxuICAgICAgICAgICAgICAgIC8vIHdhc24ndCBjb3BpZWQg4oCUIGUuZy4gaXQgYWxyZWFkeSBleGlzdGVkIGluIHRhcmdldCwgb3Igd2FzIHNraXBwZWQpIGFyZSBkcm9wcGVkXG4gICAgICAgICAgICAgICAgLy8gcmF0aGVyIHRoYW4gbGVmdCBkYW5nbGluZyBvciBwb2ludGluZyBiYWNrIGF0IHRoZSBzb3VyY2Ugc3BhY2UncyBlcXVpcG1lbnQuXG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBzb3VyY2VPYmogb2Ygc291cmNlRXF1aXBtZW50cykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByYXdTb3VyY2UgPSBzb3VyY2VPYmogYXMgYW55O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdJZCA9IGVsZW1lbnRJZHNbc291cmNlT2JqLmlkXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0lkICYmIHJhd1NvdXJjZS5zdWJlcXVpcG1lbnRzSURzICYmIHJhd1NvdXJjZS5zdWJlcXVpcG1lbnRzSURzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlbWFwcGVkID0gcmF3U291cmNlLnN1YmVxdWlwbWVudHNJRHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAubWFwKChzdWJJZDogc3RyaW5nKSA9PiBlbGVtZW50SWRzW3N1YklkXSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKChpZDogc3RyaW5nIHwgdW5kZWZpbmVkKSA9PiAhIWlkKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlbWFwcGVkLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmVxdWlwbWVudFNlcnZpY2UudXBkYXRlRXF1aXBtZW50KHsgaWQ6IG5ld0lkLCBzdWJlcXVpcG1lbnRzSURzOiByZW1hcHBlZCB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChzdWJFcXVpcEVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIHJlbWFwcGluZyBzdWItZXF1aXBtZW50cyBmb3IgXCIke3NvdXJjZU9iaj8ubmFtZX1cIjpgLCBzdWJFcXVpcEVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDb3VudCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZ0NvcHlJdGVtRXJyb3Ioc3ViRXF1aXBFcnJvciwgJ2Vycm9yRXF1aXBtZW50U3ViRXF1aXAnLCBzb3VyY2VPYmo/Lm5hbWUgfHwgc291cmNlT2JqPy5pZCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXF1aXBtZW50OiBzb3VyY2VPYmo/Lm5hbWUgfHwgc291cmNlT2JqPy5pZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIE9CSkVDVFMgM0QgKHRoZSAzRCBtb2RlbCBmaWxlIGl0c2VsZiDigJQgYHBhdGhgIOKAlCBpcyBwaHlzaWNhbGx5IGR1cGxpY2F0ZWQgaW4gUzMpXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNvdXJjZU9iamVjdHMzRC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHNvdXJjZU9iaiA9IHNvdXJjZU9iamVjdHMzRFtpXTtcblxuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4aXN0c0luVGFyZ2V0ID0gdGFyZ2V0T2JqZWN0czNELnNvbWUodGFyZ2V0T2JqID0+IHRhcmdldE9iai5uYW1lID09PSBzb3VyY2VPYmoubmFtZSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFleGlzdHNJblRhcmdldCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmF3U291cmNlID0gc291cmNlT2JqIGFzIGFueTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYHBhdGhgIG1lYW5zIHR3byBkaWZmZXJlbnQgdGhpbmdzIGRlcGVuZGluZyBvbiBgczNCdWNrZXRgLCBleGFjdGx5IGFzIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdmlld2VyIHJlYWRzIGl0IChzZWUgdmlld2VyLmNvbXBvbmVudC50cyBhbmQgbWF0dGVycG9ydC1vYmplY3QzZC5zZXJ2aWNlLnRzKTpcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAtIHMzQnVja2V0ID09PSB0cnVlICAtPiBhIGtleSBvZiBhIG1vZGVsIGZpbGUgdXBsb2FkZWQgdG8gUzMsIG91cnMgdG8gZHVwbGljYXRlO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gIC0gb3RoZXJ3aXNlICAgICAgICAgIC0+IGEgcmVmZXJlbmNlIGludG8gdGhlIDNEIG9iamVjdCBsaWJyYXJ5IHNoaXBwZWQgd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgdGhlIGFwcGxpY2F0aW9uIChcIjNET2JqZWN0cy9vYmplY3RzL2N1YmUuZGFlXCIgLT4gYXNzZXRzLzNEb2JqZWN0cy8uLi4pLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgd2hpY2ggZXhpc3RzIGluIGV2ZXJ5IHNwYWNlIGFuZCBtdXN0IGJlIHJldXNlZCB2ZXJiYXRpbS5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIENvcHlpbmcgdW5jb25kaXRpb25hbGx5IG1lYW50IGV2ZXJ5IGxpYnJhcnkgb2JqZWN0IGZhaWxlZCB3aXRoIE5vU3VjaEtleSBhbmRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSB3aG9sZSAzRCBvYmplY3Qgd2FzIHNraXBwZWQsIG1vZGVsIEFORCBQT0kuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgY29waWVkUGF0aCA9IHJhd1NvdXJjZS5wYXRoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJhd1NvdXJjZS5wYXRoICYmIHJhd1NvdXJjZS5zM0J1Y2tldCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcGllZFBhdGggPSBhd2FpdCB0aGlzLmNvcHlTM0tleUlmUHJlc2VudChyYXdTb3VyY2UucGF0aCwgYDNEIG9iamVjdCBcIiR7cmF3U291cmNlLm5hbWV9XCJgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICAgICAgICAgKiBTdHJpY3QgcGFyc2VyIHRvIGVuc3VyZSBbZmxvYXQsIGZsb2F0LCBmbG9hdF0gZm9ybWF0IGZvciBHcmFwaFFMLlxuICAgICAgICAgICAgICAgICAgICAgICAgICogRm9yY2VzIG51bWJlcnMsIGhhbmRsZXMgcG90ZW50aWFsIER5bmFtb0RCIG9iamVjdCBzdHJ1Y3R1cmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICogYW5kIGVuc3VyZXMgd2UgbmV2ZXIgc2VuZCBbMCwwLDBdIGZvciBzY2FsZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdG9GbG9hdEFycmF5ID0gKHZhbDogYW55LCBkZWZhdWx0VmFsOiBudW1iZXJbXSA9IFswLCAwLCAwXSk6IG51bWJlcltdID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgYXJyYXk6IG51bWJlcltdID0gW107XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWwpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIERCIGZvcm1hdCBbIHtOOiBcIjFcIn0sIC4uLiBdXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWwubGVuZ3RoID4gMCAmJiB0eXBlb2YgdmFsWzBdID09PSAnb2JqZWN0JyAmJiAnTicgaW4gdmFsWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcnJheSA9IHZhbC5tYXAoaXRlbSA9PiBwYXJzZUZsb2F0KGl0ZW0uTikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIGFscmVhZHkgc3RhbmRhcmQgYXJyYXkgWzEsIDEsIDFdXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJyYXkgPSB2YWwubWFwKGl0ZW0gPT4gcGFyc2VGbG9hdChpdGVtKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgb2JqZWN0IHt4LCB5LCB6fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHZhbCAmJiB0eXBlb2YgdmFsID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcnJheSA9IFtwYXJzZUZsb2F0KHZhbC54KSwgcGFyc2VGbG9hdCh2YWwueSksIHBhcnNlRmxvYXQodmFsLnopXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGVmYXVsdFZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBFbnN1cmUgd2UgcmV0dXJuIHZhbGlkIG51bWJlcnNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXJyYXkubWFwKG4gPT4gaXNOYU4obikgPyAwIDogbik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHNlcnZpY2UgaXMgc2hhcmVkLCBidXQgdGhlIHR3byBhcHBsaWNhdGlvbnMgZG8gTk9UIGRlcGxveSB0aGUgc2FtZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gT2JqZWN0M0Qgc2NoZW1hOiBgdmlld0ZydXN0dW1gIGV4aXN0cyBvbmx5IGluIHNtYXJ0ZXJwbGFuLCBhbmQgYHNjYWxlYFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXMgW0Zsb2F0XSB0aGVyZSBidXQgYSBwbGFpbiBGbG9hdCBpbiBtdXNldW0uIFNlbmRpbmcgdGhlIHNtYXJ0ZXJwbGFuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzaGFwZSB0byBtdXNldW0gd2FzIHJlamVjdGVkIHdpdGggXCJUaGUgdmFyaWFibGVzIGlucHV0IGNvbnRhaW5zIGEgZmllbGRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoYXQgaXMgbm90IGRlZmluZWQgZm9yIGlucHV0IG9iamVjdCB0eXBlICdDcmVhdGVPYmplY3QzRElucHV0J1wiLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZSBpbnB1dCB0aGVyZWZvcmUgTUlSUk9SUyB0aGUgc291cmNlIHJlY29yZCBpbnN0ZWFkIG9mIGltcG9zaW5nIGFcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNoYXBlOiBzb3VyY2UgYW5kIHRhcmdldCBsaXZlIGluIHRoZSBzYW1lIGRlcGxveW1lbnQsIHNvIHdoYXRldmVyIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc291cmNlIGNhcnJpZXMgaXMgZXhhY3RseSB3aGF0IHRoZSB0YXJnZXQgYWNjZXB0cy5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9iamVjdDNESW5wdXQ6IGFueSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRoOiBjb3BpZWRQYXRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRlbGxzIHRoZSB2aWV3ZXIgaG93IHRvIGludGVycHJldCBgcGF0aGAuIERyb3BwaW5nIGl0IHR1cm5lZCBhblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFMzLWhvc3RlZCBtb2RlbCBpbnRvIGEgbGlicmFyeSByZWZlcmVuY2Ugb24gdGhlIGNvcHksIHdoaWNoIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHZpZXdlciB0aGVuIHRyaWVkIHRvIHJlc29sdmUgYWdhaW5zdCBhc3NldHMvIGFuZCBmYWlsZWQgdG8gbG9hZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzM0J1Y2tldDogISFyYXdTb3VyY2UuczNCdWNrZXQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogcmF3U291cmNlLm5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb246IHJhd1NvdXJjZS5kZXNjcmlwdGlvbiB8fCBcIlwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwYWNlSUQ6IHRhcmdldFNwYWNlSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246IHRvRmxvYXRBcnJheShyYXdTb3VyY2UucG9zaXRpb24sIFswLCAwLCAwXSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRpb246IHRvRmxvYXRBcnJheShyYXdTb3VyY2Uucm90YXRpb24sIFswLCAwLCAwXSlcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgndmlld0ZydXN0dW0nIGluIHJhd1NvdXJjZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdDNESW5wdXQudmlld0ZydXN0dW0gPSAhIXJhd1NvdXJjZS52aWV3RnJ1c3R1bTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2NhbGUga2VlcHMgdGhlIHNvdXJjZSdzIG93biBzaGFwZTogYSBsaXN0IHN0YXlzIGEgbGlzdCwgYSBzY2FsYXIgc3RheXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGEgc2NhbGFyLiBBbiBhYnNlbnQgc2NhbGUgaXMgbGVmdCB1bnNldCByYXRoZXIgdGhhbiBpbnZlbnRlZCwgc28gdGhlIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJlbmRlcnMgZXhhY3RseSBsaWtlIHRoZSBvcmlnaW5hbC5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHJhd1NvdXJjZS5zY2FsZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYmplY3QzRElucHV0LnNjYWxlID0gdG9GbG9hdEFycmF5KHJhd1NvdXJjZS5zY2FsZSwgWzEsIDEsIDFdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocmF3U291cmNlLnNjYWxlICE9PSBudWxsICYmIHJhd1NvdXJjZS5zY2FsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2NhbGFyU2NhbGUgPSBwYXJzZUZsb2F0KHJhd1NvdXJjZS5zY2FsZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0M0RJbnB1dC5zY2FsZSA9IE51bWJlci5pc05hTihzY2FsYXJTY2FsZSkgPyAxIDogc2NhbGFyU2NhbGU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNyZWF0ZWRPYmogPSBhd2FpdCB0aGlzLm9iamVjdDNEU2VydmljZS5jcmVhdGUob2JqZWN0M0RJbnB1dCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjcmVhdGVkT2JqICYmIGNyZWF0ZWRPYmouaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50SWRzW3NvdXJjZU9iai5pZF0gPSBjcmVhdGVkT2JqLmlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHNvdXJjZVBvaSBvZiAoc291cmNlT2JqLnBvaXM/Lml0ZW1zIHx8IFtdKS5maWx0ZXIocCA9PiAhIXApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5jcmVhdGVDb3BpZWRQb2koXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZVBvaSwgY3JlYXRlZE9iai5pZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlTmF2UG9zaXRpb25zLCB0YXJnZXROYXZQb3NpdGlvbnMsIHRyYW5zZm9ybVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChpdGVtRXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhlIGJhY2tlbmQgY2FuIGRlbnkgY3JlYXRpb24gb2YgdGhpcyB3aG9sZSBtb2RlbCB0byB0aGUgc2lnbmVkLWluIGFjY291bnRcbiAgICAgICAgICAgICAgICAgICAgLy8gKGluIE1VU0VVTSwgT2JqZWN0M0Qgb25seSBncmFudHMgZ2V0L2xpc3QgdG8gdXNlclBvb2xzKS4gVGhlIGRlbmlhbCBpcyBub3RcbiAgICAgICAgICAgICAgICAgICAgLy8gcGVyLWl0ZW0sIHNvIGV2ZXJ5IHJlbWFpbmluZyBvYmplY3Qgd291bGQgZmFpbCBpZGVudGljYWxseTogcmVwb3J0IGl0IG9uY2UsXG4gICAgICAgICAgICAgICAgICAgIC8vIGFzIGEgcGVybWlzc2lvbiBwcm9ibGVtIHJhdGhlciB0aGFuIGEgY29weSBlcnJvciwgYW5kIHN0b3AgdGhlIHBoYXNlIGluc3RlYWRcbiAgICAgICAgICAgICAgICAgICAgLy8gb2YgZmlyaW5nIG9uZSBkb29tZWQgbXV0YXRpb24gcGVyIG9iamVjdC5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNVbmF1dGhvcml6ZWQoaXRlbUVycm9yKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVtYWluaW5nID0gc291cmNlT2JqZWN0czNELmxlbmd0aCAtIGk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYFtNYXR0ZXJwb3J0VGFnQ29weVNlcnZpY2VdIE5vdCBhbGxvd2VkIHRvIGNyZWF0ZSAzRCBvYmplY3RzIGluIHRoZSB0YXJnZXQgc3BhY2UsIHNraXBwaW5nICR7cmVtYWluaW5nfSBvZiB0aGVtLmAsIGl0ZW1FcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNvdW50Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZ0l0ZW1FcnJvcignZXJyb3JPYmplY3RzM2ROb3RBbGxvd2VkJywgeyBjb3VudDogcmVtYWluaW5nIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzZWRPdmVyYWxsICs9IHJlbWFpbmluZztcbiAgICAgICAgICAgICAgICAgICAgICAgIGVtaXRQcm9ncmVzcygnb2JqZWN0czNkJywgc291cmNlT2JqZWN0czNELmxlbmd0aCwgc291cmNlT2JqZWN0czNELmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFN0ZXBQcm9ncmVzcygnb2JqZWN0czNkJywgJ29iamVjdHMzZCcsIDEwMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIGNvcHlpbmcgb2JqZWN0M0QgXCIke3NvdXJjZU9iaj8ubmFtZX1cIjpgLCBpdGVtRXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICBlcnJvckNvdW50Kys7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubG9nQ29weUl0ZW1FcnJvcihpdGVtRXJyb3IsICdlcnJvck9iamVjdDNkJywgc291cmNlT2JqPy5uYW1lIHx8IHNvdXJjZU9iaj8uaWQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHByb2Nlc3NlZE92ZXJhbGwrKztcbiAgICAgICAgICAgICAgICBlbWl0UHJvZ3Jlc3MoJ29iamVjdHMzZCcsIGkgKyAxLCBzb3VyY2VPYmplY3RzM0QubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICBjb25zdCBwY3QgPSBzb3VyY2VPYmplY3RzM0QubGVuZ3RoID4gMCA/IE1hdGgucm91bmQoKChpICsgMSkgLyBzb3VyY2VPYmplY3RzM0QubGVuZ3RoKSAqIDEwMCkgOiAxMDA7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTdGVwUHJvZ3Jlc3MoJ29iamVjdHMzZCcsICdvYmplY3RzM2QnLCBwY3QpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBGRUFUVVJFUyDigJQgdGhlIFwiUE9JXCIgb2YgdGhlIE1VU0VVTSBtb2R1bGU6IGl0cyBvd24gcmVjb3JkICh0aXRsZSwgaW5kZXgsIGxvY2FsZSxcbiAgICAgICAgICAgIC8vIGtleXdvcmRzKSwgaXRzIG1lZGlhIHNldCAob25lIENvbW1lbnQgcGVyIGltYWdlL3ZpZGVvL2F1ZGlvL2RvY3VtZW50L2xpbmsvdGV4dClcbiAgICAgICAgICAgIC8vIGFuZCBpdHMgUE9JIHJlY29yZCAodGhlIHBhc3RpbGxlOiBpY29uLCB0YWcgZGVzY3JpcHRpb24sIGNvdmVyIGltYWdlKS5cbiAgICAgICAgICAgIC8vIEV2ZXJ5dGhpbmcgaXMgY29waWVkIGhlcmUsIGZpbGVzIHBoeXNpY2FsbHkgZHVwbGljYXRlZCBpbiBTMyBmaXJzdC5cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc291cmNlRmVhdHVyZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzb3VyY2VPYmogPSBzb3VyY2VGZWF0dXJlc1tpXTtcblxuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4aXN0c0luVGFyZ2V0ID0gdGhpcy5tYXRjaGVzRXhpc3RpbmcoXG4gICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VPYmogYXMgYW55LCB0YXJnZXRGZWF0dXJlcyBhcyBhbnksXG4gICAgICAgICAgICAgICAgICAgICAgICAoZjogYW55KSA9PiBbZi50aXRsZSwgZi5kZXNjcmlwdGlvbl1cbiAgICAgICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWV4aXN0c0luVGFyZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByYXdTb3VyY2UgPSBzb3VyY2VPYmogYXMgYW55O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBSZXNvbHZlZCBqdXN0IGJlZm9yZSB0aGUgd3JpdGU6IGEga2V5d29yZCBpcyBvbmx5IGNyZWF0ZWQgaW4gdGhlIHRhcmdldFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3BhY2Ugd2hlbiB0aGUgUE9JIGNhcnJ5aW5nIGl0IGlzIGFib3V0IHRvIGJlIGNyZWF0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZXNvbHZlZEhhc2h0YWdzID0gYXdhaXQgdGhpcy5yZXNvbHZlSGFzaHRhZ0lkcyhyYXdTb3VyY2UuaGFzaHRhZ3MsIHRhcmdldFNwYWNlSWQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmZWF0dXJlSW5wdXQ6IGFueSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZTogcmF3U291cmNlLnRpdGxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3J0RGVzY3JpcHRpb246IHJhd1NvdXJjZS5zaG9ydERlc2NyaXB0aW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsOiByYXdTb3VyY2UubGV2ZWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogcmF3U291cmNlLnR5cGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYGluZGV4YCBkcml2ZXMgdGhlIG9yZGVyaW5nIG9mIHRoZSBQT0kgaW4gdGhlIHNwYWNlJ3MgbGlzdCwgaW4gdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbGF0ZXJhbCBtZW51IGFuZCBpbiB0aGUgZ3VpZGVkIHRvdXIuIERyb3BwaW5nIGl0IGZvcmNlZCBhIGZ1bGwgbWFudWFsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmVudW1iZXJpbmcgb2YgZXZlcnkgY29waWVkIFBPSS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleDogcmF3U291cmNlLmluZGV4ID8/IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWlzc2lvbnMgYXJlIHBlci1zcGFjZTogc291cmNlIG1pc3Npb24gaWRzIG1lYW4gbm90aGluZyBpbiB0aGUgdGFyZ2V0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3BhY2UsIHNvIGFuIGFyY2hpdmUgbGlzdCBjYXJyaWVkIG92ZXIgd291bGQgaGlkZSBQT0lzIGZyb20gbm9ib2R5XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2hpbGUgbG9va2luZyBsaWtlIHJlYWwgZGF0YS4gUmVzZXQgaW5zdGVhZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmNoaXZlZEZvck1pc3Npb25JRDogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpcGVQcm9kdWN0SUQ6IHJhd1NvdXJjZS5zdHJpcGVQcm9kdWN0SUQgfHwgbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpcGVQcmljZUlEOiByYXdTb3VyY2Uuc3RyaXBlUHJpY2VJRCB8fCBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJvb2tpbmdQcmljZU1ldGFkYXRhOiByYXdTb3VyY2UuYm9va2luZ1ByaWNlTWV0YWRhdGEgfHwgbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhbGU6IHJhd1NvdXJjZS5sb2NhbGUgfHwgbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIYXNodGFncyBhcmUgc3BhY2Utc2NvcGVkIHJlY29yZHM6IHRoZSBpZHMgbXVzdCBiZSB0cmFuc2xhdGVkIHRvIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGVxdWl2YWxlbnQgaGFzaHRhZ3Mgb2YgdGhlIHRhcmdldCBzcGFjZSAoY3JlYXRlZCBvbiBkZW1hbmQpLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc2h0YWdzOiByZXNvbHZlZEhhc2h0YWdzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiByYXdTb3VyY2UuZGVzY3JpcHRpb24gfHwgbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBEb21haW5zIGFyZSBvcmdhbmlzYXRpb24tc2NvcGVkLCBzbyB0aGUgY2F0ZWdvcnkgc3Vydml2ZXMgYSBjb3B5XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5zaWRlIG9uZSBvcmdhbmlzYXRpb24gYW5kIG9ubHkgaGFzIHRvIGJlIGRyb3BwZWQgYWNyb3NzIHR3by5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb21haW5JRDogdGhpcy5zYW1lT3JnYW5pc2F0aW9uID8gKHJhd1NvdXJjZS5kb21haW5JRCB8fCBudWxsKSA6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BhY2VJRDogdGFyZ2V0U3BhY2VJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvd25lck1pc3Npb25JRDogdGFyZ2V0TWlzc2lvbklkXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjcmVhdGVkT2JqID0gYXdhaXQgdGhpcy5mZWF0dXJlU2VydmljZS5jcmVhdGVGZWF0dXJlKGZlYXR1cmVJbnB1dCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjcmVhdGVkT2JqICYmIGNyZWF0ZWRPYmouaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50SWRzW3NvdXJjZU9iai5pZF0gPSBjcmVhdGVkT2JqLmlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZSBmZWF0dXJlIGV4aXN0czogaXRzIGtleXdvcmRzIGFyZSBub3cgZ2VudWluZWx5IHJlZmVyZW5jZWQgYW5kXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbXVzdCBzdXJ2aXZlIHRoZSBlbmQtb2YtcnVuIGNsZWFudXAuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXJrSGFzaHRhZ3NVc2VkKHJlc29sdmVkSGFzaHRhZ3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3JlYXRlZE9iaikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlYWQgdGhlIG1lZGlhIHNldCB0aHJvdWdoIGl0cyBvd24gcGFnaW5hdGVkIHF1ZXJ5OiB0aGUgYGNvbW1lbnRzYFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNvbm5lY3Rpb24gZW1iZWRkZWQgaW4gRmVhdHVyZXNCeVNwYWNlIGlzIGNhcHBlZCBhdCAxMDAgaXRlbXMgYW5kIGl0c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5leHRUb2tlbiB3YXMgbmV2ZXIgZm9sbG93ZWQsIHNvIHJpY2ggUE9JcyBsb3N0IGF0dGFjaG1lbnRzIHNpbGVudGx5LlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzb3VyY2VDb21tZW50czogQ29tbWVudFtdID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlQ29tbWVudHMgPSBhd2FpdCB0aGlzLmNvbW1lbnRTZXJ2aWNlLmdldEFsbENvbW1lbnRzRm9yRmVhdHVyZShzb3VyY2VPYmouaWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGNvbW1lbnRzRmV0Y2hFcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYEZhbGxpbmcgYmFjayB0byB0aGUgZW1iZWRkZWQgY29tbWVudCBsaXN0IGZvciBmZWF0dXJlIFwiJHtyYXdTb3VyY2UudGl0bGV9XCI6YCwgY29tbWVudHNGZXRjaEVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlQ29tbWVudHMgPSAoc291cmNlT2JqLmNvbW1lbnRzPy5pdGVtcyB8fCBbXSkuZmlsdGVyKGMgPT4gISFjKSBhcyBDb21tZW50W107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBzb3VyY2VDb21tZW50IG9mIHRoaXMub3JkZXJDb21tZW50c0ZvckNvcHkoc291cmNlQ29tbWVudHMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjcmVhdGVkID0gYXdhaXQgdGhpcy5jb3B5Q29tbWVudEZvckZlYXR1cmUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlQ29tbWVudCwgY3JlYXRlZE9iai5pZCwgdGFyZ2V0U3BhY2VJZCwgdGFyZ2V0TWlzc2lvbklkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNyZWF0ZWQ/LmlkICYmIChzb3VyY2VDb21tZW50IGFzIGFueSkuaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbW1lbnRJZHMuc2V0KChzb3VyY2VDb21tZW50IGFzIGFueSkuaWQsIGNyZWF0ZWQuaWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChhdHRhY2htZW50RXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIGNvcHlpbmcgYXR0YWNobWVudCBcIiR7c291cmNlQ29tbWVudD8udGl0bGV9XCIgZm9yIGZlYXR1cmUgXCIke3NvdXJjZU9iaj8udGl0bGV9XCI6YCwgYXR0YWNobWVudEVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ291bnQrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9nQ29weUl0ZW1FcnJvcihhdHRhY2htZW50RXJyb3IsICdlcnJvckZlYXR1cmVBdHRhY2htZW50Jywgc291cmNlQ29tbWVudD8udGl0bGUgfHwgKHNvdXJjZUNvbW1lbnQgYXMgYW55KT8uaWQsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlOiByYXdTb3VyY2UudGl0bGUgfHwgc291cmNlT2JqLmlkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEV2ZXJ5IFBPSSBvZiB0aGUgZmVhdHVyZSwgbm90IG9ubHkgdGhlIGZpcnN0IG9uZTogYSBmZWF0dXJlIG1heSBiZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHBpbm5lZCBhdCBzZXZlcmFsIHBsYWNlcywgYW5kIG9ubHkgdGhpcyBwaGFzZSBrbm93cyB0aGUgbmV3IGVsZW1lbnQgaWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc291cmNlRmVhdHVyZVBvaXMgPSAoc291cmNlT2JqLnBvaXM/Lml0ZW1zIHx8IFtdKS5maWx0ZXIocCA9PiAhIXApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgc291cmNlUG9pIG9mIHNvdXJjZUZlYXR1cmVQb2lzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuY3JlYXRlQ29waWVkUG9pKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlUG9pLCBjcmVhdGVkT2JqLmlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlTmF2UG9zaXRpb25zLCB0YXJnZXROYXZQb3NpdGlvbnMsIHRyYW5zZm9ybVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGl0ZW1FcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBjb3B5aW5nIGZlYXR1cmUgXCIke3NvdXJjZU9iaj8udGl0bGV9XCIgKGlkOiAke3NvdXJjZU9iaj8uaWR9KTpgLCBpdGVtRXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICBlcnJvckNvdW50Kys7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubG9nQ29weUl0ZW1FcnJvcihpdGVtRXJyb3IsICdlcnJvckZlYXR1cmUnLCBzb3VyY2VPYmo/LnRpdGxlIHx8IHNvdXJjZU9iaj8uaWQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHByb2Nlc3NlZE92ZXJhbGwrKztcbiAgICAgICAgICAgICAgICBlbWl0UHJvZ3Jlc3MoJ2ZlYXR1cmVzJywgaSArIDEsIHNvdXJjZUZlYXR1cmVzLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgY29uc3QgcGN0ID0gc291cmNlRmVhdHVyZXMubGVuZ3RoID4gMCA/IE1hdGgucm91bmQoKChpICsgMSkgLyBzb3VyY2VGZWF0dXJlcy5sZW5ndGgpICogMTAwKSA6IDEwMDtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFN0ZXBQcm9ncmVzcygnZmVhdHVyZXMnLCAnZmVhdHVyZXMnLCBwY3QpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBNRUFTVVJFTUVOVFMgKElNTU8gb25seSDigJQgYSBDb21tZW50ICsgYSBwb3NpdGlvbmFsLW9ubHkgUE9JLCBubyByb3RhdGlvbjtcbiAgICAgICAgICAgIC8vIHRoZSBzY3JlZW5zaG90IGZpbGUgaXMgcGh5c2ljYWxseSBkdXBsaWNhdGVkIGluIFMzIGZpcnN0KVxuICAgICAgICAgICAgaWYgKHRoaXMuc3BNb2R1bGUgPT0gU3BNb2R1bGUuSU1NTykge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc291cmNlTWVhc3VyZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNvdXJjZU1lYXN1cmVtZW50ID0gc291cmNlTWVhc3VyZW1lbnRzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleGlzdHNJblRhcmdldCA9IHRhcmdldE1lYXN1cmVtZW50cy5zb21lKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtID0+IHRtLmNvbW1lbnQudGl0bGUgPT09IHNvdXJjZU1lYXN1cmVtZW50LmNvbW1lbnQudGl0bGVcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZXhpc3RzSW5UYXJnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByYXdDb21tZW50ID0gc291cmNlTWVhc3VyZW1lbnQuY29tbWVudCBhcyBhbnk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgY29waWVkQW5uZXhlOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmF3Q29tbWVudC5hbm5leGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29waWVkQW5uZXhlID0gYXdhaXQgdGhpcy5jb3B5UzNLZXlJZlByZXNlbnQocmF3Q29tbWVudC5hbm5leGUsIGBtZWFzdXJlbWVudCBzY3JlZW5zaG90IFwiJHtyYXdDb21tZW50LnRpdGxlfVwiYCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29tbWVudElucHV0OiBhbnkgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlOiByYXdDb21tZW50LnRpdGxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogcmF3Q29tbWVudC5kZXNjcmlwdGlvbiA/PyBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogcmF3Q29tbWVudC5tZXRhZGF0YSA/PyBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBDb21tZW50VHlwZS5NRUFTVVJFLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1lbnNpb25zOiByYXdDb21tZW50LmRpbWVuc2lvbnMgfHwgbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5uZXhlOiBjb3BpZWRBbm5leGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwYWNlSUQ6IHRhcmdldFNwYWNlSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNyZWF0ZWRDb21tZW50OiBDb21tZW50ID0gYXdhaXQgdGhpcy5jb21tZW50U2VydmljZS5jcmVhdGVDb21tZW50KGNvbW1lbnRJbnB1dCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3JlYXRlZENvbW1lbnQgJiYgKGNyZWF0ZWRDb21tZW50IGFzIGFueSkuaWQgJiYgcmF3Q29tbWVudC5pZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbW1lbnRJZHMuc2V0KHJhd0NvbW1lbnQuaWQsIChjcmVhdGVkQ29tbWVudCBhcyBhbnkpLmlkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3JlYXRlZENvbW1lbnQgJiYgc291cmNlTWVhc3VyZW1lbnQucG9pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRhcmdldFN3ZWVwSWQgPSB0aGlzLmZpbmRDbG9zZXN0VGFyZ2V0U3dlZXBJZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZU1lYXN1cmVtZW50LnBvaS5tYXR0ZXJwb3J0U3dlZXBJRCwgc291cmNlTmF2UG9zaXRpb25zLCB0YXJnZXROYXZQb3NpdGlvbnMsIHRyYW5zZm9ybVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhZGp1c3RlZFBvc2l0aW9uID0gdGhpcy5nZXRBZGp1c3RlZFBvc2l0aW9uT25seShzb3VyY2VNZWFzdXJlbWVudC5wb2kuY29vcmRpbmF0ZSwgdHJhbnNmb3JtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcG9pSW5wdXQ6IFBPSSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkaW5hdGU6IEpTT04uc3RyaW5naWZ5KGFkanVzdGVkUG9zaXRpb24pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogUG9pVHlwZS5NRUFTVVJFLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudElEOiAoY3JlYXRlZENvbW1lbnQgYXMgYW55KS5pZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNhbWUgdHJlYXRtZW50IGFzIGFueSBvdGhlciBQT0k6IHRoZSBzb3VyY2UncyBNYXR0ZXJwb3J0IHRhZ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU0lEIG11c3Qgbm90IHRyYXZlbCwgYW5kIHRoZSBzdGVtIG5vcm1hbCBoYXMgdG8gYmUgcm90YXRlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiB0aGlzLmdldEFkanVzdGVkUG9pTWV0YWRhdGEoc291cmNlTWVhc3VyZW1lbnQucG9pLm1ldGFkYXRhLCB0cmFuc2Zvcm0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0dGVycG9ydFN3ZWVwSUQ6IHRhcmdldFN3ZWVwSWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wb2lTZXJ2aWNlLmNyZWF0ZVBPSUZvclNwYWNlSUQocG9pSW5wdXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoaXRlbUVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBjb3B5aW5nIG1lYXN1cmVtZW50IFwiJHtzb3VyY2VNZWFzdXJlbWVudD8uY29tbWVudD8udGl0bGV9XCI6YCwgaXRlbUVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ291bnQrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9nQ29weUl0ZW1FcnJvcihpdGVtRXJyb3IsICdlcnJvck1lYXN1cmVtZW50Jywgc291cmNlTWVhc3VyZW1lbnQ/LmNvbW1lbnQ/LnRpdGxlIHx8IHNvdXJjZU1lYXN1cmVtZW50Py5pZCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzZWRPdmVyYWxsKys7XG4gICAgICAgICAgICAgICAgICAgIGVtaXRQcm9ncmVzcygnbWVhc3VyZW1lbnRzJywgaSArIDEsIHNvdXJjZU1lYXN1cmVtZW50cy5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwY3QgPSBzb3VyY2VNZWFzdXJlbWVudHMubGVuZ3RoID4gMCA/IE1hdGgucm91bmQoKChpICsgMSkgLyBzb3VyY2VNZWFzdXJlbWVudHMubGVuZ3RoKSAqIDEwMCkgOiAxMDA7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RlcFByb2dyZXNzKCdtZWFzdXJlbWVudHMnLCAnbWVhc3VyZW1lbnRzJywgcGN0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFBPSVMg4oCUIHN0YW5kYWxvbmUgb25lcyBvbmx5OiBldmVyeSBQT0kgb3duZWQgYnkgYW4gZWxlbWVudCB3YXMgYWxyZWFkeSBjcmVhdGVkIGJ5XG4gICAgICAgICAgICAvLyB0aGF0IGVsZW1lbnQncyBwaGFzZSwgd2l0aCB0aGUgZWxlbWVudCdzIE5FVyBpZC5cbiAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAvLyBUaGlzIHBoYXNlIHJ1bnMgTEFTVCBvbiBwdXJwb3NlLiBJdCB1c2VkIHRvIHJ1biB0aGlyZCwgYmVmb3JlIDNEIG9iamVjdHMsIGZlYXR1cmVzXG4gICAgICAgICAgICAvLyBhbmQgbWVhc3VyZW1lbnRzIGV4aXN0ZWQgaW4gdGhlIHRhcmdldCBzcGFjZSwgc28gYGVsZW1lbnRJZHNgIGFuZCBgY29tbWVudElkc2Agd2VyZVxuICAgICAgICAgICAgLy8gc3RpbGwgZW1wdHkgd2hlbiBpdCBuZWVkZWQgdGhlbTogZWxlbWVudElEIHN0YXllZCBwb2ludGluZyBhdCB0aGUgc291cmNlIHNwYWNlIGFuZFxuICAgICAgICAgICAgLy8gdGFnSW1hZ2VJRCAoYSByZWZlcmVuY2UgdG8gYSBDb21tZW50IHJlY29yZCkgY291bGQgbmV2ZXIgYmUgcmVzb2x2ZWQuXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNvdXJjZVBvaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzb3VyY2VQb2kgPSBzb3VyY2VQb2lzW2ldO1xuXG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZXhpc3RzSW5UYXJnZXQgPSB0YXJnZXRQb2lzLnNvbWUoXG4gICAgICAgICAgICAgICAgICAgICAgICB0cCA9PiB0cC5jb29yZGluYXRlID09PSBzb3VyY2VQb2kuY29vcmRpbmF0ZSAmJiB0cC50YWdEZXNjcmlwdGlvbiA9PT0gc291cmNlUG9pLnRhZ0Rlc2NyaXB0aW9uXG4gICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFleGlzdHNJblRhcmdldCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZWxlbWVudElEID0gc291cmNlUG9pLmVsZW1lbnRJRFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gKGVsZW1lbnRJZHNbc291cmNlUG9pLmVsZW1lbnRJRF0gfHwgc291cmNlUG9pLmVsZW1lbnRJRClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IHNvdXJjZVBvaS5lbGVtZW50SUQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuY3JlYXRlQ29waWVkUG9pKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZVBvaSwgZWxlbWVudElELFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZU5hdlBvc2l0aW9ucywgdGFyZ2V0TmF2UG9zaXRpb25zLCB0cmFuc2Zvcm1cbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChpdGVtRXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgRXJyb3IgY29weWluZyBQT0kgKHN3ZWVwOiAke3NvdXJjZVBvaT8ubWF0dGVycG9ydFN3ZWVwSUR9KTpgLCBpdGVtRXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICBlcnJvckNvdW50Kys7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubG9nQ29weUl0ZW1FcnJvcihpdGVtRXJyb3IsICdlcnJvclBvaScsIHNvdXJjZVBvaT8ubWF0dGVycG9ydFN3ZWVwSUQsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN3ZWVwOiBzb3VyY2VQb2k/Lm1hdHRlcnBvcnRTd2VlcElEXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHByb2Nlc3NlZE92ZXJhbGwrKztcbiAgICAgICAgICAgICAgICBlbWl0UHJvZ3Jlc3MoJ3BvaXMnLCBpICsgMSwgc291cmNlUG9pcy5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHBjdCA9IHNvdXJjZVBvaXMubGVuZ3RoID4gMCA/IE1hdGgucm91bmQoKChpICsgMSkgLyBzb3VyY2VQb2lzLmxlbmd0aCkgKiAxMDApIDogMTAwO1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RlcFByb2dyZXNzKCdwb2lzJywgJ3BvaXMnLCBwY3QpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmNvcHlQcm9ncmVzcyQubmV4dCh7XG4gICAgICAgICAgICAgICAgcGhhc2U6ICdkb25lJyxcbiAgICAgICAgICAgICAgICBwcm9jZXNzZWRJblBoYXNlOiAwLCB0b3RhbEluUGhhc2U6IDAsXG4gICAgICAgICAgICAgICAgcHJvY2Vzc2VkT3ZlcmFsbCwgdG90YWxPdmVyYWxsLFxuICAgICAgICAgICAgICAgIHBlcmNlbnQ6IDEwMCwgZXJyb3JDb3VudFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnNldFN0ZXBMb2coJ2RvbmUnLCBlcnJvckNvdW50ID4gMFxuICAgICAgICAgICAgICAgID8gdGhpcy50cmFuc2xhdGUuaW5zdGFudCgnbWF0dGVycG9ydENvcHkuZG9uZVdpdGhFcnJvcnMnLCB7IGNvdW50OiBlcnJvckNvdW50IH0pXG4gICAgICAgICAgICAgICAgOiB0aGlzLnRyYW5zbGF0ZS5pbnN0YW50KCdtYXR0ZXJwb3J0Q29weS5kb25lJykpO1xuXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGNvcHlpbmcgUE9JczonLCBlcnJvcik7XG4gICAgICAgICAgICB0aGlzLmFwcGVuZEVycm9yTG9nKHRoaXMudHJhbnNsYXRlLmluc3RhbnQoJ21hdHRlcnBvcnRDb3B5LmVycm9yR2VuZXJhbCcsIHsgZXJyb3I6IHRvRXJyb3JNZXNzYWdlKGVycm9yKSB9KSk7XG4gICAgICAgICAgICB0aGlzLmNvcHlQcm9ncmVzcyQubmV4dChudWxsKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgIC8vIEV2ZXJ5IGV4aXQgcGF0aCDigJQgc3VjY2VzcywgcGFydGlhbCBzdWNjZXNzLCBvciBnZW5lcmFsIGZhaWx1cmUg4oCUIGdpdmVzIGJhY2sgdGhlXG4gICAgICAgICAgICAvLyBrZXl3b3JkcyB0aGlzIHJ1biBjcmVhdGVkIGJ1dCBubyBjb3BpZWQgUE9JIGVuZGVkIHVwIHVzaW5nLiBQbGFjZWQgaW4gYGZpbmFsbHlgXG4gICAgICAgICAgICAvLyBzbyBhbiBleGNlcHRpb24gdGhyb3duIG1pZC1jb3B5IGNhbm5vdCBsZWF2ZSB0aGVtIGJlaGluZCBlaXRoZXIuXG4gICAgICAgICAgICBhd2FpdCB0aGlzLmNsZWFudXBVbnVzZWRDcmVhdGVkSGFzaHRhZ3MoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vXG4gICAgLy8gLS0tLS0tLS0tLSBQcm9ncmVzcyAvIGxvZyBoZWxwZXJzIC0tLS0tLS0tLS1cbiAgICAvL1xuXG4gICAgLyoqIEFkZHMgb3IgdXBkYXRlcyBhIHN0ZXAgbGluZSAoaWRlbnRpZmllZCBieSBzdGVwSWQpIHdpdGggbmV3IHRleHQsIHRoZW4gcmVwdWJsaXNoZXMgdGhlIGxvZy4gKi9cbiAgICBwcml2YXRlIHNldFN0ZXBMb2coc3RlcElkOiBzdHJpbmcsIHRleHQ6IHN0cmluZykge1xuICAgICAgICBjb25zdCBleGlzdGluZ0luZGV4ID0gdGhpcy5sb2cuZmluZEluZGV4KGUgPT4gZS50eXBlID09PSAnc3RlcCcgJiYgZS5pZCA9PT0gc3RlcElkKTtcbiAgICAgICAgY29uc3QgZW50cnk6IENvcHlMb2dFbnRyeSA9IHsgaWQ6IHN0ZXBJZCwgdHlwZTogJ3N0ZXAnLCB0ZXh0IH07XG4gICAgICAgIGlmIChleGlzdGluZ0luZGV4ID49IDApIHtcbiAgICAgICAgICAgIHRoaXMubG9nW2V4aXN0aW5nSW5kZXhdID0gZW50cnk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmxvZy5wdXNoKGVudHJ5KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNvcHlMb2ckLm5leHQoWy4uLnRoaXMubG9nXSk7XG4gICAgfVxuXG4gICAgLyoqIEFwcGVuZHMgYSBuZXcsIHBlcm1hbmVudCBsb2cgbGluZSAobmV2ZXIgb3ZlcndyaXR0ZW4pLCB0aGVuIHJlcHVibGlzaGVzIHRoZSBsb2cuICovXG4gICAgcHJpdmF0ZSBhcHBlbmRFcnJvckxvZyh0ZXh0OiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5lcnJvclNlcSsrO1xuICAgICAgICB0aGlzLmxvZy5wdXNoKHsgaWQ6IGBlcnJvci0ke3RoaXMuZXJyb3JTZXF9YCwgdHlwZTogJ2Vycm9yJywgdGV4dCB9KTtcbiAgICAgICAgdGhpcy5jb3B5TG9nJC5uZXh0KFsuLi50aGlzLmxvZ10pO1xuICAgIH1cblxuICAgIC8qKiBSZXNldHMgdGhlIGxvZyBmb3IgYSBuZXcgcnVuLiAqL1xuICAgIHByaXZhdGUgcmVzZXRMb2coKSB7XG4gICAgICAgIHRoaXMubG9nID0gW107XG4gICAgICAgIHRoaXMuZXJyb3JTZXEgPSAwO1xuICAgICAgICB0aGlzLmNvcHlMb2ckLm5leHQoW10pO1xuICAgIH1cblxuICAgIC8qKiBDbGVhcnMgZXZlcnkgaWQgbWFwIGNhcnJpZWQgb3ZlciBmcm9tIGEgcHJldmlvdXMgcnVuLiBUaGUgc2VydmljZSBpcyBhIHJvb3QtbGV2ZWxcbiAgICAgKiAgc2luZ2xldG9uLCBzbyBsZWZ0b3ZlciBtYXBwaW5ncyB3b3VsZCBzaWxlbnRseSBsaW5rIGEgbmV3IGNvcHkgdG8gcmVjb3JkcyBjcmVhdGVkXG4gICAgICogIGR1cmluZyB0aGUgcHJldmlvdXMgb25lLiAqL1xuICAgIHByaXZhdGUgcmVzZXRSdW5TdGF0ZSh0YXJnZXRTcGFjZUlkOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5lbGVtZW50SWRzID0ge307XG4gICAgICAgIHRoaXMuY29tbWVudElkcyA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5zb3VyY2VIYXNodGFnTmFtZXMgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMudGFyZ2V0SGFzaHRhZ0lkc0J5TmFtZSA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5jcmVhdGVkSGFzaHRhZ0lkcyA9IG5ldyBTZXQoKTtcbiAgICAgICAgdGhpcy51c2VkSGFzaHRhZ0lkcyA9IG5ldyBTZXQoKTtcbiAgICAgICAgdGhpcy5oYW5kbGVkRWxlbWVudElkcyA9IG5ldyBTZXQoKTtcbiAgICAgICAgdGhpcy5zYW1lT3JnYW5pc2F0aW9uID0gZmFsc2U7XG4gICAgICAgIHRoaXMudGFyZ2V0U3BhY2VJZCA9IHRhcmdldFNwYWNlSWQ7XG4gICAgfVxuXG4gICAgLyoqIEJ1aWxkcyBhbmQgc2V0cyBhIHN0ZXAncyBsb2cgbGluZSBhcyBcIjx0cmFuc2xhdGVkIGxhYmVsPjogPHBlcmNlbnQ+JVwiLCBubyBzdGVwIG51bWJlcmluZy4gKi9cbiAgICBwcml2YXRlIHNldFN0ZXBQcm9ncmVzcyhzdGVwSWQ6IHN0cmluZywgdHJhbnNsYXRpb25LZXk6IHN0cmluZywgcGVyY2VudDogbnVtYmVyKSB7XG4gICAgICAgIGNvbnN0IGxhYmVsID0gdGhpcy50cmFuc2xhdGUuaW5zdGFudChgbWF0dGVycG9ydENvcHkuJHt0cmFuc2xhdGlvbktleX1gKTtcbiAgICAgICAgdGhpcy5zZXRTdGVwTG9nKHN0ZXBJZCwgYCR7bGFiZWx9OiAke3BlcmNlbnR9JWApO1xuICAgIH1cblxuICAgIC8qKiBMb2dzIGEgdHJhbnNsYXRlZCwgcGFyYW1ldGVyaXplZCBlcnJvciBsaW5lIGZvciBhIHNpbmdsZSBmYWlsZWQgaXRlbS4gKi9cbiAgICBwcml2YXRlIGxvZ0l0ZW1FcnJvcih0cmFuc2xhdGlvbktleTogc3RyaW5nLCBwYXJhbXM6IFJlY29yZDxzdHJpbmcsIGFueT4pIHtcbiAgICAgICAgY29uc3QgdGV4dCA9IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoYG1hdHRlcnBvcnRDb3B5LiR7dHJhbnNsYXRpb25LZXl9YCwgcGFyYW1zKTtcbiAgICAgICAgdGhpcy5hcHBlbmRFcnJvckxvZyh0ZXh0KTtcbiAgICB9XG5cbiAgICAvKiogTG9ncyBhbiBpdGVtLWxldmVsIGVycm9yLCB1c2luZyBhIHNwZWNpZmljIFwibWlzc2luZyBmaWxlIC8gb3JwaGFuZWQgcmVmZXJlbmNlXCJcbiAgICAgKiAgdHJhbnNsYXRpb24ga2V5IHdoZW4gdGhlIGNhdXNlIGlzIGEgTWlzc2luZ1MzRmlsZUVycm9yLCBhbmQgdGhlIGdlbmVyaWMgcGVyLXR5cGVcbiAgICAgKiAga2V5IG90aGVyd2lzZS4gS2VlcHMgdGhlIGNvcHkgbG9nIHJlYWRhYmxlOiBhIG1pc3NpbmcgZmlsZSBpcyBub3QgYSBidWcgdG9cbiAgICAgKiAgaW52ZXN0aWdhdGUgdGhlIHNhbWUgd2F5IGEgbmV0d29yay9wZXJtaXNzaW9uIGVycm9yIGlzLlxuICAgICAqICBgZXh0cmFQYXJhbXNgIGNhcnJpZXMgdGhlIHBsYWNlaG9sZGVycyBhIGZldyBrZXlzIG5lZWQgb24gdG9wIG9mIHt7bmFtZX19L3t7ZXJyb3J9fVxuICAgICAqICAoZS5nLiBlcnJvckZlYXR1cmVBdHRhY2htZW50J3Mge3tmZWF0dXJlfX0sIGVycm9yUG9pJ3Mge3tzd2VlcH19KSwgd2hpY2ggdXNlZCB0byBiZVxuICAgICAqICByZW5kZXJlZCBhcyByYXcgXCJ7e2ZlYXR1cmV9fVwiIHRleHQgaW4gdGhlIGxvZy4gKi9cbiAgICBwcml2YXRlIGxvZ0NvcHlJdGVtRXJyb3IoXG4gICAgICAgIGVycm9yOiB1bmtub3duLFxuICAgICAgICBnZW5lcmljS2V5OiBzdHJpbmcsXG4gICAgICAgIGl0ZW1MYWJlbDogc3RyaW5nLFxuICAgICAgICBleHRyYVBhcmFtczogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9XG4gICAgKSB7XG4gICAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIE1pc3NpbmdTM0ZpbGVFcnJvcikge1xuICAgICAgICAgICAgdGhpcy5sb2dJdGVtRXJyb3IoJ2Vycm9yTWlzc2luZ1MzRmlsZVNraXBwZWQnLCB7XG4gICAgICAgICAgICAgICAgLi4uZXh0cmFQYXJhbXMsXG4gICAgICAgICAgICAgICAgbmFtZTogaXRlbUxhYmVsLFxuICAgICAgICAgICAgICAgIGZpbGU6IGVycm9yLnNvdXJjZUtleVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmxvZ0l0ZW1FcnJvcihnZW5lcmljS2V5LCB7IC4uLmV4dHJhUGFyYW1zLCBuYW1lOiBpdGVtTGFiZWwsIGVycm9yOiB0b0Vycm9yTWVzc2FnZShlcnJvcikgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBOdWxsLXNhZmUgZXF1aXZhbGVudCBvZiBGZWF0dXJlU2VydmljZS5pc0FyY2hpdmVkKCk6IHRydWUgd2hlbiB0aGUgb3BlcmF0b3IgaGFzIGFyY2hpdmVkXG4gICAgICogdGhpcyBmZWF0dXJlIG9uIHRoYXQgc3BhY2UuIFwiTm8gbWlzc2lvbiBvbiB0aGUgc3BhY2VcIiBhbnN3ZXJzIGZhbHNlIChub3RoaW5nIGFyY2hpdmVkKVxuICAgICAqIGluc3RlYWQgb2YgdGhyb3dpbmcsIHdoaWNoIGlzIHdoYXQgbWFkZSBhIGNvcHkgZnJvbSBhIHNwYWNlIHRoZSBvcGVyYXRvciBpcyBub3QgYSBtZW1iZXJcbiAgICAgKiBvZiBmYWlsIG91dHJpZ2h0LlxuICAgICAqL1xuICAgIHByaXZhdGUgaXNBcmNoaXZlZEZvck9wZXJhdG9yKGZlYXR1cmU6IEZlYXR1cmUsIHNwYWNlSWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgICBjb25zdCBhcmNoaXZlZEZvciA9IGZlYXR1cmU/LmFyY2hpdmVkRm9yTWlzc2lvbklEO1xuICAgICAgICBpZiAoIWFyY2hpdmVkRm9yIHx8IGFyY2hpdmVkRm9yLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG1pc3Npb24gPSB0aGlzLnVzZXJTZXJ2aWNlLmN1cnJlbnRNaXNzaW9uKHNwYWNlSWQpO1xuICAgICAgICByZXR1cm4gbWlzc2lvbj8uaWQgPyBhcmNoaXZlZEZvci5pbmNsdWRlcyhtaXNzaW9uLmlkKSA6IGZhbHNlO1xuICAgIH1cblxuICAgIC8vXG4gICAgLy8gLS0tLS0tLS0tLSBDcm9zcy1zcGFjZSByZWZlcmVuY2UgcmVtYXBwaW5nIC0tLS0tLS0tLS1cbiAgICAvL1xuXG4gICAgLyoqXG4gICAgICogVHJ1ZSB3aGVuIGJvdGggc3BhY2VzIGJlbG9uZyB0byB0aGUgc2FtZSBvcmdhbmlzYXRpb24uXG4gICAgICogRG9tYWlucyAoUE9JL0ZlYXR1cmUgY2F0ZWdvcmllcykgYXJlIG9yZ2FuaXNhdGlvbi1zY29wZWQgcmVjb3JkcyB3aXRoIG5vIHNwYWNlSUQsIHNvXG4gICAgICogYSBkb21haW5JRCBzdGF5cyBtZWFuaW5nZnVsIGluc2lkZSBvbmUgb3JnYW5pc2F0aW9uIGFuZCBvbmx5IGJlY29tZXMgYSBkYW5nbGluZ1xuICAgICAqIHJlZmVyZW5jZSBhY3Jvc3MgdHdvLiBBIGZhaWxlZCBsb29rdXAgYW5zd2VycyBcIm5vXCI6IGRyb3BwaW5nIGEgY2F0ZWdvcnkgaXMgcmVjb3ZlcmFibGUsXG4gICAgICogcG9pbnRpbmcgYXQgYW5vdGhlciBvcmdhbmlzYXRpb24ncyBkb21haW4gaXMgbm90LlxuICAgICAqL1xuICAgIHByaXZhdGUgYXN5bmMgc3BhY2VzU2hhcmVPcmdhbmlzYXRpb24oc291cmNlU3BhY2VJZDogc3RyaW5nLCB0YXJnZXRTcGFjZUlkOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IFtzb3VyY2VTcGFjZSwgdGFyZ2V0U3BhY2VdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgICAgICAgICAgIHRoaXMuc3BhY2VTZXJ2aWNlLmdldFNwYWNlKHNvdXJjZVNwYWNlSWQpLFxuICAgICAgICAgICAgICAgIHRoaXMuc3BhY2VTZXJ2aWNlLmdldFNwYWNlKHRhcmdldFNwYWNlSWQpXG4gICAgICAgICAgICBdKTtcbiAgICAgICAgICAgIGNvbnN0IHNvdXJjZU9yZyA9IHNvdXJjZVNwYWNlPy5vcmdhbmlzYXRpb25JRDtcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldE9yZyA9IHRhcmdldFNwYWNlPy5vcmdhbmlzYXRpb25JRDtcbiAgICAgICAgICAgIHJldHVybiAhIXNvdXJjZU9yZyAmJiAhIXRhcmdldE9yZyAmJiBzb3VyY2VPcmcgPT09IHRhcmdldE9yZztcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignW01hdHRlcnBvcnRUYWdDb3B5U2VydmljZV0gQ291bGQgbm90IGNvbXBhcmUgdGhlIHNwYWNlc1xcJyBvcmdhbmlzYXRpb25zLCBjYXRlZ29yaWVzIHdpbGwgYmUgZHJvcHBlZDonLCBlcnJvcik7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogTm9ybWFsaXNlZCBsb29rdXAga2V5IGZvciBhIGhhc2h0YWcgbmFtZSwgc28gXCJNb3llbiDDgmdlXCIgYW5kIFwibW95ZW4gw6JnZSBcIiBtYXRjaC4gKi9cbiAgICBwcml2YXRlIGhhc2h0YWdLZXkobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIG5hbWUudHJpbSgpLnRvTG93ZXJDYXNlKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUkVBRC1PTkxZIGluZGV4aW5nIG9mIGJvdGggc3BhY2VzJyBoYXNodGFncy4gQ3JlYXRlcyBub3RoaW5nLlxuICAgICAqXG4gICAgICogYEZlYXR1cmUuaGFzaHRhZ3NgIHN0b3JlcyBIYXNodGFnICppZHMqLCBhbmQgYSBIYXNodGFnIGlzIGEgcGVyLXNwYWNlIHJlY29yZCwgc28gdGhlXG4gICAgICogaWRzIGhhdmUgdG8gYmUgdHJhbnNsYXRlZCBieSBuYW1lLiBUaGUgdHJhbnNsYXRpb24gdGFibGUgaXMgYnVpbHQgaGVyZTsgdGhlIG1pc3NpbmdcbiAgICAgKiBrZXl3b3JkcyBhcmUgY3JlYXRlZCBsYXRlciwgb25lIGF0IGEgdGltZSwgb25seSB3aGVuIGEgUE9JIHRoYXQgYWN0dWFsbHkgdXNlcyB0aGVtIGlzXG4gICAgICogYWJvdXQgdG8gYmUgd3JpdHRlbiAoc2VlIHJlc29sdmVIYXNodGFnSWRzKCkpLlxuICAgICAqL1xuICAgIHByaXZhdGUgYXN5bmMgbG9hZEhhc2h0YWdJbmRleChzb3VyY2VTcGFjZUlkOiBzdHJpbmcsIHRhcmdldFNwYWNlSWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBsZXQgc291cmNlSGFzaHRhZ3M6IEhhc2h0YWdbXSA9IFtdO1xuICAgICAgICBsZXQgdGFyZ2V0SGFzaHRhZ3M6IEhhc2h0YWdbXSA9IFtdO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBbc291cmNlSGFzaHRhZ3MsIHRhcmdldEhhc2h0YWdzXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgICAgICAgICB0aGlzLmhhc2h0YWdTZXJ2aWNlLmxpc3RIYXNodGFnc0ZvclNwYWNlKHNvdXJjZVNwYWNlSWQpLFxuICAgICAgICAgICAgICAgIHRoaXMuaGFzaHRhZ1NlcnZpY2UubGlzdEhhc2h0YWdzRm9yU3BhY2UodGFyZ2V0U3BhY2VJZClcbiAgICAgICAgICAgIF0pO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdbTWF0dGVycG9ydFRhZ0NvcHlTZXJ2aWNlXSBDb3VsZCBub3QgcmVhZCB0aGUgaGFzaHRhZ3MsIGtleXdvcmRzIHdpbGwgYmUgZHJvcHBlZDonLCBlcnJvcik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGNvbnN0IGhhc2h0YWcgb2Ygc291cmNlSGFzaHRhZ3MgfHwgW10pIHtcbiAgICAgICAgICAgIGlmIChoYXNodGFnPy5pZCAmJiBoYXNodGFnLm5hbWUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNvdXJjZUhhc2h0YWdOYW1lcy5zZXQoaGFzaHRhZy5pZCwgaGFzaHRhZy5uYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IgKGNvbnN0IGhhc2h0YWcgb2YgdGFyZ2V0SGFzaHRhZ3MgfHwgW10pIHtcbiAgICAgICAgICAgIGlmIChoYXNodGFnPy5pZCAmJiBoYXNodGFnLm5hbWUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRhcmdldEhhc2h0YWdJZHNCeU5hbWUuc2V0KHRoaXMuaGFzaHRhZ0tleShoYXNodGFnLm5hbWUpLCBoYXNodGFnLmlkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRyYW5zbGF0ZXMgb25lIGZlYXR1cmUncyBoYXNodGFnIGlkcyBpbnRvIHRhcmdldC1zcGFjZSBpZHMsIGNyZWF0aW5nIG9uIHRoZSBmbHkgdGhlXG4gICAgICoga2V5d29yZHMgdGhlIHRhcmdldCBzcGFjZSBkb2VzIG5vdCBoYXZlIHlldC5cbiAgICAgKlxuICAgICAqIENyZWF0aW9uIGlzIExBWlkgb24gcHVycG9zZS4gRG9pbmcgaXQgdXAgZnJvbnQsIGZvciB0aGUgd2hvbGUgc291cmNlIHZvY2FidWxhcnksIG1lYW50XG4gICAgICogdGhhdCBhIGNvcHkgd2hpY2ggZmFpbGVkIG9yIHdhcyBjbG9zZWQgaGFsZndheSBsZWZ0IGJlaGluZCBrZXl3b3JkcyBubyBQT0kgcmVmZXJlbmNlZCDigJRcbiAgICAgKiBwb2xsdXRpb24gdGhlIG9wZXJhdG9yIGhhZCB0byBjbGVhbiB1cCBieSBoYW5kLiBIZXJlIGEga2V5d29yZCBpcyBvbmx5IGV2ZXIgd3JpdHRlblxuICAgICAqIHdoZW4gYSBQT0kgdGhhdCBjYXJyaWVzIGl0IGlzIGFib3V0IHRvIGJlIGNyZWF0ZWQsIHNvIGFuIGludGVycnVwdGVkIGNvcHkgc3RvcHNcbiAgICAgKiBjcmVhdGluZyBrZXl3b3JkcyBhdCB0aGUgc2FtZSBQT0kgaXQgc3RvcHMgY3JlYXRpbmcgY29udGVudC5cbiAgICAgKlxuICAgICAqIFRoZSByZXNpZHVhbCB3aW5kb3cgKGtleXdvcmQgY3JlYXRlZCwgdGhlbiBjcmVhdGVGZWF0dXJlIGZhaWxzKSBpcyBjbG9zZWQgYnlcbiAgICAgKiBtYXJrSGFzaHRhZ3NVc2VkKCkgKyBjbGVhbnVwVW51c2VkQ3JlYXRlZEhhc2h0YWdzKCkuXG4gICAgICpcbiAgICAgKiBBIGtleXdvcmQgdGhhdCBjYW4gbmVpdGhlciBiZSBmb3VuZCBub3IgY3JlYXRlZCBpcyBkcm9wcGVkIHJhdGhlciB0aGFuIGxlZnQgYXMgYVxuICAgICAqIGRhbmdsaW5nIGlkLlxuICAgICAqL1xuICAgIHByaXZhdGUgYXN5bmMgcmVzb2x2ZUhhc2h0YWdJZHMoXG4gICAgICAgIHNvdXJjZUhhc2h0YWdJZHM6IEFycmF5PHN0cmluZyB8IG51bGw+IHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgICAgICAgdGFyZ2V0U3BhY2VJZDogc3RyaW5nXG4gICAgKTogUHJvbWlzZTxzdHJpbmdbXSB8IG51bGw+IHtcbiAgICAgICAgaWYgKCFzb3VyY2VIYXNodGFnSWRzIHx8IHNvdXJjZUhhc2h0YWdJZHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlc29sdmVkOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgICAgIGZvciAoY29uc3Qgc291cmNlSWQgb2Ygc291cmNlSGFzaHRhZ0lkcykge1xuICAgICAgICAgICAgaWYgKCFzb3VyY2VJZCkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbmFtZSA9IHRoaXMuc291cmNlSGFzaHRhZ05hbWVzLmdldChzb3VyY2VJZCk7XG4gICAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgICAgICAvLyB0aGUgc291cmNlIGlkIHBvaW50cyBhdCBhIGhhc2h0YWcgdGhhdCBubyBsb25nZXIgZXhpc3RzIOKAlCBub3RoaW5nIHRvIGNhcnJ5IG92ZXJcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3Qga2V5ID0gdGhpcy5oYXNodGFnS2V5KG5hbWUpO1xuICAgICAgICAgICAgbGV0IHRhcmdldElkID0gdGhpcy50YXJnZXRIYXNodGFnSWRzQnlOYW1lLmdldChrZXkpO1xuXG4gICAgICAgICAgICBpZiAoIXRhcmdldElkKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY3JlYXRlZCA9IGF3YWl0IHRoaXMuaGFzaHRhZ1NlcnZpY2UuY3JlYXRlSGFzaHRhZ0ZvclNwYWNlKG5hbWUsIHRhcmdldFNwYWNlSWQpO1xuICAgICAgICAgICAgICAgICAgICB0YXJnZXRJZCA9IGNyZWF0ZWQ/LmlkO1xuICAgICAgICAgICAgICAgICAgICBpZiAodGFyZ2V0SWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudGFyZ2V0SGFzaHRhZ0lkc0J5TmFtZS5zZXQoa2V5LCB0YXJnZXRJZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNyZWF0ZWRIYXNodGFnSWRzLmFkZCh0YXJnZXRJZCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYFtNYXR0ZXJwb3J0VGFnQ29weVNlcnZpY2VdIENvdWxkIG5vdCBjcmVhdGUgdGhlIGhhc2h0YWcgXCIke25hbWV9XCIgaW4gdGhlIHRhcmdldCBzcGFjZTpgLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRhcmdldElkICYmICFyZXNvbHZlZC5pbmNsdWRlcyh0YXJnZXRJZCkpIHtcbiAgICAgICAgICAgICAgICByZXNvbHZlZC5wdXNoKHRhcmdldElkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXNvbHZlZC5sZW5ndGggPiAwID8gcmVzb2x2ZWQgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKiBSZWNvcmRzIHRoYXQgdGhlc2UgaGFzaHRhZ3MgYXJlIG5vdyByZWZlcmVuY2VkIGJ5IGEgZmVhdHVyZSB0aGF0IHJlYWxseSBleGlzdHMsIHNvXG4gICAgICogIHRoZSBlbmQtb2YtcnVuIGNsZWFudXAgbGVhdmVzIHRoZW0gYWxvbmUuICovXG4gICAgcHJpdmF0ZSBtYXJrSGFzaHRhZ3NVc2VkKGhhc2h0YWdJZHM6IHN0cmluZ1tdIHwgbnVsbCk6IHZvaWQge1xuICAgICAgICBmb3IgKGNvbnN0IGlkIG9mIGhhc2h0YWdJZHMgfHwgW10pIHtcbiAgICAgICAgICAgIHRoaXMudXNlZEhhc2h0YWdJZHMuYWRkKGlkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERlbGV0ZXMgdGhlIGhhc2h0YWdzIHRoaXMgcnVuIGNyZWF0ZWQgdGhhdCBubyBjb3BpZWQgUE9JIGVuZGVkIHVwIHJlZmVyZW5jaW5nLlxuICAgICAqXG4gICAgICogUnVucyBvbiBldmVyeSBleGl0IHBhdGgg4oCUIHN1Y2Nlc3MsIGdlbmVyYWwgZmFpbHVyZSwgb3IgZXhjZXB0aW9uIOKAlCBzbyB0aGUgdGFyZ2V0IHNwYWNlXG4gICAgICogbmV2ZXIga2VlcHMga2V5d29yZHMgdGhhdCBjYW1lIGZyb20gYW4gYWJvcnRlZCBjb3B5LiBPbmx5IGlkcyBjcmVhdGVkIGJ5IFRISVMgcnVuIGFyZVxuICAgICAqIGV2ZXIgY29uc2lkZXJlZDogYSBwcmUtZXhpc3Rpbmcga2V5d29yZCBvZiB0aGUgdGFyZ2V0IHNwYWNlIGlzIG5ldmVyIHRvdWNoZWQsIGV2ZW4gaWZcbiAgICAgKiBubyBjb3BpZWQgUE9JIHVzZXMgaXQuXG4gICAgICovXG4gICAgcHJpdmF0ZSBhc3luYyBjbGVhbnVwVW51c2VkQ3JlYXRlZEhhc2h0YWdzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBvcnBoYW5zID0gWy4uLnRoaXMuY3JlYXRlZEhhc2h0YWdJZHNdLmZpbHRlcihpZCA9PiAhdGhpcy51c2VkSGFzaHRhZ0lkcy5oYXMoaWQpKTtcbiAgICAgICAgaWYgKG9ycGhhbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlLmxvZyhgW01hdHRlcnBvcnRUYWdDb3B5U2VydmljZV0gUmVtb3ZpbmcgJHtvcnBoYW5zLmxlbmd0aH0ga2V5d29yZChzKSBjcmVhdGVkIGJ1dCBsZWZ0IHVudXNlZCBieSB0aGlzIGNvcHkuYCk7XG5cbiAgICAgICAgZm9yIChjb25zdCBoYXNodGFnSWQgb2Ygb3JwaGFucykge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmhhc2h0YWdTZXJ2aWNlLmRlbGV0ZUhhc2h0YWdCeUlkKGhhc2h0YWdJZCk7XG4gICAgICAgICAgICAgICAgdGhpcy5jcmVhdGVkSGFzaHRhZ0lkcy5kZWxldGUoaGFzaHRhZ0lkKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgLy8gQ2xlYW51cCBpcyBiZXN0LWVmZm9ydDogYSBsZWZ0b3ZlciBrZXl3b3JkIGlzIGhhcm1sZXNzIG5leHQgdG8gYSBmYWlsZWQgY29weSxcbiAgICAgICAgICAgICAgICAvLyBhbmQgbXVzdCBuZXZlciBiZSB0aGUgcmVhc29uIHRoZSB3aG9sZSBvcGVyYXRpb24gcmVwb3J0cyBhIGZhaWx1cmUuXG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBbTWF0dGVycG9ydFRhZ0NvcHlTZXJ2aWNlXSBDb3VsZCBub3QgcmVtb3ZlIHRoZSB1bnVzZWQga2V5d29yZCBcIiR7aGFzaHRhZ0lkfVwiOmAsIGVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vXG4gICAgLy8gLS0tLS0tLS0tLSBNZWRpYSBjb250ZW50IChDb21tZW50cykgLS0tLS0tLS0tLVxuICAgIC8vXG5cbiAgICAvKipcbiAgICAgKiBPcmRlcnMgYSBmZWF0dXJlJ3MgbWVkaWEgc2V0IGV4YWN0bHkgdGhlIHdheSB0aGUgVUkgd2lsbCByZWFkIGl0IGJhY2ssIGFuZCByZXBhaXJzXG4gICAgICogdGhlIG9yZGVyaW5nIGtleSB3aGVuIHRoZSBzb3VyY2UgZGF0YSBjYW5ub3QgZXhwcmVzcyB0aGUgdXNlcidzIGludGVuZGVkIG9yZGVyLlxuICAgICAqXG4gICAgICogVGhlIHZpZXdlciBzb3J0cyBlYWNoIG1lZGlhIGZhbWlseSBvbiBpdHMgb3duIChgc2V0SW1hZ2VzYCwgYHNldFZpZGVvc2AsIGBzZXRBdWRpb2AsXG4gICAgICogYHNldERvY3VtZW50c2AsIC4uLiBhbGwgZG8gYC5zb3J0KChhLCBiKSA9PiBhLmluZGV4IC0gYi5pbmRleClgKSwgc28gYGluZGV4YCBvbmx5IGhhc1xuICAgICAqIHRvIGJlIGNvbnNpc3RlbnQgV0lUSElOIGEgQ29tbWVudFR5cGUuIFRoZSBhdHRhY2htZW50IGZvcm0gaG93ZXZlciBkZWZhdWx0cyBgaW5kZXhgXG4gICAgICogdG8gMSBmb3IgZXZlcnkgbmV3IGF0dGFjaG1lbnQsIHNvIGEgbXVsdGktaW1hZ2UgUE9JIHZlcnkgb2Z0ZW4gaG9sZHMgc2V2ZXJhbCBpbWFnZXNcbiAgICAgKiBhbGwgc2hhcmluZyBpbmRleCAxIOKAlCBvciBudWxsLiBTb3J0aW5nIHRob3NlIGlzIGxlZnQgdG8gRHluYW1vREIncyBhcmJpdHJhcnkgc2NhblxuICAgICAqIG9yZGVyLCB3aGljaCBpcyB3aHkgdGhlIGNvcHkgY2FtZSBvdXQgaW4gYSBkaWZmZXJlbnQgb3JkZXIgdGhhbiB0aGUgb3JpZ2luYWwuXG4gICAgICpcbiAgICAgKiBTdHJhdGVneTogc29ydCBkZXRlcm1pbmlzdGljYWxseSAoaW5kZXgsIHRoZW4gY3JlYXRpb24gZGF0ZSwgdGhlbiBpZCDigJQgaS5lLiB0aGVcbiAgICAgKiB1cGxvYWQgb3JkZXIgdGhlIHVzZXIgYWN0dWFsbHkgc2F3KSwgYW5kIG9ubHkgcmV3cml0ZSB0aGUgaW5kaWNlcyBvZiBhIGZhbWlseSB3aGVuXG4gICAgICogdGhleSBhcmUgYW1iaWd1b3VzIChudWxsIG9yIGR1cGxpY2F0ZWQpLiBBIGZhbWlseSB3aG9zZSBpbmRpY2VzIGFyZSBhbHJlYWR5IHVuaXF1ZVxuICAgICAqIGlzIGNvcGllZCB1bnRvdWNoZWQsIHNvIGEgZGVsaWJlcmF0ZSBvcmRlcmluZyBpcyBuZXZlciBvdmVyd3JpdHRlbi5cbiAgICAgKi9cbiAgICBwcml2YXRlIG9yZGVyQ29tbWVudHNGb3JDb3B5KGNvbW1lbnRzOiBDb21tZW50W10pOiBDb21tZW50W10ge1xuICAgICAgICBjb25zdCB2YWxpZCA9IChjb21tZW50cyB8fCBbXSkuZmlsdGVyKGMgPT4gISFjKTtcblxuICAgICAgICBjb25zdCBieVR5cGUgPSBuZXcgTWFwPHN0cmluZywgQ29tbWVudFtdPigpO1xuICAgICAgICBmb3IgKGNvbnN0IGNvbW1lbnQgb2YgdmFsaWQpIHtcbiAgICAgICAgICAgIGNvbnN0IGtleSA9IChjb21tZW50LnR5cGUgYXMgc3RyaW5nKSB8fCAnVU5UWVBFRCc7XG4gICAgICAgICAgICBpZiAoIWJ5VHlwZS5oYXMoa2V5KSkge1xuICAgICAgICAgICAgICAgIGJ5VHlwZS5zZXQoa2V5LCBbXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBieVR5cGUuZ2V0KGtleSkucHVzaChjb21tZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IG9yZGVyZWQ6IENvbW1lbnRbXSA9IFtdO1xuXG4gICAgICAgIGZvciAoY29uc3QgZmFtaWx5IG9mIGJ5VHlwZS52YWx1ZXMoKSkge1xuICAgICAgICAgICAgZmFtaWx5LnNvcnQoKGEsIGIpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBhaSA9IHRoaXMub3JkZXJpbmdJbmRleE9mKGEpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGJpID0gdGhpcy5vcmRlcmluZ0luZGV4T2YoYik7XG4gICAgICAgICAgICAgICAgaWYgKGFpICE9PSBiaSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYWkgLSBiaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3QgYWQgPSB0aGlzLmNyZWF0aW9uVGltZU9mKGEpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGJkID0gdGhpcy5jcmVhdGlvblRpbWVPZihiKTtcbiAgICAgICAgICAgICAgICBpZiAoYWQgIT09IGJkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhZCAtIGJkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKChhIGFzIGFueSkuaWQgfHwgJycpLmxvY2FsZUNvbXBhcmUoU3RyaW5nKChiIGFzIGFueSkuaWQgfHwgJycpKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBjb25zdCBpbmRpY2VzID0gZmFtaWx5Lm1hcChjID0+IGMuaW5kZXgpO1xuICAgICAgICAgICAgY29uc3QgaXNBbWJpZ3VvdXMgPSBpbmRpY2VzLnNvbWUoaSA9PiBpID09PSBudWxsIHx8IGkgPT09IHVuZGVmaW5lZClcbiAgICAgICAgICAgICAgICB8fCBuZXcgU2V0KGluZGljZXMpLnNpemUgIT09IGluZGljZXMubGVuZ3RoO1xuXG4gICAgICAgICAgICBmYW1pbHkuZm9yRWFjaCgoY29tbWVudCwgcG9zaXRpb24pID0+IHtcbiAgICAgICAgICAgICAgICAoY29tbWVudCBhcyBhbnkpLl9fY29weUluZGV4ID0gaXNBbWJpZ3VvdXMgPyBwb3NpdGlvbiArIDEgOiBjb21tZW50LmluZGV4O1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIG9yZGVyZWQucHVzaCguLi5mYW1pbHkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG9yZGVyZWQ7XG4gICAgfVxuXG4gICAgLyoqIFNvcnQga2V5IGZvciBhIGNvbW1lbnQncyBwb3NpdGlvbjsgYSBtaXNzaW5nIGluZGV4IHNvcnRzIGxhc3QsIG5vdCBmaXJzdC4gKi9cbiAgICBwcml2YXRlIG9yZGVyaW5nSW5kZXhPZihjb21tZW50OiBDb21tZW50KTogbnVtYmVyIHtcbiAgICAgICAgY29uc3QgaW5kZXggPSBjb21tZW50Py5pbmRleDtcbiAgICAgICAgcmV0dXJuIGluZGV4ID09PSBudWxsIHx8IGluZGV4ID09PSB1bmRlZmluZWQgfHwgTnVtYmVyLmlzTmFOKE51bWJlcihpbmRleCkpXG4gICAgICAgICAgICA/IE51bWJlci5NQVhfU0FGRV9JTlRFR0VSXG4gICAgICAgICAgICA6IE51bWJlcihpbmRleCk7XG4gICAgfVxuXG4gICAgLyoqIENyZWF0aW9uIHRpbWVzdGFtcCBvZiBhIGNvbW1lbnQsIHVzZWQgYXMgdGhlIHRpZS1icmVha2VyOiBpdCByZWZsZWN0cyB0aGUgb3JkZXIgaW5cbiAgICAgKiAgd2hpY2ggdGhlIHVzZXIgdXBsb2FkZWQgdGhlIG1lZGlhLCB3aGljaCBpcyB0aGUgb3JkZXIgdGhleSBzYXcuICovXG4gICAgcHJpdmF0ZSBjcmVhdGlvblRpbWVPZihjb21tZW50OiBDb21tZW50KTogbnVtYmVyIHtcbiAgICAgICAgY29uc3QgY3JlYXRlZEF0ID0gKGNvbW1lbnQgYXMgYW55KT8uY3JlYXRlZEF0O1xuICAgICAgICBpZiAoIWNyZWF0ZWRBdCkge1xuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdGltZSA9IG5ldyBEYXRlKGNyZWF0ZWRBdCkuZ2V0VGltZSgpO1xuICAgICAgICByZXR1cm4gTnVtYmVyLmlzTmFOKHRpbWUpID8gMCA6IHRpbWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29waWVzIE9ORSBtZWRpYSBpdGVtIChpbWFnZSwgdmlkZW8sIGF1ZGlvLCBkb2N1bWVudCwgdGV4dCwgbGluaywgZW1iZWQsIGlmcmFtZS4uLilcbiAgICAgKiBvZiBhIGZlYXR1cmUsIGR1cGxpY2F0aW5nIGl0cyBmaWxlIGluIFMzIGZpcnN0IHdoZW4gaXQgaGFzIG9uZS5cbiAgICAgKlxuICAgICAqIEV2ZXJ5IGNvbHVtbiBvZiB0aGUgQ29tbWVudCBtb2RlbCBpcyBjYXJyaWVkIG92ZXIuIGBkZXNjcmlwdGlvbmAgYW5kIGBtZXRhZGF0YWAgd2VyZVxuICAgICAqIHByZXZpb3VzbHkgZHJvcHBlZCwgd2hpY2ggZW1wdGllZCB0aGUgY2FwdGlvbnMgb2YgaW1hZ2VzL3ZpZGVvcywgdGhlIGJvZHkgb2YgVEVYVFxuICAgICAqIGl0ZW1zIOKAlCB3aGVyZSB0aGUgd2hvbGUgY29udGVudCBsaXZlcywgc2luY2UgYSBURVhUIGNvbW1lbnQgaGFzIG5vIGZpbGUg4oCUIGFuZCBhbnlcbiAgICAgKiBwZXItbWVkaWEgc2V0dGluZ3Mgc3RvcmVkIGluIG1ldGFkYXRhLlxuICAgICAqL1xuICAgIHByaXZhdGUgYXN5bmMgY29weUNvbW1lbnRGb3JGZWF0dXJlKFxuICAgICAgICBzb3VyY2VDb21tZW50OiBDb21tZW50LFxuICAgICAgICB0YXJnZXRGZWF0dXJlSWQ6IHN0cmluZyxcbiAgICAgICAgdGFyZ2V0U3BhY2VJZDogc3RyaW5nLFxuICAgICAgICB0YXJnZXRNaXNzaW9uSWQ6IHN0cmluZyB8IG51bGxcbiAgICApOiBQcm9taXNlPENvbW1lbnQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29weUNvbW1lbnQoc291cmNlQ29tbWVudCwgdGFyZ2V0U3BhY2VJZCwgdGFyZ2V0TWlzc2lvbklkLCB7IGZlYXR1cmVJRDogdGFyZ2V0RmVhdHVyZUlkIH0pO1xuICAgIH1cblxuICAgIC8qKiBTYW1lLCBmb3IgYW4gYXR0YWNobWVudCBjYXJyaWVkIGJ5IGEgdGlja2V0IHJhdGhlciB0aGFuIGJ5IGEgZmVhdHVyZS4gKi9cbiAgICBwcml2YXRlIGFzeW5jIGNvcHlDb21tZW50Rm9yVGlja2V0KFxuICAgICAgICBzb3VyY2VDb21tZW50OiBDb21tZW50LFxuICAgICAgICB0YXJnZXRUaWNrZXRJZDogc3RyaW5nLFxuICAgICAgICB0YXJnZXRTcGFjZUlkOiBzdHJpbmcsXG4gICAgICAgIHRhcmdldE1pc3Npb25JZDogc3RyaW5nIHwgbnVsbFxuICAgICk6IFByb21pc2U8Q29tbWVudD4ge1xuICAgICAgICByZXR1cm4gdGhpcy5jb3B5Q29tbWVudChzb3VyY2VDb21tZW50LCB0YXJnZXRTcGFjZUlkLCB0YXJnZXRNaXNzaW9uSWQsIHsgdGlja2V0SUQ6IHRhcmdldFRpY2tldElkIH0pO1xuICAgIH1cblxuICAgIC8qKiBTaGFyZWQgYm9keSBvZiB0aGUgdHdvIGFib3ZlOiBgb3duZXJgIGNhcnJpZXMgd2hpY2hldmVyIGZvcmVpZ24ga2V5IGxpbmtzIHRoZSBjb3B5IGJhY2tcbiAgICAgKiAgdG8gaXRzIG5ldyBwYXJlbnQsIGV2ZXJ5dGhpbmcgZWxzZSBpcyBpZGVudGljYWwuICovXG4gICAgcHJpdmF0ZSBhc3luYyBjb3B5Q29tbWVudChcbiAgICAgICAgc291cmNlQ29tbWVudDogQ29tbWVudCxcbiAgICAgICAgdGFyZ2V0U3BhY2VJZDogc3RyaW5nLFxuICAgICAgICB0YXJnZXRNaXNzaW9uSWQ6IHN0cmluZyB8IG51bGwsXG4gICAgICAgIG93bmVyOiB7IGZlYXR1cmVJRD86IHN0cmluZzsgdGlja2V0SUQ/OiBzdHJpbmcgfVxuICAgICk6IFByb21pc2U8Q29tbWVudD4ge1xuICAgICAgICBjb25zdCByYXdDb21tZW50ID0gc291cmNlQ29tbWVudCBhcyBhbnk7XG5cbiAgICAgICAgbGV0IGNvcGllZEFubmV4ZTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gICAgICAgIGlmIChyYXdDb21tZW50LmFubmV4ZSkge1xuICAgICAgICAgICAgY29waWVkQW5uZXhlID0gYXdhaXQgdGhpcy5jb3B5UzNLZXlJZlByZXNlbnQocmF3Q29tbWVudC5hbm5leGUsIGBhdHRhY2htZW50IFwiJHtyYXdDb21tZW50LnRpdGxlfVwiYCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjb21tZW50SW5wdXQ6IGFueSA9IHtcbiAgICAgICAgICAgIHRpdGxlOiByYXdDb21tZW50LnRpdGxlLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IHJhd0NvbW1lbnQuZGVzY3JpcHRpb24gPz8gbnVsbCxcbiAgICAgICAgICAgIG1ldGFkYXRhOiByYXdDb21tZW50Lm1ldGFkYXRhID8/IG51bGwsXG4gICAgICAgICAgICB0eXBlOiByYXdDb21tZW50LnR5cGUsXG4gICAgICAgICAgICBhbm5leGU6IGNvcGllZEFubmV4ZSxcbiAgICAgICAgICAgIGV4dGVybmFsTGluazogcmF3Q29tbWVudC5leHRlcm5hbExpbmsgfHwgbnVsbCxcbiAgICAgICAgICAgIGRpbWVuc2lvbnM6IHJhd0NvbW1lbnQuZGltZW5zaW9ucyB8fCBudWxsLFxuICAgICAgICAgICAgaW5kZXg6IHJhd0NvbW1lbnQuX19jb3B5SW5kZXggPz8gcmF3Q29tbWVudC5pbmRleCA/PyBudWxsLFxuICAgICAgICAgICAgc2hvd25JblRhZzogcmF3Q29tbWVudC5zaG93bkluVGFnLFxuICAgICAgICAgICAgaXNDb3ZlckltYWdlOiByYXdDb21tZW50LmlzQ292ZXJJbWFnZSxcbiAgICAgICAgICAgIHNwYWNlSUQ6IHRhcmdldFNwYWNlSWQsXG4gICAgICAgICAgICBvd25lcklEOiB0YXJnZXRNaXNzaW9uSWQsXG4gICAgICAgICAgICAuLi5vd25lclxuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiB0aGlzLmNvbW1lbnRTZXJ2aWNlLmNyZWF0ZUNvbW1lbnQoY29tbWVudElucHV0KTtcbiAgICB9XG5cbiAgICAvL1xuICAgIC8vIC0tLS0tLS0tLS0gUE9JIGNyZWF0aW9uIC0tLS0tLS0tLS1cbiAgICAvL1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyB0aGUgdGFyZ2V0LXNwYWNlIGNvcHkgb2YgYSBzb3VyY2UgUE9JLCB3aXRoIEVWRVJZIGNvbHVtbiBvZiB0aGUgUE9JIG1vZGVsLlxuICAgICAqXG4gICAgICogU2luZ2xlIGVudHJ5IHBvaW50IGZvciBhbGwgcGhhc2VzOiB0aGUgZWxlbWVudCBwaGFzZXMgKHRpY2tldCwgZXF1aXBtZW50LCAzRCBvYmplY3QsXG4gICAgICogZmVhdHVyZSwgbWVhc3VyZW1lbnQpIHVzZWQgdG8gYnVpbGQgdGhlaXIgUE9JIGlubGluZSB3aXRoIG9ubHkgNSBmaWVsZHMg4oCUIGNvb3JkaW5hdGUsXG4gICAgICogdHlwZSwgZWxlbWVudElELCBtZXRhZGF0YSwgc3dlZXAg4oCUIHdoaWNoIGlzIHByZWNpc2VseSBob3cgbXVzZXVtIFBPSXMgbG9zdCB0aGVpclxuICAgICAqIHBhc3RpbGxlOiBgdGFnRGVzY3JpcHRpb25gICh0aGUgcG9wdXAgdGV4dCksIGB0YWdJY29uYCAodGhlIGN1c3RvbSBpY29uKSBhbmRcbiAgICAgKiBgdGFnSW1hZ2VJRGAgKHRoZSBwYXN0aWxsZSdzIGltYWdlKSBuZXZlciBsZWZ0IHRoZSBzb3VyY2Ugc3BhY2UuXG4gICAgICovXG4gICAgcHJpdmF0ZSBhc3luYyBjcmVhdGVDb3BpZWRQb2koXG4gICAgICAgIHNvdXJjZVBvaTogUE9JLFxuICAgICAgICBlbGVtZW50SUQ6IHN0cmluZyB8IG51bGwsXG4gICAgICAgIHNvdXJjZU5hdlBvc2l0aW9uczogTWFwPHN0cmluZywgVmVjMz4sXG4gICAgICAgIHRhcmdldE5hdlBvc2l0aW9uczogTWFwPHN0cmluZywgVmVjMz4sXG4gICAgICAgIHRyYW5zZm9ybTogUmlnaWRUcmFuc2Zvcm1cbiAgICApOiBQcm9taXNlPFBPST4ge1xuICAgICAgICBjb25zdCByYXcgPSBzb3VyY2VQb2kgYXMgYW55O1xuXG4gICAgICAgIGNvbnN0IHRhcmdldFN3ZWVwSWQgPSB0aGlzLmZpbmRDbG9zZXN0VGFyZ2V0U3dlZXBJZChcbiAgICAgICAgICAgIHNvdXJjZVBvaS5tYXR0ZXJwb3J0U3dlZXBJRCwgc291cmNlTmF2UG9zaXRpb25zLCB0YXJnZXROYXZQb3NpdGlvbnMsIHRyYW5zZm9ybVxuICAgICAgICApO1xuICAgICAgICBjb25zdCBhZGp1c3RlZENvb3JkaW5hdGUgPSB0aGlzLmdldEFkanVzdGVkQ29vcmRpbmF0ZXMoc291cmNlUG9pLmNvb3JkaW5hdGUsIHRyYW5zZm9ybSk7XG5cbiAgICAgICAgY29uc3QgcG9pSW5wdXQ6IGFueSA9IHtcbiAgICAgICAgICAgIGNvb3JkaW5hdGU6IGFkanVzdGVkQ29vcmRpbmF0ZSA9PT0gbnVsbCB8fCBhZGp1c3RlZENvb3JkaW5hdGUgPT09IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgID8gbnVsbFxuICAgICAgICAgICAgICAgIDogSlNPTi5zdHJpbmdpZnkoYWRqdXN0ZWRDb29yZGluYXRlKSxcbiAgICAgICAgICAgIHR5cGU6IHNvdXJjZVBvaS50eXBlLFxuICAgICAgICAgICAgZWxlbWVudElEOiBlbGVtZW50SUQgPz8gbnVsbCxcbiAgICAgICAgICAgIG1hdHRlcnBvcnRTd2VlcElEOiB0YXJnZXRTd2VlcElkLFxuXG4gICAgICAgICAgICAvLyAtLS0gcGFzdGlsbGUgKHRhZyBwb3B1cCkgLS0tXG4gICAgICAgICAgICB0YWdEZXNjcmlwdGlvbjogc291cmNlUG9pLnRhZ0Rlc2NyaXB0aW9uID8/IG51bGwsXG4gICAgICAgICAgICB0YWdJY29uOiBhd2FpdCB0aGlzLmR1cGxpY2F0ZVRhZ0ljb24oc291cmNlUG9pLnRhZ0ljb24pLFxuICAgICAgICAgICAgdGFnSW1hZ2VJRDogdGhpcy5yZXNvbHZlVGFnSW1hZ2VJRChzb3VyY2VQb2kudGFnSW1hZ2VJRCksXG5cbiAgICAgICAgICAgIC8vIC0tLSByZW5kZXJpbmcgLyB2aXNpYmlsaXR5IGZsYWdzLCBjYXJyaWVkIG92ZXIgdmVyYmF0aW0gLS0tXG4gICAgICAgICAgICBzcGVjaWZpYzogcmF3LnNwZWNpZmljID8/IG51bGwsXG4gICAgICAgICAgICBwcml2YXRlOiByYXcucHJpdmF0ZSA/PyBudWxsLFxuICAgICAgICAgICAgZ2xvYmFsOiByYXcuZ2xvYmFsID8/IG51bGwsXG4gICAgICAgICAgICBsZXZlbDogcmF3LmxldmVsID8/IG51bGwsXG4gICAgICAgICAgICByb2xlOiByYXcucm9sZSA/PyBudWxsLFxuICAgICAgICAgICAgY2F0ZWdvcnk6IHJhdy5jYXRlZ29yeSA/PyBudWxsLFxuICAgICAgICAgICAgZG9tYWluSUQ6IHRoaXMuc2FtZU9yZ2FuaXNhdGlvbiA/IChyYXcuZG9tYWluSUQgfHwgbnVsbCkgOiBudWxsLFxuXG4gICAgICAgICAgICAvLyAtLS0gTWF0dGVycG9ydCBhbmNob3JpbmcgLS0tXG4gICAgICAgICAgICBtZXRhZGF0YTogdGhpcy5nZXRBZGp1c3RlZFBvaU1ldGFkYXRhKHNvdXJjZVBvaS5tZXRhZGF0YSwgdHJhbnNmb3JtKVxuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiB0aGlzLnBvaVNlcnZpY2UuY3JlYXRlUE9JRm9yU3BhY2VJRChwb2lJbnB1dCBhcyBQT0kpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkYXB0cyBhIFBPSSdzIGBtZXRhZGF0YWAgKHNlZSBNYXR0ZXJ0YWdEYXRhLmdldE1ldGFkYXRhU3RyaW5nKCk6IHsgaWNvbiwgbm9ybWFsLCBzaWQgfSlcbiAgICAgKiB0byB0aGUgdGFyZ2V0IHNwYWNlLlxuICAgICAqXG4gICAgICogIC0gYHNpZGAgaXMgdGhlIGlkIG9mIHRoZSBNYXR0ZXJ0YWcgaW5zaWRlIHRoZSBTT1VSQ0UgTWF0dGVycG9ydCBtb2RlbC4gQ2FycmllZCBvdmVyLFxuICAgICAqICAgIHRoZSB2aWV3ZXIgdHJpZXMgdG8gcmUtY3JlYXRlIHRoZSB0YXJnZXQncyB0YWcgd2l0aCBhbiBpZCBiZWxvbmdpbmcgdG8gYW5vdGhlclxuICAgICAqICAgIG1vZGVsIChcImFscmVhZHkgaW4gdXNlXCIpLCBzbyB0aGUgcGFzdGlsbGUgZmFpbHMgdG8gYXR0YWNoLiBJdCBpcyBkcm9wcGVkOiB0aGVcbiAgICAgKiAgICB2aWV3ZXIgdGhlbiBhbGxvY2F0ZXMgYSBmcmVzaCBzaWQgb24gZmlyc3QgcmVuZGVyLlxuICAgICAqICAtIGBub3JtYWxgIGlzIHRoZSBzdGVtIGRpcmVjdGlvbi4gSXQgaXMgYSBkaXJlY3Rpb24sIHNvIG9ubHkgdGhlIHJvdGF0aW9uIGFwcGxpZXNcbiAgICAgKiAgICAobmV2ZXIgdGhlIHRyYW5zbGF0aW9uKTsgd2l0aG91dCBpdCwgYSBjb3BpZWQgcGFzdGlsbGUgcG9pbnRzIGludG8gdGhlIHdhbGxcbiAgICAgKiAgICB3aGVuZXZlciB0aGUgdHdvIG1vZGVscyBhcmUgbm90IGFsaWduZWQgb24gdGhlIHNhbWUgYXhpcy5cbiAgICAgKiAgLSBgaWNvbmAgYW5kIGFueXRoaW5nIGVsc2UgaXMga2VwdCBhcy1pcy5cbiAgICAgKi9cbiAgICBwcml2YXRlIGdldEFkanVzdGVkUG9pTWV0YWRhdGEobWV0YWRhdGE6IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQsIHRyYW5zZm9ybTogUmlnaWRUcmFuc2Zvcm0pOiBzdHJpbmcgfCBudWxsIHtcbiAgICAgICAgaWYgKCFtZXRhZGF0YSkge1xuICAgICAgICAgICAgcmV0dXJuIG1ldGFkYXRhID8/IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2UobWV0YWRhdGEpO1xuICAgICAgICAgICAgaWYgKCFwYXJzZWQgfHwgdHlwZW9mIHBhcnNlZCAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbWV0YWRhdGE7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChwYXJzZWQubm9ybWFsXG4gICAgICAgICAgICAgICAgJiYgdHlwZW9mIHBhcnNlZC5ub3JtYWwgPT09ICdvYmplY3QnXG4gICAgICAgICAgICAgICAgJiYgdHlwZW9mIHBhcnNlZC5ub3JtYWwueCA9PT0gJ251bWJlcidcbiAgICAgICAgICAgICAgICAmJiB0eXBlb2YgcGFyc2VkLm5vcm1hbC55ID09PSAnbnVtYmVyJ1xuICAgICAgICAgICAgICAgICYmIHR5cGVvZiBwYXJzZWQubm9ybWFsLnogPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICAgICAgcGFyc2VkLm5vcm1hbCA9IGFwcGx5UmlnaWRUcmFuc2Zvcm1Ub0RpcmVjdGlvbihwYXJzZWQubm9ybWFsLCB0cmFuc2Zvcm0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkZWxldGUgcGFyc2VkLnNpZDtcblxuICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHBhcnNlZCk7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgLy8gTm90IEpTT04sIG9yIHVuZXhwZWN0ZWQgc2hhcGUg4oCUIGxlYXZlIHVudG91Y2hlZCByYXRoZXIgdGhhbiBndWVzcy5cbiAgICAgICAgICAgIHJldHVybiBtZXRhZGF0YTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc29sdmVzIGEgUE9JJ3MgYHRhZ0ltYWdlSURgIOKAlCB3aGljaCB0aGUgc2NoZW1hIGRvY3VtZW50cyBhcyBhIFwiY29ubmVjdGlvbiB0b1xuICAgICAqIGNvbW1lbnQuaWRcIiwgaS5lLiB0aGUgaWQgb2YgdGhlIENvbW1lbnQgaG9sZGluZyB0aGUgaW1hZ2Ugc2hvd24gaW4gdGhlIHBhc3RpbGxlLlxuICAgICAqXG4gICAgICogSXQgaXMgTk9UIGFuIFMzIGtleSwgc28gdGhlIHByZXZpb3VzIFwiZG9lcyBpdCBjb250YWluIGEgc2xhc2g/XCIgaGV1cmlzdGljIG5ldmVyXG4gICAgICogbWF0Y2hlZCBhbmQgdGhlIHZhbHVlIHRyYXZlbGxlZCB1bmNoYW5nZWQsIGxlYXZpbmcgZXZlcnkgY29waWVkIHBhc3RpbGxlIHBvaW50aW5nIGF0XG4gICAgICogYSBDb21tZW50IG9mIHRoZSBzb3VyY2Ugc3BhY2UuIEl0IGlzIG5vdyB0cmFuc2xhdGVkIHRocm91Z2ggdGhlIGNvbW1lbnQgaWQgbWFwIGJ1aWx0XG4gICAgICogd2hpbGUgZHVwbGljYXRpbmcgdGhlIG1lZGlhLCBhbmQgZHJvcHBlZCB3aGVuIGl0IGNhbm5vdCBiZSByZXNvbHZlZCAodGhlIHBhc3RpbGxlXG4gICAgICogdGhlbiBmYWxscyBiYWNrIHRvIHRoZSBmZWF0dXJlJ3MgY292ZXIgaW1hZ2UgaW5zdGVhZCBvZiBhIGJyb2tlbiByZWZlcmVuY2UpLlxuICAgICAqL1xuICAgIHByaXZhdGUgcmVzb2x2ZVRhZ0ltYWdlSUQodGFnSW1hZ2VJRDogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCk6IHN0cmluZyB8IG51bGwge1xuICAgICAgICBpZiAoIXRhZ0ltYWdlSUQpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmNvbW1lbnRJZHMuZ2V0KHRhZ0ltYWdlSUQpID8/IG51bGw7XG4gICAgfVxuXG4gICAgLy9cbiAgICAvLyAtLS0tLS0tLS0tIER1cGxpY2F0ZSBkZXRlY3Rpb24gLS0tLS0tLS0tLVxuICAgIC8vXG5cbiAgICAvKipcbiAgICAgKiBIZXVyaXN0aWMgZHVwbGljYXRlLWRldGVjdGlvbjogY29tcGFyZXMgc2V2ZXJhbCBpZGVudGlmeWluZyBmaWVsZHMgdG9nZXRoZXIgcmF0aGVyIHRoYW5cbiAgICAgKiBhIHNpbmdsZSBsYWJlbCwgdG8gcmVkdWNlIGZhbHNlIHBvc2l0aXZlcyB3aGVuIGl0ZW1zIHNoYXJlIG9uZSBvZiB0aGVtLlxuICAgICAqXG4gICAgICogVGhlIGZpZWxkcyBhcmUgc3VwcGxpZWQgYnkgdGhlIGNhbGxlciBiZWNhdXNlIHRoZSBtb2RlbHMgZG8gbm90IGFncmVlIG9uIHRoZW0uIFRoZVxuICAgICAqIHByZXZpb3VzIHZlcnNpb24gaGFyZC1jb2RlZCBgdGl0bGVgL2BkZXNjcmlwdGlvbmAsIHdoaWNoIGRvIG5vdCBleGlzdCBvbiBFcXVpcG1lbnQgYXRcbiAgICAgKiBhbGw6IGJvdGggc2lkZXMgcmVhZCBgdW5kZWZpbmVkYCwgZXZlcnkgZXF1aXBtZW50IHRoZXJlZm9yZSBcIm1hdGNoZWRcIiBldmVyeSBvdGhlciBvbmUsXG4gICAgICogYW5kIGEgdGFyZ2V0IHNwYWNlIGhvbGRpbmcgYSBzaW5nbGUgZXF1aXBtZW50IHNpbGVudGx5IGNhdXNlZCB0aGUgd2hvbGUgZXF1aXBtZW50IHBoYXNlXG4gICAgICogdG8gY29weSBub3RoaW5nLlxuICAgICAqL1xuICAgIHByaXZhdGUgbWF0Y2hlc0V4aXN0aW5nPFQ+KFxuICAgICAgICBzb3VyY2U6IFQsXG4gICAgICAgIHRhcmdldExpc3Q6IFRbXSxcbiAgICAgICAgaWRlbnRpdHk6IChpdGVtOiBUKSA9PiBBcnJheTxzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkPlxuICAgICk6IGJvb2xlYW4ge1xuICAgICAgICBjb25zdCBzb3VyY2VLZXkgPSB0aGlzLmlkZW50aXR5S2V5KGlkZW50aXR5KHNvdXJjZSkpO1xuICAgICAgICByZXR1cm4gdGFyZ2V0TGlzdC5zb21lKHRhcmdldCA9PiB0aGlzLmlkZW50aXR5S2V5KGlkZW50aXR5KHRhcmdldCkpID09PSBzb3VyY2VLZXkpO1xuICAgIH1cblxuICAgIC8qKiBTZXJpYWxpc2VzIHRoZSBpZGVudGlmeWluZyBmaWVsZHMgdW5hbWJpZ3VvdXNseSwgc28gdGhhdCBbXCJhXCIsIFwiYlwiXSBhbmQgW1wiYWJcIiwgXCJcIl1cbiAgICAgKiAgY2FuIG5ldmVyIHByb2R1Y2UgdGhlIHNhbWUga2V5LiAqL1xuICAgIHByaXZhdGUgaWRlbnRpdHlLZXkocGFydHM6IEFycmF5PHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQ+KTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHBhcnRzLm1hcChwYXJ0ID0+IHBhcnQgPz8gJycpKTtcbiAgICB9XG5cbiAgICAvL1xuICAgIC8vIC0tLS0tLS0tLS0gU3dlZXAgcG9zaXRpb25zIC8gcmlnaWQgdHJhbnNmb3JtIC0tLS0tLS0tLS1cbiAgICAvL1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgcG9zaXRpb24gb2YgZXZlcnkgc3dlZXAgaW4gYSBzcGFjZSBhbmQgcmV0dXJucyBpdCBhcyBhIE1hcCBmb3IgTygxKSBsb29rdXAuXG4gICAgICogVXNlcyBhbGxTZXR0bGVkIHNvIGEgc2luZ2xlIGZhaWxpbmcgc3dlZXAgbG9va3VwIGRvZXNuJ3QgYWJvcnQgdGhlIHdob2xlIG1hcCDigJRcbiAgICAgKiB0aGF0IHN3ZWVwIGlzIHNpbXBseSBhYnNlbnQgZnJvbSB0aGUgcmVzdWx0aW5nIG1hcCAoYW5kIHNraXBwZWQgbGF0ZXIpLlxuICAgICAqL1xuICAgIHByaXZhdGUgYXN5bmMgYnVpbGROYXZpZ2F0aW9uUG9zaXRpb25NYXAoc3BhY2VJZDogc3RyaW5nLCBzd2VlcElkczogc3RyaW5nW10pOiBQcm9taXNlPE1hcDxzdHJpbmcsIFZlYzM+PiB7XG4gICAgICAgIGNvbnN0IG1hcCA9IG5ldyBNYXA8c3RyaW5nLCBWZWMzPigpO1xuXG4gICAgICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoXG4gICAgICAgICAgICBzd2VlcElkcy5tYXAoYXN5bmMgKHNpZCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IG5hdnMgPSBhd2FpdCB0aGlzLm5hdmlnYXRpb25TZXJ2aWNlLmdldE5hdmlnYXRpb25zRm9yTWF0dGVycG9ydElERm9yU3BhY2Uoc2lkLCBzcGFjZUlkKTtcbiAgICAgICAgICAgICAgICBpZiAobmF2cyAmJiBuYXZzLmxlbmd0aCA+IDAgJiYgbmF2c1swXS5wb3NpdGlvbikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4geyBzaWQsIHBvc2l0aW9uOiBKU09OLnBhcnNlKG5hdnNbMF0ucG9zaXRpb24pIGFzIFZlYzMgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9KVxuICAgICAgICApO1xuXG4gICAgICAgIGZvciAoY29uc3QgcmVzdWx0IG9mIHJlc3VsdHMpIHtcbiAgICAgICAgICAgIGlmIChyZXN1bHQuc3RhdHVzID09PSAnZnVsZmlsbGVkJyAmJiByZXN1bHQudmFsdWUpIHtcbiAgICAgICAgICAgICAgICBtYXAuc2V0KHJlc3VsdC52YWx1ZS5zaWQsIHJlc3VsdC52YWx1ZS5wb3NpdGlvbik7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHJlc3VsdC5zdGF0dXMgPT09ICdyZWplY3RlZCcpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0ZhaWxlZCB0byBmZXRjaCBhIHN3ZWVwIHBvc2l0aW9uLCBza2lwcGluZyBpdDonLCByZXN1bHQucmVhc29uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBtYXA7XG4gICAgfVxuXG4gICAgLyoqIEFwcGxpZXMgdGhlIHJpZ2lkIHRyYW5zZm9ybSB0byBhIFBPSSBjb29yZGluYXRlIChwb3NpdGlvbiArIG9yaWVudGF0aW9uKS4gKi9cbiAgICBwcml2YXRlIGdldEFkanVzdGVkQ29vcmRpbmF0ZXMoY29vcmRpbmF0ZTogc3RyaW5nLCB0cmFuc2Zvcm06IFJpZ2lkVHJhbnNmb3JtKTogYW55IHtcbiAgICAgICAgaWYgKGNvb3JkaW5hdGUgPT09IFwibnVsbFwiKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWNvb3JkaW5hdGUgfHwgdHlwZW9mIGNvb3JkaW5hdGUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gY29vcmRpbmF0ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2UoY29vcmRpbmF0ZSk7XG4gICAgICAgIGNvbnN0IHJvdGF0ZWRQb3MgPSBhcHBseVJpZ2lkVHJhbnNmb3JtVG9Qb2ludChcbiAgICAgICAgICAgIHsgeDogcGFyc2VkLngsIHk6IHBhcnNlZC55LCB6OiBwYXJzZWQueiB9LFxuICAgICAgICAgICAgdHJhbnNmb3JtXG4gICAgICAgICk7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHg6IHJvdGF0ZWRQb3MueCxcbiAgICAgICAgICAgIHk6IHJvdGF0ZWRQb3MueSxcbiAgICAgICAgICAgIHo6IHJvdGF0ZWRQb3MueixcbiAgICAgICAgICAgIHhSb3RhdGlvbjogcGFyc2VkLnhSb3RhdGlvbixcbiAgICAgICAgICAgIHlSb3RhdGlvbjogYXBwbHlSaWdpZFRyYW5zZm9ybVRvWVJvdGF0aW9uRGVnKHBhcnNlZC55Um90YXRpb24sIHRyYW5zZm9ybSlcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBcHBsaWVzIHRoZSByaWdpZCB0cmFuc2Zvcm0ncyB0cmFuc2xhdGlvbityb3RhdGlvbiB0byBhIHBsYWluIHt4LHksen0gcG9zaXRpb24sXG4gICAgICogV0lUSE9VVCBhZGRpbmcgeFJvdGF0aW9uL3lSb3RhdGlvbiBrZXlzLiBVc2VkIGZvciBtZWFzdXJlbWVudHMsIHdob3NlIHN0b3JlZFxuICAgICAqIGNvb3JkaW5hdGUgaXMgYSBiYXJlIHBvc2l0aW9uIChubyBvcmllbnRhdGlvbiksIHVubGlrZSBvdGhlciBQT0kgdHlwZXMuXG4gICAgICovXG4gICAgcHJpdmF0ZSBnZXRBZGp1c3RlZFBvc2l0aW9uT25seShjb29yZGluYXRlOiBzdHJpbmcsIHRyYW5zZm9ybTogUmlnaWRUcmFuc2Zvcm0pOiBhbnkge1xuICAgICAgICBpZiAoIWNvb3JkaW5hdGUgfHwgdHlwZW9mIGNvb3JkaW5hdGUgIT09ICdzdHJpbmcnIHx8IGNvb3JkaW5hdGUgPT09ICdudWxsJykge1xuICAgICAgICAgICAgcmV0dXJuIGNvb3JkaW5hdGU7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZShjb29yZGluYXRlKTtcbiAgICAgICAgcmV0dXJuIGFwcGx5UmlnaWRUcmFuc2Zvcm1Ub1BvaW50KHsgeDogcGFyc2VkLngsIHk6IHBhcnNlZC55LCB6OiBwYXJzZWQueiB9LCB0cmFuc2Zvcm0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZpbmRzIHRoZSBjbG9zZXN0IHRhcmdldCBzd2VlcCwgY29tcGFyaW5nIHBvc2l0aW9ucyBpbiB0aGUgU0FNRSBjb29yZGluYXRlIGZyYW1lLlxuICAgICAqIFB1cmUgaW4tbWVtb3J5IGxvb2t1cCDigJQgbm8gbmV0d29yayBjYWxsLCB0aGFua3MgdG8gdGhlIHByZS1idWlsdCBwb3NpdGlvbiBtYXBzLlxuICAgICAqL1xuICAgIHByaXZhdGUgZmluZENsb3Nlc3RUYXJnZXRTd2VlcElkKFxuICAgICAgICBzb3VyY2VTd2VlcElEOiBzdHJpbmcsXG4gICAgICAgIHNvdXJjZU5hdlBvc2l0aW9uczogTWFwPHN0cmluZywgVmVjMz4sXG4gICAgICAgIHRhcmdldE5hdlBvc2l0aW9uczogTWFwPHN0cmluZywgVmVjMz4sXG4gICAgICAgIHRyYW5zZm9ybTogUmlnaWRUcmFuc2Zvcm1cbiAgICApOiBzdHJpbmcgfCBudWxsIHtcbiAgICAgICAgaWYgKCFzb3VyY2VTd2VlcElEKSByZXR1cm4gbnVsbDtcblxuICAgICAgICBjb25zdCBzb3VyY2VQb3MgPSBzb3VyY2VOYXZQb3NpdGlvbnMuZ2V0KHNvdXJjZVN3ZWVwSUQpO1xuICAgICAgICBpZiAoIXNvdXJjZVBvcykgcmV0dXJuIG51bGw7XG5cbiAgICAgICAgY29uc3Qgc291cmNlUG9zSW5UYXJnZXRGcmFtZSA9IGFwcGx5UmlnaWRUcmFuc2Zvcm1Ub1BvaW50KHNvdXJjZVBvcywgdHJhbnNmb3JtKTtcblxuICAgICAgICBsZXQgY2xvc2VzdFN3ZWVwSUQ6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICAgICAgICBsZXQgbWluRGlzdGFuY2UgPSBJbmZpbml0eTtcblxuICAgICAgICBmb3IgKGNvbnN0IFt0YXJnZXRTd2VlcElkLCB0YXJnZXRQb3NdIG9mIHRhcmdldE5hdlBvc2l0aW9ucy5lbnRyaWVzKCkpIHtcbiAgICAgICAgICAgIGNvbnN0IGR4ID0gdGFyZ2V0UG9zLnggLSBzb3VyY2VQb3NJblRhcmdldEZyYW1lLng7XG4gICAgICAgICAgICBjb25zdCBkeSA9IHRhcmdldFBvcy55IC0gc291cmNlUG9zSW5UYXJnZXRGcmFtZS55O1xuICAgICAgICAgICAgY29uc3QgZHogPSB0YXJnZXRQb3MueiAtIHNvdXJjZVBvc0luVGFyZ2V0RnJhbWUuejtcbiAgICAgICAgICAgIGNvbnN0IGRpc3QgPSBNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkgKyBkeiAqIGR6KTtcblxuICAgICAgICAgICAgaWYgKGRpc3QgPCBtaW5EaXN0YW5jZSkge1xuICAgICAgICAgICAgICAgIG1pbkRpc3RhbmNlID0gZGlzdDtcbiAgICAgICAgICAgICAgICBjbG9zZXN0U3dlZXBJRCA9IHRhcmdldFN3ZWVwSWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY2xvc2VzdFN3ZWVwSUQ7XG4gICAgfVxuXG4gICAgLy9cbiAgICAvLyAtLS0tLS0tLS0tIFMzIGZpbGUgZHVwbGljYXRpb24gLS0tLS0tLS0tLVxuICAgIC8vXG5cbiAgICAvKiogR2VuZXJhdGVzIGEgc2hvcnQgcmFuZG9tIGlkLCB1c2VkIHRvIGdpdmUgZWFjaCBjb3BpZWQgUzMgZmlsZSBhIGZyZXNoLCBjb2xsaXNpb24tc2FmZSBrZXkuICovXG4gICAgcHJpdmF0ZSBnZW5lcmF0ZVNob3J0SWQoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIE1hdGgucmFuZG9tKCkudG9TdHJpbmcoMzYpLnNsaWNlKDIsIDEwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBCdWlsZHMgYSBuZXcgUzMga2V5IGZvciBhIGNvcGllZCBhdHRhY2htZW50IGFuZCBzYW5pdGl6ZXMgdGhlIGZpbGVuYW1lXG4gICAgICogdG8gcHJldmVudCBBV1MgQW1wbGlmeSBTaWduYXR1cmVEb2VzTm90TWF0Y2ggZXJyb3JzLlxuICAgICAqIGBmb2xkZXJPdmVycmlkZWAgcmUtaG9tZXMgdGhlIGNvcHkgaW50byBhbm90aGVyIHByZWZpeCDigJQgdXNlZCBmb3IgdGFnIGljb25zLCB3aGljaFxuICAgICAqIGFyZSBzdG9yZWQgcGVyIHNwYWNlIChgaWNvbnMtdGFncy88c3BhY2VJZD4vYCkgYW5kIG11c3QgZm9sbG93IHRoZSB0YXJnZXQgc3BhY2UuXG4gICAgICovXG4gICAgcHJpdmF0ZSBidWlsZENvcGllZEF0dGFjaG1lbnRLZXkoc291cmNlQW5uZXhlOiBzdHJpbmcsIGZvbGRlck92ZXJyaWRlOiBzdHJpbmcgfCBudWxsID0gbnVsbCk6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IGxhc3RTbGFzaCA9IHNvdXJjZUFubmV4ZS5sYXN0SW5kZXhPZignLycpO1xuICAgICAgICBjb25zdCBmb2xkZXIgPSBmb2xkZXJPdmVycmlkZSA/PyBzb3VyY2VBbm5leGUuc3Vic3RyaW5nKDAsIGxhc3RTbGFzaCArIDEpO1xuICAgICAgICBsZXQgZmlsZW5hbWUgPSBzb3VyY2VBbm5leGUuc3Vic3RyaW5nKGxhc3RTbGFzaCArIDEpO1xuXG4gICAgICAgIC8vIFN0cmlwIGEgbGVhZGluZyBcIjw4IGhleCBjaGFycz5fXCIgaWQgcHJlZml4IGlmIHByZXNlbnRcbiAgICAgICAgY29uc3QgcHJlZml4TWF0Y2ggPSBmaWxlbmFtZS5tYXRjaCgvXlswLTlhLWZBLUYtXXs4fV8oLispJC8pO1xuICAgICAgICBpZiAocHJlZml4TWF0Y2gpIHtcbiAgICAgICAgICAgIGZpbGVuYW1lID0gcHJlZml4TWF0Y2hbMV07XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTQU5JVElaQVRJT046IFJlcGxhY2Ugc3BhY2VzLCBwYXJlbnRoZXNlcywgYW5kIGFjY2VudHMgd2l0aCB1bmRlcnNjb3Jlc1xuICAgICAgICAvLyBDcnVjaWFsIHRvIHByZXZlbnQgQW1wbGlmeSdzIFN0b3JhZ2UuY29weSBmcm9tIGZhaWxpbmcgdGhlIHNpZ25hdHVyZSBjYWxjdWxhdGlvblxuICAgICAgICBmaWxlbmFtZSA9IGZpbGVuYW1lLnJlcGxhY2UoL1teYS16QS1aMC05LlxcLV9dL2csICdfJyk7XG5cbiAgICAgICAgY29uc3QgbmV3UHJlZml4ID0gYCR7dGhpcy5nZW5lcmF0ZVNob3J0SWQoKX1fYDtcbiAgICAgICAgcmV0dXJuIGAke2ZvbGRlcn0ke25ld1ByZWZpeH0ke2ZpbGVuYW1lfWA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRHVwbGljYXRlcyBhbiBTMyBvYmplY3QgaWYgYSBrZXkgaXMgcHJlc2VudC5cbiAgICAgKiAtIElmIHRoZSBzb3VyY2UgZmlsZSBpcyBnZW51aW5lbHkgbWlzc2luZyBmcm9tIFMzIChOb1N1Y2hLZXkgLyBvcnBoYW5lZCBEQiByZWZlcmVuY2UpLFxuICAgICAqICAgdGhyb3dzIGEgTWlzc2luZ1MzRmlsZUVycm9yIHNvIHRoZSBjYWxsZXIgY2FuIGxvZyBhIGNsZWFyLCBzcGVjaWZpYyBtZXNzYWdlIGFuZFxuICAgICAqICAgc2tpcCB0aGUgd2hvbGUgaXRlbSBlbnRpcmVseSwgcmF0aGVyIHRoYW4gY3JlYXRpbmcgYSByZWNvcmQgd2l0aCBhIGJyb2tlbiBmaWxlIGxpbmsuXG4gICAgICogLSBBbnkgb3RoZXIga2luZCBvZiBmYWlsdXJlIChwZXJtaXNzaW9ucywgbmV0d29yaywgZXRjLikgc3RpbGwgdGhyb3dzIGEgZ2VuZXJpYyBFcnJvci5cbiAgICAgKi9cbiAgICBwcml2YXRlIGFzeW5jIGNvcHlTM0tleUlmUHJlc2VudChcbiAgICAgICAga2V5OiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkLFxuICAgICAgICBjb250ZXh0TGFiZWw6IHN0cmluZyxcbiAgICAgICAgZm9sZGVyT3ZlcnJpZGU6IHN0cmluZyB8IG51bGwgPSBudWxsXG4gICAgKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiB7XG4gICAgICAgIGlmICgha2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzb3VyY2VLZXkgPSB0aGlzLmV4dHJhY3RTM0tleUZyb21WYWx1ZShrZXkpO1xuICAgICAgICBjb25zdCBkZXN0S2V5ID0gdGhpcy5idWlsZENvcGllZEF0dGFjaG1lbnRLZXkoc291cmNlS2V5LCBmb2xkZXJPdmVycmlkZSk7XG5cbiAgICAgICAgLy8gTG9nIHRoZSBzb3VyY2Uga2V5IHRvIGVuc3VyZSBpdCBtYXRjaGVzIHRoZSByZWFsIFMzIG9iamVjdCBwYXRoXG4gICAgICAgIGNvbnNvbGUubG9nKGBbREVCVUddIEF0dGVtcHRpbmcgUzMgY29weSBmcm9tIHNvdXJjZTogXCIke3NvdXJjZUtleX1cIiB0byBkZXN0OiBcIiR7ZGVzdEtleX1cImApO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBjb3BpZWQgPSBhd2FpdCBjb3B5RmlsZUluUzMoc291cmNlS2V5LCBkZXN0S2V5KTtcbiAgICAgICAgICAgIGlmICghY29waWVkKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IE1pc3NpbmdTM0ZpbGVFcnJvcihzb3VyY2VLZXksIGNvbnRleHRMYWJlbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY29waWVkO1xuICAgICAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc01pc3NpbmdTM0ZpbGUoZXJyb3IpKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBbTWF0dGVycG9ydFRhZ0NvcHlTZXJ2aWNlXSBPcnBoYW5lZCBTMyByZWZlcmVuY2UsIHNraXBwaW5nIGl0ZW06IFwiJHtzb3VyY2VLZXl9XCIgKCR7Y29udGV4dExhYmVsfSlgKTtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgTWlzc2luZ1MzRmlsZUVycm9yKHNvdXJjZUtleSwgY29udGV4dExhYmVsKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU3RvcmFnZS5jb3B5KCkgY2Fubm90IGhhbmRsZSBhIGtleSBob2xkaW5nIGEgc3BhY2UsIGFuIGFjY2VudCBvciBhIHBhcmVudGhlc2lzOlxuICAgICAgICAgICAgLy8gaXQgcHV0cyB0aGUga2V5IHVuZW5jb2RlZCBpbnRvIGB4LWFtei1jb3B5LXNvdXJjZWAsIHdoaWNoIHRoZW4gZGlzYWdyZWVzIHdpdGggdGhlXG4gICAgICAgICAgICAvLyBzaWduZWQgcmVxdWVzdC4gVGhvc2UgZmlsZXMgYXJlIHBlcmZlY3RseSByZWFkYWJsZSDigJQgb25seSB0aGF0IGhlYWRlciBpcyBicm9rZW4g4oCUXG4gICAgICAgICAgICAvLyBzbyBmYWxsIGJhY2sgdG8gZG93bmxvYWRpbmcgYW5kIHJlLXVwbG9hZGluZyB0aGVtLlxuICAgICAgICAgICAgaWYgKHRoaXMuaXNTaWduYXR1cmVNaXNtYXRjaChlcnJvcikpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYFtNYXR0ZXJwb3J0VGFnQ29weVNlcnZpY2VdIFN0b3JhZ2UuY29weSgpIHNpZ25hdHVyZSBtaXNtYXRjaCBvbiBcIiR7c291cmNlS2V5fVwiLCBmYWxsaW5nIGJhY2sgdG8gZG93bmxvYWQgKyByZS11cGxvYWQuYCk7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29waWVkID0gYXdhaXQgY29weUZpbGVJblMzVmlhRG93bmxvYWQoc291cmNlS2V5LCBkZXN0S2V5KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb3BpZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBNaXNzaW5nUzNGaWxlRXJyb3Ioc291cmNlS2V5LCBjb250ZXh0TGFiZWwpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjb3BpZWQ7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZmFsbGJhY2tFcnJvcjogYW55KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzTWlzc2luZ1MzRmlsZShmYWxsYmFja0Vycm9yKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IE1pc3NpbmdTM0ZpbGVFcnJvcihzb3VyY2VLZXksIGNvbnRleHRMYWJlbCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgZmFsbGJhY2tFcnJvcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIFRydWUgd2hlbiB0aGUgZmFpbHVyZSBtZWFucyB0aGUgc291cmNlIG9iamVjdCBzaW1wbHkgaXMgbm90IG9uIFMzIChvcnBoYW5lZCByZWZlcmVuY2UpLiAqL1xuICAgIHByaXZhdGUgaXNNaXNzaW5nUzNGaWxlKGVycm9yOiBhbnkpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIGVycm9yIGluc3RhbmNlb2YgTWlzc2luZ1MzRmlsZUVycm9yXG4gICAgICAgICAgICB8fCBlcnJvcj8uY29kZSA9PT0gJ05vU3VjaEtleSdcbiAgICAgICAgICAgIHx8IGVycm9yPy5uYW1lID09PSAnTm9TdWNoS2V5J1xuICAgICAgICAgICAgfHwgL05vU3VjaEtleXxkb2VzIG5vdCBleGlzdHxOb3RGb3VuZC9pLnRlc3QodG9FcnJvck1lc3NhZ2UoZXJyb3IpKTtcbiAgICB9XG5cbiAgICAvKiogVHJ1ZSB3aGVuIEFwcFN5bmMgcmVmdXNlZCB0aGUgb3BlcmF0aW9uIGZvciBsYWNrIG9mIHBlcm1pc3Npb24sIGFzIG9wcG9zZWQgdG8gZmFpbGluZyBpdC5cbiAgICAgKiAgTm90aGluZyBjYW4gYmUgcmV0cmllZCBvciB3b3JrZWQgYXJvdW5kIGNsaWVudC1zaWRlOiB0aGUgYWNjb3VudCBzaW1wbHkgaXMgbm90IGFsbG93ZWRcbiAgICAgKiAgdG8gd3JpdGUgdGhhdCBtb2RlbCwgd2hpY2ggaXMgYSBiYWNrZW5kIGF1dGhvcmlzYXRpb24gcnVsZSAoQGF1dGgpIHRvIGNoYW5nZS4gKi9cbiAgICBwcml2YXRlIGlzVW5hdXRob3JpemVkKGVycm9yOiBhbnkpOiBib29sZWFuIHtcbiAgICAgICAgY29uc3QgbWVzc2FnZSA9IHRvRXJyb3JNZXNzYWdlKGVycm9yKTtcbiAgICAgICAgcmV0dXJuIGVycm9yPy5lcnJvclR5cGUgPT09ICdVbmF1dGhvcml6ZWQnXG4gICAgICAgICAgICB8fCAvVW5hdXRob3JpemVkfE5vdCBBdXRob3JpemVkIHRvIGFjY2Vzcy9pLnRlc3QobWVzc2FnZSk7XG4gICAgfVxuXG4gICAgLyoqIFRydWUgZm9yIHRoZSBTaWdWNCBtaXNtYXRjaCBTdG9yYWdlLmNvcHkoKSByYWlzZXMgb24ga2V5cyB3aXRoIHNwZWNpYWwgY2hhcmFjdGVycy4gKi9cbiAgICBwcml2YXRlIGlzU2lnbmF0dXJlTWlzbWF0Y2goZXJyb3I6IGFueSk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gZXJyb3I/LmNvZGUgPT09ICdTaWduYXR1cmVEb2VzTm90TWF0Y2gnXG4gICAgICAgICAgICB8fCBlcnJvcj8ubmFtZSA9PT0gJ1NpZ25hdHVyZURvZXNOb3RNYXRjaCdcbiAgICAgICAgICAgIHx8IC9zaWduYXR1cmUgd2UgY2FsY3VsYXRlZCBkb2VzIG5vdCBtYXRjaHxTaWduYXR1cmVEb2VzTm90TWF0Y2gvaS50ZXN0KHRvRXJyb3JNZXNzYWdlKGVycm9yKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRHVwbGljYXRlcyB0aGUgZmlsZSByZWZlcmVuY2VkIGJ5IGEgUE9JJ3MgdGFnSWNvbiAoYSBKU09OIHN0cmluZyBzaGFwZWQgbGlrZVxuICAgICAqIHsgc3JjLCBvcGFjaXR5IH0sIHBlciBmb3JtLWZlYXR1cmUuY29tcG9uZW50LnRzKS5cbiAgICAgKlxuICAgICAqIFR3byBiZWhhdmlvdXJzIG1hdHRlciBoZXJlOlxuICAgICAqICAtIHRoZSBjb3B5IGlzIHJlLWhvbWVkIHVuZGVyIHRoZSBUQVJHRVQgc3BhY2UncyBpY29uIGZvbGRlclxuICAgICAqICAgIChgaWNvbnMtdGFncy88dGFyZ2V0U3BhY2VJZD4vYCwgdGhlIGxheW91dCBmb3JtLWZlYXR1cmUuY29tcG9uZW50LnRzIHVwbG9hZHMgdG8pLlxuICAgICAqICAgIEtlZXBpbmcgdGhlIHNvdXJjZSBmb2xkZXIgcHJvZHVjZWQgYSB0YXJnZXQgc3BhY2Ugd2hvc2UgaWNvbnMgYWxsIGxpdmVkIHVuZGVyXG4gICAgICogICAgYW5vdGhlciBzcGFjZSdzIHByZWZpeCwgc28gY2xlYW5pbmcgdXAgdGhlIHNvdXJjZSBzcGFjZSBicm9rZSB0aGUgY29weSdzIGljb25zLlxuICAgICAqICAtIGEgbWlzc2luZyBpY29uIGZpbGUgaXMgTk9UIGZhdGFsLiBJdCB1c2VkIHRvIGJ1YmJsZSB1cCBhcyBhIE1pc3NpbmdTM0ZpbGVFcnJvciBhbmRcbiAgICAgKiAgICBhYm9ydCB0aGUgd2hvbGUgUE9JIOKAlCBsb3NpbmcgdGhlIHBhc3RpbGxlLCBpdHMgdGV4dCBhbmQgaXRzIG1lZGlhIGJlY2F1c2Ugb2YgYVxuICAgICAqICAgIGRlY29yYXRpdmUgZmlsZS4gVGhlIFBPSSBpcyBub3cgY3JlYXRlZCB3aXRoIHRoZSBpY29uIHJlZmVyZW5jZSBkcm9wcGVkLCB3aGljaFxuICAgICAqICAgIHJlbmRlcnMgdGhlIG1vZHVsZSdzIGRlZmF1bHQgaWNvbiwgYW5kIGEgbG9nIGxpbmUgcmVwb3J0cyBpdC5cbiAgICAgKi9cbiAgICBwcml2YXRlIGFzeW5jIGR1cGxpY2F0ZVRhZ0ljb24odGFnSWNvblJhdzogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCk6IFByb21pc2U8c3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZD4ge1xuICAgICAgICBpZiAoIXRhZ0ljb25SYXcpIHtcbiAgICAgICAgICAgIHJldHVybiB0YWdJY29uUmF3ID8/IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcGFyc2VkOiBhbnk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBwYXJzZWQgPSBKU09OLnBhcnNlKHRhZ0ljb25SYXcpO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIC8vIE5vdCBKU09OIOKAlCBsZWF2ZSB1bnRvdWNoZWQgcmF0aGVyIHRoYW4gZ3Vlc3MuXG4gICAgICAgICAgICByZXR1cm4gdGFnSWNvblJhdztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghcGFyc2VkIHx8IHR5cGVvZiBwYXJzZWQgIT09ICdvYmplY3QnIHx8ICFwYXJzZWQuc3JjKSB7XG4gICAgICAgICAgICByZXR1cm4gdGFnSWNvblJhdztcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBwYXJzZWQuc3JjID0gYXdhaXQgdGhpcy5jb3B5UzNLZXlJZlByZXNlbnQoXG4gICAgICAgICAgICAgICAgcGFyc2VkLnNyYywgJ3RhZyBpY29uJywgdGhpcy5idWlsZFRhcmdldEljb25Gb2xkZXIoKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoaWNvbkVycm9yKSB7XG4gICAgICAgICAgICBpZiAoIShpY29uRXJyb3IgaW5zdGFuY2VvZiBNaXNzaW5nUzNGaWxlRXJyb3IpKSB7XG4gICAgICAgICAgICAgICAgLy8gQSByZWFsIGZhaWx1cmUgKHBlcm1pc3Npb25zLCBuZXR3b3JrLCAuLi4pIHN0aWxsIGFib3J0cyB0aGUgUE9JOiBpdCBtZWFuc1xuICAgICAgICAgICAgICAgIC8vIHRoZSBjb3B5IGNhbm5vdCBiZSB0cnVzdGVkLCB1bmxpa2UgYSBmaWxlIHRoYXQgaXMgc2ltcGx5IGFscmVhZHkgZ29uZS5cbiAgICAgICAgICAgICAgICB0aHJvdyBpY29uRXJyb3I7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oYFtNYXR0ZXJwb3J0VGFnQ29weVNlcnZpY2VdIFRhZyBpY29uIG1pc3Npbmcgb24gUzMsIGZhbGxpbmcgYmFjayB0byB0aGUgZGVmYXVsdCBpY29uOiBcIiR7aWNvbkVycm9yLnNvdXJjZUtleX1cImApO1xuICAgICAgICAgICAgdGhpcy5sb2dJdGVtRXJyb3IoJ3dhcm5pbmdUYWdJY29uTWlzc2luZycsIHsgZmlsZTogaWNvbkVycm9yLnNvdXJjZUtleSB9KTtcbiAgICAgICAgICAgIGRlbGV0ZSBwYXJzZWQuc3JjO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHBhcnNlZCk7XG4gICAgfVxuXG4gICAgLyoqIEljb24gZm9sZGVyIG9mIHRoZSBzcGFjZSBiZWluZyBjb3BpZWQgaW50bywgbWF0Y2hpbmcgd2hhdCB0aGUgZmVhdHVyZSBmb3JtIHVwbG9hZHMgdG8uICovXG4gICAgcHJpdmF0ZSBidWlsZFRhcmdldEljb25Gb2xkZXIoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgICAgIHJldHVybiB0aGlzLnRhcmdldFNwYWNlSWQgPyBgaWNvbnMtdGFncy8ke3RoaXMudGFyZ2V0U3BhY2VJZH0vYCA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXh0cmFjdHMgYW5kIG5vcm1hbGl6ZXMgdGhlIHJhdyBTMyBrZXkgZnJvbSBhIHN0b3JlZCB2YWx1ZSAod2hpY2ggbWF5IGJlIGEgZnVsbCBVUkxcbiAgICAgKiBvciBhbHJlYWR5IGEgcmF3IGtleSkuXG4gICAgICogSU1QT1JUQU5UOiB0aGlzIG11c3QgcmV0dXJuIHRoZSBSQVcgKGRlY29kZWQsIG5vbiBVUkwtZW5jb2RlZCkga2V5LiBBbXBsaWZ5J3NcbiAgICAgKiBTdG9yYWdlLmNvcHkoKSBhbHJlYWR5IGJ1aWxkcyBhbmQgZW5jb2RlcyB0aGUgJ3gtYW16LWNvcHktc291cmNlJyBoZWFkZXIgaW50ZXJuYWxseVxuICAgICAqIGZyb20gdGhlIGtleSB3ZSBnaXZlIGl0LiBQcmUtZW5jb2RpbmcgaXQgaGVyZSBjYXVzZWQgYSBkb3VibGUtZW5jb2RpbmcgYnVnIChlLmcuIGFcbiAgICAgKiBzcGFjZSBiZWNhbWUgXCIlMjUyMFwiIGluc3RlYWQgb2YgXCIlMjBcIiksIHNvIFN0b3JhZ2UuY29weSgpIGxvb2tlZCBmb3IgYSBrZXkgdGhhdCBuZXZlclxuICAgICAqIGV4aXN0ZWQgb24gUzMsIHJlc3VsdGluZyBpbiBhIE5vU3VjaEtleSBlcnJvci5cbiAgICAgKi9cbiAgICBwcml2YXRlIGV4dHJhY3RTM0tleUZyb21WYWx1ZSh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgaWYgKCF2YWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGV4dHJhY3RlZCA9IHZhbHVlO1xuXG4gICAgICAgIC8vIDEuIEV4dHJhY3QgcGF0aCBmcm9tIFVSTCBhbmQgZHJvcCBxdWVyeSBwYXJhbXNcbiAgICAgICAgaWYgKHZhbHVlLnN0YXJ0c1dpdGgoJ2h0dHA6Ly8nKSB8fCB2YWx1ZS5zdGFydHNXaXRoKCdodHRwczovLycpKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwodmFsdWUpO1xuICAgICAgICAgICAgICAgIGV4dHJhY3RlZCA9IGRlY29kZVVSSUNvbXBvbmVudCh1cmwucGF0aG5hbWUpO1xuICAgICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAgICAgZXh0cmFjdGVkID0gdmFsdWUuc3BsaXQoJz8nKVswXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGV4dHJhY3RlZCA9IHZhbHVlLnNwbGl0KCc/JylbMF07XG4gICAgICAgIH1cblxuICAgICAgICAvLyAyLiBSZW1vdmUgbGVhZGluZyBzbGFzaFxuICAgICAgICBpZiAoZXh0cmFjdGVkLnN0YXJ0c1dpdGgoJy8nKSkge1xuICAgICAgICAgICAgZXh0cmFjdGVkID0gZXh0cmFjdGVkLnN1YnN0cmluZygxKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIDMuIFJlbW92ZSAncHVibGljLycgcHJlZml4XG4gICAgICAgIC8vIEFtcGxpZnkgcHJlcGVuZHMgdGhpcyBhdXRvbWF0aWNhbGx5OyB3ZSBtdXN0IHN0cmlwIGl0IGZyb20gdGhlIGlucHV0XG4gICAgICAgIC8vIHRvIGF2b2lkIHRoZSAncHVibGljL3B1YmxpYy8nIGRvdWJsZS1wcmVmaXggaXNzdWUuXG4gICAgICAgIGlmIChleHRyYWN0ZWQuc3RhcnRzV2l0aCgncHVibGljLycpKSB7XG4gICAgICAgICAgICBleHRyYWN0ZWQgPSBleHRyYWN0ZWQuc3Vic3RyaW5nKCdwdWJsaWMvJy5sZW5ndGgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmV0dXJuIHRoZSByYXcga2V5IGFzLWlzIOKAlCBTdG9yYWdlLmNvcHkoKSB0YWtlcyBjYXJlIG9mIHByb3Blcmx5IGVuY29kaW5nIGl0XG4gICAgICAgIC8vIGZvciB0aGUgQ29weVNvdXJjZSBoZWFkZXIuIERvIE5PVCByZS1lbmNvZGUgaXQgaGVyZS5cbiAgICAgICAgcmV0dXJuIGV4dHJhY3RlZDtcbiAgICB9XG59Il19