@aws-cdk/aws-glue-alpha
Version:
The CDK Construct Library for AWS::Glue
422 lines • 47.6 kB
JavaScript
"use strict";
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Workflow = exports.WorkflowBase = void 0;
const jsiiDeprecationWarnings = require("../../.warnings.jsii.js");
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const cdk = require("aws-cdk-lib/core");
const aws_glue_1 = require("aws-cdk-lib/aws-glue");
const constants_1 = require("../constants");
const trigger_options_1 = require("./trigger-options");
const metadata_resource_1 = require("aws-cdk-lib/core/lib/metadata-resource");
const prop_injectable_1 = require("aws-cdk-lib/core/lib/prop-injectable");
/**
* Base abstract class for Workflow
*
* @see https://docs.aws.amazon.com/glue/latest/dg/about-triggers.html
*/
class WorkflowBase extends cdk.Resource {
static [JSII_RTTI_SYMBOL_1] = { fqn: "@aws-cdk/aws-glue-alpha.WorkflowBase", version: "2.225.0-alpha.0" };
/**
* Extract workflowName from arn
*/
static extractNameFromArn(scope, workflowArn) {
return cdk.Stack.of(scope).splitArn(workflowArn, cdk.ArnFormat.SLASH_RESOURCE_NAME).resourceName;
}
/**
* Add an on-demand trigger to the workflow.
*
* @param id The id of the trigger.
* @param options Additional options for the trigger.
* @throws If both job and crawler are provided, or if neither job nor crawler is provided.
* @returns The created CfnTrigger resource.
*/
addOnDemandTrigger(id, options) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_glue_alpha_OnDemandTriggerOptions(options);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addOnDemandTrigger);
}
throw error;
}
const trigger = new aws_glue_1.CfnTrigger(this, id, {
...options,
workflowName: this.workflowName,
type: 'ON_DEMAND',
actions: options.actions?.map(this.renderAction.bind(this)),
description: options.description || undefined,
});
return trigger;
}
/**
* Add a daily-scheduled trigger to the workflow.
*
* @param id The id of the trigger.
* @param options Additional options for the trigger.
* @throws If both job and crawler are provided, or if neither job nor crawler is provided.
* @returns The created CfnTrigger resource.
*/
addDailyScheduledTrigger(id, options) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_glue_alpha_DailyScheduleTriggerOptions(options);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addDailyScheduledTrigger);
}
throw error;
}
const dailySchedule = trigger_options_1.TriggerSchedule.cron({
minute: '0',
hour: '0',
});
const trigger = new aws_glue_1.CfnTrigger(this, id, {
...options,
workflowName: this.workflowName,
type: 'SCHEDULED',
actions: options.actions?.map(this.renderAction.bind(this)),
schedule: dailySchedule.expressionString,
startOnCreation: options.startOnCreation ?? false,
});
return trigger;
}
/**
* Add a weekly-scheduled trigger to the workflow.
*
* @param id The id of the trigger.
* @param options Additional options for the trigger.
* @throws If both job and crawler are provided, or if neither job nor crawler is provided.
* @returns The created CfnTrigger resource.
*/
addWeeklyScheduledTrigger(id, options) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_glue_alpha_WeeklyScheduleTriggerOptions(options);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addWeeklyScheduledTrigger);
}
throw error;
}
const weeklySchedule = trigger_options_1.TriggerSchedule.cron({
minute: '0',
hour: '0',
weekDay: 'SUN',
});
const trigger = new aws_glue_1.CfnTrigger(this, id, {
...options,
workflowName: this.workflowName,
type: 'SCHEDULED',
actions: options.actions?.map(this.renderAction.bind(this)),
schedule: weeklySchedule.expressionString,
startOnCreation: options.startOnCreation ?? false,
});
return trigger;
}
/**
* Add a custom-scheduled trigger to the workflow.
*
* @param id The id of the trigger.
* @param options Additional options for the trigger.
* @throws If both job and crawler are provided, or if neither job nor crawler is provided.
* @returns The created CfnTrigger resource.
*/
addCustomScheduledTrigger(id, options) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_glue_alpha_CustomScheduledTriggerOptions(options);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addCustomScheduledTrigger);
}
throw error;
}
const trigger = new aws_glue_1.CfnTrigger(this, id, {
...options,
workflowName: this.workflowName,
type: 'SCHEDULED',
actions: options.actions?.map(this.renderAction.bind(this)),
schedule: options.schedule.expressionString,
startOnCreation: options.startOnCreation ?? false,
});
return trigger;
}
/**
* Add an Event Bridge based trigger to the workflow.
*
* @param id The id of the trigger.
* @param options Additional options for the trigger.
* @throws If both job and crawler are provided, or if neither job nor crawler is provided.
* @returns The created CfnTrigger resource.
*/
addNotifyEventTrigger(id, options) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_glue_alpha_NotifyEventTriggerOptions(options);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addNotifyEventTrigger);
}
throw error;
}
const trigger = new aws_glue_1.CfnTrigger(this, id, {
...options,
workflowName: this.workflowName,
type: 'EVENT',
actions: options.actions?.map(this.renderAction.bind(this)),
eventBatchingCondition: this.renderEventBatchingCondition(options),
description: options.description ?? undefined,
});
return trigger;
}
/**
* Add a Condition (Predicate) based trigger to the workflow.
*
* @param id The id of the trigger.
* @param options Additional options for the trigger.
* @throws If both job and crawler are provided, or if neither job nor crawler is provided for any condition.
* @throws If a job is provided without a job state, or if a crawler is provided without a crawler state for any condition.
* @returns The created CfnTrigger resource.
*/
addConditionalTrigger(id, options) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_glue_alpha_ConditionalTriggerOptions(options);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addConditionalTrigger);
}
throw error;
}
const trigger = new aws_glue_1.CfnTrigger(this, id, {
...options,
workflowName: this.workflowName,
type: 'CONDITIONAL',
actions: options.actions?.map(this.renderAction.bind(this)),
predicate: this.renderPredicate(options),
eventBatchingCondition: this.renderEventBatchingCondition(options),
description: options.description ?? undefined,
});
return trigger;
}
renderAction(action) {
// Validate that either job or crawler is provided, but not both
if (!action.job && !action.crawler) {
throw new cdk.ValidationError('You must provide either a job or a crawler for the action.', this);
}
else if (action.job && action.crawler) {
throw new cdk.ValidationError('You cannot provide both a job and a crawler for the action.', this);
}
return {
jobName: action.job?.jobName,
arguments: action.arguments,
timeout: action.timeout?.toMinutes(),
securityConfiguration: action.securityConfiguration?.securityConfigurationName,
crawlerName: action.crawler?.name,
};
}
renderPredicate(props) {
const conditions = props.predicate.conditions?.map(condition => {
// Validate that either job or crawler is provided, but not both
if (!condition.job && !condition.crawlerName) {
throw new cdk.ValidationError('You must provide either a job or a crawler for the condition.', this);
}
else if (condition.job && condition.crawlerName) {
throw new cdk.ValidationError('You cannot provide both a job and a crawler for the condition.', this);
}
// Validate that if job is provided, job state is also provided
if (condition.job && !condition.state) {
throw new cdk.ValidationError('If you provide a job for the condition, you must also provide a job state.', this);
}
// Validate that if crawler is provided, crawler state is also provided
if (condition.crawlerName && !condition.crawlState) {
throw new cdk.ValidationError('If you provide a crawler for the condition, you must also provide a crawler state.', this);
}
return {
logicalOperator: condition.logicalOperator ?? constants_1.ConditionLogicalOperator.EQUALS,
jobName: condition.job?.jobName ?? undefined,
state: condition.state ?? undefined,
crawlerName: condition.crawlerName ?? undefined,
crawlState: condition.crawlState ?? undefined,
};
});
return {
logical: props.predicate.conditions?.length === 1 ? undefined : props.predicate.logical ?? constants_1.PredicateLogical.AND,
conditions: conditions,
};
}
renderEventBatchingCondition(props) {
const defaultBatchSize = 1;
const defaultBatchWindow = cdk.Duration.seconds(900).toSeconds();
if (!props.eventBatchingCondition) {
return {
batchSize: defaultBatchSize,
batchWindow: defaultBatchWindow,
};
}
return {
batchSize: props.eventBatchingCondition.batchSize || defaultBatchSize,
batchWindow: props.eventBatchingCondition.batchWindow?.toSeconds() || defaultBatchWindow,
};
}
buildWorkflowArn(scope, workflowName) {
return cdk.Stack.of(scope).formatArn({
service: 'glue',
resource: 'workflow',
resourceName: workflowName,
});
}
}
exports.WorkflowBase = WorkflowBase;
/**
* This module defines a construct for creating and managing AWS Glue Workflows and Triggers.
*
* AWS Glue Workflows are orchestration services that allow you to create, manage, and monitor complex extract, transform, and load (ETL) activities involving multiple crawlers, jobs, and triggers. Workflows are designed to allow you to manage interdependent jobs and crawlers as a single unit, making it easier to orchestrate and monitor complex ETL pipelines.
*
* Triggers are used to initiate an AWS Glue Workflow. You can configure different types of triggers, such as on-demand, scheduled, event-based, or conditional triggers, to start your Workflow based on specific conditions or events.
*
* @see https://docs.aws.amazon.com/glue/latest/dg/workflows_overview.html
* @see https://docs.aws.amazon.com/glue/latest/dg/about-triggers.html
*
* ## Usage Example
*
* ```ts
* const app = new App();
* const stack = new Stack(app, 'TestStack');
*
* // Create a Glue Job
* declare const role: iam.IRole;
* declare const script: glue.Code;
* const job = new glue.PySparkStreamingJob(stack, 'ImportedJob', { role, script });
*
* // Create a Glue Workflow
* const workflow = new glue.Workflow(stack, 'TestWorkflow');
*
* // Add an on-demand trigger to the Workflow
* workflow.addOnDemandTrigger('OnDemandTrigger', {
* actions: [{ job: job }],
* });
* ```
*/
let Workflow = (() => {
let _classDecorators = [prop_injectable_1.propertyInjectable];
let _classDescriptor;
let _classExtraInitializers = [];
let _classThis;
let _classSuper = WorkflowBase;
var Workflow = class extends _classSuper {
static { _classThis = this; }
static {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
Workflow = _classThis = _classDescriptor.value;
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
}
static [JSII_RTTI_SYMBOL_1] = { fqn: "@aws-cdk/aws-glue-alpha.Workflow", version: "2.225.0-alpha.0" };
/** Uniquely identifies this class. */
static PROPERTY_INJECTION_ID = '@aws-cdk.aws-glue-alpha.Workflow';
/**
* Import a workflow from its name
*/
static fromWorkflowName(scope, id, workflowName) {
return this.fromWorkflowAttributes(scope, id, {
workflowName,
});
}
/**
* Import an workflow from it's name
*/
static fromWorkflowArn(scope, id, workflowArn) {
return this.fromWorkflowAttributes(scope, id, {
workflowName: this.extractNameFromArn(scope, workflowArn),
workflowArn,
});
}
/**
* Import an existing workflow
*/
static fromWorkflowAttributes(scope, id, attrs) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_glue_alpha_WorkflowAttributes(attrs);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.fromWorkflowAttributes);
}
throw error;
}
class Import extends WorkflowBase {
workflowName = attrs.workflowName;
workflowArn = this.buildWorkflowArn(scope, this.workflowName);
}
return new Import(scope, id);
}
workflowName;
workflowArn;
constructor(scope, id, props) {
super(scope, id, {
physicalName: props?.workflowName,
});
try {
jsiiDeprecationWarnings._aws_cdk_aws_glue_alpha_WorkflowProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, Workflow);
}
throw error;
}
// Enhanced CDK Analytics Telemetry
(0, metadata_resource_1.addConstructMetadata)(this, props);
const resource = new aws_glue_1.CfnWorkflow(this, 'Resource', {
name: this.physicalName,
description: props?.description,
defaultRunProperties: props?.defaultRunProperties,
maxConcurrentRuns: props?.maxConcurrentRuns,
});
this.workflowName = this.getResourceNameAttribute(resource.ref);
this.workflowArn = this.buildWorkflowArn(this, this.workflowName);
}
static {
__runInitializers(_classThis, _classExtraInitializers);
}
};
return Workflow = _classThis;
})();
exports.Workflow = Workflow;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29ya2Zsb3cuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ3b3JrZmxvdy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSx3Q0FBd0M7QUFFeEMsbURBQStEO0FBQy9ELDRDQUdzQjtBQUN0Qix1REFTMkI7QUFDM0IsOEVBQThFO0FBQzlFLDBFQUEwRTtBQTJGMUU7Ozs7R0FJRztBQUNILE1BQXNCLFlBQWEsU0FBUSxHQUFHLENBQUMsUUFBUTs7SUFDckQ7O09BRUc7SUFDTyxNQUFNLENBQUMsa0JBQWtCLENBQUMsS0FBMkIsRUFBRSxXQUFtQjtRQUNsRixPQUFPLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLFFBQVEsQ0FDakMsV0FBVyxFQUNYLEdBQUcsQ0FBQyxTQUFTLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxZQUFhLENBQUM7S0FDcEQ7SUFLRDs7Ozs7OztPQU9HO0lBQ0ksa0JBQWtCLENBQUMsRUFBVSxFQUFFLE9BQStCOzs7Ozs7Ozs7O1FBQ25FLE1BQU0sT0FBTyxHQUFHLElBQUkscUJBQVUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxFQUFFO1lBQ3ZDLEdBQUcsT0FBTztZQUNWLFlBQVksRUFBRSxJQUFJLENBQUMsWUFBWTtZQUMvQixJQUFJLEVBQUUsV0FBVztZQUNqQixPQUFPLEVBQUUsT0FBTyxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDM0QsV0FBVyxFQUFFLE9BQU8sQ0FBQyxXQUFXLElBQUksU0FBUztTQUM5QyxDQUFDLENBQUM7UUFFSCxPQUFPLE9BQU8sQ0FBQztLQUNoQjtJQUVEOzs7Ozs7O09BT0c7SUFDSSx3QkFBd0IsQ0FBQyxFQUFVLEVBQUUsT0FBb0M7Ozs7Ozs7Ozs7UUFDOUUsTUFBTSxhQUFhLEdBQUcsaUNBQWUsQ0FBQyxJQUFJLENBQUM7WUFDekMsTUFBTSxFQUFFLEdBQUc7WUFDWCxJQUFJLEVBQUUsR0FBRztTQUNWLENBQUMsQ0FBQztRQUVILE1BQU0sT0FBTyxHQUFHLElBQUkscUJBQVUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxFQUFFO1lBQ3ZDLEdBQUcsT0FBTztZQUNWLFlBQVksRUFBRSxJQUFJLENBQUMsWUFBWTtZQUMvQixJQUFJLEVBQUUsV0FBVztZQUNqQixPQUFPLEVBQUUsT0FBTyxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDM0QsUUFBUSxFQUFFLGFBQWEsQ0FBQyxnQkFBZ0I7WUFDeEMsZUFBZSxFQUFFLE9BQU8sQ0FBQyxlQUFlLElBQUksS0FBSztTQUNsRCxDQUFDLENBQUM7UUFFSCxPQUFPLE9BQU8sQ0FBQztLQUNoQjtJQUVEOzs7Ozs7O09BT0c7SUFDSSx5QkFBeUIsQ0FBQyxFQUFVLEVBQUUsT0FBcUM7Ozs7Ozs7Ozs7UUFDaEYsTUFBTSxjQUFjLEdBQUcsaUNBQWUsQ0FBQyxJQUFJLENBQUM7WUFDMUMsTUFBTSxFQUFFLEdBQUc7WUFDWCxJQUFJLEVBQUUsR0FBRztZQUNULE9BQU8sRUFBRSxLQUFLO1NBQ2YsQ0FBQyxDQUFDO1FBRUgsTUFBTSxPQUFPLEdBQUcsSUFBSSxxQkFBVSxDQUFDLElBQUksRUFBRSxFQUFFLEVBQUU7WUFDdkMsR0FBRyxPQUFPO1lBQ1YsWUFBWSxFQUFFLElBQUksQ0FBQyxZQUFZO1lBQy9CLElBQUksRUFBRSxXQUFXO1lBQ2pCLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUMzRCxRQUFRLEVBQUUsY0FBYyxDQUFDLGdCQUFnQjtZQUN6QyxlQUFlLEVBQUUsT0FBTyxDQUFDLGVBQWUsSUFBSSxLQUFLO1NBQ2xELENBQUMsQ0FBQztRQUVILE9BQU8sT0FBTyxDQUFDO0tBQ2hCO0lBRUQ7Ozs7Ozs7T0FPRztJQUNJLHlCQUF5QixDQUFDLEVBQVUsRUFBRSxPQUFzQzs7Ozs7Ozs7OztRQUNqRixNQUFNLE9BQU8sR0FBRyxJQUFJLHFCQUFVLENBQUMsSUFBSSxFQUFFLEVBQUUsRUFBRTtZQUN2QyxHQUFHLE9BQU87WUFDVixZQUFZLEVBQUUsSUFBSSxDQUFDLFlBQVk7WUFDL0IsSUFBSSxFQUFFLFdBQVc7WUFDakIsT0FBTyxFQUFFLE9BQU8sQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzNELFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUSxDQUFDLGdCQUFnQjtZQUMzQyxlQUFlLEVBQUUsT0FBTyxDQUFDLGVBQWUsSUFBSSxLQUFLO1NBQ2xELENBQUMsQ0FBQztRQUVILE9BQU8sT0FBTyxDQUFDO0tBQ2hCO0lBRUQ7Ozs7Ozs7T0FPRztJQUNJLHFCQUFxQixDQUFDLEVBQVUsRUFBRSxPQUFrQzs7Ozs7Ozs7OztRQUN6RSxNQUFNLE9BQU8sR0FBRyxJQUFJLHFCQUFVLENBQUMsSUFBSSxFQUFFLEVBQUUsRUFBRTtZQUN2QyxHQUFHLE9BQU87WUFDVixZQUFZLEVBQUUsSUFBSSxDQUFDLFlBQVk7WUFDL0IsSUFBSSxFQUFFLE9BQU87WUFDYixPQUFPLEVBQUUsT0FBTyxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDM0Qsc0JBQXNCLEVBQUUsSUFBSSxDQUFDLDRCQUE0QixDQUFDLE9BQU8sQ0FBQztZQUNsRSxXQUFXLEVBQUUsT0FBTyxDQUFDLFdBQVcsSUFBSSxTQUFTO1NBQzlDLENBQUMsQ0FBQztRQUVILE9BQU8sT0FBTyxDQUFDO0tBQ2hCO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSSxxQkFBcUIsQ0FBQyxFQUFVLEVBQUUsT0FBa0M7Ozs7Ozs7Ozs7UUFDekUsTUFBTSxPQUFPLEdBQUcsSUFBSSxxQkFBVSxDQUFDLElBQUksRUFBRSxFQUFFLEVBQUU7WUFDdkMsR0FBRyxPQUFPO1lBQ1YsWUFBWSxFQUFFLElBQUksQ0FBQyxZQUFZO1lBQy9CLElBQUksRUFBRSxhQUFhO1lBQ25CLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUMzRCxTQUFTLEVBQUUsSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPLENBQUM7WUFDeEMsc0JBQXNCLEVBQUUsSUFBSSxDQUFDLDRCQUE0QixDQUFDLE9BQU8sQ0FBQztZQUNsRSxXQUFXLEVBQUUsT0FBTyxDQUFDLFdBQVcsSUFBSSxTQUFTO1NBQzlDLENBQUMsQ0FBQztRQUVILE9BQU8sT0FBTyxDQUFDO0tBQ2hCO0lBRU8sWUFBWSxDQUFDLE1BQWM7UUFDakMsZ0VBQWdFO1FBQ2hFLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ25DLE1BQU0sSUFBSSxHQUFHLENBQUMsZUFBZSxDQUFDLDREQUE0RCxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3BHLENBQUM7YUFBTSxJQUFJLE1BQU0sQ0FBQyxHQUFHLElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3hDLE1BQU0sSUFBSSxHQUFHLENBQUMsZUFBZSxDQUFDLDZEQUE2RCxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3JHLENBQUM7UUFFRCxPQUFPO1lBQ0wsT0FBTyxFQUFFLE1BQU0sQ0FBQyxHQUFHLEVBQUUsT0FBTztZQUM1QixTQUFTLEVBQUUsTUFBTSxDQUFDLFNBQVM7WUFDM0IsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPLEVBQUUsU0FBUyxFQUFFO1lBQ3BDLHFCQUFxQixFQUFFLE1BQU0sQ0FBQyxxQkFBcUIsRUFBRSx5QkFBeUI7WUFDOUUsV0FBVyxFQUFFLE1BQU0sQ0FBQyxPQUFPLEVBQUUsSUFBSTtTQUNsQyxDQUFDO0tBQ0g7SUFFTyxlQUFlLENBQUMsS0FBZ0M7UUFDdEQsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxVQUFVLEVBQUUsR0FBRyxDQUFDLFNBQVMsQ0FBQyxFQUFFO1lBQzdELGdFQUFnRTtZQUNoRSxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDN0MsTUFBTSxJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUMsK0RBQStELEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDdkcsQ0FBQztpQkFBTSxJQUFJLFNBQVMsQ0FBQyxHQUFHLElBQUksU0FBUyxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUNsRCxNQUFNLElBQUksR0FBRyxDQUFDLGVBQWUsQ0FBQyxnRUFBZ0UsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUN4RyxDQUFDO1lBRUQsK0RBQStEO1lBQy9ELElBQUksU0FBUyxDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDdEMsTUFBTSxJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUMsNEVBQTRFLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDcEgsQ0FBQztZQUVELHVFQUF1RTtZQUN2RSxJQUFJLFNBQVMsQ0FBQyxXQUFXLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxFQUFFLENBQUM7Z0JBQ25ELE1BQU0sSUFBSSxHQUFHLENBQUMsZUFBZSxDQUFDLG9GQUFvRixFQUFFLElBQUksQ0FBQyxDQUFDO1lBQzVILENBQUM7WUFFRCxPQUFPO2dCQUNMLGVBQWUsRUFBRSxTQUFTLENBQUMsZUFBZSxJQUFJLG9DQUF3QixDQUFDLE1BQU07Z0JBQzdFLE9BQU8sRUFBRSxTQUFTLENBQUMsR0FBRyxFQUFFLE9BQU8sSUFBSSxTQUFTO2dCQUM1QyxLQUFLLEVBQUUsU0FBUyxDQUFDLEtBQUssSUFBSSxTQUFTO2dCQUNuQyxXQUFXLEVBQUUsU0FBUyxDQUFDLFdBQVcsSUFBSSxTQUFTO2dCQUMvQyxVQUFVLEVBQUUsU0FBUyxDQUFDLFVBQVUsSUFBSSxTQUFTO2FBQzlDLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztRQUVILE9BQU87WUFDTCxPQUFPLEVBQUUsS0FBSyxDQUFDLFNBQVMsQ0FBQyxVQUFVLEVBQUUsTUFBTSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLE9BQU8sSUFBSSw0QkFBZ0IsQ0FBQyxHQUFHO1lBQy9HLFVBQVUsRUFBRSxVQUFVO1NBQ3ZCLENBQUM7S0FDSDtJQUVPLDRCQUE0QixDQUFDLEtBQWdDO1FBQ25FLE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxDQUFDO1FBQzNCLE1BQU0sa0JBQWtCLEdBQUcsR0FBRyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUM7UUFFakUsSUFBSSxDQUFDLEtBQUssQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1lBQ2xDLE9BQU87Z0JBQ0wsU0FBUyxFQUFFLGdCQUFnQjtnQkFDM0IsV0FBVyxFQUFFLGtCQUFrQjthQUNoQyxDQUFDO1FBQ0osQ0FBQztRQUVELE9BQU87WUFDTCxTQUFTLEVBQUUsS0FBSyxDQUFDLHNCQUFzQixDQUFDLFNBQVMsSUFBSSxnQkFBZ0I7WUFDckUsV0FBVyxFQUFFLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxXQUFXLEVBQUUsU0FBUyxFQUFFLElBQUksa0JBQWtCO1NBQ3pGLENBQUM7S0FDSDtJQUVTLGdCQUFnQixDQUFDLEtBQTJCLEVBQUUsWUFBb0I7UUFDMUUsT0FBTyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxTQUFTLENBQUM7WUFDbkMsT0FBTyxFQUFFLE1BQU07WUFDZixRQUFRLEVBQUUsVUFBVTtZQUNwQixZQUFZLEVBQUUsWUFBWTtTQUMzQixDQUFDLENBQUM7S0FDSjs7QUFqT0gsb0NBa09DO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBNkJHO0lBRVUsUUFBUTs0QkFEcEIsb0NBQWtCOzs7O3NCQUNXLFlBQVk7d0JBQXBCLFNBQVEsV0FBWTs7OztZQUExQyw2S0F1REM7Ozs7O1FBdERDLHNDQUFzQztRQUMvQixNQUFNLENBQVUscUJBQXFCLEdBQVcsa0NBQWtDLENBQUM7UUFFMUY7O1dBRUc7UUFDSSxNQUFNLENBQUMsZ0JBQWdCLENBQUMsS0FBMkIsRUFBRSxFQUFVLEVBQUUsWUFBb0I7WUFDMUYsT0FBTyxJQUFJLENBQUMsc0JBQXNCLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRTtnQkFDNUMsWUFBWTthQUNiLENBQUMsQ0FBQztTQUNKO1FBRUQ7O1dBRUc7UUFDSSxNQUFNLENBQUMsZUFBZSxDQUFDLEtBQTJCLEVBQUUsRUFBVSxFQUFFLFdBQW1CO1lBQ3hGLE9BQU8sSUFBSSxDQUFDLHNCQUFzQixDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUU7Z0JBQzVDLFlBQVksRUFBRSxJQUFJLENBQUMsa0JBQWtCLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQztnQkFDekQsV0FBVzthQUNaLENBQUMsQ0FBQztTQUNKO1FBRUQ7O1dBRUc7UUFDSSxNQUFNLENBQUMsc0JBQXNCLENBQUMsS0FBMkIsRUFBRSxFQUFVLEVBQUUsS0FBeUI7Ozs7Ozs7Ozs7WUFDckcsTUFBTSxNQUFPLFNBQVEsWUFBWTtnQkFDZixZQUFZLEdBQUcsS0FBSyxDQUFDLFlBQVksQ0FBQztnQkFDbEMsV0FBVyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO2FBQy9FO1lBRUQsT0FBTyxJQUFJLE1BQU0sQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7U0FDOUI7UUFFZSxZQUFZLENBQVM7UUFDckIsV0FBVyxDQUFTO1FBRXBDLFlBQVksS0FBMkIsRUFBRSxFQUFVLEVBQUUsS0FBcUI7WUFDeEUsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUU7Z0JBQ2YsWUFBWSxFQUFFLEtBQUssRUFBRSxZQUFZO2FBQ2xDLENBQUMsQ0FBQzs7Ozs7O21EQXpDTSxRQUFROzs7O1lBMENqQixtQ0FBbUM7WUFDbkMsSUFBQSx3Q0FBb0IsRUFBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFFbEMsTUFBTSxRQUFRLEdBQUcsSUFBSSxzQkFBVyxDQUFDLElBQUksRUFBRSxVQUFVLEVBQUU7Z0JBQ2pELElBQUksRUFBRSxJQUFJLENBQUMsWUFBWTtnQkFDdkIsV0FBVyxFQUFFLEtBQUssRUFBRSxXQUFXO2dCQUMvQixvQkFBb0IsRUFBRSxLQUFLLEVBQUUsb0JBQW9CO2dCQUNqRCxpQkFBaUIsRUFBRSxLQUFLLEVBQUUsaUJBQWlCO2FBQzVDLENBQUMsQ0FBQztZQUVILElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLHdCQUF3QixDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNoRSxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1NBQ25FOztZQXREVSx1REFBUTs7Ozs7QUFBUiw0QkFBUSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGNkayBmcm9tICdhd3MtY2RrLWxpYi9jb3JlJztcbmltcG9ydCAqIGFzIGNvbnN0cnVjdHMgZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBDZm5Xb3JrZmxvdywgQ2ZuVHJpZ2dlciB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1nbHVlJztcbmltcG9ydCB7XG4gIENvbmRpdGlvbkxvZ2ljYWxPcGVyYXRvcixcbiAgUHJlZGljYXRlTG9naWNhbCxcbn0gZnJvbSAnLi4vY29uc3RhbnRzJztcbmltcG9ydCB7XG4gIEFjdGlvbixcbiAgVHJpZ2dlclNjaGVkdWxlLFxuICBPbkRlbWFuZFRyaWdnZXJPcHRpb25zLFxuICBXZWVrbHlTY2hlZHVsZVRyaWdnZXJPcHRpb25zLFxuICBEYWlseVNjaGVkdWxlVHJpZ2dlck9wdGlvbnMsXG4gIEN1c3RvbVNjaGVkdWxlZFRyaWdnZXJPcHRpb25zLFxuICBOb3RpZnlFdmVudFRyaWdnZXJPcHRpb25zLFxuICBDb25kaXRpb25hbFRyaWdnZXJPcHRpb25zLFxufSBmcm9tICcuL3RyaWdnZXItb3B0aW9ucyc7XG5pbXBvcnQgeyBhZGRDb25zdHJ1Y3RNZXRhZGF0YSB9IGZyb20gJ2F3cy1jZGstbGliL2NvcmUvbGliL21ldGFkYXRhLXJlc291cmNlJztcbmltcG9ydCB7IHByb3BlcnR5SW5qZWN0YWJsZSB9IGZyb20gJ2F3cy1jZGstbGliL2NvcmUvbGliL3Byb3AtaW5qZWN0YWJsZSc7XG5cbi8qKlxuICogVGhlIGJhc2UgaW50ZXJmYWNlIGZvciBHbHVlIFdvcmtmbG93XG4gKlxuICogQHNlZSB7QGxpbmsgV29ya2Zsb3d9XG4gKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9nbHVlL2xhdGVzdC9kZy93b3JrZmxvd3Nfb3ZlcnZpZXcuaHRtbFxuICovXG5leHBvcnQgaW50ZXJmYWNlIElXb3JrZmxvdyBleHRlbmRzIGNkay5JUmVzb3VyY2Uge1xuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIHdvcmtmbG93XG4gICAqIEBhdHRyaWJ1dGVcbiAgICovXG4gIHJlYWRvbmx5IHdvcmtmbG93TmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgQVJOIG9mIHRoZSB3b3JrZmxvd1xuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICByZWFkb25seSB3b3JrZmxvd0Fybjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBZGQgYW4gb24tZGVtYW5kIHRyaWdnZXIgdG8gdGhlIHdvcmtmbG93XG4gICAqL1xuICBhZGRPbkRlbWFuZFRyaWdnZXIoaWQ6IHN0cmluZywgb3B0aW9uczogT25EZW1hbmRUcmlnZ2VyT3B0aW9ucyk6IENmblRyaWdnZXI7XG5cbiAgLyoqXG4gICAqIEFkZCBhbiBkYWlseS1zY2hlZHVsZWQgdHJpZ2dlciB0byB0aGUgd29ya2Zsb3dcbiAgICovXG4gIGFkZERhaWx5U2NoZWR1bGVkVHJpZ2dlcihpZDogc3RyaW5nLCBvcHRpb25zOiBEYWlseVNjaGVkdWxlVHJpZ2dlck9wdGlvbnMpOiBDZm5UcmlnZ2VyO1xuXG4gIC8qKlxuICAgKiBBZGQgYW4gd2Vla2x5LXNjaGVkdWxlZCB0cmlnZ2VyIHRvIHRoZSB3b3JrZmxvd1xuICAgKi9cbiAgYWRkV2Vla2x5U2NoZWR1bGVkVHJpZ2dlcihpZDogc3RyaW5nLCBvcHRpb25zOiBXZWVrbHlTY2hlZHVsZVRyaWdnZXJPcHRpb25zKTogQ2ZuVHJpZ2dlcjtcblxuICAvKipcbiAgICogQWRkIGFuIGN1c3RvbS1zY2hlZHVsZWQgdHJpZ2dlciB0byB0aGUgd29ya2Zsb3dcbiAgICovXG4gIGFkZEN1c3RvbVNjaGVkdWxlZFRyaWdnZXIoaWQ6IHN0cmluZywgb3B0aW9uczogQ3VzdG9tU2NoZWR1bGVkVHJpZ2dlck9wdGlvbnMpOiBDZm5UcmlnZ2VyO1xufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIGltcG9ydGluZyBhIFdvcmtmbG93IHVzaW5nIGl0cyBhdHRyaWJ1dGVzXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgV29ya2Zsb3dBdHRyaWJ1dGVzIHtcbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSB3b3JrZmxvdyB0byBpbXBvcnRcbiAgICovXG4gIHJlYWRvbmx5IHdvcmtmbG93TmFtZTogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIEFSTiBvZiB0aGUgd29ya2Zsb3cgdG8gaW1wb3J0XG4gICAqXG4gICAqIEBkZWZhdWx0IC0gZGVyaXZlZCBmcm9tIHRoZSB3b3JrZmxvdyBuYW1lXG4gICAqL1xuICByZWFkb25seSB3b3JrZmxvd0Fybj86IHN0cmluZztcbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBkZWZpbmluZyBhIFdvcmtmbG93XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgV29ya2Zsb3dQcm9wcyB7XG4gIC8qKlxuICAgKiBOYW1lIG9mIHRoZSB3b3JrZmxvd1xuICAgKlxuICAgKiBAZGVmYXVsdCAtIGEgbmFtZSB3aWxsIGJlIGdlbmVyYXRlZFxuICAgKi9cbiAgcmVhZG9ubHkgd29ya2Zsb3dOYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBIGRlc2NyaXB0aW9uIG9mIHRoZSB3b3JrZmxvd1xuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGRlc2NyaXB0aW9uXG4gICAqL1xuICByZWFkb25seSBkZXNjcmlwdGlvbj86IHN0cmluZztcblxuICAvKipcbiAgICogQSBtYXAgb2YgcHJvcGVydGllcyB0byB1c2Ugd2hlbiB0aGlzIHdvcmtmbG93IGlzIGV4ZWN1dGVkXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gZGVmYXVsdCBydW4gcHJvcGVydGllc1xuICAgKi9cbiAgcmVhZG9ubHkgZGVmYXVsdFJ1blByb3BlcnRpZXM/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xuXG4gIC8qKlxuICAgKiBUaGUgbWF4aW11bSBudW1iZXIgb2YgY29uY3VycmVudCBydW5zIGFsbG93ZWQgZm9yIHRoZSB3b3JrZmxvd1xuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGxpbWl0XG4gICAqL1xuICByZWFkb25seSBtYXhDb25jdXJyZW50UnVucz86IG51bWJlcjtcbn1cblxuLyoqXG4gKiBCYXNlIGFic3RyYWN0IGNsYXNzIGZvciBXb3JrZmxvd1xuICpcbiAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2dsdWUvbGF0ZXN0L2RnL2Fib3V0LXRyaWdnZXJzLmh0bWxcbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFdvcmtmbG93QmFzZSBleHRlbmRzIGNkay5SZXNvdXJjZSBpbXBsZW1lbnRzIElXb3JrZmxvdyB7XG4gIC8qKlxuICAgKiBFeHRyYWN0IHdvcmtmbG93TmFtZSBmcm9tIGFyblxuICAgKi9cbiAgcHJvdGVjdGVkIHN0YXRpYyBleHRyYWN0TmFtZUZyb21Bcm4oc2NvcGU6IGNvbnN0cnVjdHMuQ29uc3RydWN0LCB3b3JrZmxvd0Fybjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gY2RrLlN0YWNrLm9mKHNjb3BlKS5zcGxpdEFybihcbiAgICAgIHdvcmtmbG93QXJuLFxuICAgICAgY2RrLkFybkZvcm1hdC5TTEFTSF9SRVNPVVJDRV9OQU1FKS5yZXNvdXJjZU5hbWUhO1xuICB9XG5cbiAgcHVibGljIGFic3RyYWN0IHJlYWRvbmx5IHdvcmtmbG93TmFtZTogc3RyaW5nO1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgd29ya2Zsb3dBcm46IHN0cmluZztcblxuICAvKipcbiAgICogQWRkIGFuIG9uLWRlbWFuZCB0cmlnZ2VyIHRvIHRoZSB3b3JrZmxvdy5cbiAgICpcbiAgICogQHBhcmFtIGlkIFRoZSBpZCBvZiB0aGUgdHJpZ2dlci5cbiAgICogQHBhcmFtIG9wdGlvbnMgQWRkaXRpb25hbCBvcHRpb25zIGZvciB0aGUgdHJpZ2dlci5cbiAgICogQHRocm93cyBJZiBib3RoIGpvYiBhbmQgY3Jhd2xlciBhcmUgcHJvdmlkZWQsIG9yIGlmIG5laXRoZXIgam9iIG5vciBjcmF3bGVyIGlzIHByb3ZpZGVkLlxuICAgKiBAcmV0dXJucyBUaGUgY3JlYXRlZCBDZm5UcmlnZ2VyIHJlc291cmNlLlxuICAgKi9cbiAgcHVibGljIGFkZE9uRGVtYW5kVHJpZ2dlcihpZDogc3RyaW5nLCBvcHRpb25zOiBPbkRlbWFuZFRyaWdnZXJPcHRpb25zKTogQ2ZuVHJpZ2dlciB7XG4gICAgY29uc3QgdHJpZ2dlciA9IG5ldyBDZm5UcmlnZ2VyKHRoaXMsIGlkLCB7XG4gICAgICAuLi5vcHRpb25zLFxuICAgICAgd29ya2Zsb3dOYW1lOiB0aGlzLndvcmtmbG93TmFtZSxcbiAgICAgIHR5cGU6ICdPTl9ERU1BTkQnLFxuICAgICAgYWN0aW9uczogb3B0aW9ucy5hY3Rpb25zPy5tYXAodGhpcy5yZW5kZXJBY3Rpb24uYmluZCh0aGlzKSksXG4gICAgICBkZXNjcmlwdGlvbjogb3B0aW9ucy5kZXNjcmlwdGlvbiB8fCB1bmRlZmluZWQsXG4gICAgfSk7XG5cbiAgICByZXR1cm4gdHJpZ2dlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBkYWlseS1zY2hlZHVsZWQgdHJpZ2dlciB0byB0aGUgd29ya2Zsb3cuXG4gICAqXG4gICAqIEBwYXJhbSBpZCBUaGUgaWQgb2YgdGhlIHRyaWdnZXIuXG4gICAqIEBwYXJhbSBvcHRpb25zIEFkZGl0aW9uYWwgb3B0aW9ucyBmb3IgdGhlIHRyaWdnZXIuXG4gICAqIEB0aHJvd3MgSWYgYm90aCBqb2IgYW5kIGNyYXdsZXIgYXJlIHByb3ZpZGVkLCBvciBpZiBuZWl0aGVyIGpvYiBub3IgY3Jhd2xlciBpcyBwcm92aWRlZC5cbiAgICogQHJldHVybnMgVGhlIGNyZWF0ZWQgQ2ZuVHJpZ2dlciByZXNvdXJjZS5cbiAgICovXG4gIHB1YmxpYyBhZGREYWlseVNjaGVkdWxlZFRyaWdnZXIoaWQ6IHN0cmluZywgb3B0aW9uczogRGFpbHlTY2hlZHVsZVRyaWdnZXJPcHRpb25zKTogQ2ZuVHJpZ2dlciB7XG4gICAgY29uc3QgZGFpbHlTY2hlZHVsZSA9IFRyaWdnZXJTY2hlZHVsZS5jcm9uKHtcbiAgICAgIG1pbnV0ZTogJzAnLFxuICAgICAgaG91cjogJzAnLFxuICAgIH0pO1xuXG4gICAgY29uc3QgdHJpZ2dlciA9IG5ldyBDZm5UcmlnZ2VyKHRoaXMsIGlkLCB7XG4gICAgICAuLi5vcHRpb25zLFxuICAgICAgd29ya2Zsb3dOYW1lOiB0aGlzLndvcmtmbG93TmFtZSxcbiAgICAgIHR5cGU6ICdTQ0hFRFVMRUQnLFxuICAgICAgYWN0aW9uczogb3B0aW9ucy5hY3Rpb25zPy5tYXAodGhpcy5yZW5kZXJBY3Rpb24uYmluZCh0aGlzKSksXG4gICAgICBzY2hlZHVsZTogZGFpbHlTY2hlZHVsZS5leHByZXNzaW9uU3RyaW5nLFxuICAgICAgc3RhcnRPbkNyZWF0aW9uOiBvcHRpb25zLnN0YXJ0T25DcmVhdGlvbiA/PyBmYWxzZSxcbiAgICB9KTtcblxuICAgIHJldHVybiB0cmlnZ2VyO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhIHdlZWtseS1zY2hlZHVsZWQgdHJpZ2dlciB0byB0aGUgd29ya2Zsb3cuXG4gICAqXG4gICAqIEBwYXJhbSBpZCBUaGUgaWQgb2YgdGhlIHRyaWdnZXIuXG4gICAqIEBwYXJhbSBvcHRpb25zIEFkZGl0aW9uYWwgb3B0aW9ucyBmb3IgdGhlIHRyaWdnZXIuXG4gICAqIEB0aHJvd3MgSWYgYm90aCBqb2IgYW5kIGNyYXdsZXIgYXJlIHByb3ZpZGVkLCBvciBpZiBuZWl0aGVyIGpvYiBub3IgY3Jhd2xlciBpcyBwcm92aWRlZC5cbiAgICogQHJldHVybnMgVGhlIGNyZWF0ZWQgQ2ZuVHJpZ2dlciByZXNvdXJjZS5cbiAgICovXG4gIHB1YmxpYyBhZGRXZWVrbHlTY2hlZHVsZWRUcmlnZ2VyKGlkOiBzdHJpbmcsIG9wdGlvbnM6IFdlZWtseVNjaGVkdWxlVHJpZ2dlck9wdGlvbnMpOiBDZm5UcmlnZ2VyIHtcbiAgICBjb25zdCB3ZWVrbHlTY2hlZHVsZSA9IFRyaWdnZXJTY2hlZHVsZS5jcm9uKHtcbiAgICAgIG1pbnV0ZTogJzAnLFxuICAgICAgaG91cjogJzAnLFxuICAgICAgd2Vla0RheTogJ1NVTicsXG4gICAgfSk7XG5cbiAgICBjb25zdCB0cmlnZ2VyID0gbmV3IENmblRyaWdnZXIodGhpcywgaWQsIHtcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgICB3b3JrZmxvd05hbWU6IHRoaXMud29ya2Zsb3dOYW1lLFxuICAgICAgdHlwZTogJ1NDSEVEVUxFRCcsXG4gICAgICBhY3Rpb25zOiBvcHRpb25zLmFjdGlvbnM/Lm1hcCh0aGlzLnJlbmRlckFjdGlvbi5iaW5kKHRoaXMpKSxcbiAgICAgIHNjaGVkdWxlOiB3ZWVrbHlTY2hlZHVsZS5leHByZXNzaW9uU3RyaW5nLFxuICAgICAgc3RhcnRPbkNyZWF0aW9uOiBvcHRpb25zLnN0YXJ0T25DcmVhdGlvbiA/PyBmYWxzZSxcbiAgICB9KTtcblxuICAgIHJldHVybiB0cmlnZ2VyO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhIGN1c3RvbS1zY2hlZHVsZWQgdHJpZ2dlciB0byB0aGUgd29ya2Zsb3cuXG4gICAqXG4gICAqIEBwYXJhbSBpZCBUaGUgaWQgb2YgdGhlIHRyaWdnZXIuXG4gICAqIEBwYXJhbSBvcHRpb25zIEFkZGl0aW9uYWwgb3B0aW9ucyBmb3IgdGhlIHRyaWdnZXIuXG4gICAqIEB0aHJvd3MgSWYgYm90aCBqb2IgYW5kIGNyYXdsZXIgYXJlIHByb3ZpZGVkLCBvciBpZiBuZWl0aGVyIGpvYiBub3IgY3Jhd2xlciBpcyBwcm92aWRlZC5cbiAgICogQHJldHVybnMgVGhlIGNyZWF0ZWQgQ2ZuVHJpZ2dlciByZXNvdXJjZS5cbiAgICovXG4gIHB1YmxpYyBhZGRDdXN0b21TY2hlZHVsZWRUcmlnZ2VyKGlkOiBzdHJpbmcsIG9wdGlvbnM6IEN1c3RvbVNjaGVkdWxlZFRyaWdnZXJPcHRpb25zKTogQ2ZuVHJpZ2dlciB7XG4gICAgY29uc3QgdHJpZ2dlciA9IG5ldyBDZm5UcmlnZ2VyKHRoaXMsIGlkLCB7XG4gICAgICAuLi5vcHRpb25zLFxuICAgICAgd29ya2Zsb3dOYW1lOiB0aGlzLndvcmtmbG93TmFtZSxcbiAgICAgIHR5cGU6ICdTQ0hFRFVMRUQnLFxuICAgICAgYWN0aW9uczogb3B0aW9ucy5hY3Rpb25zPy5tYXAodGhpcy5yZW5kZXJBY3Rpb24uYmluZCh0aGlzKSksXG4gICAgICBzY2hlZHVsZTogb3B0aW9ucy5zY2hlZHVsZS5leHByZXNzaW9uU3RyaW5nLFxuICAgICAgc3RhcnRPbkNyZWF0aW9uOiBvcHRpb25zLnN0YXJ0T25DcmVhdGlvbiA/PyBmYWxzZSxcbiAgICB9KTtcblxuICAgIHJldHVybiB0cmlnZ2VyO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhbiBFdmVudCBCcmlkZ2UgYmFzZWQgdHJpZ2dlciB0byB0aGUgd29ya2Zsb3cuXG4gICAqXG4gICAqIEBwYXJhbSBpZCBUaGUgaWQgb2YgdGhlIHRyaWdnZXIuXG4gICAqIEBwYXJhbSBvcHRpb25zIEFkZGl0aW9uYWwgb3B0aW9ucyBmb3IgdGhlIHRyaWdnZXIuXG4gICAqIEB0aHJvd3MgSWYgYm90aCBqb2IgYW5kIGNyYXdsZXIgYXJlIHByb3ZpZGVkLCBvciBpZiBuZWl0aGVyIGpvYiBub3IgY3Jhd2xlciBpcyBwcm92aWRlZC5cbiAgICogQHJldHVybnMgVGhlIGNyZWF0ZWQgQ2ZuVHJpZ2dlciByZXNvdXJjZS5cbiAgICovXG4gIHB1YmxpYyBhZGROb3RpZnlFdmVudFRyaWdnZXIoaWQ6IHN0cmluZywgb3B0aW9uczogTm90aWZ5RXZlbnRUcmlnZ2VyT3B0aW9ucyk6IENmblRyaWdnZXIge1xuICAgIGNvbnN0IHRyaWdnZXIgPSBuZXcgQ2ZuVHJpZ2dlcih0aGlzLCBpZCwge1xuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIHdvcmtmbG93TmFtZTogdGhpcy53b3JrZmxvd05hbWUsXG4gICAgICB0eXBlOiAnRVZFTlQnLFxuICAgICAgYWN0aW9uczogb3B0aW9ucy5hY3Rpb25zPy5tYXAodGhpcy5yZW5kZXJBY3Rpb24uYmluZCh0aGlzKSksXG4gICAgICBldmVudEJhdGNoaW5nQ29uZGl0aW9uOiB0aGlzLnJlbmRlckV2ZW50QmF0Y2hpbmdDb25kaXRpb24ob3B0aW9ucyksXG4gICAgICBkZXNjcmlwdGlvbjogb3B0aW9ucy5kZXNjcmlwdGlvbiA/PyB1bmRlZmluZWQsXG4gICAgfSk7XG5cbiAgICByZXR1cm4gdHJpZ2dlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBDb25kaXRpb24gKFByZWRpY2F0ZSkgYmFzZWQgdHJpZ2dlciB0byB0aGUgd29ya2Zsb3cuXG4gICAqXG4gICAqIEBwYXJhbSBpZCBUaGUgaWQgb2YgdGhlIHRyaWdnZXIuXG4gICAqIEBwYXJhbSBvcHRpb25zIEFkZGl0aW9uYWwgb3B0aW9ucyBmb3IgdGhlIHRyaWdnZXIuXG4gICAqIEB0aHJvd3MgSWYgYm90aCBqb2IgYW5kIGNyYXdsZXIgYXJlIHByb3ZpZGVkLCBvciBpZiBuZWl0aGVyIGpvYiBub3IgY3Jhd2xlciBpcyBwcm92aWRlZCBmb3IgYW55IGNvbmRpdGlvbi5cbiAgICogQHRocm93cyBJZiBhIGpvYiBpcyBwcm92aWRlZCB3aXRob3V0IGEgam9iIHN0YXRlLCBvciBpZiBhIGNyYXdsZXIgaXMgcHJvdmlkZWQgd2l0aG91dCBhIGNyYXdsZXIgc3RhdGUgZm9yIGFueSBjb25kaXRpb24uXG4gICAqIEByZXR1cm5zIFRoZSBjcmVhdGVkIENmblRyaWdnZXIgcmVzb3VyY2UuXG4gICAqL1xuICBwdWJsaWMgYWRkQ29uZGl0aW9uYWxUcmlnZ2VyKGlkOiBzdHJpbmcsIG9wdGlvbnM6IENvbmRpdGlvbmFsVHJpZ2dlck9wdGlvbnMpOiBDZm5UcmlnZ2VyIHtcbiAgICBjb25zdCB0cmlnZ2VyID0gbmV3IENmblRyaWdnZXIodGhpcywgaWQsIHtcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgICB3b3JrZmxvd05hbWU6IHRoaXMud29ya2Zsb3dOYW1lLFxuICAgICAgdHlwZTogJ0NPTkRJVElPTkFMJyxcbiAgICAgIGFjdGlvbnM6IG9wdGlvbnMuYWN0aW9ucz8ubWFwKHRoaXMucmVuZGVyQWN0aW9uLmJpbmQodGhpcykpLFxuICAgICAgcHJlZGljYXRlOiB0aGlzLnJlbmRlclByZWRpY2F0ZShvcHRpb25zKSxcbiAgICAgIGV2ZW50QmF0Y2hpbmdDb25kaXRpb246IHRoaXMucmVuZGVyRXZlbnRCYXRjaGluZ0NvbmRpdGlvbihvcHRpb25zKSxcbiAgICAgIGRlc2NyaXB0aW9uOiBvcHRpb25zLmRlc2NyaXB0aW9uID8/IHVuZGVmaW5lZCxcbiAgICB9KTtcblxuICAgIHJldHVybiB0cmlnZ2VyO1xuICB9XG5cbiAgcHJpdmF0ZSByZW5kZXJBY3Rpb24oYWN0aW9uOiBBY3Rpb24pOiBDZm5UcmlnZ2VyLkFjdGlvblByb3BlcnR5IHtcbiAgICAvLyBWYWxpZGF0ZSB0aGF0IGVpdGhlciBqb2Igb3IgY3Jhd2xlciBpcyBwcm92aWRlZCwgYnV0IG5vdCBib3RoXG4gICAgaWYgKCFhY3Rpb24uam9iICYmICFhY3Rpb24uY3Jhd2xlcikge1xuICAgICAgdGhyb3cgbmV3IGNkay5WYWxpZGF0aW9uRXJyb3IoJ1lvdSBtdXN0IHByb3ZpZGUgZWl0aGVyIGEgam9iIG9yIGEgY3Jhd2xlciBmb3IgdGhlIGFjdGlvbi4nLCB0aGlzKTtcbiAgICB9IGVsc2UgaWYgKGFjdGlvbi5qb2IgJiYgYWN0aW9uLmNyYXdsZXIpIHtcbiAgICAgIHRocm93IG5ldyBjZGsuVmFsaWRhdGlvbkVycm9yKCdZb3UgY2Fubm90IHByb3ZpZGUgYm90aCBhIGpvYiBhbmQgYSBjcmF3bGVyIGZvciB0aGUgYWN0aW9uLicsIHRoaXMpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBqb2JOYW1lOiBhY3Rpb24uam9iPy5qb2JOYW1lLFxuICAgICAgYXJndW1lbnRzOiBhY3Rpb24uYXJndW1lbnRzLFxuICAgICAgdGltZW91dDogYWN0aW9uLnRpbWVvdXQ/LnRvTWludXRlcygpLFxuICAgICAgc2VjdXJpdHlDb25maWd1cmF0aW9uOiBhY3Rpb24uc2VjdXJpdHlDb25maWd1cmF0aW9uPy5zZWN1cml0eUNvbmZpZ3VyYXRpb25OYW1lLFxuICAgICAgY3Jhd2xlck5hbWU6IGFjdGlvbi5jcmF3bGVyPy5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIHJlbmRlclByZWRpY2F0ZShwcm9wczogQ29uZGl0aW9uYWxUcmlnZ2VyT3B0aW9ucyk6IENmblRyaWdnZXIuUHJlZGljYXRlUHJvcGVydHkge1xuICAgIGNvbnN0IGNvbmRpdGlvbnMgPSBwcm9wcy5wcmVkaWNhdGUuY29uZGl0aW9ucz8ubWFwKGNvbmRpdGlvbiA9PiB7XG4gICAgICAvLyBWYWxpZGF0ZSB0aGF0IGVpdGhlciBqb2Igb3IgY3Jhd2xlciBpcyBwcm92aWRlZCwgYnV0IG5vdCBib3RoXG4gICAgICBpZiAoIWNvbmRpdGlvbi5qb2IgJiYgIWNvbmRpdGlvbi5jcmF3bGVyTmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgY2RrLlZhbGlkYXRpb25FcnJvcignWW91IG11c3QgcHJvdmlkZSBlaXRoZXIgYSBqb2Igb3IgYSBjcmF3bGVyIGZvciB0aGUgY29uZGl0aW9uLicsIHRoaXMpO1xuICAgICAgfSBlbHNlIGlmIChjb25kaXRpb24uam9iICYmIGNvbmRpdGlvbi5jcmF3bGVyTmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgY2RrLlZhbGlkYXRpb25FcnJvcignWW91IGNhbm5vdCBwcm92aWRlIGJvdGggYSBqb2IgYW5kIGEgY3Jhd2xlciBmb3IgdGhlIGNvbmRpdGlvbi4nLCB0aGlzKTtcbiAgICAgIH1cblxuICAgICAgLy8gVmFsaWRhdGUgdGhhdCBpZiBqb2IgaXMgcHJvdmlkZWQsIGpvYiBzdGF0ZSBpcyBhbHNvIHByb3ZpZGVkXG4gICAgICBpZiAoY29uZGl0aW9uLmpvYiAmJiAhY29uZGl0aW9uLnN0YXRlKSB7XG4gICAgICAgIHRocm93IG5ldyBjZGsuVmFsaWRhdGlvbkVycm9yKCdJZiB5b3UgcHJvdmlkZSBhIGpvYiBmb3IgdGhlIGNvbmRpdGlvbiwgeW91IG11c3QgYWxzbyBwcm92aWRlIGEgam9iIHN0YXRlLicsIHRoaXMpO1xuICAgICAgfVxuXG4gICAgICAvLyBWYWxpZGF0ZSB0aGF0IGlmIGNyYXdsZXIgaXMgcHJvdmlkZWQsIGNyYXdsZXIgc3RhdGUgaXMgYWxzbyBwcm92aWRlZFxuICAgICAgaWYgKGNvbmRpdGlvbi5jcmF3bGVyTmFtZSAmJiAhY29uZGl0aW9uLmNyYXdsU3RhdGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IGNkay5WYWxpZGF0aW9uRXJyb3IoJ0lmIHlvdSBwcm92aWRlIGEgY3Jhd2xlciBmb3IgdGhlIGNvbmRpdGlvbiwgeW91IG11c3QgYWxzbyBwcm92aWRlIGEgY3Jhd2xlciBzdGF0ZS4nLCB0aGlzKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbG9naWNhbE9wZXJhdG9yOiBjb25kaXRpb24ubG9naWNhbE9wZXJhdG9yID8/IENvbmRpdGlvbkxvZ2ljYWxPcGVyYXRvci5FUVVBTFMsXG4gICAgICAgIGpvYk5hbWU6IGNvbmRpdGlvbi5qb2I/LmpvYk5hbWUgPz8gdW5kZWZpbmVkLFxuICAgICAgICBzdGF0ZTogY29uZGl0aW9uLnN0YXRlID8/IHVuZGVmaW5lZCxcbiAgICAgICAgY3Jhd2xlck5hbWU6IGNvbmRpdGlvbi5jcmF3bGVyTmFtZSA/PyB1bmRlZmluZWQsXG4gICAgICAgIGNyYXdsU3RhdGU6IGNvbmRpdGlvbi5jcmF3bFN0YXRlID8/IHVuZGVmaW5lZCxcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgbG9naWNhbDogcHJvcHMucHJlZGljYXRlLmNvbmRpdGlvbnM/Lmxlbmd0aCA9PT0gMSA/IHVuZGVmaW5lZCA6IHByb3BzLnByZWRpY2F0ZS5sb2dpY2FsID8/IFByZWRpY2F0ZUxvZ2ljYWwuQU5ELFxuICAgICAgY29uZGl0aW9uczogY29uZGl0aW9ucyxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSByZW5kZXJFdmVudEJhdGNoaW5nQ29uZGl0aW9uKHByb3BzOiBOb3RpZnlFdmVudFRyaWdnZXJPcHRpb25zKTogQ2ZuVHJpZ2dlci5FdmVudEJhdGNoaW5nQ29uZGl0aW9uUHJvcGVydHkge1xuICAgIGNvbnN0IGRlZmF1bHRCYXRjaFNpemUgPSAxO1xuICAgIGNvbnN0IGRlZmF1bHRCYXRjaFdpbmRvdyA9IGNkay5EdXJhdGlvbi5zZWNvbmRzKDkwMCkudG9TZWNvbmRzKCk7XG5cbiAgICBpZiAoIXByb3BzLmV2ZW50QmF0Y2hpbmdDb25kaXRpb24pIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGJhdGNoU2l6ZTogZGVmYXVsdEJhdGNoU2l6ZSxcbiAgICAgICAgYmF0Y2hXaW5kb3c6IGRlZmF1bHRCYXRjaFdpbmRvdyxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGJhdGNoU2l6ZTogcHJvcHMuZXZlbnRCYXRjaGluZ0NvbmRpdGlvbi5iYXRjaFNpemUgfHwgZGVmYXVsdEJhdGNoU2l6ZSxcbiAgICAgIGJhdGNoV2luZG93OiBwcm9wcy5ldmVudEJhdGNoaW5nQ29uZGl0aW9uLmJhdGNoV2luZG93Py50b1NlY29uZHMoKSB8fCBkZWZhdWx0QmF0Y2hXaW5kb3csXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBidWlsZFdvcmtmbG93QXJuKHNjb3BlOiBjb25zdHJ1Y3RzLkNvbnN0cnVjdCwgd29ya2Zsb3dOYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBjZGsuU3RhY2sub2Yoc2NvcGUpLmZvcm1hdEFybih7XG4gICAgICBzZXJ2aWNlOiAnZ2x1ZScsXG4gICAgICByZXNvdXJjZTogJ3dvcmtmbG93JyxcbiAgICAgIHJlc291cmNlTmFtZTogd29ya2Zsb3dOYW1lLFxuICAgIH0pO1xuICB9XG59XG5cbi8qKlxuICogVGhpcyBtb2R1bGUgZGVmaW5lcyBhIGNvbnN0cnVjdCBmb3IgY3JlYXRpbmcgYW5kIG1hbmFnaW5nIEFXUyBHbHVlIFdvcmtmbG93cyBhbmQgVHJpZ2dlcnMuXG4gKlxuICogQVdTIEdsdWUgV29ya2Zsb3dzIGFyZSBvcmNoZXN0cmF0aW9uIHNlcnZpY2VzIHRoYXQgYWxsb3cgeW91IHRvIGNyZWF0ZSwgbWFuYWdlLCBhbmQgbW9uaXRvciBjb21wbGV4IGV4dHJhY3QsIHRyYW5zZm9ybSwgYW5kIGxvYWQgKEVUTCkgYWN0aXZpdGllcyBpbnZvbHZpbmcgbXVsdGlwbGUgY3Jhd2xlcnMsIGpvYnMsIGFuZCB0cmlnZ2Vycy4gV29ya2Zsb3dzIGFyZSBkZXNpZ25lZCB0byBhbGxvdyB5b3UgdG8gbWFuYWdlIGludGVyZGVwZW5kZW50IGpvYnMgYW5kIGNyYXdsZXJzIGFzIGEgc2luZ2xlIHVuaXQsIG1ha2luZyBpdCBlYXNpZXIgdG8gb3JjaGVzdHJhdGUgYW5kIG1vbml0b3IgY29tcGxleCBFVEwgcGlwZWxpbmVzLlxuICpcbiAqIFRyaWdnZXJzIGFyZSB1c2VkIHRvIGluaXRpYXRlIGFuIEFXUyBHbHVlIFdvcmtmbG93LiBZb3UgY2FuIGNvbmZpZ3VyZSBkaWZmZXJlbnQgdHlwZXMgb2YgdHJpZ2dlcnMsIHN1Y2ggYXMgb24tZGVtYW5kLCBzY2hlZHVsZWQsIGV2ZW50LWJhc2VkLCBvciBjb25kaXRpb25hbCB0cmlnZ2VycywgdG8gc3RhcnQgeW91ciBXb3JrZmxvdyBiYXNlZCBvbiBzcGVjaWZpYyBjb25kaXRpb25zIG9yIGV2ZW50cy5cbiAqXG4gKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9nbHVlL2xhdGVzdC9kZy93b3JrZmxvd3Nfb3ZlcnZpZXcuaHRtbFxuICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZ2x1ZS9sYXRlc3QvZGcvYWJvdXQtdHJpZ2dlcnMuaHRtbFxuICpcbiAqICMjIFVzYWdlIEV4YW1wbGVcbiAqXG4gKiBgYGB0c1xuICogY29uc3QgYXBwID0gbmV3IEFwcCgpO1xuICogY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2soYXBwLCAnVGVzdFN0YWNrJyk7XG4gKlxuICogLy8gQ3JlYXRlIGEgR2x1ZSBKb2JcbiAqIGRlY2xhcmUgY29uc3Qgcm9sZTogaWFtLklSb2xlO1xuICogZGVjbGFyZSBjb25zdCBzY3JpcHQ6IGdsdWUuQ29kZTtcbiAqIGNvbnN0IGpvYiA9IG5ldyBnbHVlLlB5U3BhcmtTdHJlYW1pbmdKb2Ioc3RhY2ssICdJbXBvcnRlZEpvYicsIHsgcm9sZSwgc2NyaXB0IH0pO1xuICpcbiAqIC8vIENyZWF0ZSBhIEdsdWUgV29ya2Zsb3dcbiAqIGNvbnN0IHdvcmtmbG93ID0gbmV3IGdsdWUuV29ya2Zsb3coc3RhY2ssICdUZXN0V29ya2Zsb3cnKTtcbiAqXG4gKiAvLyBBZGQgYW4gb24tZGVtYW5kIHRyaWdnZXIgdG8gdGhlIFdvcmtmbG93XG4gKiB3b3JrZmxvdy5hZGRPbkRlbWFuZFRyaWdnZXIoJ09uRGVtYW5kVHJpZ2dlcicsIHtcbiAqICAgYWN0aW9uczogW3sgam9iOiBqb2IgfV0sXG4gKiB9KTtcbiAqIGBgYFxuICovXG5AcHJvcGVydHlJbmplY3RhYmxlXG5leHBvcnQgY2xhc3MgV29ya2Zsb3cgZXh0ZW5kcyBXb3JrZmxvd0Jhc2Uge1xuICAvKiogVW5pcXVlbHkgaWRlbnRpZmllcyB0aGlzIGNsYXNzLiAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IFBST1BFUlRZX0lOSkVDVElPTl9JRDogc3RyaW5nID0gJ0Bhd3MtY2RrLmF3cy1nbHVlLWFscGhhLldvcmtmbG93JztcblxuICAvKipcbiAgICogSW1wb3J0IGEgd29ya2Zsb3cgZnJvbSBpdHMgbmFtZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tV29ya2Zsb3dOYW1lKHNjb3BlOiBjb25zdHJ1Y3RzLkNvbnN0cnVjdCwgaWQ6IHN0cmluZywgd29ya2Zsb3dOYW1lOiBzdHJpbmcpOiBJV29ya2Zsb3cge1xuICAgIHJldHVybiB0aGlzLmZyb21Xb3JrZmxvd0F0dHJpYnV0ZXMoc2NvcGUsIGlkLCB7XG4gICAgICB3b3JrZmxvd05hbWUsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogSW1wb3J0IGFuIHdvcmtmbG93IGZyb20gaXQncyBuYW1lXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21Xb3JrZmxvd0FybihzY29wZTogY29uc3RydWN0cy5Db25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHdvcmtmbG93QXJuOiBzdHJpbmcpOiBJV29ya2Zsb3cge1xuICAgIHJldHVybiB0aGlzLmZyb21Xb3JrZmxvd0F0dHJpYnV0ZXMoc2NvcGUsIGlkLCB7XG4gICAgICB3b3JrZmxvd05hbWU6IHRoaXMuZXh0cmFjdE5hbWVGcm9tQXJuKHNjb3BlLCB3b3JrZmxvd0FybiksXG4gICAgICB3b3JrZmxvd0FybixcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbXBvcnQgYW4gZXhpc3Rpbmcgd29ya2Zsb3dcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbVdvcmtmbG93QXR0cmlidXRlcyhzY29wZTogY29uc3RydWN0cy5Db25zdHJ1Y3QsIGlkOiBzdHJpbmcsIGF0dHJzOiBXb3JrZmxvd0F0dHJpYnV0ZXMpOiBJV29ya2Zsb3cge1xuICAgIGNsYXNzIEltcG9ydCBleHRlbmRzIFdvcmtmbG93QmFzZSB7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgd29ya2Zsb3dOYW1lID0gYXR0cnMud29ya2Zsb3dOYW1lO1xuICAgICAgcHVibGljIHJlYWRvbmx5IHdvcmtmbG93QXJuID0gdGhpcy5idWlsZFdvcmtmbG93QXJuKHNjb3BlLCB0aGlzLndvcmtmbG93TmFtZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBJbXBvcnQoc2NvcGUsIGlkKTtcbiAgfVxuXG4gIHB1YmxpYyByZWFkb25seSB3b3JrZmxvd05hbWU6IHN0cmluZztcbiAgcHVibGljIHJlYWRvbmx5IHdvcmtmbG93QXJuOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IGNvbnN0cnVjdHMuQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wcz86IFdvcmtmbG93UHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQsIHtcbiAgICAgIHBoeXNpY2FsTmFtZTogcHJvcHM/LndvcmtmbG93TmFtZSxcbiAgICB9KTtcbiAgICAvLyBFbmhhbmNlZCBDREsgQW5hbHl0aWNzIFRlbGVtZXRyeVxuICAgIGFkZENvbnN0cnVjdE1ldGFkYXRhKHRoaXMsIHByb3BzKTtcblxuICAgIGNvbnN0IHJlc291cmNlID0gbmV3IENmbldvcmtmbG93KHRoaXMsICdSZXNvdXJjZScsIHtcbiAgICAgIG5hbWU6IHRoaXMucGh5c2ljYWxOYW1lLFxuICAgICAgZGVzY3JpcHRpb246IHByb3BzPy5kZXNjcmlwdGlvbixcbiAgICAgIGRlZmF1bHRSdW5Qcm9wZXJ0aWVzOiBwcm9wcz8uZGVmYXVsdFJ1blByb3BlcnRpZXMsXG4gICAgICBtYXhDb25jdXJyZW50UnVuczogcHJvcHM/Lm1heENvbmN1cnJlbnRSdW5zLFxuICAgIH0pO1xuXG4gICAgdGhpcy53b3JrZmxvd05hbWUgPSB0aGlzLmdldFJlc291cmNlTmFtZUF0dHJpYnV0ZShyZXNvdXJjZS5yZWYpO1xuICAgIHRoaXMud29ya2Zsb3dBcm4gPSB0aGlzLmJ1aWxkV29ya2Zsb3dBcm4odGhpcywgdGhpcy53b3JrZmxvd05hbWUpO1xuICB9XG59XG4iXX0=