velocious 1.0.580 → 1.0.581

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +1 -0
  2. package/build/cli/command-arguments.js +45 -0
  3. package/build/cli/index.js +10 -0
  4. package/build/configuration-types.js +1 -0
  5. package/build/database/generation-context.js +121 -0
  6. package/build/database/initializer-from-require-context.js +7 -0
  7. package/build/environment-handlers/node/cli/commands/db/schema/dump.js +25 -0
  8. package/build/environment-handlers/node/cli/commands/db/schema/load.js +37 -8
  9. package/build/environment-handlers/node/cli/commands/generate/base-models.js +82 -13
  10. package/build/src/cli/command-arguments.d.ts +27 -0
  11. package/build/src/cli/command-arguments.d.ts.map +1 -0
  12. package/build/src/cli/command-arguments.js +38 -0
  13. package/build/src/cli/index.d.ts.map +1 -1
  14. package/build/src/cli/index.js +9 -1
  15. package/build/src/configuration-types.d.ts +8 -0
  16. package/build/src/configuration-types.d.ts.map +1 -1
  17. package/build/src/configuration-types.js +2 -1
  18. package/build/src/database/generation-context.d.ts +62 -0
  19. package/build/src/database/generation-context.d.ts.map +1 -0
  20. package/build/src/database/generation-context.js +102 -0
  21. package/build/src/database/initializer-from-require-context.d.ts.map +1 -1
  22. package/build/src/database/initializer-from-require-context.js +6 -1
  23. package/build/src/environment-handlers/node/cli/commands/db/schema/dump.d.ts.map +1 -1
  24. package/build/src/environment-handlers/node/cli/commands/db/schema/dump.js +22 -1
  25. package/build/src/environment-handlers/node/cli/commands/db/schema/load.d.ts +11 -0
  26. package/build/src/environment-handlers/node/cli/commands/db/schema/load.d.ts.map +1 -1
  27. package/build/src/environment-handlers/node/cli/commands/db/schema/load.js +33 -7
  28. package/build/src/environment-handlers/node/cli/commands/generate/base-models.d.ts +14 -0
  29. package/build/src/environment-handlers/node/cli/commands/generate/base-models.d.ts.map +1 -1
  30. package/build/src/environment-handlers/node/cli/commands/generate/base-models.js +371 -308
  31. package/build/tsconfig.tsbuildinfo +1 -1
  32. package/package.json +1 -1
  33. package/src/cli/command-arguments.js +45 -0
  34. package/src/cli/index.js +10 -0
  35. package/src/configuration-types.js +1 -0
  36. package/src/database/generation-context.js +121 -0
  37. package/src/database/initializer-from-require-context.js +7 -0
  38. package/src/environment-handlers/node/cli/commands/db/schema/dump.js +25 -0
  39. package/src/environment-handlers/node/cli/commands/db/schema/load.js +37 -8
  40. package/src/environment-handlers/node/cli/commands/generate/base-models.js +82 -13
@@ -1,5 +1,7 @@
1
1
  // @ts-check
2
2
  import BaseCommand from "../../../../../cli/base-command.js";
3
+ import commandArguments from "../../../../../cli/command-arguments.js";
4
+ import DatabaseGenerationContext from "../../../../../database/generation-context.js";
3
5
  import deburrColumnName from "../../../../../utils/deburr-column-name.js";
4
6
  import fileExists from "../../../../../utils/file-exists.js";
5
7
  import fs from "fs/promises";
@@ -56,13 +58,60 @@ function generatedRelationshipMethod({ abstract = false, body, name, param, retu
56
58
  }
57
59
  export default class DbGenerateModel extends BaseCommand {
58
60
  async execute() {
61
+ const parsedArguments = commandArguments({
62
+ definition: {
63
+ booleanOptions: ["--allow-missing-tables"],
64
+ valueOptions: ["--tenant"]
65
+ },
66
+ processArgs: this.processArgs || []
67
+ });
68
+ const allowMissingTables = parsedArguments["allow-missing-tables"] === true;
69
+ const tenantDatabaseIdentifier = parsedArguments.tenant;
70
+ if (typeof tenantDatabaseIdentifier === "string") {
71
+ const context = await DatabaseGenerationContext.resolve({
72
+ configuration: this.getConfiguration(),
73
+ databaseIdentifier: tenantDatabaseIdentifier
74
+ });
75
+ const selectedModelClasses = Object.values(this.getConfiguration().getModelClasses()).filter((modelClass) => {
76
+ const databaseIdentifier = modelClass.getDatabaseIdentifier({
77
+ enforceTenantDatabaseScope: false,
78
+ tenant: context.tenant()
79
+ });
80
+ if (databaseIdentifier !== context.databaseIdentifier())
81
+ return false;
82
+ return modelClass.getDatabaseIdentifier({ tenant: context.tenant() }) === context.databaseIdentifier();
83
+ });
84
+ try {
85
+ return await context.run({ name: "Generate selected tenant base models", callback: async (connection) => {
86
+ await this.generateBaseModels({ allowMissingTables, connections: { [context.databaseIdentifier()]: connection }, context });
87
+ } });
88
+ }
89
+ finally {
90
+ for (const modelClass of selectedModelClasses)
91
+ modelClass.resetRecordMetadata();
92
+ }
93
+ }
59
94
  await this.getConfiguration().initializeModels();
60
- const enforceTenantDatabaseScopes = this.getConfiguration().getEnforceTenantDatabaseScopes();
95
+ return await this.getConfiguration().ensureConnections({ name: "Generate base models" }, async (connections) => {
96
+ await this.generateBaseModels({ allowMissingTables, connections });
97
+ });
98
+ }
99
+ /**
100
+ * Generates model bases from explicit connections.
101
+ * @param {object} args - Generation arguments.
102
+ * @param {boolean} args.allowMissingTables - Whether absent tables are skipped.
103
+ * @param {Record<string, import("../../../../../database/drivers/base.js").default>} args.connections - Connections keyed by logical identifier.
104
+ * @param {DatabaseGenerationContext} [args.context] - Selected tenant database context.
105
+ * @returns {Promise<void>} - Resolves after writing generated bases.
106
+ */
107
+ async generateBaseModels({ allowMissingTables, connections, context }) {
61
108
  const rootDirectory = this.directory();
62
109
  const modelsDir = `${rootDirectory}/src/models`;
63
110
  const baseModelsDir = `${rootDirectory}/src/model-bases`;
64
111
  const modelClasses = this.getConfiguration().getModelClasses();
65
- const allowMissingTables = Boolean(this.processArgs?.includes("--allow-missing-tables"));
112
+ const regenerateCommand = context
113
+ ? `${BASE_MODELS_REGENERATE_COMMAND} --tenant ${context.databaseIdentifier()}`
114
+ : BASE_MODELS_REGENERATE_COMMAND;
66
115
  let devMode = false;
67
116
  if (baseModelsDir.includes("/spec/dummy/src/model-bases")) {
68
117
  devMode = true;
@@ -70,324 +119,338 @@ export default class DbGenerateModel extends BaseCommand {
70
119
  if (!await fileExists(baseModelsDir)) {
71
120
  await fs.mkdir(baseModelsDir, { recursive: true });
72
121
  }
73
- this.getConfiguration().setEnforceTenantDatabaseScopes(false);
74
- try {
75
- await this.getConfiguration().ensureConnections({ name: "Generate base models" }, async () => {
76
- for (const modelClassName in modelClasses) {
77
- const modelClass = modelClasses[modelClassName];
78
- const table = await modelClass.connection().getTableByName(modelClass.tableName(), { throwError: !allowMissingTables });
79
- if (!table) {
80
- console.warn(`Skipping base model for '${modelClass.name}': table '${modelClass.tableName()}' was not found (--allow-missing-tables). Keeping any existing base model.`);
81
- continue;
82
- }
83
- const modelName = inflection.dasherize(modelClassName);
84
- const modelNameCamelized = inflection.camelize(modelName.replaceAll("-", "_"));
85
- const modelBaseFileName = `${inflection.dasherize(inflection.underscore(modelName))}.js`;
86
- const modelPath = `${baseModelsDir}/${modelBaseFileName}`;
87
- console.log(`create src/model-bases/${modelBaseFileName}`);
88
- const sourceModelFullFilePath = `${modelsDir}/${modelBaseFileName}`;
89
- let sourceModelFilePath;
90
- if (await fileExists(sourceModelFullFilePath)) {
91
- sourceModelFilePath = `../models/${modelBaseFileName}`;
92
- }
93
- else {
94
- sourceModelFilePath = "velocious/build/src/database/record/index.js";
95
- }
96
- let fileContent = generatedFileBanner(BASE_MODELS_REGENERATE_COMMAND);
97
- let velociousPath;
98
- if (devMode) {
99
- velociousPath = "../../../../src";
122
+ for (const modelClassName in modelClasses) {
123
+ const modelClass = modelClasses[modelClassName];
124
+ let databaseIdentifier;
125
+ if (context) {
126
+ databaseIdentifier = modelClass.getDatabaseIdentifier({
127
+ enforceTenantDatabaseScope: false,
128
+ tenant: context.tenant()
129
+ });
130
+ if (databaseIdentifier !== context.databaseIdentifier())
131
+ continue;
132
+ databaseIdentifier = modelClass.getDatabaseIdentifier({ tenant: context.tenant() });
133
+ }
134
+ else {
135
+ databaseIdentifier = modelClass.getConfiguredDatabaseIdentifier();
136
+ }
137
+ if (context && databaseIdentifier !== context.databaseIdentifier())
138
+ continue;
139
+ const connection = connections[databaseIdentifier];
140
+ // Default generation continues to ignore inactive tenant-only identifiers.
141
+ if (!connection)
142
+ continue;
143
+ if (context)
144
+ modelClass.resetRecordMetadata();
145
+ const table = await connection.getTableByName(modelClass.tableName(), { throwError: !allowMissingTables });
146
+ if (!table) {
147
+ console.warn(`Skipping base model for '${modelClass.name}': table '${modelClass.tableName()}' was not found (--allow-missing-tables). Keeping any existing base model.`);
148
+ continue;
149
+ }
150
+ await modelClass.ensureInitialized({ configuration: this.getConfiguration(), connection });
151
+ const modelName = inflection.dasherize(modelClassName);
152
+ const modelNameCamelized = inflection.camelize(modelName.replaceAll("-", "_"));
153
+ const modelBaseFileName = `${inflection.dasherize(inflection.underscore(modelName))}.js`;
154
+ const modelPath = `${baseModelsDir}/${modelBaseFileName}`;
155
+ console.log(`create src/model-bases/${modelBaseFileName}`);
156
+ const sourceModelFullFilePath = `${modelsDir}/${modelBaseFileName}`;
157
+ let sourceModelFilePath;
158
+ if (await fileExists(sourceModelFullFilePath)) {
159
+ sourceModelFilePath = `../models/${modelBaseFileName}`;
160
+ }
161
+ else {
162
+ sourceModelFilePath = "velocious/build/src/database/record/index.js";
163
+ }
164
+ let fileContent = generatedFileBanner(regenerateCommand);
165
+ let velociousPath;
166
+ if (devMode) {
167
+ velociousPath = "../../../../src";
168
+ }
169
+ else {
170
+ velociousPath = "velocious/build/src";
171
+ }
172
+ const columns = await table.getColumns();
173
+ const writeAttributeTypeName = `${modelNameCamelized}WriteAttributes`;
174
+ const belongsToWriteAttributes = await this.belongsToWriteAttributesForModel({ modelClass, modelsDir });
175
+ const nestedWriteAttributes = this.nestedWriteAttributesForModel({ modelClass });
176
+ fileContent += `import DatabaseRecord from "${velociousPath}/database/record/index.js"\n\n`;
177
+ fileContent += "/**\n";
178
+ fileContent += ` * Attributes accepted when creating or updating ${modelNameCamelized} records.\n`;
179
+ fileContent += ` * @typedef {object} ${writeAttributeTypeName}\n`;
180
+ for (const column of columns) {
181
+ const deburredColumnName = deburrColumnName(column.getName());
182
+ const camelizedColumnName = inflection.camelize(deburredColumnName, true);
183
+ const setterJsdocType = this.jsDocSetterTypeFromColumn(column, modelClass);
184
+ if (setterJsdocType) {
185
+ fileContent += ` * @property {${setterJsdocType}${column.getNull() ? " | null" : ""}} [${camelizedColumnName}] - Value for the ${camelizedColumnName} attribute.\n`;
186
+ }
187
+ }
188
+ for (const belongsToWriteAttribute of belongsToWriteAttributes) {
189
+ fileContent += ` * @property {${belongsToWriteAttribute.propertyType}} [${belongsToWriteAttribute.propertyName}] - Related ${belongsToWriteAttribute.relationshipName} record.\n`;
190
+ }
191
+ for (const nestedWriteAttribute of nestedWriteAttributes) {
192
+ fileContent += ` * @property {${nestedWriteAttribute.propertyType}} [${nestedWriteAttribute.propertyName}] - Nested ${nestedWriteAttribute.relationshipName} attributes.\n`;
193
+ }
194
+ fileContent += " */\n\n";
195
+ const hasManyRelationFilePath = `${velociousPath}/database/record/instance-relationships/has-many.js`;
196
+ fileContent += `/** @augments {DatabaseRecord<${writeAttributeTypeName}>} */\n`;
197
+ fileContent += `export default class ${modelNameCamelized}Base extends DatabaseRecord {\n`;
198
+ // --- getModelClass() override (fixes polymorphic typing in JS/JSDoc) ---
199
+ if (await fileExists(sourceModelFullFilePath)) {
200
+ // Model file exists (e.g. src/models/ticket.js) → return typeof Ticket
201
+ fileContent += ` /** @returns {typeof import("${sourceModelFilePath}").default} */\n`;
202
+ fileContent += " // @ts-ignore - override narrows return type for better IntelliSense in generated model bases\n";
203
+ fileContent += ` getModelClass() { return /** @type {typeof import("${sourceModelFilePath}").default} */ (this.constructor) }\n\n`;
204
+ }
205
+ else {
206
+ // No model file yet → fall back to typeof TicketBase
207
+ fileContent += ` /** @returns {typeof ${modelNameCamelized}Base} */\n`;
208
+ fileContent += " // @ts-ignore - override narrows return type for better IntelliSense in generated model bases\n";
209
+ fileContent += ` getModelClass() { return /** @type {typeof ${modelNameCamelized}Base} */ (this.constructor) }\n\n`;
210
+ }
211
+ let methodsCount = 0;
212
+ for (const column of columns) {
213
+ const deburredColumnName = deburrColumnName(column.getName());
214
+ const camelizedColumnName = inflection.camelize(deburredColumnName, true);
215
+ const camelizedColumnNameBigFirst = inflection.camelize(deburredColumnName);
216
+ const jsdocType = this.jsDocTypeFromColumn(column, modelClass);
217
+ if (methodsCount > 0) {
218
+ fileContent += "\n";
219
+ }
220
+ if (jsdocType) {
221
+ fileContent += ` /** @returns {${jsdocType}${column.getNull() ? " | null" : ""}} */\n`;
222
+ }
223
+ fileContent += ` ${camelizedColumnName}() { return this.readAttribute("${camelizedColumnName}") }\n\n`;
224
+ const setterJsdocType = this.jsDocSetterTypeFromColumn(column, modelClass);
225
+ if (setterJsdocType) {
226
+ fileContent += " /**\n";
227
+ fileContent += ` * @param {${setterJsdocType}${column.getNull() ? " | null" : ""}} newValue\n`;
228
+ fileContent += " * @returns {void}\n";
229
+ fileContent += " */\n";
230
+ }
231
+ fileContent += ` set${camelizedColumnNameBigFirst}(newValue) { return this._setColumnAttribute("${camelizedColumnName}", newValue) }\n\n`;
232
+ fileContent += " /** @returns {boolean} */\n";
233
+ fileContent += ` has${camelizedColumnNameBigFirst}() { return this._hasAttribute(this.${camelizedColumnName}()) }\n`;
234
+ methodsCount++;
235
+ }
236
+ if (Object.prototype.hasOwnProperty.call(modelClass, "_translations") && modelClass._translations && Object.keys(modelClass._translations).length > 0) {
237
+ const TranslationClass = modelClass.getTranslationClass();
238
+ const translationColumns = TranslationClass.getColumns();
239
+ for (const name in modelClass._translations) {
240
+ const nameUnderscore = inflection.underscore(name);
241
+ const column = translationColumns.find((translationColumn) => translationColumn.getName() === nameUnderscore);
242
+ let translationJsdocType;
243
+ if (column) {
244
+ translationJsdocType = this.jsDocTypeFromColumn(column, TranslationClass);
100
245
  }
101
- else {
102
- velociousPath = "velocious/build/src";
246
+ if (translationJsdocType && column) {
247
+ fileContent += `\n`;
248
+ fileContent += " /**\n";
249
+ fileContent += ` * @returns {${translationJsdocType}${column.getNull() ? " | null" : ""}}\n`;
250
+ fileContent += " */\n";
103
251
  }
104
- const columns = await table.getColumns();
105
- const writeAttributeTypeName = `${modelNameCamelized}WriteAttributes`;
106
- const belongsToWriteAttributes = await this.belongsToWriteAttributesForModel({ modelClass, modelsDir });
107
- const nestedWriteAttributes = this.nestedWriteAttributesForModel({ modelClass });
108
- fileContent += `import DatabaseRecord from "${velociousPath}/database/record/index.js"\n\n`;
109
- fileContent += "/**\n";
110
- fileContent += ` * Attributes accepted when creating or updating ${modelNameCamelized} records.\n`;
111
- fileContent += ` * @typedef {object} ${writeAttributeTypeName}\n`;
112
- for (const column of columns) {
113
- const deburredColumnName = deburrColumnName(column.getName());
114
- const camelizedColumnName = inflection.camelize(deburredColumnName, true);
115
- const setterJsdocType = this.jsDocSetterTypeFromColumn(column, modelClass);
116
- if (setterJsdocType) {
117
- fileContent += ` * @property {${setterJsdocType}${column.getNull() ? " | null" : ""}} [${camelizedColumnName}] - Value for the ${camelizedColumnName} attribute.\n`;
252
+ fileContent += ` ${name}() { return this._getTranslatedAttributeWithFallback("${name}", this._getConfiguration().getLocale()) ?? null }\n`;
253
+ methodsCount++;
254
+ const hasName = `has${inflection.camelize(name)}`;
255
+ const setterName = `set${inflection.camelize(name)}`;
256
+ const setterParamType = translationJsdocType || "?";
257
+ fileContent += `\n`;
258
+ fileContent += " /**\n";
259
+ fileContent += ` * @abstract\n`;
260
+ fileContent += ` * @returns {boolean}\n`;
261
+ fileContent += " */\n";
262
+ fileContent += ` ${hasName}() { throw new Error("${hasName} not implemented") }\n`;
263
+ methodsCount++;
264
+ fileContent += `\n`;
265
+ fileContent += " /**\n";
266
+ fileContent += ` * @param {${setterParamType}} newValue\n`;
267
+ fileContent += ` * @returns {void}\n`;
268
+ fileContent += " */\n";
269
+ fileContent += ` ${setterName}(newValue) { return this._setTranslatedAttribute("${name}", this._getConfiguration().getLocale(), newValue) }\n`;
270
+ methodsCount++;
271
+ for (const locale of this.getConfiguration().getLocales()) {
272
+ const localeMethodName = `${name}${inflection.camelize(locale)}`;
273
+ if (translationJsdocType && column) {
274
+ fileContent += `\n`;
275
+ fileContent += " /**\n";
276
+ fileContent += ` * @returns {${translationJsdocType}${column.getNull() ? " | null" : ""}}\n`;
277
+ fileContent += " */\n";
118
278
  }
279
+ fileContent += ` ${localeMethodName}() { return this._getTranslatedAttributeWithFallback("${name}", "${locale}") ?? null }\n`;
280
+ methodsCount++;
281
+ const localeSetterName = `${setterName}${inflection.camelize(locale)}`;
282
+ fileContent += `\n`;
283
+ fileContent += " /**\n";
284
+ fileContent += ` * @param {${setterParamType}} newValue\n`;
285
+ fileContent += ` * @returns {void}\n`;
286
+ fileContent += " */\n";
287
+ fileContent += ` ${localeSetterName}(newValue) { return this._setTranslatedAttribute("${name}", "${locale}", newValue) }\n`;
288
+ methodsCount++;
289
+ const localeHasName = `has${inflection.camelize(localeMethodName)}`;
290
+ fileContent += `\n`;
291
+ fileContent += " /**\n";
292
+ fileContent += ` * @abstract\n`;
293
+ fileContent += ` * @returns {boolean}\n`;
294
+ fileContent += " */\n";
295
+ fileContent += ` ${localeHasName}() { throw new Error("${localeHasName} not implemented") }\n`;
296
+ methodsCount++;
119
297
  }
120
- for (const belongsToWriteAttribute of belongsToWriteAttributes) {
121
- fileContent += ` * @property {${belongsToWriteAttribute.propertyType}} [${belongsToWriteAttribute.propertyName}] - Related ${belongsToWriteAttribute.relationshipName} record.\n`;
122
- }
123
- for (const nestedWriteAttribute of nestedWriteAttributes) {
124
- fileContent += ` * @property {${nestedWriteAttribute.propertyType}} [${nestedWriteAttribute.propertyName}] - Nested ${nestedWriteAttribute.relationshipName} attributes.\n`;
298
+ }
299
+ }
300
+ for (const relationship of modelClass.getRelationships()) {
301
+ let baseFilePath, baseFullFilePath, fileName, fullFilePath;
302
+ if (relationship.getPolymorphic()) {
303
+ fileName = "velocious/build/src/database/record/index.js";
304
+ }
305
+ else {
306
+ const targetModelClass = relationship.getTargetModelClass();
307
+ if (!targetModelClass)
308
+ throw new Error(`Relationship '${relationship.getRelationshipName()}' on '${modelClass.getModelName()}' has no target model class`);
309
+ fileName = inflection.dasherize(inflection.underscore(targetModelClass.getModelName()));
310
+ fullFilePath = `src/models/${fileName}.js`;
311
+ baseFilePath = `../model-bases/${fileName}.js`;
312
+ baseFullFilePath = `src/model-bases/${fileName}.js`;
313
+ }
314
+ if (methodsCount > 0) {
315
+ fileContent += "\n";
316
+ }
317
+ if (relationship.getType() == "belongsTo" || relationship.getType() == "hasOne") {
318
+ let modelFilePath;
319
+ if (fullFilePath && await fileExists(fullFilePath)) {
320
+ modelFilePath = `../models/${fileName}.js`;
125
321
  }
126
- fileContent += " */\n\n";
127
- const hasManyRelationFilePath = `${velociousPath}/database/record/instance-relationships/has-many.js`;
128
- fileContent += `/** @augments {DatabaseRecord<${writeAttributeTypeName}>} */\n`;
129
- fileContent += `export default class ${modelNameCamelized}Base extends DatabaseRecord {\n`;
130
- // --- getModelClass() override (fixes polymorphic typing in JS/JSDoc) ---
131
- if (await fileExists(sourceModelFullFilePath)) {
132
- // Model file exists (e.g. src/models/ticket.js) → return typeof Ticket
133
- fileContent += ` /** @returns {typeof import("${sourceModelFilePath}").default} */\n`;
134
- fileContent += " // @ts-ignore - override narrows return type for better IntelliSense in generated model bases\n";
135
- fileContent += ` getModelClass() { return /** @type {typeof import("${sourceModelFilePath}").default} */ (this.constructor) }\n\n`;
322
+ else if (baseFullFilePath && await fileExists(baseFullFilePath)) {
323
+ modelFilePath = baseFilePath;
136
324
  }
137
325
  else {
138
- // No model file yet → fall back to typeof TicketBase
139
- fileContent += ` /** @returns {typeof ${modelNameCamelized}Base} */\n`;
140
- fileContent += " // @ts-ignore - override narrows return type for better IntelliSense in generated model bases\n";
141
- fileContent += ` getModelClass() { return /** @type {typeof ${modelNameCamelized}Base} */ (this.constructor) }\n\n`;
326
+ modelFilePath = "velocious/build/src/database/record/index.js";
142
327
  }
143
- let methodsCount = 0;
144
- for (const column of columns) {
145
- const deburredColumnName = deburrColumnName(column.getName());
146
- const camelizedColumnName = inflection.camelize(deburredColumnName, true);
147
- const camelizedColumnNameBigFirst = inflection.camelize(deburredColumnName);
148
- const jsdocType = this.jsDocTypeFromColumn(column, modelClass);
149
- if (methodsCount > 0) {
150
- fileContent += "\n";
151
- }
152
- if (jsdocType) {
153
- fileContent += ` /** @returns {${jsdocType}${column.getNull() ? " | null" : ""}} */\n`;
154
- }
155
- fileContent += ` ${camelizedColumnName}() { return this.readAttribute("${camelizedColumnName}") }\n\n`;
156
- const setterJsdocType = this.jsDocSetterTypeFromColumn(column, modelClass);
157
- if (setterJsdocType) {
158
- fileContent += " /**\n";
159
- fileContent += ` * @param {${setterJsdocType}${column.getNull() ? " | null" : ""}} newValue\n`;
160
- fileContent += " * @returns {void}\n";
161
- fileContent += " */\n";
162
- }
163
- fileContent += ` set${camelizedColumnNameBigFirst}(newValue) { return this._setColumnAttribute("${camelizedColumnName}", newValue) }\n\n`;
164
- fileContent += " /** @returns {boolean} */\n";
165
- fileContent += ` has${camelizedColumnNameBigFirst}() { return this._hasAttribute(this.${camelizedColumnName}()) }\n`;
166
- methodsCount++;
328
+ fileContent += " /**\n";
329
+ fileContent += ` * @returns {import("${modelFilePath}").default}\n`;
330
+ fileContent += " */\n";
331
+ fileContent += ` ${relationship.getRelationshipName()}() { return /** @type {import("${modelFilePath}").default} */ (this.getRelationshipByName("${relationship.getRelationshipName()}").loaded()) }\n`;
332
+ fileContent += "\n";
333
+ fileContent += " /**\n";
334
+ fileContent += " * @abstract\n";
335
+ fileContent += " * @param {Record<string, ReturnType<typeof JSON.parse>>} [attributes]\n";
336
+ fileContent += ` * @returns {import("${modelFilePath}").default}\n`;
337
+ fileContent += " */\n";
338
+ fileContent += ` build${inflection.camelize(relationship.getRelationshipName())}(attributes) { void attributes; throw new Error("Not implemented") }\n`;
339
+ fileContent += "\n";
340
+ fileContent += " /**\n";
341
+ fileContent += " * @abstract\n";
342
+ fileContent += ` * @returns {Promise<import("${modelFilePath}").default | undefined>}\n`;
343
+ fileContent += " */\n";
344
+ fileContent += ` load${inflection.camelize(relationship.getRelationshipName())}() { throw new Error("Not implemented") }\n`;
345
+ fileContent += "\n";
346
+ fileContent += " /**\n";
347
+ fileContent += ` * @returns {Promise<import("${modelFilePath}").default | undefined>}\n`;
348
+ fileContent += " */\n";
349
+ fileContent += ` ${relationship.getRelationshipName()}OrLoad() { return /** @type {Promise<import("${modelFilePath}").default | undefined>} */ (this.relationshipOrLoad("${relationship.getRelationshipName()}")) }\n`;
350
+ fileContent += "\n";
351
+ fileContent += " /**\n";
352
+ fileContent += " * @abstract\n";
353
+ fileContent += ` * @param {import("${modelFilePath}").default} newModel\n`;
354
+ fileContent += ` * @returns {void}\n`;
355
+ fileContent += " */\n";
356
+ fileContent += ` set${inflection.camelize(relationship.getRelationshipName())}(newModel) { void newModel; throw new Error("Not implemented") }\n`;
357
+ }
358
+ else if (relationship.getType() == "hasMany") {
359
+ let recordImport;
360
+ if (fullFilePath && await fileExists(fullFilePath)) {
361
+ recordImport = `../models/${fileName}.js`;
167
362
  }
168
- if (Object.prototype.hasOwnProperty.call(modelClass, "_translations") && modelClass._translations && Object.keys(modelClass._translations).length > 0) {
169
- const TranslationClass = modelClass.getTranslationClass();
170
- const translationColumns = TranslationClass.getColumns();
171
- for (const name in modelClass._translations) {
172
- const nameUnderscore = inflection.underscore(name);
173
- const column = translationColumns.find((translationColumn) => translationColumn.getName() === nameUnderscore);
174
- let translationJsdocType;
175
- if (column) {
176
- translationJsdocType = this.jsDocTypeFromColumn(column, TranslationClass);
177
- }
178
- if (translationJsdocType && column) {
179
- fileContent += `\n`;
180
- fileContent += " /**\n";
181
- fileContent += ` * @returns {${translationJsdocType}${column.getNull() ? " | null" : ""}}\n`;
182
- fileContent += " */\n";
183
- }
184
- fileContent += ` ${name}() { return this._getTranslatedAttributeWithFallback("${name}", this._getConfiguration().getLocale()) ?? null }\n`;
185
- methodsCount++;
186
- const hasName = `has${inflection.camelize(name)}`;
187
- const setterName = `set${inflection.camelize(name)}`;
188
- const setterParamType = translationJsdocType || "?";
189
- fileContent += `\n`;
190
- fileContent += " /**\n";
191
- fileContent += ` * @abstract\n`;
192
- fileContent += ` * @returns {boolean}\n`;
193
- fileContent += " */\n";
194
- fileContent += ` ${hasName}() { throw new Error("${hasName} not implemented") }\n`;
195
- methodsCount++;
196
- fileContent += `\n`;
197
- fileContent += " /**\n";
198
- fileContent += ` * @param {${setterParamType}} newValue\n`;
199
- fileContent += ` * @returns {void}\n`;
200
- fileContent += " */\n";
201
- fileContent += ` ${setterName}(newValue) { return this._setTranslatedAttribute("${name}", this._getConfiguration().getLocale(), newValue) }\n`;
202
- methodsCount++;
203
- for (const locale of this.getConfiguration().getLocales()) {
204
- const localeMethodName = `${name}${inflection.camelize(locale)}`;
205
- if (translationJsdocType && column) {
206
- fileContent += `\n`;
207
- fileContent += " /**\n";
208
- fileContent += ` * @returns {${translationJsdocType}${column.getNull() ? " | null" : ""}}\n`;
209
- fileContent += " */\n";
210
- }
211
- fileContent += ` ${localeMethodName}() { return this._getTranslatedAttributeWithFallback("${name}", "${locale}") ?? null }\n`;
212
- methodsCount++;
213
- const localeSetterName = `${setterName}${inflection.camelize(locale)}`;
214
- fileContent += `\n`;
215
- fileContent += " /**\n";
216
- fileContent += ` * @param {${setterParamType}} newValue\n`;
217
- fileContent += ` * @returns {void}\n`;
218
- fileContent += " */\n";
219
- fileContent += ` ${localeSetterName}(newValue) { return this._setTranslatedAttribute("${name}", "${locale}", newValue) }\n`;
220
- methodsCount++;
221
- const localeHasName = `has${inflection.camelize(localeMethodName)}`;
222
- fileContent += `\n`;
223
- fileContent += " /**\n";
224
- fileContent += ` * @abstract\n`;
225
- fileContent += ` * @returns {boolean}\n`;
226
- fileContent += " */\n";
227
- fileContent += ` ${localeHasName}() { throw new Error("${localeHasName} not implemented") }\n`;
228
- methodsCount++;
229
- }
230
- }
363
+ else if (baseFullFilePath && await fileExists(baseFullFilePath)) {
364
+ recordImport = `../model-bases/${fileName}.js`;
231
365
  }
232
- for (const relationship of modelClass.getRelationships()) {
233
- let baseFilePath, baseFullFilePath, fileName, fullFilePath;
234
- if (relationship.getPolymorphic()) {
235
- fileName = "velocious/build/src/database/record/index.js";
236
- }
237
- else {
238
- const targetModelClass = relationship.getTargetModelClass();
239
- if (!targetModelClass)
240
- throw new Error(`Relationship '${relationship.getRelationshipName()}' on '${modelClass.getModelName()}' has no target model class`);
241
- fileName = inflection.dasherize(inflection.underscore(targetModelClass.getModelName()));
242
- fullFilePath = `src/models/${fileName}.js`;
243
- baseFilePath = `../model-bases/${fileName}.js`;
244
- baseFullFilePath = `src/model-bases/${fileName}.js`;
245
- }
246
- if (methodsCount > 0) {
247
- fileContent += "\n";
248
- }
249
- if (relationship.getType() == "belongsTo" || relationship.getType() == "hasOne") {
250
- let modelFilePath;
251
- if (fullFilePath && await fileExists(fullFilePath)) {
252
- modelFilePath = `../models/${fileName}.js`;
253
- }
254
- else if (baseFullFilePath && await fileExists(baseFullFilePath)) {
255
- modelFilePath = baseFilePath;
256
- }
257
- else {
258
- modelFilePath = "velocious/build/src/database/record/index.js";
259
- }
260
- fileContent += " /**\n";
261
- fileContent += ` * @returns {import("${modelFilePath}").default}\n`;
262
- fileContent += " */\n";
263
- fileContent += ` ${relationship.getRelationshipName()}() { return /** @type {import("${modelFilePath}").default} */ (this.getRelationshipByName("${relationship.getRelationshipName()}").loaded()) }\n`;
264
- fileContent += "\n";
265
- fileContent += " /**\n";
266
- fileContent += " * @abstract\n";
267
- fileContent += " * @param {Record<string, ReturnType<typeof JSON.parse>>} [attributes]\n";
268
- fileContent += ` * @returns {import("${modelFilePath}").default}\n`;
269
- fileContent += " */\n";
270
- fileContent += ` build${inflection.camelize(relationship.getRelationshipName())}(attributes) { void attributes; throw new Error("Not implemented") }\n`;
271
- fileContent += "\n";
272
- fileContent += " /**\n";
273
- fileContent += " * @abstract\n";
274
- fileContent += ` * @returns {Promise<import("${modelFilePath}").default | undefined>}\n`;
275
- fileContent += " */\n";
276
- fileContent += ` load${inflection.camelize(relationship.getRelationshipName())}() { throw new Error("Not implemented") }\n`;
277
- fileContent += "\n";
278
- fileContent += " /**\n";
279
- fileContent += ` * @returns {Promise<import("${modelFilePath}").default | undefined>}\n`;
280
- fileContent += " */\n";
281
- fileContent += ` ${relationship.getRelationshipName()}OrLoad() { return /** @type {Promise<import("${modelFilePath}").default | undefined>} */ (this.relationshipOrLoad("${relationship.getRelationshipName()}")) }\n`;
282
- fileContent += "\n";
283
- fileContent += " /**\n";
284
- fileContent += " * @abstract\n";
285
- fileContent += ` * @param {import("${modelFilePath}").default} newModel\n`;
286
- fileContent += ` * @returns {void}\n`;
287
- fileContent += " */\n";
288
- fileContent += ` set${inflection.camelize(relationship.getRelationshipName())}(newModel) { void newModel; throw new Error("Not implemented") }\n`;
289
- }
290
- else if (relationship.getType() == "hasMany") {
291
- let recordImport;
292
- if (fullFilePath && await fileExists(fullFilePath)) {
293
- recordImport = `../models/${fileName}.js`;
294
- }
295
- else if (baseFullFilePath && await fileExists(baseFullFilePath)) {
296
- recordImport = `../model-bases/${fileName}.js`;
297
- }
298
- else {
299
- recordImport = `${velociousPath}/database/record/index.js`;
300
- }
301
- fileContent += " /**\n";
302
- fileContent += ` * @returns {import("${hasManyRelationFilePath}").default<typeof import("${sourceModelFilePath}").default, typeof import("${recordImport}").default>}\n`;
303
- fileContent += " */\n";
304
- fileContent += ` ${relationship.getRelationshipName()}() { return /** @type {import("${hasManyRelationFilePath}").default<typeof import("${sourceModelFilePath}").default, typeof import("${recordImport}").default>} */ (this.getRelationshipByName("${relationship.getRelationshipName()}")) }\n`;
305
- fileContent += "\n";
306
- fileContent += " /**\n";
307
- fileContent += ` * @returns {Array<import("${recordImport}").default>}\n`;
308
- fileContent += " */\n";
309
- fileContent += ` ${relationship.getRelationshipName()}Loaded() { return /** @type {Array<import("${recordImport}").default>} */ (this.getRelationshipByName("${relationship.getRelationshipName()}").loaded()) }\n`;
310
- fileContent += "\n";
311
- fileContent += generatedRelationshipMethod({
312
- abstract: true,
313
- body: "throw new Error(\"Not implemented\")",
314
- name: `load${inflection.camelize(relationship.getRelationshipName())}`,
315
- returns: `Promise<Array<import("${recordImport}").default>>`
316
- });
317
- fileContent += "\n";
318
- fileContent += generatedRelationshipMethod({
319
- body: `return /** @type {Promise<Array<import("${recordImport}").default>>} */ (this.relationshipOrLoad("${relationship.getRelationshipName()}"))`,
320
- name: `${relationship.getRelationshipName()}OrLoad`,
321
- returns: `Promise<Array<import("${recordImport}").default>>`
322
- });
323
- fileContent += "\n";
324
- fileContent += " /**\n";
325
- fileContent += " * @abstract\n";
326
- fileContent += ` * @param {Array<import("${recordImport}").default>} newModels\n`;
327
- fileContent += " * @returns {void}\n";
328
- fileContent += " */\n";
329
- fileContent += ` set${inflection.camelize(relationship.getRelationshipName())}(newModels) { void newModels; throw new Error("Not implemented") }\n`;
330
- }
331
- else {
332
- throw new Error(`Unknown relationship type: ${relationship.getType()}`);
333
- }
334
- methodsCount++;
366
+ else {
367
+ recordImport = `${velociousPath}/database/record/index.js`;
335
368
  }
336
- // State-machine event methods. `Model.stateMachine(...)` registers these on the model's
337
- // own prototype at runtime; those override the stubs below (declared on the base class),
338
- // so these throwing stubs never execute. They exist only so call sites typecheck without
339
- // the consumer hand-writing boilerplate. Guarded on the own `_stateMachineDefinition`
340
- // property so a subclass without its own machine doesn't re-emit the parent's events.
341
- const stateMachineDefinition = Object.prototype.hasOwnProperty.call(modelClass, "_stateMachineDefinition")
342
- ? modelClass.getStateMachineDefinition()
343
- : null;
344
- if (stateMachineDefinition) {
345
- for (const eventName of Object.keys(stateMachineDefinition.events)) {
346
- // `stateMachine()` installs event methods with `proto[eventName]`, so it accepts
347
- // event keys that aren't valid JavaScript identifiers (e.g. "retry-build"). Those
348
- // can't be written as class methods without producing an unparseable file, so skip
349
- // them here — they still work at runtime via bracket access, just untyped.
350
- if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(eventName)) {
351
- console.warn(`Skipping generated state-machine methods for event '${eventName}' on '${modelClass.name}': the event name is not a valid JavaScript identifier.`);
352
- continue;
353
- }
354
- const capitalizedEvent = eventName.charAt(0).toUpperCase() + eventName.slice(1);
355
- if (methodsCount > 0) {
356
- fileContent += "\n";
357
- }
358
- fileContent += " /**\n";
359
- fileContent += " * @abstract\n";
360
- fileContent += " * @returns {void}\n";
361
- fileContent += " */\n";
362
- fileContent += ` ${eventName}() { throw new Error("Not implemented") }\n`;
363
- fileContent += "\n";
364
- fileContent += " /**\n";
365
- fileContent += " * @abstract\n";
366
- fileContent += " * @returns {Promise<void>}\n";
367
- fileContent += " */\n";
368
- fileContent += ` ${eventName}AndSave() { throw new Error("Not implemented") }\n`;
369
- fileContent += "\n";
370
- fileContent += " /**\n";
371
- fileContent += " * @abstract\n";
372
- fileContent += " * @returns {boolean}\n";
373
- fileContent += " */\n";
374
- fileContent += ` can${capitalizedEvent}() { throw new Error("Not implemented") }\n`;
375
- fileContent += "\n";
376
- fileContent += " /**\n";
377
- fileContent += " * @abstract\n";
378
- fileContent += " * @returns {Promise<boolean>}\n";
379
- fileContent += " */\n";
380
- fileContent += ` can${capitalizedEvent}Async() { throw new Error("Not implemented") }\n`;
381
- methodsCount++;
382
- }
369
+ fileContent += " /**\n";
370
+ fileContent += ` * @returns {import("${hasManyRelationFilePath}").default<typeof import("${sourceModelFilePath}").default, typeof import("${recordImport}").default>}\n`;
371
+ fileContent += " */\n";
372
+ fileContent += ` ${relationship.getRelationshipName()}() { return /** @type {import("${hasManyRelationFilePath}").default<typeof import("${sourceModelFilePath}").default, typeof import("${recordImport}").default>} */ (this.getRelationshipByName("${relationship.getRelationshipName()}")) }\n`;
373
+ fileContent += "\n";
374
+ fileContent += " /**\n";
375
+ fileContent += ` * @returns {Array<import("${recordImport}").default>}\n`;
376
+ fileContent += " */\n";
377
+ fileContent += ` ${relationship.getRelationshipName()}Loaded() { return /** @type {Array<import("${recordImport}").default>} */ (this.getRelationshipByName("${relationship.getRelationshipName()}").loaded()) }\n`;
378
+ fileContent += "\n";
379
+ fileContent += generatedRelationshipMethod({
380
+ abstract: true,
381
+ body: "throw new Error(\"Not implemented\")",
382
+ name: `load${inflection.camelize(relationship.getRelationshipName())}`,
383
+ returns: `Promise<Array<import("${recordImport}").default>>`
384
+ });
385
+ fileContent += "\n";
386
+ fileContent += generatedRelationshipMethod({
387
+ body: `return /** @type {Promise<Array<import("${recordImport}").default>>} */ (this.relationshipOrLoad("${relationship.getRelationshipName()}"))`,
388
+ name: `${relationship.getRelationshipName()}OrLoad`,
389
+ returns: `Promise<Array<import("${recordImport}").default>>`
390
+ });
391
+ fileContent += "\n";
392
+ fileContent += " /**\n";
393
+ fileContent += " * @abstract\n";
394
+ fileContent += ` * @param {Array<import("${recordImport}").default>} newModels\n`;
395
+ fileContent += " * @returns {void}\n";
396
+ fileContent += " */\n";
397
+ fileContent += ` set${inflection.camelize(relationship.getRelationshipName())}(newModels) { void newModels; throw new Error("Not implemented") }\n`;
398
+ }
399
+ else {
400
+ throw new Error(`Unknown relationship type: ${relationship.getType()}`);
401
+ }
402
+ methodsCount++;
403
+ }
404
+ // State-machine event methods. `Model.stateMachine(...)` registers these on the model's
405
+ // own prototype at runtime; those override the stubs below (declared on the base class),
406
+ // so these throwing stubs never execute. They exist only so call sites typecheck without
407
+ // the consumer hand-writing boilerplate. Guarded on the own `_stateMachineDefinition`
408
+ // property so a subclass without its own machine doesn't re-emit the parent's events.
409
+ const stateMachineDefinition = Object.prototype.hasOwnProperty.call(modelClass, "_stateMachineDefinition")
410
+ ? modelClass.getStateMachineDefinition()
411
+ : null;
412
+ if (stateMachineDefinition) {
413
+ for (const eventName of Object.keys(stateMachineDefinition.events)) {
414
+ // `stateMachine()` installs event methods with `proto[eventName]`, so it accepts
415
+ // event keys that aren't valid JavaScript identifiers (e.g. "retry-build"). Those
416
+ // can't be written as class methods without producing an unparseable file, so skip
417
+ // them here — they still work at runtime via bracket access, just untyped.
418
+ if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(eventName)) {
419
+ console.warn(`Skipping generated state-machine methods for event '${eventName}' on '${modelClass.name}': the event name is not a valid JavaScript identifier.`);
420
+ continue;
421
+ }
422
+ const capitalizedEvent = eventName.charAt(0).toUpperCase() + eventName.slice(1);
423
+ if (methodsCount > 0) {
424
+ fileContent += "\n";
383
425
  }
384
- fileContent += "}\n";
385
- await fs.writeFile(modelPath, fileContent);
426
+ fileContent += " /**\n";
427
+ fileContent += " * @abstract\n";
428
+ fileContent += " * @returns {void}\n";
429
+ fileContent += " */\n";
430
+ fileContent += ` ${eventName}() { throw new Error("Not implemented") }\n`;
431
+ fileContent += "\n";
432
+ fileContent += " /**\n";
433
+ fileContent += " * @abstract\n";
434
+ fileContent += " * @returns {Promise<void>}\n";
435
+ fileContent += " */\n";
436
+ fileContent += ` ${eventName}AndSave() { throw new Error("Not implemented") }\n`;
437
+ fileContent += "\n";
438
+ fileContent += " /**\n";
439
+ fileContent += " * @abstract\n";
440
+ fileContent += " * @returns {boolean}\n";
441
+ fileContent += " */\n";
442
+ fileContent += ` can${capitalizedEvent}() { throw new Error("Not implemented") }\n`;
443
+ fileContent += "\n";
444
+ fileContent += " /**\n";
445
+ fileContent += " * @abstract\n";
446
+ fileContent += " * @returns {Promise<boolean>}\n";
447
+ fileContent += " */\n";
448
+ fileContent += ` can${capitalizedEvent}Async() { throw new Error("Not implemented") }\n`;
449
+ methodsCount++;
386
450
  }
387
- });
388
- }
389
- finally {
390
- this.getConfiguration().setEnforceTenantDatabaseScopes(enforceTenantDatabaseScopes);
451
+ }
452
+ fileContent += "}\n";
453
+ await fs.writeFile(modelPath, fileContent);
391
454
  }
392
455
  }
393
456
  /**
@@ -473,4 +536,4 @@ export default class DbGenerateModel extends BaseCommand {
473
536
  return nestedWriteAttributes;
474
537
  }
475
538
  }
476
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1tb2RlbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvZW52aXJvbm1lbnQtaGFuZGxlcnMvbm9kZS9jbGkvY29tbWFuZHMvZ2VuZXJhdGUvYmFzZS1tb2RlbHMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sV0FBVyxNQUFNLG9DQUFvQyxDQUFBO0FBQzVELE9BQU8sZ0JBQWdCLE1BQU0sNENBQTRDLENBQUE7QUFDekUsT0FBTyxVQUFVLE1BQU0scUNBQXFDLENBQUE7QUFDNUQsT0FBTyxFQUFFLE1BQU0sYUFBYSxDQUFBO0FBQzVCLE9BQU8sbUJBQW1CLE1BQU0sNEJBQTRCLENBQUE7QUFDNUQsT0FBTyxLQUFLLFVBQVUsTUFBTSxZQUFZLENBQUE7QUFFeEMsTUFBTSw4QkFBOEIsR0FBRyxnQ0FBZ0MsQ0FBQTtBQUV2RTs7O0dBR0c7QUFDSCxNQUFNLHFCQUFxQixHQUFHO0lBQzVCLE1BQU0sRUFBRSxRQUFRO0lBQ2hCLEdBQUcsRUFBRSxRQUFRO0lBQ2IsSUFBSSxFQUFFLFFBQVE7SUFDZCxPQUFPLEVBQUUsU0FBUztJQUNsQixJQUFJLEVBQUUsUUFBUTtJQUNkLG1CQUFtQixFQUFFLFFBQVE7SUFDN0IsSUFBSSxFQUFFLE1BQU07SUFDWixRQUFRLEVBQUUsTUFBTTtJQUNoQixPQUFPLEVBQUUsUUFBUTtJQUNqQixLQUFLLEVBQUUsUUFBUTtJQUNmLEdBQUcsRUFBRSxRQUFRO0lBQ2IsT0FBTyxFQUFFLFFBQVE7SUFDakIsSUFBSSxFQUFFLHlCQUF5QjtJQUMvQixRQUFRLEVBQUUsUUFBUTtJQUNsQixVQUFVLEVBQUUsUUFBUTtJQUNwQixPQUFPLEVBQUUsUUFBUTtJQUNqQixRQUFRLEVBQUUsUUFBUTtJQUNsQixRQUFRLEVBQUUsUUFBUTtJQUNsQixJQUFJLEVBQUUsUUFBUTtJQUNkLDZCQUE2QixFQUFFLE1BQU07SUFDckMsT0FBTyxFQUFFLFFBQVE7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XCIuLi8uLi8uLi8uLi8uLi9jbGkvYmFzZS1jb21tYW5kLmpzXCJcbmltcG9ydCBkZWJ1cnJDb2x1bW5OYW1lIGZyb20gXCIuLi8uLi8uLi8uLi8uLi91dGlscy9kZWJ1cnItY29sdW1uLW5hbWUuanNcIlxuaW1wb3J0IGZpbGVFeGlzdHMgZnJvbSBcIi4uLy4uLy4uLy4uLy4uL3V0aWxzL2ZpbGUtZXhpc3RzLmpzXCJcbmltcG9ydCBmcyBmcm9tIFwiZnMvcHJvbWlzZXNcIlxuaW1wb3J0IGdlbmVyYXRlZEZpbGVCYW5uZXIgZnJvbSBcIi4vZ2VuZXJhdGVkLWZpbGUtYmFubmVyLmpzXCJcbmltcG9ydCAqIGFzIGluZmxlY3Rpb24gZnJvbSBcImluZmxlY3Rpb25cIlxuXG5jb25zdCBCQVNFX01PREVMU19SRUdFTkVSQVRFX0NPTU1BTkQgPSBcInZlbG9jaW91cyBnZW5lcmF0ZTpiYXNlLW1vZGVsc1wiXG5cbi8qKlxuICogTWFwcyBhbiBlZmZlY3RpdmUgY29sdW1uIHR5cGUgdG8gdGhlIEpTRG9jIHR5cGUgdXNlZCBpbiBnZW5lcmF0ZWQgYmFzZSBtb2RlbHMuXG4gKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgc3RyaW5nPn1cbiAqL1xuY29uc3QganNEb2NUeXBlQnlDb2x1bW5UeXBlID0ge1xuICBiaWdpbnQ6IFwibnVtYmVyXCIsXG4gIGJpdDogXCJudW1iZXJcIixcbiAgYmxvYjogXCJzdHJpbmdcIixcbiAgYm9vbGVhbjogXCJib29sZWFuXCIsXG4gIGNoYXI6IFwic3RyaW5nXCIsXG4gIFwiY2hhcmFjdGVyIHZhcnlpbmdcIjogXCJzdHJpbmdcIixcbiAgZGF0ZTogXCJEYXRlXCIsXG4gIGRhdGV0aW1lOiBcIkRhdGVcIixcbiAgZGVjaW1hbDogXCJudW1iZXJcIixcbiAgZmxvYXQ6IFwibnVtYmVyXCIsXG4gIGludDogXCJudW1iZXJcIixcbiAgaW50ZWdlcjogXCJudW1iZXJcIixcbiAganNvbjogXCJSZWNvcmQ8c3RyaW5nLCB1bmtub3duPlwiLFxuICBsb25ndGV4dDogXCJzdHJpbmdcIixcbiAgbWVkaXVtdGV4dDogXCJzdHJpbmdcIixcbiAgbnVtZXJpYzogXCJudW1iZXJcIixcbiAgbnZhcmNoYXI6IFwic3RyaW5nXCIsXG4gIHNtYWxsaW50OiBcIm51bWJlclwiLFxuICB0ZXh0OiBcInN0cmluZ1wiLFxuICBcInRpbWVzdGFtcCB3aXRob3V0IHRpbWUgem9uZVwiOiBcIkRhdGVcIixcbiAgdGlueWludDogXCJudW1iZXJcIixcbiAgdGlueXRleHQ6IFwic3RyaW5nXCIsXG4gIHV1aWQ6IFwic3RyaW5nXCIsXG4gIHZhcmNoYXI6IFwic3RyaW5nXCJcbn1cblxuLyoqIEVmZmVjdGl2ZSBjb2x1bW4gdHlwZXMgd2hvc2UgZ2VuZXJhdGVkIHNldHRlciBhZGRpdGlvbmFsbHkgYWNjZXB0cyBhIHN0cmluZy4gKi9cbmNvbnN0IHNldHRlclN0cmluZ0lucHV0Q29sdW1uVHlwZXMgPSBuZXcgU2V0KFtcImRhdGVcIiwgXCJkYXRldGltZVwiLCBcInRpbWVzdGFtcCB3aXRob3V0IHRpbWUgem9uZVwiXSlcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSBiYXNlLW1vZGVsIHJlbGF0aW9uc2hpcCBtZXRob2QuXG4gKiBAcGFyYW0ge3thYnN0cmFjdD86IGJvb2xlYW4sIGJvZHk6IHN0cmluZywgbmFtZTogc3RyaW5nLCBwYXJhbT86IHtuYW1lOiBzdHJpbmcsIHR5cGU6IHN0cmluZ30sIHJldHVybnM6IHN0cmluZ319IGFyZ3MgLSBNZXRob2QgcGFydHMuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSAtIEdlbmVyYXRlZCBtZXRob2Qgc291cmNlLlxuICovXG5mdW5jdGlvbiBnZW5lcmF0ZWRSZWxhdGlvbnNoaXBNZXRob2Qoe2Fic3RyYWN0ID0gZmFsc2UsIGJvZHksIG5hbWUsIHBhcmFtLCByZXR1cm5zfSkge1xuICBsZXQgZmlsZUNvbnRlbnQgPSBcIiAgLyoqXFxuXCJcblxuICBpZiAoYWJzdHJhY3QpIGZpbGVDb250ZW50ICs9IFwiICAgKiBAYWJzdHJhY3RcXG5cIlxuICBpZiAocGFyYW0pIGZpbGVDb250ZW50ICs9IGAgICAqIEBwYXJhbSB7JHtwYXJhbS50eXBlfX0gJHtwYXJhbS5uYW1lfVxcbmBcbiAgZmlsZUNvbnRlbnQgKz0gYCAgICogQHJldHVybnMgeyR7cmV0dXJuc319XFxuYFxuICBmaWxlQ29udGVudCArPSBcIiAgICovXFxuXCJcbiAgZmlsZUNvbnRlbnQgKz0gYCAgJHtuYW1lfSgke3BhcmFtID8gcGFyYW0ubmFtZSA6IFwiXCJ9KSB7ICR7Ym9keX0gfVxcbmBcblxuICByZXR1cm4gZmlsZUNvbnRlbnRcbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRGJHZW5lcmF0ZU1vZGVsIGV4dGVuZHMgQmFzZUNvbW1hbmQge1xuICBhc3luYyBleGVjdXRlKCkge1xuICAgIGF3YWl0IHRoaXMuZ2V0Q29uZmlndXJhdGlvbigpLmluaXRpYWxpemVNb2RlbHMoKVxuXG4gICAgY29uc3QgZW5mb3JjZVRlbmFudERhdGFiYXNlU2NvcGVzID0gdGhpcy5nZXRDb25maWd1cmF0aW9uKCkuZ2V0RW5mb3JjZVRlbmFudERhdGFiYXNlU2NvcGVzKClcblxuICAgIGNvbnN0IHJvb3REaXJlY3RvcnkgPSB0aGlzLmRpcmVjdG9yeSgpXG4gICAgY29uc3QgbW9kZWxzRGlyID0gYCR7cm9vdERpcmVjdG9yeX0vc3JjL21vZGVsc2BcbiAgICBjb25zdCBiYXNlTW9kZWxzRGlyID0gYCR7cm9vdERpcmVjdG9yeX0vc3JjL21vZGVsLWJhc2VzYFxuICAgIGNvbnN0IG1vZGVsQ2xhc3NlcyA9IHRoaXMuZ2V0Q29uZmlndXJhdGlvbigpLmdldE1vZGVsQ2xhc3NlcygpXG4gICAgY29uc3QgYWxsb3dNaXNzaW5nVGFibGVzID0gQm9vbGVhbih0aGlzLnByb2Nlc3NBcmdzPy5pbmNsdWRlcyhcIi0tYWxsb3ctbWlzc2luZy10YWJsZXNcIikpXG4gICAgbGV0IGRldk1vZGUgPSBmYWxzZVxuXG4gICAgaWYgKGJhc2VNb2RlbHNEaXIuaW5jbHVkZXMoXCIvc3BlYy9kdW1teS9zcmMvbW9kZWwtYmFzZXNcIikpIHtcbiAgICAgIGRldk1vZGUgPSB0cnVlXG4gICAgfVxuXG4gICAgaWYgKCFhd2FpdCBmaWxlRXhpc3RzKGJhc2VNb2RlbHNEaXIpKSB7XG4gICAgICBhd2FpdCBmcy5ta2RpcihiYXNlTW9kZWxzRGlyLCB7cmVjdXJzaXZlOiB0cnVlfSlcbiAgICB9XG5cbiAgICB0aGlzLmdldENvbmZpZ3VyYXRpb24oKS5zZXRFbmZvcmNlVGVuYW50RGF0YWJhc2VTY29wZXMoZmFsc2UpXG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5nZXRDb25maWd1cmF0aW9uKCkuZW5zdXJlQ29ubmVjdGlvbnMoe25hbWU6IFwiR2VuZXJhdGUgYmFzZSBtb2RlbHNcIn0sIGFzeW5jICgpID0+IHtcbiAgICAgICAgZm9yIChjb25zdCBtb2RlbENsYXNzTmFtZSBpbiBtb2RlbENsYXNzZXMpIHtcbiAgICAgICAgY29uc3QgbW9kZWxDbGFzcyA9IG1vZGVsQ2xhc3Nlc1ttb2RlbENsYXNzTmFtZV1cbiAgICAgICAgY29uc3QgdGFibGUgPSBhd2FpdCBtb2RlbENsYXNzLmNvbm5lY3Rpb24oKS5nZXRUYWJsZUJ5TmFtZShtb2RlbENsYXNzLnRhYmxlTmFtZSgpLCB7dGhyb3dFcnJvcjogIWFsbG93TWlzc2luZ1RhYmxlc30pXG5cbiAgICAgICAgaWYgKCF0YWJsZSkge1xuICAgICAgICAgIGNvbnNvbGUud2FybihgU2tpcHBpbmcgYmFzZSBtb2RlbCBmb3IgJyR7bW9kZWxDbGFzcy5uYW1lfSc6IHRhYmxlICcke21vZGVsQ2xhc3MudGFibGVOYW1lKCl9JyB3YXMgbm90IGZvdW5kICgtLWFsbG93LW1pc3NpbmctdGFibGVzKS4gS2VlcGluZyBhbnkgZXhpc3RpbmcgYmFzZSBtb2RlbC5gKVxuXG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IG1vZGVsTmFtZSA9IGluZmxlY3Rpb24uZGFzaGVyaXplKG1vZGVsQ2xhc3NOYW1lKVxuICAgICAgICBjb25zdCBtb2RlbE5hbWVDYW1lbGl6ZWQgPSBpbmZsZWN0aW9uLmNhbWVsaXplKG1vZGVsTmFtZS5yZXBsYWNlQWxsKFwiLVwiLCBcIl9cIikpXG4gICAgICAgIGNvbnN0IG1vZGVsQmFzZUZpbGVOYW1lID0gYCR7aW5mbGVjdGlvbi5kYXNoZXJpemUoaW5mbGVjdGlvbi51bmRlcnNjb3JlKG1vZGVsTmFtZSkpfS5qc2BcbiAgICAgICAgY29uc3QgbW9kZWxQYXRoID0gYCR7YmFzZU1vZGVsc0Rpcn0vJHttb2RlbEJhc2VGaWxlTmFtZX1gXG5cbiAgICAgICAgY29uc29sZS5sb2coYGNyZWF0ZSBzcmMvbW9kZWwtYmFzZXMvJHttb2RlbEJhc2VGaWxlTmFtZX1gKVxuXG4gICAgICAgIGNvbnN0IHNvdXJjZU1vZGVsRnVsbEZpbGVQYXRoID0gYCR7bW9kZWxzRGlyfS8ke21vZGVsQmFzZUZpbGVOYW1lfWBcbiAgICAgICAgbGV0IHNvdXJjZU1vZGVsRmlsZVBhdGhcblxuICAgICAgICBpZiAoYXdhaXQgZmlsZUV4aXN0cyhzb3VyY2VNb2RlbEZ1bGxGaWxlUGF0aCkpIHtcbiAgICAgICAgICBzb3VyY2VNb2RlbEZpbGVQYXRoID0gYC4uL21vZGVscy8ke21vZGVsQmFzZUZpbGVOYW1lfWBcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzb3VyY2VNb2RlbEZpbGVQYXRoID0gXCJ2ZWxvY2lvdXMvYnVpbGQvc3JjL2RhdGFiYXNlL3JlY29yZC9pbmRleC5qc1wiXG4gICAgICAgIH1cblxuICAgICAgICBsZXQgZmlsZUNvbnRlbnQgPSBnZW5lcmF0ZWRGaWxlQmFubmVyKEJBU0VfTU9ERUxTX1JFR0VORVJBVEVfQ09NTUFORClcbiAgICAgICAgbGV0IHZlbG9jaW91c1BhdGhcblxuICAgICAgICBpZiAoZGV2TW9kZSkge1xuICAgICAgICAgIHZlbG9jaW91c1BhdGggPSBcIi4uLy4uLy4uLy4uL3NyY1wiXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmVsb2Npb3VzUGF0aCA9IFwidmVsb2Npb3VzL2J1aWxkL3NyY1wiXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjb2x1bW5zID0gYXdhaXQgdGFibGUuZ2V0Q29sdW1ucygpXG4gICAgICAgIGNvbnN0IHdyaXRlQXR0cmlidXRlVHlwZU5hbWUgPSBgJHttb2RlbE5hbWVDYW1lbGl6ZWR9V3JpdGVBdHRyaWJ1dGVzYFxuICAgICAgICBjb25zdCBiZWxvbmdzVG9Xcml0ZUF0dHJpYnV0ZXMgPSBhd2FpdCB0aGlzLmJlbG9uZ3NUb1dyaXRlQXR0cmlidXRlc0Zvck1vZGVsKHttb2RlbENsYXNzLCBtb2RlbHNEaXJ9KVxuICAgICAgICBjb25zdCBuZXN0ZWRXcml0ZUF0dHJpYnV0ZXMgPSB0aGlzLm5lc3RlZFdyaXRlQXR0cmlidXRlc0Zvck1vZGVsKHttb2RlbENsYXNzfSlcblxuICAgICAgICBmaWxlQ29udGVudCArPSBgaW1wb3J0IERhdGFiYXNlUmVjb3JkIGZyb20gXCIke3ZlbG9jaW91c1BhdGh9L2RhdGFiYXNlL3JlY29yZC9pbmRleC5qc1wiXFxuXFxuYFxuICAgICAgICBmaWxlQ29udGVudCArPSBcIi8qKlxcblwiXG4gICAgICAgIGZpbGVDb250ZW50ICs9IGAgKiBBdHRyaWJ1dGVzIGFjY2VwdGVkIHdoZW4gY3JlYXRpbmcgb3IgdXBkYXRpbmcgJHttb2RlbE5hbWVDYW1lbGl6ZWR9IHJlY29yZHMuXFxuYFxuICAgICAgICBmaWxlQ29udGVudCArPSBgICogQHR5cGVkZWYge29iamVjdH0gJHt3cml0ZUF0dHJpYnV0ZVR5cGVOYW1lfVxcbmBcbiAgICAgICAgZm9yIChjb25zdCBjb2x1bW4gb2YgY29sdW1ucykge1xuICAgICAgICAgIGNvbnN0IGRlYnVycmVkQ29sdW1uTmFtZSA9IGRlYnVyckNvbHVtbk5hbWUoY29sdW1uLmdldE5hbWUoKSlcbiAgICAgICAgICBjb25zdCBjYW1lbGl6ZWRDb2x1bW5OYW1lID0gaW5mbGVjdGlvbi5jYW1lbGl6ZShkZWJ1cnJlZENvbHVtbk5hbWUsIHRydWUpXG4gICAgICAgICAgY29uc3Qgc2V0dGVySnNkb2NUeXBlID0gdGhpcy5qc0RvY1NldHRlclR5cGVGcm9tQ29sdW1uKGNvbHVtbiwgbW9kZWxDbGFzcylcblxuICAgICAgICAgIGlmIChzZXR0ZXJKc2RvY1R5cGUpIHtcbiAgICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgKiBAcHJvcGVydHkgeyR7c2V0dGVySnNkb2NUeXBlfSR7Y29sdW1uLmdldE51bGwoKSA/IFwiIHwgbnVsbFwiIDogXCJcIn19IFske2NhbWVsaXplZENvbHVtbk5hbWV9XSAtIFZhbHVlIGZvciB0aGUgJHtjYW1lbGl6ZWRDb2x1bW5OYW1lfSBhdHRyaWJ1dGUuXFxuYFxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IgKGNvbnN0IGJlbG9uZ3NUb1dyaXRlQXR0cmlidXRlIG9mIGJlbG9uZ3NUb1dyaXRlQXR0cmlidXRlcykge1xuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgKiBAcHJvcGVydHkgeyR7YmVsb25nc1RvV3JpdGVBdHRyaWJ1dGUucHJvcGVydHlUeXBlfX0gWyR7YmVsb25nc1RvV3JpdGVBdHRyaWJ1dGUucHJvcGVydHlOYW1lfV0gLSBSZWxhdGVkICR7YmVsb25nc1RvV3JpdGVBdHRyaWJ1dGUucmVsYXRpb25zaGlwTmFtZX0gcmVjb3JkLlxcbmBcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGNvbnN0IG5lc3RlZFdyaXRlQXR0cmlidXRlIG9mIG5lc3RlZFdyaXRlQXR0cmlidXRlcykge1xuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgKiBAcHJvcGVydHkgeyR7bmVzdGVkV3JpdGVBdHRyaWJ1dGUucHJvcGVydHlUeXBlfX0gWyR7bmVzdGVkV3JpdGVBdHRyaWJ1dGUucHJvcGVydHlOYW1lfV0gLSBOZXN0ZWQgJHtuZXN0ZWRXcml0ZUF0dHJpYnV0ZS5yZWxhdGlvbnNoaXBOYW1lfSBhdHRyaWJ1dGVzLlxcbmBcbiAgICAgICAgfVxuICAgICAgICBmaWxlQ29udGVudCArPSBcIiAqL1xcblxcblwiXG5cbiAgICAgICAgY29uc3QgaGFzTWFueVJlbGF0aW9uRmlsZVBhdGggPSBgJHt2ZWxvY2lvdXNQYXRofS9kYXRhYmFzZS9yZWNvcmQvaW5zdGFuY2UtcmVsYXRpb25zaGlwcy9oYXMtbWFueS5qc2BcblxuICAgICAgICBmaWxlQ29udGVudCArPSBgLyoqIEBhdWdtZW50cyB7RGF0YWJhc2VSZWNvcmQ8JHt3cml0ZUF0dHJpYnV0ZVR5cGVOYW1lfT59ICovXFxuYFxuICAgICAgICBmaWxlQ29udGVudCArPSBgZXhwb3J0IGRlZmF1bHQgY2xhc3MgJHttb2RlbE5hbWVDYW1lbGl6ZWR9QmFzZSBleHRlbmRzIERhdGFiYXNlUmVjb3JkIHtcXG5gXG5cbiAgICAgIC8vIC0tLSBnZXRNb2RlbENsYXNzKCkgb3ZlcnJpZGUgKGZpeGVzIHBvbHltb3JwaGljIHR5cGluZyBpbiBKUy9KU0RvYykgLS0tXG4gICAgICBpZiAoYXdhaXQgZmlsZUV4aXN0cyhzb3VyY2VNb2RlbEZ1bGxGaWxlUGF0aCkpIHtcbiAgICAgICAgLy8gTW9kZWwgZmlsZSBleGlzdHMgKGUuZy4gc3JjL21vZGVscy90aWNrZXQuanMpIOKGkiByZXR1cm4gdHlwZW9mIFRpY2tldFxuICAgICAgICBmaWxlQ29udGVudCArPSBgICAvKiogQHJldHVybnMge3R5cGVvZiBpbXBvcnQoXCIke3NvdXJjZU1vZGVsRmlsZVBhdGh9XCIpLmRlZmF1bHR9ICovXFxuYFxuICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgLy8gQHRzLWlnbm9yZSAtIG92ZXJyaWRlIG5hcnJvd3MgcmV0dXJuIHR5cGUgZm9yIGJldHRlciBJbnRlbGxpU2Vuc2UgaW4gZ2VuZXJhdGVkIG1vZGVsIGJhc2VzXFxuXCJcbiAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgZ2V0TW9kZWxDbGFzcygpIHsgcmV0dXJuIC8qKiBAdHlwZSB7dHlwZW9mIGltcG9ydChcIiR7c291cmNlTW9kZWxGaWxlUGF0aH1cIikuZGVmYXVsdH0gKi8gKHRoaXMuY29uc3RydWN0b3IpIH1cXG5cXG5gXG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBObyBtb2RlbCBmaWxlIHlldCDihpIgZmFsbCBiYWNrIHRvIHR5cGVvZiBUaWNrZXRCYXNlXG4gICAgICAgIGZpbGVDb250ZW50ICs9IGAgIC8qKiBAcmV0dXJucyB7dHlwZW9mICR7bW9kZWxOYW1lQ2FtZWxpemVkfUJhc2V9ICovXFxuYFxuICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgLy8gQHRzLWlnbm9yZSAtIG92ZXJyaWRlIG5hcnJvd3MgcmV0dXJuIHR5cGUgZm9yIGJldHRlciBJbnRlbGxpU2Vuc2UgaW4gZ2VuZXJhdGVkIG1vZGVsIGJhc2VzXFxuXCJcbiAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgZ2V0TW9kZWxDbGFzcygpIHsgcmV0dXJuIC8qKiBAdHlwZSB7dHlwZW9mICR7bW9kZWxOYW1lQ2FtZWxpemVkfUJhc2V9ICovICh0aGlzLmNvbnN0cnVjdG9yKSB9XFxuXFxuYFxuICAgICAgfVxuXG4gICAgICBsZXQgbWV0aG9kc0NvdW50ID0gMFxuXG4gICAgICBmb3IgKGNvbnN0IGNvbHVtbiBvZiBjb2x1bW5zKSB7XG4gICAgICAgIGNvbnN0IGRlYnVycmVkQ29sdW1uTmFtZSA9IGRlYnVyckNvbHVtbk5hbWUoY29sdW1uLmdldE5hbWUoKSlcbiAgICAgICAgY29uc3QgY2FtZWxpemVkQ29sdW1uTmFtZSA9IGluZmxlY3Rpb24uY2FtZWxpemUoZGVidXJyZWRDb2x1bW5OYW1lLCB0cnVlKVxuICAgICAgICBjb25zdCBjYW1lbGl6ZWRDb2x1bW5OYW1lQmlnRmlyc3QgPSBpbmZsZWN0aW9uLmNhbWVsaXplKGRlYnVycmVkQ29sdW1uTmFtZSlcbiAgICAgICAgY29uc3QganNkb2NUeXBlID0gdGhpcy5qc0RvY1R5cGVGcm9tQ29sdW1uKGNvbHVtbiwgbW9kZWxDbGFzcylcblxuICAgICAgICBpZiAobWV0aG9kc0NvdW50ID4gMCkge1xuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiXFxuXCJcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChqc2RvY1R5cGUpIHtcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAvKiogQHJldHVybnMgeyR7anNkb2NUeXBlfSR7Y29sdW1uLmdldE51bGwoKSA/IFwiIHwgbnVsbFwiIDogXCJcIn19ICovXFxuYFxuICAgICAgICB9XG5cbiAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgJHtjYW1lbGl6ZWRDb2x1bW5OYW1lfSgpIHsgcmV0dXJuIHRoaXMucmVhZEF0dHJpYnV0ZShcIiR7Y2FtZWxpemVkQ29sdW1uTmFtZX1cIikgfVxcblxcbmBcblxuICAgICAgICBjb25zdCBzZXR0ZXJKc2RvY1R5cGUgPSB0aGlzLmpzRG9jU2V0dGVyVHlwZUZyb21Db2x1bW4oY29sdW1uLCBtb2RlbENsYXNzKVxuXG4gICAgICAgIGlmIChzZXR0ZXJKc2RvY1R5cGUpIHtcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgLyoqXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAgKiBAcGFyYW0geyR7c2V0dGVySnNkb2NUeXBlfSR7Y29sdW1uLmdldE51bGwoKSA/IFwiIHwgbnVsbFwiIDogXCJcIn19IG5ld1ZhbHVlXFxuYFxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKiBAcmV0dXJucyB7dm9pZH1cXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKi9cXG5cIlxuICAgICAgICB9XG5cbiAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgc2V0JHtjYW1lbGl6ZWRDb2x1bW5OYW1lQmlnRmlyc3R9KG5ld1ZhbHVlKSB7IHJldHVybiB0aGlzLl9zZXRDb2x1bW5BdHRyaWJ1dGUoXCIke2NhbWVsaXplZENvbHVtbk5hbWV9XCIsIG5ld1ZhbHVlKSB9XFxuXFxuYFxuXG4gICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAvKiogQHJldHVybnMge2Jvb2xlYW59ICovXFxuXCJcbiAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgaGFzJHtjYW1lbGl6ZWRDb2x1bW5OYW1lQmlnRmlyc3R9KCkgeyByZXR1cm4gdGhpcy5faGFzQXR0cmlidXRlKHRoaXMuJHtjYW1lbGl6ZWRDb2x1bW5OYW1lfSgpKSB9XFxuYFxuXG4gICAgICAgIG1ldGhvZHNDb3VudCsrXG4gICAgICB9XG5cbiAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobW9kZWxDbGFzcywgXCJfdHJhbnNsYXRpb25zXCIpICYmIG1vZGVsQ2xhc3MuX3RyYW5zbGF0aW9ucyAmJiBPYmplY3Qua2V5cyhtb2RlbENsYXNzLl90cmFuc2xhdGlvbnMpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29uc3QgVHJhbnNsYXRpb25DbGFzcyA9IG1vZGVsQ2xhc3MuZ2V0VHJhbnNsYXRpb25DbGFzcygpXG4gICAgICAgIGNvbnN0IHRyYW5zbGF0aW9uQ29sdW1ucyA9IFRyYW5zbGF0aW9uQ2xhc3MuZ2V0Q29sdW1ucygpXG5cbiAgICAgICAgZm9yIChjb25zdCBuYW1lIGluIG1vZGVsQ2xhc3MuX3RyYW5zbGF0aW9ucykge1xuICAgICAgICAgIGNvbnN0IG5hbWVVbmRlcnNjb3JlID0gaW5mbGVjdGlvbi51bmRlcnNjb3JlKG5hbWUpXG4gICAgICAgICAgY29uc3QgY29sdW1uID0gdHJhbnNsYXRpb25Db2x1bW5zLmZpbmQoKHRyYW5zbGF0aW9uQ29sdW1uKSA9PiB0cmFuc2xhdGlvbkNvbHVtbi5nZXROYW1lKCkgPT09IG5hbWVVbmRlcnNjb3JlKVxuICAgICAgICAgIGxldCB0cmFuc2xhdGlvbkpzZG9jVHlwZVxuXG4gICAgICAgICAgaWYgKGNvbHVtbikge1xuICAgICAgICAgICAgdHJhbnNsYXRpb25Kc2RvY1R5cGUgPSB0aGlzLmpzRG9jVHlwZUZyb21Db2x1bW4oY29sdW1uLCBUcmFuc2xhdGlvbkNsYXNzKVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0cmFuc2xhdGlvbkpzZG9jVHlwZSAmJiBjb2x1bW4pIHtcbiAgICAgICAgICAgIGZpbGVDb250ZW50ICs9IGBcXG5gXG4gICAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgLyoqXFxuXCJcbiAgICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICAqIEByZXR1cm5zIHske3RyYW5zbGF0aW9uSnNkb2NUeXBlfSR7Y29sdW1uLmdldE51bGwoKSA/IFwiIHwgbnVsbFwiIDogXCJcIn19XFxuYFxuICAgICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgICAqL1xcblwiXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgJHtuYW1lfSgpIHsgcmV0dXJuIHRoaXMuX2dldFRyYW5zbGF0ZWRBdHRyaWJ1dGVXaXRoRmFsbGJhY2soXCIke25hbWV9XCIsIHRoaXMuX2dldENvbmZpZ3VyYXRpb24oKS5nZXRMb2NhbGUoKSkgPz8gbnVsbCB9XFxuYFxuICAgICAgICAgIG1ldGhvZHNDb3VudCsrXG5cbiAgICAgICAgICBjb25zdCBoYXNOYW1lID0gYGhhcyR7aW5mbGVjdGlvbi5jYW1lbGl6ZShuYW1lKX1gXG4gICAgICAgICAgY29uc3Qgc2V0dGVyTmFtZSA9IGBzZXQke2luZmxlY3Rpb24uY2FtZWxpemUobmFtZSl9YFxuICAgICAgICAgIGNvbnN0IHNldHRlclBhcmFtVHlwZSA9IHRyYW5zbGF0aW9uSnNkb2NUeXBlIHx8IFwiP1wiXG5cbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgXFxuYFxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAvKipcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICAqIEBhYnN0cmFjdFxcbmBcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cXG5gXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgICAqL1xcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgJHtoYXNOYW1lfSgpIHsgdGhyb3cgbmV3IEVycm9yKFwiJHtoYXNOYW1lfSBub3QgaW1wbGVtZW50ZWRcIikgfVxcbmBcbiAgICAgICAgICBtZXRob2RzQ291bnQrK1xuXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYFxcbmBcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgLyoqXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAgKiBAcGFyYW0geyR7c2V0dGVyUGFyYW1UeXBlfX0gbmV3VmFsdWVcXG5gXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgICogQHJldHVybnMge3ZvaWR9XFxuYFxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKi9cXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICR7c2V0dGVyTmFtZX0obmV3VmFsdWUpIHsgcmV0dXJuIHRoaXMuX3NldFRyYW5zbGF0ZWRBdHRyaWJ1dGUoXCIke25hbWV9XCIsIHRoaXMuX2dldENvbmZpZ3VyYXRpb24oKS5nZXRMb2NhbGUoKSwgbmV3VmFsdWUpIH1cXG5gXG4gICAgICAgICAgbWV0aG9kc0NvdW50KytcblxuICAgICAgICAgIGZvciAoY29uc3QgbG9jYWxlIG9mIHRoaXMuZ2V0Q29uZmlndXJhdGlvbigpLmdldExvY2FsZXMoKSkge1xuICAgICAgICAgICAgY29uc3QgbG9jYWxlTWV0aG9kTmFtZSA9IGAke25hbWV9JHtpbmZsZWN0aW9uLmNhbWVsaXplKGxvY2FsZSl9YFxuXG4gICAgICAgICAgICBpZiAodHJhbnNsYXRpb25Kc2RvY1R5cGUgJiYgY29sdW1uKSB7XG4gICAgICAgICAgICAgIGZpbGVDb250ZW50ICs9IGBcXG5gXG4gICAgICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAvKipcXG5cIlxuICAgICAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAgKiBAcmV0dXJucyB7JHt0cmFuc2xhdGlvbkpzZG9jVHlwZX0ke2NvbHVtbi5nZXROdWxsKCkgPyBcIiB8IG51bGxcIiA6IFwiXCJ9fVxcbmBcbiAgICAgICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgICAqL1xcblwiXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICR7bG9jYWxlTWV0aG9kTmFtZX0oKSB7IHJldHVybiB0aGlzLl9nZXRUcmFuc2xhdGVkQXR0cmlidXRlV2l0aEZhbGxiYWNrKFwiJHtuYW1lfVwiLCBcIiR7bG9jYWxlfVwiKSA/PyBudWxsIH1cXG5gXG4gICAgICAgICAgICBtZXRob2RzQ291bnQrK1xuXG4gICAgICAgICAgICBjb25zdCBsb2NhbGVTZXR0ZXJOYW1lID0gYCR7c2V0dGVyTmFtZX0ke2luZmxlY3Rpb24uY2FtZWxpemUobG9jYWxlKX1gXG5cbiAgICAgICAgICAgIGZpbGVDb250ZW50ICs9IGBcXG5gXG4gICAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgLyoqXFxuXCJcbiAgICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICAqIEBwYXJhbSB7JHtzZXR0ZXJQYXJhbVR5cGV9fSBuZXdWYWx1ZVxcbmBcbiAgICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICAqIEByZXR1cm5zIHt2b2lkfVxcbmBcbiAgICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKi9cXG5cIlxuICAgICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgJHtsb2NhbGVTZXR0ZXJOYW1lfShuZXdWYWx1ZSkgeyByZXR1cm4gdGhpcy5fc2V0VHJhbnNsYXRlZEF0dHJpYnV0ZShcIiR7bmFtZX1cIiwgXCIke2xvY2FsZX1cIiwgbmV3VmFsdWUpIH1cXG5gXG4gICAgICAgICAgICBtZXRob2RzQ291bnQrK1xuXG4gICAgICAgICAgICBjb25zdCBsb2NhbGVIYXNOYW1lID0gYGhhcyR7aW5mbGVjdGlvbi5jYW1lbGl6ZShsb2NhbGVNZXRob2ROYW1lKX1gXG5cbiAgICAgICAgICAgIGZpbGVDb250ZW50ICs9IGBcXG5gXG4gICAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgLyoqXFxuXCJcbiAgICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICAqIEBhYnN0cmFjdFxcbmBcbiAgICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICAqIEByZXR1cm5zIHtib29sZWFufVxcbmBcbiAgICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKi9cXG5cIlxuICAgICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgJHtsb2NhbGVIYXNOYW1lfSgpIHsgdGhyb3cgbmV3IEVycm9yKFwiJHtsb2NhbGVIYXNOYW1lfSBub3QgaW1wbGVtZW50ZWRcIikgfVxcbmBcbiAgICAgICAgICAgIG1ldGhvZHNDb3VudCsrXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGZvciAoY29uc3QgcmVsYXRpb25zaGlwIG9mIG1vZGVsQ2xhc3MuZ2V0UmVsYXRpb25zaGlwcygpKSB7XG4gICAgICAgIGxldCBiYXNlRmlsZVBhdGgsIGJhc2VGdWxsRmlsZVBhdGgsIGZpbGVOYW1lLCBmdWxsRmlsZVBhdGhcblxuICAgICAgICBpZiAocmVsYXRpb25zaGlwLmdldFBvbHltb3JwaGljKCkpIHtcbiAgICAgICAgICBmaWxlTmFtZSA9IFwidmVsb2Npb3VzL2J1aWxkL3NyYy9kYXRhYmFzZS9yZWNvcmQvaW5kZXguanNcIlxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnN0IHRhcmdldE1vZGVsQ2xhc3MgPSByZWxhdGlvbnNoaXAuZ2V0VGFyZ2V0TW9kZWxDbGFzcygpXG5cbiAgICAgICAgICBpZiAoIXRhcmdldE1vZGVsQ2xhc3MpIHRocm93IG5ldyBFcnJvcihgUmVsYXRpb25zaGlwICcke3JlbGF0aW9uc2hpcC5nZXRSZWxhdGlvbnNoaXBOYW1lKCl9JyBvbiAnJHttb2RlbENsYXNzLmdldE1vZGVsTmFtZSgpfScgaGFzIG5vIHRhcmdldCBtb2RlbCBjbGFzc2ApXG5cbiAgICAgICAgICBmaWxlTmFtZSA9IGluZmxlY3Rpb24uZGFzaGVyaXplKGluZmxlY3Rpb24udW5kZXJzY29yZSh0YXJnZXRNb2RlbENsYXNzLmdldE1vZGVsTmFtZSgpKSlcbiAgICAgICAgICBmdWxsRmlsZVBhdGggPSBgc3JjL21vZGVscy8ke2ZpbGVOYW1lfS5qc2BcbiAgICAgICAgICBiYXNlRmlsZVBhdGggPSBgLi4vbW9kZWwtYmFzZXMvJHtmaWxlTmFtZX0uanNgXG4gICAgICAgICAgYmFzZUZ1bGxGaWxlUGF0aCA9IGBzcmMvbW9kZWwtYmFzZXMvJHtmaWxlTmFtZX0uanNgXG4gICAgICAgIH1cblxuICAgICAgICBpZiAobWV0aG9kc0NvdW50ID4gMCkge1xuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiXFxuXCJcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChyZWxhdGlvbnNoaXAuZ2V0VHlwZSgpID09IFwiYmVsb25nc1RvXCIgfHwgcmVsYXRpb25zaGlwLmdldFR5cGUoKSA9PSBcImhhc09uZVwiKSB7XG4gICAgICAgICAgbGV0IG1vZGVsRmlsZVBhdGhcblxuICAgICAgICAgIGlmIChmdWxsRmlsZVBhdGggJiYgYXdhaXQgZmlsZUV4aXN0cyhmdWxsRmlsZVBhdGgpKSB7XG4gICAgICAgICAgICBtb2RlbEZpbGVQYXRoID0gYC4uL21vZGVscy8ke2ZpbGVOYW1lfS5qc2BcbiAgICAgICAgICB9IGVsc2UgaWYgKGJhc2VGdWxsRmlsZVBhdGggJiYgYXdhaXQgZmlsZUV4aXN0cyhiYXNlRnVsbEZpbGVQYXRoKSkge1xuICAgICAgICAgICAgbW9kZWxGaWxlUGF0aCA9IGJhc2VGaWxlUGF0aFxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtb2RlbEZpbGVQYXRoID0gXCJ2ZWxvY2lvdXMvYnVpbGQvc3JjL2RhdGFiYXNlL3JlY29yZC9pbmRleC5qc1wiXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgIC8qKlxcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgICogQHJldHVybnMge2ltcG9ydChcIiR7bW9kZWxGaWxlUGF0aH1cIikuZGVmYXVsdH1cXG5gXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgICAqL1xcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgJHtyZWxhdGlvbnNoaXAuZ2V0UmVsYXRpb25zaGlwTmFtZSgpfSgpIHsgcmV0dXJuIC8qKiBAdHlwZSB7aW1wb3J0KFwiJHttb2RlbEZpbGVQYXRofVwiKS5kZWZhdWx0fSAqLyAodGhpcy5nZXRSZWxhdGlvbnNoaXBCeU5hbWUoXCIke3JlbGF0aW9uc2hpcC5nZXRSZWxhdGlvbnNoaXBOYW1lKCl9XCIpLmxvYWRlZCgpKSB9XFxuYFxuXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCJcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAvKipcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKiBAYWJzdHJhY3RcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pn0gW2F0dHJpYnV0ZXNdXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAgKiBAcmV0dXJucyB7aW1wb3J0KFwiJHttb2RlbEZpbGVQYXRofVwiKS5kZWZhdWx0fVxcbmBcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICovXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICBidWlsZCR7aW5mbGVjdGlvbi5jYW1lbGl6ZShyZWxhdGlvbnNoaXAuZ2V0UmVsYXRpb25zaGlwTmFtZSgpKX0oYXR0cmlidXRlcykgeyB2b2lkIGF0dHJpYnV0ZXM7IHRocm93IG5ldyBFcnJvcihcIk5vdCBpbXBsZW1lbnRlZFwiKSB9XFxuYFxuXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCJcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAvKipcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKiBAYWJzdHJhY3RcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICAqIEByZXR1cm5zIHtQcm9taXNlPGltcG9ydChcIiR7bW9kZWxGaWxlUGF0aH1cIikuZGVmYXVsdCB8IHVuZGVmaW5lZD59XFxuYFxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKi9cXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgIGxvYWQke2luZmxlY3Rpb24uY2FtZWxpemUocmVsYXRpb25zaGlwLmdldFJlbGF0aW9uc2hpcE5hbWUoKSl9KCkgeyB0aHJvdyBuZXcgRXJyb3IoXCJOb3QgaW1wbGVtZW50ZWRcIikgfVxcbmBcblxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgLyoqXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAgKiBAcmV0dXJucyB7UHJvbWlzZTxpbXBvcnQoXCIke21vZGVsRmlsZVBhdGh9XCIpLmRlZmF1bHQgfCB1bmRlZmluZWQ+fVxcbmBcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICovXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAke3JlbGF0aW9uc2hpcC5nZXRSZWxhdGlvbnNoaXBOYW1lKCl9T3JMb2FkKCkgeyByZXR1cm4gLyoqIEB0eXBlIHtQcm9taXNlPGltcG9ydChcIiR7bW9kZWxGaWxlUGF0aH1cIikuZGVmYXVsdCB8IHVuZGVmaW5lZD59ICovICh0aGlzLnJlbGF0aW9uc2hpcE9yTG9hZChcIiR7cmVsYXRpb25zaGlwLmdldFJlbGF0aW9uc2hpcE5hbWUoKX1cIikpIH1cXG5gXG5cbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIlxcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgIC8qKlxcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgICAqIEBhYnN0cmFjdFxcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgICogQHBhcmFtIHtpbXBvcnQoXCIke21vZGVsRmlsZVBhdGh9XCIpLmRlZmF1bHR9IG5ld01vZGVsXFxuYFxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICAqIEByZXR1cm5zIHt2b2lkfVxcbmBcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICovXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICBzZXQke2luZmxlY3Rpb24uY2FtZWxpemUocmVsYXRpb25zaGlwLmdldFJlbGF0aW9uc2hpcE5hbWUoKSl9KG5ld01vZGVsKSB7IHZvaWQgbmV3TW9kZWw7IHRocm93IG5ldyBFcnJvcihcIk5vdCBpbXBsZW1lbnRlZFwiKSB9XFxuYFxuICAgICAgICB9IGVsc2UgaWYgKHJlbGF0aW9uc2hpcC5nZXRUeXBlKCkgPT0gXCJoYXNNYW55XCIpIHtcbiAgICAgICAgICBsZXQgcmVjb3JkSW1wb3J0XG5cbiAgICAgICAgICBpZiAoZnVsbEZpbGVQYXRoICYmIGF3YWl0IGZpbGVFeGlzdHMoZnVsbEZpbGVQYXRoKSkge1xuICAgICAgICAgICAgcmVjb3JkSW1wb3J0ID0gYC4uL21vZGVscy8ke2ZpbGVOYW1lfS5qc2BcbiAgICAgICAgICB9IGVsc2UgaWYgKGJhc2VGdWxsRmlsZVBhdGggJiYgYXdhaXQgZmlsZUV4aXN0cyhiYXNlRnVsbEZpbGVQYXRoKSkge1xuICAgICAgICAgICAgcmVjb3JkSW1wb3J0ID0gYC4uL21vZGVsLWJhc2VzLyR7ZmlsZU5hbWV9LmpzYFxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZWNvcmRJbXBvcnQgPSBgJHt2ZWxvY2lvdXNQYXRofS9kYXRhYmFzZS9yZWNvcmQvaW5kZXguanNgXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgIC8qKlxcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgICogQHJldHVybnMge2ltcG9ydChcIiR7aGFzTWFueVJlbGF0aW9uRmlsZVBhdGh9XCIpLmRlZmF1bHQ8dHlwZW9mIGltcG9ydChcIiR7c291cmNlTW9kZWxGaWxlUGF0aH1cIikuZGVmYXVsdCwgdHlwZW9mIGltcG9ydChcIiR7cmVjb3JkSW1wb3J0fVwiKS5kZWZhdWx0Pn1cXG5gXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgICAqL1xcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgJHtyZWxhdGlvbnNoaXAuZ2V0UmVsYXRpb25zaGlwTmFtZSgpfSgpIHsgcmV0dXJuIC8qKiBAdHlwZSB7aW1wb3J0KFwiJHtoYXNNYW55UmVsYXRpb25GaWxlUGF0aH1cIikuZGVmYXVsdDx0eXBlb2YgaW1wb3J0KFwiJHtzb3VyY2VNb2RlbEZpbGVQYXRofVwiKS5kZWZhdWx0LCB0eXBlb2YgaW1wb3J0KFwiJHtyZWNvcmRJbXBvcnR9XCIpLmRlZmF1bHQ+fSAqLyAodGhpcy5nZXRSZWxhdGlvbnNoaXBCeU5hbWUoXCIke3JlbGF0aW9uc2hpcC5nZXRSZWxhdGlvbnNoaXBOYW1lKCl9XCIpKSB9XFxuYFxuXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCJcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAvKipcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICAqIEByZXR1cm5zIHtBcnJheTxpbXBvcnQoXCIke3JlY29yZEltcG9ydH1cIikuZGVmYXVsdD59XFxuYFxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKi9cXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICR7cmVsYXRpb25zaGlwLmdldFJlbGF0aW9uc2hpcE5hbWUoKX1Mb2FkZWQoKSB7IHJldHVybiAvKiogQHR5cGUge0FycmF5PGltcG9ydChcIiR7cmVjb3JkSW1wb3J0fVwiKS5kZWZhdWx0Pn0gKi8gKHRoaXMuZ2V0UmVsYXRpb25zaGlwQnlOYW1lKFwiJHtyZWxhdGlvbnNoaXAuZ2V0UmVsYXRpb25zaGlwTmFtZSgpfVwiKS5sb2FkZWQoKSkgfVxcbmBcblxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBnZW5lcmF0ZWRSZWxhdGlvbnNoaXBNZXRob2Qoe1xuICAgICAgICAgICAgYWJzdHJhY3Q6IHRydWUsXG4gICAgICAgICAgICBib2R5OiBcInRocm93IG5ldyBFcnJvcihcXFwiTm90IGltcGxlbWVudGVkXFxcIilcIixcbiAgICAgICAgICAgIG5hbWU6IGBsb2FkJHtpbmZsZWN0aW9uLmNhbWVsaXplKHJlbGF0aW9uc2hpcC5nZXRSZWxhdGlvbnNoaXBOYW1lKCkpfWAsXG4gICAgICAgICAgICByZXR1cm5zOiBgUHJvbWlzZTxBcnJheTxpbXBvcnQoXCIke3JlY29yZEltcG9ydH1cIikuZGVmYXVsdD4+YFxuICAgICAgICAgIH0pXG5cbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIlxcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gZ2VuZXJhdGVkUmVsYXRpb25zaGlwTWV0aG9kKHtcbiAgICAgICAgICAgIGJvZHk6IGByZXR1cm4gLyoqIEB0eXBlIHtQcm9taXNlPEFycmF5PGltcG9ydChcIiR7cmVjb3JkSW1wb3J0fVwiKS5kZWZhdWx0Pj59ICovICh0aGlzLnJlbGF0aW9uc2hpcE9yTG9hZChcIiR7cmVsYXRpb25zaGlwLmdldFJlbGF0aW9uc2hpcE5hbWUoKX1cIikpYCxcbiAgICAgICAgICAgIG5hbWU6IGAke3JlbGF0aW9uc2hpcC5nZXRSZWxhdGlvbnNoaXBOYW1lKCl9T3JMb2FkYCxcbiAgICAgICAgICAgIHJldHVybnM6IGBQcm9taXNlPEFycmF5PGltcG9ydChcIiR7cmVjb3JkSW1wb3J0fVwiKS5kZWZhdWx0Pj5gXG4gICAgICAgICAgfSlcblxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgLyoqXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICogQGFic3RyYWN0XFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAgKiBAcGFyYW0ge0FycmF5PGltcG9ydChcIiR7cmVjb3JkSW1wb3J0fVwiKS5kZWZhdWx0Pn0gbmV3TW9kZWxzXFxuYFxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKiBAcmV0dXJucyB7dm9pZH1cXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKi9cXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgIHNldCR7aW5mbGVjdGlvbi5jYW1lbGl6ZShyZWxhdGlvbnNoaXAuZ2V0UmVsYXRpb25zaGlwTmFtZSgpKX0obmV3TW9kZWxzKSB7IHZvaWQgbmV3TW9kZWxzOyB0aHJvdyBuZXcgRXJyb3IoXCJOb3QgaW1wbGVtZW50ZWRcIikgfVxcbmBcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gcmVsYXRpb25zaGlwIHR5cGU6ICR7cmVsYXRpb25zaGlwLmdldFR5cGUoKX1gKVxuICAgICAgICB9XG5cbiAgICAgICAgbWV0aG9kc0NvdW50KytcbiAgICAgIH1cblxuICAgICAgLy8gU3RhdGUtbWFjaGluZSBldmVudCBtZXRob2RzLiBgTW9kZWwuc3RhdGVNYWNoaW5lKC4uLilgIHJlZ2lzdGVycyB0aGVzZSBvbiB0aGUgbW9kZWwnc1xuICAgICAgLy8gb3duIHByb3RvdHlwZSBhdCBydW50aW1lOyB0aG9zZSBvdmVycmlkZSB0aGUgc3R1YnMgYmVsb3cgKGRlY2xhcmVkIG9uIHRoZSBiYXNlIGNsYXNzKSxcbiAgICAgIC8vIHNvIHRoZXNlIHRocm93aW5nIHN0dWJzIG5ldmVyIGV4ZWN1dGUuIFRoZXkgZXhpc3Qgb25seSBzbyBjYWxsIHNpdGVzIHR5cGVjaGVjayB3aXRob3V0XG4gICAgICAvLyB0aGUgY29uc3VtZXIgaGFuZC13cml0aW5nIGJvaWxlcnBsYXRlLiBHdWFyZGVkIG9uIHRoZSBvd24gYF9zdGF0ZU1hY2hpbmVEZWZpbml0aW9uYFxuICAgICAgLy8gcHJvcGVydHkgc28gYSBzdWJjbGFzcyB3aXRob3V0IGl0cyBvd24gbWFjaGluZSBkb2Vzbid0IHJlLWVtaXQgdGhlIHBhcmVudCdzIGV2ZW50cy5cbiAgICAgIGNvbnN0IHN0YXRlTWFjaGluZURlZmluaXRpb24gPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobW9kZWxDbGFzcywgXCJfc3RhdGVNYWNoaW5lRGVmaW5pdGlvblwiKVxuICAgICAgICA/IG1vZGVsQ2xhc3MuZ2V0U3RhdGVNYWNoaW5lRGVmaW5pdGlvbigpXG4gICAgICAgIDogbnVsbFxuXG4gICAgICBpZiAoc3RhdGVNYWNoaW5lRGVmaW5pdGlvbikge1xuICAgICAgICBmb3IgKGNvbnN0IGV2ZW50TmFtZSBvZiBPYmplY3Qua2V5cyhzdGF0ZU1hY2hpbmVEZWZpbml0aW9uLmV2ZW50cykpIHtcbiAgICAgICAgICAvLyBgc3RhdGVNYWNoaW5lKClgIGluc3RhbGxzIGV2ZW50IG1ldGhvZHMgd2l0aCBgcHJvdG9bZXZlbnROYW1lXWAsIHNvIGl0IGFjY2VwdHNcbiAgICAgICAgICAvLyBldmVudCBrZXlzIHRoYXQgYXJlbid0IHZhbGlkIEphdmFTY3JpcHQgaWRlbnRpZmllcnMgKGUuZy4gXCJyZXRyeS1idWlsZFwiKS4gVGhvc2VcbiAgICAgICAgICAvLyBjYW4ndCBiZSB3cml0dGVuIGFzIGNsYXNzIG1ldGhvZHMgd2l0aG91dCBwcm9kdWNpbmcgYW4gdW5wYXJzZWFibGUgZmlsZSwgc28gc2tpcFxuICAgICAgICAgIC8vIHRoZW0gaGVyZSDigJQgdGhleSBzdGlsbCB3b3JrIGF0IHJ1bnRpbWUgdmlhIGJyYWNrZXQgYWNjZXNzLCBqdXN0IHVudHlwZWQuXG4gICAgICAgICAgaWYgKCEvXltBLVphLXpfJF1bQS1aYS16MC05XyRdKiQvLnRlc3QoZXZlbnROYW1lKSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKGBTa2lwcGluZyBnZW5lcmF0ZWQgc3RhdGUtbWFjaGluZSBtZXRob2RzIGZvciBldmVudCAnJHtldmVudE5hbWV9JyBvbiAnJHttb2RlbENsYXNzLm5hbWV9JzogdGhlIGV2ZW50IG5hbWUgaXMgbm90IGEgdmFsaWQgSmF2YVNjcmlwdCBpZGVudGlmaWVyLmApXG5cbiAgICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgY2FwaXRhbGl6ZWRFdmVudCA9IGV2ZW50TmFtZS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIGV2ZW50TmFtZS5zbGljZSgxKVxuXG4gICAgICAgICAgaWYgKG1ldGhvZHNDb3VudCA+IDApIHtcbiAgICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiXFxuXCJcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgLyoqXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICogQGFic3RyYWN0XFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICogQHJldHVybnMge3ZvaWR9XFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICovXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAke2V2ZW50TmFtZX0oKSB7IHRocm93IG5ldyBFcnJvcihcIk5vdCBpbXBsZW1lbnRlZFwiKSB9XFxuYFxuXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCJcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAvKipcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKiBAYWJzdHJhY3RcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKi9cXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICR7ZXZlbnROYW1lfUFuZFNhdmUoKSB7IHRocm93IG5ldyBFcnJvcihcIk5vdCBpbXBsZW1lbnRlZFwiKSB9XFxuYFxuXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCJcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAvKipcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKiBAYWJzdHJhY3RcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKi9cXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgIGNhbiR7Y2FwaXRhbGl6ZWRFdmVudH0oKSB7IHRocm93IG5ldyBFcnJvcihcIk5vdCBpbXBsZW1lbnRlZFwiKSB9XFxuYFxuXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCJcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAvKipcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKiBAYWJzdHJhY3RcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKiBAcmV0dXJucyB7UHJvbWlzZTxib29sZWFuPn1cXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKi9cXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgIGNhbiR7Y2FwaXRhbGl6ZWRFdmVudH1Bc3luYygpIHsgdGhyb3cgbmV3IEVycm9yKFwiTm90IGltcGxlbWVudGVkXCIpIH1cXG5gXG5cbiAgICAgICAgICBtZXRob2RzQ291bnQrK1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGZpbGVDb250ZW50ICs9IFwifVxcblwiXG5cbiAgICAgICAgYXdhaXQgZnMud3JpdGVGaWxlKG1vZGVsUGF0aCwgZmlsZUNvbnRlbnQpXG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMuZ2V0Q29uZmlndXJhdGlvbigpLnNldEVuZm9yY2VUZW5hbnREYXRhYmFzZVNjb3BlcyhlbmZvcmNlVGVuYW50RGF0YWJhc2VTY29wZXMpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMganMgZG9jIHR5cGUgZnJvbSBjb2x1bW4uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vLi4vLi4vLi4vZGF0YWJhc2UvZHJpdmVycy9iYXNlLWNvbHVtbi5qc1wiKS5kZWZhdWx0fSBjb2x1bW4gLSBDb2x1bW4uXG4gICAqIEBwYXJhbSB7dHlwZW9mIGltcG9ydChcIi4uLy4uLy4uLy4uLy4uL2RhdGFiYXNlL3JlY29yZC9pbmRleC5qc1wiKS5kZWZhdWx0fSBtb2RlbENsYXNzIC0gTW9kZWwgY2xhc3Mgb3duaW5nIHRoZSBjb2x1bW4gKGZvciBkZWNsYXJlZCBhdHRyaWJ1dGUgY2FzdHMpLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nIHwgdW5kZWZpbmVkfSAtIFRoZSBqcyBkb2MgdHlwZSBmcm9tIGNvbHVtbi5cbiAgICovXG4gIGpzRG9jVHlwZUZyb21Db2x1bW4oY29sdW1uLCBtb2RlbENsYXNzKSB7XG4gICAgY29uc3QgdHlwZSA9IG1vZGVsQ2xhc3MuZ2V0Q29sdW1uVHlwZUJ5TmFtZShjb2x1bW4uZ2V0TmFtZSgpKVxuICAgIGNvbnN0IGpzRG9jVHlwZSA9IHR5cGUgPyBqc0RvY1R5cGVCeUNvbHVtblR5cGVbdHlwZV0gOiB1bmRlZmluZWRcblxuICAgIGlmICghanNEb2NUeXBlKSB7XG4gICAgICBjb25zb2xlLmVycm9yKGBVbmtub3duIGNvbHVtbiB0eXBlOiAke3R5cGV9YClcblxuICAgICAgcmV0dXJuIHVuZGVmaW5lZFxuICAgIH1cblxuICAgIHJldHVybiBqc0RvY1R5cGVcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGpzIGRvYyBzZXR0ZXIgdHlwZSBmcm9tIGNvbHVtbi5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi8uLi8uLi8uLi9kYXRhYmFzZS9kcml2ZXJzL2Jhc2UtY29sdW1uLmpzXCIpLmRlZmF1bHR9IGNvbHVtbiAtIENvbHVtbi5cbiAgICogQHBhcmFtIHt0eXBlb2YgaW1wb3J0KFwiLi4vLi4vLi4vLi4vLi4vZGF0YWJhc2UvcmVjb3JkL2luZGV4LmpzXCIpLmRlZmF1bHR9IG1vZGVsQ2xhc3MgLSBNb2RlbCBjbGFzcyBvd25pbmcgdGhlIGNvbHVtbiAoZm9yIGRlY2xhcmVkIGF0dHJpYnV0ZSBjYXN0cykuXG4gICAqIEByZXR1cm5zIHtzdHJpbmcgfCB1bmRlZmluZWR9IC0gVGhlIGpzIGRvYyBzZXR0ZXIgdHlwZSBmcm9tIGNvbHVtbi5cbiAgICovXG4gIGpzRG9jU2V0dGVyVHlwZUZyb21Db2x1bW4oY29sdW1uLCBtb2RlbENsYXNzKSB7XG4gICAgY29uc3QgdHlwZSA9IG1vZGVsQ2xhc3MuZ2V0Q29sdW1uVHlwZUJ5TmFtZShjb2x1bW4uZ2V0TmFtZSgpKVxuXG4gICAgaWYgKHR5cGUgJiYgc2V0dGVyU3RyaW5nSW5wdXRDb2x1bW5UeXBlcy5oYXModHlwZSkpIHtcbiAgICAgIHJldHVybiBcIkRhdGUgfCBzdHJpbmdcIlxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmpzRG9jVHlwZUZyb21Db2x1bW4oY29sdW1uLCBtb2RlbENsYXNzKVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgYmVsb25ncyB0byB3cml0ZSBhdHRyaWJ1dGVzIGZvciBtb2RlbC5cbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBBcmd1bWVudHMuXG4gICAqIEBwYXJhbSB7dHlwZW9mIGltcG9ydChcIi4uLy4uLy4uLy4uLy4uL2RhdGFiYXNlL3JlY29yZC9pbmRleC5qc1wiKS5kZWZhdWx0fSBhcmdzLm1vZGVsQ2xhc3MgLSBNb2RlbCBjbGFzcy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGFyZ3MubW9kZWxzRGlyIC0gU291cmNlIG1vZGVscyBkaXJlY3RvcnkuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPEFycmF5PHtwcm9wZXJ0eU5hbWU6IHN0cmluZywgcHJvcGVydHlUeXBlOiBzdHJpbmcsIHJlbGF0aW9uc2hpcE5hbWU6IHN0cmluZ30+Pn0gLSBCZWxvbmdzLXRvIHdyaXRlIGF0dHJpYnV0ZXMuXG4gICAqL1xuICBhc3luYyBiZWxvbmdzVG9Xcml0ZUF0dHJpYnV0ZXNGb3JNb2RlbCh7bW9kZWxDbGFzcywgbW9kZWxzRGlyfSkge1xuICAgIGNvbnN0IHdyaXRlQXR0cmlidXRlcyA9IFtdXG5cbiAgICBmb3IgKGNvbnN0IHJlbGF0aW9uc2hpcCBvZiBtb2RlbENsYXNzLmdldFJlbGF0aW9uc2hpcHMoKSkge1xuICAgICAgaWYgKHJlbGF0aW9uc2hpcC5nZXRUeXBlKCkgIT09IFwiYmVsb25nc1RvXCIpIGNvbnRpbnVlXG4gICAgICBpZiAocmVsYXRpb25zaGlwLmdldFBvbHltb3JwaGljKCkpIGNvbnRpbnVlXG5cbiAgICAgIGNvbnN0IHRhcmdldE1vZGVsQ2xhc3MgPSByZWxhdGlvbnNoaXAuZ2V0VGFyZ2V0TW9kZWxDbGFzcygpXG5cbiAgICAgIGlmICghdGFyZ2V0TW9kZWxDbGFzcykgdGhyb3cgbmV3IEVycm9yKGBSZWxhdGlvbnNoaXAgJyR7cmVsYXRpb25zaGlwLmdldFJlbGF0aW9uc2hpcE5hbWUoKX0nIG9uICcke21vZGVsQ2xhc3MuZ2V0TW9kZWxOYW1lKCl9JyBoYXMgbm8gdGFyZ2V0IG1vZGVsIGNsYXNzYClcblxuICAgICAgY29uc3QgdGFyZ2V0TW9kZWxGaWxlTmFtZSA9IGluZmxlY3Rpb24uZGFzaGVyaXplKGluZmxlY3Rpb24udW5kZXJzY29yZSh0YXJnZXRNb2RlbENsYXNzLmdldE1vZGVsTmFtZSgpKSlcbiAgICAgIGNvbnN0IHRhcmdldE1vZGVsUGF0aCA9IGAke21vZGVsc0Rpcn0vJHt0YXJnZXRNb2RlbEZpbGVOYW1lfS5qc2BcbiAgICAgIGNvbnN0IHRhcmdldEltcG9ydFBhdGggPSBhd2FpdCBmaWxlRXhpc3RzKHRhcmdldE1vZGVsUGF0aCkgPyBgLi4vbW9kZWxzLyR7dGFyZ2V0TW9kZWxGaWxlTmFtZX0uanNgIDogYC4vJHt0YXJnZXRNb2RlbEZpbGVOYW1lfS5qc2BcblxuICAgICAgd3JpdGVBdHRyaWJ1dGVzLnB1c2goe1xuICAgICAgICBwcm9wZXJ0eU5hbWU6IHJlbGF0aW9uc2hpcC5nZXRSZWxhdGlvbnNoaXBOYW1lKCksXG4gICAgICAgIHByb3BlcnR5VHlwZTogYGltcG9ydChcIiR7dGFyZ2V0SW1wb3J0UGF0aH1cIikuZGVmYXVsdGAsXG4gICAgICAgIHJlbGF0aW9uc2hpcE5hbWU6IHJlbGF0aW9uc2hpcC5nZXRSZWxhdGlvbnNoaXBOYW1lKClcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgcmV0dXJuIHdyaXRlQXR0cmlidXRlc1xuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgbmVzdGVkIHdyaXRlIGF0dHJpYnV0ZXMgZm9yIG1vZGVsLlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIEFyZ3VtZW50cy5cbiAgICogQHBhcmFtIHt0eXBlb2YgaW1wb3J0KFwiLi4vLi4vLi4vLi4vLi4vZGF0YWJhc2UvcmVjb3JkL2luZGV4LmpzXCIpLmRlZmF1bHR9IGFyZ3MubW9kZWxDbGFzcyAtIE1vZGVsIGNsYXNzLlxuICAgKiBAcmV0dXJucyB7QXJyYXk8e3Byb3BlcnR5TmFtZTogc3RyaW5nLCBwcm9wZXJ0eVR5cGU6IHN0cmluZywgcmVsYXRpb25zaGlwTmFtZTogc3RyaW5nfT59IC0gTmVzdGVkIHdyaXRlIGF0dHJpYnV0ZXMuXG4gICAqL1xuICBuZXN0ZWRXcml0ZUF0dHJpYnV0ZXNGb3JNb2RlbCh7bW9kZWxDbGFzc30pIHtcbiAgICBjb25zdCBhY2NlcHRlZE5lc3RlZEF0dHJpYnV0ZXMgPSBtb2RlbENsYXNzLl9hY2NlcHRlZE5lc3RlZEF0dHJpYnV0ZXMgfHwge31cbiAgICBjb25zdCBuZXN0ZWRXcml0ZUF0dHJpYnV0ZXMgPSBbXVxuXG4gICAgZm9yIChjb25zdCByZWxhdGlvbnNoaXBOYW1lIG9mIE9iamVjdC5rZXlzKGFjY2VwdGVkTmVzdGVkQXR0cmlidXRlcykpIHtcbiAgICAgIGNvbnN0IHJlbGF0aW9uc2hpcCA9IG1vZGVsQ2xhc3MuZ2V0UmVsYXRpb25zaGlwQnlOYW1lKHJlbGF0aW9uc2hpcE5hbWUpXG4gICAgICBjb25zdCByZWxhdGlvbnNoaXBUeXBlID0gcmVsYXRpb25zaGlwLmdldFR5cGUoKVxuICAgICAgY29uc3QgdGFyZ2V0TW9kZWxDbGFzcyA9IHJlbGF0aW9uc2hpcC5nZXRUYXJnZXRNb2RlbENsYXNzKClcblxuICAgICAgaWYgKCF0YXJnZXRNb2RlbENsYXNzKSB0aHJvdyBuZXcgRXJyb3IoYFJlbGF0aW9uc2hpcCAnJHtyZWxhdGlvbnNoaXBOYW1lfScgb24gJyR7bW9kZWxDbGFzcy5nZXRNb2RlbE5hbWUoKX0nIGhhcyBubyB0YXJnZXQgbW9kZWwgY2xhc3NgKVxuXG4gICAgICBjb25zdCB0YXJnZXRNb2RlbEZpbGVOYW1lID0gaW5mbGVjdGlvbi5kYXNoZXJpemUoaW5mbGVjdGlvbi51bmRlcnNjb3JlKHRhcmdldE1vZGVsQ2xhc3MuZ2V0TW9kZWxOYW1lKCkpKVxuICAgICAgY29uc3QgdGFyZ2V0V3JpdGVUeXBlTmFtZSA9IGAke2luZmxlY3Rpb24uY2FtZWxpemUodGFyZ2V0TW9kZWxDbGFzcy5nZXRNb2RlbE5hbWUoKS5yZXBsYWNlQWxsKFwiLVwiLCBcIl9cIikpfVdyaXRlQXR0cmlidXRlc2BcbiAgICAgIGNvbnN0IG5lc3RlZFR5cGUgPSBgaW1wb3J0KFwiLi8ke3RhcmdldE1vZGVsRmlsZU5hbWV9LmpzXCIpLiR7dGFyZ2V0V3JpdGVUeXBlTmFtZX0ke2FjY2VwdGVkTmVzdGVkQXR0cmlidXRlc1tyZWxhdGlvbnNoaXBOYW1lXT8uYWxsb3dEZXN0cm95ID8gXCIgJiB7X2Rlc3Ryb3k/OiBib29sZWFufVwiIDogXCJcIn1gXG5cbiAgICAgIG5lc3RlZFdyaXRlQXR0cmlidXRlcy5wdXNoKHtcbiAgICAgICAgcHJvcGVydHlOYW1lOiBgJHtyZWxhdGlvbnNoaXBOYW1lfUF0dHJpYnV0ZXNgLFxuICAgICAgICBwcm9wZXJ0eVR5cGU6IHJlbGF0aW9uc2hpcFR5cGUgPT0gXCJoYXNNYW55XCIgPyBgQXJyYXk8JHtuZXN0ZWRUeXBlfT5gIDogbmVzdGVkVHlwZSxcbiAgICAgICAgcmVsYXRpb25zaGlwTmFtZVxuICAgICAgfSlcbiAgICB9XG5cbiAgICByZXR1cm4gbmVzdGVkV3JpdGVBdHRyaWJ1dGVzXG4gIH1cbn1cbiJdfQ==
539
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1tb2RlbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvZW52aXJvbm1lbnQtaGFuZGxlcnMvbm9kZS9jbGkvY29tbWFuZHMvZ2VuZXJhdGUvYmFzZS1tb2RlbHMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sV0FBVyxNQUFNLG9DQUFvQyxDQUFBO0FBQzVELE9BQU8sZ0JBQWdCLE1BQU0seUNBQXlDLENBQUE7QUFDdEUsT0FBTyx5QkFBeUIsTUFBTSwrQ0FBK0MsQ0FBQTtBQUNyRixPQUFPLGdCQUFnQixNQUFNLDRDQUE0QyxDQUFBO0FBQ3pFLE9BQU8sVUFBVSxNQUFNLHFDQUFxQyxDQUFBO0FBQzVELE9BQU8sRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQUM1QixPQUFPLG1CQUFtQixNQUFNLDRCQUE0QixDQUFBO0FBQzVELE9BQU8sS0FBSyxVQUFVLE1BQU0sWUFBWSxDQUFBO0FBRXhDLE1BQU0sOEJBQThCLEdBQUcsZ0NBQWdDLENBQUE7QUFFdkU7OztHQUdHO0FBQ0gsTUFBTSxxQkFBcUIsR0FBRztJQUM1QixNQUFNLEVBQUUsUUFBUTtJQUNoQixHQUFHLEVBQUUsUUFBUTtJQUNiLElBQUksRUFBRSxRQUFRO0lBQ2QsT0FBTyxFQUFFLFNBQVM7SUFDbEIsSUFBSSxFQUFFLFFBQVE7SUFDZCxtQkFBbUIsRUFBRSxRQUFRO0lBQzdCLElBQUksRUFBRSxNQUFNO0lBQ1osUUFBUSxFQUFFLE1BQU07SUFDaEIsT0FBTyxFQUFFLFFBQVE7SUFDakIsS0FBSyxFQUFFLFFBQVE7SUFDZixHQUFHLEVBQUUsUUFBUTtJQUNiLE9BQU8sRUFBRSxRQUFRO0lBQ2pCLElBQUksRUFBRSx5QkFBeUI7SUFDL0IsUUFBUSxFQUFFLFFBQVE7SUFDbEIsVUFBVSxFQUFFLFFBQVE7SUFDcEIsT0FBTyxFQUFFLFFBQVE7SUFDakIsUUFBUSxFQUFFLFFBQVE7SUFDbEIsUUFBUSxFQUFF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QkFDakYsZ0JBQWdCO2FBQ2pCLENBQUMsQ0FBQTtRQUNKLENBQUM7UUFFRCxPQUFPLHFCQUFxQixDQUFBO0lBQzlCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgQmFzZUNvbW1hbmQgZnJvbSBcIi4uLy4uLy4uLy4uLy4uL2NsaS9iYXNlLWNvbW1hbmQuanNcIlxuaW1wb3J0IGNvbW1hbmRBcmd1bWVudHMgZnJvbSBcIi4uLy4uLy4uLy4uLy4uL2NsaS9jb21tYW5kLWFyZ3VtZW50cy5qc1wiXG5pbXBvcnQgRGF0YWJhc2VHZW5lcmF0aW9uQ29udGV4dCBmcm9tIFwiLi4vLi4vLi4vLi4vLi4vZGF0YWJhc2UvZ2VuZXJhdGlvbi1jb250ZXh0LmpzXCJcbmltcG9ydCBkZWJ1cnJDb2x1bW5OYW1lIGZyb20gXCIuLi8uLi8uLi8uLi8uLi91dGlscy9kZWJ1cnItY29sdW1uLW5hbWUuanNcIlxuaW1wb3J0IGZpbGVFeGlzdHMgZnJvbSBcIi4uLy4uLy4uLy4uLy4uL3V0aWxzL2ZpbGUtZXhpc3RzLmpzXCJcbmltcG9ydCBmcyBmcm9tIFwiZnMvcHJvbWlzZXNcIlxuaW1wb3J0IGdlbmVyYXRlZEZpbGVCYW5uZXIgZnJvbSBcIi4vZ2VuZXJhdGVkLWZpbGUtYmFubmVyLmpzXCJcbmltcG9ydCAqIGFzIGluZmxlY3Rpb24gZnJvbSBcImluZmxlY3Rpb25cIlxuXG5jb25zdCBCQVNFX01PREVMU19SRUdFTkVSQVRFX0NPTU1BTkQgPSBcInZlbG9jaW91cyBnZW5lcmF0ZTpiYXNlLW1vZGVsc1wiXG5cbi8qKlxuICogTWFwcyBhbiBlZmZlY3RpdmUgY29sdW1uIHR5cGUgdG8gdGhlIEpTRG9jIHR5cGUgdXNlZCBpbiBnZW5lcmF0ZWQgYmFzZSBtb2RlbHMuXG4gKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgc3RyaW5nPn1cbiAqL1xuY29uc3QganNEb2NUeXBlQnlDb2x1bW5UeXBlID0ge1xuICBiaWdpbnQ6IFwibnVtYmVyXCIsXG4gIGJpdDogXCJudW1iZXJcIixcbiAgYmxvYjogXCJzdHJpbmdcIixcbiAgYm9vbGVhbjogXCJib29sZWFuXCIsXG4gIGNoYXI6IFwic3RyaW5nXCIsXG4gIFwiY2hhcmFjdGVyIHZhcnlpbmdcIjogXCJzdHJpbmdcIixcbiAgZGF0ZTogXCJEYXRlXCIsXG4gIGRhdGV0aW1lOiBcIkRhdGVcIixcbiAgZGVjaW1hbDogXCJudW1iZXJcIixcbiAgZmxvYXQ6IFwibnVtYmVyXCIsXG4gIGludDogXCJudW1iZXJcIixcbiAgaW50ZWdlcjogXCJudW1iZXJcIixcbiAganNvbjogXCJSZWNvcmQ8c3RyaW5nLCB1bmtub3duPlwiLFxuICBsb25ndGV4dDogXCJzdHJpbmdcIixcbiAgbWVkaXVtdGV4dDogXCJzdHJpbmdcIixcbiAgbnVtZXJpYzogXCJudW1iZXJcIixcbiAgbnZhcmNoYXI6IFwic3RyaW5nXCIsXG4gIHNtYWxsaW50OiBcIm51bWJlclwiLFxuICB0ZXh0OiBcInN0cmluZ1wiLFxuICBcInRpbWVzdGFtcCB3aXRob3V0IHRpbWUgem9uZVwiOiBcIkRhdGVcIixcbiAgdGlueWludDogXCJudW1iZXJcIixcbiAgdGlueXRleHQ6IFwic3RyaW5nXCIsXG4gIHV1aWQ6IFwic3RyaW5nXCIsXG4gIHZhcmNoYXI6IFwic3RyaW5nXCJcbn1cblxuLyoqIEVmZmVjdGl2ZSBjb2x1bW4gdHlwZXMgd2hvc2UgZ2VuZXJhdGVkIHNldHRlciBhZGRpdGlvbmFsbHkgYWNjZXB0cyBhIHN0cmluZy4gKi9cbmNvbnN0IHNldHRlclN0cmluZ0lucHV0Q29sdW1uVHlwZXMgPSBuZXcgU2V0KFtcImRhdGVcIiwgXCJkYXRldGltZVwiLCBcInRpbWVzdGFtcCB3aXRob3V0IHRpbWUgem9uZVwiXSlcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSBiYXNlLW1vZGVsIHJlbGF0aW9uc2hpcCBtZXRob2QuXG4gKiBAcGFyYW0ge3thYnN0cmFjdD86IGJvb2xlYW4sIGJvZHk6IHN0cmluZywgbmFtZTogc3RyaW5nLCBwYXJhbT86IHtuYW1lOiBzdHJpbmcsIHR5cGU6IHN0cmluZ30sIHJldHVybnM6IHN0cmluZ319IGFyZ3MgLSBNZXRob2QgcGFydHMuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSAtIEdlbmVyYXRlZCBtZXRob2Qgc291cmNlLlxuICovXG5mdW5jdGlvbiBnZW5lcmF0ZWRSZWxhdGlvbnNoaXBNZXRob2Qoe2Fic3RyYWN0ID0gZmFsc2UsIGJvZHksIG5hbWUsIHBhcmFtLCByZXR1cm5zfSkge1xuICBsZXQgZmlsZUNvbnRlbnQgPSBcIiAgLyoqXFxuXCJcblxuICBpZiAoYWJzdHJhY3QpIGZpbGVDb250ZW50ICs9IFwiICAgKiBAYWJzdHJhY3RcXG5cIlxuICBpZiAocGFyYW0pIGZpbGVDb250ZW50ICs9IGAgICAqIEBwYXJhbSB7JHtwYXJhbS50eXBlfX0gJHtwYXJhbS5uYW1lfVxcbmBcbiAgZmlsZUNvbnRlbnQgKz0gYCAgICogQHJldHVybnMgeyR7cmV0dXJuc319XFxuYFxuICBmaWxlQ29udGVudCArPSBcIiAgICovXFxuXCJcbiAgZmlsZUNvbnRlbnQgKz0gYCAgJHtuYW1lfSgke3BhcmFtID8gcGFyYW0ubmFtZSA6IFwiXCJ9KSB7ICR7Ym9keX0gfVxcbmBcblxuICByZXR1cm4gZmlsZUNvbnRlbnRcbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRGJHZW5lcmF0ZU1vZGVsIGV4dGVuZHMgQmFzZUNvbW1hbmQge1xuICBhc3luYyBleGVjdXRlKCkge1xuICAgIGNvbnN0IHBhcnNlZEFyZ3VtZW50cyA9IGNvbW1hbmRBcmd1bWVudHMoe1xuICAgICAgZGVmaW5pdGlvbjoge1xuICAgICAgICBib29sZWFuT3B0aW9uczogW1wiLS1hbGxvdy1taXNzaW5nLXRhYmxlc1wiXSxcbiAgICAgICAgdmFsdWVPcHRpb25zOiBbXCItLXRlbmFudFwiXVxuICAgICAgfSxcbiAgICAgIHByb2Nlc3NBcmdzOiB0aGlzLnByb2Nlc3NBcmdzIHx8IFtdXG4gICAgfSlcbiAgICBjb25zdCBhbGxvd01pc3NpbmdUYWJsZXMgPSBwYXJzZWRBcmd1bWVudHNbXCJhbGxvdy1taXNzaW5nLXRhYmxlc1wiXSA9PT0gdHJ1ZVxuICAgIGNvbnN0IHRlbmFudERhdGFiYXNlSWRlbnRpZmllciA9IHBhcnNlZEFyZ3VtZW50cy50ZW5hbnRcblxuICAgIGlmICh0eXBlb2YgdGVuYW50RGF0YWJhc2VJZGVudGlmaWVyID09PSBcInN0cmluZ1wiKSB7XG4gICAgICBjb25zdCBjb250ZXh0ID0gYXdhaXQgRGF0YWJhc2VHZW5lcmF0aW9uQ29udGV4dC5yZXNvbHZlKHtcbiAgICAgICAgY29uZmlndXJhdGlvbjogdGhpcy5nZXRDb25maWd1cmF0aW9uKCksXG4gICAgICAgIGRhdGFiYXNlSWRlbnRpZmllcjogdGVuYW50RGF0YWJhc2VJZGVudGlmaWVyXG4gICAgICB9KVxuICAgICAgY29uc3Qgc2VsZWN0ZWRNb2RlbENsYXNzZXMgPSBPYmplY3QudmFsdWVzKHRoaXMuZ2V0Q29uZmlndXJhdGlvbigpLmdldE1vZGVsQ2xhc3NlcygpKS5maWx0ZXIoKG1vZGVsQ2xhc3MpID0+IHtcbiAgICAgICAgY29uc3QgZGF0YWJhc2VJZGVudGlmaWVyID0gbW9kZWxDbGFzcy5nZXREYXRhYmFzZUlkZW50aWZpZXIoe1xuICAgICAgICAgIGVuZm9yY2VUZW5hbnREYXRhYmFzZVNjb3BlOiBmYWxzZSxcbiAgICAgICAgICB0ZW5hbnQ6IGNvbnRleHQudGVuYW50KClcbiAgICAgICAgfSlcblxuICAgICAgICBpZiAoZGF0YWJhc2VJZGVudGlmaWVyICE9PSBjb250ZXh0LmRhdGFiYXNlSWRlbnRpZmllcigpKSByZXR1cm4gZmFsc2VcblxuICAgICAgICByZXR1cm4gbW9kZWxDbGFzcy5nZXREYXRhYmFzZUlkZW50aWZpZXIoe3RlbmFudDogY29udGV4dC50ZW5hbnQoKX0pID09PSBjb250ZXh0LmRhdGFiYXNlSWRlbnRpZmllcigpXG4gICAgICB9KVxuXG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gYXdhaXQgY29udGV4dC5ydW4oe25hbWU6IFwiR2VuZXJhdGUgc2VsZWN0ZWQgdGVuYW50IGJhc2UgbW9kZWxzXCIsIGNhbGxiYWNrOiBhc3luYyAoY29ubmVjdGlvbikgPT4ge1xuICAgICAgICAgIGF3YWl0IHRoaXMuZ2VuZXJhdGVCYXNlTW9kZWxzKHthbGxvd01pc3NpbmdUYWJsZXMsIGNvbm5lY3Rpb25zOiB7W2NvbnRleHQuZGF0YWJhc2VJZGVudGlmaWVyKCldOiBjb25uZWN0aW9ufSwgY29udGV4dH0pXG4gICAgICAgIH19KVxuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgZm9yIChjb25zdCBtb2RlbENsYXNzIG9mIHNlbGVjdGVkTW9kZWxDbGFzc2VzKSBtb2RlbENsYXNzLnJlc2V0UmVjb3JkTWV0YWRhdGEoKVxuICAgICAgfVxuICAgIH1cblxuICAgIGF3YWl0IHRoaXMuZ2V0Q29uZmlndXJhdGlvbigpLmluaXRpYWxpemVNb2RlbHMoKVxuXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuZ2V0Q29uZmlndXJhdGlvbigpLmVuc3VyZUNvbm5lY3Rpb25zKHtuYW1lOiBcIkdlbmVyYXRlIGJhc2UgbW9kZWxzXCJ9LCBhc3luYyAoY29ubmVjdGlvbnMpID0+IHtcbiAgICAgIGF3YWl0IHRoaXMuZ2VuZXJhdGVCYXNlTW9kZWxzKHthbGxvd01pc3NpbmdUYWJsZXMsIGNvbm5lY3Rpb25zfSlcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlcyBtb2RlbCBiYXNlcyBmcm9tIGV4cGxpY2l0IGNvbm5lY3Rpb25zLlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIEdlbmVyYXRpb24gYXJndW1lbnRzLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGFyZ3MuYWxsb3dNaXNzaW5nVGFibGVzIC0gV2hldGhlciBhYnNlbnQgdGFibGVzIGFyZSBza2lwcGVkLlxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGltcG9ydChcIi4uLy4uLy4uLy4uLy4uL2RhdGFiYXNlL2RyaXZlcnMvYmFzZS5qc1wiKS5kZWZhdWx0Pn0gYXJncy5jb25uZWN0aW9ucyAtIENvbm5lY3Rpb25zIGtleWVkIGJ5IGxvZ2ljYWwgaWRlbnRpZmllci5cbiAgICogQHBhcmFtIHtEYXRhYmFzZUdlbmVyYXRpb25Db250ZXh0fSBbYXJncy5jb250ZXh0XSAtIFNlbGVjdGVkIHRlbmFudCBkYXRhYmFzZSBjb250ZXh0LlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyBhZnRlciB3cml0aW5nIGdlbmVyYXRlZCBiYXNlcy5cbiAgICovXG4gIGFzeW5jIGdlbmVyYXRlQmFzZU1vZGVscyh7YWxsb3dNaXNzaW5nVGFibGVzLCBjb25uZWN0aW9ucywgY29udGV4dH0pIHtcbiAgICBjb25zdCByb290RGlyZWN0b3J5ID0gdGhpcy5kaXJlY3RvcnkoKVxuICAgIGNvbnN0IG1vZGVsc0RpciA9IGAke3Jvb3REaXJlY3Rvcnl9L3NyYy9tb2RlbHNgXG4gICAgY29uc3QgYmFzZU1vZGVsc0RpciA9IGAke3Jvb3REaXJlY3Rvcnl9L3NyYy9tb2RlbC1iYXNlc2BcbiAgICBjb25zdCBtb2RlbENsYXNzZXMgPSB0aGlzLmdldENvbmZpZ3VyYXRpb24oKS5nZXRNb2RlbENsYXNzZXMoKVxuICAgIGNvbnN0IHJlZ2VuZXJhdGVDb21tYW5kID0gY29udGV4dFxuICAgICAgPyBgJHtCQVNFX01PREVMU19SRUdFTkVSQVRFX0NPTU1BTkR9IC0tdGVuYW50ICR7Y29udGV4dC5kYXRhYmFzZUlkZW50aWZpZXIoKX1gXG4gICAgICA6IEJBU0VfTU9ERUxTX1JFR0VORVJBVEVfQ09NTUFORFxuICAgIGxldCBkZXZNb2RlID0gZmFsc2VcblxuICAgIGlmIChiYXNlTW9kZWxzRGlyLmluY2x1ZGVzKFwiL3NwZWMvZHVtbXkvc3JjL21vZGVsLWJhc2VzXCIpKSB7XG4gICAgICBkZXZNb2RlID0gdHJ1ZVxuICAgIH1cblxuICAgIGlmICghYXdhaXQgZmlsZUV4aXN0cyhiYXNlTW9kZWxzRGlyKSkge1xuICAgICAgYXdhaXQgZnMubWtkaXIoYmFzZU1vZGVsc0Rpciwge3JlY3Vyc2l2ZTogdHJ1ZX0pXG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBtb2RlbENsYXNzTmFtZSBpbiBtb2RlbENsYXNzZXMpIHtcbiAgICAgICAgY29uc3QgbW9kZWxDbGFzcyA9IG1vZGVsQ2xhc3Nlc1ttb2RlbENsYXNzTmFtZV1cbiAgICAgICAgbGV0IGRhdGFiYXNlSWRlbnRpZmllclxuXG4gICAgICAgIGlmIChjb250ZXh0KSB7XG4gICAgICAgICAgZGF0YWJhc2VJZGVudGlmaWVyID0gbW9kZWxDbGFzcy5nZXREYXRhYmFzZUlkZW50aWZpZXIoe1xuICAgICAgICAgICAgZW5mb3JjZVRlbmFudERhdGFiYXNlU2NvcGU6IGZhbHNlLFxuICAgICAgICAgICAgdGVuYW50OiBjb250ZXh0LnRlbmFudCgpXG4gICAgICAgICAgfSlcblxuICAgICAgICAgIGlmIChkYXRhYmFzZUlkZW50aWZpZXIgIT09IGNvbnRleHQuZGF0YWJhc2VJZGVudGlmaWVyKCkpIGNvbnRpbnVlXG5cbiAgICAgICAgICBkYXRhYmFzZUlkZW50aWZpZXIgPSBtb2RlbENsYXNzLmdldERhdGFiYXNlSWRlbnRpZmllcih7dGVuYW50OiBjb250ZXh0LnRlbmFudCgpfSlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBkYXRhYmFzZUlkZW50aWZpZXIgPSBtb2RlbENsYXNzLmdldENvbmZpZ3VyZWREYXRhYmFzZUlkZW50aWZpZXIoKVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNvbnRleHQgJiYgZGF0YWJhc2VJZGVudGlmaWVyICE9PSBjb250ZXh0LmRhdGFiYXNlSWRlbnRpZmllcigpKSBjb250aW51ZVxuXG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBjb25uZWN0aW9uc1tkYXRhYmFzZUlkZW50aWZpZXJdXG5cbiAgICAgICAgLy8gRGVmYXVsdCBnZW5lcmF0aW9uIGNvbnRpbnVlcyB0byBpZ25vcmUgaW5hY3RpdmUgdGVuYW50LW9ubHkgaWRlbnRpZmllcnMuXG4gICAgICAgIGlmICghY29ubmVjdGlvbikgY29udGludWVcblxuICAgICAgICBpZiAoY29udGV4dCkgbW9kZWxDbGFzcy5yZXNldFJlY29yZE1ldGFkYXRhKClcblxuICAgICAgICBjb25zdCB0YWJsZSA9IGF3YWl0IGNvbm5lY3Rpb24uZ2V0VGFibGVCeU5hbWUobW9kZWxDbGFzcy50YWJsZU5hbWUoKSwge3Rocm93RXJyb3I6ICFhbGxvd01pc3NpbmdUYWJsZXN9KVxuXG4gICAgICAgIGlmICghdGFibGUpIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oYFNraXBwaW5nIGJhc2UgbW9kZWwgZm9yICcke21vZGVsQ2xhc3MubmFtZX0nOiB0YWJsZSAnJHttb2RlbENsYXNzLnRhYmxlTmFtZSgpfScgd2FzIG5vdCBmb3VuZCAoLS1hbGxvdy1taXNzaW5nLXRhYmxlcykuIEtlZXBpbmcgYW55IGV4aXN0aW5nIGJhc2UgbW9kZWwuYClcblxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCBtb2RlbENsYXNzLmVuc3VyZUluaXRpYWxpemVkKHtjb25maWd1cmF0aW9uOiB0aGlzLmdldENvbmZpZ3VyYXRpb24oKSwgY29ubmVjdGlvbn0pXG5cbiAgICAgICAgY29uc3QgbW9kZWxOYW1lID0gaW5mbGVjdGlvbi5kYXNoZXJpemUobW9kZWxDbGFzc05hbWUpXG4gICAgICAgIGNvbnN0IG1vZGVsTmFtZUNhbWVsaXplZCA9IGluZmxlY3Rpb24uY2FtZWxpemUobW9kZWxOYW1lLnJlcGxhY2VBbGwoXCItXCIsIFwiX1wiKSlcbiAgICAgICAgY29uc3QgbW9kZWxCYXNlRmlsZU5hbWUgPSBgJHtpbmZsZWN0aW9uLmRhc2hlcml6ZShpbmZsZWN0aW9uLnVuZGVyc2NvcmUobW9kZWxOYW1lKSl9LmpzYFxuICAgICAgICBjb25zdCBtb2RlbFBhdGggPSBgJHtiYXNlTW9kZWxzRGlyfS8ke21vZGVsQmFzZUZpbGVOYW1lfWBcblxuICAgICAgICBjb25zb2xlLmxvZyhgY3JlYXRlIHNyYy9tb2RlbC1iYXNlcy8ke21vZGVsQmFzZUZpbGVOYW1lfWApXG5cbiAgICAgICAgY29uc3Qgc291cmNlTW9kZWxGdWxsRmlsZVBhdGggPSBgJHttb2RlbHNEaXJ9LyR7bW9kZWxCYXNlRmlsZU5hbWV9YFxuICAgICAgICBsZXQgc291cmNlTW9kZWxGaWxlUGF0aFxuXG4gICAgICAgIGlmIChhd2FpdCBmaWxlRXhpc3RzKHNvdXJjZU1vZGVsRnVsbEZpbGVQYXRoKSkge1xuICAgICAgICAgIHNvdXJjZU1vZGVsRmlsZVBhdGggPSBgLi4vbW9kZWxzLyR7bW9kZWxCYXNlRmlsZU5hbWV9YFxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHNvdXJjZU1vZGVsRmlsZVBhdGggPSBcInZlbG9jaW91cy9idWlsZC9zcmMvZGF0YWJhc2UvcmVjb3JkL2luZGV4LmpzXCJcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBmaWxlQ29udGVudCA9IGdlbmVyYXRlZEZpbGVCYW5uZXIocmVnZW5lcmF0ZUNvbW1hbmQpXG4gICAgICAgIGxldCB2ZWxvY2lvdXNQYXRoXG5cbiAgICAgICAgaWYgKGRldk1vZGUpIHtcbiAgICAgICAgICB2ZWxvY2lvdXNQYXRoID0gXCIuLi8uLi8uLi8uLi9zcmNcIlxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZlbG9jaW91c1BhdGggPSBcInZlbG9jaW91cy9idWlsZC9zcmNcIlxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY29sdW1ucyA9IGF3YWl0IHRhYmxlLmdldENvbHVtbnMoKVxuICAgICAgICBjb25zdCB3cml0ZUF0dHJpYnV0ZVR5cGVOYW1lID0gYCR7bW9kZWxOYW1lQ2FtZWxpemVkfVdyaXRlQXR0cmlidXRlc2BcbiAgICAgICAgY29uc3QgYmVsb25nc1RvV3JpdGVBdHRyaWJ1dGVzID0gYXdhaXQgdGhpcy5iZWxvbmdzVG9Xcml0ZUF0dHJpYnV0ZXNGb3JNb2RlbCh7bW9kZWxDbGFzcywgbW9kZWxzRGlyfSlcbiAgICAgICAgY29uc3QgbmVzdGVkV3JpdGVBdHRyaWJ1dGVzID0gdGhpcy5uZXN0ZWRXcml0ZUF0dHJpYnV0ZXNGb3JNb2RlbCh7bW9kZWxDbGFzc30pXG5cbiAgICAgICAgZmlsZUNvbnRlbnQgKz0gYGltcG9ydCBEYXRhYmFzZVJlY29yZCBmcm9tIFwiJHt2ZWxvY2lvdXNQYXRofS9kYXRhYmFzZS9yZWNvcmQvaW5kZXguanNcIlxcblxcbmBcbiAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIvKipcXG5cIlxuICAgICAgICBmaWxlQ29udGVudCArPSBgICogQXR0cmlidXRlcyBhY2NlcHRlZCB3aGVuIGNyZWF0aW5nIG9yIHVwZGF0aW5nICR7bW9kZWxOYW1lQ2FtZWxpemVkfSByZWNvcmRzLlxcbmBcbiAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAqIEB0eXBlZGVmIHtvYmplY3R9ICR7d3JpdGVBdHRyaWJ1dGVUeXBlTmFtZX1cXG5gXG4gICAgICAgIGZvciAoY29uc3QgY29sdW1uIG9mIGNvbHVtbnMpIHtcbiAgICAgICAgICBjb25zdCBkZWJ1cnJlZENvbHVtbk5hbWUgPSBkZWJ1cnJDb2x1bW5OYW1lKGNvbHVtbi5nZXROYW1lKCkpXG4gICAgICAgICAgY29uc3QgY2FtZWxpemVkQ29sdW1uTmFtZSA9IGluZmxlY3Rpb24uY2FtZWxpemUoZGVidXJyZWRDb2x1bW5OYW1lLCB0cnVlKVxuICAgICAgICAgIGNvbnN0IHNldHRlckpzZG9jVHlwZSA9IHRoaXMuanNEb2NTZXR0ZXJUeXBlRnJvbUNvbHVtbihjb2x1bW4sIG1vZGVsQ2xhc3MpXG5cbiAgICAgICAgICBpZiAoc2V0dGVySnNkb2NUeXBlKSB7XG4gICAgICAgICAgICBmaWxlQ29udGVudCArPSBgICogQHByb3BlcnR5IHske3NldHRlckpzZG9jVHlwZX0ke2NvbHVtbi5nZXROdWxsKCkgPyBcIiB8IG51bGxcIiA6IFwiXCJ9fSBbJHtjYW1lbGl6ZWRDb2x1bW5OYW1lfV0gLSBWYWx1ZSBmb3IgdGhlICR7Y2FtZWxpemVkQ29sdW1uTmFtZX0gYXR0cmlidXRlLlxcbmBcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChjb25zdCBiZWxvbmdzVG9Xcml0ZUF0dHJpYnV0ZSBvZiBiZWxvbmdzVG9Xcml0ZUF0dHJpYnV0ZXMpIHtcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICogQHByb3BlcnR5IHske2JlbG9uZ3NUb1dyaXRlQXR0cmlidXRlLnByb3BlcnR5VHlwZX19IFske2JlbG9uZ3NUb1dyaXRlQXR0cmlidXRlLnByb3BlcnR5TmFtZX1dIC0gUmVsYXRlZCAke2JlbG9uZ3NUb1dyaXRlQXR0cmlidXRlLnJlbGF0aW9uc2hpcE5hbWV9IHJlY29yZC5cXG5gXG4gICAgICAgIH1cbiAgICAgICAgZm9yIChjb25zdCBuZXN0ZWRXcml0ZUF0dHJpYnV0ZSBvZiBuZXN0ZWRXcml0ZUF0dHJpYnV0ZXMpIHtcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICogQHByb3BlcnR5IHske25lc3RlZFdyaXRlQXR0cmlidXRlLnByb3BlcnR5VHlwZX19IFske25lc3RlZFdyaXRlQXR0cmlidXRlLnByb3BlcnR5TmFtZX1dIC0gTmVzdGVkICR7bmVzdGVkV3JpdGVBdHRyaWJ1dGUucmVsYXRpb25zaGlwTmFtZX0gYXR0cmlidXRlcy5cXG5gXG4gICAgICAgIH1cbiAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgKi9cXG5cXG5cIlxuXG4gICAgICAgIGNvbnN0IGhhc01hbnlSZWxhdGlvbkZpbGVQYXRoID0gYCR7dmVsb2Npb3VzUGF0aH0vZGF0YWJhc2UvcmVjb3JkL2luc3RhbmNlLXJlbGF0aW9uc2hpcHMvaGFzLW1hbnkuanNgXG5cbiAgICAgICAgZmlsZUNvbnRlbnQgKz0gYC8qKiBAYXVnbWVudHMge0RhdGFiYXNlUmVjb3JkPCR7d3JpdGVBdHRyaWJ1dGVUeXBlTmFtZX0+fSAqL1xcbmBcbiAgICAgICAgZmlsZUNvbnRlbnQgKz0gYGV4cG9ydCBkZWZhdWx0IGNsYXNzICR7bW9kZWxOYW1lQ2FtZWxpemVkfUJhc2UgZXh0ZW5kcyBEYXRhYmFzZVJlY29yZCB7XFxuYFxuXG4gICAgICAvLyAtLS0gZ2V0TW9kZWxDbGFzcygpIG92ZXJyaWRlIChmaXhlcyBwb2x5bW9ycGhpYyB0eXBpbmcgaW4gSlMvSlNEb2MpIC0tLVxuICAgICAgaWYgKGF3YWl0IGZpbGVFeGlzdHMoc291cmNlTW9kZWxGdWxsRmlsZVBhdGgpKSB7XG4gICAgICAgIC8vIE1vZGVsIGZpbGUgZXhpc3RzIChlLmcuIHNyYy9tb2RlbHMvdGlja2V0LmpzKSDihpIgcmV0dXJuIHR5cGVvZiBUaWNrZXRcbiAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgLyoqIEByZXR1cm5zIHt0eXBlb2YgaW1wb3J0KFwiJHtzb3VyY2VNb2RlbEZpbGVQYXRofVwiKS5kZWZhdWx0fSAqL1xcbmBcbiAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgIC8vIEB0cy1pZ25vcmUgLSBvdmVycmlkZSBuYXJyb3dzIHJldHVybiB0eXBlIGZvciBiZXR0ZXIgSW50ZWxsaVNlbnNlIGluIGdlbmVyYXRlZCBtb2RlbCBiYXNlc1xcblwiXG4gICAgICAgIGZpbGVDb250ZW50ICs9IGAgIGdldE1vZGVsQ2xhc3MoKSB7IHJldHVybiAvKiogQHR5cGUge3R5cGVvZiBpbXBvcnQoXCIke3NvdXJjZU1vZGVsRmlsZVBhdGh9XCIpLmRlZmF1bHR9ICovICh0aGlzLmNvbnN0cnVjdG9yKSB9XFxuXFxuYFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gTm8gbW9kZWwgZmlsZSB5ZXQg4oaSIGZhbGwgYmFjayB0byB0eXBlb2YgVGlja2V0QmFzZVxuICAgICAgICBmaWxlQ29udGVudCArPSBgICAvKiogQHJldHVybnMge3R5cGVvZiAke21vZGVsTmFtZUNhbWVsaXplZH1CYXNlfSAqL1xcbmBcbiAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgIC8vIEB0cy1pZ25vcmUgLSBvdmVycmlkZSBuYXJyb3dzIHJldHVybiB0eXBlIGZvciBiZXR0ZXIgSW50ZWxsaVNlbnNlIGluIGdlbmVyYXRlZCBtb2RlbCBiYXNlc1xcblwiXG4gICAgICAgIGZpbGVDb250ZW50ICs9IGAgIGdldE1vZGVsQ2xhc3MoKSB7IHJldHVybiAvKiogQHR5cGUge3R5cGVvZiAke21vZGVsTmFtZUNhbWVsaXplZH1CYXNlfSAqLyAodGhpcy5jb25zdHJ1Y3RvcikgfVxcblxcbmBcbiAgICAgIH1cblxuICAgICAgbGV0IG1ldGhvZHNDb3VudCA9IDBcblxuICAgICAgZm9yIChjb25zdCBjb2x1bW4gb2YgY29sdW1ucykge1xuICAgICAgICBjb25zdCBkZWJ1cnJlZENvbHVtbk5hbWUgPSBkZWJ1cnJDb2x1bW5OYW1lKGNvbHVtbi5nZXROYW1lKCkpXG4gICAgICAgIGNvbnN0IGNhbWVsaXplZENvbHVtbk5hbWUgPSBpbmZsZWN0aW9uLmNhbWVsaXplKGRlYnVycmVkQ29sdW1uTmFtZSwgdHJ1ZSlcbiAgICAgICAgY29uc3QgY2FtZWxpemVkQ29sdW1uTmFtZUJpZ0ZpcnN0ID0gaW5mbGVjdGlvbi5jYW1lbGl6ZShkZWJ1cnJlZENvbHVtbk5hbWUpXG4gICAgICAgIGNvbnN0IGpzZG9jVHlwZSA9IHRoaXMuanNEb2NUeXBlRnJvbUNvbHVtbihjb2x1bW4sIG1vZGVsQ2xhc3MpXG5cbiAgICAgICAgaWYgKG1ldGhvZHNDb3VudCA+IDApIHtcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIlxcblwiXG4gICAgICAgIH1cblxuICAgICAgICBpZiAoanNkb2NUeXBlKSB7XG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgLyoqIEByZXR1cm5zIHske2pzZG9jVHlwZX0ke2NvbHVtbi5nZXROdWxsKCkgPyBcIiB8IG51bGxcIiA6IFwiXCJ9fSAqL1xcbmBcbiAgICAgICAgfVxuXG4gICAgICAgIGZpbGVDb250ZW50ICs9IGAgICR7Y2FtZWxpemVkQ29sdW1uTmFtZX0oKSB7IHJldHVybiB0aGlzLnJlYWRBdHRyaWJ1dGUoXCIke2NhbWVsaXplZENvbHVtbk5hbWV9XCIpIH1cXG5cXG5gXG5cbiAgICAgICAgY29uc3Qgc2V0dGVySnNkb2NUeXBlID0gdGhpcy5qc0RvY1NldHRlclR5cGVGcm9tQ29sdW1uKGNvbHVtbiwgbW9kZWxDbGFzcylcblxuICAgICAgICBpZiAoc2V0dGVySnNkb2NUeXBlKSB7XG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgIC8qKlxcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgICogQHBhcmFtIHske3NldHRlckpzZG9jVHlwZX0ke2NvbHVtbi5nZXROdWxsKCkgPyBcIiB8IG51bGxcIiA6IFwiXCJ9fSBuZXdWYWx1ZVxcbmBcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICogQHJldHVybnMge3ZvaWR9XFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICovXFxuXCJcbiAgICAgICAgfVxuXG4gICAgICAgIGZpbGVDb250ZW50ICs9IGAgIHNldCR7Y2FtZWxpemVkQ29sdW1uTmFtZUJpZ0ZpcnN0fShuZXdWYWx1ZSkgeyByZXR1cm4gdGhpcy5fc2V0Q29sdW1uQXR0cmlidXRlKFwiJHtjYW1lbGl6ZWRDb2x1bW5OYW1lfVwiLCBuZXdWYWx1ZSkgfVxcblxcbmBcblxuICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgLyoqIEByZXR1cm5zIHtib29sZWFufSAqL1xcblwiXG4gICAgICAgIGZpbGVDb250ZW50ICs9IGAgIGhhcyR7Y2FtZWxpemVkQ29sdW1uTmFtZUJpZ0ZpcnN0fSgpIHsgcmV0dXJuIHRoaXMuX2hhc0F0dHJpYnV0ZSh0aGlzLiR7Y2FtZWxpemVkQ29sdW1uTmFtZX0oKSkgfVxcbmBcblxuICAgICAgICBtZXRob2RzQ291bnQrK1xuICAgICAgfVxuXG4gICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG1vZGVsQ2xhc3MsIFwiX3RyYW5zbGF0aW9uc1wiKSAmJiBtb2RlbENsYXNzLl90cmFuc2xhdGlvbnMgJiYgT2JqZWN0LmtleXMobW9kZWxDbGFzcy5fdHJhbnNsYXRpb25zKS5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvbnN0IFRyYW5zbGF0aW9uQ2xhc3MgPSBtb2RlbENsYXNzLmdldFRyYW5zbGF0aW9uQ2xhc3MoKVxuICAgICAgICBjb25zdCB0cmFuc2xhdGlvbkNvbHVtbnMgPSBUcmFuc2xhdGlvbkNsYXNzLmdldENvbHVtbnMoKVxuXG4gICAgICAgIGZvciAoY29uc3QgbmFtZSBpbiBtb2RlbENsYXNzLl90cmFuc2xhdGlvbnMpIHtcbiAgICAgICAgICBjb25zdCBuYW1lVW5kZXJzY29yZSA9IGluZmxlY3Rpb24udW5kZXJzY29yZShuYW1lKVxuICAgICAgICAgIGNvbnN0IGNvbHVtbiA9IHRyYW5zbGF0aW9uQ29sdW1ucy5maW5kKCh0cmFuc2xhdGlvbkNvbHVtbikgPT4gdHJhbnNsYXRpb25Db2x1bW4uZ2V0TmFtZSgpID09PSBuYW1lVW5kZXJzY29yZSlcbiAgICAgICAgICBsZXQgdHJhbnNsYXRpb25Kc2RvY1R5cGVcblxuICAgICAgICAgIGlmIChjb2x1bW4pIHtcbiAgICAgICAgICAgIHRyYW5zbGF0aW9uSnNkb2NUeXBlID0gdGhpcy5qc0RvY1R5cGVGcm9tQ29sdW1uKGNvbHVtbiwgVHJhbnNsYXRpb25DbGFzcylcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAodHJhbnNsYXRpb25Kc2RvY1R5cGUgJiYgY29sdW1uKSB7XG4gICAgICAgICAgICBmaWxlQ29udGVudCArPSBgXFxuYFxuICAgICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgIC8qKlxcblwiXG4gICAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAgKiBAcmV0dXJucyB7JHt0cmFuc2xhdGlvbkpzZG9jVHlwZX0ke2NvbHVtbi5nZXROdWxsKCkgPyBcIiB8IG51bGxcIiA6IFwiXCJ9fVxcbmBcbiAgICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKi9cXG5cIlxuICAgICAgICAgIH1cblxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICR7bmFtZX0oKSB7IHJldHVybiB0aGlzLl9nZXRUcmFuc2xhdGVkQXR0cmlidXRlV2l0aEZhbGxiYWNrKFwiJHtuYW1lfVwiLCB0aGlzLl9nZXRDb25maWd1cmF0aW9uKCkuZ2V0TG9jYWxlKCkpID8/IG51bGwgfVxcbmBcbiAgICAgICAgICBtZXRob2RzQ291bnQrK1xuXG4gICAgICAgICAgY29uc3QgaGFzTmFtZSA9IGBoYXMke2luZmxlY3Rpb24uY2FtZWxpemUobmFtZSl9YFxuICAgICAgICAgIGNvbnN0IHNldHRlck5hbWUgPSBgc2V0JHtpbmZsZWN0aW9uLmNhbWVsaXplKG5hbWUpfWBcbiAgICAgICAgICBjb25zdCBzZXR0ZXJQYXJhbVR5cGUgPSB0cmFuc2xhdGlvbkpzZG9jVHlwZSB8fCBcIj9cIlxuXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYFxcbmBcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgLyoqXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAgKiBAYWJzdHJhY3RcXG5gXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgICogQHJldHVybnMge2Jvb2xlYW59XFxuYFxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKi9cXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICR7aGFzTmFtZX0oKSB7IHRocm93IG5ldyBFcnJvcihcIiR7aGFzTmFtZX0gbm90IGltcGxlbWVudGVkXCIpIH1cXG5gXG4gICAgICAgICAgbWV0aG9kc0NvdW50KytcblxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGBcXG5gXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgIC8qKlxcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgICogQHBhcmFtIHske3NldHRlclBhcmFtVHlwZX19IG5ld1ZhbHVlXFxuYFxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICAqIEByZXR1cm5zIHt2b2lkfVxcbmBcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICovXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAke3NldHRlck5hbWV9KG5ld1ZhbHVlKSB7IHJldHVybiB0aGlzLl9zZXRUcmFuc2xhdGVkQXR0cmlidXRlKFwiJHtuYW1lfVwiLCB0aGlzLl9nZXRDb25maWd1cmF0aW9uKCkuZ2V0TG9jYWxlKCksIG5ld1ZhbHVlKSB9XFxuYFxuICAgICAgICAgIG1ldGhvZHNDb3VudCsrXG5cbiAgICAgICAgICBmb3IgKGNvbnN0IGxvY2FsZSBvZiB0aGlzLmdldENvbmZpZ3VyYXRpb24oKS5nZXRMb2NhbGVzKCkpIHtcbiAgICAgICAgICAgIGNvbnN0IGxvY2FsZU1ldGhvZE5hbWUgPSBgJHtuYW1lfSR7aW5mbGVjdGlvbi5jYW1lbGl6ZShsb2NhbGUpfWBcblxuICAgICAgICAgICAgaWYgKHRyYW5zbGF0aW9uSnNkb2NUeXBlICYmIGNvbHVtbikge1xuICAgICAgICAgICAgICBmaWxlQ29udGVudCArPSBgXFxuYFxuICAgICAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgLyoqXFxuXCJcbiAgICAgICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgICogQHJldHVybnMgeyR7dHJhbnNsYXRpb25Kc2RvY1R5cGV9JHtjb2x1bW4uZ2V0TnVsbCgpID8gXCIgfCBudWxsXCIgOiBcIlwifX1cXG5gXG4gICAgICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKi9cXG5cIlxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAke2xvY2FsZU1ldGhvZE5hbWV9KCkgeyByZXR1cm4gdGhpcy5fZ2V0VHJhbnNsYXRlZEF0dHJpYnV0ZVdpdGhGYWxsYmFjayhcIiR7bmFtZX1cIiwgXCIke2xvY2FsZX1cIikgPz8gbnVsbCB9XFxuYFxuICAgICAgICAgICAgbWV0aG9kc0NvdW50KytcblxuICAgICAgICAgICAgY29uc3QgbG9jYWxlU2V0dGVyTmFtZSA9IGAke3NldHRlck5hbWV9JHtpbmZsZWN0aW9uLmNhbWVsaXplKGxvY2FsZSl9YFxuXG4gICAgICAgICAgICBmaWxlQ29udGVudCArPSBgXFxuYFxuICAgICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgIC8qKlxcblwiXG4gICAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAgKiBAcGFyYW0geyR7c2V0dGVyUGFyYW1UeXBlfX0gbmV3VmFsdWVcXG5gXG4gICAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAgKiBAcmV0dXJucyB7dm9pZH1cXG5gXG4gICAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICovXFxuXCJcbiAgICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICR7bG9jYWxlU2V0dGVyTmFtZX0obmV3VmFsdWUpIHsgcmV0dXJuIHRoaXMuX3NldFRyYW5zbGF0ZWRBdHRyaWJ1dGUoXCIke25hbWV9XCIsIFwiJHtsb2NhbGV9XCIsIG5ld1ZhbHVlKSB9XFxuYFxuICAgICAgICAgICAgbWV0aG9kc0NvdW50KytcblxuICAgICAgICAgICAgY29uc3QgbG9jYWxlSGFzTmFtZSA9IGBoYXMke2luZmxlY3Rpb24uY2FtZWxpemUobG9jYWxlTWV0aG9kTmFtZSl9YFxuXG4gICAgICAgICAgICBmaWxlQ29udGVudCArPSBgXFxuYFxuICAgICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgIC8qKlxcblwiXG4gICAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAgKiBAYWJzdHJhY3RcXG5gXG4gICAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cXG5gXG4gICAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICovXFxuXCJcbiAgICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICR7bG9jYWxlSGFzTmFtZX0oKSB7IHRocm93IG5ldyBFcnJvcihcIiR7bG9jYWxlSGFzTmFtZX0gbm90IGltcGxlbWVudGVkXCIpIH1cXG5gXG4gICAgICAgICAgICBtZXRob2RzQ291bnQrK1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IHJlbGF0aW9uc2hpcCBvZiBtb2RlbENsYXNzLmdldFJlbGF0aW9uc2hpcHMoKSkge1xuICAgICAgICBsZXQgYmFzZUZpbGVQYXRoLCBiYXNlRnVsbEZpbGVQYXRoLCBmaWxlTmFtZSwgZnVsbEZpbGVQYXRoXG5cbiAgICAgICAgaWYgKHJlbGF0aW9uc2hpcC5nZXRQb2x5bW9ycGhpYygpKSB7XG4gICAgICAgICAgZmlsZU5hbWUgPSBcInZlbG9jaW91cy9idWlsZC9zcmMvZGF0YWJhc2UvcmVjb3JkL2luZGV4LmpzXCJcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCB0YXJnZXRNb2RlbENsYXNzID0gcmVsYXRpb25zaGlwLmdldFRhcmdldE1vZGVsQ2xhc3MoKVxuXG4gICAgICAgICAgaWYgKCF0YXJnZXRNb2RlbENsYXNzKSB0aHJvdyBuZXcgRXJyb3IoYFJlbGF0aW9uc2hpcCAnJHtyZWxhdGlvbnNoaXAuZ2V0UmVsYXRpb25zaGlwTmFtZSgpfScgb24gJyR7bW9kZWxDbGFzcy5nZXRNb2RlbE5hbWUoKX0nIGhhcyBubyB0YXJnZXQgbW9kZWwgY2xhc3NgKVxuXG4gICAgICAgICAgZmlsZU5hbWUgPSBpbmZsZWN0aW9uLmRhc2hlcml6ZShpbmZsZWN0aW9uLnVuZGVyc2NvcmUodGFyZ2V0TW9kZWxDbGFzcy5nZXRNb2RlbE5hbWUoKSkpXG4gICAgICAgICAgZnVsbEZpbGVQYXRoID0gYHNyYy9tb2RlbHMvJHtmaWxlTmFtZX0uanNgXG4gICAgICAgICAgYmFzZUZpbGVQYXRoID0gYC4uL21vZGVsLWJhc2VzLyR7ZmlsZU5hbWV9LmpzYFxuICAgICAgICAgIGJhc2VGdWxsRmlsZVBhdGggPSBgc3JjL21vZGVsLWJhc2VzLyR7ZmlsZU5hbWV9LmpzYFxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG1ldGhvZHNDb3VudCA+IDApIHtcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIlxcblwiXG4gICAgICAgIH1cblxuICAgICAgICBpZiAocmVsYXRpb25zaGlwLmdldFR5cGUoKSA9PSBcImJlbG9uZ3NUb1wiIHx8IHJlbGF0aW9uc2hpcC5nZXRUeXBlKCkgPT0gXCJoYXNPbmVcIikge1xuICAgICAgICAgIGxldCBtb2RlbEZpbGVQYXRoXG5cbiAgICAgICAgICBpZiAoZnVsbEZpbGVQYXRoICYmIGF3YWl0IGZpbGVFeGlzdHMoZnVsbEZpbGVQYXRoKSkge1xuICAgICAgICAgICAgbW9kZWxGaWxlUGF0aCA9IGAuLi9tb2RlbHMvJHtmaWxlTmFtZX0uanNgXG4gICAgICAgICAgfSBlbHNlIGlmIChiYXNlRnVsbEZpbGVQYXRoICYmIGF3YWl0IGZpbGVFeGlzdHMoYmFzZUZ1bGxGaWxlUGF0aCkpIHtcbiAgICAgICAgICAgIG1vZGVsRmlsZVBhdGggPSBiYXNlRmlsZVBhdGhcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbW9kZWxGaWxlUGF0aCA9IFwidmVsb2Npb3VzL2J1aWxkL3NyYy9kYXRhYmFzZS9yZWNvcmQvaW5kZXguanNcIlxuICAgICAgICAgIH1cblxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAvKipcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICAqIEByZXR1cm5zIHtpbXBvcnQoXCIke21vZGVsRmlsZVBhdGh9XCIpLmRlZmF1bHR9XFxuYFxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKi9cXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICR7cmVsYXRpb25zaGlwLmdldFJlbGF0aW9uc2hpcE5hbWUoKX0oKSB7IHJldHVybiAvKiogQHR5cGUge2ltcG9ydChcIiR7bW9kZWxGaWxlUGF0aH1cIikuZGVmYXVsdH0gKi8gKHRoaXMuZ2V0UmVsYXRpb25zaGlwQnlOYW1lKFwiJHtyZWxhdGlvbnNoaXAuZ2V0UmVsYXRpb25zaGlwTmFtZSgpfVwiKS5sb2FkZWQoKSkgfVxcbmBcblxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgLyoqXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICogQGFic3RyYWN0XFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj59IFthdHRyaWJ1dGVzXVxcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgICogQHJldHVybnMge2ltcG9ydChcIiR7bW9kZWxGaWxlUGF0aH1cIikuZGVmYXVsdH1cXG5gXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgICAqL1xcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgYnVpbGQke2luZmxlY3Rpb24uY2FtZWxpemUocmVsYXRpb25zaGlwLmdldFJlbGF0aW9uc2hpcE5hbWUoKSl9KGF0dHJpYnV0ZXMpIHsgdm9pZCBhdHRyaWJ1dGVzOyB0aHJvdyBuZXcgRXJyb3IoXCJOb3QgaW1wbGVtZW50ZWRcIikgfVxcbmBcblxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgLyoqXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICogQGFic3RyYWN0XFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAgKiBAcmV0dXJucyB7UHJvbWlzZTxpbXBvcnQoXCIke21vZGVsRmlsZVBhdGh9XCIpLmRlZmF1bHQgfCB1bmRlZmluZWQ+fVxcbmBcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICovXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICBsb2FkJHtpbmZsZWN0aW9uLmNhbWVsaXplKHJlbGF0aW9uc2hpcC5nZXRSZWxhdGlvbnNoaXBOYW1lKCkpfSgpIHsgdGhyb3cgbmV3IEVycm9yKFwiTm90IGltcGxlbWVudGVkXCIpIH1cXG5gXG5cbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIlxcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgIC8qKlxcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgICogQHJldHVybnMge1Byb21pc2U8aW1wb3J0KFwiJHttb2RlbEZpbGVQYXRofVwiKS5kZWZhdWx0IHwgdW5kZWZpbmVkPn1cXG5gXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgICAqL1xcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgJHtyZWxhdGlvbnNoaXAuZ2V0UmVsYXRpb25zaGlwTmFtZSgpfU9yTG9hZCgpIHsgcmV0dXJuIC8qKiBAdHlwZSB7UHJvbWlzZTxpbXBvcnQoXCIke21vZGVsRmlsZVBhdGh9XCIpLmRlZmF1bHQgfCB1bmRlZmluZWQ+fSAqLyAodGhpcy5yZWxhdGlvbnNoaXBPckxvYWQoXCIke3JlbGF0aW9uc2hpcC5nZXRSZWxhdGlvbnNoaXBOYW1lKCl9XCIpKSB9XFxuYFxuXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCJcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAvKipcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKiBAYWJzdHJhY3RcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICAqIEBwYXJhbSB7aW1wb3J0KFwiJHttb2RlbEZpbGVQYXRofVwiKS5kZWZhdWx0fSBuZXdNb2RlbFxcbmBcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAgKiBAcmV0dXJucyB7dm9pZH1cXG5gXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgICAqL1xcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgc2V0JHtpbmZsZWN0aW9uLmNhbWVsaXplKHJlbGF0aW9uc2hpcC5nZXRSZWxhdGlvbnNoaXBOYW1lKCkpfShuZXdNb2RlbCkgeyB2b2lkIG5ld01vZGVsOyB0aHJvdyBuZXcgRXJyb3IoXCJOb3QgaW1wbGVtZW50ZWRcIikgfVxcbmBcbiAgICAgICAgfSBlbHNlIGlmIChyZWxhdGlvbnNoaXAuZ2V0VHlwZSgpID09IFwiaGFzTWFueVwiKSB7XG4gICAgICAgICAgbGV0IHJlY29yZEltcG9ydFxuXG4gICAgICAgICAgaWYgKGZ1bGxGaWxlUGF0aCAmJiBhd2FpdCBmaWxlRXhpc3RzKGZ1bGxGaWxlUGF0aCkpIHtcbiAgICAgICAgICAgIHJlY29yZEltcG9ydCA9IGAuLi9tb2RlbHMvJHtmaWxlTmFtZX0uanNgXG4gICAgICAgICAgfSBlbHNlIGlmIChiYXNlRnVsbEZpbGVQYXRoICYmIGF3YWl0IGZpbGVFeGlzdHMoYmFzZUZ1bGxGaWxlUGF0aCkpIHtcbiAgICAgICAgICAgIHJlY29yZEltcG9ydCA9IGAuLi9tb2RlbC1iYXNlcy8ke2ZpbGVOYW1lfS5qc2BcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVjb3JkSW1wb3J0ID0gYCR7dmVsb2Npb3VzUGF0aH0vZGF0YWJhc2UvcmVjb3JkL2luZGV4LmpzYFxuICAgICAgICAgIH1cblxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAvKipcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICAqIEByZXR1cm5zIHtpbXBvcnQoXCIke2hhc01hbnlSZWxhdGlvbkZpbGVQYXRofVwiKS5kZWZhdWx0PHR5cGVvZiBpbXBvcnQoXCIke3NvdXJjZU1vZGVsRmlsZVBhdGh9XCIpLmRlZmF1bHQsIHR5cGVvZiBpbXBvcnQoXCIke3JlY29yZEltcG9ydH1cIikuZGVmYXVsdD59XFxuYFxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiICAgKi9cXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGAgICR7cmVsYXRpb25zaGlwLmdldFJlbGF0aW9uc2hpcE5hbWUoKX0oKSB7IHJldHVybiAvKiogQHR5cGUge2ltcG9ydChcIiR7aGFzTWFueVJlbGF0aW9uRmlsZVBhdGh9XCIpLmRlZmF1bHQ8dHlwZW9mIGltcG9ydChcIiR7c291cmNlTW9kZWxGaWxlUGF0aH1cIikuZGVmYXVsdCwgdHlwZW9mIGltcG9ydChcIiR7cmVjb3JkSW1wb3J0fVwiKS5kZWZhdWx0Pn0gKi8gKHRoaXMuZ2V0UmVsYXRpb25zaGlwQnlOYW1lKFwiJHtyZWxhdGlvbnNoaXAuZ2V0UmVsYXRpb25zaGlwTmFtZSgpfVwiKSkgfVxcbmBcblxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgLyoqXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAgKiBAcmV0dXJucyB7QXJyYXk8aW1wb3J0KFwiJHtyZWNvcmRJbXBvcnR9XCIpLmRlZmF1bHQ+fVxcbmBcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICovXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAke3JlbGF0aW9uc2hpcC5nZXRSZWxhdGlvbnNoaXBOYW1lKCl9TG9hZGVkKCkgeyByZXR1cm4gLyoqIEB0eXBlIHtBcnJheTxpbXBvcnQoXCIke3JlY29yZEltcG9ydH1cIikuZGVmYXVsdD59ICovICh0aGlzLmdldFJlbGF0aW9uc2hpcEJ5TmFtZShcIiR7cmVsYXRpb25zaGlwLmdldFJlbGF0aW9uc2hpcE5hbWUoKX1cIikubG9hZGVkKCkpIH1cXG5gXG5cbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIlxcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gZ2VuZXJhdGVkUmVsYXRpb25zaGlwTWV0aG9kKHtcbiAgICAgICAgICAgIGFic3RyYWN0OiB0cnVlLFxuICAgICAgICAgICAgYm9keTogXCJ0aHJvdyBuZXcgRXJyb3IoXFxcIk5vdCBpbXBsZW1lbnRlZFxcXCIpXCIsXG4gICAgICAgICAgICBuYW1lOiBgbG9hZCR7aW5mbGVjdGlvbi5jYW1lbGl6ZShyZWxhdGlvbnNoaXAuZ2V0UmVsYXRpb25zaGlwTmFtZSgpKX1gLFxuICAgICAgICAgICAgcmV0dXJuczogYFByb21pc2U8QXJyYXk8aW1wb3J0KFwiJHtyZWNvcmRJbXBvcnR9XCIpLmRlZmF1bHQ+PmBcbiAgICAgICAgICB9KVxuXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCJcXG5cIlxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IGdlbmVyYXRlZFJlbGF0aW9uc2hpcE1ldGhvZCh7XG4gICAgICAgICAgICBib2R5OiBgcmV0dXJuIC8qKiBAdHlwZSB7UHJvbWlzZTxBcnJheTxpbXBvcnQoXCIke3JlY29yZEltcG9ydH1cIikuZGVmYXVsdD4+fSAqLyAodGhpcy5yZWxhdGlvbnNoaXBPckxvYWQoXCIke3JlbGF0aW9uc2hpcC5nZXRSZWxhdGlvbnNoaXBOYW1lKCl9XCIpKWAsXG4gICAgICAgICAgICBuYW1lOiBgJHtyZWxhdGlvbnNoaXAuZ2V0UmVsYXRpb25zaGlwTmFtZSgpfU9yTG9hZGAsXG4gICAgICAgICAgICByZXR1cm5zOiBgUHJvbWlzZTxBcnJheTxpbXBvcnQoXCIke3JlY29yZEltcG9ydH1cIikuZGVmYXVsdD4+YFxuICAgICAgICAgIH0pXG5cbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIlxcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgIC8qKlxcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgICAqIEBhYnN0cmFjdFxcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgICogQHBhcmFtIHtBcnJheTxpbXBvcnQoXCIke3JlY29yZEltcG9ydH1cIikuZGVmYXVsdD59IG5ld01vZGVsc1xcbmBcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICogQHJldHVybnMge3ZvaWR9XFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICovXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICBzZXQke2luZmxlY3Rpb24uY2FtZWxpemUocmVsYXRpb25zaGlwLmdldFJlbGF0aW9uc2hpcE5hbWUoKSl9KG5ld01vZGVscykgeyB2b2lkIG5ld01vZGVsczsgdGhyb3cgbmV3IEVycm9yKFwiTm90IGltcGxlbWVudGVkXCIpIH1cXG5gXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIHJlbGF0aW9uc2hpcCB0eXBlOiAke3JlbGF0aW9uc2hpcC5nZXRUeXBlKCl9YClcbiAgICAgICAgfVxuXG4gICAgICAgIG1ldGhvZHNDb3VudCsrXG4gICAgICB9XG5cbiAgICAgIC8vIFN0YXRlLW1hY2hpbmUgZXZlbnQgbWV0aG9kcy4gYE1vZGVsLnN0YXRlTWFjaGluZSguLi4pYCByZWdpc3RlcnMgdGhlc2Ugb24gdGhlIG1vZGVsJ3NcbiAgICAgIC8vIG93biBwcm90b3R5cGUgYXQgcnVudGltZTsgdGhvc2Ugb3ZlcnJpZGUgdGhlIHN0dWJzIGJlbG93IChkZWNsYXJlZCBvbiB0aGUgYmFzZSBjbGFzcyksXG4gICAgICAvLyBzbyB0aGVzZSB0aHJvd2luZyBzdHVicyBuZXZlciBleGVjdXRlLiBUaGV5IGV4aXN0IG9ubHkgc28gY2FsbCBzaXRlcyB0eXBlY2hlY2sgd2l0aG91dFxuICAgICAgLy8gdGhlIGNvbnN1bWVyIGhhbmQtd3JpdGluZyBib2lsZXJwbGF0ZS4gR3VhcmRlZCBvbiB0aGUgb3duIGBfc3RhdGVNYWNoaW5lRGVmaW5pdGlvbmBcbiAgICAgIC8vIHByb3BlcnR5IHNvIGEgc3ViY2xhc3Mgd2l0aG91dCBpdHMgb3duIG1hY2hpbmUgZG9lc24ndCByZS1lbWl0IHRoZSBwYXJlbnQncyBldmVudHMuXG4gICAgICBjb25zdCBzdGF0ZU1hY2hpbmVEZWZpbml0aW9uID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG1vZGVsQ2xhc3MsIFwiX3N0YXRlTWFjaGluZURlZmluaXRpb25cIilcbiAgICAgICAgPyBtb2RlbENsYXNzLmdldFN0YXRlTWFjaGluZURlZmluaXRpb24oKVxuICAgICAgICA6IG51bGxcblxuICAgICAgaWYgKHN0YXRlTWFjaGluZURlZmluaXRpb24pIHtcbiAgICAgICAgZm9yIChjb25zdCBldmVudE5hbWUgb2YgT2JqZWN0LmtleXMoc3RhdGVNYWNoaW5lRGVmaW5pdGlvbi5ldmVudHMpKSB7XG4gICAgICAgICAgLy8gYHN0YXRlTWFjaGluZSgpYCBpbnN0YWxscyBldmVudCBtZXRob2RzIHdpdGggYHByb3RvW2V2ZW50TmFtZV1gLCBzbyBpdCBhY2NlcHRzXG4gICAgICAgICAgLy8gZXZlbnQga2V5cyB0aGF0IGFyZW4ndCB2YWxpZCBKYXZhU2NyaXB0IGlkZW50aWZpZXJzIChlLmcuIFwicmV0cnktYnVpbGRcIikuIFRob3NlXG4gICAgICAgICAgLy8gY2FuJ3QgYmUgd3JpdHRlbiBhcyBjbGFzcyBtZXRob2RzIHdpdGhvdXQgcHJvZHVjaW5nIGFuIHVucGFyc2VhYmxlIGZpbGUsIHNvIHNraXBcbiAgICAgICAgICAvLyB0aGVtIGhlcmUg4oCUIHRoZXkgc3RpbGwgd29yayBhdCBydW50aW1lIHZpYSBicmFja2V0IGFjY2VzcywganVzdCB1bnR5cGVkLlxuICAgICAgICAgIGlmICghL15bQS1aYS16XyRdW0EtWmEtejAtOV8kXSokLy50ZXN0KGV2ZW50TmFtZSkpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihgU2tpcHBpbmcgZ2VuZXJhdGVkIHN0YXRlLW1hY2hpbmUgbWV0aG9kcyBmb3IgZXZlbnQgJyR7ZXZlbnROYW1lfScgb24gJyR7bW9kZWxDbGFzcy5uYW1lfSc6IHRoZSBldmVudCBuYW1lIGlzIG5vdCBhIHZhbGlkIEphdmFTY3JpcHQgaWRlbnRpZmllci5gKVxuXG4gICAgICAgICAgICBjb250aW51ZVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGNhcGl0YWxpemVkRXZlbnQgPSBldmVudE5hbWUuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBldmVudE5hbWUuc2xpY2UoMSlcblxuICAgICAgICAgIGlmIChtZXRob2RzQ291bnQgPiAwKSB7XG4gICAgICAgICAgICBmaWxlQ29udGVudCArPSBcIlxcblwiXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgIC8qKlxcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgICAqIEBhYnN0cmFjdFxcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgICAqIEByZXR1cm5zIHt2b2lkfVxcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gXCIgICAqL1xcblwiXG4gICAgICAgICAgZmlsZUNvbnRlbnQgKz0gYCAgJHtldmVudE5hbWV9KCkgeyB0aHJvdyBuZXcgRXJyb3IoXCJOb3QgaW1wbGVtZW50ZWRcIikgfVxcbmBcblxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgLyoqXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICogQGFic3RyYWN0XFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICovXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICAke2V2ZW50TmFtZX1BbmRTYXZlKCkgeyB0aHJvdyBuZXcgRXJyb3IoXCJOb3QgaW1wbGVtZW50ZWRcIikgfVxcbmBcblxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgLyoqXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICogQGFic3RyYWN0XFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICogQHJldHVybnMge2Jvb2xlYW59XFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICovXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICBjYW4ke2NhcGl0YWxpemVkRXZlbnR9KCkgeyB0aHJvdyBuZXcgRXJyb3IoXCJOb3QgaW1wbGVtZW50ZWRcIikgfVxcbmBcblxuICAgICAgICAgIGZpbGVDb250ZW50ICs9IFwiXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgLyoqXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICogQGFic3RyYWN0XFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICogQHJldHVybnMge1Byb21pc2U8Ym9vbGVhbj59XFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBcIiAgICovXFxuXCJcbiAgICAgICAgICBmaWxlQ29udGVudCArPSBgICBjYW4ke2NhcGl0YWxpemVkRXZlbnR9QXN5bmMoKSB7IHRocm93IG5ldyBFcnJvcihcIk5vdCBpbXBsZW1lbnRlZFwiKSB9XFxuYFxuXG4gICAgICAgICAgbWV0aG9kc0NvdW50KytcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmaWxlQ29udGVudCArPSBcIn1cXG5cIlxuXG4gICAgICAgIGF3YWl0IGZzLndyaXRlRmlsZShtb2RlbFBhdGgsIGZpbGVDb250ZW50KVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGpzIGRvYyB0eXBlIGZyb20gY29sdW1uLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uLy4uLy4uLy4uL2RhdGFiYXNlL2RyaXZlcnMvYmFzZS1jb2x1bW4uanNcIikuZGVmYXVsdH0gY29sdW1uIC0gQ29sdW1uLlxuICAgKiBAcGFyYW0ge3R5cGVvZiBpbXBvcnQoXCIuLi8uLi8uLi8uLi8uLi9kYXRhYmFzZS9yZWNvcmQvaW5kZXguanNcIikuZGVmYXVsdH0gbW9kZWxDbGFzcyAtIE1vZGVsIGNsYXNzIG93bmluZyB0aGUgY29sdW1uIChmb3IgZGVjbGFyZWQgYXR0cmlidXRlIGNhc3RzKS5cbiAgICogQHJldHVybnMge3N0cmluZyB8IHVuZGVmaW5lZH0gLSBUaGUganMgZG9jIHR5cGUgZnJvbSBjb2x1bW4uXG4gICAqL1xuICBqc0RvY1R5cGVGcm9tQ29sdW1uKGNvbHVtbiwgbW9kZWxDbGFzcykge1xuICAgIGNvbnN0IHR5cGUgPSBtb2RlbENsYXNzLmdldENvbHVtblR5cGVCeU5hbWUoY29sdW1uLmdldE5hbWUoKSlcbiAgICBjb25zdCBqc0RvY1R5cGUgPSB0eXBlID8ganNEb2NUeXBlQnlDb2x1bW5UeXBlW3R5cGVdIDogdW5kZWZpbmVkXG5cbiAgICBpZiAoIWpzRG9jVHlwZSkge1xuICAgICAgY29uc29sZS5lcnJvcihgVW5rbm93biBjb2x1bW4gdHlwZTogJHt0eXBlfWApXG5cbiAgICAgIHJldHVybiB1bmRlZmluZWRcbiAgICB9XG5cbiAgICByZXR1cm4ganNEb2NUeXBlXG4gIH1cblxuICAvKipcbiAgICogUnVucyBqcyBkb2Mgc2V0dGVyIHR5cGUgZnJvbSBjb2x1bW4uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vLi4vLi4vLi4vZGF0YWJhc2UvZHJpdmVycy9iYXNlLWNvbHVtbi5qc1wiKS5kZWZhdWx0fSBjb2x1bW4gLSBDb2x1bW4uXG4gICAqIEBwYXJhbSB7dHlwZW9mIGltcG9ydChcIi4uLy4uLy4uLy4uLy4uL2RhdGFiYXNlL3JlY29yZC9pbmRleC5qc1wiKS5kZWZhdWx0fSBtb2RlbENsYXNzIC0gTW9kZWwgY2xhc3Mgb3duaW5nIHRoZSBjb2x1bW4gKGZvciBkZWNsYXJlZCBhdHRyaWJ1dGUgY2FzdHMpLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nIHwgdW5kZWZpbmVkfSAtIFRoZSBqcyBkb2Mgc2V0dGVyIHR5cGUgZnJvbSBjb2x1bW4uXG4gICAqL1xuICBqc0RvY1NldHRlclR5cGVGcm9tQ29sdW1uKGNvbHVtbiwgbW9kZWxDbGFzcykge1xuICAgIGNvbnN0IHR5cGUgPSBtb2RlbENsYXNzLmdldENvbHVtblR5cGVCeU5hbWUoY29sdW1uLmdldE5hbWUoKSlcblxuICAgIGlmICh0eXBlICYmIHNldHRlclN0cmluZ0lucHV0Q29sdW1uVHlwZXMuaGFzKHR5cGUpKSB7XG4gICAgICByZXR1cm4gXCJEYXRlIHwgc3RyaW5nXCJcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5qc0RvY1R5cGVGcm9tQ29sdW1uKGNvbHVtbiwgbW9kZWxDbGFzcylcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGJlbG9uZ3MgdG8gd3JpdGUgYXR0cmlidXRlcyBmb3IgbW9kZWwuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gQXJndW1lbnRzLlxuICAgKiBAcGFyYW0ge3R5cGVvZiBpbXBvcnQoXCIuLi8uLi8uLi8uLi8uLi9kYXRhYmFzZS9yZWNvcmQvaW5kZXguanNcIikuZGVmYXVsdH0gYXJncy5tb2RlbENsYXNzIC0gTW9kZWwgY2xhc3MuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLm1vZGVsc0RpciAtIFNvdXJjZSBtb2RlbHMgZGlyZWN0b3J5LlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxBcnJheTx7cHJvcGVydHlOYW1lOiBzdHJpbmcsIHByb3BlcnR5VHlwZTogc3RyaW5nLCByZWxhdGlvbnNoaXBOYW1lOiBzdHJpbmd9Pj59IC0gQmVsb25ncy10byB3cml0ZSBhdHRyaWJ1dGVzLlxuICAgKi9cbiAgYXN5bmMgYmVsb25nc1RvV3JpdGVBdHRyaWJ1dGVzRm9yTW9kZWwoe21vZGVsQ2xhc3MsIG1vZGVsc0Rpcn0pIHtcbiAgICBjb25zdCB3cml0ZUF0dHJpYnV0ZXMgPSBbXVxuXG4gICAgZm9yIChjb25zdCByZWxhdGlvbnNoaXAgb2YgbW9kZWxDbGFzcy5nZXRSZWxhdGlvbnNoaXBzKCkpIHtcbiAgICAgIGlmIChyZWxhdGlvbnNoaXAuZ2V0VHlwZSgpICE9PSBcImJlbG9uZ3NUb1wiKSBjb250aW51ZVxuICAgICAgaWYgKHJlbGF0aW9uc2hpcC5nZXRQb2x5bW9ycGhpYygpKSBjb250aW51ZVxuXG4gICAgICBjb25zdCB0YXJnZXRNb2RlbENsYXNzID0gcmVsYXRpb25zaGlwLmdldFRhcmdldE1vZGVsQ2xhc3MoKVxuXG4gICAgICBpZiAoIXRhcmdldE1vZGVsQ2xhc3MpIHRocm93IG5ldyBFcnJvcihgUmVsYXRpb25zaGlwICcke3JlbGF0aW9uc2hpcC5nZXRSZWxhdGlvbnNoaXBOYW1lKCl9JyBvbiAnJHttb2RlbENsYXNzLmdldE1vZGVsTmFtZSgpfScgaGFzIG5vIHRhcmdldCBtb2RlbCBjbGFzc2ApXG5cbiAgICAgIGNvbnN0IHRhcmdldE1vZGVsRmlsZU5hbWUgPSBpbmZsZWN0aW9uLmRhc2hlcml6ZShpbmZsZWN0aW9uLnVuZGVyc2NvcmUodGFyZ2V0TW9kZWxDbGFzcy5nZXRNb2RlbE5hbWUoKSkpXG4gICAgICBjb25zdCB0YXJnZXRNb2RlbFBhdGggPSBgJHttb2RlbHNEaXJ9LyR7dGFyZ2V0TW9kZWxGaWxlTmFtZX0uanNgXG4gICAgICBjb25zdCB0YXJnZXRJbXBvcnRQYXRoID0gYXdhaXQgZmlsZUV4aXN0cyh0YXJnZXRNb2RlbFBhdGgpID8gYC4uL21vZGVscy8ke3RhcmdldE1vZGVsRmlsZU5hbWV9LmpzYCA6IGAuLyR7dGFyZ2V0TW9kZWxGaWxlTmFtZX0uanNgXG5cbiAgICAgIHdyaXRlQXR0cmlidXRlcy5wdXNoKHtcbiAgICAgICAgcHJvcGVydHlOYW1lOiByZWxhdGlvbnNoaXAuZ2V0UmVsYXRpb25zaGlwTmFtZSgpLFxuICAgICAgICBwcm9wZXJ0eVR5cGU6IGBpbXBvcnQoXCIke3RhcmdldEltcG9ydFBhdGh9XCIpLmRlZmF1bHRgLFxuICAgICAgICByZWxhdGlvbnNoaXBOYW1lOiByZWxhdGlvbnNoaXAuZ2V0UmVsYXRpb25zaGlwTmFtZSgpXG4gICAgICB9KVxuICAgIH1cblxuICAgIHJldHVybiB3cml0ZUF0dHJpYnV0ZXNcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIG5lc3RlZCB3cml0ZSBhdHRyaWJ1dGVzIGZvciBtb2RlbC5cbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBBcmd1bWVudHMuXG4gICAqIEBwYXJhbSB7dHlwZW9mIGltcG9ydChcIi4uLy4uLy4uLy4uLy4uL2RhdGFiYXNlL3JlY29yZC9pbmRleC5qc1wiKS5kZWZhdWx0fSBhcmdzLm1vZGVsQ2xhc3MgLSBNb2RlbCBjbGFzcy5cbiAgICogQHJldHVybnMge0FycmF5PHtwcm9wZXJ0eU5hbWU6IHN0cmluZywgcHJvcGVydHlUeXBlOiBzdHJpbmcsIHJlbGF0aW9uc2hpcE5hbWU6IHN0cmluZ30+fSAtIE5lc3RlZCB3cml0ZSBhdHRyaWJ1dGVzLlxuICAgKi9cbiAgbmVzdGVkV3JpdGVBdHRyaWJ1dGVzRm9yTW9kZWwoe21vZGVsQ2xhc3N9KSB7XG4gICAgY29uc3QgYWNjZXB0ZWROZXN0ZWRBdHRyaWJ1dGVzID0gbW9kZWxDbGFzcy5fYWNjZXB0ZWROZXN0ZWRBdHRyaWJ1dGVzIHx8IHt9XG4gICAgY29uc3QgbmVzdGVkV3JpdGVBdHRyaWJ1dGVzID0gW11cblxuICAgIGZvciAoY29uc3QgcmVsYXRpb25zaGlwTmFtZSBvZiBPYmplY3Qua2V5cyhhY2NlcHRlZE5lc3RlZEF0dHJpYnV0ZXMpKSB7XG4gICAgICBjb25zdCByZWxhdGlvbnNoaXAgPSBtb2RlbENsYXNzLmdldFJlbGF0aW9uc2hpcEJ5TmFtZShyZWxhdGlvbnNoaXBOYW1lKVxuICAgICAgY29uc3QgcmVsYXRpb25zaGlwVHlwZSA9IHJlbGF0aW9uc2hpcC5nZXRUeXBlKClcbiAgICAgIGNvbnN0IHRhcmdldE1vZGVsQ2xhc3MgPSByZWxhdGlvbnNoaXAuZ2V0VGFyZ2V0TW9kZWxDbGFzcygpXG5cbiAgICAgIGlmICghdGFyZ2V0TW9kZWxDbGFzcykgdGhyb3cgbmV3IEVycm9yKGBSZWxhdGlvbnNoaXAgJyR7cmVsYXRpb25zaGlwTmFtZX0nIG9uICcke21vZGVsQ2xhc3MuZ2V0TW9kZWxOYW1lKCl9JyBoYXMgbm8gdGFyZ2V0IG1vZGVsIGNsYXNzYClcblxuICAgICAgY29uc3QgdGFyZ2V0TW9kZWxGaWxlTmFtZSA9IGluZmxlY3Rpb24uZGFzaGVyaXplKGluZmxlY3Rpb24udW5kZXJzY29yZSh0YXJnZXRNb2RlbENsYXNzLmdldE1vZGVsTmFtZSgpKSlcbiAgICAgIGNvbnN0IHRhcmdldFdyaXRlVHlwZU5hbWUgPSBgJHtpbmZsZWN0aW9uLmNhbWVsaXplKHRhcmdldE1vZGVsQ2xhc3MuZ2V0TW9kZWxOYW1lKCkucmVwbGFjZUFsbChcIi1cIiwgXCJfXCIpKX1Xcml0ZUF0dHJpYnV0ZXNgXG4gICAgICBjb25zdCBuZXN0ZWRUeXBlID0gYGltcG9ydChcIi4vJHt0YXJnZXRNb2RlbEZpbGVOYW1lfS5qc1wiKS4ke3RhcmdldFdyaXRlVHlwZU5hbWV9JHthY2NlcHRlZE5lc3RlZEF0dHJpYnV0ZXNbcmVsYXRpb25zaGlwTmFtZV0/LmFsbG93RGVzdHJveSA/IFwiICYge19kZXN0cm95PzogYm9vbGVhbn1cIiA6IFwiXCJ9YFxuXG4gICAgICBuZXN0ZWRXcml0ZUF0dHJpYnV0ZXMucHVzaCh7XG4gICAgICAgIHByb3BlcnR5TmFtZTogYCR7cmVsYXRpb25zaGlwTmFtZX1BdHRyaWJ1dGVzYCxcbiAgICAgICAgcHJvcGVydHlUeXBlOiByZWxhdGlvbnNoaXBUeXBlID09IFwiaGFzTWFueVwiID8gYEFycmF5PCR7bmVzdGVkVHlwZX0+YCA6IG5lc3RlZFR5cGUsXG4gICAgICAgIHJlbGF0aW9uc2hpcE5hbWVcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgcmV0dXJuIG5lc3RlZFdyaXRlQXR0cmlidXRlc1xuICB9XG59XG4iXX0=