@cdklabs/cdk-appmod-catalog-blueprints 1.4.1 → 1.6.0

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 (93) hide show
  1. package/.jsii +2579 -194
  2. package/lib/document-processing/adapter/adapter.d.ts +4 -2
  3. package/lib/document-processing/adapter/adapter.js +1 -1
  4. package/lib/document-processing/adapter/queued-s3-adapter.d.ts +9 -2
  5. package/lib/document-processing/adapter/queued-s3-adapter.js +29 -15
  6. package/lib/document-processing/agentic-document-processing.d.ts +4 -0
  7. package/lib/document-processing/agentic-document-processing.js +20 -10
  8. package/lib/document-processing/base-document-processing.d.ts +54 -2
  9. package/lib/document-processing/base-document-processing.js +136 -82
  10. package/lib/document-processing/bedrock-document-processing.d.ts +202 -2
  11. package/lib/document-processing/bedrock-document-processing.js +717 -77
  12. package/lib/document-processing/chunking-config.d.ts +614 -0
  13. package/lib/document-processing/chunking-config.js +5 -0
  14. package/lib/document-processing/default-document-processing-config.js +1 -1
  15. package/lib/document-processing/index.d.ts +1 -0
  16. package/lib/document-processing/index.js +2 -1
  17. package/lib/document-processing/resources/aggregation/handler.py +567 -0
  18. package/lib/document-processing/resources/aggregation/requirements.txt +7 -0
  19. package/lib/document-processing/resources/aggregation/test_handler.py +362 -0
  20. package/lib/document-processing/resources/cleanup/handler.py +276 -0
  21. package/lib/document-processing/resources/cleanup/requirements.txt +5 -0
  22. package/lib/document-processing/resources/cleanup/test_handler.py +436 -0
  23. package/lib/document-processing/resources/default-bedrock-invoke/index.py +85 -3
  24. package/lib/document-processing/resources/default-bedrock-invoke/test_index.py +622 -0
  25. package/lib/document-processing/resources/pdf-chunking/README.md +313 -0
  26. package/lib/document-processing/resources/pdf-chunking/chunking_strategies.py +460 -0
  27. package/lib/document-processing/resources/pdf-chunking/error_handling.py +491 -0
  28. package/lib/document-processing/resources/pdf-chunking/handler.py +958 -0
  29. package/lib/document-processing/resources/pdf-chunking/metrics.py +435 -0
  30. package/lib/document-processing/resources/pdf-chunking/requirements.txt +3 -0
  31. package/lib/document-processing/resources/pdf-chunking/strategy_selection.py +420 -0
  32. package/lib/document-processing/resources/pdf-chunking/structured_logging.py +457 -0
  33. package/lib/document-processing/resources/pdf-chunking/test_chunking_strategies.py +353 -0
  34. package/lib/document-processing/resources/pdf-chunking/test_error_handling.py +487 -0
  35. package/lib/document-processing/resources/pdf-chunking/test_handler.py +609 -0
  36. package/lib/document-processing/resources/pdf-chunking/test_integration.py +694 -0
  37. package/lib/document-processing/resources/pdf-chunking/test_metrics.py +532 -0
  38. package/lib/document-processing/resources/pdf-chunking/test_strategy_selection.py +471 -0
  39. package/lib/document-processing/resources/pdf-chunking/test_structured_logging.py +449 -0
  40. package/lib/document-processing/resources/pdf-chunking/test_token_estimation.py +374 -0
  41. package/lib/document-processing/resources/pdf-chunking/token_estimation.py +189 -0
  42. package/lib/document-processing/tests/agentic-document-processing-nag.test.js +4 -3
  43. package/lib/document-processing/tests/agentic-document-processing.test.js +488 -4
  44. package/lib/document-processing/tests/base-document-processing-nag.test.js +9 -2
  45. package/lib/document-processing/tests/base-document-processing-schema.test.d.ts +1 -0
  46. package/lib/document-processing/tests/base-document-processing-schema.test.js +337 -0
  47. package/lib/document-processing/tests/base-document-processing.test.js +114 -8
  48. package/lib/document-processing/tests/bedrock-document-processing-chunking-nag.test.d.ts +1 -0
  49. package/lib/document-processing/tests/bedrock-document-processing-chunking-nag.test.js +382 -0
  50. package/lib/document-processing/tests/bedrock-document-processing-nag.test.js +4 -3
  51. package/lib/document-processing/tests/bedrock-document-processing-security.test.d.ts +1 -0
  52. package/lib/document-processing/tests/bedrock-document-processing-security.test.js +389 -0
  53. package/lib/document-processing/tests/bedrock-document-processing.test.js +808 -8
  54. package/lib/document-processing/tests/chunking-config.test.d.ts +1 -0
  55. package/lib/document-processing/tests/chunking-config.test.js +238 -0
  56. package/lib/document-processing/tests/queued-s3-adapter-nag.test.js +9 -2
  57. package/lib/document-processing/tests/queued-s3-adapter.test.js +17 -6
  58. package/lib/framework/agents/base-agent.js +1 -1
  59. package/lib/framework/agents/batch-agent.js +1 -1
  60. package/lib/framework/agents/default-agent-config.js +1 -1
  61. package/lib/framework/bedrock/bedrock.js +1 -1
  62. package/lib/framework/custom-resource/default-runtimes.js +1 -1
  63. package/lib/framework/foundation/access-log.js +1 -1
  64. package/lib/framework/foundation/eventbridge-broker.js +1 -1
  65. package/lib/framework/foundation/network.d.ts +4 -2
  66. package/lib/framework/foundation/network.js +52 -41
  67. package/lib/framework/tests/access-log.test.js +5 -2
  68. package/lib/framework/tests/batch-agent.test.js +5 -2
  69. package/lib/framework/tests/bedrock.test.js +5 -2
  70. package/lib/framework/tests/eventbridge-broker.test.js +5 -2
  71. package/lib/framework/tests/framework-nag.test.js +26 -7
  72. package/lib/framework/tests/network.test.js +30 -2
  73. package/lib/tsconfig.tsbuildinfo +1 -1
  74. package/lib/utilities/data-loader.js +1 -1
  75. package/lib/utilities/lambda-iam-utils.js +1 -1
  76. package/lib/utilities/observability/cloudfront-distribution-observability-property-injector.js +1 -1
  77. package/lib/utilities/observability/default-observability-config.js +1 -1
  78. package/lib/utilities/observability/lambda-observability-property-injector.js +1 -1
  79. package/lib/utilities/observability/log-group-data-protection-utils.js +1 -1
  80. package/lib/utilities/observability/powertools-config.d.ts +10 -1
  81. package/lib/utilities/observability/powertools-config.js +19 -3
  82. package/lib/utilities/observability/state-machine-observability-property-injector.js +1 -1
  83. package/lib/utilities/test-utils.d.ts +43 -0
  84. package/lib/utilities/test-utils.js +56 -0
  85. package/lib/utilities/tests/data-loader-nag.test.js +3 -2
  86. package/lib/utilities/tests/data-loader.test.js +3 -2
  87. package/lib/webapp/frontend-construct.js +1 -1
  88. package/lib/webapp/tests/frontend-construct-nag.test.js +3 -2
  89. package/lib/webapp/tests/frontend-construct.test.js +3 -2
  90. package/package.json +6 -5
  91. package/lib/document-processing/resources/default-error-handler/index.js +0 -46
  92. package/lib/document-processing/resources/default-pdf-processor/index.js +0 -46
  93. package/lib/document-processing/resources/default-pdf-validator/index.js +0 -36
@@ -11,6 +11,7 @@ const aws_cdk_lib_1 = require("aws-cdk-lib");
11
11
  const aws_ec2_1 = require("aws-cdk-lib/aws-ec2");
12
12
  const aws_iam_1 = require("aws-cdk-lib/aws-iam");
13
13
  const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
14
+ const aws_stepfunctions_1 = require("aws-cdk-lib/aws-stepfunctions");
14
15
  const aws_stepfunctions_tasks_1 = require("aws-cdk-lib/aws-stepfunctions-tasks");
15
16
  const base_document_processing_1 = require("./base-document-processing");
16
17
  const framework_1 = require("../framework");
@@ -58,9 +59,24 @@ class BedrockDocumentProcessing extends base_document_processing_1.BaseDocumentP
58
59
  * @param scope - The scope in which to define this construct
59
60
  * @param id - The scoped construct ID. Must be unique within the scope.
60
61
  * @param props - Configuration properties for the Bedrock document processing pipeline
62
+ * @throws Error if chunking configuration is invalid
61
63
  */
62
64
  constructor(scope, id, props) {
63
65
  super(scope, id, props);
66
+ /** Counter for generating unique classification step IDs */
67
+ this._classificationStepCounter = 0;
68
+ /** Counter for generating unique processing step IDs */
69
+ this._processingStepCounter = 0;
70
+ /** Counter for generating unique aggregation step IDs */
71
+ this._aggregationStepCounter = 0;
72
+ /** Counter for generating unique enrichment step IDs */
73
+ this._enrichmentStepCounter = 0;
74
+ /** Counter for generating unique post-processing step IDs */
75
+ this._postProcessingStepCounter = 0;
76
+ // Validate chunking configuration if provided
77
+ if (props.enableChunking && props.chunkingConfig) {
78
+ this.validateChunkingConfig(props.chunkingConfig);
79
+ }
64
80
  if (props.network) {
65
81
  props.network.createServiceEndpoint('vpce-bedrock', aws_ec2_1.InterfaceVpcEndpointAwsService.BEDROCK);
66
82
  props.network.createServiceEndpoint('vpce-bedrock-runtime', aws_ec2_1.InterfaceVpcEndpointAwsService.BEDROCK_RUNTIME);
@@ -68,6 +84,77 @@ class BedrockDocumentProcessing extends base_document_processing_1.BaseDocumentP
68
84
  this.bedrockDocumentProcessingProps = props;
69
85
  this.stateMachine = this.handleStateMachineCreation('bedrock-document-processing-workflow');
70
86
  }
87
+ /**
88
+ * Validates the chunking configuration parameters.
89
+ *
90
+ * Ensures that:
91
+ * - Chunk size is greater than 0
92
+ * - Overlap is non-negative and less than chunk size
93
+ * - Thresholds are greater than 0
94
+ * - Max concurrency is greater than 0
95
+ * - Min success threshold is between 0 and 1
96
+ *
97
+ * @param config - The chunking configuration to validate
98
+ * @throws Error if any configuration parameter is invalid
99
+ */
100
+ validateChunkingConfig(config) {
101
+ // Validate chunk size (for fixed-pages strategy)
102
+ if (config.chunkSize !== undefined) {
103
+ if (config.chunkSize <= 0) {
104
+ throw new Error('ChunkingConfig validation error: chunkSize must be greater than 0');
105
+ }
106
+ }
107
+ // Validate overlap pages (for fixed-pages strategy)
108
+ if (config.overlapPages !== undefined) {
109
+ if (config.overlapPages < 0) {
110
+ throw new Error('ChunkingConfig validation error: overlapPages must be non-negative');
111
+ }
112
+ const effectiveChunkSize = config.chunkSize || 50; // default chunk size
113
+ if (config.overlapPages >= effectiveChunkSize) {
114
+ throw new Error('ChunkingConfig validation error: overlapPages must be less than chunkSize');
115
+ }
116
+ }
117
+ // Validate page threshold
118
+ if (config.pageThreshold !== undefined && config.pageThreshold <= 0) {
119
+ throw new Error('ChunkingConfig validation error: pageThreshold must be greater than 0');
120
+ }
121
+ // Validate token threshold
122
+ if (config.tokenThreshold !== undefined && config.tokenThreshold <= 0) {
123
+ throw new Error('ChunkingConfig validation error: tokenThreshold must be greater than 0');
124
+ }
125
+ // Validate max tokens per chunk (for token-based strategy)
126
+ if (config.maxTokensPerChunk !== undefined && config.maxTokensPerChunk <= 0) {
127
+ throw new Error('ChunkingConfig validation error: maxTokensPerChunk must be greater than 0');
128
+ }
129
+ // Validate overlap tokens (for token-based and hybrid strategies)
130
+ if (config.overlapTokens !== undefined) {
131
+ if (config.overlapTokens < 0) {
132
+ throw new Error('ChunkingConfig validation error: overlapTokens must be non-negative');
133
+ }
134
+ const effectiveMaxTokens = config.maxTokensPerChunk || 100000; // default max tokens
135
+ if (config.overlapTokens >= effectiveMaxTokens) {
136
+ throw new Error('ChunkingConfig validation error: overlapTokens must be less than maxTokensPerChunk');
137
+ }
138
+ }
139
+ // Validate max pages per chunk (for hybrid strategy)
140
+ if (config.maxPagesPerChunk !== undefined && config.maxPagesPerChunk <= 0) {
141
+ throw new Error('ChunkingConfig validation error: maxPagesPerChunk must be greater than 0');
142
+ }
143
+ // Validate target tokens per chunk (for hybrid strategy)
144
+ if (config.targetTokensPerChunk !== undefined && config.targetTokensPerChunk <= 0) {
145
+ throw new Error('ChunkingConfig validation error: targetTokensPerChunk must be greater than 0');
146
+ }
147
+ // Validate max concurrency
148
+ if (config.maxConcurrency !== undefined && config.maxConcurrency <= 0) {
149
+ throw new Error('ChunkingConfig validation error: maxConcurrency must be greater than 0');
150
+ }
151
+ // Validate min success threshold
152
+ if (config.minSuccessThreshold !== undefined) {
153
+ if (config.minSuccessThreshold < 0 || config.minSuccessThreshold > 1) {
154
+ throw new Error('ChunkingConfig validation error: minSuccessThreshold must be between 0 and 1');
155
+ }
156
+ }
157
+ }
71
158
  /**
72
159
  * Implements the document classification step using Amazon Bedrock.
73
160
  *
@@ -75,47 +162,60 @@ class BedrockDocumentProcessing extends base_document_processing_1.BaseDocumentP
75
162
  * the document type. The function reads the document from S3 and sends it to
76
163
  * Bedrock with the classification prompt.
77
164
  *
165
+ * This method caches the Lambda function to avoid creating duplicate resources,
166
+ * but creates a new LambdaInvoke task each time to allow proper state chaining.
167
+ *
78
168
  * @returns LambdaInvoke task configured for document classification
79
169
  */
80
170
  classificationStep() {
81
- const prompt = this.bedrockDocumentProcessingProps.classificationPrompt || BedrockDocumentProcessing.DEFAULT_CLASSIFICATION_PROMPT;
82
- const adjustedModelId = bedrock_1.BedrockModelUtils.deriveActualModelId(this.bedrockDocumentProcessingProps.classificationBedrockModel);
83
- const role = this.generateLambdaRoleForBedrock('ClassificationLambdaRole', this.bedrockDocumentProcessingProps.classificationBedrockModel);
84
- const { region, account } = aws_cdk_lib_1.Stack.of(this);
85
- const generatedLogPermissions = utilities_1.LambdaIamUtils.createLogsPermissions({
86
- account,
87
- functionName: 'bedrock-idp-classification',
88
- region,
89
- scope: this,
90
- enableObservability: this.bedrockDocumentProcessingProps.enableObservability,
91
- });
92
- this.encryptionKey.grantEncryptDecrypt(role);
93
- const bedrockFunction = new aws_lambda_python_alpha_1.PythonFunction(this, 'BedrockClassificationFunction', {
94
- functionName: generatedLogPermissions.uniqueFunctionName,
95
- architecture: aws_lambda_1.Architecture.X86_64,
96
- runtime: framework_1.DefaultRuntimes.PYTHON,
97
- entry: path.join(__dirname, 'resources/default-bedrock-invoke'),
98
- role,
99
- memorySize: 512,
100
- timeout: this.bedrockDocumentProcessingProps.stepTimeouts || aws_cdk_lib_1.Duration.minutes(5),
101
- environment: {
102
- MODEL_ID: adjustedModelId,
103
- PROMPT: prompt,
104
- INVOKE_TYPE: 'classification',
105
- ...powertools_config_1.PowertoolsConfig.generateDefaultLambdaConfig(this.bedrockDocumentProcessingProps.enableObservability, this.metricNamespace, this.metricServiceName),
106
- },
107
- environmentEncryption: this.encryptionKey,
108
- vpc: this.bedrockDocumentProcessingProps.network ? this.bedrockDocumentProcessingProps.network.vpc : undefined,
109
- vpcSubnets: this.bedrockDocumentProcessingProps.network ? this.bedrockDocumentProcessingProps.network.applicationSubnetSelection() : undefined,
110
- });
111
- for (const statement of generatedLogPermissions.policyStatements) {
112
- bedrockFunction.role?.addToPrincipalPolicy(statement);
113
- }
114
- if (this.bedrockDocumentProcessingProps.network) {
115
- bedrockFunction.role?.addToPrincipalPolicy(utilities_1.LambdaIamUtils.generateLambdaVPCPermissions());
171
+ // Create Lambda function only once
172
+ if (!this._classificationFunction) {
173
+ const prompt = this.bedrockDocumentProcessingProps.classificationPrompt || BedrockDocumentProcessing.DEFAULT_CLASSIFICATION_PROMPT;
174
+ const adjustedModelId = bedrock_1.BedrockModelUtils.deriveActualModelId(this.bedrockDocumentProcessingProps.classificationBedrockModel);
175
+ const role = this.generateLambdaRoleForBedrock('ClassificationLambdaRole', this.bedrockDocumentProcessingProps.classificationBedrockModel);
176
+ const { region, account } = aws_cdk_lib_1.Stack.of(this);
177
+ const generatedLogPermissions = utilities_1.LambdaIamUtils.createLogsPermissions({
178
+ account,
179
+ functionName: 'bedrock-idp-classification',
180
+ region,
181
+ scope: this,
182
+ enableObservability: this.bedrockDocumentProcessingProps.enableObservability,
183
+ });
184
+ this.encryptionKey.grantEncryptDecrypt(role);
185
+ this._classificationFunction = new aws_lambda_python_alpha_1.PythonFunction(this, 'BedrockClassificationFunction', {
186
+ functionName: generatedLogPermissions.uniqueFunctionName,
187
+ architecture: aws_lambda_1.Architecture.X86_64,
188
+ runtime: framework_1.DefaultRuntimes.PYTHON,
189
+ entry: path.join(__dirname, 'resources/default-bedrock-invoke'),
190
+ role,
191
+ memorySize: 512,
192
+ timeout: this.bedrockDocumentProcessingProps.stepTimeouts || aws_cdk_lib_1.Duration.minutes(5),
193
+ environment: {
194
+ MODEL_ID: adjustedModelId,
195
+ PROMPT: prompt,
196
+ INVOKE_TYPE: 'classification',
197
+ ...powertools_config_1.PowertoolsConfig.generateDefaultLambdaConfig(this.bedrockDocumentProcessingProps.enableObservability, this.metricNamespace, this.metricServiceName),
198
+ },
199
+ environmentEncryption: this.encryptionKey,
200
+ vpc: this.bedrockDocumentProcessingProps.network
201
+ ? this.bedrockDocumentProcessingProps.network.vpc
202
+ : undefined,
203
+ vpcSubnets: this.bedrockDocumentProcessingProps.network
204
+ ? this.bedrockDocumentProcessingProps.network.applicationSubnetSelection()
205
+ : undefined,
206
+ });
207
+ for (const statement of generatedLogPermissions.policyStatements) {
208
+ this._classificationFunction.role?.addToPrincipalPolicy(statement);
209
+ }
210
+ if (this.bedrockDocumentProcessingProps.network) {
211
+ this._classificationFunction.role?.addToPrincipalPolicy(utilities_1.LambdaIamUtils.generateLambdaVPCPermissions());
212
+ }
116
213
  }
117
- return new aws_stepfunctions_tasks_1.LambdaInvoke(this, 'ClassificationStep', {
118
- lambdaFunction: bedrockFunction,
214
+ // Always create a new LambdaInvoke task to allow proper state chaining
215
+ const stepId = `ClassificationStep-${this._classificationStepCounter}`;
216
+ this._classificationStepCounter++;
217
+ return new aws_stepfunctions_tasks_1.LambdaInvoke(this, stepId, {
218
+ lambdaFunction: this._classificationFunction,
119
219
  resultPath: '$.classificationResult',
120
220
  resultSelector: {
121
221
  'documentClassification.$': '$.Payload.documentClassification',
@@ -129,46 +229,59 @@ class BedrockDocumentProcessing extends base_document_processing_1.BaseDocumentP
129
229
  * structured data from the document. Uses the classification result from the
130
230
  * previous step to provide context for more accurate extraction.
131
231
  *
232
+ * This method caches the Lambda function to avoid creating duplicate resources,
233
+ * but creates a new LambdaInvoke task each time to allow proper state chaining.
234
+ *
132
235
  * @returns LambdaInvoke task configured for document extraction
133
236
  */
134
237
  processingStep() {
135
- const prompt = this.bedrockDocumentProcessingProps.processingPrompt || BedrockDocumentProcessing.DEFAULT_PROCESSING_PROMPT;
136
- const adjustedModelId = bedrock_1.BedrockModelUtils.deriveActualModelId(this.bedrockDocumentProcessingProps.processingBedrockModel);
137
- const role = this.generateLambdaRoleForBedrock('ProcessingLambdaRole', this.bedrockDocumentProcessingProps.processingBedrockModel);
138
- const { region, account } = aws_cdk_lib_1.Stack.of(this);
139
- const generatedLogPermissions = utilities_1.LambdaIamUtils.createLogsPermissions({
140
- account,
141
- functionName: 'bedrock-idp-processing',
142
- region,
143
- scope: this,
144
- });
145
- this.encryptionKey.grantEncryptDecrypt(role);
146
- const bedrockFunction = new aws_lambda_python_alpha_1.PythonFunction(this, 'BedrockExtractionFunction', {
147
- functionName: generatedLogPermissions.uniqueFunctionName,
148
- runtime: framework_1.DefaultRuntimes.PYTHON,
149
- architecture: aws_lambda_1.Architecture.X86_64,
150
- entry: path.join(__dirname, 'resources/default-bedrock-invoke'),
151
- role,
152
- memorySize: 512,
153
- timeout: this.bedrockDocumentProcessingProps.stepTimeouts || aws_cdk_lib_1.Duration.minutes(5),
154
- environment: {
155
- MODEL_ID: adjustedModelId,
156
- PROMPT: prompt,
157
- INVOKE_TYPE: 'processing',
158
- ...powertools_config_1.PowertoolsConfig.generateDefaultLambdaConfig(this.bedrockDocumentProcessingProps.enableObservability, this.metricNamespace, this.metricServiceName),
159
- },
160
- environmentEncryption: this.encryptionKey,
161
- vpc: this.bedrockDocumentProcessingProps.network ? this.bedrockDocumentProcessingProps.network.vpc : undefined,
162
- vpcSubnets: this.bedrockDocumentProcessingProps.network ? this.bedrockDocumentProcessingProps.network.applicationSubnetSelection() : undefined,
163
- });
164
- for (const statement of generatedLogPermissions.policyStatements) {
165
- bedrockFunction.role?.addToPrincipalPolicy(statement);
166
- }
167
- if (this.bedrockDocumentProcessingProps.network) {
168
- bedrockFunction.role?.addToPrincipalPolicy(utilities_1.LambdaIamUtils.generateLambdaVPCPermissions());
238
+ // Create Lambda function only once
239
+ if (!this._processingFunction) {
240
+ const prompt = this.bedrockDocumentProcessingProps.processingPrompt || BedrockDocumentProcessing.DEFAULT_PROCESSING_PROMPT;
241
+ const adjustedModelId = bedrock_1.BedrockModelUtils.deriveActualModelId(this.bedrockDocumentProcessingProps.processingBedrockModel);
242
+ const role = this.generateLambdaRoleForBedrock('ProcessingLambdaRole', this.bedrockDocumentProcessingProps.processingBedrockModel);
243
+ const { region, account } = aws_cdk_lib_1.Stack.of(this);
244
+ const generatedLogPermissions = utilities_1.LambdaIamUtils.createLogsPermissions({
245
+ account,
246
+ functionName: 'bedrock-idp-processing',
247
+ region,
248
+ scope: this,
249
+ });
250
+ this.encryptionKey.grantEncryptDecrypt(role);
251
+ this._processingFunction = new aws_lambda_python_alpha_1.PythonFunction(this, 'BedrockExtractionFunction', {
252
+ functionName: generatedLogPermissions.uniqueFunctionName,
253
+ runtime: framework_1.DefaultRuntimes.PYTHON,
254
+ architecture: aws_lambda_1.Architecture.X86_64,
255
+ entry: path.join(__dirname, 'resources/default-bedrock-invoke'),
256
+ role,
257
+ memorySize: 512,
258
+ timeout: this.bedrockDocumentProcessingProps.stepTimeouts || aws_cdk_lib_1.Duration.minutes(5),
259
+ environment: {
260
+ MODEL_ID: adjustedModelId,
261
+ PROMPT: prompt,
262
+ INVOKE_TYPE: 'processing',
263
+ ...powertools_config_1.PowertoolsConfig.generateDefaultLambdaConfig(this.bedrockDocumentProcessingProps.enableObservability, this.metricNamespace, this.metricServiceName),
264
+ },
265
+ environmentEncryption: this.encryptionKey,
266
+ vpc: this.bedrockDocumentProcessingProps.network
267
+ ? this.bedrockDocumentProcessingProps.network.vpc
268
+ : undefined,
269
+ vpcSubnets: this.bedrockDocumentProcessingProps.network
270
+ ? this.bedrockDocumentProcessingProps.network.applicationSubnetSelection()
271
+ : undefined,
272
+ });
273
+ for (const statement of generatedLogPermissions.policyStatements) {
274
+ this._processingFunction.role?.addToPrincipalPolicy(statement);
275
+ }
276
+ if (this.bedrockDocumentProcessingProps.network) {
277
+ this._processingFunction.role?.addToPrincipalPolicy(utilities_1.LambdaIamUtils.generateLambdaVPCPermissions());
278
+ }
169
279
  }
170
- return new aws_stepfunctions_tasks_1.LambdaInvoke(this, 'ProcessingStep', {
171
- lambdaFunction: bedrockFunction,
280
+ // Always create a new LambdaInvoke task to allow proper state chaining
281
+ const stepId = `ProcessingStep-${this._processingStepCounter}`;
282
+ this._processingStepCounter++;
283
+ return new aws_stepfunctions_tasks_1.LambdaInvoke(this, stepId, {
284
+ lambdaFunction: this._processingFunction,
172
285
  resultPath: '$.processingResult',
173
286
  resultSelector: {
174
287
  'documentClassification.$': '$.Payload.documentClassification',
@@ -182,6 +295,7 @@ class BedrockDocumentProcessing extends base_document_processing_1.BaseDocumentP
182
295
  inlinePolicies: {
183
296
  BedrockInvokePolicy: new aws_iam_1.PolicyDocument({
184
297
  statements: [
298
+ // S3 read-only access for document retrieval - least privilege
185
299
  ...this.ingressAdapter.generateAdapterIAMPolicies(),
186
300
  bedrock_1.BedrockModelUtils.generateModelIAMPermissions(this, model),
187
301
  ],
@@ -202,9 +316,13 @@ class BedrockDocumentProcessing extends base_document_processing_1.BaseDocumentP
202
316
  if (!this.bedrockDocumentProcessingProps.enrichmentLambdaFunction) {
203
317
  return undefined;
204
318
  }
205
- return new aws_stepfunctions_tasks_1.LambdaInvoke(this, 'EnrichmentStep', {
319
+ const stepId = `EnrichmentStep-${this._enrichmentStepCounter}`;
320
+ this._enrichmentStepCounter++;
321
+ return new aws_stepfunctions_tasks_1.LambdaInvoke(this, stepId, {
206
322
  lambdaFunction: this.bedrockDocumentProcessingProps.enrichmentLambdaFunction,
207
323
  resultPath: '$.enrichedResult',
324
+ outputPath: '$',
325
+ payloadResponseOnly: true,
208
326
  });
209
327
  }
210
328
  /**
@@ -220,15 +338,515 @@ class BedrockDocumentProcessing extends base_document_processing_1.BaseDocumentP
220
338
  if (!this.bedrockDocumentProcessingProps.postProcessingLambdaFunction) {
221
339
  return undefined;
222
340
  }
223
- return new aws_stepfunctions_tasks_1.LambdaInvoke(this, 'PostProcessingStep', {
341
+ const stepId = `PostProcessingStep-${this._postProcessingStepCounter}`;
342
+ this._postProcessingStepCounter++;
343
+ return new aws_stepfunctions_tasks_1.LambdaInvoke(this, stepId, {
224
344
  lambdaFunction: this.bedrockDocumentProcessingProps.postProcessingLambdaFunction,
225
345
  resultPath: '$.postProcessedResult',
346
+ outputPath: '$',
347
+ payloadResponseOnly: true,
226
348
  });
227
349
  }
350
+ /**
351
+ * Implements the optional preprocessing step for PDF chunking.
352
+ *
353
+ * When chunking is enabled, creates a Lambda function that analyzes PDFs and
354
+ * splits large documents into manageable chunks. The function:
355
+ * 1. Analyzes the PDF to determine page count and token estimates
356
+ * 2. Decides if chunking is needed based on configured thresholds
357
+ * 3. If chunking is needed, splits the PDF and uploads chunks to S3
358
+ *
359
+ * @returns LambdaInvoke task for PDF analysis and chunking, or undefined if chunking is disabled
360
+ */
361
+ preprocessingStep() {
362
+ // Only enable chunking if explicitly configured
363
+ if (!this.bedrockDocumentProcessingProps.enableChunking) {
364
+ return undefined;
365
+ }
366
+ const { region, account } = aws_cdk_lib_1.Stack.of(this);
367
+ const chunkingConfig = this.bedrockDocumentProcessingProps.chunkingConfig || {};
368
+ // Create IAM role for chunking Lambda with least privilege permissions
369
+ // Chunking Lambda needs: GetObject (read raw PDFs), PutObject (write chunks)
370
+ const role = new aws_iam_1.Role(this, 'ChunkingLambdaRole', {
371
+ assumedBy: new aws_iam_1.ServicePrincipal('lambda.amazonaws.com'),
372
+ inlinePolicies: {
373
+ ChunkingPolicy: new aws_iam_1.PolicyDocument({
374
+ statements: [
375
+ ...this.ingressAdapter.generateAdapterIAMPolicies(),
376
+ ],
377
+ }),
378
+ },
379
+ });
380
+ const generatedLogPermissions = utilities_1.LambdaIamUtils.createLogsPermissions({
381
+ account,
382
+ functionName: 'bedrock-idp-chunking',
383
+ region,
384
+ scope: this,
385
+ enableObservability: this.bedrockDocumentProcessingProps.enableObservability,
386
+ });
387
+ this.encryptionKey.grantEncryptDecrypt(role);
388
+ // Create PDF Analysis & Chunking Lambda
389
+ const chunkingLambda = new aws_lambda_python_alpha_1.PythonFunction(this, 'PDFChunkingFunction', {
390
+ functionName: generatedLogPermissions.uniqueFunctionName,
391
+ entry: path.join(__dirname, 'resources/pdf-chunking'),
392
+ index: 'handler.py',
393
+ handler: 'handler',
394
+ runtime: framework_1.DefaultRuntimes.PYTHON,
395
+ architecture: aws_lambda_1.Architecture.X86_64,
396
+ role,
397
+ memorySize: 2048,
398
+ timeout: aws_cdk_lib_1.Duration.minutes(10),
399
+ environment: {
400
+ CHUNKING_STRATEGY: chunkingConfig.strategy || 'hybrid',
401
+ PAGE_THRESHOLD: String(chunkingConfig.pageThreshold || 100),
402
+ TOKEN_THRESHOLD: String(chunkingConfig.tokenThreshold || 150000),
403
+ CHUNK_SIZE: String(chunkingConfig.chunkSize || 50),
404
+ OVERLAP_PAGES: String(chunkingConfig.overlapPages || 5),
405
+ MAX_TOKENS_PER_CHUNK: String(chunkingConfig.maxTokensPerChunk || 100000),
406
+ OVERLAP_TOKENS: String(chunkingConfig.overlapTokens || 5000),
407
+ TARGET_TOKENS_PER_CHUNK: String(chunkingConfig.targetTokensPerChunk || 80000),
408
+ MAX_PAGES_PER_CHUNK: String(chunkingConfig.maxPagesPerChunk || 99),
409
+ ...powertools_config_1.PowertoolsConfig.generateDefaultLambdaConfig(this.bedrockDocumentProcessingProps.enableObservability, this.metricNamespace, this.metricServiceName),
410
+ },
411
+ environmentEncryption: this.encryptionKey,
412
+ vpc: this.bedrockDocumentProcessingProps.network
413
+ ? this.bedrockDocumentProcessingProps.network.vpc
414
+ : undefined,
415
+ vpcSubnets: this.bedrockDocumentProcessingProps.network
416
+ ? this.bedrockDocumentProcessingProps.network.applicationSubnetSelection()
417
+ : undefined,
418
+ });
419
+ for (const statement of generatedLogPermissions.policyStatements) {
420
+ chunkingLambda.role?.addToPrincipalPolicy(statement);
421
+ }
422
+ if (this.bedrockDocumentProcessingProps.network) {
423
+ chunkingLambda.role?.addToPrincipalPolicy(utilities_1.LambdaIamUtils.generateLambdaVPCPermissions());
424
+ }
425
+ return new aws_stepfunctions_tasks_1.LambdaInvoke(this, 'PDFAnalysisAndChunking', {
426
+ lambdaFunction: chunkingLambda,
427
+ resultPath: '$.chunkingResult',
428
+ resultSelector: {
429
+ 'requiresChunking.$': '$.Payload.requiresChunking',
430
+ 'tokenAnalysis.$': '$.Payload.tokenAnalysis',
431
+ 'strategy.$': '$.Payload.strategy',
432
+ 'chunks.$': '$.Payload.chunks',
433
+ },
434
+ });
435
+ }
436
+ /**
437
+ * Provides additional metadata fields for chunking to be stored in DynamoDB.
438
+ *
439
+ * When chunking is enabled, adds fields for:
440
+ * - ChunkingEnabled: string representation of boolean flag
441
+ * - ChunkingStrategy: strategy used (fixed-pages, token-based, hybrid)
442
+ * - TokenAnalysis: JSON string with token analysis results
443
+ * - ChunkMetadata: JSON string array with chunk information
444
+ *
445
+ * @returns Record of DynamoDB attribute values for chunking metadata
446
+ */
447
+ preprocessingMetadata() {
448
+ if (!this.bedrockDocumentProcessingProps.enableChunking) {
449
+ return {};
450
+ }
451
+ return {
452
+ ChunkingEnabled: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('States.Format(\'{}\', $.chunkingResult.requiresChunking)')),
453
+ ChunkingStrategy: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.chunkingResult.strategy')),
454
+ TokenAnalysis: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.jsonToString(aws_stepfunctions_1.JsonPath.objectAt('$.chunkingResult.tokenAnalysis'))),
455
+ ChunkMetadata: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.jsonToString(aws_stepfunctions_1.JsonPath.objectAt('$.chunkingResult.chunks'))),
456
+ };
457
+ }
458
+ /**
459
+ * Creates the processing workflow with conditional branching for chunked documents.
460
+ *
461
+ * When chunking is enabled, creates a Choice State that:
462
+ * - Routes to chunked processing flow if document was chunked
463
+ * - Routes to standard processing flow if document was not chunked
464
+ *
465
+ * When chunking is disabled, returns the standard processing workflow.
466
+ *
467
+ * @returns Step Functions chain for processing the document
468
+ */
469
+ createProcessingWorkflow() {
470
+ // If chunking is not enabled, use standard workflow
471
+ if (!this.bedrockDocumentProcessingProps.enableChunking) {
472
+ return this.createStandardProcessingWorkflow();
473
+ }
474
+ // Create Choice State to check if chunking was applied
475
+ const choiceState = new aws_stepfunctions_1.Choice(this, 'CheckIfChunked');
476
+ choiceState
477
+ .when(aws_stepfunctions_1.Condition.booleanEquals('$.chunkingResult.requiresChunking', true), this.createChunkedProcessingFlow())
478
+ .otherwise(
479
+ // Pass 'Standard' prefix to avoid construct ID collisions with chunked flow
480
+ this.createStandardProcessingWorkflow('Standard'));
481
+ return choiceState;
482
+ }
483
+ /**
484
+ * Creates the chunked processing flow for large documents.
485
+ *
486
+ * This flow:
487
+ * 1. Uses a Map State to process each chunk in parallel (or sequentially)
488
+ * 2. Each chunk goes through classification and processing
489
+ * 3. Results are aggregated using the aggregation Lambda
490
+ * 4. DynamoDB is updated with the aggregated result
491
+ * 5. Temporary chunks are cleaned up from S3
492
+ *
493
+ * @returns Step Functions chain for chunked document processing
494
+ */
495
+ createChunkedProcessingFlow() {
496
+ const chunkingConfig = this.bedrockDocumentProcessingProps.chunkingConfig || {};
497
+ const maxConcurrency = chunkingConfig.processingMode === 'sequential'
498
+ ? 1
499
+ : (chunkingConfig.maxConcurrency || 10);
500
+ // Create Map State for processing chunks
501
+ const mapState = new aws_stepfunctions_1.Map(this, 'ProcessChunks', {
502
+ itemsPath: '$.chunkingResult.chunks',
503
+ maxConcurrency,
504
+ parameters: {
505
+ 'documentId.$': '$.documentId',
506
+ 'chunk.$': '$$.Map.Item.Value',
507
+ 'chunkIndex.$': '$$.Map.Item.Index',
508
+ 'totalChunks.$': 'States.ArrayLength($.chunkingResult.chunks)',
509
+ // Override content to point to the chunk PDF, not the original document
510
+ 'content': {
511
+ 'location': 's3',
512
+ 'bucket.$': '$$.Map.Item.Value.bucket',
513
+ 'key.$': '$$.Map.Item.Value.key',
514
+ 'filename.$': '$.content.filename',
515
+ },
516
+ 'contentType.$': '$.contentType',
517
+ },
518
+ resultPath: '$.chunkResults',
519
+ });
520
+ // Define per-chunk processing: classification → processing
521
+ const chunkClassification = this.classificationStep();
522
+ const chunkProcessing = this.processingStep();
523
+ mapState.itemProcessor(chunkClassification.next(chunkProcessing));
524
+ // Create aggregation step (Lambda invoke only, normalization added separately)
525
+ const aggregationLambdaStep = this.createAggregationStep();
526
+ // Add a Pass state to normalize the aggregated result for downstream compatibility
527
+ // This copies aggregatedResult to processingResult so enrichment/post-processing
528
+ // see a consistent structure regardless of whether chunking was used
529
+ const normalizeState = new aws_stepfunctions_1.Pass(this, 'NormalizeAggregatedResult', {
530
+ parameters: {
531
+ 'documentId.$': '$.documentId',
532
+ 'contentType.$': '$.contentType',
533
+ 'content.$': '$.content',
534
+ 'chunkingResult.$': '$.chunkingResult',
535
+ 'chunkResults.$': '$.chunkResults',
536
+ 'aggregatedResult.$': '$.aggregatedResult',
537
+ // Copy aggregated result to processingResult for downstream compatibility
538
+ 'processingResult': {
539
+ 'result.$': '$.aggregatedResult.result',
540
+ },
541
+ // Also set classificationResult from the first successful chunk for consistency
542
+ 'classificationResult.$': '$.chunkResults[0].classificationResult',
543
+ },
544
+ });
545
+ // Create DynamoDB update step for aggregated result
546
+ const updateAggregatedResultStep = this.createUpdateAggregatedResultStep();
547
+ // Create cleanup step
548
+ const cleanupStep = this.createCleanupStep();
549
+ // Create move to processed chain with 'Chunked' prefix to avoid ID collisions
550
+ const moveToProcessed = this.ingressAdapter.createSuccessChain(this, 'Chunked');
551
+ // Create error handler for aggregation failures
552
+ const aggregationErrorHandler = this.createAggregationErrorHandler();
553
+ // Get optional enrichment and post-processing steps
554
+ const enrichmentStep = this.enrichmentStep();
555
+ const postProcessingStep = this.postProcessingStep();
556
+ // Build the final chain after aggregation
557
+ // Chain: Map State → Aggregation → DynamoDB Update → [Enrichment] → [PostProcessing] → Cleanup → Move to Processed
558
+ let finalChain = cleanupStep
559
+ .addRetry({
560
+ errors: ['Lambda.ServiceException', 'Lambda.TooManyRequestsException'],
561
+ interval: aws_cdk_lib_1.Duration.seconds(2),
562
+ maxAttempts: 3,
563
+ backoffRate: 2,
564
+ })
565
+ .next(moveToProcessed);
566
+ // Add post-processing if provided (insert before cleanup)
567
+ if (postProcessingStep) {
568
+ const postProcessingErrorHandler = new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'ChunkedPostProcessingFailDDBUpdate', {
569
+ table: this.documentProcessingTable,
570
+ key: {
571
+ DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
572
+ },
573
+ updateExpression: 'SET WorkflowStatus = :newStatus',
574
+ expressionAttributeValues: {
575
+ ':newStatus': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('post-processing-failure'),
576
+ },
577
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
578
+ }).next(this.ingressAdapter.createFailedChain(this, 'ChunkedPostProc'));
579
+ finalChain = postProcessingStep
580
+ .addCatch(postProcessingErrorHandler, {
581
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
582
+ })
583
+ .next(new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'ChunkedPostProcessingSuccessUpdate', {
584
+ table: this.documentProcessingTable,
585
+ key: {
586
+ DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
587
+ },
588
+ updateExpression: 'SET WorkflowStatus = :newStatus, PostProcessingResult = :postProcessingResult',
589
+ expressionAttributeValues: {
590
+ ':newStatus': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('post-processing-complete'),
591
+ ':postProcessingResult': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.jsonToString(aws_stepfunctions_1.JsonPath.objectAt('$.postProcessedResult'))),
592
+ },
593
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
594
+ }).next(finalChain));
595
+ }
596
+ // Add enrichment if provided (insert before post-processing or cleanup)
597
+ if (enrichmentStep) {
598
+ const enrichmentErrorHandler = new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'ChunkedEnrichmentFailDDBUpdate', {
599
+ table: this.documentProcessingTable,
600
+ key: {
601
+ DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
602
+ },
603
+ updateExpression: 'SET WorkflowStatus = :newStatus',
604
+ expressionAttributeValues: {
605
+ ':newStatus': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('enrichment-failure'),
606
+ },
607
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
608
+ }).next(this.ingressAdapter.createFailedChain(this, 'ChunkedEnrich'));
609
+ finalChain = enrichmentStep
610
+ .addCatch(enrichmentErrorHandler, {
611
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
612
+ })
613
+ .next(new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'ChunkedEnrichmentSuccessUpdate', {
614
+ table: this.documentProcessingTable,
615
+ key: {
616
+ DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
617
+ },
618
+ updateExpression: 'SET WorkflowStatus = :newStatus, EnrichmentResult = :enrichmentResult',
619
+ expressionAttributeValues: {
620
+ ':newStatus': postProcessingStep
621
+ ? aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('enrichment-complete')
622
+ : aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('complete'),
623
+ ':enrichmentResult': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.jsonToString(aws_stepfunctions_1.JsonPath.objectAt('$.enrichedResult'))),
624
+ },
625
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
626
+ }).next(finalChain));
627
+ }
628
+ // Chain: Map State → Aggregation → Normalize → DynamoDB Update → [Enrichment] → [PostProcessing] → Cleanup → Move to Processed
629
+ return mapState
630
+ .addCatch(aggregationErrorHandler, {
631
+ resultPath: '$.error',
632
+ })
633
+ .next(aggregationLambdaStep
634
+ .addCatch(aggregationErrorHandler, {
635
+ resultPath: '$.error',
636
+ })
637
+ .addRetry({
638
+ errors: ['Lambda.ServiceException', 'Lambda.TooManyRequestsException'],
639
+ interval: aws_cdk_lib_1.Duration.seconds(2),
640
+ maxAttempts: 3,
641
+ backoffRate: 2,
642
+ })
643
+ .next(normalizeState.next(updateAggregatedResultStep
644
+ .addRetry({
645
+ errors: ['DynamoDB.ProvisionedThroughputExceededException'],
646
+ interval: aws_cdk_lib_1.Duration.seconds(1),
647
+ maxAttempts: 3,
648
+ backoffRate: 2,
649
+ })
650
+ .next(finalChain))));
651
+ }
652
+ /**
653
+ * Creates the aggregation step for combining chunk results using Bedrock.
654
+ *
655
+ * Uses the same Bedrock invoke Lambda pattern as the processing step but with
656
+ * a different prompt designed for aggregating multiple chunk results.
657
+ * The chunk processing results are passed as text data to the model.
658
+ *
659
+ * @returns LambdaInvoke task for result aggregation
660
+ */
661
+ createAggregationStep() {
662
+ // Create Lambda function only once (reuses bedrock-invoke pattern)
663
+ if (!this._aggregationFunction) {
664
+ const prompt = this.bedrockDocumentProcessingProps.aggregationPrompt || BedrockDocumentProcessing.DEFAULT_AGGREGATION_PROMPT;
665
+ const adjustedModelId = bedrock_1.BedrockModelUtils.deriveActualModelId(this.bedrockDocumentProcessingProps.processingBedrockModel);
666
+ const role = this.generateLambdaRoleForBedrock('AggregationLambdaRole', this.bedrockDocumentProcessingProps.processingBedrockModel);
667
+ const { region, account } = aws_cdk_lib_1.Stack.of(this);
668
+ const generatedLogPermissions = utilities_1.LambdaIamUtils.createLogsPermissions({
669
+ account,
670
+ functionName: 'bedrock-idp-aggregation',
671
+ region,
672
+ scope: this,
673
+ enableObservability: this.bedrockDocumentProcessingProps.enableObservability,
674
+ });
675
+ this.encryptionKey.grantEncryptDecrypt(role);
676
+ this._aggregationFunction = new aws_lambda_python_alpha_1.PythonFunction(this, 'BedrockAggregationFunction', {
677
+ functionName: generatedLogPermissions.uniqueFunctionName,
678
+ architecture: aws_lambda_1.Architecture.X86_64,
679
+ runtime: framework_1.DefaultRuntimes.PYTHON,
680
+ entry: path.join(__dirname, 'resources/default-bedrock-invoke'),
681
+ role,
682
+ memorySize: 1024,
683
+ timeout: this.bedrockDocumentProcessingProps.stepTimeouts || aws_cdk_lib_1.Duration.minutes(5),
684
+ environment: {
685
+ MODEL_ID: adjustedModelId,
686
+ PROMPT: prompt,
687
+ INVOKE_TYPE: 'aggregation',
688
+ INVOKE_MAX_TOKENS: '64000', // Aggregation may need more tokens for merged output
689
+ ...powertools_config_1.PowertoolsConfig.generateDefaultLambdaConfig(this.bedrockDocumentProcessingProps.enableObservability, this.metricNamespace, this.metricServiceName),
690
+ },
691
+ environmentEncryption: this.encryptionKey,
692
+ vpc: this.bedrockDocumentProcessingProps.network
693
+ ? this.bedrockDocumentProcessingProps.network.vpc
694
+ : undefined,
695
+ vpcSubnets: this.bedrockDocumentProcessingProps.network
696
+ ? this.bedrockDocumentProcessingProps.network.applicationSubnetSelection()
697
+ : undefined,
698
+ });
699
+ for (const statement of generatedLogPermissions.policyStatements) {
700
+ this._aggregationFunction.role?.addToPrincipalPolicy(statement);
701
+ }
702
+ if (this.bedrockDocumentProcessingProps.network) {
703
+ this._aggregationFunction.role?.addToPrincipalPolicy(utilities_1.LambdaIamUtils.generateLambdaVPCPermissions());
704
+ }
705
+ }
706
+ // Always create a new LambdaInvoke task to allow proper state chaining
707
+ const stepId = `AggregationStep-${this._aggregationStepCounter}`;
708
+ this._aggregationStepCounter++;
709
+ // Pass chunk results as data content - the Lambda will format them for Bedrock
710
+ return new aws_stepfunctions_tasks_1.LambdaInvoke(this, stepId, {
711
+ lambdaFunction: this._aggregationFunction,
712
+ payload: aws_stepfunctions_1.TaskInput.fromObject({
713
+ 'documentId.$': '$.documentId',
714
+ 'contentType': 'data',
715
+ 'content': {
716
+ // Pass the chunk results as JSON string for the Lambda to process
717
+ 'data.$': 'States.JsonToString($.chunkResults)',
718
+ },
719
+ }),
720
+ // Store in both aggregatedResult AND processingResult for consistency with non-chunked flow
721
+ // This allows enrichment/post-processing steps to use $.processingResult regardless of chunking
722
+ resultPath: '$.aggregatedResult',
723
+ resultSelector: {
724
+ 'result.$': '$.Payload.result',
725
+ },
726
+ });
727
+ }
728
+ /**
729
+ * Creates the DynamoDB update step for storing aggregated results.
730
+ *
731
+ * Updates the document record with:
732
+ * - AggregatedResult: JSON string with classification, entities, and summary
733
+ * - WorkflowStatus: 'complete'
734
+ *
735
+ * @returns DynamoUpdateItem task for storing aggregated results
736
+ */
737
+ createUpdateAggregatedResultStep() {
738
+ return new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'StoreAggregatedResult', {
739
+ table: this.documentProcessingTable,
740
+ key: {
741
+ DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
742
+ },
743
+ updateExpression: 'SET AggregatedResult = :result, WorkflowStatus = :status',
744
+ expressionAttributeValues: {
745
+ ':result': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.jsonToString(aws_stepfunctions_1.JsonPath.objectAt('$.aggregatedResult'))),
746
+ ':status': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('complete'),
747
+ },
748
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
749
+ });
750
+ }
751
+ /**
752
+ * Creates the cleanup Lambda step for removing temporary chunk files.
753
+ *
754
+ * The cleanup Lambda:
755
+ * - Deletes all chunk files from S3 chunks/ prefix
756
+ * - Uses batch delete for efficiency (up to 1000 objects per request)
757
+ * - Logs errors but doesn't fail the workflow
758
+ *
759
+ * @returns LambdaInvoke task for chunk cleanup
760
+ */
761
+ createCleanupStep() {
762
+ // Create Lambda function only once
763
+ if (!this._cleanupFunction) {
764
+ const { region, account } = aws_cdk_lib_1.Stack.of(this);
765
+ const role = new aws_iam_1.Role(this, 'CleanupLambdaRole', {
766
+ assumedBy: new aws_iam_1.ServicePrincipal('lambda.amazonaws.com'),
767
+ inlinePolicies: {
768
+ CleanupPolicy: new aws_iam_1.PolicyDocument({
769
+ statements: [
770
+ // S3 access for deleting chunks only - least privilege
771
+ ...this.ingressAdapter.generateAdapterIAMPolicies(['s3:DeleteObject'], true),
772
+ ],
773
+ }),
774
+ },
775
+ });
776
+ const generatedLogPermissions = utilities_1.LambdaIamUtils.createLogsPermissions({
777
+ account,
778
+ functionName: 'bedrock-idp-cleanup',
779
+ region,
780
+ scope: this,
781
+ enableObservability: this.bedrockDocumentProcessingProps.enableObservability,
782
+ });
783
+ this.encryptionKey.grantEncryptDecrypt(role);
784
+ this._cleanupFunction = new aws_lambda_python_alpha_1.PythonFunction(this, 'CleanupFunction', {
785
+ functionName: generatedLogPermissions.uniqueFunctionName,
786
+ entry: path.join(__dirname, 'resources/cleanup'),
787
+ index: 'handler.py',
788
+ handler: 'handler',
789
+ runtime: framework_1.DefaultRuntimes.PYTHON,
790
+ architecture: aws_lambda_1.Architecture.X86_64,
791
+ role,
792
+ memorySize: 512,
793
+ timeout: aws_cdk_lib_1.Duration.minutes(5),
794
+ environment: {
795
+ ...powertools_config_1.PowertoolsConfig.generateDefaultLambdaConfig(this.bedrockDocumentProcessingProps.enableObservability, this.metricNamespace, this.metricServiceName),
796
+ },
797
+ environmentEncryption: this.encryptionKey,
798
+ vpc: this.bedrockDocumentProcessingProps.network
799
+ ? this.bedrockDocumentProcessingProps.network.vpc
800
+ : undefined,
801
+ vpcSubnets: this.bedrockDocumentProcessingProps.network
802
+ ? this.bedrockDocumentProcessingProps.network.applicationSubnetSelection()
803
+ : undefined,
804
+ });
805
+ for (const statement of generatedLogPermissions.policyStatements) {
806
+ this._cleanupFunction.role?.addToPrincipalPolicy(statement);
807
+ }
808
+ if (this.bedrockDocumentProcessingProps.network) {
809
+ this._cleanupFunction.role?.addToPrincipalPolicy(utilities_1.LambdaIamUtils.generateLambdaVPCPermissions());
810
+ }
811
+ }
812
+ return new aws_stepfunctions_tasks_1.LambdaInvoke(this, 'CleanupChunks', {
813
+ lambdaFunction: this._cleanupFunction,
814
+ payload: aws_stepfunctions_1.TaskInput.fromObject({
815
+ 'documentId.$': '$.documentId',
816
+ 'chunks.$': '$.chunkingResult.chunks',
817
+ }),
818
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
819
+ });
820
+ }
821
+ /**
822
+ * Creates the error handler for aggregation failures.
823
+ *
824
+ * When aggregation fails:
825
+ * - Updates DynamoDB with 'aggregation-failure' status
826
+ * - Moves document to failed/ prefix
827
+ *
828
+ * @returns Step Functions chain for handling aggregation errors
829
+ */
830
+ createAggregationErrorHandler() {
831
+ const updateFailureStatus = new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'AggregationFailDDBUpdate', {
832
+ table: this.documentProcessingTable,
833
+ key: {
834
+ DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
835
+ },
836
+ updateExpression: 'SET WorkflowStatus = :newStatus',
837
+ expressionAttributeValues: {
838
+ ':newStatus': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('aggregation-failure'),
839
+ },
840
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
841
+ });
842
+ // Use 'Chunked' prefix to avoid ID collisions with standard workflow
843
+ const moveToFailed = this.ingressAdapter.createFailedChain(this, 'Chunked');
844
+ return updateFailureStatus.next(moveToFailed);
845
+ }
228
846
  }
229
847
  exports.BedrockDocumentProcessing = BedrockDocumentProcessing;
230
848
  _a = JSII_RTTI_SYMBOL_1;
231
- BedrockDocumentProcessing[_a] = { fqn: "@cdklabs/cdk-appmod-catalog-blueprints.BedrockDocumentProcessing", version: "1.4.1" };
849
+ BedrockDocumentProcessing[_a] = { fqn: "@cdklabs/cdk-appmod-catalog-blueprints.BedrockDocumentProcessing", version: "1.6.0" };
232
850
  BedrockDocumentProcessing.DEFAULT_CLASSIFICATION_PROMPT = `
233
851
  Analyze the document below, and classify the type of document it is (eg. INVOICE, IDENTITY_DOCUMENT, RECEIPT, etc). The result should be in JSON and should follow the following structure (only respond in JSON with the following structure and do not use markdown to indicate the json, just output plain old json with nothing else):
234
852
 
@@ -258,4 +876,26 @@ BedrockDocumentProcessing.DEFAULT_PROCESSING_PROMPT = `
258
876
  Attached document is as follows:
259
877
 
260
878
  `;
261
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmVkcm9jay1kb2N1bWVudC1wcm9jZXNzaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdXNlLWNhc2VzL2RvY3VtZW50LXByb2Nlc3NpbmcvYmVkcm9jay1kb2N1bWVudC1wcm9jZXNzaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEscUVBQXFFO0FBQ3JFLHNDQUFzQztBQUV0Qyw2QkFBNkI7QUFDN0IsOEVBQWtFO0FBQ2xFLDZDQUE4QztBQUM5QyxpREFBcUU7QUFDckUsaURBQTZFO0FBQzdFLHVEQUFnRTtBQUVoRSxpRkFBbUU7QUFFbkUseUVBQTZIO0FBQzdILDRDQUErQztBQUMvQyxrREFBNEU7QUFDNUUsNENBQThDO0FBQzlDLG9GQUFnRjtBQTZDaEY7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBNkJHO0FBQ0gsTUFBYSx5QkFBMEIsU0FBUSxpREFBc0I7SUFxQ25FOzs7Ozs7Ozs7O09BVUc7SUFDSCxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQXFDO1FBQzdFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3hCLElBQUksS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2xCLEtBQUssQ0FBQyxPQUFPLENBQUMscUJBQXFCLENBQUMsY0FBYyxFQUFFLHdDQUE4QixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzVGLEtBQUssQ0FBQyxPQUFPLENBQUMscUJBQXFCLENBQUMsc0JBQXNCLEVBQUUsd0NBQThCLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDOUcsQ0FBQztRQUVELElBQUksQ0FBQyw4QkFBOEIsR0FBRyxLQUFLLENBQUM7UUFDNUMsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsMEJBQTBCLENBQUMsc0NBQXNDLENBQUMsQ0FBQztJQUM5RixDQUFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDTyxrQkFBa0I7UUFDMUIsTUFBTSxNQUFNLEdBQUcs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ZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IFB5dGhvbkZ1bmN0aW9uIH0gZnJvbSAnQGF3cy1jZGsvYXdzLWxhbWJkYS1weXRob24tYWxwaGEnO1xuaW1wb3J0IHsgRHVyYXRpb24sIFN0YWNrIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgSW50ZXJmYWNlVnBjRW5kcG9pbnRBd3NTZXJ2aWNlIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWVjMic7XG5pbXBvcnQgeyBSb2xlLCBTZXJ2aWNlUHJpbmNpcGFsLCBQb2xpY3lEb2N1bWVudCB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0IHsgRnVuY3Rpb24sIEFyY2hpdGVjdHVyZSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEnO1xuaW1wb3J0IHsgU3RhdGVNYWNoaW5lIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXN0ZXBmdW5jdGlvbnMnO1xuaW1wb3J0IHsgTGFtYmRhSW52b2tlIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXN0ZXBmdW5jdGlvbnMtdGFza3MnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBCYXNlRG9jdW1lbnRQcm9jZXNzaW5nLCBCYXNlRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMsIERvY3VtZW50UHJvY2Vzc2luZ1N0ZXBUeXBlIH0gZnJvbSAnLi9iYXNlLWRvY3VtZW50LXByb2Nlc3NpbmcnO1xuaW1wb3J0IHsgRGVmYXVsdFJ1bnRpbWVzIH0gZnJvbSAnLi4vZnJhbWV3b3JrJztcbmltcG9ydCB7IEJlZHJvY2tNb2RlbFByb3BzLCBCZWRyb2NrTW9kZWxVdGlscyB9IGZyb20gJy4uL2ZyYW1ld29yay9iZWRyb2NrJztcbmltcG9ydCB7IExhbWJkYUlhbVV0aWxzIH0gZnJvbSAnLi4vdXRpbGl0aWVzJztcbmltcG9ydCB7IFBvd2VydG9vbHNDb25maWcgfSBmcm9tICcuLi91dGlsaXRpZXMvb2JzZXJ2YWJpbGl0eS9wb3dlcnRvb2xzLWNvbmZpZyc7XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBwcm9wZXJ0aWVzIGZvciBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nIGNvbnN0cnVjdC5cbiAqIEV4dGVuZHMgQmFzZURvY3VtZW50UHJvY2Vzc2luZ1Byb3BzIHdpdGggQmVkcm9jay1zcGVjaWZpYyBvcHRpb25zLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcyBleHRlbmRzIEJhc2VEb2N1bWVudFByb2Nlc3NpbmdQcm9wcyB7XG4gIC8qKlxuICAgKiBCZWRyb2NrIGZvdW5kYXRpb24gbW9kZWwgZm9yIGRvY3VtZW50IGNsYXNzaWZpY2F0aW9uIHN0ZXAuXG4gICAqL1xuICByZWFkb25seSBjbGFzc2lmaWNhdGlvbkJlZHJvY2tNb2RlbD86IEJlZHJvY2tNb2RlbFByb3BzO1xuXG4gIC8qKlxuICAgKiBCZWRyb2NrIGZvdW5kYXRpb24gbW9kZWwgZm9yIGRvY3VtZW50IGV4dHJhY3Rpb24gc3RlcC5cbiAgICovXG4gIHJlYWRvbmx5IHByb2Nlc3NpbmdCZWRyb2NrTW9kZWw/OiBCZWRyb2NrTW9kZWxQcm9wcztcbiAgLyoqXG4gICAqIEN1c3RvbSBwcm9tcHQgdGVtcGxhdGUgZm9yIGRvY3VtZW50IGNsYXNzaWZpY2F0aW9uLlxuICAgKiBNdXN0IGluY2x1ZGUgcGxhY2Vob2xkZXIgZm9yIGRvY3VtZW50IGNvbnRlbnQuXG4gICAqIEBkZWZhdWx0IERFRkFVTFRfQ0xBU1NJRklDQVRJT05fUFJPTVBUXG4gICAqL1xuICByZWFkb25seSBjbGFzc2lmaWNhdGlvblByb21wdD86IHN0cmluZztcbiAgLyoqXG4gICAqIEN1c3RvbSBwcm9tcHQgdGVtcGxhdGUgZm9yIGRvY3VtZW50IGV4dHJhY3Rpb24uXG4gICAqIE11c3QgaW5jbHVkZSBwbGFjZWhvbGRlciBmb3IgZG9jdW1lbnQgY29udGVudCBhbmQgY2xhc3NpZmljYXRpb24gcmVzdWx0LlxuICAgKiBAZGVmYXVsdCBERUZBVUxUX0VYVFJBQ1RJT05fUFJPTVBUXG4gICAqL1xuICByZWFkb25seSBwcm9jZXNzaW5nUHJvbXB0Pzogc3RyaW5nO1xuICAvKipcbiAgICogT3B0aW9uYWwgTGFtYmRhIGZ1bmN0aW9uIGZvciBkb2N1bWVudCBlbnJpY2htZW50IHN0ZXAuXG4gICAqIElmIHByb3ZpZGVkLCB3aWxsIGJlIGludm9rZWQgYWZ0ZXIgZXh0cmFjdGlvbiB3aXRoIHdvcmtmbG93IHN0YXRlLlxuICAgKi9cbiAgcmVhZG9ubHkgZW5yaWNobWVudExhbWJkYUZ1bmN0aW9uPzogRnVuY3Rpb247XG4gIC8qKlxuICAgKiBPcHRpb25hbCBMYW1iZGEgZnVuY3Rpb24gZm9yIHBvc3QtcHJvY2Vzc2luZyBzdGVwLlxuICAgKiBJZiBwcm92aWRlZCwgd2lsbCBiZSBpbnZva2VkIGFmdGVyIGVucmljaG1lbnQgd2l0aCB3b3JrZmxvdyBzdGF0ZS5cbiAgICovXG4gIHJlYWRvbmx5IHBvc3RQcm9jZXNzaW5nTGFtYmRhRnVuY3Rpb24/OiBGdW5jdGlvbjtcbiAgLyoqXG4gICAqIFRpbWVvdXQgZm9yIGluZGl2aWR1YWwgU3RlcCBGdW5jdGlvbnMgdGFza3MgKGNsYXNzaWZpY2F0aW9uLCBleHRyYWN0aW9uLCBldGMuKS5cbiAgICogQGRlZmF1bHQgRHVyYXRpb24ubWludXRlcyg1KVxuICAgKi9cbiAgcmVhZG9ubHkgc3RlcFRpbWVvdXRzPzogRHVyYXRpb247XG59XG5cbi8qKlxuICogRG9jdW1lbnQgcHJvY2Vzc2luZyB3b3JrZmxvdyBwb3dlcmVkIGJ5IEFtYXpvbiBCZWRyb2NrIGZvdW5kYXRpb24gbW9kZWxzLlxuICpcbiAqIEV4dGVuZHMgQmFzZURvY3VtZW50UHJvY2Vzc2luZyB0byBwcm92aWRlIEFJLXBvd2VyZWQgZG9jdW1lbnQgY2xhc3NpZmljYXRpb24gYW5kIGV4dHJhY3Rpb25cbiAqIHVzaW5nIEFtYXpvbiBCZWRyb2NrIGZvdW5kYXRpb24gbW9kZWxzLiBUaGlzIGltcGxlbWVudGF0aW9uIG9mZmVyczpcbiAqXG4gKiAjIyBLZXkgRmVhdHVyZXNcbiAqIC0gKipBSS1Qb3dlcmVkIENsYXNzaWZpY2F0aW9uKio6IFVzZXMgQ2xhdWRlIDMuNyBTb25uZXQgKGNvbmZpZ3VyYWJsZSkgdG8gY2xhc3NpZnkgZG9jdW1lbnQgdHlwZXNcbiAqIC0gKipJbnRlbGxpZ2VudCBFeHRyYWN0aW9uKio6IEV4dHJhY3RzIHN0cnVjdHVyZWQgZGF0YSBmcm9tIGRvY3VtZW50cyB1c2luZyBmb3VuZGF0aW9uIG1vZGVsc1xuICogLSAqKkNyb3NzLVJlZ2lvbiBJbmZlcmVuY2UqKjogT3B0aW9uYWwgc3VwcG9ydCBmb3IgaW1wcm92ZWQgYXZhaWxhYmlsaXR5IHZpYSBpbmZlcmVuY2UgcHJvZmlsZXNcbiAqIC0gKipGbGV4aWJsZSBQcm9jZXNzaW5nKio6IE9wdGlvbmFsIGVucmljaG1lbnQgYW5kIHBvc3QtcHJvY2Vzc2luZyBMYW1iZGEgZnVuY3Rpb25zXG4gKiAtICoqQ29zdCBPcHRpbWl6ZWQqKjogQ29uZmlndXJhYmxlIHRpbWVvdXRzIGFuZCBtb2RlbCBzZWxlY3Rpb24gZm9yIGNvc3QgY29udHJvbFxuICpcbiAqICMjIFByb2Nlc3NpbmcgV29ya2Zsb3dcbiAqIFMzIFVwbG9hZCDihpIgQ2xhc3NpZmljYXRpb24gKEJlZHJvY2spIOKGkiBFeHRyYWN0aW9uIChCZWRyb2NrKSDihpIgW0VucmljaG1lbnRdIOKGkiBbUG9zdC1Qcm9jZXNzaW5nXSDihpIgUmVzdWx0c1xuICpcbiAqICMjIERlZmF1bHQgTW9kZWxzXG4gKiAtIENsYXNzaWZpY2F0aW9uOiBDbGF1ZGUgMy43IFNvbm5ldCAoYW50aHJvcGljLmNsYXVkZS0zLTctc29ubmV0LTIwMjUwMjE5LXYxOjApXG4gKiAtIEV4dHJhY3Rpb246IENsYXVkZSAzLjcgU29ubmV0IChhbnRocm9waWMuY2xhdWRlLTMtNy1zb25uZXQtMjAyNTAyMTktdjE6MClcbiAqXG4gKiAjIyBQcm9tcHQgVGVtcGxhdGVzXG4gKiBUaGUgY29uc3RydWN0IHVzZXMgZGVmYXVsdCBwcm9tcHRzIHRoYXQgY2FuIGJlIGN1c3RvbWl6ZWQ6XG4gKiAtICoqQ2xhc3NpZmljYXRpb24qKjogQW5hbHl6ZXMgZG9jdW1lbnQgYW5kIHJldHVybnMgSlNPTiB3aXRoIGRvY3VtZW50Q2xhc3NpZmljYXRpb24gZmllbGRcbiAqIC0gKipFeHRyYWN0aW9uKio6IFVzZXMgY2xhc3NpZmljYXRpb24gcmVzdWx0IHRvIGV4dHJhY3QgZW50aXRpZXMgaW4gc3RydWN0dXJlZCBKU09OIGZvcm1hdFxuICpcbiAqICMjIENyb3NzLVJlZ2lvbiBJbmZlcmVuY2VcbiAqIFdoZW4gZW5hYmxlZCwgdXNlcyBCZWRyb2NrIGluZmVyZW5jZSBwcm9maWxlcyBmb3IgaW1wcm92ZWQgYXZhaWxhYmlsaXR5OlxuICogLSBVUyBwcmVmaXg6IFJvdXRlcyB0byBVUy1iYXNlZCByZWdpb25zIGZvciBsb3dlciBsYXRlbmN5XG4gKiAtIEVVIHByZWZpeDogUm91dGVzIHRvIEVVLWJhc2VkIHJlZ2lvbnMgZm9yIGRhdGEgcmVzaWRlbmN5IGNvbXBsaWFuY2VcbiAqL1xuZXhwb3J0IGNsYXNzIEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmcgZXh0ZW5kcyBCYXNlRG9jdW1lbnRQcm9jZXNzaW5nIHtcbiAgcHJvdGVjdGVkIHN0YXRpYyByZWFkb25seSBERUZBVUxUX0NMQVNTSUZJQ0FUSU9OX1BST01QVCA9IGBcbiAgQW5hbHl6ZSB0aGUgZG9jdW1lbnQgYmVsb3csIGFuZCBjbGFzc2lmeSB0aGUgdHlwZSBvZiBkb2N1bWVudCBpdCBpcyAoZWcuIElOVk9JQ0UsIElERU5USVRZX0RPQ1VNRU5ULCBSRUNFSVBULCBldGMpLiBUaGUgcmVzdWx0IHNob3VsZCBiZSBpbiBKU09OIGFuZCBzaG91bGQgZm9sbG93IHRoZSBmb2xsb3dpbmcgc3RydWN0dXJlIChvbmx5IHJlc3BvbmQgaW4gSlNPTiB3aXRoIHRoZSBmb2xsb3dpbmcgc3RydWN0dXJlIGFuZCBkbyBub3QgdXNlIG1hcmtkb3duIHRvIGluZGljYXRlIHRoZSBqc29uLCBqdXN0IG91dHB1dCBwbGFpbiBvbGQganNvbiB3aXRoIG5vdGhpbmcgZWxzZSk6XG5cbiAge1xuICAgICAgZG9jdW1lbnRDbGFzc2lmaWNhdGlvbjogPENMQVNTSUZJQ0FUSU9OPlxuICB9XG5cbiAgQXR0YWNoZWQgZG9jdW1lbnQgaXMgYXMgZm9sbG93czpcblxuICBgO1xuXG4gIHByb3RlY3RlZCBzdGF0aWMgcmVhZG9ubHkgREVGQVVMVF9QUk9DRVNTSU5HX1BST01QVCA9IGBcbiAgVGhlIGRvY3VtZW50IGJlbG93IGhhcyBiZWVuIGNsYXNzaWZpZWQgYXMgW0FDVFVBTF9DTEFTU0lGSUNBVElPTl0uIEV4dHJhY3QgaW1wb3J0YW50IGVudGl0aWVzIGZyb20gdGhlIGRvY3VtZW50IGFuZCByZXR1cm4gdGhlIHJlc3VsdCBhcyBKU09OIGZvbGxvd2luZyB0aGUgc3RydWN0dXJlIGJlbG93IChvbmx5IHJlc3BvbmQgaW4gSlNPTiB3aXRoIHRoZSBmb2xsb3dpbmcgc3RydWN0dXJlIGFuZCBkbyBub3QgdXNlIG1hcmtkb3duIHRvIGluZGljYXRlIHRoZSBqc29uLCBqdXN0IG91dHB1dCBwbGFpbiBvbGQganNvbiB3aXRoIG5vdGhpbmcgZWxzZSk6XG5cbiAge1xuICAgICAgZG9jdW1lbnRDbGFzc2lmaWNhdGlvbjogPENMQVNTSUZJQ0FUSU9OPixcbiAgICAgIHJlc3VsdDoge1xuICAgICAgICBlbnRpdGllczogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHR5cGU6IDxUWVBFIE9GIEVOVElUWT5cbiAgICAgICAgICAgICAgICB2YWx1ZTogPFZBTFVFIE9GIEVOVElUWT5cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAuLi5cbiAgICAgICAgXVxuICAgICAgfVxuICB9XG5cbiAgQXR0YWNoZWQgZG9jdW1lbnQgaXMgYXMgZm9sbG93czpcblxuICBgO1xuXG4gIC8qKiBDb25maWd1cmF0aW9uIHByb3BlcnRpZXMgc3BlY2lmaWMgdG8gQmVkcm9jayBkb2N1bWVudCBwcm9jZXNzaW5nICovXG4gIHByb3RlY3RlZCByZWFkb25seSBiZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHM6IEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcztcbiAgLyoqIFRoZSBTdGVwIEZ1bmN0aW9ucyBzdGF0ZSBtYWNoaW5lIHRoYXQgb3JjaGVzdHJhdGVzIHRoZSBkb2N1bWVudCBwcm9jZXNzaW5nIHdvcmtmbG93ICovXG4gIHJlYWRvbmx5IHN0YXRlTWFjaGluZTogU3RhdGVNYWNoaW5lO1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmcgY29uc3RydWN0LlxuICAgKlxuICAgKiBJbml0aWFsaXplcyB0aGUgQmVkcm9jay1wb3dlcmVkIGRvY3VtZW50IHByb2Nlc3NpbmcgcGlwZWxpbmUgd2l0aCBBSSBjbGFzc2lmaWNhdGlvblxuICAgKiBhbmQgZXh0cmFjdGlvbiBjYXBhYmlsaXRpZXMuIENyZWF0ZXMgTGFtYmRhIGZ1bmN0aW9ucyB3aXRoIGFwcHJvcHJpYXRlIElBTSByb2xlc1xuICAgKiBmb3IgQmVkcm9jayBtb2RlbCBpbnZvY2F0aW9uIGFuZCBTMyBhY2Nlc3MuXG4gICAqXG4gICAqIEBwYXJhbSBzY29wZSAtIFRoZSBzY29wZSBpbiB3aGljaCB0byBkZWZpbmUgdGhpcyBjb25zdHJ1Y3RcbiAgICogQHBhcmFtIGlkIC0gVGhlIHNjb3BlZCBjb25zdHJ1Y3QgSUQuIE11c3QgYmUgdW5pcXVlIHdpdGhpbiB0aGUgc2NvcGUuXG4gICAqIEBwYXJhbSBwcm9wcyAtIENvbmZpZ3VyYXRpb24gcHJvcGVydGllcyBmb3IgdGhlIEJlZHJvY2sgZG9jdW1lbnQgcHJvY2Vzc2luZyBwaXBlbGluZVxuICAgKi9cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCwgcHJvcHMpO1xuICAgIGlmIChwcm9wcy5uZXR3b3JrKSB7XG4gICAgICBwcm9wcy5uZXR3b3JrLmNyZWF0ZVNlcnZpY2VFbmRwb2ludCgndnBjZS1iZWRyb2NrJywgSW50ZXJmYWNlVnBjRW5kcG9pbnRBd3NTZXJ2aWNlLkJFRFJPQ0spO1xuICAgICAgcHJvcHMubmV0d29yay5jcmVhdGVTZXJ2aWNlRW5kcG9pbnQoJ3ZwY2UtYmVkcm9jay1ydW50aW1lJywgSW50ZXJmYWNlVnBjRW5kcG9pbnRBd3NTZXJ2aWNlLkJFRFJPQ0tfUlVOVElNRSk7XG4gICAgfVxuXG4gICAgdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMgPSBwcm9wcztcbiAgICB0aGlzLnN0YXRlTWFjaGluZSA9IHRoaXMuaGFuZGxlU3RhdGVNYWNoaW5lQ3JlYXRpb24oJ2JlZHJvY2stZG9jdW1lbnQtcHJvY2Vzc2luZy13b3JrZmxvdycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEltcGxlbWVudHMgdGhlIGRvY3VtZW50IGNsYXNzaWZpY2F0aW9uIHN0ZXAgdXNpbmcgQW1hem9uIEJlZHJvY2suXG4gICAqXG4gICAqIENyZWF0ZXMgYSBMYW1iZGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIHRoZSBjb25maWd1cmVkIEJlZHJvY2sgbW9kZWwgdG8gY2xhc3NpZnlcbiAgICogdGhlIGRvY3VtZW50IHR5cGUuIFRoZSBmdW5jdGlvbiByZWFkcyB0aGUgZG9jdW1lbnQgZnJvbSBTMyBhbmQgc2VuZHMgaXQgdG9cbiAgICogQmVkcm9jayB3aXRoIHRoZSBjbGFzc2lmaWNhdGlvbiBwcm9tcHQuXG4gICAqXG4gICAqIEByZXR1cm5zIExhbWJkYUludm9rZSB0YXNrIGNvbmZpZ3VyZWQgZm9yIGRvY3VtZW50IGNsYXNzaWZpY2F0aW9uXG4gICAqL1xuICBwcm90ZWN0ZWQgY2xhc3NpZmljYXRpb25TdGVwKCk6IERvY3VtZW50UHJvY2Vzc2luZ1N0ZXBUeXBlIHtcbiAgICBjb25zdCBwcm9tcHQgPSB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5jbGFzc2lmaWNhdGlvblByb21wdCB8fCBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nLkRFRkFVTFRfQ0xBU1NJRklDQVRJT05fUFJPTVBUO1xuICAgIGNvbnN0IGFkanVzdGVkTW9kZWxJZCA9IEJlZHJvY2tNb2RlbFV0aWxzLmRlcml2ZUFjdHVhbE1vZGVsSWQodGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuY2xhc3NpZmljYXRpb25CZWRyb2NrTW9kZWwpO1xuICAgIGNvbnN0IHJvbGUgPSB0aGlzLmdlbmVyYXRlTGFtYmRhUm9sZUZvckJlZHJvY2soJ0NsYXNzaWZpY2F0aW9uTGFtYmRhUm9sZScsIHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLmNsYXNzaWZpY2F0aW9uQmVkcm9ja01vZGVsKTtcbiAgICBjb25zdCB7IHJlZ2lvbiwgYWNjb3VudCB9ID0gU3RhY2sub2YodGhpcyk7XG4gICAgY29uc3QgZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMgPSBMYW1iZGFJYW1VdGlscy5jcmVhdGVMb2dzUGVybWlzc2lvbnMoe1xuICAgICAgYWNjb3VudCxcbiAgICAgIGZ1bmN0aW9uTmFtZTogJ2JlZHJvY2staWRwLWNsYXNzaWZpY2F0aW9uJyxcbiAgICAgIHJlZ2lvbixcbiAgICAgIHNjb3BlOiB0aGlzLFxuICAgICAgZW5hYmxlT2JzZXJ2YWJpbGl0eTogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuZW5hYmxlT2JzZXJ2YWJpbGl0eSxcbiAgICB9KTtcblxuICAgIHRoaXMuZW5jcnlwdGlvbktleS5ncmFudEVuY3J5cHREZWNyeXB0KHJvbGUpO1xuXG4gICAgY29uc3QgYmVkcm9ja0Z1bmN0aW9uID0gbmV3IFB5dGhvbkZ1bmN0aW9uKHRoaXMsICdCZWRyb2NrQ2xhc3NpZmljYXRpb25GdW5jdGlvbicsIHtcbiAgICAgIGZ1bmN0aW9uTmFtZTogZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMudW5pcXVlRnVuY3Rpb25OYW1lLFxuICAgICAgYXJjaGl0ZWN0dXJlOiBBcmNoaXRlY3R1cmUuWDg2XzY0LFxuICAgICAgcnVudGltZTogRGVmYXVsdFJ1bnRpbWVzLlBZVEhPTixcbiAgICAgIGVudHJ5OiBwYXRoLmpvaW4oX19kaXJuYW1lLCAncmVzb3VyY2VzL2RlZmF1bHQtYmVkcm9jay1pbnZva2UnKSxcbiAgICAgIHJvbGUsXG4gICAgICBtZW1vcnlTaXplOiA1MTIsXG4gICAgICB0aW1lb3V0OiB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5zdGVwVGltZW91dHMgfHwgRHVyYXRpb24ubWludXRlcyg1KSxcbiAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgIE1PREVMX0lEOiBhZGp1c3RlZE1vZGVsSWQsXG4gICAgICAgIFBST01QVDogcHJvbXB0LFxuICAgICAgICBJTlZPS0VfVFlQRTogJ2NsYXNzaWZpY2F0aW9uJyxcbiAgICAgICAgLi4uUG93ZXJ0b29sc0NvbmZpZy5nZW5lcmF0ZURlZmF1bHRMYW1iZGFDb25maWcoXG4gICAgICAgICAgdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuZW5hYmxlT2JzZXJ2YWJpbGl0eSxcbiAgICAgICAgICB0aGlzLm1ldHJpY05hbWVzcGFjZSxcbiAgICAgICAgICB0aGlzLm1ldHJpY1NlcnZpY2VOYW1lLFxuICAgICAgICApLFxuICAgICAgfSxcbiAgICAgIGVudmlyb25tZW50RW5jcnlwdGlvbjogdGhpcy5lbmNyeXB0aW9uS2V5LFxuICAgICAgdnBjOiB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrID8gdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29yay52cGMgOiB1bmRlZmluZWQsXG4gICAgICB2cGNTdWJuZXRzOiB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrID8gdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29yay5hcHBsaWNhdGlvblN1Ym5ldFNlbGVjdGlvbigpIDogdW5kZWZpbmVkLFxuICAgIH0pO1xuXG4gICAgZm9yIChjb25zdCBzdGF0ZW1lbnQgb2YgZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMucG9saWN5U3RhdGVtZW50cykge1xuICAgICAgYmVkcm9ja0Z1bmN0aW9uLnJvbGU/LmFkZFRvUHJpbmNpcGFsUG9saWN5KHN0YXRlbWVudCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLm5ldHdvcmspIHtcbiAgICAgIGJlZHJvY2tGdW5jdGlvbi5yb2xlPy5hZGRUb1ByaW5jaXBhbFBvbGljeShMYW1iZGFJYW1VdGlscy5nZW5lcmF0ZUxhbWJkYVZQQ1Blcm1pc3Npb25zKCkpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgTGFtYmRhSW52b2tlKHRoaXMsICdDbGFzc2lmaWNhdGlvblN0ZXAnLCB7XG4gICAgICBsYW1iZGFGdW5jdGlvbjogYmVkcm9ja0Z1bmN0aW9uLFxuICAgICAgcmVzdWx0UGF0aDogJyQuY2xhc3NpZmljYXRpb25SZXN1bHQnLFxuICAgICAgcmVzdWx0U2VsZWN0b3I6IHtcbiAgICAgICAgJ2RvY3VtZW50Q2xhc3NpZmljYXRpb24uJCc6ICckLlBheWxvYWQuZG9jdW1lbnRDbGFzc2lmaWNhdGlvbicsXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEltcGxlbWVudHMgdGhlIGRvY3VtZW50IGV4dHJhY3Rpb24gc3RlcCB1c2luZyBBbWF6b24gQmVkcm9jay5cbiAgICpcbiAgICogQ3JlYXRlcyBhIExhbWJkYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgdGhlIGNvbmZpZ3VyZWQgQmVkcm9jayBtb2RlbCB0byBleHRyYWN0XG4gICAqIHN0cnVjdHVyZWQgZGF0YSBmcm9tIHRoZSBkb2N1bWVudC4gVXNlcyB0aGUgY2xhc3NpZmljYXRpb24gcmVzdWx0IGZyb20gdGhlXG4gICAqIHByZXZpb3VzIHN0ZXAgdG8gcHJvdmlkZSBjb250ZXh0IGZvciBtb3JlIGFjY3VyYXRlIGV4dHJhY3Rpb24uXG4gICAqXG4gICAqIEByZXR1cm5zIExhbWJkYUludm9rZSB0YXNrIGNvbmZpZ3VyZWQgZm9yIGRvY3VtZW50IGV4dHJhY3Rpb25cbiAgICovXG4gIHByb3RlY3RlZCBwcm9jZXNzaW5nU3RlcCgpOiBEb2N1bWVudFByb2Nlc3NpbmdTdGVwVHlwZSB7XG4gICAgY29uc3QgcHJvbXB0ID0gdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMucHJvY2Vzc2luZ1Byb21wdCB8fCBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nLkRFRkFVTFRfUFJPQ0VTU0lOR19QUk9NUFQ7XG4gICAgY29uc3QgYWRqdXN0ZWRNb2RlbElkID0gQmVkcm9ja01vZGVsVXRpbHMuZGVyaXZlQWN0dWFsTW9kZWxJZCh0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5wcm9jZXNzaW5nQmVkcm9ja01vZGVsKTtcbiAgICBjb25zdCByb2xlID0gdGhpcy5nZW5lcmF0ZUxhbWJkYVJvbGVGb3JCZWRyb2NrKCdQcm9jZXNzaW5nTGFtYmRhUm9sZScsIHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLnByb2Nlc3NpbmdCZWRyb2NrTW9kZWwpO1xuICAgIGNvbnN0IHsgcmVnaW9uLCBhY2NvdW50IH0gPSBTdGFjay5vZih0aGlzKTtcblxuICAgIGNvbnN0IGdlbmVyYXRlZExvZ1Blcm1pc3Npb25zID0gTGFtYmRhSWFtVXRpbHMuY3JlYXRlTG9nc1Blcm1pc3Npb25zKHtcbiAgICAgIGFjY291bnQsXG4gICAgICBmdW5jdGlvbk5hbWU6ICdiZWRyb2NrLWlkcC1wcm9jZXNzaW5nJyxcbiAgICAgIHJlZ2lvbixcbiAgICAgIHNjb3BlOiB0aGlzLFxuICAgIH0pO1xuICAgIHRoaXMuZW5jcnlwdGlvbktleS5ncmFudEVuY3J5cHREZWNyeXB0KHJvbGUpO1xuICAgIGNvbnN0IGJlZHJvY2tGdW5jdGlvbiA9IG5ldyBQeXRob25GdW5jdGlvbih0aGlzLCAnQmVkcm9ja0V4dHJhY3Rpb25GdW5jdGlvbicsIHtcbiAgICAgIGZ1bmN0aW9uTmFtZTogZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMudW5pcXVlRnVuY3Rpb25OYW1lLFxuICAgICAgcnVudGltZTogRGVmYXVsdFJ1bnRpbWVzLlBZVEhPTixcbiAgICAgIGFyY2hpdGVjdHVyZTogQXJjaGl0ZWN0dXJlLlg4Nl82NCxcbiAgICAgIGVudHJ5OiBwYXRoLmpvaW4oX19kaXJuYW1lLCAncmVzb3VyY2VzL2RlZmF1bHQtYmVkcm9jay1pbnZva2UnKSxcbiAgICAgIHJvbGUsXG4gICAgICBtZW1vcnlTaXplOiA1MTIsXG4gICAgICB0aW1lb3V0OiB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5zdGVwVGltZW91dHMgfHwgRHVyYXRpb24ubWludXRlcyg1KSxcbiAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgIE1PREVMX0lEOiBhZGp1c3RlZE1vZGVsSWQsXG4gICAgICAgIFBST01QVDogcHJvbXB0LFxuICAgICAgICBJTlZPS0VfVFlQRTogJ3Byb2Nlc3NpbmcnLFxuICAgICAgICAuLi5Qb3dlcnRvb2xzQ29uZmlnLmdlbmVyYXRlRGVmYXVsdExhbWJkYUNvbmZpZyhcbiAgICAgICAgICB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5lbmFibGVPYnNlcnZhYmlsaXR5LFxuICAgICAgICAgIHRoaXMubWV0cmljTmFtZXNwYWNlLFxuICAgICAgICAgIHRoaXMubWV0cmljU2VydmljZU5hbWUsXG4gICAgICAgICksXG4gICAgICB9LFxuICAgICAgZW52aXJvbm1lbnRFbmNyeXB0aW9uOiB0aGlzLmVuY3J5cHRpb25LZXksXG4gICAgICB2cGM6IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLm5ldHdvcmsgPyB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrLnZwYyA6IHVuZGVmaW5lZCxcbiAgICAgIHZwY1N1Ym5ldHM6IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLm5ldHdvcmsgPyB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrLmFwcGxpY2F0aW9uU3VibmV0U2VsZWN0aW9uKCkgOiB1bmRlZmluZWQsXG4gICAgfSk7XG5cbiAgICBmb3IgKGNvbnN0IHN0YXRlbWVudCBvZiBnZW5lcmF0ZWRMb2dQZXJtaXNzaW9ucy5wb2xpY3lTdGF0ZW1lbnRzKSB7XG4gICAgICBiZWRyb2NrRnVuY3Rpb24ucm9sZT8uYWRkVG9QcmluY2lwYWxQb2xpY3koc3RhdGVtZW50KTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29yaykge1xuICAgICAgYmVkcm9ja0Z1bmN0aW9uLnJvbGU/LmFkZFRvUHJpbmNpcGFsUG9saWN5KExhbWJkYUlhbVV0aWxzLmdlbmVyYXRlTGFtYmRhVlBDUGVybWlzc2lvbnMoKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBMYW1iZGFJbnZva2UodGhpcywgJ1Byb2Nlc3NpbmdTdGVwJywge1xuICAgICAgbGFtYmRhRnVuY3Rpb246IGJlZHJvY2tGdW5jdGlvbixcbiAgICAgIHJlc3VsdFBhdGg6ICckLnByb2Nlc3NpbmdSZXN1bHQnLFxuICAgICAgcmVzdWx0U2VsZWN0b3I6IHtcbiAgICAgICAgJ2RvY3VtZW50Q2xhc3NpZmljYXRpb24uJCc6ICckLlBheWxvYWQuZG9jdW1lbnRDbGFzc2lmaWNhdGlvbicsXG4gICAgICAgICdyZXN1bHQuJCc6ICckLlBheWxvYWQucmVzdWx0JyxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2VuZXJhdGVMYW1iZGFSb2xlRm9yQmVkcm9jayhpZDogc3RyaW5nLCBtb2RlbD86IEJlZHJvY2tNb2RlbFByb3BzKSB7XG4gICAgcmV0dXJuIG5ldyBSb2xlKHRoaXMsIGlkLCB7XG4gICAgICBhc3N1bWVkQnk6IG5ldyBTZXJ2aWNlUHJpbmNpcGFsKCdsYW1iZGEuYW1hem9uYXdzLmNvbScpLFxuICAgICAgaW5saW5lUG9saWNpZXM6IHtcbiAgICAgICAgQmVkcm9ja0ludm9rZVBvbGljeTogbmV3IFBvbGljeURvY3VtZW50KHtcbiAgICAgICAgICBzdGF0ZW1lbnRzOiBbXG4gICAgICAgICAgICAuLi50aGlzLmluZ3Jlc3NBZGFwdGVyLmdlbmVyYXRlQWRhcHRlcklBTVBvbGljaWVzKCksXG4gICAgICAgICAgICBCZWRyb2NrTW9kZWxVdGlscy5nZW5lcmF0ZU1vZGVsSUFNUGVybWlzc2lvbnModGhpcywgbW9kZWwpLFxuICAgICAgICAgIF0sXG4gICAgICAgIH0pLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbXBsZW1lbnRzIHRoZSBvcHRpb25hbCBkb2N1bWVudCBlbnJpY2htZW50IHN0ZXAuXG4gICAqXG4gICAqIElmIGFuIGVucmljaG1lbnQgTGFtYmRhIGZ1bmN0aW9uIGlzIHByb3ZpZGVkIGluIHRoZSBwcm9wcywgY3JlYXRlcyBhIExhbWJkYUludm9rZVxuICAgKiB0YXNrIHRvIHBlcmZvcm0gYWRkaXRpb25hbCBwcm9jZXNzaW5nIG9uIHRoZSBleHRyYWN0ZWQgZGF0YS4gVGhpcyBzdGVwIGlzIHVzZWZ1bFxuICAgKiBmb3IgZGF0YSB2YWxpZGF0aW9uLCB0cmFuc2Zvcm1hdGlvbiwgb3IgaW50ZWdyYXRpb24gd2l0aCBleHRlcm5hbCBzeXN0ZW1zLlxuICAgKlxuICAgKiBAcmV0dXJucyBMYW1iZGFJbnZva2UgdGFzayBmb3IgZW5yaWNobWVudCwgb3IgdW5kZWZpbmVkIHRvIHNraXAgdGhpcyBzdGVwXG4gICAqL1xuICBwcm90ZWN0ZWQgZW5yaWNobWVudFN0ZXAoKTogRG9jdW1lbnRQcm9jZXNzaW5nU3RlcFR5cGUgfCB1bmRlZmluZWQge1xuICAgIGlmICghdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuZW5yaWNobWVudExhbWJkYUZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgTGFtYmRhSW52b2tlKHRoaXMsICdFbnJpY2htZW50U3RlcCcsIHtcbiAgICAgIGxhbWJkYUZ1bmN0aW9uOiB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5lbnJpY2htZW50TGFtYmRhRnVuY3Rpb24sXG4gICAgICByZXN1bHRQYXRoOiAnJC5lbnJpY2hlZFJlc3VsdCcsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogSW1wbGVtZW50cyB0aGUgb3B0aW9uYWwgcG9zdC1wcm9jZXNzaW5nIHN0ZXAuXG4gICAqXG4gICAqIElmIGEgcG9zdC1wcm9jZXNzaW5nIExhbWJkYSBmdW5jdGlvbiBpcyBwcm92aWRlZCBpbiB0aGUgcHJvcHMsIGNyZWF0ZXMgYSBMYW1iZGFJbnZva2VcbiAgICogdGFzayB0byBwZXJmb3JtIGZpbmFsIHByb2Nlc3Npbmcgb24gdGhlIHdvcmtmbG93IHJlc3VsdHMuIFRoaXMgc3RlcCBpcyB1c2VmdWwgZm9yXG4gICAqIGRhdGEgZm9ybWF0dGluZywgbm90aWZpY2F0aW9ucywgb3IgaW50ZWdyYXRpb24gd2l0aCBkb3duc3RyZWFtIHN5c3RlbXMuXG4gICAqXG4gICAqIEByZXR1cm5zIExhbWJkYUludm9rZSB0YXNrIGZvciBwb3N0LXByb2Nlc3NpbmcsIG9yIHVuZGVmaW5lZCB0byBza2lwIHRoaXMgc3RlcFxuICAgKi9cbiAgcHJvdGVjdGVkIHBvc3RQcm9jZXNzaW5nU3RlcCgpOiBEb2N1bWVudFByb2Nlc3NpbmdTdGVwVHlwZSB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCF0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5wb3N0UHJvY2Vzc2luZ0xhbWJkYUZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgTGFtYmRhSW52b2tlKHRoaXMsICdQb3N0UHJvY2Vzc2luZ1N0ZXAnLCB7XG4gICAgICBsYW1iZGFGdW5jdGlvbjogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMucG9zdFByb2Nlc3NpbmdMYW1iZGFGdW5jdGlvbixcbiAgICAgIHJlc3VsdFBhdGg6ICckLnBvc3RQcm9jZXNzZWRSZXN1bHQnLFxuICAgIH0pO1xuICB9XG59Il19
879
+ BedrockDocumentProcessing.DEFAULT_AGGREGATION_PROMPT = `
880
+ You are given the processing results from multiple chunks of a large document that was split for processing.
881
+ Your task is to synthesize these chunk results into a single, coherent final result.
882
+
883
+ Instructions:
884
+ 1. Review all the chunk results provided below
885
+ 2. Merge and deduplicate any overlapping information (chunks may have overlapping pages)
886
+ 3. Synthesize the information into a unified, coherent result
887
+ 4. Maintain the same output format as the individual chunk results
888
+ 5. If the chunks contain summaries, create a comprehensive summary that covers all sections
889
+ 6. If the chunks contain entities, deduplicate and consolidate them
890
+ 7. Preserve important details from each chunk while avoiding redundancy
891
+
892
+ Return the result as JSON (only respond in JSON without markdown formatting):
893
+
894
+ {
895
+ "result": <SYNTHESIZED_RESULT>
896
+ }
897
+
898
+ The chunk results to aggregate are as follows:
899
+
900
+ `;
901
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmVkcm9jay1kb2N1bWVudC1wcm9jZXNzaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdXNlLWNhc2VzL2RvY3VtZW50LXByb2Nlc3NpbmcvYmVkcm9jay1kb2N1bWVudC1wcm9jZXNzaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEscUVBQXFFO0FBQ3JFLHNDQUFzQztBQUV0Qyw2QkFBNkI7QUFDN0IsOEVBQWtFO0FBQ2xFLDZDQUE4QztBQUM5QyxpREFBcUU7QUFDckUsaURBQTZFO0FBQzdFLHVEQUFnRTtBQUNoRSxxRUFBOEc7QUFDOUcsaUZBQTJHO0FBRTNHLHlFQUE2SDtBQUU3SCw0Q0FBK0M7QUFDL0Msa0RBQTRFO0FBQzVFLDRDQUE4QztBQUM5QyxvRkFBZ0Y7QUFvSGhGOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTZCRztBQUNILE1BQWEseUJBQTBCLFNBQVEsaURBQXNCO0lBK0VuRTs7Ozs7Ozs7Ozs7T0FXRztJQUNILFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBcUM7UUFDN0UsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7UUE3QjFCLDREQUE0RDtRQUNwRCwrQkFBMEIsR0FBRyxDQUFDLENBQUM7UUFDdkMsd0RBQXdEO1FBQ2hELDJCQUFzQixHQUFHLENBQUMsQ0FBQztRQUduQyx5REFBeUQ7UUFDakQsNEJBQXVCLEdBQUcsQ0FBQyxDQUFDO1FBR3BDLHdEQUF3RDtRQUNoRCwyQkFBc0IsR0FBRyxDQUFDLENBQUM7UUFDbkMsNkRBQTZEO1FBQ3JELCtCQUEwQixHQUFHLENBQUMsQ0FBQztRQWtCckMsOENBQThDO1FBQzlDLElBQUksS0FBSyxDQUFDLGNBQWMsSUFBSSxLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDakQsSUFBSSxDQUFDLHNCQUFzQixDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUNwRCxDQUFDO1FBRUQsSUFB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QUFtQixDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNoRCxDQUFDOztBQW4rQkgsOERBbytCQzs7O0FBbitCMkIsdURBQTZCLEdBQUc7Ozs7Ozs7OztHQVN6RCxBQVRzRCxDQVNyRDtBQUV3QixtREFBeUIsR0FBRzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBa0JyRCxBQWxCa0QsQ0FrQmpEO0FBRXdCLG9EQUEwQixHQUFHOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQnRELEFBckJtRCxDQXFCbEQiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBQeXRob25GdW5jdGlvbiB9IGZyb20gJ0Bhd3MtY2RrL2F3cy1sYW1iZGEtcHl0aG9uLWFscGhhJztcbmltcG9ydCB7IER1cmF0aW9uLCBTdGFjayB9IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCB7IEludGVyZmFjZVZwY0VuZHBvaW50QXdzU2VydmljZSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1lYzInO1xuaW1wb3J0IHsgUm9sZSwgU2VydmljZVByaW5jaXBhbCwgUG9saWN5RG9jdW1lbnQgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCB7IEZ1bmN0aW9uLCBBcmNoaXRlY3R1cmUgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcbmltcG9ydCB7IElDaGFpbmFibGUsIENob2ljZSwgQ29uZGl0aW9uLCBNYXAsIEpzb25QYXRoLCBUYXNrSW5wdXQsIFBhc3MgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc3RlcGZ1bmN0aW9ucyc7XG5pbXBvcnQgeyBEeW5hbW9BdHRyaWJ1dGVWYWx1ZSwgRHluYW1vVXBkYXRlSXRlbSwgTGFtYmRhSW52b2tlIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXN0ZXBmdW5jdGlvbnMtdGFza3MnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBCYXNlRG9jdW1lbnRQcm9jZXNzaW5nLCBCYXNlRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMsIERvY3VtZW50UHJvY2Vzc2luZ1N0ZXBUeXBlIH0gZnJvbSAnLi9iYXNlLWRvY3VtZW50LXByb2Nlc3NpbmcnO1xuaW1wb3J0IHsgQ2h1bmtpbmdDb25maWcgfSBmcm9tICcuL2NodW5raW5nLWNvbmZpZyc7XG5pbXBvcnQgeyBEZWZhdWx0UnVudGltZXMgfSBmcm9tICcuLi9mcmFtZXdvcmsnO1xuaW1wb3J0IHsgQmVkcm9ja01vZGVsUHJvcHMsIEJlZHJvY2tNb2RlbFV0aWxzIH0gZnJvbSAnLi4vZnJhbWV3b3JrL2JlZHJvY2snO1xuaW1wb3J0IHsgTGFtYmRhSWFtVXRpbHMgfSBmcm9tICcuLi91dGlsaXRpZXMnO1xuaW1wb3J0IHsgUG93ZXJ0b29sc0NvbmZpZyB9IGZyb20gJy4uL3V0aWxpdGllcy9vYnNlcnZhYmlsaXR5L3Bvd2VydG9vbHMtY29uZmlnJztcblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIHByb3BlcnRpZXMgZm9yIEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmcgY29uc3RydWN0LlxuICogRXh0ZW5kcyBCYXNlRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMgd2l0aCBCZWRyb2NrLXNwZWNpZmljIG9wdGlvbnMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzIGV4dGVuZHMgQmFzZURvY3VtZW50UHJvY2Vzc2luZ1Byb3BzIHtcbiAgLyoqXG4gICAqIEJlZHJvY2sgZm91bmRhdGlvbiBtb2RlbCBmb3IgZG9jdW1lbnQgY2xhc3NpZmljYXRpb24gc3RlcC5cbiAgICovXG4gIHJlYWRvbmx5IGNsYXNzaWZpY2F0aW9uQmVkcm9ja01vZGVsPzogQmVkcm9ja01vZGVsUHJvcHM7XG5cbiAgLyoqXG4gICAqIEJlZHJvY2sgZm91bmRhdGlvbiBtb2RlbCBmb3IgZG9jdW1lbnQgZXh0cmFjdGlvbiBzdGVwLlxuICAgKi9cbiAgcmVhZG9ubHkgcHJvY2Vzc2luZ0JlZHJvY2tNb2RlbD86IEJlZHJvY2tNb2RlbFByb3BzO1xuICAvKipcbiAgICogQ3VzdG9tIHByb21wdCB0ZW1wbGF0ZSBmb3IgZG9jdW1lbnQgY2xhc3NpZmljYXRpb24uXG4gICAqIE11c3QgaW5jbHVkZSBwbGFjZWhvbGRlciBmb3IgZG9jdW1lbnQgY29udGVudC5cbiAgICogQGRlZmF1bHQgREVGQVVMVF9DTEFTU0lGSUNBVElPTl9QUk9NUFRcbiAgICovXG4gIHJlYWRvbmx5IGNsYXNzaWZpY2F0aW9uUHJvbXB0Pzogc3RyaW5nO1xuICAvKipcbiAgICogQ3VzdG9tIHByb21wdCB0ZW1wbGF0ZSBmb3IgZG9jdW1lbnQgZXh0cmFjdGlvbi5cbiAgICogTXVzdCBpbmNsdWRlIHBsYWNlaG9sZGVyIGZvciBkb2N1bWVudCBjb250ZW50IGFuZCBjbGFzc2lmaWNhdGlvbiByZXN1bHQuXG4gICAqIEBkZWZhdWx0IERFRkFVTFRfRVhUUkFDVElPTl9QUk9NUFRcbiAgICovXG4gIHJlYWRvbmx5IHByb2Nlc3NpbmdQcm9tcHQ/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBPcHRpb25hbCBMYW1iZGEgZnVuY3Rpb24gZm9yIGRvY3VtZW50IGVucmljaG1lbnQgc3RlcC5cbiAgICogSWYgcHJvdmlkZWQsIHdpbGwgYmUgaW52b2tlZCBhZnRlciBleHRyYWN0aW9uIHdpdGggd29ya2Zsb3cgc3RhdGUuXG4gICAqL1xuICByZWFkb25seSBlbnJpY2htZW50TGFtYmRhRnVuY3Rpb24/OiBGdW5jdGlvbjtcbiAgLyoqXG4gICAqIE9wdGlvbmFsIExhbWJkYSBmdW5jdGlvbiBmb3IgcG9zdC1wcm9jZXNzaW5nIHN0ZXAuXG4gICAqIElmIHByb3ZpZGVkLCB3aWxsIGJlIGludm9rZWQgYWZ0ZXIgZW5yaWNobWVudCB3aXRoIHdvcmtmbG93IHN0YXRlLlxuICAgKi9cbiAgcmVhZG9ubHkgcG9zdFByb2Nlc3NpbmdMYW1iZGFGdW5jdGlvbj86IEZ1bmN0aW9uO1xuICAvKipcbiAgICogVGltZW91dCBmb3IgaW5kaXZpZHVhbCBTdGVwIEZ1bmN0aW9ucyB0YXNrcyAoY2xhc3NpZmljYXRpb24sIGV4dHJhY3Rpb24sIGV0Yy4pLlxuICAgKiBAZGVmYXVsdCBEdXJhdGlvbi5taW51dGVzKDUpXG4gICAqL1xuICByZWFkb25seSBzdGVwVGltZW91dHM/OiBEdXJhdGlvbjtcblxuICAvKipcbiAgICogQ3VzdG9tIHByb21wdCB0ZW1wbGF0ZSBmb3IgYWdncmVnYXRpbmcgcmVzdWx0cyBmcm9tIG11bHRpcGxlIGNodW5rcy5cbiAgICogVXNlZCB3aGVuIGNodW5raW5nIGlzIGVuYWJsZWQgdG8gbWVyZ2UgcHJvY2Vzc2luZyByZXN1bHRzIGZyb20gYWxsIGNodW5rc1xuICAgKiBpbnRvIGEgc2luZ2xlIGNvaGVyZW50IHJlc3VsdC5cbiAgICpcbiAgICogVGhlIHByb21wdCByZWNlaXZlcyB0aGUgY29uY2F0ZW5hdGVkIHByb2Nlc3NpbmcgcmVzdWx0cyBmcm9tIGFsbCBjaHVua3NcbiAgICogYW5kIHNob3VsZCBpbnN0cnVjdCB0aGUgbW9kZWwgdG8gc3ludGhlc2l6ZSB0aGVtIGludG8gYSB1bmlmaWVkIG91dHB1dC5cbiAgICpcbiAgICogQGRlZmF1bHQgREVGQVVMVF9BR0dSRUdBVElPTl9QUk9NUFRcbiAgICovXG4gIHJlYWRvbmx5IGFnZ3JlZ2F0aW9uUHJvbXB0Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBFbmFibGUgUERGIGNodW5raW5nIGZvciBsYXJnZSBkb2N1bWVudHMuXG4gICAqXG4gICAqIFdoZW4gZW5hYmxlZCwgZG9jdW1lbnRzIGV4Y2VlZGluZyBjb25maWd1cmVkIHRocmVzaG9sZHMgd2lsbCBiZSBhdXRvbWF0aWNhbGx5XG4gICAqIHNwbGl0IGludG8gY2h1bmtzLCBwcm9jZXNzZWQgaW4gcGFyYWxsZWwgb3Igc2VxdWVudGlhbGx5LCBhbmQgcmVzdWx0cyBhZ2dyZWdhdGVkLlxuICAgKlxuICAgKiBUaGlzIGZlYXR1cmUgaXMgdXNlZnVsIGZvcjpcbiAgICogLSBQcm9jZXNzaW5nIGxhcmdlIFBERnMgKD4xMDAgcGFnZXMpXG4gICAqIC0gSGFuZGxpbmcgZG9jdW1lbnRzIHRoYXQgZXhjZWVkIEJlZHJvY2sgdG9rZW4gbGltaXRzICh+MjAwSyB0b2tlbnMpXG4gICAqIC0gSW1wcm92aW5nIHByb2Nlc3NpbmcgcmVsaWFiaWxpdHkgZm9yIGNvbXBsZXggZG9jdW1lbnRzXG4gICAqIC0gUHJvY2Vzc2luZyBkb2N1bWVudHMgd2l0aCB2YXJpYWJsZSBjb250ZW50IGRlbnNpdHlcbiAgICpcbiAgICogVGhlIGNodW5raW5nIHdvcmtmbG93OlxuICAgKiAxLiBBbmFseXplcyBQREYgdG8gZGV0ZXJtaW5lIHBhZ2UgY291bnQgYW5kIGVzdGltYXRlIHRva2VuIGNvdW50XG4gICAqIDIuIERlY2lkZXMgaWYgY2h1bmtpbmcgaXMgbmVlZGVkIGJhc2VkIG9uIGNvbmZpZ3VyZWQgdGhyZXNob2xkc1xuICAgKiAzLiBJZiBjaHVua2luZyBpcyBuZWVkZWQsIHNwbGl0cyBQREYgaW50byBjaHVua3MgYW5kIHVwbG9hZHMgdG8gUzNcbiAgICogNC4gUHJvY2Vzc2VzIGVhY2ggY2h1bmsgdGhyb3VnaCBjbGFzc2lmaWNhdGlvbiBhbmQgZXh0cmFjdGlvblxuICAgKiA1LiBBZ2dyZWdhdGVzIHJlc3VsdHMgdXNpbmcgbWFqb3JpdHkgdm90aW5nIGZvciBjbGFzc2lmaWNhdGlvblxuICAgKiA2LiBEZWR1cGxpY2F0ZXMgZW50aXRpZXMgYWNyb3NzIGNodW5rc1xuICAgKiA3LiBDbGVhbnMgdXAgdGVtcG9yYXJ5IGNodW5rIGZpbGVzIGZyb20gUzNcbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGVuYWJsZUNodW5raW5nPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogQ29uZmlndXJhdGlvbiBmb3IgUERGIGNodW5raW5nIGJlaGF2aW9yLlxuICAgKlxuICAgKiBPbmx5IGFwcGxpZXMgd2hlbiBgZW5hYmxlQ2h1bmtpbmdgIGlzIHRydWUuIEFsbG93cyBjdXN0b21pemF0aW9uIG9mOlxuICAgKiAtICoqQ2h1bmtpbmcgc3RyYXRlZ3kqKjogSG93IGRvY3VtZW50cyBhcmUgc3BsaXQgKGZpeGVkLXBhZ2VzLCB0b2tlbi1iYXNlZCwgb3IgaHlicmlkKVxuICAgKiAtICoqVGhyZXNob2xkcyoqOiBXaGVuIHRvIHRyaWdnZXIgY2h1bmtpbmcgYmFzZWQgb24gcGFnZSBjb3VudCBvciB0b2tlbiBjb3VudFxuICAgKiAtICoqQ2h1bmsgc2l6ZSBhbmQgb3ZlcmxhcCoqOiBDb250cm9sIGNodW5rIGJvdW5kYXJpZXMgYW5kIGNvbnRleHQgcHJlc2VydmF0aW9uXG4gICAqIC0gKipQcm9jZXNzaW5nIG1vZGUqKjogUGFyYWxsZWwgKGZhc3Rlcikgb3Igc2VxdWVudGlhbCAoY29zdC1vcHRpbWl6ZWQpXG4gICAqIC0gKipBZ2dyZWdhdGlvbiBzdHJhdGVneSoqOiBIb3cgdG8gY29tYmluZSByZXN1bHRzIGZyb20gbXVsdGlwbGUgY2h1bmtzXG4gICAqXG4gICAqICMjIERlZmF1bHQgQ29uZmlndXJhdGlvblxuICAgKlxuICAgKiBJZiBub3QgcHJvdmlkZWQsIHVzZXMgc2Vuc2libGUgZGVmYXVsdHMgb3B0aW1pemVkIGZvciBtb3N0IHVzZSBjYXNlczpcbiAgICogLSBTdHJhdGVneTogYCdoeWJyaWQnYCAocmVjb21tZW5kZWQgLSBiYWxhbmNlcyB0b2tlbiBhbmQgcGFnZSBsaW1pdHMpXG4gICAqIC0gUGFnZSB0aHJlc2hvbGQ6IDEwMCBwYWdlc1xuICAgKiAtIFRva2VuIHRocmVzaG9sZDogMTUwLDAwMCB0b2tlbnNcbiAgICogLSBQcm9jZXNzaW5nIG1vZGU6IGAncGFyYWxsZWwnYFxuICAgKiAtIE1heCBjb25jdXJyZW5jeTogMTBcbiAgICogLSBBZ2dyZWdhdGlvbiBzdHJhdGVneTogYCdtYWpvcml0eS12b3RlJ2BcbiAgICpcbiAgICogIyMgU3RyYXRlZ3kgQ29tcGFyaXNvblxuICAgKlxuICAgKiB8IFN0cmF0ZWd5IHwgQmVzdCBGb3IgfCBQcm9zIHwgQ29ucyB8XG4gICAqIHwtLS0tLS0tLS0tfC0tLS0tLS0tLS18LS0tLS0tfC0tLS0tLXxcbiAgICogfCBgaHlicmlkYCB8IE1vc3QgZG9jdW1lbnRzIHwgQmFsYW5jZXMgdG9rZW4vcGFnZSBsaW1pdHMgfCBTbGlnaHRseSBtb3JlIGNvbXBsZXggfFxuICAgKiB8IGB0b2tlbi1iYXNlZGAgfCBWYXJpYWJsZSBkZW5zaXR5IHwgUmVzcGVjdHMgbW9kZWwgbGltaXRzIHwgU2xvd2VyIGFuYWx5c2lzIHxcbiAgICogfCBgZml4ZWQtcGFnZXNgIHwgVW5pZm9ybSBkZW5zaXR5IHwgU2ltcGxlLCBmYXN0IHwgTWF5IGV4Y2VlZCB0b2tlbiBsaW1pdHMgfFxuICAgKlxuICAgKiBAZGVmYXVsdCB1bmRlZmluZWQgKHVzZXMgZGVmYXVsdCBjb25maWd1cmF0aW9uIHdoZW4gZW5hYmxlQ2h1bmtpbmcgaXMgdHJ1ZSlcbiAgICpcbiAgICogQHNlZSB7QGxpbmsgQ2h1bmtpbmdDb25maWd9IGZvciBkZXRhaWxlZCBjb25maWd1cmF0aW9uIG9wdGlvbnNcbiAgICovXG4gIHJlYWRvbmx5IGNodW5raW5nQ29uZmlnPzogQ2h1bmtpbmdDb25maWc7XG59XG5cbi8qKlxuICogRG9jdW1lbnQgcHJvY2Vzc2luZyB3b3JrZmxvdyBwb3dlcmVkIGJ5IEFtYXpvbiBCZWRyb2NrIGZvdW5kYXRpb24gbW9kZWxzLlxuICpcbiAqIEV4dGVuZHMgQmFzZURvY3VtZW50UHJvY2Vzc2luZyB0byBwcm92aWRlIEFJLXBvd2VyZWQgZG9jdW1lbnQgY2xhc3NpZmljYXRpb24gYW5kIGV4dHJhY3Rpb25cbiAqIHVzaW5nIEFtYXpvbiBCZWRyb2NrIGZvdW5kYXRpb24gbW9kZWxzLiBUaGlzIGltcGxlbWVudGF0aW9uIG9mZmVyczpcbiAqXG4gKiAjIyBLZXkgRmVhdHVyZXNcbiAqIC0gKipBSS1Qb3dlcmVkIENsYXNzaWZpY2F0aW9uKio6IFVzZXMgQ2xhdWRlIDMuNyBTb25uZXQgKGNvbmZpZ3VyYWJsZSkgdG8gY2xhc3NpZnkgZG9jdW1lbnQgdHlwZXNcbiAqIC0gKipJbnRlbGxpZ2VudCBFeHRyYWN0aW9uKio6IEV4dHJhY3RzIHN0cnVjdHVyZWQgZGF0YSBmcm9tIGRvY3VtZW50cyB1c2luZyBmb3VuZGF0aW9uIG1vZGVsc1xuICogLSAqKkNyb3NzLVJlZ2lvbiBJbmZlcmVuY2UqKjogT3B0aW9uYWwgc3VwcG9ydCBmb3IgaW1wcm92ZWQgYXZhaWxhYmlsaXR5IHZpYSBpbmZlcmVuY2UgcHJvZmlsZXNcbiAqIC0gKipGbGV4aWJsZSBQcm9jZXNzaW5nKio6IE9wdGlvbmFsIGVucmljaG1lbnQgYW5kIHBvc3QtcHJvY2Vzc2luZyBMYW1iZGEgZnVuY3Rpb25zXG4gKiAtICoqQ29zdCBPcHRpbWl6ZWQqKjogQ29uZmlndXJhYmxlIHRpbWVvdXRzIGFuZCBtb2RlbCBzZWxlY3Rpb24gZm9yIGNvc3QgY29udHJvbFxuICpcbiAqICMjIFByb2Nlc3NpbmcgV29ya2Zsb3dcbiAqIFMzIFVwbG9hZCDihpIgQ2xhc3NpZmljYXRpb24gKEJlZHJvY2spIOKGkiBFeHRyYWN0aW9uIChCZWRyb2NrKSDihpIgW0VucmljaG1lbnRdIOKGkiBbUG9zdC1Qcm9jZXNzaW5nXSDihpIgUmVzdWx0c1xuICpcbiAqICMjIERlZmF1bHQgTW9kZWxzXG4gKiAtIENsYXNzaWZpY2F0aW9uOiBDbGF1ZGUgMy43IFNvbm5ldCAoYW50aHJvcGljLmNsYXVkZS0zLTctc29ubmV0LTIwMjUwMjE5LXYxOjApXG4gKiAtIEV4dHJhY3Rpb246IENsYXVkZSAzLjcgU29ubmV0IChhbnRocm9waWMuY2xhdWRlLTMtNy1zb25uZXQtMjAyNTAyMTktdjE6MClcbiAqXG4gKiAjIyBQcm9tcHQgVGVtcGxhdGVzXG4gKiBUaGUgY29uc3RydWN0IHVzZXMgZGVmYXVsdCBwcm9tcHRzIHRoYXQgY2FuIGJlIGN1c3RvbWl6ZWQ6XG4gKiAtICoqQ2xhc3NpZmljYXRpb24qKjogQW5hbHl6ZXMgZG9jdW1lbnQgYW5kIHJldHVybnMgSlNPTiB3aXRoIGRvY3VtZW50Q2xhc3NpZmljYXRpb24gZmllbGRcbiAqIC0gKipFeHRyYWN0aW9uKio6IFVzZXMgY2xhc3NpZmljYXRpb24gcmVzdWx0IHRvIGV4dHJhY3QgZW50aXRpZXMgaW4gc3RydWN0dXJlZCBKU09OIGZvcm1hdFxuICpcbiAqICMjIENyb3NzLVJlZ2lvbiBJbmZlcmVuY2VcbiAqIFdoZW4gZW5hYmxlZCwgdXNlcyBCZWRyb2NrIGluZmVyZW5jZSBwcm9maWxlcyBmb3IgaW1wcm92ZWQgYXZhaWxhYmlsaXR5OlxuICogLSBVUyBwcmVmaXg6IFJvdXRlcyB0byBVUy1iYXNlZCByZWdpb25zIGZvciBsb3dlciBsYXRlbmN5XG4gKiAtIEVVIHByZWZpeDogUm91dGVzIHRvIEVVLWJhc2VkIHJlZ2lvbnMgZm9yIGRhdGEgcmVzaWRlbmN5IGNvbXBsaWFuY2VcbiAqL1xuZXhwb3J0IGNsYXNzIEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmcgZXh0ZW5kcyBCYXNlRG9jdW1lbnRQcm9jZXNzaW5nIHtcbiAgcHJvdGVjdGVkIHN0YXRpYyByZWFkb25seSBERUZBVUxUX0NMQVNTSUZJQ0FUSU9OX1BST01QVCA9IGBcbiAgQW5hbHl6ZSB0aGUgZG9jdW1lbnQgYmVsb3csIGFuZCBjbGFzc2lmeSB0aGUgdHlwZSBvZiBkb2N1bWVudCBpdCBpcyAoZWcuIElOVk9JQ0UsIElERU5USVRZX0RPQ1VNRU5ULCBSRUNFSVBULCBldGMpLiBUaGUgcmVzdWx0IHNob3VsZCBiZSBpbiBKU09OIGFuZCBzaG91bGQgZm9sbG93IHRoZSBmb2xsb3dpbmcgc3RydWN0dXJlIChvbmx5IHJlc3BvbmQgaW4gSlNPTiB3aXRoIHRoZSBmb2xsb3dpbmcgc3RydWN0dXJlIGFuZCBkbyBub3QgdXNlIG1hcmtkb3duIHRvIGluZGljYXRlIHRoZSBqc29uLCBqdXN0IG91dHB1dCBwbGFpbiBvbGQganNvbiB3aXRoIG5vdGhpbmcgZWxzZSk6XG5cbiAge1xuICAgICAgZG9jdW1lbnRDbGFzc2lmaWNhdGlvbjogPENMQVNTSUZJQ0FUSU9OPlxuICB9XG5cbiAgQXR0YWNoZWQgZG9jdW1lbnQgaXMgYXMgZm9sbG93czpcblxuICBgO1xuXG4gIHByb3RlY3RlZCBzdGF0aWMgcmVhZG9ubHkgREVGQVVMVF9QUk9DRVNTSU5HX1BST01QVCA9IGBcbiAgVGhlIGRvY3VtZW50IGJlbG93IGhhcyBiZWVuIGNsYXNzaWZpZWQgYXMgW0FDVFVBTF9DTEFTU0lGSUNBVElPTl0uIEV4dHJhY3QgaW1wb3J0YW50IGVudGl0aWVzIGZyb20gdGhlIGRvY3VtZW50IGFuZCByZXR1cm4gdGhlIHJlc3VsdCBhcyBKU09OIGZvbGxvd2luZyB0aGUgc3RydWN0dXJlIGJlbG93IChvbmx5IHJlc3BvbmQgaW4gSlNPTiB3aXRoIHRoZSBmb2xsb3dpbmcgc3RydWN0dXJlIGFuZCBkbyBub3QgdXNlIG1hcmtkb3duIHRvIGluZGljYXRlIHRoZSBqc29uLCBqdXN0IG91dHB1dCBwbGFpbiBvbGQganNvbiB3aXRoIG5vdGhpbmcgZWxzZSk6XG5cbiAge1xuICAgICAgZG9jdW1lbnRDbGFzc2lmaWNhdGlvbjogPENMQVNTSUZJQ0FUSU9OPixcbiAgICAgIHJlc3VsdDoge1xuICAgICAgICBlbnRpdGllczogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHR5cGU6IDxUWVBFIE9GIEVOVElUWT5cbiAgICAgICAgICAgICAgICB2YWx1ZTogPFZBTFVFIE9GIEVOVElUWT5cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAuLi5cbiAgICAgICAgXVxuICAgICAgfVxuICB9XG5cbiAgQXR0YWNoZWQgZG9jdW1lbnQgaXMgYXMgZm9sbG93czpcblxuICBgO1xuXG4gIHByb3RlY3RlZCBzdGF0aWMgcmVhZG9ubHkgREVGQVVMVF9BR0dSRUdBVElPTl9QUk9NUFQgPSBgXG4gIFlvdSBhcmUgZ2l2ZW4gdGhlIHByb2Nlc3NpbmcgcmVzdWx0cyBmcm9tIG11bHRpcGxlIGNodW5rcyBvZiBhIGxhcmdlIGRvY3VtZW50IHRoYXQgd2FzIHNwbGl0IGZvciBwcm9jZXNzaW5nLlxuICBZb3VyIHRhc2sgaXMgdG8gc3ludGhlc2l6ZSB0aGVzZSBjaHVuayByZXN1bHRzIGludG8gYSBzaW5nbGUsIGNvaGVyZW50IGZpbmFsIHJlc3VsdC5cblxuICBJbnN0cnVjdGlvbnM6XG4gIDEuIFJldmlldyBhbGwgdGhlIGNodW5rIHJlc3VsdHMgcHJvdmlkZWQgYmVsb3dcbiAgMi4gTWVyZ2UgYW5kIGRlZHVwbGljYXRlIGFueSBvdmVybGFwcGluZyBpbmZvcm1hdGlvbiAoY2h1bmtzIG1heSBoYXZlIG92ZXJsYXBwaW5nIHBhZ2VzKVxuICAzLiBTeW50aGVzaXplIHRoZSBpbmZvcm1hdGlvbiBpbnRvIGEgdW5pZmllZCwgY29oZXJlbnQgcmVzdWx0XG4gIDQuIE1haW50YWluIHRoZSBzYW1lIG91dHB1dCBmb3JtYXQgYXMgdGhlIGluZGl2aWR1YWwgY2h1bmsgcmVzdWx0c1xuICA1LiBJZiB0aGUgY2h1bmtzIGNvbnRhaW4gc3VtbWFyaWVzLCBjcmVhdGUgYSBjb21wcmVoZW5zaXZlIHN1bW1hcnkgdGhhdCBjb3ZlcnMgYWxsIHNlY3Rpb25zXG4gIDYuIElmIHRoZSBjaHVua3MgY29udGFpbiBlbnRpdGllcywgZGVkdXBsaWNhdGUgYW5kIGNvbnNvbGlkYXRlIHRoZW1cbiAgNy4gUHJlc2VydmUgaW1wb3J0YW50IGRldGFpbHMgZnJvbSBlYWNoIGNodW5rIHdoaWxlIGF2b2lkaW5nIHJlZHVuZGFuY3lcblxuICBSZXR1cm4gdGhlIHJlc3VsdCBhcyBKU09OIChvbmx5IHJlc3BvbmQgaW4gSlNPTiB3aXRob3V0IG1hcmtkb3duIGZvcm1hdHRpbmcpOlxuXG4gIHtcbiAgICAgIFwicmVzdWx0XCI6IDxTWU5USEVTSVpFRF9SRVNVTFQ+XG4gIH1cblxuICBUaGUgY2h1bmsgcmVzdWx0cyB0byBhZ2dyZWdhdGUgYXJlIGFzIGZvbGxvd3M6XG5cbiAgYDtcblxuICAvKiogQ29uZmlndXJhdGlvbiBwcm9wZXJ0aWVzIHNwZWNpZmljIHRvIEJlZHJvY2sgZG9jdW1lbnQgcHJvY2Vzc2luZyAqL1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzOiBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHM7XG4gIC8qKiBUaGUgU3RlcCBGdW5jdGlvbnMgc3RhdGUgbWFjaGluZSB0aGF0IG9yY2hlc3RyYXRlcyB0aGUgZG9jdW1lbnQgcHJvY2Vzc2luZyB3b3JrZmxvdyAqL1xuICByZWFkb25seSBzdGF0ZU1hY2hpbmU7XG4gIC8qKiBDYWNoZWQgY2xhc3NpZmljYXRpb24gTGFtYmRhIGZ1bmN0aW9uIHRvIGF2b2lkIGR1cGxpY2F0ZSByZXNvdXJjZSBjcmVhdGlvbiAqL1xuICBwcml2YXRlIF9jbGFzc2lmaWNhdGlvbkZ1bmN0aW9uPzogRnVuY3Rpb247XG4gIC8qKiBDYWNoZWQgcHJvY2Vzc2luZyBMYW1iZGEgZnVuY3Rpb24gdG8gYXZvaWQgZHVwbGljYXRlIHJlc291cmNlIGNyZWF0aW9uICovXG4gIHByaXZhdGUgX3Byb2Nlc3NpbmdGdW5jdGlvbj86IEZ1bmN0aW9uO1xuICAvKiogQ291bnRlciBmb3IgZ2VuZXJhdGluZyB1bmlxdWUgY2xhc3NpZmljYXRpb24gc3RlcCBJRHMgKi9cbiAgcHJpdmF0ZSBfY2xhc3NpZmljYXRpb25TdGVwQ291bnRlciA9IDA7XG4gIC8qKiBDb3VudGVyIGZvciBnZW5lcmF0aW5nIHVuaXF1ZSBwcm9jZXNzaW5nIHN0ZXAgSURzICovXG4gIHByaXZhdGUgX3Byb2Nlc3NpbmdTdGVwQ291bnRlciA9IDA7XG4gIC8qKiBDYWNoZWQgYWdncmVnYXRpb24gTGFtYmRhIGZ1bmN0aW9uIHRvIGF2b2lkIGR1cGxpY2F0ZSByZXNvdXJjZSBjcmVhdGlvbiAqL1xuICBwcml2YXRlIF9hZ2dyZWdhdGlvbkZ1bmN0aW9uPzogRnVuY3Rpb247XG4gIC8qKiBDb3VudGVyIGZvciBnZW5lcmF0aW5nIHVuaXF1ZSBhZ2dyZWdhdGlvbiBzdGVwIElEcyAqL1xuICBwcml2YXRlIF9hZ2dyZWdhdGlvblN0ZXBDb3VudGVyID0gMDtcbiAgLyoqIENhY2hlZCBjbGVhbnVwIExhbWJkYSBmdW5jdGlvbiB0byBhdm9pZCBkdXBsaWNhdGUgcmVzb3VyY2UgY3JlYXRpb24gKi9cbiAgcHJpdmF0ZSBfY2xlYW51cEZ1bmN0aW9uPzogRnVuY3Rpb247XG4gIC8qKiBDb3VudGVyIGZvciBnZW5lcmF0aW5nIHVuaXF1ZSBlbnJpY2htZW50IHN0ZXAgSURzICovXG4gIHByaXZhdGUgX2VucmljaG1lbnRTdGVwQ291bnRlciA9IDA7XG4gIC8qKiBDb3VudGVyIGZvciBnZW5lcmF0aW5nIHVuaXF1ZSBwb3N0LXByb2Nlc3Npbmcgc3RlcCBJRHMgKi9cbiAgcHJpdmF0ZSBfcG9zdFByb2Nlc3NpbmdTdGVwQ291bnRlciA9IDA7XG5cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nIGNvbnN0cnVjdC5cbiAgICpcbiAgICogSW5pdGlhbGl6ZXMgdGhlIEJlZHJvY2stcG93ZXJlZCBkb2N1bWVudCBwcm9jZXNzaW5nIHBpcGVsaW5lIHdpdGggQUkgY2xhc3NpZmljYXRpb25cbiAgICogYW5kIGV4dHJhY3Rpb24gY2FwYWJpbGl0aWVzLiBDcmVhdGVzIExhbWJkYSBmdW5jdGlvbnMgd2l0aCBhcHByb3ByaWF0ZSBJQU0gcm9sZXNcbiAgICogZm9yIEJlZHJvY2sgbW9kZWwgaW52b2NhdGlvbiBhbmQgUzMgYWNjZXNzLlxuICAgKlxuICAgKiBAcGFyYW0gc2NvcGUgLSBUaGUgc2NvcGUgaW4gd2hpY2ggdG8gZGVmaW5lIHRoaXMgY29uc3RydWN0XG4gICAqIEBwYXJhbSBpZCAtIFRoZSBzY29wZWQgY29uc3RydWN0IElELiBNdXN0IGJlIHVuaXF1ZSB3aXRoaW4gdGhlIHNjb3BlLlxuICAgKiBAcGFyYW0gcHJvcHMgLSBDb25maWd1cmF0aW9uIHByb3BlcnRpZXMgZm9yIHRoZSBCZWRyb2NrIGRvY3VtZW50IHByb2Nlc3NpbmcgcGlwZWxpbmVcbiAgICogQHRocm93cyBFcnJvciBpZiBjaHVua2luZyBjb25maWd1cmF0aW9uIGlzIGludmFsaWRcbiAgICovXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQsIHByb3BzKTtcblxuICAgIC8vIFZhbGlkYXRlIGNodW5raW5nIGNvbmZpZ3VyYXRpb24gaWYgcHJvdmlkZWRcbiAgICBpZiAocHJvcHMuZW5hYmxlQ2h1bmtpbmcgJiYgcHJvcHMuY2h1bmtpbmdDb25maWcpIHtcbiAgICAgIHRoaXMudmFsaWRhdGVDaHVua2luZ0NvbmZpZyhwcm9wcy5jaHVua2luZ0NvbmZpZyk7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLm5ldHdvcmspIHtcbiAgICAgIHByb3BzLm5ldHdvcmsuY3JlYXRlU2VydmljZUVuZHBvaW50KCd2cGNlLWJlZHJvY2snLCBJbnRlcmZhY2VWcGNFbmRwb2ludEF3c1NlcnZpY2UuQkVEUk9DSyk7XG4gICAgICBwcm9wcy5uZXR3b3JrLmNyZWF0ZVNlcnZpY2VFbmRwb2ludCgndnBjZS1iZWRyb2NrLXJ1bnRpbWUnLCBJbnRlcmZhY2VWcGNFbmRwb2ludEF3c1NlcnZpY2UuQkVEUk9DS19SVU5USU1FKTtcbiAgICB9XG5cbiAgICB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcyA9IHByb3BzO1xuICAgIHRoaXMuc3RhdGVNYWNoaW5lID0gdGhpcy5oYW5kbGVTdGF0ZU1hY2hpbmVDcmVhdGlvbignYmVkcm9jay1kb2N1bWVudC1wcm9jZXNzaW5nLXdvcmtmbG93Jyk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHRoZSBjaHVua2luZyBjb25maWd1cmF0aW9uIHBhcmFtZXRlcnMuXG4gICAqXG4gICAqIEVuc3VyZXMgdGhhdDpcbiAgICogLSBDaHVuayBzaXplIGlzIGdyZWF0ZXIgdGhhbiAwXG4gICAqIC0gT3ZlcmxhcCBpcyBub24tbmVnYXRpdmUgYW5kIGxlc3MgdGhhbiBjaHVuayBzaXplXG4gICAqIC0gVGhyZXNob2xkcyBhcmUgZ3JlYXRlciB0aGFuIDBcbiAgICogLSBNYXggY29uY3VycmVuY3kgaXMgZ3JlYXRlciB0aGFuIDBcbiAgICogLSBNaW4gc3VjY2VzcyB0aHJlc2hvbGQgaXMgYmV0d2VlbiAwIGFuZCAxXG4gICAqXG4gICAqIEBwYXJhbSBjb25maWcgLSBUaGUgY2h1bmtpbmcgY29uZmlndXJhdGlvbiB0byB2YWxpZGF0ZVxuICAgKiBAdGhyb3dzIEVycm9yIGlmIGFueSBjb25maWd1cmF0aW9uIHBhcmFtZXRlciBpcyBpbnZhbGlkXG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlQ2h1bmtpbmdDb25maWcoY29uZmlnOiBDaHVua2luZ0NvbmZpZyk6IHZvaWQge1xuICAgIC8vIFZhbGlkYXRlIGNodW5rIHNpemUgKGZvciBmaXhlZC1wYWdlcyBzdHJhdGVneSlcbiAgICBpZiAoY29uZmlnLmNodW5rU2l6ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAoY29uZmlnLmNodW5rU2l6ZSA8PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ2h1bmtpbmdDb25maWcgdmFsaWRhdGlvbiBlcnJvcjogY2h1bmtTaXplIG11c3QgYmUgZ3JlYXRlciB0aGFuIDAnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBWYWxpZGF0ZSBvdmVybGFwIHBhZ2VzIChmb3IgZml4ZWQtcGFnZXMgc3RyYXRlZ3kpXG4gICAgaWYgKGNvbmZpZy5vdmVybGFwUGFnZXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKGNvbmZpZy5vdmVybGFwUGFnZXMgPCAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ2h1bmtpbmdDb25maWcgdmFsaWRhdGlvbiBlcnJvcjogb3ZlcmxhcFBhZ2VzIG11c3QgYmUgbm9uLW5lZ2F0aXZlJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBlZmZlY3RpdmVDaHVua1NpemUgPSBjb25maWcuY2h1bmtTaXplIHx8IDUwOyAvLyBkZWZhdWx0IGNodW5rIHNpemVcbiAgICAgIGlmIChjb25maWcub3ZlcmxhcFBhZ2VzID49IGVmZmVjdGl2ZUNodW5rU2l6ZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NodW5raW5nQ29uZmlnIHZhbGlkYXRpb24gZXJyb3I6IG92ZXJsYXBQYWdlcyBtdXN0IGJlIGxlc3MgdGhhbiBjaHVua1NpemUnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBWYWxpZGF0ZSBwYWdlIHRocmVzaG9sZFxuICAgIGlmIChjb25maWcucGFnZVRocmVzaG9sZCAhPT0gdW5kZWZpbmVkICYmIGNvbmZpZy5wYWdlVGhyZXNob2xkIDw9IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2h1bmtpbmdDb25maWcgdmFsaWRhdGlvbiBlcnJvcjogcGFnZVRocmVzaG9sZCBtdXN0IGJlIGdyZWF0ZXIgdGhhbiAwJyk7XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgdG9rZW4gdGhyZXNob2xkXG4gICAgaWYgKGNvbmZpZy50b2tlblRocmVzaG9sZCAhPT0gdW5kZWZpbmVkICYmIGNvbmZpZy50b2tlblRocmVzaG9sZCA8PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NodW5raW5nQ29uZmlnIHZhbGlkYXRpb24gZXJyb3I6IHRva2VuVGhyZXNob2xkIG11c3QgYmUgZ3JlYXRlciB0aGFuIDAnKTtcbiAgICB9XG5cbiAgICAvLyBWYWxpZGF0ZSBtYXggdG9rZW5zIHBlciBjaHVuayAoZm9yIHRva2VuLWJhc2VkIHN0cmF0ZWd5KVxuICAgIGlmIChjb25maWcubWF4VG9rZW5zUGVyQ2h1bmsgIT09IHVuZGVmaW5lZCAmJiBjb25maWcubWF4VG9rZW5zUGVyQ2h1bmsgPD0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDaHVua2luZ0NvbmZpZyB2YWxpZGF0aW9uIGVycm9yOiBtYXhUb2tlbnNQZXJDaHVuayBtdXN0IGJlIGdyZWF0ZXIgdGhhbiAwJyk7XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgb3ZlcmxhcCB0b2tlbnMgKGZvciB0b2tlbi1iYXNlZCBhbmQgaHlicmlkIHN0cmF0ZWdpZXMpXG4gICAgaWYgKGNvbmZpZy5vdmVybGFwVG9rZW5zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmIChjb25maWcub3ZlcmxhcFRva2VucyA8IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDaHVua2luZ0NvbmZpZyB2YWxpZGF0aW9uIGVycm9yOiBvdmVybGFwVG9rZW5zIG11c3QgYmUgbm9uLW5lZ2F0aXZlJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBlZmZlY3RpdmVNYXhUb2tlbnMgPSBjb25maWcubWF4VG9rZW5zUGVyQ2h1bmsgfHwgMTAwMDAwOyAvLyBkZWZhdWx0IG1heCB0b2tlbnNcbiAgICAgIGlmIChjb25maWcub3ZlcmxhcFRva2VucyA+PSBlZmZlY3RpdmVNYXhUb2tlbnMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDaHVua2luZ0NvbmZpZyB2YWxpZGF0aW9uIGVycm9yOiBvdmVybGFwVG9rZW5zIG11c3QgYmUgbGVzcyB0aGFuIG1heFRva2Vuc1BlckNodW5rJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgbWF4IHBhZ2VzIHBlciBjaHVuayAoZm9yIGh5YnJpZCBzdHJhdGVneSlcbiAgICBpZiAoY29uZmlnLm1heFBhZ2VzUGVyQ2h1bmsgIT09IHVuZGVmaW5lZCAmJiBjb25maWcubWF4UGFnZXNQZXJDaHVuayA8PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NodW5raW5nQ29uZmlnIHZhbGlkYXRpb24gZXJyb3I6IG1heFBhZ2VzUGVyQ2h1bmsgbXVzdCBiZSBncmVhdGVyIHRoYW4gMCcpO1xuICAgIH1cblxuICAgIC8vIFZhbGlkYXRlIHRhcmdldCB0b2tlbnMgcGVyIGNodW5rIChmb3IgaHlicmlkIHN0cmF0ZWd5KVxuICAgIGlmIChjb25maWcudGFyZ2V0VG9rZW5zUGVyQ2h1bmsgIT09IHVuZGVmaW5lZCAmJiBjb25maWcudGFyZ2V0VG9rZW5zUGVyQ2h1bmsgPD0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDaHVua2luZ0NvbmZpZyB2YWxpZGF0aW9uIGVycm9yOiB0YXJnZXRUb2tlbnNQZXJDaHVuayBtdXN0IGJlIGdyZWF0ZXIgdGhhbiAwJyk7XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgbWF4IGNvbmN1cnJlbmN5XG4gICAgaWYgKGNvbmZpZy5tYXhDb25jdXJyZW5jeSAhPT0gdW5kZWZpbmVkICYmIGNvbmZpZy5tYXhDb25jdXJyZW5jeSA8PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NodW5raW5nQ29uZmlnIHZhbGlkYXRpb24gZXJyb3I6IG1heENvbmN1cnJlbmN5IG11c3QgYmUgZ3JlYXRlciB0aGFuIDAnKTtcbiAgICB9XG5cbiAgICAvLyBWYWxpZGF0ZSBtaW4gc3VjY2VzcyB0aHJlc2hvbGRcbiAgICBpZiAoY29uZmlnLm1pblN1Y2Nlc3NUaHJlc2hvbGQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKGNvbmZpZy5taW5TdWNjZXNzVGhyZXNob2xkIDwgMCB8fCBjb25maWcubWluU3VjY2Vzc1RocmVzaG9sZCA+IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDaHVua2luZ0NvbmZpZyB2YWxpZGF0aW9uIGVycm9yOiBtaW5TdWNjZXNzVGhyZXNob2xkIG11c3QgYmUgYmV0d2VlbiAwIGFuZCAxJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEltcGxlbWVudHMgdGhlIGRvY3VtZW50IGNsYXNzaWZpY2F0aW9uIHN0ZXAgdXNpbmcgQW1hem9uIEJlZHJvY2suXG4gICAqXG4gICAqIENyZWF0ZXMgYSBMYW1iZGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIHRoZSBjb25maWd1cmVkIEJlZHJvY2sgbW9kZWwgdG8gY2xhc3NpZnlcbiAgICogdGhlIGRvY3VtZW50IHR5cGUuIFRoZSBmdW5jdGlvbiByZWFkcyB0aGUgZG9jdW1lbnQgZnJvbSBTMyBhbmQgc2VuZHMgaXQgdG9cbiAgICogQmVkcm9jayB3aXRoIHRoZSBjbGFzc2lmaWNhdGlvbiBwcm9tcHQuXG4gICAqXG4gICAqIFRoaXMgbWV0aG9kIGNhY2hlcyB0aGUgTGFtYmRhIGZ1bmN0aW9uIHRvIGF2b2lkIGNyZWF0aW5nIGR1cGxpY2F0ZSByZXNvdXJjZXMsXG4gICAqIGJ1dCBjcmVhdGVzIGEgbmV3IExhbWJkYUludm9rZSB0YXNrIGVhY2ggdGltZSB0byBhbGxvdyBwcm9wZXIgc3RhdGUgY2hhaW5pbmcuXG4gICAqXG4gICAqIEByZXR1cm5zIExhbWJkYUludm9rZSB0YXNrIGNvbmZpZ3VyZWQgZm9yIGRvY3VtZW50IGNsYXNzaWZpY2F0aW9uXG4gICAqL1xuICBwcm90ZWN0ZWQgY2xhc3NpZmljYXRpb25TdGVwKCk6IERvY3VtZW50UHJvY2Vzc2luZ1N0ZXBUeXBlIHtcbiAgICAvLyBDcmVhdGUgTGFtYmRhIGZ1bmN0aW9uIG9ubHkgb25jZVxuICAgIGlmICghdGhpcy5fY2xhc3NpZmljYXRpb25GdW5jdGlvbikge1xuICAgICAgY29uc3QgcHJvbXB0ID0gdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuY2xhc3NpZmljYXRpb25Qcm9tcHQgfHwgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZy5ERUZBVUxUX0NMQVNTSUZJQ0FUSU9OX1BST01QVDtcbiAgICAgIGNvbnN0IGFkanVzdGVkTW9kZWxJZCA9IEJlZHJvY2tNb2RlbFV0aWxzLmRlcml2ZUFjdHVhbE1vZGVsSWQodGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuY2xhc3NpZmljYXRpb25CZWRyb2NrTW9kZWwpO1xuICAgICAgY29uc3Qgcm9sZSA9IHRoaXMuZ2VuZXJhdGVMYW1iZGFSb2xlRm9yQmVkcm9jaygnQ2xhc3NpZmljYXRpb25MYW1iZGFSb2xlJywgdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuY2xhc3NpZmljYXRpb25CZWRyb2NrTW9kZWwpO1xuICAgICAgY29uc3QgeyByZWdpb24sIGFjY291bnQgfSA9IFN0YWNrLm9mKHRoaXMpO1xuICAgICAgY29uc3QgZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMgPSBMYW1iZGFJYW1VdGlscy5jcmVhdGVMb2dzUGVybWlzc2lvbnMoe1xuICAgICAgICBhY2NvdW50LFxuICAgICAgICBmdW5jdGlvbk5hbWU6ICdiZWRyb2NrLWlkcC1jbGFzc2lmaWNhdGlvbicsXG4gICAgICAgIHJlZ2lvbixcbiAgICAgICAgc2NvcGU6IHRoaXMsXG4gICAgICAgIGVuYWJsZU9ic2VydmFiaWxpdHk6IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLmVuYWJsZU9ic2VydmFiaWxpdHksXG4gICAgICB9KTtcblxuICAgICAgdGhpcy5lbmNyeXB0aW9uS2V5LmdyYW50RW5jcnlwdERlY3J5cHQocm9sZSk7XG5cbiAgICAgIHRoaXMuX2NsYXNzaWZpY2F0aW9uRnVuY3Rpb24gPSBuZXcgUHl0aG9uRnVuY3Rpb24odGhpcywgJ0JlZHJvY2tDbGFzc2lmaWNhdGlvbkZ1bmN0aW9uJywge1xuICAgICAgICBmdW5jdGlvbk5hbWU6IGdlbmVyYXRlZExvZ1Blcm1pc3Npb25zLnVuaXF1ZUZ1bmN0aW9uTmFtZSxcbiAgICAgICAgYXJjaGl0ZWN0dXJlOiBBcmNoaXRlY3R1cmUuWDg2XzY0LFxuICAgICAgICBydW50aW1lOiBEZWZhdWx0UnVudGltZXMuUFlUSE9OLFxuICAgICAgICBlbnRyeTogcGF0aC5qb2luKF9fZGlybmFtZSwgJ3Jlc291cmNlcy9kZWZhdWx0LWJlZHJvY2staW52b2tlJyksXG4gICAgICAgIHJvbGUsXG4gICAgICAgIG1lbW9yeVNpemU6IDUxMixcbiAgICAgICAgdGltZW91dDogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuc3RlcFRpbWVvdXRzIHx8IER1cmF0aW9uLm1pbnV0ZXMoNSksXG4gICAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgICAgTU9ERUxfSUQ6IGFkanVzdGVkTW9kZWxJZCxcbiAgICAgICAgICBQUk9NUFQ6IHByb21wdCxcbiAgICAgICAgICBJTlZPS0VfVFlQRTogJ2NsYXNzaWZpY2F0aW9uJyxcbiAgICAgICAgICAuLi5Qb3dlcnRvb2xzQ29uZmlnLmdlbmVyYXRlRGVmYXVsdExhbWJkYUNvbmZpZyhcbiAgICAgICAgICAgIHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLmVuYWJsZU9ic2VydmFiaWxpdHksXG4gICAgICAgICAgICB0aGlzLm1ldHJpY05hbWVzcGFjZSxcbiAgICAgICAgICAgIHRoaXMubWV0cmljU2VydmljZU5hbWUsXG4gICAgICAgICAgKSxcbiAgICAgICAgfSxcbiAgICAgICAgZW52aXJvbm1lbnRFbmNyeXB0aW9uOiB0aGlzLmVuY3J5cHRpb25LZXksXG4gICAgICAgIHZwYzogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29ya1xuICAgICAgICAgID8gdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29yay52cGNcbiAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgdnBjU3VibmV0czogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29ya1xuICAgICAgICAgID8gdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29yay5hcHBsaWNhdGlvblN1Ym5ldFNlbGVjdGlvbigpXG4gICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICB9KTtcblxuICAgICAgZm9yIChjb25zdCBzdGF0ZW1lbnQgb2YgZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMucG9saWN5U3RhdGVtZW50cykge1xuICAgICAgICB0aGlzLl9jbGFzc2lmaWNhdGlvbkZ1bmN0aW9uLnJvbGU/LmFkZFRvUHJpbmNpcGFsUG9saWN5KHN0YXRlbWVudCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrKSB7XG4gICAgICAgIHRoaXMuX2NsYXNzaWZpY2F0aW9uRnVuY3Rpb24ucm9sZT8uYWRkVG9QcmluY2lwYWxQb2xpY3koTGFtYmRhSWFtVXRpbHMuZ2VuZXJhdGVMYW1iZGFWUENQZXJtaXNzaW9ucygpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBbHdheXMgY3JlYXRlIGEgbmV3IExhbWJkYUludm9rZSB0YXNrIHRvIGFsbG93IHByb3BlciBzdGF0ZSBjaGFpbmluZ1xuICAgIGNvbnN0IHN0ZXBJZCA9IGBDbGFzc2lmaWNhdGlvblN0ZXAtJHt0aGlzLl9jbGFzc2lmaWNhdGlvblN0ZXBDb3VudGVyfWA7XG4gICAgdGhpcy5fY2xhc3NpZmljYXRpb25TdGVwQ291bnRlcisrO1xuXG4gICAgcmV0dXJuIG5ldyBMYW1iZGFJbnZva2UodGhpcywgc3RlcElkLCB7XG4gICAgICBsYW1iZGFGdW5jdGlvbjogdGhpcy5fY2xhc3NpZmljYXRpb25GdW5jdGlvbixcbiAgICAgIHJlc3VsdFBhdGg6ICckLmNsYXNzaWZpY2F0aW9uUmVzdWx0JyxcbiAgICAgIHJlc3VsdFNlbGVjdG9yOiB7XG4gICAgICAgICdkb2N1bWVudENsYXNzaWZpY2F0aW9uLiQnOiAnJC5QYXlsb2FkLmRvY3VtZW50Q2xhc3NpZmljYXRpb24nLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbXBsZW1lbnRzIHRoZSBkb2N1bWVudCBleHRyYWN0aW9uIHN0ZXAgdXNpbmcgQW1hem9uIEJlZHJvY2suXG4gICAqXG4gICAqIENyZWF0ZXMgYSBMYW1iZGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIHRoZSBjb25maWd1cmVkIEJlZHJvY2sgbW9kZWwgdG8gZXh0cmFjdFxuICAgKiBzdHJ1Y3R1cmVkIGRhdGEgZnJvbSB0aGUgZG9jdW1lbnQuIFVzZXMgdGhlIGNsYXNzaWZpY2F0aW9uIHJlc3VsdCBmcm9tIHRoZVxuICAgKiBwcmV2aW91cyBzdGVwIHRvIHByb3ZpZGUgY29udGV4dCBmb3IgbW9yZSBhY2N1cmF0ZSBleHRyYWN0aW9uLlxuICAgKlxuICAgKiBUaGlzIG1ldGhvZCBjYWNoZXMgdGhlIExhbWJkYSBmdW5jdGlvbiB0byBhdm9pZCBjcmVhdGluZyBkdXBsaWNhdGUgcmVzb3VyY2VzLFxuICAgKiBidXQgY3JlYXRlcyBhIG5ldyBMYW1iZGFJbnZva2UgdGFzayBlYWNoIHRpbWUgdG8gYWxsb3cgcHJvcGVyIHN0YXRlIGNoYWluaW5nLlxuICAgKlxuICAgKiBAcmV0dXJucyBMYW1iZGFJbnZva2UgdGFzayBjb25maWd1cmVkIGZvciBkb2N1bWVudCBleHRyYWN0aW9uXG4gICAqL1xuICBwcm90ZWN0ZWQgcHJvY2Vzc2luZ1N0ZXAoKTogRG9jdW1lbnRQcm9jZXNzaW5nU3RlcFR5cGUge1xuICAgIC8vIENyZWF0ZSBMYW1iZGEgZnVuY3Rpb24gb25seSBvbmNlXG4gICAgaWYgKCF0aGlzLl9wcm9jZXNzaW5nRnVuY3Rpb24pIHtcbiAgICAgIGNvbnN0IHByb21wdCA9IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLnByb2Nlc3NpbmdQcm9tcHQgfHwgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZy5ERUZBVUxUX1BST0NFU1NJTkdfUFJPTVBUO1xuICAgICAgY29uc3QgYWRqdXN0ZWRNb2RlbElkID0gQmVkcm9ja01vZGVsVXRpbHMuZGVyaXZlQWN0dWFsTW9kZWxJZCh0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5wcm9jZXNzaW5nQmVkcm9ja01vZGVsKTtcbiAgICAgIGNvbnN0IHJvbGUgPSB0aGlzLmdlbmVyYXRlTGFtYmRhUm9sZUZvckJlZHJvY2soJ1Byb2Nlc3NpbmdMYW1iZGFSb2xlJywgdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMucHJvY2Vzc2luZ0JlZHJvY2tNb2RlbCk7XG4gICAgICBjb25zdCB7IHJlZ2lvbiwgYWNjb3VudCB9ID0gU3RhY2sub2YodGhpcyk7XG5cbiAgICAgIGNvbnN0IGdlbmVyYXRlZExvZ1Blcm1pc3Npb25zID0gTGFtYmRhSWFtVXRpbHMuY3JlYXRlTG9nc1Blcm1pc3Npb25zKHtcbiAgICAgICAgYWNjb3VudCxcbiAgICAgICAgZnVuY3Rpb25OYW1lOiAnYmVkcm9jay1pZHAtcHJvY2Vzc2luZycsXG4gICAgICAgIHJlZ2lvbixcbiAgICAgICAgc2NvcGU6IHRoaXMsXG4gICAgICB9KTtcbiAgICAgIHRoaXMuZW5jcnlwdGlvbktleS5ncmFudEVuY3J5cHREZWNyeXB0KHJvbGUpO1xuICAgICAgdGhpcy5fcHJvY2Vzc2luZ0Z1bmN0aW9uID0gbmV3IFB5dGhvbkZ1bmN0aW9uKHRoaXMsICdCZWRyb2NrRXh0cmFjdGlvbkZ1bmN0aW9uJywge1xuICAgICAgICBmdW5jdGlvbk5hbWU6IGdlbmVyYXRlZExvZ1Blcm1pc3Npb25zLnVuaXF1ZUZ1bmN0aW9uTmFtZSxcbiAgICAgICAgcnVudGltZTogRGVmYXVsdFJ1bnRpbWVzLlBZVEhPTixcbiAgICAgICAgYXJjaGl0ZWN0dXJlOiBBcmNoaXRlY3R1cmUuWDg2XzY0LFxuICAgICAgICBlbnRyeTogcGF0aC5qb2luKF9fZGlybmFtZSwgJ3Jlc291cmNlcy9kZWZhdWx0LWJlZHJvY2staW52b2tlJyksXG4gICAgICAgIHJvbGUsXG4gICAgICAgIG1lbW9yeVNpemU6IDUxMixcbiAgICAgICAgdGltZW91dDogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuc3RlcFRpbWVvdXRzIHx8IER1cmF0aW9uLm1pbnV0ZXMoNSksXG4gICAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgICAgTU9ERUxfSUQ6IGFkanVzdGVkTW9kZWxJZCxcbiAgICAgICAgICBQUk9NUFQ6IHByb21wdCxcbiAgICAgICAgICBJTlZPS0VfVFlQRTogJ3Byb2Nlc3NpbmcnLFxuICAgICAgICAgIC4uLlBvd2VydG9vbHNDb25maWcuZ2VuZXJhdGVEZWZhdWx0TGFtYmRhQ29uZmlnKFxuICAgICAgICAgICAgdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuZW5hYmxlT2JzZXJ2YWJpbGl0eSxcbiAgICAgICAgICAgIHRoaXMubWV0cmljTmFtZXNwYWNlLFxuICAgICAgICAgICAgdGhpcy5tZXRyaWNTZXJ2aWNlTmFtZSxcbiAgICAgICAgICApLFxuICAgICAgICB9LFxuICAgICAgICBlbnZpcm9ubWVudEVuY3J5cHRpb246IHRoaXMuZW5jcnlwdGlvbktleSxcbiAgICAgICAgdnBjOiB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrXG4gICAgICAgICAgPyB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrLnZwY1xuICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgICB2cGNTdWJuZXRzOiB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrXG4gICAgICAgICAgPyB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrLmFwcGxpY2F0aW9uU3VibmV0U2VsZWN0aW9uKClcbiAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgIH0pO1xuXG4gICAgICBmb3IgKGNvbnN0IHN0YXRlbWVudCBvZiBnZW5lcmF0ZWRMb2dQZXJtaXNzaW9ucy5wb2xpY3lTdGF0ZW1lbnRzKSB7XG4gICAgICAgIHRoaXMuX3Byb2Nlc3NpbmdGdW5jdGlvbi5yb2xlPy5hZGRUb1ByaW5jaXBhbFBvbGljeShzdGF0ZW1lbnQpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29yaykge1xuICAgICAgICB0aGlzLl9wcm9jZXNzaW5nRnVuY3Rpb24ucm9sZT8uYWRkVG9QcmluY2lwYWxQb2xpY3koTGFtYmRhSWFtVXRpbHMuZ2VuZXJhdGVMYW1iZGFWUENQZXJtaXNzaW9ucygpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBbHdheXMgY3JlYXRlIGEgbmV3IExhbWJkYUludm9rZSB0YXNrIHRvIGFsbG93IHByb3BlciBzdGF0ZSBjaGFpbmluZ1xuICAgIGNvbnN0IHN0ZXBJZCA9IGBQcm9jZXNzaW5nU3RlcC0ke3RoaXMuX3Byb2Nlc3NpbmdTdGVwQ291bnRlcn1gO1xuICAgIHRoaXMuX3Byb2Nlc3NpbmdTdGVwQ291bnRlcisrO1xuXG4gICAgcmV0dXJuIG5ldyBMYW1iZGFJbnZva2UodGhpcywgc3RlcElkLCB7XG4gICAgICBsYW1iZGFGdW5jdGlvbjogdGhpcy5fcHJvY2Vzc2luZ0Z1bmN0aW9uLFxuICAgICAgcmVzdWx0UGF0aDogJyQucHJvY2Vzc2luZ1Jlc3VsdCcsXG4gICAgICByZXN1bHRTZWxlY3Rvcjoge1xuICAgICAgICAnZG9jdW1lbnRDbGFzc2lmaWNhdGlvbi4kJzogJyQuUGF5bG9hZC5kb2N1bWVudENsYXNzaWZpY2F0aW9uJyxcbiAgICAgICAgJ3Jlc3VsdC4kJzogJyQuUGF5bG9hZC5yZXN1bHQnLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZW5lcmF0ZUxhbWJkYVJvbGVGb3JCZWRyb2NrKGlkOiBzdHJpbmcsIG1vZGVsPzogQmVkcm9ja01vZGVsUHJvcHMpIHtcbiAgICByZXR1cm4gbmV3IFJvbGUodGhpcywgaWQsIHtcbiAgICAgIGFzc3VtZWRCeTogbmV3IFNlcnZpY2VQcmluY2lwYWwoJ2xhbWJkYS5hbWF6b25hd3MuY29tJyksXG4gICAgICBpbmxpbmVQb2xpY2llczoge1xuICAgICAgICBCZWRyb2NrSW52b2tlUG9saWN5OiBuZXcgUG9saWN5RG9jdW1lbnQoe1xuICAgICAgICAgIHN0YXRlbWVudHM6IFtcbiAgICAgICAgICAgIC8vIFMzIHJlYWQtb25seSBhY2Nlc3MgZm9yIGRvY3VtZW50IHJldHJpZXZhbCAtIGxlYXN0IHByaXZpbGVnZVxuICAgICAgICAgICAgLi4udGhpcy5pbmdyZXNzQWRhcHRlci5nZW5lcmF0ZUFkYXB0ZXJJQU1Qb2xpY2llcygpLFxuICAgICAgICAgICAgQmVkcm9ja01vZGVsVXRpbHMuZ2VuZXJhdGVNb2RlbElBTVBlcm1pc3Npb25zKHRoaXMsIG1vZGVsKSxcbiAgICAgICAgICBdLFxuICAgICAgICB9KSxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogSW1wbGVtZW50cyB0aGUgb3B0aW9uYWwgZG9jdW1lbnQgZW5yaWNobWVudCBzdGVwLlxuICAgKlxuICAgKiBJZiBhbiBlbnJpY2htZW50IExhbWJkYSBmdW5jdGlvbiBpcyBwcm92aWRlZCBpbiB0aGUgcHJvcHMsIGNyZWF0ZXMgYSBMYW1iZGFJbnZva2VcbiAgICogdGFzayB0byBwZXJmb3JtIGFkZGl0aW9uYWwgcHJvY2Vzc2luZyBvbiB0aGUgZXh0cmFjdGVkIGRhdGEuIFRoaXMgc3RlcCBpcyB1c2VmdWxcbiAgICogZm9yIGRhdGEgdmFsaWRhdGlvbiwgdHJhbnNmb3JtYXRpb24sIG9yIGludGVncmF0aW9uIHdpdGggZXh0ZXJuYWwgc3lzdGVtcy5cbiAgICpcbiAgICogQHJldHVybnMgTGFtYmRhSW52b2tlIHRhc2sgZm9yIGVucmljaG1lbnQsIG9yIHVuZGVmaW5lZCB0byBza2lwIHRoaXMgc3RlcFxuICAgKi9cbiAgcHJvdGVjdGVkIGVucmljaG1lbnRTdGVwKCk6IERvY3VtZW50UHJvY2Vzc2luZ1N0ZXBUeXBlIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIXRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLmVucmljaG1lbnRMYW1iZGFGdW5jdGlvbikge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBjb25zdCBzdGVwSWQgPSBgRW5yaWNobWVudFN0ZXAtJHt0aGlzLl9lbnJpY2htZW50U3RlcENvdW50ZXJ9YDtcbiAgICB0aGlzLl9lbnJpY2htZW50U3RlcENvdW50ZXIrKztcblxuICAgIHJldHVybiBuZXcgTGFtYmRhSW52b2tlKHRoaXMsIHN0ZXBJZCwge1xuICAgICAgbGFtYmRhRnVuY3Rpb246IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLmVucmljaG1lbnRMYW1iZGFGdW5jdGlvbixcbiAgICAgIHJlc3VsdFBhdGg6ICckLmVucmljaGVkUmVzdWx0JyxcbiAgICAgIG91dHB1dFBhdGg6ICckJyxcbiAgICAgIHBheWxvYWRSZXNwb25zZU9ubHk6IHRydWUsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogSW1wbGVtZW50cyB0aGUgb3B0aW9uYWwgcG9zdC1wcm9jZXNzaW5nIHN0ZXAuXG4gICAqXG4gICAqIElmIGEgcG9zdC1wcm9jZXNzaW5nIExhbWJkYSBmdW5jdGlvbiBpcyBwcm92aWRlZCBpbiB0aGUgcHJvcHMsIGNyZWF0ZXMgYSBMYW1iZGFJbnZva2VcbiAgICogdGFzayB0byBwZXJmb3JtIGZpbmFsIHByb2Nlc3Npbmcgb24gdGhlIHdvcmtmbG93IHJlc3VsdHMuIFRoaXMgc3RlcCBpcyB1c2VmdWwgZm9yXG4gICAqIGRhdGEgZm9ybWF0dGluZywgbm90aWZpY2F0aW9ucywgb3IgaW50ZWdyYXRpb24gd2l0aCBkb3duc3RyZWFtIHN5c3RlbXMuXG4gICAqXG4gICAqIEByZXR1cm5zIExhbWJkYUludm9rZSB0YXNrIGZvciBwb3N0LXByb2Nlc3NpbmcsIG9yIHVuZGVmaW5lZCB0byBza2lwIHRoaXMgc3RlcFxuICAgKi9cbiAgcHJvdGVjdGVkIHBvc3RQcm9jZXNzaW5nU3RlcCgpOiBEb2N1bWVudFByb2Nlc3NpbmdTdGVwVHlwZSB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCF0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5wb3N0UHJvY2Vzc2luZ0xhbWJkYUZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGNvbnN0IHN0ZXBJZCA9IGBQb3N0UHJvY2Vzc2luZ1N0ZXAtJHt0aGlzLl9wb3N0UHJvY2Vzc2luZ1N0ZXBDb3VudGVyfWA7XG4gICAgdGhpcy5fcG9zdFByb2Nlc3NpbmdTdGVwQ291bnRlcisrO1xuXG4gICAgcmV0dXJuIG5ldyBMYW1iZGFJbnZva2UodGhpcywgc3RlcElkLCB7XG4gICAgICBsYW1iZGFGdW5jdGlvbjogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMucG9zdFByb2Nlc3NpbmdMYW1iZGFGdW5jdGlvbixcbiAgICAgIHJlc3VsdFBhdGg6ICckLnBvc3RQcm9jZXNzZWRSZXN1bHQnLFxuICAgICAgb3V0cHV0UGF0aDogJyQnLFxuICAgICAgcGF5bG9hZFJlc3BvbnNlT25seTogdHJ1ZSxcbiAgICB9KTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIEltcGxlbWVudHMgdGhlIG9wdGlvbmFsIHByZXByb2Nlc3Npbmcgc3RlcCBmb3IgUERGIGNodW5raW5nLlxuICAgKlxuICAgKiBXaGVuIGNodW5raW5nIGlzIGVuYWJsZWQsIGNyZWF0ZXMgYSBMYW1iZGEgZnVuY3Rpb24gdGhhdCBhbmFseXplcyBQREZzIGFuZFxuICAgKiBzcGxpdHMgbGFyZ2UgZG9jdW1lbnRzIGludG8gbWFuYWdlYWJsZSBjaHVua3MuIFRoZSBmdW5jdGlvbjpcbiAgICogMS4gQW5hbHl6ZXMgdGhlIFBERiB0byBkZXRlcm1pbmUgcGFnZSBjb3VudCBhbmQgdG9rZW4gZXN0aW1hdGVzXG4gICAqIDIuIERlY2lkZXMgaWYgY2h1bmtpbmcgaXMgbmVlZGVkIGJhc2VkIG9uIGNvbmZpZ3VyZWQgdGhyZXNob2xkc1xuICAgKiAzLiBJZiBjaHVua2luZyBpcyBuZWVkZWQsIHNwbGl0cyB0aGUgUERGIGFuZCB1cGxvYWRzIGNodW5rcyB0byBTM1xuICAgKlxuICAgKiBAcmV0dXJucyBMYW1iZGFJbnZva2UgdGFzayBmb3IgUERGIGFuYWx5c2lzIGFuZCBjaHVua2luZywgb3IgdW5kZWZpbmVkIGlmIGNodW5raW5nIGlzIGRpc2FibGVkXG4gICAqL1xuICBwcm90ZWN0ZWQgcHJlcHJvY2Vzc2luZ1N0ZXAoKTogRG9jdW1lbnRQcm9jZXNzaW5nU3RlcFR5cGUgfCB1bmRlZmluZWQge1xuICAgIC8vIE9ubHkgZW5hYmxlIGNodW5raW5nIGlmIGV4cGxpY2l0bHkgY29uZmlndXJlZFxuICAgIGlmICghdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuZW5hYmxlQ2h1bmtpbmcpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgeyByZWdpb24sIGFjY291bnQgfSA9IFN0YWNrLm9mKHRoaXMpO1xuICAgIGNvbnN0IGNodW5raW5nQ29uZmlnID0gdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuY2h1bmtpbmdDb25maWcgfHwge307XG5cbiAgICAvLyBDcmVhdGUgSUFNIHJvbGUgZm9yIGNodW5raW5nIExhbWJkYSB3aXRoIGxlYXN0IHByaXZpbGVnZSBwZXJtaXNzaW9uc1xuICAgIC8vIENodW5raW5nIExhbWJkYSBuZWVkczogR2V0T2JqZWN0IChyZWFkIHJhdyBQREZzKSwgUHV0T2JqZWN0ICh3cml0ZSBjaHVua3MpXG4gICAgY29uc3Qgcm9sZSA9IG5ldyBSb2xlKHRoaXMsICdDaHVua2luZ0xhbWJkYVJvbGUnLCB7XG4gICAgICBhc3N1bWVkQnk6IG5ldyBTZXJ2aWNlUHJpbmNpcGFsKCdsYW1iZGEuYW1hem9uYXdzLmNvbScpLFxuICAgICAgaW5saW5lUG9saWNpZXM6IHtcbiAgICAgICAgQ2h1bmtpbmdQb2xpY3k6IG5ldyBQb2xpY3lEb2N1bWVudCh7XG4gICAgICAgICAgc3RhdGVtZW50czogW1xuICAgICAgICAgICAgLi4udGhpcy5pbmdyZXNzQWRhcHRlci5nZW5lcmF0ZUFkYXB0ZXJJQU1Qb2xpY2llcygpLFxuICAgICAgICAgIF0sXG4gICAgICAgIH0pLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGdlbmVyYXRlZExvZ1Blcm1pc3Npb25zID0gTGFtYmRhSWFtVXRpbHMuY3JlYXRlTG9nc1Blcm1pc3Npb25zKHtcbiAgICAgIGFjY291bnQsXG4gICAgICBmdW5jdGlvbk5hbWU6ICdiZWRyb2NrLWlkcC1jaHVua2luZycsXG4gICAgICByZWdpb24sXG4gICAgICBzY29wZTogdGhpcyxcbiAgICAgIGVuYWJsZU9ic2VydmFiaWxpdHk6IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLmVuYWJsZU9ic2VydmFiaWxpdHksXG4gICAgfSk7XG5cbiAgICB0aGlzLmVuY3J5cHRpb25LZXkuZ3JhbnRFbmNyeXB0RGVjcnlwdChyb2xlKTtcblxuICAgIC8vIENyZWF0ZSBQREYgQW5hbHlzaXMgJiBDaHVua2luZyBMYW1iZGFcbiAgICBjb25zdCBjaHVua2luZ0xhbWJkYSA9IG5ldyBQeXRob25GdW5jdGlvbih0aGlzLCAnUERGQ2h1bmtpbmdGdW5jdGlvbicsIHtcbiAgICAgIGZ1bmN0aW9uTmFtZTogZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMudW5pcXVlRnVuY3Rpb25OYW1lLFxuICAgICAgZW50cnk6IHBhdGguam9pbihfX2Rpcm5hbWUsICdyZXNvdXJjZXMvcGRmLWNodW5raW5nJyksXG4gICAgICBpbmRleDogJ2hhbmRsZXIucHknLFxuICAgICAgaGFuZGxlcjogJ2hhbmRsZXInLFxuICAgICAgcnVudGltZTogRGVmYXVsdFJ1bnRpbWVzLlBZVEhPTixcbiAgICAgIGFyY2hpdGVjdHVyZTogQXJjaGl0ZWN0dXJlLlg4Nl82NCxcbiAgICAgIHJvbGUsXG4gICAgICBtZW1vcnlTaXplOiAyMDQ4LFxuICAgICAgdGltZW91dDogRHVyYXRpb24ubWludXRlcygxMCksXG4gICAgICBlbnZpcm9ubWVudDoge1xuICAgICAgICBDSFVOS0lOR19TVFJBVEVHWTogY2h1bmtpbmdDb25maWcuc3RyYXRlZ3kgfHwgJ2h5YnJpZCcsXG4gICAgICAgIFBBR0VfVEhSRVNIT0xEOiBTdHJpbmcoY2h1bmtpbmdDb25maWcucGFnZVRocmVzaG9sZCB8fCAxMDApLFxuICAgICAgICBUT0tFTl9USFJFU0hPTEQ6IFN0cmluZyhjaHVua2luZ0NvbmZpZy50b2tlblRocmVzaG9sZCB8fCAxNTAwMDApLFxuICAgICAgICBDSFVOS19TSVpFOiBTdHJpbmcoY2h1bmtpbmdDb25maWcuY2h1bmtTaXplIHx8IDUwKSxcbiAgICAgICAgT1ZFUkxBUF9QQUdFUzogU3RyaW5nKGNodW5raW5nQ29uZmlnLm92ZXJsYXBQYWdlcyB8fCA1KSxcbiAgICAgICAgTUFYX1RPS0VOU19QRVJfQ0hVTks6IFN0cmluZyhjaHVua2luZ0NvbmZpZy5tYXhUb2tlbnNQZXJDaHVuayB8fCAxMDAwMDApLFxuICAgICAgICBPVkVSTEFQX1RPS0VOUzogU3RyaW5nKGNodW5raW5nQ29uZmlnLm92ZXJsYXBUb2tlbnMgfHwgNTAwMCksXG4gICAgICAgIFRBUkdFVF9UT0tFTlNfUEVSX0NIVU5LOiBTdHJpbmcoY2h1bmtpbmdDb25maWcudGFyZ2V0VG9rZW5zUGVyQ2h1bmsgfHwgODAwMDApLFxuICAgICAgICBNQVhfUEFHRVNfUEVSX0NIVU5LOiBTdHJpbmcoY2h1bmtpbmdDb25maWcubWF4UGFnZXNQZXJDaHVuayB8fCA5OSksXG4gICAgICAgIC4uLlBvd2VydG9vbHNDb25maWcuZ2VuZXJhdGVEZWZhdWx0TGFtYmRhQ29uZmlnKFxuICAgICAgICAgIHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLmVuYWJsZU9ic2VydmFiaWxpdHksXG4gICAgICAgICAgdGhpcy5tZXRyaWNOYW1lc3BhY2UsXG4gICAgICAgICAgdGhpcy5tZXRyaWNTZXJ2aWNlTmFtZSxcbiAgICAgICAgKSxcbiAgICAgIH0sXG4gICAgICBlbnZpcm9ubWVudEVuY3J5cHRpb246IHRoaXMuZW5jcnlwdGlvbktleSxcbiAgICAgIHZwYzogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29ya1xuICAgICAgICA/IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLm5ldHdvcmsudnBjXG4gICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgdnBjU3VibmV0czogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29ya1xuICAgICAgICA/IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLm5ldHdvcmsuYXBwbGljYXRpb25TdWJuZXRTZWxlY3Rpb24oKVxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICB9KTtcblxuICAgIGZvciAoY29uc3Qgc3RhdGVtZW50IG9mIGdlbmVyYXRlZExvZ1Blcm1pc3Npb25zLnBvbGljeVN0YXRlbWVudHMpIHtcbiAgICAgIGNodW5raW5nTGFtYmRhLnJvbGU/LmFkZFRvUHJpbmNpcGFsUG9saWN5KHN0YXRlbWVudCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLm5ldHdvcmspIHtcbiAgICAgIGNodW5raW5nTGFtYmRhLnJvbGU/LmFkZFRvUHJpbmNpcGFsUG9saWN5KExhbWJkYUlhbVV0aWxzLmdlbmVyYXRlTGFtYmRhVlBDUGVybWlzc2lvbnMoKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBMYW1iZGFJbnZva2UodGhpcywgJ1BERkFuYWx5c2lzQW5kQ2h1bmtpbmcnLCB7XG4gICAgICBsYW1iZGFGdW5jdGlvbjogY2h1bmtpbmdMYW1iZGEsXG4gICAgICByZXN1bHRQYXRoOiAnJC5jaHVua2luZ1Jlc3VsdCcsXG4gICAgICByZXN1bHRTZWxlY3Rvcjoge1xuICAgICAgICAncmVxdWlyZXNDaHVua2luZy4kJzogJyQuUGF5bG9hZC5yZXF1aXJlc0NodW5raW5nJyxcbiAgICAgICAgJ3Rva2VuQW5hbHlzaXMuJCc6ICckLlBheWxvYWQudG9rZW5BbmFseXNpcycsXG4gICAgICAgICdzdHJhdGVneS4kJzogJyQuUGF5bG9hZC5zdHJhdGVneScsXG4gICAgICAgICdjaHVua3MuJCc6ICckLlBheWxvYWQuY2h1bmtzJyxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUHJvdmlkZXMgYWRkaXRpb25hbCBtZXRhZGF0YSBmaWVsZHMgZm9yIGNodW5raW5nIHRvIGJlIHN0b3JlZCBpbiBEeW5hbW9EQi5cbiAgICpcbiAgICogV2hlbiBjaHVua2luZyBpcyBlbmFibGVkLCBhZGRzIGZpZWxkcyBmb3I6XG4gICAqIC0gQ2h1bmtpbmdFbmFibGVkOiBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYm9vbGVhbiBmbGFnXG4gICAqIC0gQ2h1bmtpbmdTdHJhdGVneTogc3RyYXRlZ3kgdXNlZCAoZml4ZWQtcGFnZXMsIHRva2VuLWJhc2VkLCBoeWJyaWQpXG4gICAqIC0gVG9rZW5BbmFseXNpczogSlNPTiBzdHJpbmcgd2l0aCB0b2tlbiBhbmFseXNpcyByZXN1bHRzXG4gICAqIC0gQ2h1bmtNZXRhZGF0YTogSlNPTiBzdHJpbmcgYXJyYXkgd2l0aCBjaHVuayBpbmZvcm1hdGlvblxuICAgKlxuICAgKiBAcmV0dXJucyBSZWNvcmQgb2YgRHluYW1vREIgYXR0cmlidXRlIHZhbHVlcyBmb3IgY2h1bmtpbmcgbWV0YWRhdGFcbiAgICovXG4gIHByb3RlY3RlZCBwcmVwcm9jZXNzaW5nTWV0YWRhdGEoKTogUmVjb3JkPHN0cmluZywgRHluYW1vQXR0cmlidXRlVmFsdWU+IHtcbiAgICBpZiAoIXRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLmVuYWJsZUNodW5raW5nKSB7XG4gICAgICByZXR1cm4ge307XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIENodW5raW5nRW5hYmxlZDogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZyhcbiAgICAgICAgSnNvblBhdGguc3RyaW5nQXQoJ1N0YXRlcy5Gb3JtYXQoXFwne31cXCcsICQuY2h1bmtpbmdSZXN1bHQucmVxdWlyZXNDaHVua2luZyknKSxcbiAgICAgICksXG4gICAgICBDaHVua2luZ1N0cmF0ZWd5OiBEeW5hbW9BdHRyaWJ1dGVWYWx1ZS5mcm9tU3RyaW5nKFxuICAgICAgICBKc29uUGF0aC5zdHJpbmdBdCgnJC5jaHVua2luZ1Jlc3VsdC5zdHJhdGVneScpLFxuICAgICAgKSxcbiAgICAgIFRva2VuQW5hbHlzaXM6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoXG4gICAgICAgIEpzb25QYXRoLmpzb25Ub1N0cmluZyhKc29uUGF0aC5vYmplY3RBdCgnJC5jaHVua2luZ1Jlc3VsdC50b2tlbkFuYWx5c2lzJykpLFxuICAgICAgKSxcbiAgICAgIENodW5rTWV0YWRhdGE6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoXG4gICAgICAgIEpzb25QYXRoLmpzb25Ub1N0cmluZyhKc29uUGF0aC5vYmplY3RBdCgnJC5jaHVua2luZ1Jlc3VsdC5jaHVua3MnKSksXG4gICAgICApLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyB0aGUgcHJvY2Vzc2luZyB3b3JrZmxvdyB3aXRoIGNvbmRpdGlvbmFsIGJyYW5jaGluZyBmb3IgY2h1bmtlZCBkb2N1bWVudHMuXG4gICAqXG4gICAqIFdoZW4gY2h1bmtpbmcgaXMgZW5hYmxlZCwgY3JlYXRlcyBhIENob2ljZSBTdGF0ZSB0aGF0OlxuICAgKiAtIFJvdXRlcyB0byBjaHVua2VkIHByb2Nlc3NpbmcgZmxvdyBpZiBkb2N1bWVudCB3YXMgY2h1bmtlZFxuICAgKiAtIFJvdXRlcyB0byBzdGFuZGFyZCBwcm9jZXNzaW5nIGZsb3cgaWYgZG9jdW1lbnQgd2FzIG5vdCBjaHVua2VkXG4gICAqXG4gICAqIFdoZW4gY2h1bmtpbmcgaXMgZGlzYWJsZWQsIHJldHVybnMgdGhlIHN0YW5kYXJkIHByb2Nlc3Npbmcgd29ya2Zsb3cuXG4gICAqXG4gICAqIEByZXR1cm5zIFN0ZXAgRnVuY3Rpb25zIGNoYWluIGZvciBwcm9jZXNzaW5nIHRoZSBkb2N1bWVudFxuICAgKi9cbiAgcHJvdGVjdGVkIGNyZWF0ZVByb2Nlc3NpbmdXb3JrZmxvdygpOiBJQ2hhaW5hYmxlIHtcbiAgICAvLyBJZiBjaHVua2luZyBpcyBub3QgZW5hYmxlZCwgdXNlIHN0YW5kYXJkIHdvcmtmbG93XG4gICAgaWYgKCF0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5lbmFibGVDaHVua2luZykge1xuICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlU3RhbmRhcmRQcm9jZXNzaW5nV29ya2Zsb3coKTtcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgQ2hvaWNlIFN0YXRlIHRvIGNoZWNrIGlmIGNodW5raW5nIHdhcyBhcHBsaWVkXG4gICAgY29uc3QgY2hvaWNlU3RhdGUgPSBuZXcgQ2hvaWNlKHRoaXMsICdDaGVja0lmQ2h1bmtlZCcpO1xuXG4gICAgY2hvaWNlU3RhdGVcbiAgICAgIC53aGVuKFxuICAgICAgICBDb25kaXRpb24uYm9vbGVhbkVxdWFscygnJC5jaHVua2luZ1Jlc3VsdC5yZXF1aXJlc0NodW5raW5nJywgdHJ1ZSksXG4gICAgICAgIHRoaXMuY3JlYXRlQ2h1bmtlZFByb2Nlc3NpbmdGbG93KCksXG4gICAgICApXG4gICAgICAub3RoZXJ3aXNlKFxuICAgICAgICAvLyBQYXNzICdTdGFuZGFyZCcgcHJlZml4IHRvIGF2b2lkIGNvbnN0cnVjdCBJRCBjb2xsaXNpb25zIHdpdGggY2h1bmtlZCBmbG93XG4gICAgICAgIHRoaXMuY3JlYXRlU3RhbmRhcmRQcm9jZXNzaW5nV29ya2Zsb3coJ1N0YW5kYXJkJyksXG4gICAgICApO1xuXG4gICAgcmV0dXJuIGNob2ljZVN0YXRlO1xuICB9XG5cblxuICAvKipcbiAgICogQ3JlYXRlcyB0aGUgY2h1bmtlZCBwcm9jZXNzaW5nIGZsb3cgZm9yIGxhcmdlIGRvY3VtZW50cy5cbiAgICpcbiAgICogVGhpcyBmbG93OlxuICAgKiAxLiBVc2VzIGEgTWFwIFN0YXRlIHRvIHByb2Nlc3MgZWFjaCBjaHVuayBpbiBwYXJhbGxlbCAob3Igc2VxdWVudGlhbGx5KVxuICAgKiAyLiBFYWNoIGNodW5rIGdvZXMgdGhyb3VnaCBjbGFzc2lmaWNhdGlvbiBhbmQgcHJvY2Vzc2luZ1xuICAgKiAzLiBSZXN1bHRzIGFyZSBhZ2dyZWdhdGVkIHVzaW5nIHRoZSBhZ2dyZWdhdGlvbiBMYW1iZGFcbiAgICogNC4gRHluYW1vREIgaXMgdXBkYXRlZCB3aXRoIHRoZSBhZ2dyZWdhdGVkIHJlc3VsdFxuICAgKiA1LiBUZW1wb3JhcnkgY2h1bmtzIGFyZSBjbGVhbmVkIHVwIGZyb20gUzNcbiAgICpcbiAgICogQHJldHVybnMgU3RlcCBGdW5jdGlvbnMgY2hhaW4gZm9yIGNodW5rZWQgZG9jdW1lbnQgcHJvY2Vzc2luZ1xuICAgKi9cbiAgcHJpdmF0ZSBjcmVhdGVDaHVua2VkUHJvY2Vzc2luZ0Zsb3coKTogSUNoYWluYWJsZSB7XG4gICAgY29uc3QgY2h1bmtpbmdDb25maWcgPSB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5jaHVua2luZ0NvbmZpZyB8fCB7fTtcbiAgICBjb25zdCBtYXhDb25jdXJyZW5jeSA9IGNodW5raW5nQ29uZmlnLnByb2Nlc3NpbmdNb2RlID09PSAnc2VxdWVudGlhbCdcbiAgICAgID8gMVxuICAgICAgOiAoY2h1bmtpbmdDb25maWcubWF4Q29uY3VycmVuY3kgfHwgMTApO1xuXG4gICAgLy8gQ3JlYXRlIE1hcCBTdGF0ZSBmb3IgcHJvY2Vzc2luZyBjaHVua3NcbiAgICBjb25zdCBtYXBTdGF0ZSA9IG5ldyBNYXAodGhpcywgJ1Byb2Nlc3NDaHVua3MnLCB7XG4gICAgICBpdGVtc1BhdGg6ICckLmNodW5raW5nUmVzdWx0LmNodW5rcycsXG4gICAgICBtYXhDb25jdXJyZW5jeSxcbiAgICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgICAgJ2RvY3VtZW50SWQuJCc6ICckLmRvY3VtZW50SWQnLFxuICAgICAgICAnY2h1bmsuJCc6ICckJC5NYXAuSXRlbS5WYWx1ZScsXG4gICAgICAgICdjaHVua0luZGV4LiQnOiAnJCQuTWFwLkl0ZW0uSW5kZXgnLFxuICAgICAgICAndG90YWxDaHVua3MuJCc6ICdTdGF0ZXMuQXJyYXlMZW5ndGgoJC5jaHVua2luZ1Jlc3VsdC5jaHVua3MpJyxcbiAgICAgICAgLy8gT3ZlcnJpZGUgY29udGVudCB0byBwb2ludCB0byB0aGUgY2h1bmsgUERGLCBub3QgdGhlIG9yaWdpbmFsIGRvY3VtZW50XG4gICAgICAgICdjb250ZW50Jzoge1xuICAgICAgICAgICdsb2NhdGlvbic6ICdzMycsXG4gICAgICAgICAgJ2J1Y2tldC4kJzogJyQkLk1hcC5JdGVtLlZhbHVlLmJ1Y2tldCcsXG4gICAgICAgICAgJ2tleS4kJzogJyQkLk1hcC5JdGVtLlZhbHVlLmtleScsXG4gICAgICAgICAgJ2ZpbGVuYW1lLiQnOiAnJC5jb250ZW50LmZpbGVuYW1lJyxcbiAgICAgICAgfSxcbiAgICAgICAgJ2NvbnRlbnRUeXBlLiQnOiAnJC5jb250ZW50VHlwZScsXG4gICAgICB9LFxuICAgICAgcmVzdWx0UGF0aDogJyQuY2h1bmtSZXN1bHRzJyxcbiAgICB9KTtcblxuICAgIC8vIERlZmluZSBwZXItY2h1bmsgcHJvY2Vzc2luZzogY2xhc3NpZmljYXRpb24g4oaSIHByb2Nlc3NpbmdcbiAgICBjb25zdCBjaHVua0NsYXNzaWZpY2F0aW9uID0gdGhpcy5jbGFzc2lmaWNhdGlvblN0ZXAoKTtcbiAgICBjb25zdCBjaHVua1Byb2Nlc3NpbmcgPSB0aGlzLnByb2Nlc3NpbmdTdGVwKCk7XG5cbiAgICBtYXBTdGF0ZS5pdGVtUHJvY2Vzc29yKFxuICAgICAgY2h1bmtDbGFzc2lmaWNhdGlvbi5uZXh0KGNodW5rUHJvY2Vzc2luZyksXG4gICAgKTtcblxuICAgIC8vIENyZWF0ZSBhZ2dyZWdhdGlvbiBzdGVwIChMYW1iZGEgaW52b2tlIG9ubHksIG5vcm1hbGl6YXRpb24gYWRkZWQgc2VwYXJhdGVseSlcbiAgICBjb25zdCBhZ2dyZWdhdGlvbkxhbWJkYVN0ZXAgPSB0aGlzLmNyZWF0ZUFnZ3JlZ2F0aW9uU3RlcCgpO1xuXG4gICAgLy8gQWRkIGEgUGFzcyBzdGF0ZSB0byBub3JtYWxpemUgdGhlIGFnZ3JlZ2F0ZWQgcmVzdWx0IGZvciBkb3duc3RyZWFtIGNvbXBhdGliaWxpdHlcbiAgICAvLyBUaGlzIGNvcGllcyBhZ2dyZWdhdGVkUmVzdWx0IHRvIHByb2Nlc3NpbmdSZXN1bHQgc28gZW5yaWNobWVudC9wb3N0LXByb2Nlc3NpbmdcbiAgICAvLyBzZWUgYSBjb25zaXN0ZW50IHN0cnVjdHVyZSByZWdhcmRsZXNzIG9mIHdoZXRoZXIgY2h1bmtpbmcgd2FzIHVzZWRcbiAgICBjb25zdCBub3JtYWxpemVTdGF0ZSA9IG5ldyBQYXNzKHRoaXMsICdOb3JtYWxpemVBZ2dyZWdhdGVkUmVzdWx0Jywge1xuICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICAnZG9jdW1lbnRJZC4kJzogJyQuZG9jdW1lbnRJZCcsXG4gICAgICAgICdjb250ZW50VHlwZS4kJzogJyQuY29udGVudFR5cGUnLFxuICAgICAgICAnY29udGVudC4kJzogJyQuY29udGVudCcsXG4gICAgICAgICdjaHVua2luZ1Jlc3VsdC4kJzogJyQuY2h1bmtpbmdSZXN1bHQnLFxuICAgICAgICAnY2h1bmtSZXN1bHRzLiQnOiAnJC5jaHVua1Jlc3VsdHMnLFxuICAgICAgICAnYWdncmVnYXRlZFJlc3VsdC4kJzogJyQuYWdncmVnYXRlZFJlc3VsdCcsXG4gICAgICAgIC8vIENvcHkgYWdncmVnYXRlZCByZXN1bHQgdG8gcHJvY2Vzc2luZ1Jlc3VsdCBmb3IgZG93bnN0cmVhbSBjb21wYXRpYmlsaXR5XG4gICAgICAgICdwcm9jZXNzaW5nUmVzdWx0Jzoge1xuICAgICAgICAgICdyZXN1bHQuJCc6ICckLmFnZ3JlZ2F0ZWRSZXN1bHQucmVzdWx0JyxcbiAgICAgICAgfSxcbiAgICAgICAgLy8gQWxzbyBzZXQgY2xhc3NpZmljYXRpb25SZXN1bHQgZnJvbSB0aGUgZmlyc3Qgc3VjY2Vzc2Z1bCBjaHVuayBmb3IgY29uc2lzdGVuY3lcbiAgICAgICAgJ2NsYXNzaWZpY2F0aW9uUmVzdWx0LiQnOiAnJC5jaHVua1Jlc3VsdHNbMF0uY2xhc3NpZmljYXRpb25SZXN1bHQnLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vIENyZWF0ZSBEeW5hbW9EQiB1cGRhdGUgc3RlcCBmb3IgYWdncmVnYXRlZCByZXN1bHRcbiAgICBjb25zdCB1cGRhdGVBZ2dyZWdhdGVkUmVzdWx0U3RlcCA9IHRoaXMuY3JlYXRlVXBkYXRlQWdncmVnYXRlZFJlc3VsdFN0ZXAoKTtcblxuICAgIC8vIENyZWF0ZSBjbGVhbnVwIHN0ZXBcbiAgICBjb25zdCBjbGVhbnVwU3RlcCA9IHRoaXMuY3JlYXRlQ2xlYW51cFN0ZXAoKTtcblxuICAgIC8vIENyZWF0ZSBtb3ZlIHRvIHByb2Nlc3NlZCBjaGFpbiB3aXRoICdDaHVua2VkJyBwcmVmaXggdG8gYXZvaWQgSUQgY29sbGlzaW9uc1xuICAgIGNvbnN0IG1vdmVUb1Byb2Nlc3NlZCA9IHRoaXMuaW5ncmVzc0FkYXB0ZXIuY3JlYXRlU3VjY2Vzc0NoYWluKHRoaXMsICdDaHVua2VkJyk7XG5cbiAgICAvLyBDcmVhdGUgZXJyb3IgaGFuZGxlciBmb3IgYWdncmVnYXRpb24gZmFpbHVyZXNcbiAgICBjb25zdCBhZ2dyZWdhdGlvbkVycm9ySGFuZGxlciA9IHRoaXMuY3JlYXRlQWdncmVnYXRpb25FcnJvckhhbmRsZXIoKTtcblxuICAgIC8vIEdldCBvcHRpb25hbCBlbnJpY2htZW50IGFuZCBwb3N0LXByb2Nlc3Npbmcgc3RlcHNcbiAgICBjb25zdCBlbnJpY2htZW50U3RlcCA9IHRoaXMuZW5yaWNobWVudFN0ZXAoKTtcbiAgICBjb25zdCBwb3N0UHJvY2Vzc2luZ1N0ZXAgPSB0aGlzLnBvc3RQcm9jZXNzaW5nU3RlcCgpO1xuXG4gICAgLy8gQnVpbGQgdGhlIGZpbmFsIGNoYWluIGFmdGVyIGFnZ3JlZ2F0aW9uXG4gICAgLy8gQ2hhaW46IE1hcCBTdGF0ZSDihpIgQWdncmVnYXRpb24g4oaSIER5bmFtb0RCIFVwZGF0ZSDihpIgW0VucmljaG1lbnRdIOKGkiBbUG9zdFByb2Nlc3NpbmddIOKGkiBDbGVhbnVwIOKGkiBNb3ZlIHRvIFByb2Nlc3NlZFxuICAgIGxldCBmaW5hbENoYWluOiBJQ2hhaW5hYmxlID0gY2xlYW51cFN0ZXBcbiAgICAgIC5hZGRSZXRyeSh7XG4gICAgICAgIGVycm9yczogWydMYW1iZGEuU2VydmljZUV4Y2VwdGlvbicsICdMYW1iZGEuVG9vTWFueVJlcXVlc3RzRXhjZXB0aW9uJ10sXG4gICAgICAgIGludGVydmFsOiBEdXJhdGlvbi5zZWNvbmRzKDIpLFxuICAgICAgICBtYXhBdHRlbXB0czogMyxcbiAgICAgICAgYmFja29mZlJhdGU6IDIsXG4gICAgICB9KVxuICAgICAgLm5leHQobW92ZVRvUHJvY2Vzc2VkKTtcblxuICAgIC8vIEFkZCBwb3N0LXByb2Nlc3NpbmcgaWYgcHJvdmlkZWQgKGluc2VydCBiZWZvcmUgY2xlYW51cClcbiAgICBpZiAocG9zdFByb2Nlc3NpbmdTdGVwKSB7XG4gICAgICBjb25zdCBwb3N0UHJvY2Vzc2luZ0Vycm9ySGFuZGxlciA9IG5ldyBEeW5hbW9VcGRhdGVJdGVtKHRoaXMsICdDaHVua2VkUG9zdFByb2Nlc3NpbmdGYWlsRERCVXBkYXRlJywge1xuICAgICAgICB0YWJsZTogdGhpcy5kb2N1bWVudFByb2Nlc3NpbmdUYWJsZSxcbiAgICAgICAga2V5OiB7XG4gICAgICAgICAgRG9jdW1lbnRJZDogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZyhKc29uUGF0aC5zdHJpbmdBdCgnJC5kb2N1bWVudElkJykpLFxuICAgICAgICB9LFxuICAgICAgICB1cGRhdGVFeHByZXNzaW9uOiAnU0VUIFdvcmtmbG93U3RhdHVzID0gOm5ld1N0YXR1cycsXG4gICAgICAgIGV4cHJlc3Npb25BdHRyaWJ1dGVWYWx1ZXM6IHtcbiAgICAgICAgICAnOm5ld1N0YXR1cyc6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoJ3Bvc3QtcHJvY2Vzc2luZy1mYWlsdXJlJyksXG4gICAgICAgIH0sXG4gICAgICAgIHJlc3VsdFBhdGg6IEpzb25QYXRoLkRJU0NBUkQsXG4gICAgICB9KS5uZXh0KHRoaXMuaW5ncmVzc0FkYXB0ZXIuY3JlYXRlRmFpbGVkQ2hhaW4odGhpcywgJ0NodW5rZWRQb3N0UHJvYycpKTtcblxuICAgICAgZmluYWxDaGFpbiA9IHBvc3RQcm9jZXNzaW5nU3RlcFxuICAgICAgICAuYWRkQ2F0Y2gocG9zdFByb2Nlc3NpbmdFcnJvckhhbmRsZXIsIHtcbiAgICAgICAgICByZXN1bHRQYXRoOiBKc29uUGF0aC5ESVNDQVJELFxuICAgICAgICB9KVxuICAgICAgICAubmV4dChcbiAgICAgICAgICBuZXcgRHluYW1vVXBkYXRlSXRlbSh0aGlzLCAnQ2h1bmtlZFBvc3RQcm9jZXNzaW5nU3VjY2Vzc1VwZGF0ZScsIHtcbiAgICAgICAgICAgIHRhYmxlOiB0aGlzLmRvY3VtZW50UHJvY2Vzc2luZ1RhYmxlLFxuICAgICAgICAgICAga2V5OiB7XG4gICAgICAgICAgICAgIERvY3VtZW50SWQ6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoSnNvblBhdGguc3RyaW5nQXQoJyQuZG9jdW1lbnRJZCcpKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB1cGRhdGVFeHByZXNzaW9uOiAnU0VUIFdvcmtmbG93U3RhdHVzID0gOm5ld1N0YXR1cywgUG9zdFByb2Nlc3NpbmdSZXN1bHQgPSA6cG9zdFByb2Nlc3NpbmdSZXN1bHQnLFxuICAgICAgICAgICAgZXhwcmVzc2lvbkF0dHJpYnV0ZVZhbHVlczoge1xuICAgICAgICAgICAgICAnOm5ld1N0YXR1cyc6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoJ3Bvc3QtcHJvY2Vzc2luZy1jb21wbGV0ZScpLFxuICAgICAgICAgICAgICAnOnBvc3RQcm9jZXNzaW5nUmVzdWx0JzogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZyhKc29uUGF0aC5qc29uVG9TdHJpbmcoSnNvblBhdGgub2JqZWN0QXQoJyQucG9zdFByb2Nlc3NlZFJlc3VsdCcpKSksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmVzdWx0UGF0aDogSnNvblBhdGguRElTQ0FSRCxcbiAgICAgICAgICB9KS5uZXh0KGZpbmFsQ2hhaW4pLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8vIEFkZCBlbnJpY2htZW50IGlmIHByb3ZpZGVkIChpbnNlcnQgYmVmb3JlIHBvc3QtcHJvY2Vzc2luZyBvciBjbGVhbnVwKVxuICAgIGlmIChlbnJpY2htZW50U3RlcCkge1xuICAgICAgY29uc3QgZW5yaWNobWVudEVycm9ySGFuZGxlciA9IG5ldyBEeW5hbW9VcGRhdGVJdGVtKHRoaXMsICdDaHVua2VkRW5yaWNobWVudEZhaWxEREJVcGRhdGUnLCB7XG4gICAgICAgIHRhYmxlOiB0aGlzLmRvY3VtZW50UHJvY2Vzc2luZ1RhYmxlLFxuICAgICAgICBrZXk6IHtcbiAgICAgICAgICBEb2N1bWVudElkOiBEeW5hbW9BdHRyaWJ1dGVWYWx1ZS5mcm9tU3RyaW5nKEpzb25QYXRoLnN0cmluZ0F0KCckLmRvY3VtZW50SWQnKSksXG4gICAgICAgIH0sXG4gICAgICAgIHVwZGF0ZUV4cHJlc3Npb246ICdTRVQgV29ya2Zsb3dTdGF0dXMgPSA6bmV3U3RhdHVzJyxcbiAgICAgICAgZXhwcmVzc2lvbkF0dHJpYnV0ZVZhbHVlczoge1xuICAgICAgICAgICc6bmV3U3RhdHVzJzogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZygnZW5yaWNobWVudC1mYWlsdXJlJyksXG4gICAgICAgIH0sXG4gICAgICAgIHJlc3VsdFBhdGg6IEpzb25QYXRoLkRJU0NBUkQsXG4gICAgICB9KS5uZXh0KHRoaXMuaW5ncmVzc0FkYXB0ZXIuY3JlYXRlRmFpbGVkQ2hhaW4odGhpcywgJ0NodW5rZWRFbnJpY2gnKSk7XG5cbiAgICAgIGZpbmFsQ2hhaW4gPSBlbnJpY2htZW50U3RlcFxuICAgICAgICAuYWRkQ2F0Y2goZW5yaWNobWVudEVycm9ySGFuZGxlciwge1xuICAgICAgICAgIHJlc3VsdFBhdGg6IEpzb25QYXRoLkRJU0NBUkQsXG4gICAgICAgIH0pXG4gICAgICAgIC5uZXh0KFxuICAgICAgICAgIG5ldyBEeW5hbW9VcGRhdGVJdGVtKHRoaXMsICdDaHVua2VkRW5yaWNobWVudFN1Y2Nlc3NVcGRhdGUnLCB7XG4gICAgICAgICAgICB0YWJsZTogdGhpcy5kb2N1bWVudFByb2Nlc3NpbmdUYWJsZSxcbiAgICAgICAgICAgIGtleToge1xuICAgICAgICAgICAgICBEb2N1bWVudElkOiBEeW5hbW9BdHRyaWJ1dGVWYWx1ZS5mcm9tU3RyaW5nKEpzb25QYXRoLnN0cmluZ0F0KCckLmRvY3VtZW50SWQnKSksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdXBkYXRlRXhwcmVzc2lvbjogJ1NFVCBXb3JrZmxvd1N0YXR1cyA9IDpuZXdTdGF0dXMsIEVucmljaG1lbnRSZXN1bHQgPSA6ZW5yaWNobWVudFJlc3VsdCcsXG4gICAgICAgICAgICBleHByZXNzaW9uQXR0cmlidXRlVmFsdWVzOiB7XG4gICAgICAgICAgICAgICc6bmV3U3RhdHVzJzogcG9zdFByb2Nlc3NpbmdTdGVwXG4gICAgICAgICAgICAgICAgPyBEeW5hbW9BdHRyaWJ1dGVWYWx1ZS5mcm9tU3RyaW5nKCdlbnJpY2htZW50LWNvbXBsZXRlJylcbiAgICAgICAgICAgICAgICA6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoJ2NvbXBsZXRlJyksXG4gICAgICAgICAgICAgICc6ZW5yaWNobWVudFJlc3VsdCc6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoSnNvblBhdGguanNvblRvU3RyaW5nKEpzb25QYXRoLm9iamVjdEF0KCckLmVucmljaGVkUmVzdWx0JykpKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByZXN1bHRQYXRoOiBKc29uUGF0aC5ESVNDQVJELFxuICAgICAgICAgIH0pLm5leHQoZmluYWxDaGFpbiksXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gQ2hhaW46IE1hcCBTdGF0ZSDihpIgQWdncmVnYXRpb24g4oaSIE5vcm1hbGl6ZSDihpIgRHluYW1vREIgVXBkYXRlIOKGkiBbRW5yaWNobWVudF0g4oaSIFtQb3N0UHJvY2Vzc2luZ10g4oaSIENsZWFudXAg4oaSIE1vdmUgdG8gUHJvY2Vzc2VkXG4gICAgcmV0dXJuIG1hcFN0YXRlXG4gICAgICAuYWRkQ2F0Y2goYWdncmVnYXRpb25FcnJvckhhbmRsZXIsIHtcbiAgICAgICAgcmVzdWx0UGF0aDogJyQuZXJyb3InLFxuICAgICAgfSlcbiAgICAgIC5uZXh0KFxuICAgICAgICBhZ2dyZWdhdGlvbkxhbWJkYVN0ZXBcbiAgICAgICAgICAuYWRkQ2F0Y2goYWdncmVnYXRpb25FcnJvckhhbmRsZXIsIHtcbiAgICAgICAgICAgIHJlc3VsdFBhdGg6ICckLmVycm9yJyxcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5hZGRSZXRyeSh7XG4gICAgICAgICAgICBlcnJvcnM6IFsnTGFtYmRhLlNlcnZpY2VFeGNlcHRpb24nLCAnTGFtYmRhLlRvb01hbnlSZXF1ZXN0c0V4Y2VwdGlvbiddLFxuICAgICAgICAgICAgaW50ZXJ2YWw6IER1cmF0aW9uLnNlY29uZHMoMiksXG4gICAgICAgICAgICBtYXhBdHRlbXB0czogMyxcbiAgICAgICAgICAgIGJhY2tvZmZSYXRlOiAyLFxuICAgICAgICAgIH0pXG4gICAgICAgICAgLm5leHQoXG4gICAgICAgICAgICBub3JtYWxpemVTdGF0ZS5uZXh0KFxuICAgICAgICAgICAgICB1cGRhdGVBZ2dyZWdhdGVkUmVzdWx0U3RlcFxuICAgICAgICAgICAgICAgIC5hZGRSZXRyeSh7XG4gICAgICAgICAgICAgICAgICBlcnJvcnM6IFsnRHluYW1vREIuUHJvdmlzaW9uZWRUaHJvdWdocHV0RXhjZWVkZWRFeGNlcHRpb24nXSxcbiAgICAgICAgICAgICAgICAgIGludGVydmFsOiBEdXJhdGlvbi5zZWNvbmRzKDEpLFxuICAgICAgICAgICAgICAgICAgbWF4QXR0ZW1wdHM6IDMsXG4gICAgICAgICAgICAgICAgICBiYWNrb2ZmUmF0ZTogMixcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5uZXh0KGZpbmFsQ2hhaW4pLFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICApLFxuICAgICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIHRoZSBhZ2dyZWdhdGlvbiBzdGVwIGZvciBjb21iaW5pbmcgY2h1bmsgcmVzdWx0cyB1c2luZyBCZWRyb2NrLlxuICAgKlxuICAgKiBVc2VzIHRoZSBzYW1lIEJlZHJvY2sgaW52b2tlIExhbWJkYSBwYXR0ZXJuIGFzIHRoZSBwcm9jZXNzaW5nIHN0ZXAgYnV0IHdpdGhcbiAgICogYSBkaWZmZXJlbnQgcHJvbXB0IGRlc2lnbmVkIGZvciBhZ2dyZWdhdGluZyBtdWx0aXBsZSBjaHVuayByZXN1bHRzLlxuICAgKiBUaGUgY2h1bmsgcHJvY2Vzc2luZyByZXN1bHRzIGFyZSBwYXNzZWQgYXMgdGV4dCBkYXRhIHRvIHRoZSBtb2RlbC5cbiAgICpcbiAgICogQHJldHVybnMgTGFtYmRhSW52b2tlIHRhc2sgZm9yIHJlc3VsdCBhZ2dyZWdhdGlvblxuICAgKi9cbiAgcHJpdmF0ZSBjcmVhdGVBZ2dyZWdhdGlvblN0ZXAoKTogTGFtYmRhSW52b2tlIHtcbiAgICAvLyBDcmVhdGUgTGFtYmRhIGZ1bmN0aW9uIG9ubHkgb25jZSAocmV1c2VzIGJlZHJvY2staW52b2tlIHBhdHRlcm4pXG4gICAgaWYgKCF0aGlzLl9hZ2dyZWdhdGlvbkZ1bmN0aW9uKSB7XG4gICAgICBjb25zdCBwcm9tcHQgPSB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5hZ2dyZWdhdGlvblByb21wdCB8fCBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nLkRFRkFVTFRfQUdHUkVHQVRJT05fUFJPTVBUO1xuICAgICAgY29uc3QgYWRqdXN0ZWRNb2RlbElkID0gQmVkcm9ja01vZGVsVXRpbHMuZGVyaXZlQWN0dWFsTW9kZWxJZCh0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5wcm9jZXNzaW5nQmVkcm9ja01vZGVsKTtcbiAgICAgIGNvbnN0IHJvbGUgPSB0aGlzLmdlbmVyYXRlTGFtYmRhUm9sZUZvckJlZHJvY2soJ0FnZ3JlZ2F0aW9uTGFtYmRhUm9sZScsIHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLnByb2Nlc3NpbmdCZWRyb2NrTW9kZWwpO1xuICAgICAgY29uc3QgeyByZWdpb24sIGFjY291bnQgfSA9IFN0YWNrLm9mKHRoaXMpO1xuXG4gICAgICBjb25zdCBnZW5lcmF0ZWRMb2dQZXJtaXNzaW9ucyA9IExhbWJkYUlhbVV0aWxzLmNyZWF0ZUxvZ3NQZXJtaXNzaW9ucyh7XG4gICAgICAgIGFjY291bnQsXG4gICAgICAgIGZ1bmN0aW9uTmFtZTogJ2JlZHJvY2staWRwLWFnZ3JlZ2F0aW9uJyxcbiAgICAgICAgcmVnaW9uLFxuICAgICAgICBzY29wZTogdGhpcyxcbiAgICAgICAgZW5hYmxlT2JzZXJ2YWJpbGl0eTogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuZW5hYmxlT2JzZXJ2YWJpbGl0eSxcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLmVuY3J5cHRpb25LZXkuZ3JhbnRFbmNyeXB0RGVjcnlwdChyb2xlKTtcblxuICAgICAgdGhpcy5fYWdncmVnYXRpb25GdW5jdGlvbiA9IG5ldyBQeXRob25GdW5jdGlvbih0aGlzLCAnQmVkcm9ja0FnZ3JlZ2F0aW9uRnVuY3Rpb24nLCB7XG4gICAgICAgIGZ1bmN0aW9uTmFtZTogZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMudW5pcXVlRnVuY3Rpb25OYW1lLFxuICAgICAgICBhcmNoaXRlY3R1cmU6IEFyY2hpdGVjdHVyZS5YODZfNjQsXG4gICAgICAgIHJ1bnRpbWU6IERlZmF1bHRSdW50aW1lcy5QWVRIT04sXG4gICAgICAgIGVudHJ5OiBwYXRoLmpvaW4oX19kaXJuYW1lLCAncmVzb3VyY2VzL2RlZmF1bHQtYmVkcm9jay1pbnZva2UnKSxcbiAgICAgICAgcm9sZSxcbiAgICAgICAgbWVtb3J5U2l6ZTogMTAyNCxcbiAgICAgICAgdGltZW91dDogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuc3RlcFRpbWVvdXRzIHx8IER1cmF0aW9uLm1pbnV0ZXMoNSksXG4gICAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgICAgTU9ERUxfSUQ6IGFkanVzdGVkTW9kZWxJZCxcbiAgICAgICAgICBQUk9NUFQ6IHByb21wdCxcbiAgICAgICAgICBJTlZPS0VfVFlQRTogJ2FnZ3JlZ2F0aW9uJyxcbiAgICAgICAgICBJTlZPS0VfTUFYX1RPS0VOUzogJzY0MDAwJywgLy8gQWdncmVnYXRpb24gbWF5IG5lZWQgbW9yZSB0b2tlbnMgZm9yIG1lcmdlZCBvdXRwdXRcbiAgICAgICAgICAuLi5Qb3dlcnRvb2xzQ29uZmlnLmdlbmVyYXRlRGVmYXVsdExhbWJkYUNvbmZpZyhcbiAgICAgICAgICAgIHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLmVuYWJsZU9ic2VydmFiaWxpdHksXG4gICAgICAgICAgICB0aGlzLm1ldHJpY05hbWVzcGFjZSxcbiAgICAgICAgICAgIHRoaXMubWV0cmljU2VydmljZU5hbWUsXG4gICAgICAgICAgKSxcbiAgICAgICAgfSxcbiAgICAgICAgZW52aXJvbm1lbnRFbmNyeXB0aW9uOiB0aGlzLmVuY3J5cHRpb25LZXksXG4gICAgICAgIHZwYzogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29ya1xuICAgICAgICAgID8gdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29yay52cGNcbiAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgdnBjU3VibmV0czogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29ya1xuICAgICAgICAgID8gdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29yay5hcHBsaWNhdGlvblN1Ym5ldFNlbGVjdGlvbigpXG4gICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICB9KTtcblxuICAgICAgZm9yIChjb25zdCBzdGF0ZW1lbnQgb2YgZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMucG9saWN5U3RhdGVtZW50cykge1xuICAgICAgICB0aGlzLl9hZ2dyZWdhdGlvbkZ1bmN0aW9uLnJvbGU/LmFkZFRvUHJpbmNpcGFsUG9saWN5KHN0YXRlbWVudCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrKSB7XG4gICAgICAgIHRoaXMuX2FnZ3JlZ2F0aW9uRnVuY3Rpb24ucm9sZT8uYWRkVG9QcmluY2lwYWxQb2xpY3koTGFtYmRhSWFtVXRpbHMuZ2VuZXJhdGVMYW1iZGFWUENQZXJtaXNzaW9ucygpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBbHdheXMgY3JlYXRlIGEgbmV3IExhbWJkYUludm9rZSB0YXNrIHRvIGFsbG93IHByb3BlciBzdGF0ZSBjaGFpbmluZ1xuICAgIGNvbnN0IHN0ZXBJZCA9IGBBZ2dyZWdhdGlvblN0ZXAtJHt0aGlzLl9hZ2dyZWdhdGlvblN0ZXBDb3VudGVyfWA7XG4gICAgdGhpcy5fYWdncmVnYXRpb25TdGVwQ291bnRlcisrO1xuXG4gICAgLy8gUGFzcyBjaHVuayByZXN1bHRzIGFzIGRhdGEgY29udGVudCAtIHRoZSBMYW1iZGEgd2lsbCBmb3JtYXQgdGhlbSBmb3IgQmVkcm9ja1xuICAgIHJldHVybiBuZXcgTGFtYmRhSW52b2tlKHRoaXMsIHN0ZXBJZCwge1xuICAgICAgbGFtYmRhRnVuY3Rpb246IHRoaXMuX2FnZ3JlZ2F0aW9uRnVuY3Rpb24sXG4gICAgICBwYXlsb2FkOiBUYXNrSW5wdXQuZnJvbU9iamVjdCh7XG4gICAgICAgICdkb2N1bWVudElkLiQnOiAnJC5kb2N1bWVudElkJyxcbiAgICAgICAgJ2NvbnRlbnRUeXBlJzogJ2RhdGEnLFxuICAgICAgICAnY29udGVudCc6IHtcbiAgICAgICAgICAvLyBQYXNzIHRoZSBjaHVuayByZXN1bHRzIGFzIEpTT04gc3RyaW5nIGZvciB0aGUgTGFtYmRhIHRvIHByb2Nlc3NcbiAgICAgICAgICAnZGF0YS4kJzogJ1N0YXRlcy5Kc29uVG9TdHJpbmcoJC5jaHVua1Jlc3VsdHMpJyxcbiAgICAgICAgfSxcbiAgICAgIH0pLFxuICAgICAgLy8gU3RvcmUgaW4gYm90aCBhZ2dyZWdhdGVkUmVzdWx0IEFORCBwcm9jZXNzaW5nUmVzdWx0IGZvciBjb25zaXN0ZW5jeSB3aXRoIG5vbi1jaHVua2VkIGZsb3dcbiAgICAgIC8vIFRoaXMgYWxsb3dzIGVucmljaG1lbnQvcG9zdC1wcm9jZXNzaW5nIHN0ZXBzIHRvIHVzZSAkLnByb2Nlc3NpbmdSZXN1bHQgcmVnYXJkbGVzcyBvZiBjaHVua2luZ1xuICAgICAgcmVzdWx0UGF0aDogJyQuYWdncmVnYXRlZFJlc3VsdCcsXG4gICAgICByZXN1bHRTZWxlY3Rvcjoge1xuICAgICAgICAncmVzdWx0LiQnOiAnJC5QYXlsb2FkLnJlc3VsdCcsXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgdGhlIER5bmFtb0RCIHVwZGF0ZSBzdGVwIGZvciBzdG9yaW5nIGFnZ3JlZ2F0ZWQgcmVzdWx0cy5cbiAgICpcbiAgICogVXBkYXRlcyB0aGUgZG9jdW1lbnQgcmVjb3JkIHdpdGg6XG4gICAqIC0gQWdncmVnYXRlZFJlc3VsdDogSlNPTiBzdHJpbmcgd2l0aCBjbGFzc2lmaWNhdGlvbiwgZW50aXRpZXMsIGFuZCBzdW1tYXJ5XG4gICAqIC0gV29ya2Zsb3dTdGF0dXM6ICdjb21wbGV0ZSdcbiAgICpcbiAgICogQHJldHVybnMgRHluYW1vVXBkYXRlSXRlbSB0YXNrIGZvciBzdG9yaW5nIGFnZ3JlZ2F0ZWQgcmVzdWx0c1xuICAgKi9cbiAgcHJpdmF0ZSBjcmVhdGVVcGRhdGVBZ2dyZWdhdGVkUmVzdWx0U3RlcCgpOiBEeW5hbW9VcGRhdGVJdGVtIHtcbiAgICByZXR1cm4gbmV3IER5bmFtb1VwZGF0ZUl0ZW0odGhpcywgJ1N0b3JlQWdncmVnYXRlZFJlc3VsdCcsIHtcbiAgICAgIHRhYmxlOiB0aGlzLmRvY3VtZW50UHJvY2Vzc2luZ1RhYmxlLFxuICAgICAga2V5OiB7XG4gICAgICAgIERvY3VtZW50SWQ6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoSnNvblBhdGguc3RyaW5nQXQoJyQuZG9jdW1lbnRJZCcpKSxcbiAgICAgIH0sXG4gICAgICB1cGRhdGVFeHByZXNzaW9uOiAnU0VUIEFnZ3JlZ2F0ZWRSZXN1bHQgPSA6cmVzdWx0LCBXb3JrZmxvd1N0YXR1cyA9IDpzdGF0dXMnLFxuICAgICAgZXhwcmVzc2lvbkF0dHJpYnV0ZVZhbHVlczoge1xuICAgICAgICAnOnJlc3VsdCc6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoXG4gICAgICAgICAgSnNvblBhdGguanNvblRvU3RyaW5nKEpzb25QYXRoLm9iamVjdEF0KCckLmFnZ3JlZ2F0ZWRSZXN1bHQnKSksXG4gICAgICAgICksXG4gICAgICAgICc6c3RhdHVzJzogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZygnY29tcGxldGUnKSxcbiAgICAgIH0sXG4gICAgICByZXN1bHRQYXRoOiBKc29uUGF0aC5ESVNDQVJELFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgdGhlIGNsZWFudXAgTGFtYmRhIHN0ZXAgZm9yIHJlbW92aW5nIHRlbXBvcmFyeSBjaHVuayBmaWxlcy5cbiAgICpcbiAgICogVGhlIGNsZWFudXAgTGFtYmRhOlxuICAgKiAtIERlbGV0ZXMgYWxsIGNodW5rIGZpbGVzIGZyb20gUzMgY2h1bmtzLyBwcmVmaXhcbiAgICogLSBVc2VzIGJhdGNoIGRlbGV0ZSBmb3IgZWZmaWNpZW5jeSAodXAgdG8gMTAwMCBvYmplY3RzIHBlciByZXF1ZXN0KVxuICAgKiAtIExvZ3MgZXJyb3JzIGJ1dCBkb2Vzbid0IGZhaWwgdGhlIHdvcmtmbG93XG4gICAqXG4gICAqIEByZXR1cm5zIExhbWJkYUludm9rZSB0YXNrIGZvciBjaHVuayBjbGVhbnVwXG4gICAqL1xuICBwcml2YXRlIGNyZWF0ZUNsZWFudXBTdGVwKCk6IExhbWJkYUludm9rZSB7XG4gICAgLy8gQ3JlYXRlIExhbWJkYSBmdW5jdGlvbiBvbmx5IG9uY2VcbiAgICBpZiAoIXRoaXMuX2NsZWFudXBGdW5jdGlvbikge1xuICAgICAgY29uc3QgeyByZWdpb24sIGFjY291bnQgfSA9IFN0YWNrLm9mKHRoaXMpO1xuXG4gICAgICBjb25zdCByb2xlID0gbmV3IFJvbGUodGhpcywgJ0NsZWFudXBMYW1iZGFSb2xlJywge1xuICAgICAgICBhc3N1bWVkQnk6IG5ldyBTZXJ2aWNlUHJpbmNpcGFsKCdsYW1iZGEuYW1hem9uYXdzLmNvbScpLFxuICAgICAgICBpbmxpbmVQb2xpY2llczoge1xuICAgICAgICAgIENsZWFudXBQb2xpY3k6IG5ldyBQb2xpY3lEb2N1bWVudCh7XG4gICAgICAgICAgICBzdGF0ZW1lbnRzOiBbXG4gICAgICAgICAgICAgIC8vIFMzIGFjY2VzcyBmb3IgZGVsZXRpbmcgY2h1bmtzIG9ubHkgLSBsZWFzdCBwcml2aWxlZ2VcbiAgICAgICAgICAgICAgLi4udGhpcy5pbmdyZXNzQWRhcHRlci5nZW5lcmF0ZUFkYXB0ZXJJQU1Qb2xpY2llcyhbJ3MzOkRlbGV0ZU9iamVjdCddLCB0cnVlKSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSksXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMgPSBMYW1iZGFJYW1VdGlscy5jcmVhdGVMb2dzUGVybWlzc2lvbnMoe1xuICAgICAgICBhY2NvdW50LFxuICAgICAgICBmdW5jdGlvbk5hbWU6ICdiZWRyb2NrLWlkcC1jbGVhbnVwJyxcbiAgICAgICAgcmVnaW9uLFxuICAgICAgICBzY29wZTogdGhpcyxcbiAgICAgICAgZW5hYmxlT2JzZXJ2YWJpbGl0eTogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuZW5hYmxlT2JzZXJ2YWJpbGl0eSxcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLmVuY3J5cHRpb25LZXkuZ3JhbnRFbmNyeXB0RGVjcnlwdChyb2xlKTtcblxuICAgICAgdGhpcy5fY2xlYW51cEZ1bmN0aW9uID0gbmV3IFB5dGhvbkZ1bmN0aW9uKHRoaXMsICdDbGVhbnVwRnVuY3Rpb24nLCB7XG4gICAgICAgIGZ1bmN0aW9uTmFtZTogZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMudW5pcXVlRnVuY3Rpb25OYW1lLFxuICAgICAgICBlbnRyeTogcGF0aC5qb2luKF9fZGlybmFtZSwgJ3Jlc291cmNlcy9jbGVhbnVwJyksXG4gICAgICAgIGluZGV4OiAnaGFuZGxlci5weScsXG4gICAgICAgIGhhbmRsZXI6ICdoYW5kbGVyJyxcbiAgICAgICAgcnVudGltZTogRGVmYXVsdFJ1bnRpbWVzLlBZVEhPTixcbiAgICAgICAgYXJjaGl0ZWN0dXJlOiBBcmNoaXRlY3R1cmUuWDg2XzY0LFxuICAgICAgICByb2xlLFxuICAgICAgICBtZW1vcnlTaXplOiA1MTIsXG4gICAgICAgIHRpbWVvdXQ6IER1cmF0aW9uLm1pbnV0ZXMoNSksXG4gICAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgICAgLi4uUG93ZXJ0b29sc0NvbmZpZy5nZW5lcmF0ZURlZmF1bHRMYW1iZGFDb25maWcoXG4gICAgICAgICAgICB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5lbmFibGVPYnNlcnZhYmlsaXR5LFxuICAgICAgICAgICAgdGhpcy5tZXRyaWNOYW1lc3BhY2UsXG4gICAgICAgICAgICB0aGlzLm1ldHJpY1NlcnZpY2VOYW1lLFxuICAgICAgICAgICksXG4gICAgICAgIH0sXG4gICAgICAgIGVudmlyb25tZW50RW5jcnlwdGlvbjogdGhpcy5lbmNyeXB0aW9uS2V5LFxuICAgICAgICB2cGM6IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLm5ldHdvcmtcbiAgICAgICAgICA/IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLm5ldHdvcmsudnBjXG4gICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgIHZwY1N1Ym5ldHM6IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLm5ldHdvcmtcbiAgICAgICAgICA/IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLm5ldHdvcmsuYXBwbGljYXRpb25TdWJuZXRTZWxlY3Rpb24oKVxuICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgfSk7XG5cbiAgICAgIGZvciAoY29uc3Qgc3RhdGVtZW50IG9mIGdlbmVyYXRlZExvZ1Blcm1pc3Npb25zLnBvbGljeVN0YXRlbWVudHMpIHtcbiAgICAgICAgdGhpcy5fY2xlYW51cEZ1bmN0aW9uLnJvbGU/LmFkZFRvUHJpbmNpcGFsUG9saWN5KHN0YXRlbWVudCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrKSB7XG4gICAgICAgIHRoaXMuX2NsZWFudXBGdW5jdGlvbi5yb2xlPy5hZGRUb1ByaW5jaXBhbFBvbGljeShMYW1iZGFJYW1VdGlscy5nZW5lcmF0ZUxhbWJkYVZQQ1Blcm1pc3Npb25zKCkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBuZXcgTGFtYmRhSW52b2tlKHRoaXMsICdDbGVhbnVwQ2h1bmtzJywge1xuICAgICAgbGFtYmRhRnVuY3Rpb246IHRoaXMuX2NsZWFudXBGdW5jdGlvbixcbiAgICAgIHBheWxvYWQ6IFRhc2tJbnB1dC5mcm9tT2JqZWN0KHtcbiAgICAgICAgJ2RvY3VtZW50SWQuJCc6ICckLmRvY3VtZW50SWQnLFxuICAgICAgICAnY2h1bmtzLiQnOiAnJC5jaHVua2luZ1Jlc3VsdC5jaHVua3MnLFxuICAgICAgfSksXG4gICAgICByZXN1bHRQYXRoOiBKc29uUGF0aC5ESVNDQVJELFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgdGhlIGVycm9yIGhhbmRsZXIgZm9yIGFnZ3JlZ2F0aW9uIGZhaWx1cmVzLlxuICAgKlxuICAgKiBXaGVuIGFnZ3JlZ2F0aW9uIGZhaWxzOlxuICAgKiAtIFVwZGF0ZXMgRHluYW1vREIgd2l0aCAnYWdncmVnYXRpb24tZmFpbHVyZScgc3RhdHVzXG4gICAqIC0gTW92ZXMgZG9jdW1lbnQgdG8gZmFpbGVkLyBwcmVmaXhcbiAgICpcbiAgICogQHJldHVybnMgU3RlcCBGdW5jdGlvbnMgY2hhaW4gZm9yIGhhbmRsaW5nIGFnZ3JlZ2F0aW9uIGVycm9yc1xuICAgKi9cbiAgcHJpdmF0ZSBjcmVhdGVBZ2dyZWdhdGlvbkVycm9ySGFuZGxlcigpOiBJQ2hhaW5hYmxlIHtcbiAgICBjb25zdCB1cGRhdGVGYWlsdXJlU3RhdHVzID0gbmV3IER5bmFtb1VwZGF0ZUl0ZW0odGhpcywgJ0FnZ3JlZ2F0aW9uRmFpbEREQlVwZGF0ZScsIHtcbiAgICAgIHRhYmxlOiB0aGlzLmRvY3VtZW50UHJvY2Vzc2luZ1RhYmxlLFxuICAgICAga2V5OiB7XG4gICAgICAgIERvY3VtZW50SWQ6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoSnNvblBhdGguc3RyaW5nQXQoJyQuZG9jdW1lbnRJZCcpKSxcbiAgICAgIH0sXG4gICAgICB1cGRhdGVFeHByZXNzaW9uOiAnU0VUIFdvcmtmbG93U3RhdHVzID0gOm5ld1N0YXR1cycsXG4gICAgICBleHByZXNzaW9uQXR0cmlidXRlVmFsdWVzOiB7XG4gICAgICAgICc6bmV3U3RhdHVzJzogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZygnYWdncmVnYXRpb24tZmFpbHVyZScpLFxuICAgICAgfSxcbiAgICAgIHJlc3VsdFBhdGg6IEpzb25QYXRoLkRJU0NBUkQsXG4gICAgfSk7XG5cbiAgICAvLyBVc2UgJ0NodW5rZWQnIHByZWZpeCB0byBhdm9pZCBJRCBjb2xsaXNpb25zIHdpdGggc3RhbmRhcmQgd29ya2Zsb3dcbiAgICBjb25zdCBtb3ZlVG9GYWlsZWQgPSB0aGlzLmluZ3Jlc3NBZGFwdGVyLmNyZWF0ZUZhaWxlZENoYWluKHRoaXMsICdDaHVua2VkJyk7XG5cbiAgICByZXR1cm4gdXBkYXRlRmFpbHVyZVN0YXR1cy5uZXh0KG1vdmVUb0ZhaWxlZCk7XG4gIH1cbn1cbiJdfQ==