UNPKG

@adobe/cq-angular-editable-components

Version:

* [API](#api) * [Documentation](#documentation) * [Changelog](#changelog)

640 lines (629 loc) 56.6 kB
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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