@aws-cdk/core
Version:
AWS Cloud Development Kit Core Library
650 lines • 79.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const cloudformation_lang_1 = require("./private/cloudformation-lang");
const intrinsic_1 = require("./private/intrinsic");
const reference_1 = require("./reference");
const stack_trace_1 = require("./stack-trace");
const token_1 = require("./token");
// tslint:disable:max-line-length
/**
* CloudFormation intrinsic functions.
* http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html
*/
class Fn {
/**
* The ``Ref`` intrinsic function returns the value of the specified parameter or resource.
* Note that it doesn't validate the logicalName, it mainly serves paremeter/resource reference defined in a ``CfnInclude`` template.
* @param logicalName The logical name of a parameter/resource for which you want to retrieve its value.
*/
static ref(logicalName) {
return new FnRef(logicalName).toString();
}
/**
* The ``Fn::GetAtt`` intrinsic function returns the value of an attribute
* from a resource in the template.
* @param logicalNameOfResource The logical name (also called logical ID) of
* the resource that contains the attribute that you want.
* @param attributeName The name of the resource-specific attribute whose
* value you want. See the resource's reference page for details about the
* attributes available for that resource type.
* @returns an IResolvable object
*/
static getAtt(logicalNameOfResource, attributeName) {
return new FnGetAtt(logicalNameOfResource, attributeName);
}
/**
* The intrinsic function ``Fn::Join`` appends a set of values into a single
* value, separated by the specified delimiter. If a delimiter is the empty
* string, the set of values are concatenated with no delimiter.
* @param delimiter The value you want to occur between fragments. The
* delimiter will occur between fragments only. It will not terminate the
* final value.
* @param listOfValues The list of values you want combined.
* @returns a token represented as a string
*/
static join(delimiter, listOfValues) {
if (listOfValues.length === 0) {
throw new Error(`FnJoin requires at least one value to be provided`);
}
return new FnJoin(delimiter, listOfValues).toString();
}
/**
* To split a string into a list of string values so that you can select an element from the
* resulting string list, use the ``Fn::Split`` intrinsic function. Specify the location of splits
* with a delimiter, such as , (a comma). After you split a string, use the ``Fn::Select`` function
* to pick a specific element.
* @param delimiter A string value that determines where the source string is divided.
* @param source The string value that you want to split.
* @returns a token represented as a string array
*/
static split(delimiter, source) {
// short-circut if source is not a token
if (!token_1.Token.isUnresolved(source)) {
return source.split(delimiter);
}
return token_1.Token.asList(new FnSplit(delimiter, source));
}
/**
* The intrinsic function ``Fn::Select`` returns a single object from a list of objects by index.
* @param index The index of the object to retrieve. This must be a value from zero to N-1, where N represents the number of elements in the array.
* @param array The list of objects to select from. This list must not be null, nor can it have null entries.
* @returns a token represented as a string
*/
static select(index, array) {
if (!token_1.Token.isUnresolved(array)) {
return array[index];
}
return new FnSelect(index, array).toString();
}
/**
* The intrinsic function ``Fn::Sub`` substitutes variables in an input string
* with values that you specify. In your templates, you can use this function
* to construct commands or outputs that include values that aren't available
* until you create or update a stack.
* @param body A string with variables that AWS CloudFormation substitutes
* with their associated values at runtime. Write variables as ${MyVarName}.
* Variables can be template parameter names, resource logical IDs, resource
* attributes, or a variable in a key-value map. If you specify only template
* parameter names, resource logical IDs, and resource attributes, don't
* specify a key-value map.
* @param variables The name of a variable that you included in the String
* parameter. The value that AWS CloudFormation substitutes for the associated
* variable name at runtime.
* @returns a token represented as a string
*/
static sub(body, variables) {
return new FnSub(body, variables).toString();
}
/**
* The intrinsic function ``Fn::Base64`` returns the Base64 representation of
* the input string. This function is typically used to pass encoded data to
* Amazon EC2 instances by way of the UserData property.
* @param data The string value you want to convert to Base64.
* @returns a token represented as a string
*/
static base64(data) {
return new FnBase64(data).toString();
}
/**
* The intrinsic function ``Fn::Cidr`` returns the specified Cidr address block.
* @param ipBlock The user-specified default Cidr address block.
* @param count The number of subnets' Cidr block wanted. Count can be 1 to 256.
* @param sizeMask The digit covered in the subnet.
* @returns a token represented as a string
*/
static cidr(ipBlock, count, sizeMask) {
return token_1.Token.asList(new FnCidr(ipBlock, count, sizeMask));
}
/**
* The intrinsic function ``Fn::GetAZs`` returns an array that lists
* Availability Zones for a specified region. Because customers have access to
* different Availability Zones, the intrinsic function ``Fn::GetAZs`` enables
* template authors to write templates that adapt to the calling user's
* access. That way you don't have to hard-code a full list of Availability
* Zones for a specified region.
* @param region The name of the region for which you want to get the
* Availability Zones. You can use the AWS::Region pseudo parameter to specify
* the region in which the stack is created. Specifying an empty string is
* equivalent to specifying AWS::Region.
* @returns a token represented as a string array
*/
static getAzs(region) {
return token_1.Token.asList(new FnGetAZs(region));
}
/**
* The intrinsic function ``Fn::ImportValue`` returns the value of an output
* exported by another stack. You typically use this function to create
* cross-stack references. In the following example template snippets, Stack A
* exports VPC security group values and Stack B imports them.
* @param sharedValueToImport The stack output value that you want to import.
* @returns a token represented as a string
*/
static importValue(sharedValueToImport) {
return new FnImportValue(sharedValueToImport).toString();
}
/**
* The intrinsic function ``Fn::FindInMap`` returns the value corresponding to
* keys in a two-level map that is declared in the Mappings section.
* @returns a token represented as a string
*/
static findInMap(mapName, topLevelKey, secondLevelKey) {
return new FnFindInMap(mapName, topLevelKey, secondLevelKey).toString();
}
/**
* Returns true if all the specified conditions evaluate to true, or returns
* false if any one of the conditions evaluates to false. ``Fn::And`` acts as
* an AND operator. The minimum number of conditions that you can include is
* 2, and the maximum is 10.
* @param conditions conditions to AND
* @returns an FnCondition token
*/
static conditionAnd(...conditions) {
return new FnAnd(...conditions);
}
/**
* Compares if two values are equal. Returns true if the two values are equal
* or false if they aren't.
* @param lhs A value of any type that you want to compare.
* @param rhs A value of any type that you want to compare.
* @returns an FnCondition token
*/
static conditionEquals(lhs, rhs) {
return new FnEquals(lhs, rhs);
}
/**
* Returns one value if the specified condition evaluates to true and another
* value if the specified condition evaluates to false. Currently, AWS
* CloudFormation supports the ``Fn::If`` intrinsic function in the metadata
* attribute, update policy attribute, and property values in the Resources
* section and Outputs sections of a template. You can use the AWS::NoValue
* pseudo parameter as a return value to remove the corresponding property.
* @param conditionId A reference to a condition in the Conditions section. Use
* the condition's name to reference it.
* @param valueIfTrue A value to be returned if the specified condition
* evaluates to true.
* @param valueIfFalse A value to be returned if the specified condition
* evaluates to false.
* @returns an FnCondition token
*/
static conditionIf(conditionId, valueIfTrue, valueIfFalse) {
return new FnIf(conditionId, valueIfTrue, valueIfFalse);
}
/**
* Returns true for a condition that evaluates to false or returns false for a
* condition that evaluates to true. ``Fn::Not`` acts as a NOT operator.
* @param condition A condition such as ``Fn::Equals`` that evaluates to true
* or false.
* @returns an FnCondition token
*/
static conditionNot(condition) {
return new FnNot(condition);
}
/**
* Returns true if any one of the specified conditions evaluate to true, or
* returns false if all of the conditions evaluates to false. ``Fn::Or`` acts
* as an OR operator. The minimum number of conditions that you can include is
* 2, and the maximum is 10.
* @param conditions conditions that evaluates to true or false.
* @returns an FnCondition token
*/
static conditionOr(...conditions) {
return new FnOr(...conditions);
}
/**
* Returns true if a specified string matches at least one value in a list of
* strings.
* @param listOfStrings A list of strings, such as "A", "B", "C".
* @param value A string, such as "A", that you want to compare against a list of strings.
* @returns an FnCondition token
*/
static conditionContains(listOfStrings, value) {
return new FnContains(listOfStrings, value);
}
/**
* Returns true if a specified string matches all values in a list.
* @param listOfStrings A list of strings, such as "A", "B", "C".
* @param value A string, such as "A", that you want to compare against a list
* of strings.
* @returns an FnCondition token
*/
static conditionEachMemberEquals(listOfStrings, value) {
return new FnEachMemberEquals(listOfStrings, value);
}
/**
* Returns true if each member in a list of strings matches at least one value
* in a second list of strings.
* @param stringsToCheck A list of strings, such as "A", "B", "C". AWS
* CloudFormation checks whether each member in the strings_to_check parameter
* is in the strings_to_match parameter.
* @param stringsToMatch A list of strings, such as "A", "B", "C". Each member
* in the strings_to_match parameter is compared against the members of the
* strings_to_check parameter.
* @returns an FnCondition token
*/
static conditionEachMemberIn(stringsToCheck, stringsToMatch) {
return new FnEachMemberIn(stringsToCheck, stringsToMatch);
}
/**
* Returns all values for a specified parameter type.
* @param parameterType An AWS-specific parameter type, such as
* AWS::EC2::SecurityGroup::Id or AWS::EC2::VPC::Id. For more information, see
* Parameters in the AWS CloudFormation User Guide.
* @returns a token represented as a string array
*/
static refAll(parameterType) {
return token_1.Token.asList(new FnRefAll(parameterType));
}
/**
* Returns an attribute value or list of values for a specific parameter and
* attribute.
* @param parameterOrLogicalId The name of a parameter for which you want to
* retrieve attribute values. The parameter must be declared in the Parameters
* section of the template.
* @param attribute The name of an attribute from which you want to retrieve a
* value.
* @returns a token represented as a string
*/
static valueOf(parameterOrLogicalId, attribute) {
return new FnValueOf(parameterOrLogicalId, attribute).toString();
}
/**
* Returns a list of all attribute values for a given parameter type and
* attribute.
* @param parameterType An AWS-specific parameter type, such as
* AWS::EC2::SecurityGroup::Id or AWS::EC2::VPC::Id. For more information, see
* Parameters in the AWS CloudFormation User Guide.
* @param attribute The name of an attribute from which you want to retrieve a
* value. For more information about attributes, see Supported Attributes.
* @returns a token represented as a string array
*/
static valueOfAll(parameterType, attribute) {
return token_1.Token.asList(new FnValueOfAll(parameterType, attribute));
}
constructor() { }
}
exports.Fn = Fn;
/**
* Base class for tokens that represent CloudFormation intrinsic functions.
*/
class FnBase extends intrinsic_1.Intrinsic {
constructor(name, value) {
super({ [name]: value });
}
}
/**
* The intrinsic function ``Ref`` returns the value of the specified parameter or resource.
* When you specify a parameter's logical name, it returns the value of the parameter.
* When you specify a resource's logical name, it returns a value that you can typically use to refer to that resource, such as a physical ID.
*/
class FnRef extends FnBase {
/**
* Creates an ``Ref`` function.
* @param logicalName The logical name of a parameter/resource for which you want to retrieve its value.
*/
constructor(logicalName) {
super('Ref', logicalName);
}
}
/**
* The intrinsic function ``Fn::FindInMap`` returns the value corresponding to keys in a two-level
* map that is declared in the Mappings section.
*/
class FnFindInMap extends FnBase {
/**
* Creates an ``Fn::FindInMap`` function.
* @param mapName The logical name of a mapping declared in the Mappings section that contains the keys and values.
* @param topLevelKey The top-level key name. Its value is a list of key-value pairs.
* @param secondLevelKey The second-level key name, which is set to one of the keys from the list assigned to TopLevelKey.
*/
constructor(mapName, topLevelKey, secondLevelKey) {
super('Fn::FindInMap', [mapName, topLevelKey, secondLevelKey]);
}
}
/**
* The ``Fn::GetAtt`` intrinsic function returns the value of an attribute from a resource in the template.
*/
class FnGetAtt extends FnBase {
/**
* Creates a ``Fn::GetAtt`` function.
* @param logicalNameOfResource The logical name (also called logical ID) of the resource that contains the attribute that you want.
* @param attributeName The name of the resource-specific attribute whose value you want. See the resource's reference page for details about the attributes available for that resource type.
*/
constructor(logicalNameOfResource, attributeName) {
super('Fn::GetAtt', [logicalNameOfResource, attributeName]);
}
}
/**
* The intrinsic function ``Fn::GetAZs`` returns an array that lists Availability Zones for a
* specified region. Because customers have access to different Availability Zones, the intrinsic
* function ``Fn::GetAZs`` enables template authors to write templates that adapt to the calling
* user's access. That way you don't have to hard-code a full list of Availability Zones for a
* specified region.
*/
class FnGetAZs extends FnBase {
/**
* Creates an ``Fn::GetAZs`` function.
* @param region The name of the region for which you want to get the Availability Zones.
* You can use the AWS::Region pseudo parameter to specify the region in
* which the stack is created. Specifying an empty string is equivalent to
* specifying AWS::Region.
*/
constructor(region) {
super('Fn::GetAZs', region || '');
}
}
/**
* The intrinsic function ``Fn::ImportValue`` returns the value of an output exported by another stack.
* You typically use this function to create cross-stack references. In the following example
* template snippets, Stack A exports VPC security group values and Stack B imports them.
*/
class FnImportValue extends FnBase {
/**
* Creates an ``Fn::ImportValue`` function.
* @param sharedValueToImport The stack output value that you want to import.
*/
constructor(sharedValueToImport) {
super('Fn::ImportValue', sharedValueToImport);
}
}
/**
* The intrinsic function ``Fn::Select`` returns a single object from a list of objects by index.
*/
class FnSelect extends FnBase {
/**
* Creates an ``Fn::Select`` function.
* @param index The index of the object to retrieve. This must be a value from zero to N-1, where N represents the number of elements in the array.
* @param array The list of objects to select from. This list must not be null, nor can it have null entries.
*/
constructor(index, array) {
super('Fn::Select', [index, array]);
}
}
/**
* To split a string into a list of string values so that you can select an element from the
* resulting string list, use the ``Fn::Split`` intrinsic function. Specify the location of splits
* with a delimiter, such as , (a comma). After you split a string, use the ``Fn::Select`` function
* to pick a specific element.
*/
class FnSplit extends FnBase {
/**
* Create an ``Fn::Split`` function.
* @param delimiter A string value that determines where the source string is divided.
* @param source The string value that you want to split.
*/
constructor(delimiter, source) {
super('Fn::Split', [delimiter, source]);
}
}
/**
* The intrinsic function ``Fn::Sub`` substitutes variables in an input string with values that
* you specify. In your templates, you can use this function to construct commands or outputs
* that include values that aren't available until you create or update a stack.
*/
class FnSub extends FnBase {
/**
* Creates an ``Fn::Sub`` function.
* @param body A string with variables that AWS CloudFormation substitutes with their
* associated values at runtime. Write variables as ${MyVarName}. Variables
* can be template parameter names, resource logical IDs, resource attributes,
* or a variable in a key-value map. If you specify only template parameter names,
* resource logical IDs, and resource attributes, don't specify a key-value map.
* @param variables The name of a variable that you included in the String parameter.
* The value that AWS CloudFormation substitutes for the associated variable name at runtime.
*/
constructor(body, variables) {
super('Fn::Sub', variables ? [body, variables] : body);
}
}
/**
* The intrinsic function ``Fn::Base64`` returns the Base64 representation of the input string.
* This function is typically used to pass encoded data to Amazon EC2 instances by way of
* the UserData property.
*/
class FnBase64 extends FnBase {
/**
* Creates an ``Fn::Base64`` function.
* @param data The string value you want to convert to Base64.
*/
constructor(data) {
super('Fn::Base64', data);
}
}
/**
* The intrinsic function ``Fn::Cidr`` returns the specified Cidr address block.
*/
class FnCidr extends FnBase {
/**
* Creates an ``Fn::Cidr`` function.
* @param ipBlock The user-specified default Cidr address block.
* @param count The number of subnets' Cidr block wanted. Count can be 1 to 256.
* @param sizeMask The digit covered in the subnet.
*/
constructor(ipBlock, count, sizeMask) {
if (count < 1 || count > 256) {
throw new Error(`Fn::Cidr's count attribute must be betwen 1 and 256, ${count} was provided.`);
}
super('Fn::Cidr', [ipBlock, count, sizeMask]);
}
}
class FnConditionBase extends intrinsic_1.Intrinsic {
constructor(type, value) {
super({ [type]: value });
}
}
/**
* Returns true if all the specified conditions evaluate to true, or returns false if any one
* of the conditions evaluates to false. ``Fn::And`` acts as an AND operator. The minimum number of
* conditions that you can include is 2, and the maximum is 10.
*/
class FnAnd extends FnConditionBase {
constructor(...condition) {
super('Fn::And', condition);
}
}
/**
* Compares if two values are equal. Returns true if the two values are equal or false
* if they aren't.
*/
class FnEquals extends FnConditionBase {
/**
* Creates an ``Fn::Equals`` condition function.
* @param lhs A value of any type that you want to compare.
* @param rhs A value of any type that you want to compare.
*/
constructor(lhs, rhs) {
super('Fn::Equals', [lhs, rhs]);
}
}
/**
* Returns one value if the specified condition evaluates to true and another value if the
* specified condition evaluates to false. Currently, AWS CloudFormation supports the ``Fn::If``
* intrinsic function in the metadata attribute, update policy attribute, and property values
* in the Resources section and Outputs sections of a template. You can use the AWS::NoValue
* pseudo parameter as a return value to remove the corresponding property.
*/
class FnIf extends FnConditionBase {
/**
* Creates an ``Fn::If`` condition function.
* @param condition A reference to a condition in the Conditions section. Use the condition's name to reference it.
* @param valueIfTrue A value to be returned if the specified condition evaluates to true.
* @param valueIfFalse A value to be returned if the specified condition evaluates to false.
*/
constructor(condition, valueIfTrue, valueIfFalse) {
super('Fn::If', [condition, valueIfTrue, valueIfFalse]);
}
}
/**
* Returns true for a condition that evaluates to false or returns false for a condition that evaluates to true.
* ``Fn::Not`` acts as a NOT operator.
*/
class FnNot extends FnConditionBase {
/**
* Creates an ``Fn::Not`` condition function.
* @param condition A condition such as ``Fn::Equals`` that evaluates to true or false.
*/
constructor(condition) {
super('Fn::Not', [condition]);
}
}
/**
* Returns true if any one of the specified conditions evaluate to true, or returns false if
* all of the conditions evaluates to false. ``Fn::Or`` acts as an OR operator. The minimum number
* of conditions that you can include is 2, and the maximum is 10.
*/
class FnOr extends FnConditionBase {
/**
* Creates an ``Fn::Or`` condition function.
* @param condition A condition that evaluates to true or false.
*/
constructor(...condition) {
super('Fn::Or', condition);
}
}
/**
* Returns true if a specified string matches at least one value in a list of strings.
*/
class FnContains extends FnConditionBase {
/**
* Creates an ``Fn::Contains`` function.
* @param listOfStrings A list of strings, such as "A", "B", "C".
* @param value A string, such as "A", that you want to compare against a list of strings.
*/
constructor(listOfStrings, value) {
super('Fn::Contains', [listOfStrings, value]);
}
}
/**
* Returns true if a specified string matches all values in a list.
*/
class FnEachMemberEquals extends FnConditionBase {
/**
* Creates an ``Fn::EachMemberEquals`` function.
* @param listOfStrings A list of strings, such as "A", "B", "C".
* @param value A string, such as "A", that you want to compare against a list of strings.
*/
constructor(listOfStrings, value) {
super('Fn::EachMemberEquals', [listOfStrings, value]);
}
}
/**
* Returns true if each member in a list of strings matches at least one value in a second
* list of strings.
*/
class FnEachMemberIn extends FnConditionBase {
/**
* Creates an ``Fn::EachMemberIn`` function.
* @param stringsToCheck A list of strings, such as "A", "B", "C". AWS CloudFormation checks whether each member in the strings_to_check parameter is in the strings_to_match parameter.
* @param stringsToMatch A list of strings, such as "A", "B", "C". Each member in the strings_to_match parameter is compared against the members of the strings_to_check parameter.
*/
constructor(stringsToCheck, stringsToMatch) {
super('Fn::EachMemberIn', [stringsToCheck, stringsToMatch]);
}
}
/**
* Returns all values for a specified parameter type.
*/
class FnRefAll extends FnBase {
/**
* Creates an ``Fn::RefAll`` function.
* @param parameterType An AWS-specific parameter type, such as AWS::EC2::SecurityGroup::Id or
* AWS::EC2::VPC::Id. For more information, see Parameters in the AWS
* CloudFormation User Guide.
*/
constructor(parameterType) {
super('Fn::RefAll', parameterType);
}
}
/**
* Returns an attribute value or list of values for a specific parameter and attribute.
*/
class FnValueOf extends FnBase {
/**
* Creates an ``Fn::ValueOf`` function.
* @param parameterOrLogicalId The name of a parameter for which you want to retrieve attribute values. The parameter must be declared in the Parameters section of the template.
* @param attribute The name of an attribute from which you want to retrieve a value.
*/
constructor(parameterOrLogicalId, attribute) {
super('Fn::ValueOf', [parameterOrLogicalId, attribute]);
}
}
/**
* Returns a list of all attribute values for a given parameter type and attribute.
*/
class FnValueOfAll extends FnBase {
/**
* Creates an ``Fn::ValueOfAll`` function.
* @param parameterType An AWS-specific parameter type, such as AWS::EC2::SecurityGroup::Id or AWS::EC2::VPC::Id. For more information, see Parameters in the AWS CloudFormation User Guide.
* @param attribute The name of an attribute from which you want to retrieve a value. For more information about attributes, see Supported Attributes.
*/
constructor(parameterType, attribute) {
super('Fn::ValueOfAll', [parameterType, attribute]);
}
}
/**
* The intrinsic function ``Fn::Join`` appends a set of values into a single value, separated by
* the specified delimiter. If a delimiter is the empty string, the set of values are concatenated
* with no delimiter.
*/
class FnJoin {
/**
* Creates an ``Fn::Join`` function.
* @param delimiter The value you want to occur between fragments. The delimiter will occur between fragments only.
* It will not terminate the final value.
* @param listOfValues The list of values you want combined.
*/
constructor(delimiter, listOfValues) {
if (listOfValues.length === 0) {
throw new Error(`FnJoin requires at least one value to be provided`);
}
this.delimiter = delimiter;
this.listOfValues = listOfValues;
this.creationStack = stack_trace_1.captureStackTrace();
}
resolve(context) {
if (token_1.Token.isUnresolved(this.listOfValues)) {
// This is a list token, don't try to do smart things with it.
return { 'Fn::Join': [this.delimiter, this.listOfValues] };
}
const resolved = this.resolveValues(context);
if (resolved.length === 1) {
return resolved[0];
}
return { 'Fn::Join': [this.delimiter, resolved] };
}
toString() {
return token_1.Token.asString(this, { displayHint: 'Fn::Join' });
}
toJSON() {
return `<Fn::Join>`;
}
/**
* Optimization: if an Fn::Join is nested in another one and they share the same delimiter, then flatten it up. Also,
* if two concatenated elements are literal strings (not tokens), then pre-concatenate them with the delimiter, to
* generate shorter output.
*/
resolveValues(context) {
const resolvedValues = this.listOfValues.map(x => reference_1.Reference.isReference(x) ? x : context.resolve(x));
return cloudformation_lang_1.minimalCloudFormationJoin(this.delimiter, resolvedValues);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2ZuLWZuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiY2ZuLWZuLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQ0EsdUVBQTBFO0FBQzFFLG1EQUFnRDtBQUNoRCwyQ0FBd0M7QUFFeEMsK0NBQWtEO0FBQ2xELG1DQUFnQztBQUVoQyxpQ0FBaUM7QUFFakM7OztHQUdHO0FBQ0gsTUFBYSxFQUFFO0lBQ2I7Ozs7T0FJRztJQUNJLE1BQU0sQ0FBQyxHQUFHLENBQUMsV0FBbUI7UUFDbkMsT0FBTyxJQUFJLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUMzQyxDQUFDO0lBRUQ7Ozs7Ozs7OztPQVNHO0lBQ0ksTUFBTSxDQUFDLE1BQU0sQ0FBQyxxQkFBNkIsRUFBRSxhQUFxQjtRQUN2RSxPQUFPLElBQUksUUFBUSxDQUFDLHFCQUFxQixFQUFFLGFBQWEsQ0FBQyxDQUFDO0lBQzVELENBQUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDSSxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQWlCLEVBQUUsWUFBc0I7UUFDMUQsSUFBSSxZQUFZLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUM3QixNQUFNLElBQUksS0FBSyxDQUFDLG1EQUFtRCxDQUFDLENBQUM7U0FDdEU7UUFFRCxPQUFPLElBQUksTUFBTSxDQUFDLFNBQVMsRUFBRSxZQUFZLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUN4RCxDQUFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSSxNQUFNLENBQUMsS0FBSyxDQUFDLFNBQWlCLEVBQUUsTUFBYztRQUVuRCx3Q0FBd0M7UUFDeEMsSUFBSSxDQUFDLGFBQUssQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDL0IsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1NBQ2hDO1FBRUQsT0FBTyxhQUFLLENBQUMsTUFBTSxDQUFDLElBQUksT0FBTyxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3RELENBQUM7SUFFRDs7Ozs7T0FLRztJQUNJLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBYSxFQUFFLEtBQWU7UUFDakQsSUFBSSxDQUFDLGFBQUssQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLEVBQUU7WUFDOUIsT0FBTyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDckI7UUFFRCxPQUFPLElBQUksUUFBUSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUMvQyxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7Ozs7OztPQWVHO0lBQ0ksTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFZLEVBQUUsU0FBcUM7UUFDbkUsT0FBTyxJQUFJLEtBQUssQ0FBQyxJQUFJLEVBQUUsU0FBUyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDL0MsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNJLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBWTtRQUMvQixPQUFPLElBQUksUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ3ZDLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSSxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQWUsRUFBRSxLQUFhLEVBQUUsUUFBaUI7UUFDbEUsT0FBTyxhQUFLLENBQUMsTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQztJQUM1RCxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7OztPQVlHO0lBQ0ksTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFlO1FBQ2xDLE9BQU8sYUFBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQzVDLENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0ksTUFBTSxDQUFDLFdBQVcsQ0FBQyxtQkFBMkI7UUFDbkQsT0FBTyxJQUFJLGFBQWEsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQzNELENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksTUFBTSxDQUFDLFNBQVMsQ0FBQyxPQUFlLEVBQUUsV0FBbUIsRUFBRSxjQUFzQjtRQUNsRixPQUFPLElBQUksV0FBVyxDQUFDLE9BQU8sRUFBRSxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDMUUsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSSxNQUFNLENBQUMsWUFBWSxDQUFDLEdBQUcsVUFBcUM7UUFDakUsT0FBTyxJQUFJLEtBQUssQ0FBQyxHQUFHLFVBQVUsQ0FBQyxDQUFDO0lBQ2xDLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSSxNQUFNLENBQUMsZUFBZSxDQUFDLEdBQVEsRUFBRSxHQUFRO1FBQzlDLE9BQU8sSUFBSSxRQUFRLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ2hDLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7T0FjRztJQUNJLE1BQU0sQ0FBQyxXQUFXLENBQUMsV0FBbUIsRUFBRSxXQUFnQixFQUFFLFlBQWlCO1FBQ2hGLE9BQU8sSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFLFdBQVcsRUFBRSxZQUFZLENBQUMsQ0FBQztJQUMxRCxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksTUFBTSxDQUFDLFlBQVksQ0FBQyxTQUFrQztRQUMzRCxPQUFPLElBQUksS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzlCLENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0ksTUFBTSxDQUFDLFdBQVcsQ0FBQyxHQUFHLFVBQXFDO1FBQ2hFLE9BQU8sSUFBSSxJQUFJLENBQUMsR0FBRyxVQUFVLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksTUFBTSxDQUFDLGlCQUFpQixDQUFDLGFBQXVCLEVBQUUsS0FBYTtRQUNwRSxPQUFPLElBQUksVUFBVSxDQUFDLGFBQWEsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUM5QyxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksTUFBTSxDQUFDLHlCQUF5QixDQUFDLGFBQXVCLEVBQUUsS0FBYTtRQUM1RSxPQUFPLElBQUksa0JBQWtCLENBQUMsYUFBYSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3RELENBQUM7SUFFRDs7Ozs7Ozs7OztPQVVHO0lBQ0ksTUFBTSxDQUFDLHFCQUFxQixDQUFDLGNBQXdCLEVBQUUsY0FBd0I7UUFDcEYsT0FBTyxJQUFJLGNBQWMsQ0FBQyxjQUFjLEVBQUUsY0FBYyxDQUFDLENBQUM7SUFDNUQsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNJLE1BQU0sQ0FBQyxNQUFNLENBQUMsYUFBcUI7UUFDeEMsT0FBTyxhQUFLLENBQUMsTUFBTSxDQUFDLElBQUksUUFBUSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUVEOzs7Ozs7Ozs7T0FTRztJQUNJLE1BQU0sQ0FBQyxPQUFPLENBQUMsb0JBQTRCLEVBQUUsU0FBaUI7UUFDbkUsT0FBTyxJQUFJLFNBQVMsQ0FBQyxvQkFBb0IsRUFBRSxTQUFTLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUNuRSxDQUFDO0lBRUQ7Ozs7Ozs7OztPQVNHO0lBQ0ksTUFBTSxDQUFDLFVBQVUsQ0FBQyxhQUFxQixFQUFFLFNBQWlCO1FBQy9ELE9BQU8sYUFBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLFlBQVksQ0FBQyxhQUFhLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQztJQUNsRSxDQUFDO0lBRUQsZ0JBQXdCLENBQUM7Q0FDMUI7QUF6U0QsZ0JBeVNDO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLE1BQU8sU0FBUSxxQkFBUztJQUM1QixZQUFZLElBQVksRUFBRSxLQUFVO1FBQ2xDLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztJQUMzQixDQUFDO0NBQ0Y7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxLQUFNLFNBQVEsTUFBTTtJQUN4Qjs7O09BR0c7SUFDSCxZQUFZLFdBQW1CO1FBQzdCLEtBQUssQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDNUIsQ0FBQztDQUNGO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxXQUFZLFNBQVEsTUFBTTtJQUM5Qjs7Ozs7T0FLRztJQUNILFlBQVksT0FBZSxFQUFFLFdBQWdCLEVBQUUsY0FBbUI7UUFDaEUsS0FBSyxDQUFDLGVBQWUsRUFBRSxDQUFFLE9BQU8sRUFBRSxXQUFXLEVBQUUsY0FBYyxDQUFFLENBQUMsQ0FBQztJQUNuRSxDQUFDO0NBQ0Y7QUFFRDs7R0FFRztBQUNILE1BQU0sUUFBUyxTQUFRLE1BQU07SUFDM0I7Ozs7T0FJRztJQUNILFlBQVkscUJBQTZCLEVBQUUsYUFBcUI7UUFDOUQsS0FBSyxDQUFDLFlBQVksRUFBRSxDQUFFLHFCQUFxQixFQUFFLGFBQWEsQ0FBRSxDQUFDLENBQUM7SUFDaEUsQ0FBQztDQUNGO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxRQUFTLFNBQVEsTUFBTTtJQUMzQjs7Ozs7O09BTUc7SUFDSCxZQUFZLE1BQWU7UUFDekIsS0FBSyxDQUFDLFlBQVksRUFBRSxNQUFNLElBQUksRUFBRSxDQUFDLENBQUM7SUFDcEMsQ0FBQztDQUNGO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sYUFBYyxTQUFRLE1BQU07SUFDaEM7OztPQUdHO0lBQ0gsWUFBWSxtQkFBMkI7UUFDckMsS0FBSyxDQUFDLGlCQUFpQixFQUFFLG1CQUFtQixDQUFDLENBQUM7SUFDaEQsQ0FBQztDQUNGO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLFFBQVMsU0FBUSxNQUFNO0lBQzNCOzs7O09BSUc7SUFDSCxZQUFZLEtBQWEsRUFBRSxLQUFVO1FBQ25DLEtBQUssQ0FBQyxZQUFZLEVBQUUsQ0FBRSxLQUFLLEVBQUUsS0FBSyxDQUFFLENBQUMsQ0FBQztJQUN4QyxDQUFDO0NBQ0Y7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sT0FBUSxTQUFRLE1BQU07SUFDMUI7Ozs7T0FJRztJQUNILFlBQVksU0FBaUIsRUFBRSxNQUFXO1FBQ3hDLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBRSxTQUFTLEVBQUUsTUFBTSxDQUFFLENBQUMsQ0FBQztJQUM1QyxDQUFDO0NBQ0Y7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxLQUFNLFNBQVEsTUFBTTtJQUN4Qjs7Ozs7Ozs7O09BU0c7SUFDSCxZQUFZLElBQVksRUFBRSxTQUFrQztRQUMxRCxLQUFLLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3pELENBQUM7Q0FDRjtBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLFFBQVMsU0FBUSxNQUFNO0lBRTNCOzs7T0FHRztJQUNILFlBQVksSUFBUztRQUNuQixLQUFLLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQzVCLENBQUM7Q0FDRjtBQUVEOztHQUVHO0FBQ0gsTUFBTSxNQUFPLFNBQVEsTUFBTTtJQUN6Qjs7Ozs7T0FLRztJQUNILFlBQVksT0FBWSxFQUFFLEtBQVUsRUFBRSxRQUFjO1FBQ2xELElBQUksS0FBSyxHQUFHLENBQUMsSUFBSSxLQUFLLEdBQUcsR0FBRyxFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsd0RBQXdELEtBQUssZ0JBQWdCLENBQUMsQ0FBQztTQUNoRztRQUNELEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFDaEQsQ0FBQztDQUNGO0FBRUQsTUFBTSxlQUFnQixTQUFRLHFCQUFTO0lBQ3JDLFlBQVksSUFBWSxFQUFFLEtBQVU7UUFDbEMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQzNCLENBQUM7Q0FDRjtBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLEtBQU0sU0FBUSxlQUFlO0lBQ2pDLFlBQVksR0FBRyxTQUFvQztRQUNqRCxLQUFLLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQzlCLENBQUM7Q0FDRjtBQUVEOzs7R0FHRztBQUNILE1BQU0sUUFBUyxTQUFRLGVBQWU7SUFDcEM7Ozs7T0FJRztJQUNILFlBQVksR0FBUSxFQUFFLEdBQVE7UUFDNUIsS0FBSyxDQUFDLFlBQVksRUFBRSxDQUFFLEdBQUcsRUFBRSxHQUFHLENBQUUsQ0FBQyxDQUFDO0lBQ3BDLENBQUM7Q0FDRjtBQUVEOzs7Ozs7R0FNRztBQUNILE1BQU0sSUFBSyxTQUFRLGVBQWU7SUFDaEM7Ozs7O09BS0c7SUFDSCxZQUFZLFNBQWlCLEVBQUUsV0FBZ0IsRUFBRSxZQUFpQjtRQUNoRSxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxZQUFZLENBQUUsQ0FBQyxDQUFDO0lBQzVELENBQUM7Q0FDRjtBQUVEOzs7R0FHRztBQUNILE1BQU0sS0FBTSxTQUFRLGVBQWU7SUFDakM7OztPQUdHO0lBQ0gsWUFBWSxTQUFrQztRQUM1QyxLQUFLLENBQUMsU0FBUyxFQUFFLENBQUUsU0FBUyxDQUFFLENBQUMsQ0FBQztJQUNsQyxDQUFDO0NBQ0Y7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxJQUFLLFNBQVEsZUFBZTtJQUNoQzs7O09BR0c7SUFDSCxZQUFZLEdBQUcsU0FBb0M7UUFDakQsS0FBSyxDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUM3QixDQUFDO0NBQ0Y7QUFFRDs7R0FFRztBQUNILE1BQU0sVUFBVyxTQUFRLGVBQWU7SUFDdEM7Ozs7T0FJRztJQUNILFlBQVksYUFBa0IsRUFBRSxLQUFhO1FBQzNDLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBRSxhQUFhLEVBQUUsS0FBSyxDQUFFLENBQUMsQ0FBQztJQUNsRCxDQUFDO0NBQ0Y7QUFFRDs7R0FFRztBQUNILE1BQU0sa0JBQW1CLFNBQVEsZUFBZTtJQUM5Qzs7OztPQUlHO0lBQ0gsWUFBWSxhQUFrQixFQUFFLEtBQWE7UUFDM0MsS0FBSyxDQUFDLHNCQUFzQixFQUFFLENBQUUsYUFBYSxFQUFFLEtBQUssQ0FBRSxDQUFDLENBQUM7SUFDMUQsQ0FBQztDQUNGO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxjQUFlLFNBQVEsZUFBZTtJQUMxQzs7OztPQUlHO0lBQ0gsWUFBWSxjQUF3QixFQUFFLGNBQXdCO1FBQzVELEtBQUssQ0FBQyxrQkFBa0IsRUFBRSxDQUFDLGNBQWMsRUFBRSxjQUFjLENBQUMsQ0FBQyxDQUFDO0lBQzlELENBQUM7Q0FDRjtBQUVEOztHQUVHO0FBQ0gsTUFBTSxRQUFTLFNBQVEsTUFBTTtJQUMzQjs7Ozs7T0FLRztJQUNILFlBQVksYUFBcUI7UUFDL0IsS0FBSyxDQUFDLFlBQVksRUFBRSxhQUFhLENBQUMsQ0FBQztJQUNyQyxDQUFDO0NBQ0Y7QUFFRDs7R0FFRztBQUNILE1BQU0sU0FBVSxTQUFRLE1BQU07SUFDNUI7Ozs7T0FJRztJQUNILFlBQVksb0JBQTRCLEVBQUUsU0FBaUI7UUFDekQsS0FBSyxDQUFDLGFBQWEsRUFBRSxDQUFFLG9CQUFvQixFQUFFLFNBQVMsQ0FBRSxDQUFDLENBQUM7SUFDNUQsQ0FBQztDQUNGO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLFlBQWEsU0FBUSxNQUFNO0lBQy9COzs7O09BSUc7SUFDSCxZQUFZLGFBQXFCLEVBQUUsU0FBaUI7UUFDbEQsS0FBSyxDQUFDLGdCQUFnQixFQUFFLENBQUUsYUFBYSxFQUFFLFNBQVMsQ0FBRSxDQUFDLENBQUM7SUFDeEQsQ0FBQztDQUNGO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sTUFBTTtJQU1WOzs7OztPQUtHO0lBQ0gsWUFBWSxTQUFpQixFQUFFLFlBQW1CO1FBQ2hELElBQUksWUFBWSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFDN0IsTUFBTSxJQUFJLEtBQUssQ0FBQyxtREFBbUQsQ0FBQyxDQUFDO1NBQ3RFO1FBRUQsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7UUFDM0IsSUFBSSxDQUFDLFlBQVksR0FBRyxZQUFZLENBQUM7UUFDakMsSUFBSSxDQUFDLGFBQWEsR0FBRywrQkFBaUIsRUFBRSxDQUFDO0lBQzNDLENBQUM7SUFFTSxPQUFPLENBQUMsT0FBd0I7UUFDckMsSUFBSSxhQUFLLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsRUFBRTtZQUN6Qyw4REFBOEQ7WUFDOUQsT0FBTyxFQUFFLFVBQVUsRUFBRSxDQUFFLElBQUksQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBRSxFQUFFLENBQUM7U0FDOUQ7UUFDRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzdDLElBQUksUUFBUSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFDekIsT0FBTyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDcEI7UUFDRCxPQUFPLEVBQUUsVUFBVSxFQUFFLENBQUUsSUFBSSxDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUUsRUFBRSxDQUFDO0lBQ3RELENBQUM7SUFFTSxRQUFRO1FBQ2IsT0FBTyxhQUFLLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxFQUFFLFdBQVcsRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDO0lBQzNELENBQUM7SUFFTSxNQUFNO1FBQ1gsT0FBTyxZQUFZLENBQUM7SUFDdEIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxhQUFhLENBQUMsT0FBd0I7UUFDNUMsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxxQkFBUyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsT0FBUSwrQ0FBeUIsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLGNBQWMsQ0FBQyxDQUFDO0lBQ3BFLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IElDZm5Db25kaXRpb25FeHByZXNzaW9uIH0gZnJvbSAnLi9jZm4tY29uZGl0aW9uJztcbmltcG9ydCB7IG1pbmltYWxDbG91ZEZvcm1hdGlvbkpvaW4gfSBmcm9tICcuL3ByaXZhdGUvY2xvdWRmb3JtYXRpb24tbGFuZyc7XG5pbXBvcnQgeyBJbnRyaW5zaWMgfSBmcm9tICcuL3ByaXZhdGUvaW50cmluc2ljJztcbmltcG9ydCB7IFJlZmVyZW5jZSB9IGZyb20gJy4vcmVmZXJlbmNlJztcbmltcG9ydCB7IElSZXNvbHZhYmxlLCBJUmVzb2x2ZUNvbnRleHQgfSBmcm9tICcuL3Jlc29sdmFibGUnO1xuaW1wb3J0IHsgY2FwdHVyZVN0YWNrVHJhY2UgfSBmcm9tICcuL3N0YWNrLXRyYWNlJztcbmltcG9ydCB7IFRva2VuIH0gZnJvbSAnLi90b2tlbic7XG5cbi8vIHRzbGludDpkaXNhYmxlOm1heC1saW5lLWxlbmd0aFxuXG4vKipcbiAqIENsb3VkRm9ybWF0aW9uIGludHJpbnNpYyBmdW5jdGlvbnMuXG4gKiBodHRwOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2ludHJpbnNpYy1mdW5jdGlvbi1yZWZlcmVuY2UuaHRtbFxuICovXG5leHBvcnQgY2xhc3MgRm4ge1xuICAvKipcbiAgICogVGhlIGBgUmVmYGAgaW50cmluc2ljIGZ1bmN0aW9uIHJldHVybnMgdGhlIHZhbHVlIG9mIHRoZSBzcGVjaWZpZWQgcGFyYW1ldGVyIG9yIHJlc291cmNlLlxuICAgKiBOb3RlIHRoYXQgaXQgZG9lc24ndCB2YWxpZGF0ZSB0aGUgbG9naWNhbE5hbWUsIGl0IG1haW5seSBzZXJ2ZXMgcGFyZW1ldGVyL3Jlc291cmNlIHJlZmVyZW5jZSBkZWZpbmVkIGluIGEgYGBDZm5JbmNsdWRlYGAgdGVtcGxhdGUuXG4gICAqIEBwYXJhbSBsb2dpY2FsTmFtZSBUaGUgbG9naWNhbCBuYW1lIG9mIGEgcGFyYW1ldGVyL3Jlc291cmNlIGZvciB3aGljaCB5b3Ugd2FudCB0byByZXRyaWV2ZSBpdHMgdmFsdWUuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlZihsb2dpY2FsTmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gbmV3IEZuUmVmKGxvZ2ljYWxOYW1lKS50b1N0cmluZygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBgYEZuOjpHZXRBdHRgYCBpbnRyaW5zaWMgZnVuY3Rpb24gcmV0dXJucyB0aGUgdmFsdWUgb2YgYW4gYXR0cmlidXRlXG4gICAqIGZyb20gYSByZXNvdXJjZSBpbiB0aGUgdGVtcGxhdGUuXG4gICAqIEBwYXJhbSBsb2dpY2FsTmFtZU9mUmVzb3VyY2UgVGhlIGxvZ2ljYWwgbmFtZSAoYWxzbyBjYWxsZWQgbG9naWNhbCBJRCkgb2ZcbiAgICogdGhlIHJlc291cmNlIHRoYXQgY29udGFpbnMgdGhlIGF0dHJpYnV0ZSB0aGF0IHlvdSB3YW50LlxuICAgKiBAcGFyYW0gYXR0cmlidXRlTmFtZSBUaGUgbmFtZSBvZiB0aGUgcmVzb3VyY2Utc3BlY2lmaWMgYXR0cmlidXRlIHdob3NlXG4gICAqIHZhbHVlIHlvdSB3YW50LiBTZWUgdGhlIHJlc291cmNlJ3MgcmVmZXJlbmNlIHBhZ2UgZm9yIGRldGFpbHMgYWJvdXQgdGhlXG4gICAqIGF0dHJpYnV0ZXMgYXZhaWxhYmxlIGZvciB0aGF0IHJlc291cmNlIHR5cGUuXG4gICAqIEByZXR1cm5zIGFuIElSZXNvbHZhYmxlIG9iamVjdFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBnZXRBdHQobG9naWNhbE5hbWVPZlJlc291cmNlOiBzdHJpbmcsIGF0dHJpYnV0ZU5hbWU6IHN0cmluZyk6IElSZXNvbHZhYmxlIHtcbiAgICByZXR1cm4gbmV3IEZuR2V0QXR0KGxvZ2ljYWxOYW1lT2ZSZXNvdXJjZSwgYXR0cmlidXRlTmFtZSk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGludHJpbnNpYyBmdW5jdGlvbiBgYEZuOjpKb2luYGAgYXBwZW5kcyBhIHNldCBvZiB2YWx1ZXMgaW50byBhIHNpbmdsZVxuICAgKiB2YWx1ZSwgc2VwYXJhdGVkIGJ5IHRoZSBzcGVjaWZpZWQgZGVsaW1pdGVyLiBJZiBhIGRlbGltaXRlciBpcyB0aGUgZW1wdHlcbiAgICogc3RyaW5nLCB0aGUgc2V0IG9mIHZhbHVlcyBhcmUgY29uY2F0ZW5hdGVkIHdpdGggbm8gZGVsaW1pdGVyLlxuICAgKiBAcGFyYW0gZGVsaW1pdGVyIFRoZSB2YWx1ZSB5b3Ugd2FudCB0byBvY2N1ciBiZXR3ZWVuIGZyYWdtZW50cy4gVGhlXG4gICAqIGRlbGltaXRlciB3aWxsIG9jY3VyIGJldHdlZW4gZnJhZ21lbnRzIG9ubHkuIEl0IHdpbGwgbm90IHRlcm1pbmF0ZSB0aGVcbiAgICogZmluYWwgdmFsdWUuXG4gICAqIEBwYXJhbSBsaXN0T2ZWYWx1ZXMgVGhlIGxpc3Qgb2YgdmFsdWVzIHlvdSB3YW50IGNvbWJpbmVkLlxuICAgKiBAcmV0dXJucyBhIHRva2VuIHJlcHJlc2VudGVkIGFzIGEgc3RyaW5nXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGpvaW4oZGVsaW1pdGVyOiBzdHJpbmcsIGxpc3RPZlZhbHVlczogc3RyaW5nW10pOiBzdHJpbmcge1xuICAgIGlmIChsaXN0T2ZWYWx1ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEZuSm9pbiByZXF1aXJlcyBhdCBsZWFzdCBvbmUgdmFsdWUgdG8gYmUgcHJvdmlkZWRgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IEZuSm9pbihkZWxpbWl0ZXIsIGxpc3RPZlZhbHVlcykudG9TdHJpbmcoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUbyBzcGxpdCBhIHN0cmluZyBpbnRvIGEgbGlzdCBvZiBzdHJpbmcgdmFsdWVzIHNvIHRoYXQgeW91IGNhbiBzZWxlY3QgYW4gZWxlbWVudCBmcm9tIHRoZVxuICAgKiByZXN1bHRpbmcgc3RyaW5nIGxpc3QsIHVzZSB0aGUgYGBGbjo6U3BsaXRgYCBpbnRyaW5zaWMgZnVuY3Rpb24uIFNwZWNpZnkgdGhlIGxvY2F0aW9uIG9mIHNwbGl0c1xuICAgKiB3aXRoIGEgZGVsaW1pdGVyLCBzdWNoIGFzICwgKGEgY29tbWEpLiBBZnRlciB5b3Ugc3BsaXQgYSBzdHJpbmcsIHVzZSB0aGUgYGBGbjo6U2VsZWN0YGAgZnVuY3Rpb25cbiAgICogdG8gcGljayBhIHNwZWNpZmljIGVsZW1lbnQuXG4gICAqIEBwYXJhbSBkZWxpbWl0ZXIgQSBzdHJpbmcgdmFsdWUgdGhhdCBkZXRlcm1pbmVzIHdoZXJlIHRoZSBzb3VyY2Ugc3RyaW5nIGlzIGRpdmlkZWQuXG4gICAqIEBwYXJhbSBzb3VyY2UgVGhlIHN0cmluZyB2YWx1ZSB0aGF0IHlvdSB3YW50IHRvIHNwbGl0LlxuICAgKiBAcmV0dXJucyBhIHRva2VuIHJlcHJlc2VudGVkIGFzIGEgc3RyaW5nIGFycmF5XG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHNwbGl0KGRlbGltaXRlcjogc3RyaW5nLCBzb3VyY2U6IHN0cmluZyk6IHN0cmluZ1tdIHtcblxuICAgIC8vIHNob3J0LWNpcmN1dCBpZiBzb3VyY2UgaXMgbm90IGEgdG9rZW5cbiAgICBpZiAoIVRva2VuLmlzVW5yZXNvbHZlZChzb3VyY2UpKSB7XG4gICAgICByZXR1cm4gc291cmNlLnNwbGl0KGRlbGltaXRlcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIFRva2VuLmFzTGlzdChuZXcgRm5TcGxpdChkZWxpbWl0ZXIsIHNvdXJjZSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBpbnRyaW5zaWMgZnVuY3Rpb24gYGBGbjo6U2VsZWN0YGAgcmV0dXJucyBhIHNpbmdsZSBvYmplY3QgZnJvbSBhIGxpc3Qgb2Ygb2JqZWN0cyBieSBpbmRleC5cbiAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgb2JqZWN0IHRvIHJldHJpZXZlLiBUaGlzIG11c3QgYmUgYSB2YWx1ZSBmcm9tIHplcm8gdG8gTi0xLCB3aGVyZSBOIHJlcHJlc2VudHMgdGhlIG51bWJlciBvZiBlbGVtZW50cyBpbiB0aGUgYXJyYXkuXG4gICAqIEBwYXJhbSBhcnJheSBUaGUgbGlzdCBvZiBvYmplY3RzIHRvIHNlbGVjdCBmcm9tLiBUaGlzIGxpc3QgbXVzdCBub3QgYmUgbnVsbCwgbm9yIGNhbiBpdCBoYXZlIG51bGwgZW50cmllcy5cbiAgICogQHJldHVybnMgYSB0b2tlbiByZXByZXNlbnRlZCBhcyBhIHN0cmluZ1xuICAgKi9cbiAgcHVibGljIHN0YXRpYyBzZWxlY3QoaW5kZXg6IG51bWJlciwgYXJyYXk6IHN0cmluZ1tdKTogc3RyaW5nIHtcbiAgICBpZiAoIVRva2VuLmlzVW5yZXNvbHZlZChhcnJheSkpIHtcbiAgICAgIHJldHVybiBhcnJheVtpbmRleF07XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBGblNlbGVjdChpbmRleCwgYXJyYXkpLnRvU3RyaW5nKCk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGludHJpbnNpYyBmdW5jdGlvbiBgYEZuOjpTdWJgYCBzdWJzdGl0dXRlcyB2YXJpYWJsZXMgaW4gYW4gaW5wdXQgc3RyaW5nXG4gICAqIHdpdGggdmFsdWVzIHRoYXQgeW91IHNwZWNpZnkuIEluIHlvdXIgdGVtcGxhdGVzLCB5b3UgY2FuIHVzZSB0aGlzIGZ1bmN0aW9uXG4gICAqIHRvIGNvbnN0cnVjdCBjb21tYW5kcyBvciBvdXRwdXRzIHRoYXQgaW5jbHVkZSB2YWx1ZXMgdGhhdCBhcmVuJ3QgYXZhaWxhYmxlXG4gICAqIHVudGlsIHlvdSBjcmVhdGUgb3IgdXBkYXRlIGEgc3RhY2suXG4gICAqIEBwYXJhbSBib2R5IEEgc3RyaW5nIHdpdGggdmFyaWFibGVzIHRoYXQgQVdTIENsb3VkRm9ybWF0aW9uIHN1YnN0aXR1dGVzXG4gICAqIHdpdGggdGhlaXIgYXNzb2NpYXRlZCB2YWx1ZXMgYXQgcnVudGltZS4gV3JpdGUgdmFyaWFibGVzIGFzICR7TXlWYXJOYW1lfS5cbiAgICogVmFyaWFibGVzIGNhbiBiZSB0ZW1wbGF0ZSBwYXJhbWV0ZXIgbmFtZXMsIHJlc291cmNlIGxvZ2ljYWwgSURzLCByZXNvdXJjZVxuICAgKiBhdHRyaWJ1dGVzLCBvciBhIHZhcmlhYmxlIGluIGEga2V5LXZhbHVlIG1hcC4gSWYgeW91IHNwZWNpZnkgb25seSB0ZW1wbGF0ZVxuICAgKiBwYXJhbWV0ZXIgbmFtZXMsIHJlc291cmNlIGxvZ2ljYWwgSURzLCBhbmQgcmVzb3VyY2UgYXR0cmlidXRlcywgZG9uJ3RcbiAgICogc3BlY2lmeSBhIGtleS12YWx1ZSBtYXAuXG4gICAqIEBwYXJhbSB2YXJpYWJsZXMgVGhlIG5hbWUgb2YgYSB2YXJpYWJsZSB0aGF0IHlvdSBpbmNsdWRlZCBpbiB0aGUgU3RyaW5nXG4gICAqIHBhcmFtZXRlci4gVGhlIHZhbHVlIHRoYXQgQVdTIENsb3VkRm9ybWF0aW9uIHN1YnN0aXR1dGVzIGZvciB0aGUgYXNzb2NpYXRlZFxuICAgKiB2YXJpYWJsZSBuYW1lIGF0IHJ1bnRpbWUuXG4gICAqIEByZXR1cm5zIGEgdG9rZW4gcmVwcmVzZW50ZWQgYXMgYSBzdHJpbmdcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgc3ViKGJvZHk6IHN0cmluZywgdmFyaWFibGVzPzogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSk6IHN0cmluZyB7XG4gICAgcmV0dXJuIG5ldyBGblN1Yihib2R5LCB2YXJpYWJsZXMpLnRvU3RyaW5nKCk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGludHJpbnNpYyBmdW5jdGlvbiBgYEZuOjpCYXNlNjRgYCByZXR1cm5zIHRoZSBCYXNlNjQgcmVwcmVzZW50YXRpb24gb2ZcbiAgICogdGhlIGlucHV0IHN0cmluZy4gVGhpcyBmdW5jdGlvbiBpcyB0eXBpY2FsbHkgdXNlZCB0byBwYXNzIGVuY29kZWQgZGF0YSB0b1xuICAgKiBBbWF6b24gRUMyIGluc3RhbmNlcyBieSB3YXkgb2YgdGhlIFVzZXJEYXRhIHByb3BlcnR5LlxuICAgKiBAcGFyYW0gZGF0YSBUaGUgc3RyaW5nIHZhbHVlIHlvdSB3YW50IHRvIGNvbnZlcnQgdG8gQmFzZTY0LlxuICAgKiBAcmV0dXJucyBhIHRva2VuIHJlcHJlc2VudGVkIGFzIGEgc3RyaW5nXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGJhc2U2NChkYXRhOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBuZXcgRm5CYXNlNjQoZGF0YSkudG9TdHJpbmcoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgaW50cmluc2ljIGZ1bmN0aW9uIGBgRm46OkNpZHJgYCByZXR1cm5zIHRoZSBzcGVjaWZpZWQgQ2lkciBhZGRyZXNzIGJsb2NrLlxuICAgKiBAcGFyYW0gaXBCbG9jayAgVGhlIHVzZXItc3BlY2lmaWVkIGRlZmF1bHQgQ2lkciBhZGRyZXNzIGJsb2NrLlxuICAgKiBAcGFyYW0gY291bnQgIFRoZSBudW1iZXIgb2Ygc3VibmV0cycgQ2lkciBibG9jayB3YW50ZWQuIENvdW50IGNhbiBiZSAxIHRvIDI1Ni5cbiAgICogQHBhcmFtIHNpemVNYXNrIFRoZSBkaWdpdCBjb3ZlcmVkIGluIHRoZSBzdWJuZXQuXG4gICAqIEByZXR1cm5zIGEgdG9rZW4gcmVwcmVzZW50ZWQgYXMgYSBzdHJpbmdcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY2lkcihpcEJsb2NrOiBzdHJpbmcsIGNvdW50OiBudW1iZXIsIHNpemVNYXNrPzogc3RyaW5nKTogc3RyaW5nW10ge1xuICAgIHJldHVybiBUb2tlbi5hc0xpc3QobmV3IEZuQ2lkcihpcEJsb2NrLCBjb3VudCwgc2l6ZU1hc2spKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgaW50cmluc2ljIGZ1bmN0aW9uIGBgRm46OkdldEFac2BgIHJldHVybnMgYW4gYXJyYXkgdGhhdCBsaXN0c1xuICAgKiBBdmFpbGFiaWxpdHkgWm9uZXMgZm9yIGEgc3BlY2lmaWVkIHJlZ2lvbi4gQmVjYXVzZSBjdXN0b21lcnMgaGF2ZSBhY2Nlc3MgdG9cbiAgICogZGlmZmVyZW50IEF2YWlsYWJpbGl0eSBab25lcywgdGhlIGludHJpbnNpYyBmdW5jdGlvbiBgYEZuOjpHZXRBWnNgYCBlbmFibGVzXG4gICAqIHRlbXBsYXRlIGF1dGhvcnMgdG8gd3JpdGUgdGVtcGxhdGVzIHRoYXQgYWRhcHQgdG8gdGhlIGNhbGxpbmcgdXNlcidzXG4gICAqIGFjY2Vzcy4gVGhhdCB3YXkgeW91IGRvbid0IGhhdmUgdG8gaGFyZC1jb2RlIGEgZnVsbCBsaXN0IG9mIEF2YWlsYWJpbGl0eVxuICAgKiBab25lcyBmb3IgYSBzcGVjaWZpZWQgcmVnaW9uLlxuICAgKiBAcGFyYW0gcmVnaW9uIFRoZSBuYW1lIG9mIHRoZSByZWdpb24gZm9yIHdoaWNoIHlvdSB3YW50IHRvIGdldCB0aGVcbiAgICogQXZhaWxhYmlsaXR5IFpvbmVzLiBZb3UgY2FuIHVzZSB0aGUgQVdTOjpSZWdpb24gcHNldWRvIHBhcmFtZXRlciB0byBzcGVjaWZ5XG4gICAqIHRoZSByZWdpb24gaW4gd2hpY2ggdGhlIHN0YWNrIGlzIGNyZWF0ZWQuIFNwZWNpZnlpbmcgYW4gZW1wdHkgc3RyaW5nIGlzXG4gICAqIGVxdWl2YWxlbnQgdG8gc3BlY2lmeWluZyBBV1M6OlJlZ2lvbi5cbiAgICogQHJldHVybnMgYSB0b2tlbiByZXByZXNlbnRlZCBhcyBhIHN0cmluZyBhcnJheVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBnZXRBenMocmVnaW9uPzogc3RyaW5nKTogc3RyaW5nW10ge1xuICAgIHJldHVybiBUb2tlbi5hc0xpc3QobmV3IEZuR2V0QVpzKHJlZ2lvbikpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBpbnRyaW5zaWMgZnVuY3Rpb24gYGBGbjo6SW1wb3J0VmFsdWVgYCByZXR1cm5zIHRoZSB2YWx1ZSBvZiBhbiBvdXRwdXRcbiAgICogZXhwb3J0ZWQgYnkgYW5vdGhlciBzdGFjay4gWW91IHR5cGljYWxseSB1c2UgdGhpcyBmdW5jdGlvbiB0byBjcmVhdGVcbiAgICogY3Jvc3Mtc3RhY2sgcmVmZXJlbmNlcy4gSW4gdGhlIGZvbGxvd2luZyBleGFtcGxlIHRlbXBsYXRlIHNuaXBwZXRzLCBTdGFjayBBXG4gICAqIGV4cG9ydHMgVlBDIHNlY3VyaXR5IGdyb3VwIHZhbHVlcyBhbmQgU3RhY2sgQiBpbXBvcnRzIHRoZW0uXG4gICAqIEBwYXJhbSBzaGFyZWRWYWx1ZVRvSW1wb3J0IFRoZSBzdGFjayBvdXRwdXQgdmFsdWUgdGhhdCB5b3Ugd2FudCB0byBpbXBvcnQuXG4gICAqIEByZXR1cm5zIGEgdG9rZW4gcmVwcmVzZW50ZWQgYXMgYSBzdHJpbmdcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgaW1wb3J0VmFsdWUoc2hhcmVkVmFsdWVUb0ltcG9ydDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gbmV3IEZuSW1wb3J0VmFsdWUoc2hhcmVkVmFsdWVUb0ltcG9ydCkudG9TdHJpbmcoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgaW50cmluc2ljIGZ1bmN0aW9uIGBgRm46OkZpbmRJbk1hcGBgIHJldHVybnMgdGhlIHZhbHVlIGNvcnJlc3BvbmRpbmcgdG9cbiAgICoga2V5cyBpbiBhIHR3by1sZXZlbCBtYXAgdGhhdCBpcyBkZWNsYXJlZCBpbiB0aGUgTWFwcGluZ3Mgc2VjdGlvbi5cbiAgICogQHJldHVybnMgYSB0b2tlbiByZXByZXNlbnRlZCBhcyBhIHN0cml