@adobe/cq-angular-editable-components
Version:
* [API](#api) * [Documentation](#documentation) * [Changelog](#changelog)
640 lines (629 loc) • 56.6 kB
JavaScript
import { ComponentMapping } from '@adobe/cq-spa-component-mapping';
import { Constants, PageModelManager } from '@adobe/cq-spa-page-model-manager';
import { Directive, Input, Renderer2, NgZone, ViewContainerRef, ComponentFactoryResolver, Component, NgModule } from '@angular/core';
import { __extends } from 'tslib';
import { CommonModule } from '@angular/common';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var ComponentMappingWithConfig = /** @class */ (function () {
function ComponentMappingWithConfig(spaMapping) {
this.spaMapping = spaMapping;
this.editConfigMap = new WeakMap();
}
/**
* @param {?} resourceTypes
* @param {?} clazz
* @param {?=} editConfig
* @return {?}
*/
ComponentMappingWithConfig.prototype.map = /**
* @param {?} resourceTypes
* @param {?} clazz
* @param {?=} editConfig
* @return {?}
*/
function (resourceTypes, clazz, editConfig) {
if (editConfig === void 0) { editConfig = null; }
var /** @type {?} */ innerClass = clazz;
if (editConfig) {
this.editConfigMap.set(clazz, editConfig);
}
this.spaMapping.map(resourceTypes, innerClass);
};
/**
* @param {?} resourceType
* @return {?}
*/
ComponentMappingWithConfig.prototype.get = /**
* @param {?} resourceType
* @return {?}
*/
function (resourceType) {
return this.spaMapping.get(resourceType);
};
/**
* @param {?} component
* @return {?}
*/
ComponentMappingWithConfig.prototype.getEditConfig = /**
* @param {?} component
* @return {?}
*/
function (component) {
return this.editConfigMap.get(component);
};
return ComponentMappingWithConfig;
}());
var /** @type {?} */ componentMapping = new ComponentMappingWithConfig(ComponentMapping);
/**
* @param {?} resourceTypes
* @return {?}
*/
function MapTo(resourceTypes) {
return function (clazz, editConfig) {
if (editConfig === void 0) { editConfig = null; }
return componentMapping.map(resourceTypes, clazz, editConfig);
};
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var /** @type {?} */ Constants$1 = {
/**
* Class names associated with a new section component
*
*/
NEW_SECTION_CLASS_NAMES: 'new section',
TYPE_PROP: Constants.TYPE_PROP,
/**
* List of child items of an item
*
*/
ITEMS_PROP: Constants.ITEMS_PROP,
/**
* Order in which the items should be listed
*
*/
ITEMS_ORDER_PROP: Constants.ITEMS_ORDER_PROP,
/**
* Path of the item
*
*/
PATH_PROP: Constants.PATH_PROP,
/**
* Children of an item
*
*/
CHILDREN_PROP: Constants.CHILDREN_PROP,
/**
* Path of the resource in the model
*
*/
DATA_PATH_PROP: ':dataPath',
/**
* Hierarchical type of the item
*/
HIERARCHY_TYPE_PROP: ':hierarchyType'
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/*
* ADOBE CONFIDENTIAL
*
* Copyright 2018 Adobe Systems Incorporated
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any. The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated and its
* suppliers and may be covered by U.S. and Foreign Patents,
* patents in process, and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
*/
/**
* Selector that identifies the node that contains the WCM mode state
*
*/
var /** @type {?} */ WCM_MODE_META_SELECTOR = 'meta[property="cq:wcmmode"]';
/**
* The editor is in one of the edition modes
*/
var /** @type {?} */ EDIT_MODE = 'edit';
/**
* The editor is in preview mode
*/
var /** @type {?} */ PREVIEW_MODE = 'preview';
/**
* Returns the current WCM mode
*
* <p>Note that the value isn't, as of the date of this writing, updated by the editor</p>
*
*
* @return {?}
*/
function getWCMMode() {
var /** @type {?} */ wcmModeMeta = document.head.querySelector(WCM_MODE_META_SELECTOR);
return wcmModeMeta && wcmModeMeta.content;
}
/**
* Helper functions for interacting with the AEM environment
*
*/
var /** @type {?} */ Utils = {
/**
* Is the app used in the context of the AEM Page editor
*
*/
isInEditor: /**
* Is the app used in the context of the AEM Page editor
*
* @return {?}
*/
function () {
var /** @type {?} */ wcmMode = getWCMMode();
return wcmMode && (EDIT_MODE === wcmMode || PREVIEW_MODE === wcmMode);
}
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var /** @type {?} */ PLACEHOLDER_CLASS_NAME = 'cq-placeholder';
var /** @type {?} */ DRAG_DROP_CLASS_NAME = 'cq-dd-';
var AEMComponentDirective = /** @class */ (function () {
function AEMComponentDirective(renderer, viewContainer, factoryResolver, ngZone) {
this.renderer = renderer;
this.viewContainer = viewContainer;
this.factoryResolver = factoryResolver;
this.ngZone = ngZone;
}
/**
* @return {?}
*/
AEMComponentDirective.prototype.ngOnInit = /**
* @return {?}
*/
function () {
this.renderComponent(componentMapping.get(this.type));
};
Object.defineProperty(AEMComponentDirective.prototype, "type", {
/**
* Returns the type of the cqModel if exists.
*/
get: /**
* Returns the type of the cqModel if exists.
* @return {?}
*/
function () {
return this.cqModel && this.cqModel[":type"];
},
enumerable: true,
configurable: true
});
Object.defineProperty(AEMComponentDirective.prototype, "columnClasses", {
/**
* Returns the column classes of the cqModel
*/
get: /**
* Returns the column classes of the cqModel
* @return {?}
*/
function () {
return this.cqModel && (this.cqModel.columnClassNames || '');
},
enumerable: true,
configurable: true
});
/**
* Updates the cqModel
* @return {?}
*/
AEMComponentDirective.prototype.updateCqModel = /**
* Updates the cqModel
* @return {?}
*/
function () {
var _this = this;
// Fetching the latest data for the item at the given path
this.getCqModel().then(function (model) {
_this.ngZone.run(function () {
model[Constants$1.DATA_PATH_PROP] = _this.path;
_this.cqModel = model;
_this.updateComponentData();
_this.setupElement();
var /** @type {?} */ editConfig = componentMapping.getEditConfig(componentMapping.get(_this.type));
if (editConfig) {
_this.setupPlaceholder(editConfig);
}
});
});
};
/**
* Returns the Cq Model
*
* @return {?}
*/
AEMComponentDirective.prototype.getCqModel = /**
* Returns the Cq Model
*
* @return {?}
*/
function () {
return PageModelManager.getData({ pagePath: this.pagePath, dataPath: this.path });
};
/**
* Renders a component dynamically based on the component definition
*
* @param {?} componentDefinition The component definition to render
* @return {?}
*/
AEMComponentDirective.prototype.renderComponent = /**
* Renders a component dynamically based on the component definition
*
* @param {?} componentDefinition The component definition to render
* @return {?}
*/
function (componentDefinition) {
if (componentDefinition) {
var /** @type {?} */ factory = this.factoryResolver.resolveComponentFactory(componentDefinition);
this.viewContainer.clear();
this._component = this.viewContainer.createComponent(factory);
this.updateComponentData();
this.setupElement();
var /** @type {?} */ editConfig = componentMapping.getEditConfig(componentDefinition);
if (editConfig && Utils.isInEditor) {
this.setupPlaceholder(editConfig);
}
PageModelManager.removeListener({ pagePath: this.pagePath, dataPath: this.path, callback: this.updateCqModel.bind(this) });
PageModelManager.addListener({ pagePath: this.pagePath, dataPath: this.path, callback: this.updateCqModel.bind(this) });
}
};
/**
* Updates the data of the component based the data of the directive
* @return {?}
*/
AEMComponentDirective.prototype.updateComponentData = /**
* Updates the data of the component based the data of the directive
* @return {?}
*/
function () {
this._component.instance.cqModel = this.cqModel;
this._component.instance.path = this.path;
this._component.instance.pagePath = this.pagePath;
this._component.instance.modelName = this.modelName;
};
/**
* Setups the DOM element, setting the classes and attributes needed for the AEM editor.
* @return {?}
*/
AEMComponentDirective.prototype.setupElement = /**
* Setups the DOM element, setting the classes and attributes needed for the AEM editor.
* @return {?}
*/
function () {
var _this = this;
if (this._oldClasses) {
var /** @type {?} */ oldClasses = this._oldClasses.split(' ');
oldClasses.forEach(function (columnClass) {
_this.renderer.removeClass(_this._component.location.nativeElement, columnClass);
});
}
this._oldClasses = this.columnClasses;
// Manually add the classes
if (this.columnClasses) {
var /** @type {?} */ classes = this.columnClasses.split(' ');
classes.forEach(function (columnClass) {
_this.renderer.addClass(_this._component.location.nativeElement, columnClass);
});
}
if (this.path) {
this.renderer.setAttribute(this._component.location.nativeElement, "data-cq-data-path", this.path);
}
};
/**
* Setups the placeholder of needed for the AEM editor
*
* @param {?} editConfig - the editConfig, which will dictate the classes to be added on.
* @return {?}
*/
AEMComponentDirective.prototype.setupPlaceholder = /**
* Setups the placeholder of needed for the AEM editor
*
* @param {?} editConfig - the editConfig, which will dictate the classes to be added on.
* @return {?}
*/
function (editConfig) {
// Remove previous drag and drop class names
this.renderer.removeClass(this._component.location.nativeElement, DRAG_DROP_CLASS_NAME + editConfig.dragDropName);
if (editConfig.dragDropName && editConfig.dragDropName.trim().length > 0) {
this.renderer.addClass(this._component.location.nativeElement, DRAG_DROP_CLASS_NAME + editConfig.dragDropName);
}
if (this.usePlaceholder(editConfig)) {
this.renderer.addClass(this._component.location.nativeElement, PLACEHOLDER_CLASS_NAME);
this._component.location.nativeElement.dataset.emptytext = editConfig.emptyLabel;
}
else {
this.renderer.removeClass(this._component.location.nativeElement, PLACEHOLDER_CLASS_NAME);
delete this._component.location.nativeElement.dataset.emptytext;
}
};
/**
* Determines if the placeholder should e displayed.
*
* @param {?} editConfig - the edit config of the directive
* @return {?}
*/
AEMComponentDirective.prototype.usePlaceholder = /**
* Determines if the placeholder should e displayed.
*
* @param {?} editConfig - the edit config of the directive
* @return {?}
*/
function (editConfig) {
return editConfig.isEmpty && typeof editConfig.isEmpty === "function" && editConfig.isEmpty(this.cqModel);
};
/**
* @return {?}
*/
AEMComponentDirective.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
PageModelManager.removeListener({ pagePath: this.pagePath, dataPath: this.path, callback: this.updateCqModel.bind(this) });
this._component && this._component.destroy();
};
AEMComponentDirective.decorators = [
{ type: Directive, args: [{
selector: '[aemComponent]'
},] },
];
/** @nocollapse */
AEMComponentDirective.ctorParameters = function () { return [
{ type: Renderer2, },
{ type: ViewContainerRef, },
{ type: ComponentFactoryResolver, },
{ type: NgZone, },
]; };
AEMComponentDirective.propDecorators = {
"cqModel": [{ type: Input },],
"path": [{ type: Input },],
"pagePath": [{ type: Input },],
"modelName": [{ type: Input },],
"aemComponent": [{ type: Input },],
};
return AEMComponentDirective;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var AEMContainerComponent = /** @class */ (function () {
function AEMContainerComponent() {
this.path = '';
this.pagePath = '';
this.modelName = '';
}
/**
* Returns the aggregated path of this container path and the provided path
*
* @param path - the provided path to aggregate with the container path
*/
/**
* Returns the aggregated path of this container path and the provided path
*
* @param {?} path - the provided path to aggregate with the container path
* @return {?}
*/
AEMContainerComponent.prototype.getDataPath = /**
* Returns the aggregated path of this container path and the provided path
*
* @param {?} path - the provided path to aggregate with the container path
* @return {?}
*/
function (path) {
return this.path ? this.path + "/" + path : path;
};
/**
* Return the page path from the data, defaulting to the provided pagePath to the container.
*/
/**
* Return the page path from the data, defaulting to the provided pagePath to the container.
* @return {?}
*/
AEMContainerComponent.prototype.getPagePath = /**
* Return the page path from the data, defaulting to the provided pagePath to the container.
* @return {?}
*/
function () {
return this.cqModel[Constants$1.PATH_PROP] || this.pagePath;
};
/**
* Returns the item data from the cqModel
*
* @param itemKey - the itemKey to look for in the items.
*/
/**
* Returns the item data from the cqModel
*
* @param {?} itemKey - the itemKey to look for in the items.
* @return {?}
*/
AEMContainerComponent.prototype.getItem = /**
* Returns the item data from the cqModel
*
* @param {?} itemKey - the itemKey to look for in the items.
* @return {?}
*/
function (itemKey) {
return this.cqModel[Constants$1.ITEMS_PROP][itemKey];
};
Object.defineProperty(AEMContainerComponent.prototype, "itemsOrder", {
/**
* Returns the itemsOrder array from the cqModel
*/
get: /**
* Returns the itemsOrder array from the cqModel
* @return {?}
*/
function () {
return this.cqModel && this.cqModel[Constants$1.ITEMS_ORDER_PROP];
},
enumerable: true,
configurable: true
});
AEMContainerComponent.decorators = [
{ type: Component, args: [{
selector: 'aem-container',
host: {
'[attr.data-cq-data-path]': 'path'
},
template: "<ng-container *ngFor=\"let itemKey of itemsOrder\">\n <ng-container [aemComponent] [cqModel]='getItem(itemKey)' [pagePath]='getPagePath()' [path]='getDataPath(itemKey)' [modelName]='itemKey'></ng-container>\n</ng-container>\n"
},] },
];
/** @nocollapse */
AEMContainerComponent.ctorParameters = function () { return []; };
AEMContainerComponent.propDecorators = {
"cqModel": [{ type: Input },],
"path": [{ type: Input },],
"pagePath": [{ type: Input },],
"modelName": [{ type: Input },],
};
return AEMContainerComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var /** @type {?} */ CONTAINER_CLASS_NAMES = 'aem-container';
var /** @type {?} */ PLACEHOLDER_CLASS_NAMES = Constants$1.NEW_SECTION_CLASS_NAMES + ' aem-Grid-newComponent';
var AEMResponsiveGridComponent = /** @class */ (function (_super) {
__extends(AEMResponsiveGridComponent, _super);
function AEMResponsiveGridComponent() {
return _super !== null && _super.apply(this, arguments) || this;
}
Object.defineProperty(AEMResponsiveGridComponent.prototype, "isInEditMode", {
/**
* Returns weather of not we are in the editor
*/
get: /**
* Returns weather of not we are in the editor
* @return {?}
*/
function () {
return Utils.isInEditor();
},
enumerable: true,
configurable: true
});
Object.defineProperty(AEMResponsiveGridComponent.prototype, "placeholderClass", {
/**
* Returns the placeholder classes
*/
get: /**
* Returns the placeholder classes
* @return {?}
*/
function () {
return PLACEHOLDER_CLASS_NAMES;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AEMResponsiveGridComponent.prototype, "placeholdePath", {
/**
* Returns the placeholder path
*/
get: /**
* Returns the placeholder path
* @return {?}
*/
function () {
return this.path && this.path + "/*";
},
enumerable: true,
configurable: true
});
Object.defineProperty(AEMResponsiveGridComponent.prototype, "gridClasses", {
/**
* Returns the gridClasses for the cqModel of the responsive grid
*/
get: /**
* Returns the gridClasses for the cqModel of the responsive grid
* @return {?}
*/
function () {
return this.cqModel && (this.cqModel["gridClassNames"] || '');
},
enumerable: true,
configurable: true
});
Object.defineProperty(AEMResponsiveGridComponent.prototype, "classNames", {
/**
* Returns the class names of the responsive grid based on the data from the cqModel
*/
get: /**
* Returns the class names of the responsive grid based on the data from the cqModel
* @return {?}
*/
function () {
if (!this.cqModel) {
return '';
}
var /** @type {?} */ classNames = CONTAINER_CLASS_NAMES;
if (this.cqModel.classNames) {
classNames += ' ' + (this.cqModel.classNames || '');
}
if (this.cqModel.columnClassNames) {
classNames += ' ' + (this.cqModel.columnClassNames || '');
}
return classNames;
},
enumerable: true,
configurable: true
});
AEMResponsiveGridComponent.decorators = [
{ type: Component, args: [{
selector: 'aem-responsivegrid',
host: {
'[class]': 'classNames',
'[attr.data-cq-data-path]': 'path'
},
template: "<div [class]=\"gridClasses\">\n <ng-container *ngFor=\"let itemKey of itemsOrder\">\n <ng-container [aemComponent] [cqModel]='getItem(itemKey)' [pagePath]='getPagePath()' [path]='getDataPath(itemKey)' [modelName]='itemKey'></ng-container>\n </ng-container>\n <div *ngIf=\"isInEditMode\" [attr.data-cq-data-path]=\"placeholdePath\" [class]=\"placeholderClass\"></div>\n</div>\n",
},] },
];
return AEMResponsiveGridComponent;
}(AEMContainerComponent));
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var SpaAngularEditableComponentsModule = /** @class */ (function () {
function SpaAngularEditableComponentsModule() {
}
SpaAngularEditableComponentsModule.decorators = [
{ type: NgModule, args: [{
imports: [CommonModule],
declarations: [AEMContainerComponent, AEMResponsiveGridComponent, AEMComponentDirective],
exports: [AEMContainerComponent, AEMResponsiveGridComponent, AEMComponentDirective]
},] },
];
return SpaAngularEditableComponentsModule;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
export { AEMComponentDirective, AEMContainerComponent, AEMResponsiveGridComponent, ComponentMappingWithConfig, componentMapping as ComponentMapping, MapTo, Constants$1 as Constants, Utils, SpaAngularEditableComponentsModule };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWRvYmUtY3EtYW5ndWxhci1lZGl0YWJsZS1jb21wb25lbnRzLmpzLm1hcCIsInNvdXJjZXMiOlsibmc6Ly9AYWRvYmUvY3EtYW5ndWxhci1lZGl0YWJsZS1jb21wb25lbnRzL2xpYi9sYXlvdXQvY29tcG9uZW50LW1hcHBpbmcudHMiLCJuZzovL0BhZG9iZS9jcS1hbmd1bGFyLWVkaXRhYmxlLWNvbXBvbmVudHMvbGliL2xheW91dC9jb25zdGFudHMudHMiLCJuZzovL0BhZG9iZS9jcS1hbmd1bGFyLWVkaXRhYmxlLWNvbXBvbmVudHMvbGliL2xheW91dC91dGlscy50cyIsIm5nOi8vQGFkb2JlL2NxLWFuZ3VsYXItZWRpdGFibGUtY29tcG9uZW50cy9saWIvbGF5b3V0L2FlbS1jb21wb25lbnQuZGlyZWN0aXZlLnRzIiwibmc6Ly9AYWRvYmUvY3EtYW5ndWxhci1lZGl0YWJsZS1jb21wb25lbnRzL2xpYi9sYXlvdXQvYWVtLWNvbnRhaW5lci9hZW0tY29udGFpbmVyLmNvbXBvbmVudC50cyIsIm5nOi8vQGFkb2JlL2NxLWFuZ3VsYXItZWRpdGFibGUtY29tcG9uZW50cy9saWIvbGF5b3V0L2FlbS1yZXNwb25zaXZlZ3JpZC9hZW0tcmVzcG9uc2l2ZWdyaWQuY29tcG9uZW50LnRzIiwibmc6Ly9AYWRvYmUvY3EtYW5ndWxhci1lZGl0YWJsZS1jb21wb25lbnRzL2xpYi9jcS1hbmd1bGFyLWVkaXRhYmxlLWNvbXBvbmVudHMubW9kdWxlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBBRE9CRSBDT05GSURFTlRJQUxcbiAqXG4gKiBDb3B5cmlnaHQgMjAxOCBBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZFxuICogQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBOT1RJQ0U6ICBBbGwgaW5mb3JtYXRpb24gY29udGFpbmVkIGhlcmVpbiBpcywgYW5kIHJlbWFpbnNcbiAqIHRoZSBwcm9wZXJ0eSBvZiBBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZCBhbmQgaXRzIHN1cHBsaWVycyxcbiAqIGlmIGFueS4gIFRoZSBpbnRlbGxlY3R1YWwgYW5kIHRlY2huaWNhbCBjb25jZXB0cyBjb250YWluZWRcbiAqIGhlcmVpbiBhcmUgcHJvcHJpZXRhcnkgdG8gQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQgYW5kIGl0c1xuICogc3VwcGxpZXJzIGFuZCBtYXkgYmUgY292ZXJlZCBieSBVLlMuIGFuZCBGb3JlaWduIFBhdGVudHMsXG4gKiBwYXRlbnRzIGluIHByb2Nlc3MsIGFuZCBhcmUgcHJvdGVjdGVkIGJ5IHRyYWRlIHNlY3JldCBvciBjb3B5cmlnaHQgbGF3LlxuICogRGlzc2VtaW5hdGlvbiBvZiB0aGlzIGluZm9ybWF0aW9uIG9yIHJlcHJvZHVjdGlvbiBvZiB0aGlzIG1hdGVyaWFsXG4gKiBpcyBzdHJpY3RseSBmb3JiaWRkZW4gdW5sZXNzIHByaW9yIHdyaXR0ZW4gcGVybWlzc2lvbiBpcyBvYnRhaW5lZFxuICogZnJvbSBBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZC5cbiAqL1xuXG5pbXBvcnQgeyBDb21wb25lbnRNYXBwaW5nIGFzIFNQQUNvbXBvbmVudE1hcHBpbmcgfSBmcm9tIFwiQGFkb2JlL2NxLXNwYS1jb21wb25lbnQtbWFwcGluZ1wiO1xuXG5leHBvcnQgY2xhc3MgQ29tcG9uZW50TWFwcGluZ1dpdGhDb25maWcge1xuICBwcml2YXRlIGVkaXRDb25maWdNYXA6V2Vha01hcDxhbnksIGFueT4gID0gbmV3IFdlYWtNYXAoKTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHNwYU1hcHBpbmc6U1BBQ29tcG9uZW50TWFwcGluZykge31cblxuICBtYXAocmVzb3VyY2VUeXBlcywgY2xhenosIGVkaXRDb25maWcgPSBudWxsKSB7XG4gICAgICBsZXQgaW5uZXJDbGFzcyA9IGNsYXp6O1xuXG4gICAgICBpZiAoZWRpdENvbmZpZykge1xuICAgICAgICAgIHRoaXMuZWRpdENvbmZpZ01hcC5zZXQoY2xhenosIGVkaXRDb25maWcpO1xuICAgICAgfVxuICAgICAgdGhpcy5zcGFNYXBwaW5nLm1hcChyZXNvdXJjZVR5cGVzLCBpbm5lckNsYXNzKTtcbiAgfTtcblxuICBnZXQocmVzb3VyY2VUeXBlKSB7XG4gICAgcmV0dXJuIHRoaXMuc3BhTWFwcGluZy5nZXQocmVzb3VyY2VUeXBlKTtcbiAgfVxuXG4gIGdldEVkaXRDb25maWcoY29tcG9uZW50KSB7XG4gICAgcmV0dXJuIHRoaXMuZWRpdENvbmZpZ01hcC5nZXQoY29tcG9uZW50KTtcbiAgfVxufVxuXG5sZXQgY29tcG9uZW50TWFwcGluZyA9IG5ldyBDb21wb25lbnRNYXBwaW5nV2l0aENvbmZpZyhTUEFDb21wb25lbnRNYXBwaW5nKTtcblxuZnVuY3Rpb24gTWFwVG8ocmVzb3VyY2VUeXBlcykge1xuICAgIHJldHVybiAoY2xhenosIGVkaXRDb25maWcgPSBudWxsKSA9PiB7XG4gICAgICAgIHJldHVybiBjb21wb25lbnRNYXBwaW5nLm1hcChyZXNvdXJjZVR5cGVzLCBjbGF6eiwgZWRpdENvbmZpZyk7XG4gICAgfTtcbn1cblxuXG5leHBvcnQgeyBjb21wb25lbnRNYXBwaW5nIGFzIENvbXBvbmVudE1hcHBpbmcsIE1hcFRvIH07XG4iLCIvKlxuICogQURPQkUgQ09ORklERU5USUFMXG4gKlxuICogQ29weXJpZ2h0IDIwMTggQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWRcbiAqIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogTk9USUNFOiAgQWxsIGluZm9ybWF0aW9uIGNvbnRhaW5lZCBoZXJlaW4gaXMsIGFuZCByZW1haW5zXG4gKiB0aGUgcHJvcGVydHkgb2YgQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQgYW5kIGl0cyBzdXBwbGllcnMsXG4gKiBpZiBhbnkuICBUaGUgaW50ZWxsZWN0dWFsIGFuZCB0ZWNobmljYWwgY29uY2VwdHMgY29udGFpbmVkXG4gKiBoZXJlaW4gYXJlIHByb3ByaWV0YXJ5IHRvIEFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkIGFuZCBpdHNcbiAqIHN1cHBsaWVycyBhbmQgbWF5IGJlIGNvdmVyZWQgYnkgVS5TLiBhbmQgRm9yZWlnbiBQYXRlbnRzLFxuICogcGF0ZW50cyBpbiBwcm9jZXNzLCBhbmQgYXJlIHByb3RlY3RlZCBieSB0cmFkZSBzZWNyZXQgb3IgY29weXJpZ2h0IGxhdy5cbiAqIERpc3NlbWluYXRpb24gb2YgdGhpcyBpbmZvcm1hdGlvbiBvciByZXByb2R1Y3Rpb24gb2YgdGhpcyBtYXRlcmlhbFxuICogaXMgc3RyaWN0bHkgZm9yYmlkZGVuIHVubGVzcyBwcmlvciB3cml0dGVuIHBlcm1pc3Npb24gaXMgb2J0YWluZWRcbiAqIGZyb20gQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQuXG4gKi9cblxuaW1wb3J0IHtDb25zdGFudHMgYXMgUE1Db25zdGFudHN9IGZyb20gJ0BhZG9iZS9jcS1zcGEtcGFnZS1tb2RlbC1tYW5hZ2VyJztcblxuZXhwb3J0IGNvbnN0IENvbnN0YW50cyA9IHtcblxuICAgIC8qKlxuICAgICAqIENsYXNzIG5hbWVzIGFzc29jaWF0ZWQgd2l0aCBhIG5ldyBzZWN0aW9uIGNvbXBvbmVudFxuICAgICAqXG4gICAgICovXG4gICAgTkVXX1NFQ1RJT05fQ0xBU1NfTkFNRVM6ICduZXcgc2VjdGlvbicsXG5cbiAgICBUWVBFX1BST1A6IFBNQ29uc3RhbnRzLlRZUEVfUFJPUCxcblxuICAgIC8qKlxuICAgICAqIExpc3Qgb2YgY2hpbGQgaXRlbXMgb2YgYW4gaXRlbVxuICAgICAqXG4gICAgICovXG4gICAgSVRFTVNfUFJPUDogUE1Db25zdGFudHMuSVRFTVNfUFJPUCxcblxuICAgIC8qKlxuICAgICAqIE9yZGVyIGluIHdoaWNoIHRoZSBpdGVtcyBzaG91bGQgYmUgbGlzdGVkXG4gICAgICpcbiAgICAgKi9cbiAgICBJVEVNU19PUkRFUl9QUk9QOiBQTUNvbnN0YW50cy5JVEVNU19PUkRFUl9QUk9QLFxuXG4gICAgLyoqXG4gICAgICogUGF0aCBvZiB0aGUgaXRlbVxuICAgICAqXG4gICAgICovXG4gICAgUEFUSF9QUk9QOiBQTUNvbnN0YW50cy5QQVRIX1BST1AsXG5cbiAgICAvKipcbiAgICAgKiBDaGlsZHJlbiBvZiBhbiBpdGVtXG4gICAgICpcbiAgICAgKi9cbiAgICBDSElMRFJFTl9QUk9QOiBQTUNvbnN0YW50cy5DSElMRFJFTl9QUk9QLFxuXG4gICAgLyoqXG4gICAgICogUGF0aCBvZiB0aGUgcmVzb3VyY2UgaW4gdGhlIG1vZGVsXG4gICAgICpcbiAgICAgKi9cbiAgICBEQVRBX1BBVEhfUFJPUDogJzpkYXRhUGF0aCcsXG5cbiAgICAvKipcbiAgICAgKiBIaWVyYXJjaGljYWwgdHlwZSBvZiB0aGUgaXRlbVxuICAgICAqL1xuICAgIEhJRVJBUkNIWV9UWVBFX1BST1A6ICc6aGllcmFyY2h5VHlwZSdcbn07XG4iLCIvKlxuICogQURPQkUgQ09ORklERU5USUFMXG4gKlxuICogQ29weXJpZ2h0IDIwMTggQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWRcbiAqIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogTk9USUNFOiAgQWxsIGluZm9ybWF0aW9uIGNvbnRhaW5lZCBoZXJlaW4gaXMsIGFuZCByZW1haW5zXG4gKiB0aGUgcHJvcGVydHkgb2YgQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQgYW5kIGl0cyBzdXBwbGllcnMsXG4gKiBpZiBhbnkuICBUaGUgaW50ZWxsZWN0dWFsIGFuZCB0ZWNobmljYWwgY29uY2VwdHMgY29udGFpbmVkXG4gKiBoZXJlaW4gYXJlIHByb3ByaWV0YXJ5IHRvIEFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkIGFuZCBpdHNcbiAqIHN1cHBsaWVycyBhbmQgbWF5IGJlIGNvdmVyZWQgYnkgVS5TLiBhbmQgRm9yZWlnbiBQYXRlbnRzLFxuICogcGF0ZW50cyBpbiBwcm9jZXNzLCBhbmQgYXJlIHByb3RlY3RlZCBieSB0cmFkZSBzZWNyZXQgb3IgY29weXJpZ2h0IGxhdy5cbiAqIERpc3NlbWluYXRpb24gb2YgdGhpcyBpbmZvcm1hdGlvbiBvciByZXByb2R1Y3Rpb24gb2YgdGhpcyBtYXRlcmlhbFxuICogaXMgc3RyaWN0bHkgZm9yYmlkZGVuIHVubGVzcyBwcmlvciB3cml0dGVuIHBlcm1pc3Npb24gaXMgb2J0YWluZWRcbiAqIGZyb20gQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQuXG4gKi9cblxuLyoqXG4gKiBTZWxlY3RvciB0aGF0IGlkZW50aWZpZXMgdGhlIG5vZGUgdGhhdCBjb250YWlucyB0aGUgV0NNIG1vZGUgc3RhdGVcbiAqXG4gKi9cbmNvbnN0IFdDTV9NT0RFX01FVEFfU0VMRUNUT1I6c3RyaW5nID0gJ21ldGFbcHJvcGVydHk9XCJjcTp3Y21tb2RlXCJdJztcblxuLyoqXG4gKiBUaGUgZWRpdG9yIGlzIGluIG9uZSBvZiB0aGUgZWRpdGlvbiBtb2Rlc1xuICovXG5jb25zdCBFRElUX01PREU6c3RyaW5nID0gJ2VkaXQnO1xuXG4vKipcbiAqIFRoZSBlZGl0b3IgaXMgaW4gcHJldmlldyBtb2RlXG4gKi9cbmNvbnN0IFBSRVZJRVdfTU9ERTpzdHJpbmcgPSAncHJldmlldyc7XG5cbi8qKlxuICogUmV0dXJucyB0aGUgY3VycmVudCBXQ00gbW9kZVxuICpcbiAqIDxwPk5vdGUgdGhhdCB0aGUgdmFsdWUgaXNuJ3QsIGFzIG9mIHRoZSBkYXRlIG9mIHRoaXMgd3JpdGluZywgdXBkYXRlZCBieSB0aGUgZWRpdG9yPC9wPlxuICpcbiAqXG4gKi9cbmZ1bmN0aW9uIGdldFdDTU1vZGUoKSB7XG4gICAgY29uc3Qgd2NtTW9kZU1ldGE6YW55ID0gZG9jdW1lbnQuaGVhZC5xdWVyeVNlbGVjdG9yKFdDTV9NT0RFX01FVEFfU0VMRUNUT1IpO1xuICAgIHJldHVybiB3Y21Nb2RlTWV0YSAmJiB3Y21Nb2RlTWV0YS5jb250ZW50O1xufVxuXG4vKipcbiAqIEhlbHBlciBmdW5jdGlvbnMgZm9yIGludGVyYWN0aW5nIHdpdGggdGhlIEFFTSBlbnZpcm9ubWVudFxuICpcbiAqL1xuZXhwb3J0IGNvbnN0IFV0aWxzID0ge1xuXG4gICAgLyoqXG4gICAgICogSXMgdGhlIGFwcCB1c2VkIGluIHRoZSBjb250ZXh0IG9mIHRoZSBBRU0gUGFnZSBlZGl0b3JcbiAgICAgKlxuICAgICAqL1xuICAgIGlzSW5FZGl0b3IoKSB7XG4gICAgICAgIGNvbnN0IHdjbU1vZGUgPSBnZXRXQ01Nb2RlKCk7XG4gICAgICAgIHJldHVybiB3Y21Nb2RlICYmIChFRElUX01PREUgPT09IHdjbU1vZGUgfHwgUFJFVklFV19NT0RFID09PSB3Y21Nb2RlKTtcbiAgICB9XG59O1xuIiwiLypcbiAqIEFET0JFIENPTkZJREVOVElBTFxuICpcbiAqIENvcHlyaWdodCAyMDE4IEFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkXG4gKiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIE5PVElDRTogIEFsbCBpbmZvcm1hdGlvbiBjb250YWluZWQgaGVyZWluIGlzLCBhbmQgcmVtYWluc1xuICogdGhlIHByb3BlcnR5IG9mIEFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkIGFuZCBpdHMgc3VwcGxpZXJzLFxuICogaWYgYW55LiAgVGhlIGludGVsbGVjdHVhbCBhbmQgdGVjaG5pY2FsIGNvbmNlcHRzIGNvbnRhaW5lZFxuICogaGVyZWluIGFyZSBwcm9wcmlldGFyeSB0byBBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZCBhbmQgaXRzXG4gKiBzdXBwbGllcnMgYW5kIG1heSBiZSBjb3ZlcmVkIGJ5IFUuUy4gYW5kIEZvcmVpZ24gUGF0ZW50cyxcbiAqIHBhdGVudHMgaW4gcHJvY2VzcywgYW5kIGFyZSBwcm90ZWN0ZWQgYnkgdHJhZGUgc2VjcmV0IG9yIGNvcHlyaWdodCBsYXcuXG4gKiBEaXNzZW1pbmF0aW9uIG9mIHRoaXMgaW5mb3JtYXRpb24gb3IgcmVwcm9kdWN0aW9uIG9mIHRoaXMgbWF0ZXJpYWxcbiAqIGlzIHN0cmljdGx5IGZvcmJpZGRlbiB1bmxlc3MgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uIGlzIG9idGFpbmVkXG4gKiBmcm9tIEFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkLlxuICovXG5cbmltcG9ydCB7IERpcmVjdGl2ZSwgSW5wdXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBSZW5kZXJlcjIsIE5nWm9uZSwgQ2hhbmdlRGV0ZWN0b3JSZWYsIFZpZXdDb250YWluZXJSZWYsIENvbXBvbmVudEZhY3RvcnlSZXNvbHZlciwgQXBwbGljYXRpb25SZWYsIENvbXBvbmVudFJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQgeyBDb21wb25lbnRNYXBwaW5nIH0gZnJvbSBcIi4vY29tcG9uZW50LW1hcHBpbmdcIjtcblxuaW1wb3J0IHsgUGFnZU1vZGVsTWFuYWdlciB9IGZyb20gJ0BhZG9iZS9jcS1zcGEtcGFnZS1tb2RlbC1tYW5hZ2VyJztcblxuaW1wb3J0IHsgQ29uc3RhbnRzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBVdGlscyB9IGZyb20gXCIuL3V0aWxzXCI7XG5cblxuY29uc3QgUExBQ0VIT0xERVJfQ0xBU1NfTkFNRSA9ICdjcS1wbGFjZWhvbGRlcic7XG5jb25zdCBEUkFHX0RST1BfUkVHRVggPSAvY3EtZGQtKFteIF0pKy9nO1xuY29uc3QgRFJBR19EUk9QX0NMQVNTX05BTUUgPSAnY3EtZGQtJztcblxuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnW2FlbUNvbXBvbmVudF0nXG59KVxuXG5leHBvcnQgY2xhc3MgQUVNQ29tcG9uZW50RGlyZWN0aXZlIHtcbiAgcHJpdmF0ZSBfY29tcG9uZW50OkNvbXBvbmVudFJlZjxhbnk+O1xuICBwcml2YXRlIF9vbGRDbGFzc2VzOnN0cmluZztcblxuICBASW5wdXQoKSBjcU1vZGVsOmFueTtcbiAgQElucHV0KCkgcGF0aDpzdHJpbmc7XG4gIEBJbnB1dCgpIHBhZ2VQYXRoOnN0cmluZztcbiAgQElucHV0KCkgbW9kZWxOYW1lOnN0cmluZztcbiAgQElucHV0KCkgYWVtQ29tcG9uZW50O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVuZGVyZXI6IFJlbmRlcmVyMixcbiAgICBwcml2YXRlIHZpZXdDb250YWluZXI6IFZpZXdDb250YWluZXJSZWYsXG4gICAgcHJpdmF0ZSBmYWN0b3J5UmVzb2x2ZXI6IENvbXBvbmVudEZhY3RvcnlSZXNvbHZlcixcbiAgICBwcml2YXRlIG5nWm9uZTogTmdab25lKSB7XG4gIH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLnJlbmRlckNvbXBvbmVudChDb21wb25lbnRNYXBwaW5nLmdldCh0aGlzLnR5cGUpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSB0eXBlIG9mIHRoZSBjcU1vZGVsIGlmIGV4aXN0cy5cbiAgICovXG4gIGdldCB0eXBlKCkge1xuICAgIHJldHVybiB0aGlzLmNxTW9kZWwgJiYgdGhpcy5jcU1vZGVsW1wiOnR5cGVcIl07XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY29sdW1uIGNsYXNzZXMgb2YgdGhlIGNxTW9kZWxcbiAgICovXG4gIGdldCBjb2x1bW5DbGFzc2VzKCkge1xuICAgIHJldHVybiB0aGlzLmNxTW9kZWwgJiYgKHRoaXMuY3FNb2RlbC5jb2x1bW5DbGFzc05hbWVzIHx8ICcnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGVzIHRoZSBjcU1vZGVsXG4gICAqL1xuICBwcml2YXRlIHVwZGF0ZUNxTW9kZWwoKSB7XG4gICAgbGV0IHNlbGYgPSB0aGlzO1xuICAgIC8vIEZldGNoaW5nIHRoZSBsYXRlc3QgZGF0YSBmb3IgdGhlIGl0ZW0gYXQgdGhlIGdpdmVuIHBhdGhcbiAgICB0aGlzLmdldENxTW9kZWwoKS50aGVuKG1vZGVsID0+IHtcbiAgICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICBtb2RlbFtDb25zdGFudHMuREFUQV9QQVRIX1BST1BdID0gdGhpcy5wYXRoO1xuICAgICAgICAgIHRoaXMuY3FNb2RlbCA9IG1vZGVsO1xuICAgICAgICAgIHRoaXMudXBkYXRlQ29tcG9uZW50RGF0YSgpO1xuICAgICAgICAgIHRoaXMuc2V0dXBFbGVtZW50KCk7XG4gICAgICAgICAgbGV0IGVkaXRDb25maWcgPSBDb21wb25lbnRNYXBwaW5nLmdldEVkaXRDb25maWcoQ29tcG9uZW50TWFwcGluZy5nZXQodGhpcy50eXBlKSk7XG4gICAgICAgICAgaWYgKGVkaXRDb25maWcpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0dXBQbGFjZWhvbGRlcihlZGl0Q29uZmlnKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIENxIE1vZGVsXG4gICAqXG4gICAqL1xuICBwcml2YXRlIGdldENxTW9kZWwoKSB7XG4gICAgICByZXR1cm4gUGFnZU1vZGVsTWFuYWdlci5nZXREYXRhKHtwYWdlUGF0aDogdGhpcy5wYWdlUGF0aCwgZGF0YVBhdGg6IHRoaXMucGF0aH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbmRlcnMgYSBjb21wb25lbnQgZHluYW1pY2FsbHkgYmFzZWQgb24gdGhlIGNvbXBvbmVudCBkZWZpbml0aW9uXG4gICAqXG4gICAqIEBwYXJhbSBjb21wb25lbnREZWZpbml0aW9uIFRoZSBjb21wb25lbnQgZGVmaW5pdGlvbiB0byByZW5kZXJcbiAgICovXG4gIHByaXZhdGUgcmVuZGVyQ29tcG9uZW50KGNvbXBvbmVudERlZmluaXRpb246YW55KSB7XG4gICAgaWYgKGNvbXBvbmVudERlZmluaXRpb24pIHtcbiAgICAgIGNvbnN0IGZhY3RvcnkgPSB0aGlzLmZhY3RvcnlSZXNvbHZlci5yZXNvbHZlQ29tcG9uZW50RmFjdG9yeShjb21wb25lbnREZWZpbml0aW9uKTtcbiAgICAgIHRoaXMudmlld0NvbnRhaW5lci5jbGVhcigpO1xuICAgICAgdGhpcy5fY29tcG9uZW50ID0gdGhpcy52aWV3Q29udGFpbmVyLmNyZWF0ZUNvbXBvbmVudChmYWN0b3J5KTtcblxuICAgICAgdGhpcy51cGRhdGVDb21wb25lbnREYXRhKCk7XG4gICAgICB0aGlzLnNldHVwRWxlbWVudCgpO1xuICAgICAgbGV0IGVkaXRDb25maWcgPSBDb21wb25lbnRNYXBwaW5nLmdldEVkaXRDb25maWcoY29tcG9uZW50RGVmaW5pdGlvbik7XG4gICAgICBpZiAoZWRpdENvbmZpZyAmJiBVdGlscy5pc0luRWRpdG9yKSB7XG4gICAgICAgIHRoaXMuc2V0dXBQbGFjZWhvbGRlcihlZGl0Q29uZmlnKTtcbiAgICAgIH1cbiAgICAgIFBhZ2VNb2RlbE1hbmFnZXIucmVtb3ZlTGlzdGVuZXIoe3BhZ2VQYXRoOiB0aGlzLnBhZ2VQYXRoLCBkYXRhUGF0aDogdGhpcy5wYXRoLCBjYWxsYmFjazogdGhpcy51cGRhdGVDcU1vZGVsLmJpbmQodGhpcykgfSk7XG4gICAgICBQYWdlTW9kZWxNYW5hZ2VyLmFkZExpc3RlbmVyKHtwYWdlUGF0aDogdGhpcy5wYWdlUGF0aCwgZGF0YVBhdGg6IHRoaXMucGF0aCwgY2FsbGJhY2s6IHRoaXMudXBkYXRlQ3FNb2RlbC5iaW5kKHRoaXMpIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGVzIHRoZSBkYXRhIG9mIHRoZSBjb21wb25lbnQgYmFzZWQgdGhlIGRhdGEgb2YgdGhlIGRpcmVjdGl2ZVxuICAgKi9cbiAgcHJpdmF0ZSB1cGRhdGVDb21wb25lbnREYXRhKCkge1xuICAgIHRoaXMuX2NvbXBvbmVudC5pbnN0YW5jZS5jcU1vZGVsID0gdGhpcy5jcU1vZGVsO1xuICAgIHRoaXMuX2NvbXBvbmVudC5pbnN0YW5jZS5wYXRoID0gdGhpcy5wYXRoO1xuICAgIHRoaXMuX2NvbXBvbmVudC5pbnN0YW5jZS5wYWdlUGF0aCA9IHRoaXMucGFnZVBhdGg7XG4gICAgdGhpcy5fY29tcG9uZW50Lmluc3RhbmNlLm1vZGVsTmFtZSA9IHRoaXMubW9kZWxOYW1lO1xuXG4gIH1cblxuICAvKipcbiAgICogU2V0dXBzIHRoZSBET00gZWxlbWVudCwgc2V0dGluZyB0aGUgY2xhc3NlcyBhbmQgYXR0cmlidXRlcyBuZWVkZWQgZm9yIHRoZSBBRU0gZWRpdG9yLlxuICAgKi9cbiAgcHJpdmF0ZSBzZXR1cEVsZW1lbnQoKSAge1xuICAgIGlmICh0aGlzLl9vbGRDbGFzc2VzKSB7XG4gICAgICBsZXQgb2xkQ2xhc3NlcyA9IHRoaXMuX29sZENsYXNzZXMuc3BsaXQoJyAnKTtcbiAgICAgIG9sZENsYXNzZXMuZm9yRWFjaCgoY29sdW1uQ2xhc3MpID0+IHtcbiAgICAgICAgdGhpcy5yZW5kZXJlci5yZW1vdmVDbGFzcyh0aGlzLl9jb21wb25lbnQubG9jYXRpb24ubmF0aXZlRWxlbWVudCwgY29sdW1uQ2xhc3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgdGhpcy5fb2xkQ2xhc3NlcyA9IHRoaXMuY29sdW1uQ2xhc3NlcztcbiAgICAvLyBNYW51YWxseSBhZGQgdGhlIGNsYXNzZXNcbiAgICBpZiAodGhpcy5jb2x1bW5DbGFzc2VzKSB7XG4gICAgICBsZXQgY2xhc3NlcyA9IHRoaXMuY29sdW1uQ2xhc3Nlcy5zcGxpdCgnICcpO1xuICAgICAgY2xhc3Nlcy5mb3JFYWNoKChjb2x1bW5DbGFzcykgPT4ge1xuICAgICAgICB0aGlzLnJlbmRlcmVyLmFkZENsYXNzKHRoaXMuX2NvbXBvbmVudC5sb2NhdGlvbi5uYXRpdmVFbGVtZW50LCBjb2x1bW5DbGFzcyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5wYXRoKSB7XG4gICAgICB0aGlzLnJlbmRlcmVyLnNldEF0dHJpYnV0ZSh0aGlzLl9jb21wb25lbnQubG9jYXRpb24ubmF0aXZlRWxlbWVudCwgXCJkYXRhLWNxLWRhdGEtcGF0aFwiICx0aGlzLnBhdGgpO1xuICAgIH1cblxuICB9XG5cbiAgLyoqXG4gICAqIFNldHVwcyB0aGUgcGxhY2Vob2xkZXIgb2YgbmVlZGVkIGZvciB0aGUgQUVNIGVkaXRvclxuICAgKlxuICAgKiBAcGFyYW0gZWRpdENvbmZpZyAtIHRoZSBlZGl0Q29uZmlnLCB3aGljaCB3aWxsIGRpY3RhdGUgdGhlIGNsYXNzZXMgdG8gYmUgYWRkZWQgb24uXG4gICAqL1xuICBwcml2YXRlIHNldHVwUGxhY2Vob2xkZXIoZWRpdENvbmZpZykge1xuICAgIC8vIFJlbW92ZSBwcmV2aW91cyBkcmFnIGFuZCBkcm9wIGNsYXNzIG5hbWVzXG4gICAgdGhpcy5yZW5kZXJlci5yZW1vdmVDbGFzcyh0aGlzLl9jb21wb25lbnQubG9jYXRpb24ubmF0aXZlRWxlbWVudCwgRFJBR19EUk9QX0NMQVNTX05BTUUgKyBlZGl0Q29uZmlnLmRyYWdEcm9wTmFtZSk7XG5cbiAgICBpZiAoZWRpdENvbmZpZy5kcmFnRHJvcE5hbWUgJiYgZWRpdENvbmZpZy5kcmFnRHJvcE5hbWUudHJpbSgpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdGhpcy5yZW5kZXJlci5hZGRDbGFzcyh0aGlzLl9jb21wb25lbnQubG9jYXRpb24ubmF0aXZlRWxlbWVudCwgRFJBR19EUk9QX0NMQVNTX05BTUUgKyBlZGl0Q29uZmlnLmRyYWdEcm9wTmFtZSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMudXNlUGxhY2Vob2xkZXIoZWRpdENvbmZpZykpIHtcbiAgICAgICAgdGhpcy5yZW5kZXJlci5hZGRDbGFzcyh0aGlzLl9jb21wb25lbnQubG9jYXRpb24ubmF0aXZlRWxlbWVudCwgUExBQ0VIT0xERVJfQ0xBU1NfTkFNRSk7XG4gICAgICAgIHRoaXMuX2NvbXBvbmVudC5sb2NhdGlvbi5uYXRpdmVFbGVtZW50LmRhdGFzZXQuZW1wdHl0ZXh0ID0gZWRpdENvbmZpZy5lbXB0eUxhYmVsO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucmVuZGVyZXIucmVtb3ZlQ2xhc3ModGhpcy5fY29tcG9uZW50LmxvY2F0aW9uLm5hdGl2ZUVsZW1lbnQsIFBMQUNFSE9MREVSX0NMQVNTX05BTUUpO1xuICAgICAgICBkZWxldGUgdGhpcy5fY29tcG9uZW50LmxvY2F0aW9uLm5hdGl2ZUVsZW1lbnQuZGF0YXNldC5lbXB0eXRleHQ7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERldGVybWluZXMgaWYgdGhlIHBsYWNlaG9sZGVyIHNob3VsZCBlIGRpc3BsYXllZC5cbiAgICpcbiAgICogQHBhcmFtIGVkaXRDb25maWcgLSB0aGUgZWRpdCBjb25maWcgb2YgdGhlIGRpcmVjdGl2ZVxuICAgKi9cbiAgcHJpdmF0ZSB1c2VQbGFjZWhvbGRlcihlZGl0Q29uZmlnKSB7XG4gICAgcmV0dXJuIGVkaXRDb25maWcuaXNFbXB0eSAmJiB0eXBlb2YgZWRpdENvbmZpZy5pc0VtcHR5ID09PSBcImZ1bmN0aW9uXCIgJiYgZWRpdENvbmZpZy5pc0VtcHR5KHRoaXMuY3FNb2RlbCk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICBQYWdlTW9kZWxNYW5hZ2VyLnJlbW92ZUxpc3RlbmVyKHtwYWdlUGF0aDogdGhpcy5wYWdlUGF0aCwgZGF0YVBhdGg6IHRoaXMucGF0aCwgY2FsbGJhY2s6IHRoaXMudXBkYXRlQ3FNb2RlbC5iaW5kKHRoaXMpIH0pO1xuICAgIHRoaXMuX2NvbXBvbmVudCAmJiB0aGlzLl9jb21wb25lbnQuZGVzdHJveSgpO1xuICB9XG5cbn1cbiIsIi8qXG4gKiBBRE9CRSBDT05GSURFTlRJQUxcbiAqXG4gKiBDb3B5cmlnaHQgMjAxOCBBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZFxuICogQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBOT1RJQ0U6ICBBbGwgaW5mb3JtYXRpb24gY29udGFpbmVkIGhlcmVpbiBpcywgYW5kIHJlbWFpbnNcbiAqIHRoZSBwcm9wZXJ0eSBvZiBBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZCBhbmQgaXRzIHN1cHBsaWVycyxcbiAqIGlmIGFueS4gIFRoZSBpbnRlbGxlY3R1YWwgYW5kIHRlY2huaWNhbCBjb25jZXB0cyBjb250YWluZWRcbiAqIGhlcmVpbiBhcmUgcHJvcHJpZXRhcnkgdG8gQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQgYW5kIGl0c1xuICogc3VwcGxpZXJzIGFuZCBtYXkgYmUgY292ZXJlZCBieSBVLlMuIGFuZCBGb3JlaWduIFBhdGVudHMsXG4gKiBwYXRlbnRzIGluIHByb2Nlc3MsIGFuZCBhcmUgcHJvdGVjdGVkIGJ5IHRyYWRlIHNlY3JldCBvciBjb3B5cmlnaHQgbGF3LlxuICogRGlzc2VtaW5hdGlvbiBvZiB0aGlzIGluZm9ybWF0aW9uIG9yIHJlcHJvZHVjdGlvbiBvZiB0aGlzIG1hdGVyaWFsXG4gKiBpcyBzdHJpY3RseSBmb3JiaWRkZW4gdW5sZXNzIHByaW9yIHdyaXR0ZW4gcGVybWlzc2lvbiBpcyBvYnRhaW5lZFxuICogZnJvbSBBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZC5cbiAqL1xuXG5pbXBvcnQgeyBDb21wb25lbnQsIElucHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb25zdGFudHMgfSBmcm9tICcuLi9jb25zdGFudHMnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdhZW0tY29udGFpbmVyJyxcbiAgaG9zdDoge1xuICAgICAgJ1thdHRyLmRhdGEtY3EtZGF0YS1wYXRoXSc6J3BhdGgnXG4gIH0sXG4gIHRlbXBsYXRlOiBgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgaXRlbUtleSBvZiBpdGVtc09yZGVyXCI+XG4gIDxuZy1jb250YWluZXIgW2FlbUNvbXBvbmVudF0gW2NxTW9kZWxdPSdnZXRJdGVtKGl0ZW1LZXkpJyBbcGFnZVBhdGhdPSdnZXRQYWdlUGF0aCgpJyBbcGF0aF09J2dldERhdGFQYXRoKGl0ZW1LZXkpJyBbbW9kZWxOYW1lXT0naXRlbUtleSc+PC9uZy1jb250YWluZXI+XG48L25nLWNvbnRhaW5lcj5cbmBcbn0pXG5leHBvcnQgY2xhc3MgQUVNQ29udGFpbmVyQ29tcG9uZW50IHtcbiAgQElucHV0KCkgY3FNb2RlbDphbnk7XG4gIEBJbnB1dCgpIHBhdGg6c3RyaW5nID0gJyc7XG4gIEBJbnB1dCgpIHBhZ2VQYXRoOnN0cmluZyA9ICcnO1xuICBASW5wdXQoKSBtb2RlbE5hbWU6c3RyaW5nID0gJyc7XG5cbiAgY29uc3RydWN0b3IoKSB7fVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBhZ2dyZWdhdGVkIHBhdGggb2YgdGhpcyBjb250YWluZXIgcGF0aCBhbmQgdGhlIHByb3ZpZGVkIHBhdGhcbiAgICpcbiAgICogQHBhcmFtIHBhdGggLSB0aGUgcHJvdmlkZWQgcGF0aCB0byBhZ2dyZWdhdGUgd2l0aCB0aGUgY29udGFpbmVyIHBhdGhcbiAgICovXG4gIGdldERhdGFQYXRoKHBhdGgpIHtcbiAgICByZXR1cm4gdGhpcy5wYXRoID8gdGhpcy5wYXRoICsgXCIvXCIgKyBwYXRoIDogcGF0aDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIHBhZ2UgcGF0aCBmcm9tIHRoZSBkYXRhLCBkZWZhdWx0aW5nIHRvIHRoZSBwcm92aWRlZCBwYWdlUGF0aCB0byB0aGUgY29udGFpbmVyLlxuICAgKi9cbiAgZ2V0UGFnZVBhdGgoKSB7XG4gICAgcmV0dXJuIHRoaXMuY3FNb2RlbFtDb25zdGFudHMuUEFUSF9QUk9QXSB8fCB0aGlzLnBhZ2VQYXRoO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGl0ZW0gZGF0YSBmcm9tIHRoZSBjcU1vZGVsXG4gICAqXG4gICAqIEBwYXJhbSBpdGVtS2V5IC0gdGhlIGl0ZW1LZXkgdG8gbG9vayBmb3IgaW4gdGhlIGl0ZW1zLlxuICAgKi9cbiAgZ2V0SXRlbShpdGVtS2V5KSB7XG4gICAgcmV0dXJuIHRoaXMuY3FNb2RlbFtDb25zdGFudHMuSVRFTVNfUFJPUF1baXRlbUtleV07XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgaXRlbXNPcmRlciBhcnJheSBmcm9tIHRoZSBjcU1vZGVsXG4gICAqL1xuICBnZXQgaXRlbXNPcmRlcigpIHtcbiAgICByZXR1cm4gdGhpcy5jcU1vZGVsICYmIHRoaXMuY3FNb2RlbFtDb25zdGFudHMuSVRFTVNfT1JERVJfUFJPUF07XG4gIH1cbn1cblxuIiwiLypcbiAqIEFET0JFIENPTkZJREVOVElBTFxuICpcbiAqIENvcHlyaWdodCAyMDE4IEFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkXG4gKiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIE5PVElDRTogIEFsbCBpbmZvcm1hdGlvbiBjb250YWluZWQgaGVyZWluIGlzLCBhbmQgcmVtYWluc1xuICogdGhlIHByb3BlcnR5IG9mIEFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkIGFuZCBpdHMgc3VwcGxpZXJzLFxuICogaWYgYW55LiAgVGhlIGludGVsbGVjdHVhbCBhbmQgdGVjaG5pY2FsIGNvbmNlcHRzIGNvbnRhaW5lZFxuICogaGVyZWluIGFyZSBwcm9wcmlldGFyeSB0byBBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZCBhbmQgaXRzXG4gKiBzdXBwbGllcnMgYW5kIG1heSBiZSBjb3ZlcmVkIGJ5IFUuUy4gYW5kIEZvcmVpZ24gUGF0ZW50cyxcbiAqIHBhdGVudHMgaW4gcHJvY2VzcywgYW5kIGFyZSBwcm90ZWN0ZWQgYnkgdHJhZGUgc2VjcmV0IG9yIGNvcHlyaWdodCBsYXcuXG4gKiBEaXNzZW1pbmF0aW9uIG9mIHRoaXMgaW5mb3JtYXRpb24gb3IgcmVwcm9kdWN0aW9uIG9mIHRoaXMgbWF0ZXJpYWxcbiAqIGlzIHN0cmljdGx5IGZvcmJpZGRlbiB1bmxlc3MgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uIGlzIG9idGFpbmVkXG4gKiBmcm9tIEFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkLlxuICovXG5cbmltcG9ydCB7IENvbXBvbmVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQUVNQ29udGFpbmVyQ29tcG9uZW50IH0gZnJvbSAnLi4vYWVtLWNvbnRhaW5lci9hZW0tY29udGFpbmVyLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBVdGlscyB9IGZyb20gXCIuLi91dGlsc1wiO1xuaW1wb3J0IHsgQ29uc3RhbnRzIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuXG5jb25zdCBDT05UQUlORVJfQ0xBU1NfTkFNRVMgPSAnYWVtLWNvbnRhaW5lcic7XG5jb25zdCBQTEFDRUhPTERFUl9DTEFTU19OQU1FUyA9IENvbnN0YW50cy5ORVdfU0VDVElPTl9DTEFTU19OQU1FUyArICcgYWVtLUdyaWQtbmV3Q29tcG9uZW50JztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYWVtLXJlc3BvbnNpdmVncmlkJyxcbiAgaG9zdDoge1xuICAgICAgJ1tjbGFzc10nOiAnY2xhc3NOYW1lcycsXG4gICAgICAnW2F0dHIuZGF0YS1jcS1kYXRhLXBhdGhdJzoncGF0aCdcbiAgfSxcbiAgdGVtcGxhdGU6IGA8ZGl2IFtjbGFzc109XCJncmlkQ2xhc3Nlc1wiPlxuICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBpdGVtS2V5IG9mIGl0ZW1zT3JkZXJcIj5cbiAgICA8bmctY29udGFpbmVyIFthZW1Db21wb25lbnRdIFtjcU1vZGVsXT0nZ2V0SXRlbShpdGVtS2V5KScgW3BhZ2VQYXRoXT0nZ2V0UGFnZVBhdGgoKScgW3BhdGhdPSdnZXREYXRhUGF0aChpdGVtS2V5KScgW21vZGVsTmFtZV09J2l0ZW1LZXknPjwvbmctY29udGFpbmVyPlxuICA8L25nLWNvbnRhaW5lcj5cbiAgPGRpdiAqbmdJZj1cImlzSW5FZGl0TW9kZVwiIFthdHRyLmRhdGEtY3EtZGF0YS1wYXRoXT1cInBsYWNlaG9sZGVQYXRoXCIgW2NsYXNzXT1cInBsYWNlaG9sZGVyQ2xhc3NcIj48L2Rpdj5cbjwvZGl2PlxuYCxcbn0pXG5leHBvcnQgY2xhc3MgQUVNUmVzcG9uc2l2ZUdyaWRDb21wb25lbnQgZXh0ZW5kcyBBRU1Db250YWluZXJDb21wb25lbnQge1xuICAvKipcbiAgICogUmV0dXJucyB3ZWF0aGVyIG9mIG5vdCB3ZSBhcmUgaW4gdGhlIGVkaXRvclxuICAgKi9cbiAgZ2V0IGlzSW5FZGl0TW9kZSgpIHtcbiAgICByZXR1cm4gVXRpbHMuaXNJbkVkaXRvcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHBsYWNlaG9sZGVyIGNsYXNzZXNcbiAgICovXG4gIGdldCBwbGFjZWhvbGRlckNsYXNzKCkge1xuICAgIHJldHVybiBQTEFDRUhPTERFUl9DTEFTU19OQU1FUztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBwbGFjZWhvbGRlciBwYXRoXG4gICAqL1xuICBnZXQgcGxhY2Vob2xkZVBhdGgoKSB7XG4gICAgcmV0dXJuIHRoaXMucGF0aCAmJiB0aGlzLnBhdGggKyBcIi8qXCI7XG4gIH1cblxuICAgIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBncmlkQ2xhc3NlcyBmb3IgdGhlIGNxTW9kZWwgb2YgdGhlIHJlc3BvbnNpdmUgZ3JpZFxuICAgKi9cbiAgZ2V0IGdyaWRDbGFzc2VzKCkge1xuICAgIHJldHVybiB0aGlzLmNxTW9kZWwgJiYgKHRoaXMuY3FNb2RlbFtcImdyaWRDbGFzc05hbWVzXCJdIHx8ICcnKTtcbiAgfVxuXG4gICAgLyoqXG4gICAqIFJldHVybnMgdGhlIGNsYXNzIG5hbWVzIG9mIHRoZSByZXNwb25zaXZlIGdyaWQgYmFzZWQgb24gdGhlIGRhdGEgZnJvbSB0aGUgY3FNb2RlbFxuICAgKi9cbiAgZ2V0IGNsYXNzTmFtZXMoKSB7XG4gICAgaWYgKCF0aGlzLmNxTW9kZWwpIHtcbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIGxldCBjbGFzc05hbWVzID0gQ09OVEFJTkVSX0NMQVNTX05BTUVTO1xuXG4gICAgaWYgKHRoaXMuY3FNb2RlbC5jbGFzc05hbWVzKSB7XG4gICAgICAgIGNsYXNzTmFtZXMgKz0gJyAnICsgKHRoaXMuY3FNb2RlbC5jbGFzc05hbWVzIHx8ICcnKSA7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuY3FNb2RlbC5jb2x1bW5DbGFzc05hbWVzKSB7XG4gICAgICAgIGNsYXNzTmFtZXMgKz0gJyAnICsgKHRoaXMuY3FNb2RlbC5jb2x1bW5DbGFzc05hbWVzIHx8ICcnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2xhc3NOYW1lcztcbiAgfVxufVxuIiwiLypcbiAqICBDb3B5cmlnaHQgMjAxOCBBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZC4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBUaGlzIGZpbGUgaXMgbGljZW5zZWQgdG8geW91IHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiAgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLiBZb3UgbWF5IG9idGFpbiBhIGNvcHlcbiAqICBvZiB0aGUgTGljZW5zZSBhdCBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiAgVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZSBkaXN0cmlidXRlZCB1bmRlclxuICogIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTIE9SIFJFUFJFU0VOVEFUSU9OU1xuICogIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZVxuICogIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQgbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IE5nTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBRU1Db21wb25lbnREaXJlY3RpdmUgfSBmcm9tIFwiLi9sYXlvdXQvYWVtLWNvbXBvbmVudC5kaXJlY3RpdmVcIjtcbmltcG9ydCB7IEFFTUNvbnRhaW5lckNvbXBvbmVudCB9IGZyb20gXCIuL2xheW91dC9hZW0tY29udGFpbmVyL2FlbS1jb250YWluZXIuY29tcG9uZW50XCI7XG5pbXBvcnQgeyBBRU1SZXNwb25zaXZlR3JpZENvbXBvbmVudCB9IGZyb20gXCIuL2xheW91dC9hZW0tcmVzcG9uc2l2ZWdyaWQvYWVtLXJlc3BvbnNpdmVncmlkLmNvbXBvbmVudFwiO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcblxuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZV0sXG5cbiAgZGVjbGFyYXRpb25zOiBbQUVNQ29udGFpbmVyQ29tcG9uZW50LCBBRU1SZXNwb25zaXZlR3JpZENvbXBvbmVudCwgQUVNQ29tcG9uZW50RGlyZWN0aXZlXSxcbiAgZXhwb3J0czogW0FFTUNvbnRhaW5lckNvbXBvbmVudCwgQUVNUmVzcG9uc2l2ZUdyaWRDb21wb25lbnQsIEFFTUNvbXBvbmVudERpcmVjdGl2ZV1cbn0pXG5leHBvcnQgY2xhc3MgU3BhQW5ndWxhckVkaXRhYmxlQ29tcG9uZW50c01vZHVsZSB7IH1cbiJdLCJuYW1lcyI6WyJTUEFDb21wb25lbnRNYXBwaW5nIiwiQ29uc3RhbnRzIiwiUE1Db25zdGFudHMiLCJDb21wb25lbnRNYXBwaW5nIiwidHNsaWJfMS5fX2V4dGVuZHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7SUFtQkE7SUFHRSxvQ0FBb0IsVUFBOEI7UUFBOUIsZUFBVSxHQUFWLFVBQVUsQ0FBb0I7NkJBRlAsSUFBSSxPQUFPLEVBQUU7S0FFRjs7Ozs7OztJQUV0RCx3Q0FBRzs7Ozs7O0lBQUgsVUFBSSxhQUFhLEVBQUUsS0FBSyxFQUFFLFVBQWlCO1FBQWpCLDJCQUFBLEVBQUEsaUJBQWlCO1FBQ3ZDLHFCQUFJLFVBQVUsR0FBRyxLQUFLLENBQUM7UUFFdkIsSUFBSSxVQUFVLEVBQUU7WUFDWixJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsVUFBVSxDQUFDLENBQUM7U0FDN0M7UUFDRCxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsVUFBVSxDQUFDLENBQUM7S0FDbEQ7Ozs7O0lBRUQsd0NBQUc7Ozs7SUFBSCxVQUFJLFlBQVk7UUFDZCxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFDO0tBQzFDOzs7OztJQUVELGtEQUFhOzs7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