constructs
Version:
A programming model for software-defined state
553 lines • 60.7 kB
JavaScript
"use strict";
var _a, _b, _c;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RootConstruct = exports.ConstructOrder = exports.Construct = exports.Node = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const dependency_1 = require("./dependency");
const stack_trace_1 = require("./private/stack-trace");
const uniqueid_1 = require("./private/uniqueid");
const CONSTRUCT_SYM = Symbol.for('constructs.Construct');
/**
* Represents the construct node in the scope tree.
*/
class Node {
/**
* Returns the node associated with a construct.
* @param construct the construct
*
* @deprecated use `construct.node` instead
*/
static of(construct) {
return construct.node;
}
constructor(host, scope, id) {
this.host = host;
this._locked = false; // if this is "true", addChild will fail
id = id ?? ''; // if undefined, convert to empty string
this.id = sanitizeId(id);
this.scope = scope;
if (scope && !this.id) {
throw new Error('Only root constructs may have an empty ID');
}
if (scope) {
scope.node.addChild(host, this.id);
this.path = scope.node.path ? `${scope.node.path}${Node.PATH_SEP}${this.id}` : this.id;
this._scopes = [...scope.node._scopes, this.host];
}
else {
this.path = this.id;
this._scopes = [this.host];
}
}
/**
* All parent scopes of this construct.
*
* @returns a list of parent scopes. The last element in the list will always
* be the current construct and the first element will be the root of the
* tree.
*/
get scopes() {
// Needs to return a copy to make sure callers can't accidentally mutate
// internal state. jsii doesn't support ReadonlyArray.
return [...this._scopes];
}
/**
* Returns an opaque tree-unique address for this construct.
*
* Addresses are 42 characters hexadecimal strings. They begin with "c8"
* followed by 40 lowercase hexadecimal characters (0-9a-f).
*
* Addresses are calculated using a SHA-1 of the components of the construct
* path.
*
* To enable refactoring of construct trees, constructs with the ID `Default`
* will be excluded from the calculation. In those cases constructs in the
* same tree may have the same address.
*
* @example c83a2846e506bcc5f10682b564084bca2d275709ee
*/
get addr() {
if (!this._addr) {
this._addr = (0, uniqueid_1.addressOf)(this._scopes.map(c => c.node.id));
}
return this._addr;
}
/**
* Return a direct child by id, or undefined
*
* @param id Identifier of direct child
* @returns the child if found, or undefined
*/
tryFindChild(id) {
return this._children?.[sanitizeId(id)];
}
/**
* Return a direct child by id
*
* Throws an error if the child is not found.
*
* @param id Identifier of direct child
* @returns Child with the given id.
*/
findChild(id) {
const ret = this.tryFindChild(id);
if (!ret) {
throw new Error(`No child with id: '${id}'`);
}
return ret;
}
/**
* Returns the child construct that has the id `Default` or `Resource`.
* This is usually the construct that provides the bulk of the underlying functionality.
* Useful for modifications of the underlying construct that are not available at the higher levels.
*
* @throws if there is more than one child
* @returns a construct or undefined if there is no default child
*/
get defaultChild() {
if (this._defaultChild !== undefined) {
return this._defaultChild;
}
const resourceChild = this.tryFindChild('Resource');
const defaultChild = this.tryFindChild('Default');
if (resourceChild && defaultChild) {
throw new Error(`Cannot determine default child for ${this.path}. There is both a child with id "Resource" and id "Default"`);
}
return defaultChild || resourceChild;
}
/**
* Override the defaultChild property.
*
* This should only be used in the cases where the correct
* default child is not named 'Resource' or 'Default' as it
* should be.
*
* If you set this to undefined, the default behavior of finding
* the child named 'Resource' or 'Default' will be used.
*/
set defaultChild(value) {
this._defaultChild = value;
}
/**
* All direct children of this construct.
*/
get children() {
return Object.values(this._children ?? {});
}
/**
* Return this construct and all of its children in the given order
*/
findAll(order = ConstructOrder.PREORDER) {
const ret = new Array();
visit(this.host);
return ret;
function visit(c) {
if (order === ConstructOrder.PREORDER) {
ret.push(c);
}
for (const child of c.node.children) {
visit(child);
}
if (order === ConstructOrder.POSTORDER) {
ret.push(c);
}
}
}
/**
* This can be used to set contextual values.
* Context must be set before any children are added, since children may consult context info during construction.
* If the key already exists, it will be overridden.
* @param key The context key
* @param value The context value
*/
setContext(key, value) {
if (this.children.length > 0) {
const names = this.children.map(c => c.node.id);
throw new Error('Cannot set context after children have been added: ' + names.join(','));
}
if (!this._context) {
this._context = {};
}
this._context[key] = value;
}
/**
* Retrieves a value from tree context if present. Otherwise, would throw an error.
*
* Context is usually initialized at the root, but can be overridden at any point in the tree.
*
* @param key The context key
* @returns The context value or throws error if there is no context value for this key
*/
getContext(key) {
const value = this._context?.[key];
if (value !== undefined) {
return value;
}
if (value === undefined && !this.scope?.node) {
throw new Error(`No context value present for ${key} key`);
}
return this.scope && this.scope.node.getContext(key);
}
/**
* Retrieves the all context of a node from tree context.
*
* Context is usually initialized at the root, but can be overridden at any point in the tree.
*
* @param defaults Any keys to override the retrieved context
* @returns The context object or an empty object if there is discovered context
*/
getAllContext(defaults) {
const ret = { ...defaults };
for (const scope of this._scopes) {
Object.assign(ret, scope.node._context);
}
return ret;
}
/**
* Retrieves a value from tree context.
*
* Context is usually initialized at the root, but can be overridden at any point in the tree.
*
* @param key The context key
* @returns The context value or `undefined` if there is no context value for this key.
*/
tryGetContext(key) {
const value = this._context?.[key];
if (value !== undefined) {
return value;
}
return this.scope && this.scope.node.tryGetContext(key);
}
/**
* An immutable array of metadata objects associated with this construct.
* This can be used, for example, to implement support for deprecation notices, source mapping, etc.
*/
get metadata() {
return [...this._metadata ?? []];
}
/**
* Adds a metadata entry to this construct.
* Entries are arbitrary values and will also include a stack trace to allow tracing back to
* the code location for when the entry was added. It can be used, for example, to include source
* mapping in CloudFormation templates to improve diagnostics.
* Note that construct metadata is not the same as CloudFormation resource metadata and is never written to the CloudFormation template.
* The metadata entries are written to the Cloud Assembly Manifest if the `treeMetadata` property is specified in the props of the App that contains this Construct.
*
* @param type a string denoting the type of metadata
* @param data the value of the metadata (can be a Token). If null/undefined, metadata will not be added.
* @param options options
*/
addMetadata(type, data, options = {}) {
if (data == null) {
return;
}
const node = this;
function getTrace() {
if (options.stackTraceOverride && options.stackTraceOverride.length > 0) {
return options.stackTraceOverride;
}
const shouldTrace = options.stackTrace ?? false;
return shouldTrace ? (0, stack_trace_1.captureStackTrace)(options.traceFromFunction ?? node.addMetadata) : undefined;
}
if (!this._metadata) {
this._metadata = [];
}
this._metadata.push({ type, data, trace: getTrace() });
}
/**
* Returns the root of the construct tree.
* @returns The root of the construct tree.
*/
get root() {
return this._scopes[0];
}
/**
* Returns true if this construct or the scopes in which it is defined are
* locked.
*/
get locked() {
if (this._locked) {
return true;
}
if (this.scope && this.scope.node.locked) {
return true;
}
return false;
}
/**
* Add an ordering dependency on a Dependable (a construct or set of constructs)
*
* It is up to the target document language to decide what an ordering
* relationship means and how it should be rendered; for example, in the AWS
* CDK for CloudFormation it means a dependency from every resource in scope
* of the current construct to every resource in scope of the target set
* of constructs, that get realized as either stack dependencies or
* `DependsOn` relationships in the synthesized template.
*
* `IDependable` is a marker interface that indicates that a class has used
* `Dependable.implement()` to implement the `IDependable` interface. It
* can be used to make the target object represent more than one set of
* constructs at a time. For example, a `DependencyGroup` uses this
* interface to represent an explicit list of 0 or more constructs that should
* be involved in the dependency relationship.
*/
addDependency(...deps) {
if (!this._dependencies) {
this._dependencies = new Set();
}
for (const d of deps) {
this._dependencies.add(d);
}
}
/**
* Remove an ordering dependency on a Dependenable (a construct or set of constructs)
*
* This removes any dependency added using `node.addDependency()`. It must
* use the exact same object that was involved in the `addDependency()` call.
*/
removeDependency(...deps) {
if (!this._dependencies) {
this._dependencies = new Set();
}
for (const d of deps) {
this._dependencies.delete(d);
}
}
/**
* Constructs that this construct depends on directly
*
* This expands the sets of `Dependables` to the set of `Constructs` that they
* represent.
*/
get dependencies() {
const result = new Array();
if (this._dependencies) {
for (const dep of this._dependencies) {
for (const root of dependency_1.Dependable.of(dep).dependencyRoots) {
result.push(root);
}
}
}
return result;
}
/**
* Remove the child with the given name, if present.
*
* @returns Whether a child with the given name was deleted.
*/
tryRemoveChild(childName) {
if (!this._children || !(childName in this._children)) {
return false;
}
delete this._children[childName];
return true;
}
/**
* Adds a validation to this construct.
*
* When `node.validate()` is called, the `validate()` method will be called on
* all validations and all errors will be returned.
*
* @param validation The validation object
*/
addValidation(validation) {
if (!this._validations) {
this._validations = [];
}
this._validations.push(validation);
}
/**
* Validates this construct.
*
* Invokes the `validate()` method on all validations added through
* `addValidation()`.
*
* @returns an array of validation error messages associated with this
* construct.
*/
validate() {
return (this._validations ?? []).flatMap(v => v.validate());
}
/**
* Locks this construct from allowing more children to be added. After this
* call, no more children can be added to this construct or to any children.
*/
lock() {
this._locked = true;
}
/**
* Applies one or more mixins to this construct.
*
* Mixins are applied in order. The list of constructs is captured at the
* start of the call, so constructs added by a mixin will not be visited.
* Use multiple `with()` calls if subsequent mixins should apply to added
* constructs.
*
* @param mixins The mixins to apply
* @returns This construct for chaining
*/
with(...mixins) {
const allConstructs = this.findAll();
for (const mixin of mixins) {
for (const construct of allConstructs) {
if (mixin.supports(construct)) {
mixin.applyTo(construct);
}
}
}
return this.host;
}
;
/**
* Adds a child construct to this node.
*
* @param child The child construct
* @param childName The type name of the child construct.
* @returns The resolved path part name of the child
*/
addChild(child, childName) {
if (this.locked) {
// special error if root is locked
if (!this.path) {
throw new Error('Cannot add children during synthesis');
}
throw new Error(`Cannot add children to "${this.path}" during synthesis`);
}
if (!this._children) {
this._children = {};
}
if (this._children[childName]) {
const name = this.id ?? '';
const typeName = this.host.constructor.name;
throw new Error(`There is already a Construct with name '${childName}' in ${typeName}${name.length > 0 ? ' [' + name + ']' : ''}`);
}
this._children[childName] = child;
}
}
exports.Node = Node;
_a = JSII_RTTI_SYMBOL_1;
Node[_a] = { fqn: "constructs.Node", version: "10.7.1" };
/**
* Separator used to delimit construct path components.
*/
Node.PATH_SEP = '/';
/**
* Represents the building block of the construct graph.
*
* All constructs besides the root construct must be created within the scope of
* another construct.
*/
class Construct {
/**
* Checks if `x` is a construct.
*
* Use this method instead of `instanceof` to properly detect `Construct`
* instances, even when the construct library is symlinked.
*
* Explanation: in JavaScript, multiple copies of the `constructs` library on
* disk are seen as independent, completely different libraries. As a
* consequence, the class `Construct` in each copy of the `constructs` library
* is seen as a different class, and an instance of one class will not test as
* `instanceof` the other class. `npm install` will not create installations
* like this, but users may manually symlink construct libraries together or
* use a monorepo tool: in those cases, multiple copies of the `constructs`
* library can be accidentally installed, and `instanceof` will behave
* unpredictably. It is safest to avoid using `instanceof`, and using
* this type-testing method instead.
*
* @returns true if `x` is an object created from a class which extends `Construct`.
* @param x Any object
*/
static isConstruct(x) {
return x && typeof x === 'object' && x[CONSTRUCT_SYM];
}
/**
* Creates a new construct node.
*
* @param scope The scope in which to define this construct
* @param id The scoped construct ID. Must be unique amongst siblings. If
* the ID includes a path separator (`/`), then it will be replaced by double
* dash `--`.
*/
constructor(scope, id) {
this.node = new Node(this, scope, id);
// implement IDependable privately
dependency_1.Dependable.implement(this, {
dependencyRoots: [this],
});
}
/**
* Applies one or more mixins to this construct.
*
* Mixins are applied in order. The list of constructs is captured at the
* start of the call, so constructs added by a mixin will not be visited.
* Use multiple `with()` calls if subsequent mixins should apply to added
* constructs.
*
* @param mixins The mixins to apply
* @returns This construct for chaining
*/
with(...mixins) {
return this.node.with(...mixins);
}
;
/**
* Returns a string representation of this construct.
*/
toString() {
return this.node.path || '<root>';
}
}
exports.Construct = Construct;
_b = JSII_RTTI_SYMBOL_1;
Construct[_b] = { fqn: "constructs.Construct", version: "10.7.1" };
/**
* In what order to return constructs
*/
var ConstructOrder;
(function (ConstructOrder) {
/**
* Depth-first, pre-order
*/
ConstructOrder[ConstructOrder["PREORDER"] = 0] = "PREORDER";
/**
* Depth-first, post-order (leaf nodes first)
*/
ConstructOrder[ConstructOrder["POSTORDER"] = 1] = "POSTORDER";
})(ConstructOrder || (exports.ConstructOrder = ConstructOrder = {}));
const PATH_SEP_REGEX = new RegExp(`${Node.PATH_SEP}`, 'g');
/**
* Return a sanitized version of an arbitrary string, so it can be used as an ID
*/
function sanitizeId(id) {
// Escape path seps as double dashes
return id.replace(PATH_SEP_REGEX, '--');
}
// Mark all instances of 'Construct'
Object.defineProperty(Construct.prototype, CONSTRUCT_SYM, {
value: true,
enumerable: false,
writable: false,
});
/**
* Creates a new root construct node.
*
* The root construct represents the top of the construct tree and is not contained within a parent scope itself.
* For root constructs, the id is optional.
*/
class RootConstruct extends Construct {
/**
* Creates a new root construct node.
*
* @param id The scoped construct ID. Must be unique amongst siblings. If
* the ID includes a path separator (`/`), then it will be replaced by double
* dash `--`.
*/
constructor(id) {
super(undefined, id ?? '');
}
}
exports.RootConstruct = RootConstruct;
_c = JSII_RTTI_SYMBOL_1;
RootConstruct[_c] = { fqn: "constructs.RootConstruct", version: "10.7.1" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RydWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NvbnN0cnVjdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUNBLDZDQUEwQztBQUcxQyx1REFBMEQ7QUFDMUQsaURBQStDO0FBRS9DLE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsc0JBQXNCLENBQUMsQ0FBQztBQXVCekQ7O0dBRUc7QUFDSCxNQUFhLElBQUk7SUFNZjs7Ozs7T0FLRztJQUNJLE1BQU0sQ0FBQyxFQUFFLENBQUMsU0FBcUI7UUFDcEMsT0FBTyxTQUFTLENBQUMsSUFBSSxDQUFDO0lBQ3hCLENBQUM7SUFrQ0QsWUFBb0MsSUFBZSxFQUFFLEtBQWlCLEVBQUUsRUFBVTtRQUE5QyxTQUFJLEdBQUosSUFBSSxDQUFXO1FBWDNDLFlBQU8sR0FBRyxLQUFLLENBQUMsQ0FBQyx3Q0FBd0M7UUFZL0QsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyx3Q0FBd0M7UUFFdkQsSUFBSSxDQUFDLEVBQUUsR0FBRyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDekIsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7UUFFbkIsSUFBSSxLQUFLLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDdEIsTUFBTSxJQUFJLEtBQUssQ0FBQywyQ0FBMkMsQ0FBQyxDQUFDO1FBQy9ELENBQUM7UUFFRCxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ1YsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNuQyxJQUFJLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLEVBQUUsRUFB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QWEsRUFBRTtJQUN4RCxLQUFLLEVBQUUsSUFBSTtJQUNYLFVBQVUsRUFBRSxLQUFLO0lBQ2pCLFFBQVEsRUFBRSxLQUFLO0NBQ2hCLENBQUMsQ0FBQztBQUVIOzs7OztHQUtHO0FBQ0gsTUFBYSxhQUFjLFNBQVEsU0FBUztJQUMxQzs7Ozs7O09BTUc7SUFDSCxZQUFZLEVBQVc7UUFDckIsS0FBSyxDQUFDLFNBQWdCLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3BDLENBQUM7O0FBVkgsc0NBV0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IElEZXBlbmRhYmxlIH0gZnJvbSAnLi9kZXBlbmRlbmN5JztcbmltcG9ydCB7IERlcGVuZGFibGUgfSBmcm9tICcuL2RlcGVuZGVuY3knO1xuaW1wb3J0IHR5cGUgeyBNZXRhZGF0YUVudHJ5IH0gZnJvbSAnLi9tZXRhZGF0YSc7XG5pbXBvcnQgdHlwZSB7IElNaXhpbiB9IGZyb20gJy4vbWl4aW4nO1xuaW1wb3J0IHsgY2FwdHVyZVN0YWNrVHJhY2UgfSBmcm9tICcuL3ByaXZhdGUvc3RhY2stdHJhY2UnO1xuaW1wb3J0IHsgYWRkcmVzc09mIH0gZnJvbSAnLi9wcml2YXRlL3VuaXF1ZWlkJztcblxuY29uc3QgQ09OU1RSVUNUX1NZTSA9IFN5bWJvbC5mb3IoJ2NvbnN0cnVjdHMuQ29uc3RydWN0Jyk7XG5cbi8qKlxuICogUmVwcmVzZW50cyBhIGNvbnN0cnVjdC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJQ29uc3RydWN0IGV4dGVuZHMgSURlcGVuZGFibGUge1xuICAvKipcbiAgICogVGhlIHRyZWUgbm9kZS5cbiAgICovXG4gIHJlYWRvbmx5IG5vZGU6IE5vZGU7XG5cbiAgLyoqXG4gICAqIEFwcGxpZXMgb25lIG9yIG1vcmUgbWl4aW5zIHRvIHRoaXMgY29uc3RydWN0LlxuICAgKlxuICAgKiBNaXhpbnMgYXJlIGFwcGxpZWQgaW4gb3JkZXIuIFRoZSBsaXN0IG9mIGNvbnN0cnVjdHMgaXMgY2FwdHVyZWQgYXQgdGhlXG4gICAqIHN0YXJ0IG9mIHRoZSBjYWxsLCBzbyBjb25zdHJ1Y3RzIGFkZGVkIGJ5IGEgbWl4aW4gd2lsbCBub3QgYmUgdmlzaXRlZC5cbiAgICpcbiAgICogQHBhcmFtIG1peGlucyBUaGUgbWl4aW5zIHRvIGFwcGx5XG4gICAqIEByZXR1cm5zIFRoaXMgY29uc3RydWN0IGZvciBjaGFpbmluZ1xuICAgKi9cbiAgd2l0aCguLi5taXhpbnM6IElNaXhpbltdKTogSUNvbnN0cnVjdDtcbn1cblxuLyoqXG4gKiBSZXByZXNlbnRzIHRoZSBjb25zdHJ1Y3Qgbm9kZSBpbiB0aGUgc2NvcGUgdHJlZS5cbiAqL1xuZXhwb3J0IGNsYXNzIE5vZGUge1xuICAvKipcbiAgICogU2VwYXJhdG9yIHVzZWQgdG8gZGVsaW1pdCBjb25zdHJ1Y3QgcGF0aCBjb21wb25lbnRzLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBQQVRIX1NFUCA9ICcvJztcblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgbm9kZSBhc3NvY2lhdGVkIHdpdGggYSBjb25zdHJ1Y3QuXG4gICAqIEBwYXJhbSBjb25zdHJ1Y3QgdGhlIGNvbnN0cnVjdFxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCB1c2UgYGNvbnN0cnVjdC5ub2RlYCBpbnN0ZWFkXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIG9mKGNvbnN0cnVjdDogSUNvbnN0cnVjdCk6IE5vZGUge1xuICAgIHJldHVybiBjb25zdHJ1Y3Qubm9kZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBzY29wZSBpbiB3aGljaCB0aGlzIGNvbnN0cnVjdCBpcyBkZWZpbmVkLlxuICAgKlxuICAgKiBUaGUgdmFsdWUgaXMgYHVuZGVmaW5lZGAgYXQgdGhlIHJvb3Qgb2YgdGhlIGNvbnN0cnVjdCBzY29wZSB0cmVlLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHNjb3BlPzogSUNvbnN0cnVjdDtcblxuICAvKipcbiAgICogVGhlIGlkIG9mIHRoaXMgY29uc3RydWN0IHdpdGhpbiB0aGUgY3VycmVudCBzY29wZS5cbiAgICpcbiAgICogVGhpcyBpcyBhIHNjb3BlLXVuaXF1ZSBpZC4gVG8gb2J0YWluIGFuIGFwcC11bmlxdWUgaWQgZm9yIHRoaXMgY29uc3RydWN0LCB1c2UgYGFkZHJgLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGlkOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBmdWxsLCBhYnNvbHV0ZSBwYXRoIG9mIHRoaXMgY29uc3RydWN0IGluIHRoZSB0cmVlLlxuICAgKlxuICAgKiBDb21wb25lbnRzIGFyZSBzZXBhcmF0ZWQgYnkgJy8nLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHBhdGg6IHN0cmluZztcblxuICBwcml2YXRlIF9sb2NrZWQgPSBmYWxzZTsgLy8gaWYgdGhpcyBpcyBcInRydWVcIiwgYWRkQ2hpbGQgd2lsbCBmYWlsXG4gIHByaXZhdGUgX2NoaWxkcmVuOiB7IFtpZDogc3RyaW5nXTogSUNvbnN0cnVjdCB9IHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIF9jb250ZXh0OiB7IFtrZXk6IHN0cmluZ106IGFueSB9IHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIF9tZXRhZGF0YTogQXJyYXk8TWV0YWRhdGFFbnRyeT4gfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgX2RlcGVuZGVuY2llczogU2V0PElEZXBlbmRhYmxlPiB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBfZGVmYXVsdENoaWxkOiBJQ29uc3RydWN0IHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIF92YWxpZGF0aW9uczogQXJyYXk8SVZhbGlkYXRpb24+IHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIF9hZGRyPzogc3RyaW5nOyAvLyBjYWNoZVxuICBwcml2YXRlIF9zY29wZXM6IHJlYWRvbmx5IElDb25zdHJ1Y3RbXTtcblxuXG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IGhvc3Q6IENvbnN0cnVjdCwgc2NvcGU6IElDb25zdHJ1Y3QsIGlkOiBzdHJpbmcpIHtcbiAgICBpZCA9IGlkID8/ICcnOyAvLyBpZiB1bmRlZmluZWQsIGNvbnZlcnQgdG8gZW1wdHkgc3RyaW5nXG5cbiAgICB0aGlzLmlkID0gc2FuaXRpemVJZChpZCk7XG4gICAgdGhpcy5zY29wZSA9IHNjb3BlO1xuXG4gICAgaWYgKHNjb3BlICYmICF0aGlzLmlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ09ubHkgcm9vdCBjb25zdHJ1Y3RzIG1heSBoYXZlIGFuIGVtcHR5IElEJyk7XG4gICAgfVxuXG4gICAgaWYgKHNjb3BlKSB7XG4gICAgICBzY29wZS5ub2RlLmFkZENoaWxkKGhvc3QsIHRoaXMuaWQpO1xuICAgICAgdGhpcy5wYXRoID0gc2NvcGUubm9kZS5wYXRoID8gYCR7c2NvcGUubm9kZS5wYXRofSR7Tm9kZS5QQVRIX1NFUH0ke3RoaXMuaWR9YCA6IHRoaXMuaWQ7XG4gICAgICB0aGlzLl9zY29wZXMgPSBbLi4uc2NvcGUubm9kZS5fc2NvcGVzLCB0aGlzLmhvc3RdO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnBhdGggPSB0aGlzLmlkO1xuICAgICAgdGhpcy5fc2NvcGVzID0gW3RoaXMuaG9zdF07XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFsbCBwYXJlbnQgc2NvcGVzIG9mIHRoaXMgY29uc3RydWN0LlxuICAgKlxuICAgKiBAcmV0dXJucyBhIGxpc3Qgb2YgcGFyZW50IHNjb3Blcy4gVGhlIGxhc3QgZWxlbWVudCBpbiB0aGUgbGlzdCB3aWxsIGFsd2F5c1xuICAgKiBiZSB0aGUgY3VycmVudCBjb25zdHJ1Y3QgYW5kIHRoZSBmaXJzdCBlbGVtZW50IHdpbGwgYmUgdGhlIHJvb3Qgb2YgdGhlXG4gICAqIHRyZWUuXG4gICAqL1xuICBwdWJsaWMgZ2V0IHNjb3BlcygpOiBJQ29uc3RydWN0W10ge1xuICAgIC8vIE5lZWRzIHRvIHJldHVybiBhIGNvcHkgdG8gbWFrZSBzdXJlIGNhbGxlcnMgY2FuJ3QgYWNjaWRlbnRhbGx5IG11dGF0ZVxuICAgIC8vIGludGVybmFsIHN0YXRlLiBqc2lpIGRvZXNuJ3Qgc3VwcG9ydCBSZWFkb25seUFycmF5LlxuICAgIHJldHVybiBbLi4udGhpcy5fc2NvcGVzXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFuIG9wYXF1ZSB0cmVlLXVuaXF1ZSBhZGRyZXNzIGZvciB0aGlzIGNvbnN0cnVjdC5cbiAgICpcbiAgICogQWRkcmVzc2VzIGFyZSA0MiBjaGFyYWN0ZXJzIGhleGFkZWNpbWFsIHN0cmluZ3MuIFRoZXkgYmVnaW4gd2l0aCBcImM4XCJcbiAgICogZm9sbG93ZWQgYnkgNDAgbG93ZXJjYXNlIGhleGFkZWNpbWFsIGNoYXJhY3RlcnMgKDAtOWEtZikuXG4gICAqXG4gICAqIEFkZHJlc3NlcyBhcmUgY2FsY3VsYXRlZCB1c2luZyBhIFNIQS0xIG9mIHRoZSBjb21wb25lbnRzIG9mIHRoZSBjb25zdHJ1Y3RcbiAgICogcGF0aC5cbiAgICpcbiAgICogVG8gZW5hYmxlIHJlZmFjdG9yaW5nIG9mIGNvbnN0cnVjdCB0cmVlcywgY29uc3RydWN0cyB3aXRoIHRoZSBJRCBgRGVmYXVsdGBcbiAgICogd2lsbCBiZSBleGNsdWRlZCBmcm9tIHRoZSBjYWxjdWxhdGlvbi4gSW4gdGhvc2UgY2FzZXMgY29uc3RydWN0cyBpbiB0aGVcbiAgICogc2FtZSB0cmVlIG1heSBoYXZlIHRoZSBzYW1lIGFkZHJlc3MuXG4gICAqXG4gICAqIEBleGFtcGxlIGM4M2EyODQ2ZTUwNmJjYzVmMTA2ODJiNTY0MDg0YmNhMmQyNzU3MDllZVxuICAgKi9cbiAgcHVibGljIGdldCBhZGRyKCk6IHN0cmluZyB7XG4gICAgaWYgKCF0aGlzLl9hZGRyKSB7XG4gICAgICB0aGlzLl9hZGRyID0gYWRkcmVzc09mKHRoaXMuX3Njb3Blcy5tYXAoYyA9PiBjLm5vZGUuaWQpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fYWRkcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYSBkaXJlY3QgY2hpbGQgYnkgaWQsIG9yIHVuZGVmaW5lZFxuICAgKlxuICAgKiBAcGFyYW0gaWQgSWRlbnRpZmllciBvZiBkaXJlY3QgY2hpbGRcbiAgICogQHJldHVybnMgdGhlIGNoaWxkIGlmIGZvdW5kLCBvciB1bmRlZmluZWRcbiAgICovXG4gIHB1YmxpYyB0cnlGaW5kQ2hpbGQoaWQ6IHN0cmluZyk6IElDb25zdHJ1Y3QgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl9jaGlsZHJlbj8uW3Nhbml0aXplSWQoaWQpXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYSBkaXJlY3QgY2hpbGQgYnkgaWRcbiAgICpcbiAgICogVGhyb3dzIGFuIGVycm9yIGlmIHRoZSBjaGlsZCBpcyBub3QgZm91bmQuXG4gICAqXG4gICAqIEBwYXJhbSBpZCBJZGVudGlmaWVyIG9mIGRpcmVjdCBjaGlsZFxuICAgKiBAcmV0dXJucyBDaGlsZCB3aXRoIHRoZSBnaXZlbiBpZC5cbiAgICovXG4gIHB1YmxpYyBmaW5kQ2hpbGQoaWQ6IHN0cmluZyk6IElDb25zdHJ1Y3Qge1xuICAgIGNvbnN0IHJldCA9IHRoaXMudHJ5RmluZENoaWxkKGlkKTtcbiAgICBpZiAoIXJldCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyBjaGlsZCB3aXRoIGlkOiAnJHtpZH0nYCk7XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY2hpbGQgY29uc3RydWN0IHRoYXQgaGFzIHRoZSBpZCBgRGVmYXVsdGAgb3IgYFJlc291cmNlYC5cbiAgICogVGhpcyBpcyB1c3VhbGx5IHRoZSBjb25zdHJ1Y3QgdGhhdCBwcm92aWRlcyB0aGUgYnVsayBvZiB0aGUgdW5kZXJseWluZyBmdW5jdGlvbmFsaXR5LlxuICAgKiBVc2VmdWwgZm9yIG1vZGlmaWNhdGlvbnMgb2YgdGhlIHVuZGVybHlpbmcgY29uc3RydWN0IHRoYXQgYXJlIG5vdCBhdmFpbGFibGUgYXQgdGhlIGhpZ2hlciBsZXZlbHMuXG4gICAqXG4gICAqIEB0aHJvd3MgaWYgdGhlcmUgaXMgbW9yZSB0aGFuIG9uZSBjaGlsZFxuICAgKiBAcmV0dXJucyBhIGNvbnN0cnVjdCBvciB1bmRlZmluZWQgaWYgdGhlcmUgaXMgbm8gZGVmYXVsdCBjaGlsZFxuICAgKi9cbiAgcHVibGljIGdldCBkZWZhdWx0Q2hpbGQoKTogSUNvbnN0cnVjdCB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKHRoaXMuX2RlZmF1bHRDaGlsZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gdGhpcy5fZGVmYXVsdENoaWxkO1xuICAgIH1cblxuICAgIGNvbnN0IHJlc291cmNlQ2hpbGQgPSB0aGlzLnRyeUZpbmRDaGlsZCgnUmVzb3VyY2UnKTtcbiAgICBjb25zdCBkZWZhdWx0Q2hpbGQgPSB0aGlzLnRyeUZpbmRDaGlsZCgnRGVmYXVsdCcpO1xuICAgIGlmIChyZXNvdXJjZUNoaWxkICYmIGRlZmF1bHRDaGlsZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgZGV0ZXJtaW5lIGRlZmF1bHQgY2hpbGQgZm9yICR7dGhpcy5wYXRofS4gVGhlcmUgaXMgYm90aCBhIGNoaWxkIHdpdGggaWQgXCJSZXNvdXJjZVwiIGFuZCBpZCBcIkRlZmF1bHRcImApO1xuICAgIH1cblxuICAgIHJldHVybiBkZWZhdWx0Q2hpbGQgfHwgcmVzb3VyY2VDaGlsZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBPdmVycmlkZSB0aGUgZGVmYXVsdENoaWxkIHByb3BlcnR5LlxuICAgKlxuICAgKiBUaGlzIHNob3VsZCBvbmx5IGJlIHVzZWQgaW4gdGhlIGNhc2VzIHdoZXJlIHRoZSBjb3JyZWN0XG4gICAqIGRlZmF1bHQgY2hpbGQgaXMgbm90IG5hbWVkICdSZXNvdXJjZScgb3IgJ0RlZmF1bHQnIGFzIGl0XG4gICAqIHNob3VsZCBiZS5cbiAgICpcbiAgICogSWYgeW91IHNldCB0aGlzIHRvIHVuZGVmaW5lZCwgdGhlIGRlZmF1bHQgYmVoYXZpb3Igb2YgZmluZGluZ1xuICAgKiB0aGUgY2hpbGQgbmFtZWQgJ1Jlc291cmNlJyBvciAnRGVmYXVsdCcgd2lsbCBiZSB1c2VkLlxuICAgKi9cbiAgcHVibGljIHNldCBkZWZhdWx0Q2hpbGQodmFsdWU6IElDb25zdHJ1Y3QgfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLl9kZWZhdWx0Q2hpbGQgPSB2YWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbGwgZGlyZWN0IGNoaWxkcmVuIG9mIHRoaXMgY29uc3RydWN0LlxuICAgKi9cbiAgcHVibGljIGdldCBjaGlsZHJlbigpIHtcbiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyh0aGlzLl9jaGlsZHJlbiA/PyB7fSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIHRoaXMgY29uc3RydWN0IGFuZCBhbGwgb2YgaXRzIGNoaWxkcmVuIGluIHRoZSBnaXZlbiBvcmRlclxuICAgKi9cbiAgcHVibGljIGZpbmRBbGwob3JkZXI6IENvbnN0cnVjdE9yZGVyID0gQ29uc3RydWN0T3JkZXIuUFJFT1JERVIpOiBJQ29uc3RydWN0W10ge1xuICAgIGNvbnN0IHJldCA9IG5ldyBBcnJheTxJQ29uc3RydWN0PigpO1xuICAgIHZpc2l0KHRoaXMuaG9zdCk7XG4gICAgcmV0dXJuIHJldDtcblxuICAgIGZ1bmN0aW9uIHZpc2l0KGM6IElDb25zdHJ1Y3QpIHtcbiAgICAgIGlmIChvcmRlciA9PT0gQ29uc3RydWN0T3JkZXIuUFJFT1JERVIpIHtcbiAgICAgICAgcmV0LnB1c2goYyk7XG4gICAgICB9XG5cbiAgICAgIGZvciAoY29uc3QgY2hpbGQgb2YgYy5ub2RlLmNoaWxkcmVuKSB7XG4gICAgICAgIHZpc2l0KGNoaWxkKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9yZGVyID09PSBDb25zdHJ1Y3RPcmRlci5QT1NUT1JERVIpIHtcbiAgICAgICAgcmV0LnB1c2goYyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgY2FuIGJlIHVzZWQgdG8gc2V0IGNvbnRleHR1YWwgdmFsdWVzLlxuICAgKiBDb250ZXh0IG11c3QgYmUgc2V0IGJlZm9yZSBhbnkgY2hpbGRyZW4gYXJlIGFkZGVkLCBzaW5jZSBjaGlsZHJlbiBtYXkgY29uc3VsdCBjb250ZXh0IGluZm8gZHVyaW5nIGNvbnN0cnVjdGlvbi5cbiAgICogSWYgdGhlIGtleSBhbHJlYWR5IGV4aXN0cywgaXQgd2lsbCBiZSBvdmVycmlkZGVuLlxuICAgKiBAcGFyYW0ga2V5IFRoZSBjb250ZXh0IGtleVxuICAgKiBAcGFyYW0gdmFsdWUgVGhlIGNvbnRleHQgdmFsdWVcbiAgICovXG4gIHB1YmxpYyBzZXRDb250ZXh0KGtleTogc3RyaW5nLCB2YWx1ZTogYW55KSB7XG4gICAgaWYgKHRoaXMuY2hpbGRyZW4ubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgbmFtZXMgPSB0aGlzLmNoaWxkcmVuLm1hcChjID0+IGMubm9kZS5pZCk7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBzZXQgY29udGV4dCBhZnRlciBjaGlsZHJlbiBoYXZlIGJlZW4gYWRkZWQ6ICcgKyBuYW1lcy5qb2luKCcsJykpO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuX2NvbnRleHQpIHtcbiAgICAgIHRoaXMuX2NvbnRleHQgPSB7fTtcbiAgICB9XG4gICAgdGhpcy5fY29udGV4dFtrZXldID0gdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIGEgdmFsdWUgZnJvbSB0cmVlIGNvbnRleHQgaWYgcHJlc2VudC4gT3RoZXJ3aXNlLCB3b3VsZCB0aHJvdyBhbiBlcnJvci5cbiAgICpcbiAgICogQ29udGV4dCBpcyB1c3VhbGx5IGluaXRpYWxpemVkIGF0IHRoZSByb290LCBidXQgY2FuIGJlIG92ZXJyaWRkZW4gYXQgYW55IHBvaW50IGluIHRoZSB0cmVlLlxuICAgKlxuICAgKiBAcGFyYW0ga2V5IFRoZSBjb250ZXh0IGtleVxuICAgKiBAcmV0dXJucyBUaGUgY29udGV4dCB2YWx1ZSBvciB0aHJvd3MgZXJyb3IgaWYgdGhlcmUgaXMgbm8gY29udGV4dCB2YWx1ZSBmb3IgdGhpcyBrZXlcbiAgICovXG4gIHB1YmxpYyBnZXRDb250ZXh0KGtleTogc3RyaW5nKTogYW55IHtcbiAgICBjb25zdCB2YWx1ZSA9IHRoaXMuX2NvbnRleHQ/LltrZXldO1xuXG4gICAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHsgcmV0dXJuIHZhbHVlOyB9XG5cbiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCAmJiAhdGhpcy5zY29wZT8ubm9kZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyBjb250ZXh0IHZhbHVlIHByZXNlbnQgZm9yICR7a2V5fSBrZXlgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zY29wZSAmJiB0aGlzLnNjb3BlLm5vZGUuZ2V0Q29udGV4dChrZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyB0aGUgYWxsIGNvbnRleHQgb2YgYSBub2RlIGZyb20gdHJlZSBjb250ZXh0LlxuICAgKlxuICAgKiBDb250ZXh0IGlzIHVzdWFsbHkgaW5pdGlhbGl6ZWQgYXQgdGhlIHJvb3QsIGJ1dCBjYW4gYmUgb3ZlcnJpZGRlbiBhdCBhbnkgcG9pbnQgaW4gdGhlIHRyZWUuXG4gICAqXG4gICAqIEBwYXJhbSBkZWZhdWx0cyBBbnkga2V5cyB0byBvdmVycmlkZSB0aGUgcmV0cmlldmVkIGNvbnRleHRcbiAgICogQHJldHVybnMgVGhlIGNvbnRleHQgb2JqZWN0IG9yIGFuIGVtcHR5IG9iamVjdCBpZiB0aGVyZSBpcyBkaXNjb3ZlcmVkIGNvbnRleHRcbiAgICovXG4gIHB1YmxpYyBnZXRBbGxDb250ZXh0KGRlZmF1bHRzPzogb2JqZWN0KTogYW55IHtcbiAgICBjb25zdCByZXQgPSB7IC4uLmRlZmF1bHRzIH07XG4gICAgZm9yIChjb25zdCBzY29wZSBvZiB0aGlzLl9zY29wZXMpIHtcbiAgICAgIE9iamVjdC5hc3NpZ24ocmV0LCBzY29wZS5ub2RlLl9jb250ZXh0KTtcbiAgICB9XG4gICAgcmV0dXJuIHJldDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgYSB2YWx1ZSBmcm9tIHRyZWUgY29udGV4dC5cbiAgICpcbiAgICogQ29udGV4dCBpcyB1c3VhbGx5IGluaXRpYWxpemVkIGF0IHRoZSByb290LCBidXQgY2FuIGJlIG92ZXJyaWRkZW4gYXQgYW55IHBvaW50IGluIHRoZSB0cmVlLlxuICAgKlxuICAgKiBAcGFyYW0ga2V5IFRoZSBjb250ZXh0IGtleVxuICAgKiBAcmV0dXJucyBUaGUgY29udGV4dCB2YWx1ZSBvciBgdW5kZWZpbmVkYCBpZiB0aGVyZSBpcyBubyBjb250ZXh0IHZhbHVlIGZvciB0aGlzIGtleS5cbiAgICovXG4gIHB1YmxpYyB0cnlHZXRDb250ZXh0KGtleTogc3RyaW5nKTogYW55IHtcbiAgICBjb25zdCB2YWx1ZSA9IHRoaXMuX2NvbnRleHQ/LltrZXldO1xuICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7IHJldHVybiB2YWx1ZTsgfVxuXG4gICAgcmV0dXJuIHRoaXMuc2NvcGUgJiYgdGhpcy5zY29wZS5ub2RlLnRyeUdldENvbnRleHQoa2V5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbiBpbW11dGFibGUgYXJyYXkgb2YgbWV0YWRhdGEgb2JqZWN0cyBhc3NvY2lhdGVkIHdpdGggdGhpcyBjb25zdHJ1Y3QuXG4gICAqIFRoaXMgY2FuIGJlIHVzZWQsIGZvciBleGFtcGxlLCB0byBpbXBsZW1lbnQgc3VwcG9ydCBmb3IgZGVwcmVjYXRpb24gbm90aWNlcywgc291cmNlIG1hcHBpbmcsIGV0Yy5cbiAgICovXG4gIHB1YmxpYyBnZXQgbWV0YWRhdGEoKSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLl9tZXRhZGF0YSA/PyBbXV07XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIG1ldGFkYXRhIGVudHJ5IHRvIHRoaXMgY29uc3RydWN0LlxuICAgKiBFbnRyaWVzIGFyZSBhcmJpdHJhcnkgdmFsdWVzIGFuZCB3aWxsIGFsc28gaW5jbHVkZSBhIHN0YWNrIHRyYWNlIHRvIGFsbG93IHRyYWNpbmcgYmFjayB0b1xuICAgKiB0aGUgY29kZSBsb2NhdGlvbiBmb3Igd2hlbiB0aGUgZW50cnkgd2FzIGFkZGVkLiBJdCBjYW4gYmUgdXNlZCwgZm9yIGV4YW1wbGUsIHRvIGluY2x1ZGUgc291cmNlXG4gICAqIG1hcHBpbmcgaW4gQ2xvdWRGb3JtYXRpb24gdGVtcGxhdGVzIHRvIGltcHJvdmUgZGlhZ25vc3RpY3MuXG4gICAqIE5vdGUgdGhhdCBjb25zdHJ1Y3QgbWV0YWRhdGEgaXMgbm90IHRoZSBzYW1lIGFzIENsb3VkRm9ybWF0aW9uIHJlc291cmNlIG1ldGFkYXRhIGFuZCBpcyBuZXZlciB3cml0dGVuIHRvIHRoZSBDbG91ZEZvcm1hdGlvbiB0ZW1wbGF0ZS5cbiAgICogVGhlIG1ldGFkYXRhIGVudHJpZXMgYXJlIHdyaXR0ZW4gdG8gdGhlIENsb3VkIEFzc2VtYmx5IE1hbmlmZXN0IGlmIHRoZSBgdHJlZU1ldGFkYXRhYCBwcm9wZXJ0eSBpcyBzcGVjaWZpZWQgaW4gdGhlIHByb3BzIG9mIHRoZSBBcHAgdGhhdCBjb250YWlucyB0aGlzIENvbnN0cnVjdC5cbiAgICpcbiAgICogQHBhcmFtIHR5cGUgYSBzdHJpbmcgZGVub3RpbmcgdGhlIHR5cGUgb2YgbWV0YWRhdGFcbiAgICogQHBhcmFtIGRhdGEgdGhlIHZhbHVlIG9mIHRoZSBtZXRhZGF0YSAoY2FuIGJlIGEgVG9rZW4pLiBJZiBudWxsL3VuZGVmaW5lZCwgbWV0YWRhdGEgd2lsbCBub3QgYmUgYWRkZWQuXG4gICAqIEBwYXJhbSBvcHRpb25zIG9wdGlvbnNcbiAgICovXG4gIHB1YmxpYyBhZGRNZXRhZGF0YSh0eXBlOiBzdHJpbmcsIGRhdGE6IGFueSwgb3B0aW9uczogTWV0YWRhdGFPcHRpb25zID0geyB9KTogdm9pZCB7XG4gICAgaWYgKGRhdGEgPT0gbnVsbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IG5vZGUgPSB0aGlzO1xuICAgIGZ1bmN0aW9uIGdldFRyYWNlKCkge1xuICAgICAgaWYgKG9wdGlvbnMuc3RhY2tUcmFjZU92ZXJyaWRlICYmIG9wdGlvbnMuc3RhY2tUcmFjZU92ZXJyaWRlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgcmV0dXJuIG9wdGlvbnMuc3RhY2tUcmFjZU92ZXJyaWRlO1xuICAgICAgfVxuICAgICAgY29uc3Qgc2hvdWxkVHJhY2UgPSBvcHRpb25zLnN0YWNrVHJhY2UgPz8gZmFsc2U7XG4gICAgICByZXR1cm4gc2hvdWxkVHJhY2UgPyBjYXB0dXJlU3RhY2tUcmFjZShvcHRpb25zLnRyYWNlRnJvbUZ1bmN0aW9uID8/IG5vZGUuYWRkTWV0YWRhdGEpIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5fbWV0YWRhdGEpIHtcbiAgICAgIHRoaXMuX21ldGFkYXRhID0gW107XG4gICAgfVxuICAgIHRoaXMuX21ldGFkYXRhLnB1c2goeyB0eXBlLCBkYXRhLCB0cmFjZTogZ2V0VHJhY2UoKSB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSByb290IG9mIHRoZSBjb25zdHJ1Y3QgdHJlZS5cbiAgICogQHJldHVybnMgVGhlIHJvb3Qgb2YgdGhlIGNvbnN0cnVjdCB0cmVlLlxuICAgKi9cbiAgcHVibGljIGdldCByb290KCkge1xuICAgIHJldHVybiB0aGlzLl9zY29wZXNbMF07XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0cnVlIGlmIHRoaXMgY29uc3RydWN0IG9yIHRoZSBzY29wZXMgaW4gd2hpY2ggaXQgaXMgZGVmaW5lZCBhcmVcbiAgICogbG9ja2VkLlxuICAgKi9cbiAgcHVibGljIGdldCBsb2NrZWQoKSB7XG4gICAgaWYgKHRoaXMuX2xvY2tlZCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc2NvcGUgJiYgdGhpcy5zY29wZS5ub2RlLmxvY2tlZCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhbiBvcmRlcmluZyBkZXBlbmRlbmN5IG9uIGEgRGVwZW5kYWJsZSAoYSBjb25zdHJ1Y3Qgb3Igc2V0IG9mIGNvbnN0cnVjdHMpXG4gICAqXG4gICAqIEl0IGlzIHVwIHRvIHRoZSB0YXJnZXQgZG9jdW1lbnQgbGFuZ3VhZ2UgdG8gZGVjaWRlIHdoYXQgYW4gb3JkZXJpbmdcbiAgICogcmVsYXRpb25zaGlwIG1lYW5zIGFuZCBob3cgaXQgc2hvdWxkIGJlIHJlbmRlcmVkOyBmb3IgZXhhbXBsZSwgaW4gdGhlIEFXU1xuICAgKiBDREsgZm9yIENsb3VkRm9ybWF0aW9uIGl0IG1lYW5zIGEgZGVwZW5kZW5jeSBmcm9tIGV2ZXJ5IHJlc291cmNlIGluIHNjb3BlXG4gICAqIG9mIHRoZSBjdXJyZW50IGNvbnN0cnVjdCB0byBldmVyeSByZXNvdXJjZSBpbiBzY29wZSBvZiB0aGUgdGFyZ2V0IHNldFxuICAgKiBvZiBjb25zdHJ1Y3RzLCB0aGF0IGdldCByZWFsaXplZCBhcyBlaXRoZXIgc3RhY2sgZGVwZW5kZW5jaWVzIG9yXG4gICAqIGBEZXBlbmRzT25gIHJlbGF0aW9uc2hpcHMgaW4gdGhlIHN5bnRoZXNpemVkIHRlbXBsYXRlLlxuICAgKlxuICAgKiBgSURlcGVuZGFibGVgIGlzIGEgbWFya2VyIGludGVyZmFjZSB0aGF0IGluZGljYXRlcyB0aGF0IGEgY2xhc3MgaGFzIHVzZWRcbiAgICogYERlcGVuZGFibGUuaW1wbGVtZW50KClgIHRvIGltcGxlbWVudCB0aGUgYElEZXBlbmRhYmxlYCBpbnRlcmZhY2UuIEl0XG4gICAqIGNhbiBiZSB1c2VkIHRvIG1ha2UgdGhlIHRhcmdldCBvYmplY3QgcmVwcmVzZW50IG1vcmUgdGhhbiBvbmUgc2V0IG9mXG4gICAqIGNvbnN0cnVjdHMgYXQgYSB0aW1lLiBGb3IgZXhhbXBsZSwgYSBgRGVwZW5kZW5jeUdyb3VwYCB1c2VzIHRoaXNcbiAgICogaW50ZXJmYWNlIHRvIHJlcHJlc2VudCBhbiBleHBsaWNpdCBsaXN0IG9mIDAgb3IgbW9yZSBjb25zdHJ1Y3RzIHRoYXQgc2hvdWxkXG4gICAqIGJlIGludm9sdmVkIGluIHRoZSBkZXBlbmRlbmN5IHJlbGF0aW9uc2hpcC5cbiAgICovXG4gIHB1YmxpYyBhZGREZXBlbmRlbmN5KC4uLmRlcHM6IElEZXBlbmRhYmxlW10pIHtcbiAgICBpZiAoIXRoaXMuX2RlcGVuZGVuY2llcykge1xuICAgICAgdGhpcy5fZGVwZW5kZW5jaWVzID0gbmV3IFNldCgpO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IGQgb2YgZGVwcykge1xuICAgICAgdGhpcy5fZGVwZW5kZW5jaWVzLmFkZChkKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlIGFuIG9yZGVyaW5nIGRlcGVuZGVuY3kgb24gYSBEZXBlbmRlbmFibGUgKGEgY29uc3RydWN0IG9yIHNldCBvZiBjb25zdHJ1Y3RzKVxuICAgKlxuICAgKiBUaGlzIHJlbW92ZXMgYW55IGRlcGVuZGVuY3kgYWRkZWQgdXNpbmcgYG5vZGUuYWRkRGVwZW5kZW5jeSgpYC4gSXQgbXVzdFxuICAgKiB1c2UgdGhlIGV4YWN0IHNhbWUgb2JqZWN0IHRoYXQgd2FzIGludm9sdmVkIGluIHRoZSBgYWRkRGVwZW5kZW5jeSgpYCBjYWxsLlxuICAgKi9cbiAgcHVibGljIHJlbW92ZURlcGVuZGVuY3koLi4uZGVwczogSURlcGVuZGFibGVbXSkge1xuICAgIGlmICghdGhpcy5fZGVwZW5kZW5jaWVzKSB7XG4gICAgICB0aGlzLl9kZXBlbmRlbmNpZXMgPSBuZXcgU2V0KCk7XG4gICAgfVxuICAgIGZvciAoY29uc3QgZCBvZiBkZXBzKSB7XG4gICAgICB0aGlzLl9kZXBlbmRlbmNpZXMuZGVsZXRlKGQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIHRoYXQgdGhpcyBjb25zdHJ1Y3QgZGVwZW5kcyBvbiBkaXJlY3RseVxuICAgKlxuICAgKiBUaGlzIGV4cGFuZHMgdGhlIHNldHMgb2YgYERlcGVuZGFibGVzYCB0byB0aGUgc2V0IG9mIGBDb25zdHJ1Y3RzYCB0aGF0IHRoZXlcbiAgICogcmVwcmVzZW50LlxuICAgKi9cbiAgcHVibGljIGdldCBkZXBlbmRlbmNpZXMoKTogSUNvbnN0cnVjdFtdIHtcbiAgICBjb25zdCByZXN1bHQgPSBuZXcgQXJyYXk8SUNvbnN0cnVjdD4oKTtcbiAgICBpZiAodGhpcy5fZGVwZW5kZW5jaWVzKSB7XG4gICAgICBmb3IgKGNvbnN0IGRlcCBvZiB0aGlzLl9kZXBlbmRlbmNpZXMpIHtcbiAgICAgICAgZm9yIChjb25zdCByb290IG9mIERlcGVuZGFibGUub2YoZGVwKS5kZXBlbmRlbmN5Um9vdHMpIHtcbiAgICAgICAgICByZXN1bHQucHVzaCh