UNPKG

@adobe/cq-angular-editable-components

Version:

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

499 lines (488 loc) 50.2 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 { CommonModule } from '@angular/common'; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class ComponentMappingWithConfig { /** * @param {?} spaMapping */ constructor(spaMapping) { this.spaMapping = spaMapping; this.editConfigMap = new WeakMap(); } /** * @param {?} resourceTypes * @param {?} clazz * @param {?=} editConfig * @return {?} */ map(resourceTypes, clazz, editConfig = null) { let /** @type {?} */ innerClass = clazz; if (editConfig) { this.editConfigMap.set(clazz, editConfig); } this.spaMapping.map(resourceTypes, innerClass); } ; /** * @param {?} resourceType * @return {?} */ get(resourceType) { return this.spaMapping.get(resourceType); } /** * @param {?} component * @return {?} */ getEditConfig(component) { return this.editConfigMap.get(component); } } let /** @type {?} */ componentMapping = new ComponentMappingWithConfig(ComponentMapping); /** * @param {?} resourceTypes * @return {?} */ function MapTo(resourceTypes) { return (clazz, editConfig = null) => { return componentMapping.map(resourceTypes, clazz, editConfig); }; } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ const /** @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 * */ const /** @type {?} */ WCM_MODE_META_SELECTOR = 'meta[property="cq:wcmmode"]'; /** * The editor is in one of the edition modes */ const /** @type {?} */ EDIT_MODE = 'edit'; /** * The editor is in preview mode */ const /** @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() { const /** @type {?} */ wcmModeMeta = document.head.querySelector(WCM_MODE_META_SELECTOR); return wcmModeMeta && wcmModeMeta.content; } /** * Helper functions for interacting with the AEM environment * */ const /** @type {?} */ Utils = { /** * Is the app used in the context of the AEM Page editor * * @return {?} */ isInEditor() { const /** @type {?} */ wcmMode = getWCMMode(); return wcmMode && (EDIT_MODE === wcmMode || PREVIEW_MODE === wcmMode); } }; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ const /** @type {?} */ PLACEHOLDER_CLASS_NAME = 'cq-placeholder'; const /** @type {?} */ DRAG_DROP_CLASS_NAME = 'cq-dd-'; class AEMComponentDirective { /** * @param {?} renderer * @param {?} viewContainer * @param {?} factoryResolver * @param {?} ngZone */ constructor(renderer, viewContainer, factoryResolver, ngZone) { this.renderer = renderer; this.viewContainer = viewContainer; this.factoryResolver = factoryResolver; this.ngZone = ngZone; } /** * @return {?} */ ngOnInit() { this.renderComponent(componentMapping.get(this.type)); } /** * Returns the type of the cqModel if exists. * @return {?} */ get type() { return this.cqModel && this.cqModel[":type"]; } /** * Returns the column classes of the cqModel * @return {?} */ get columnClasses() { return this.cqModel && (this.cqModel.columnClassNames || ''); } /** * Updates the cqModel * @return {?} */ updateCqModel() { // Fetching the latest data for the item at the given path this.getCqModel().then(model => { this.ngZone.run(() => { model[Constants$1.DATA_PATH_PROP] = this.path; this.cqModel = model; this.updateComponentData(); this.setupElement(); let /** @type {?} */ editConfig = componentMapping.getEditConfig(componentMapping.get(this.type)); if (editConfig) { this.setupPlaceholder(editConfig); } }); }); } /** * Returns the Cq Model * * @return {?} */ getCqModel() { 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 {?} */ renderComponent(componentDefinition) { if (componentDefinition) { const /** @type {?} */ factory = this.factoryResolver.resolveComponentFactory(componentDefinition); this.viewContainer.clear(); this._component = this.viewContainer.createComponent(factory); this.updateComponentData(); this.setupElement(); let /** @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 {?} */ updateComponentData() { 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 {?} */ setupElement() { if (this._oldClasses) { let /** @type {?} */ oldClasses = this._oldClasses.split(' '); oldClasses.forEach((columnClass) => { this.renderer.removeClass(this._component.location.nativeElement, columnClass); }); } this._oldClasses = this.columnClasses; // Manually add the classes if (this.columnClasses) { let /** @type {?} */ classes = this.columnClasses.split(' '); classes.forEach((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 {?} */ setupPlaceholder(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 {?} */ usePlaceholder(editConfig) { return editConfig.isEmpty && typeof editConfig.isEmpty === "function" && editConfig.isEmpty(this.cqModel); } /** * @return {?} */ ngOnDestroy() { 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 = () => [ { 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 },], }; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class AEMContainerComponent { constructor() { 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 * @return {?} */ getDataPath(path) { return this.path ? this.path + "/" + path : path; } /** * Return the page path from the data, defaulting to the provided pagePath to the container. * @return {?} */ getPagePath() { 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. * @return {?} */ getItem(itemKey) { return this.cqModel[Constants$1.ITEMS_PROP][itemKey]; } /** * Returns the itemsOrder array from the cqModel * @return {?} */ get itemsOrder() { return this.cqModel && this.cqModel[Constants$1.ITEMS_ORDER_PROP]; } } AEMContainerComponent.decorators = [ { type: Component, args: [{ selector: 'aem-container', host: { '[attr.data-cq-data-path]': 'path' }, template: `<ng-container *ngFor="let itemKey of itemsOrder"> <ng-container [aemComponent] [cqModel]='getItem(itemKey)' [pagePath]='getPagePath()' [path]='getDataPath(itemKey)' [modelName]='itemKey'></ng-container> </ng-container> ` },] }, ]; /** @nocollapse */ AEMContainerComponent.ctorParameters = () => []; AEMContainerComponent.propDecorators = { "cqModel": [{ type: Input },], "path": [{ type: Input },], "pagePath": [{ type: Input },], "modelName": [{ type: Input },], }; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ const /** @type {?} */ CONTAINER_CLASS_NAMES = 'aem-container'; const /** @type {?} */ PLACEHOLDER_CLASS_NAMES = Constants$1.NEW_SECTION_CLASS_NAMES + ' aem-Grid-newComponent'; class AEMResponsiveGridComponent extends AEMContainerComponent { /** * Returns weather of not we are in the editor * @return {?} */ get isInEditMode() { return Utils.isInEditor(); } /** * Returns the placeholder classes * @return {?} */ get placeholderClass() { return PLACEHOLDER_CLASS_NAMES; } /** * Returns the placeholder path * @return {?} */ get placeholdePath() { return this.path && this.path + "/*"; } /** * Returns the gridClasses for the cqModel of the responsive grid * @return {?} */ get gridClasses() { return this.cqModel && (this.cqModel["gridClassNames"] || ''); } /** * Returns the class names of the responsive grid based on the data from the cqModel * @return {?} */ get classNames() { if (!this.cqModel) { return ''; } let /** @type {?} */ classNames = CONTAINER_CLASS_NAMES; if (this.cqModel.classNames) { classNames += ' ' + (this.cqModel.classNames || ''); } if (this.cqModel.columnClassNames) { classNames += ' ' + (this.cqModel.columnClassNames || ''); } return classNames; } } AEMResponsiveGridComponent.decorators = [ { type: Component, args: [{ selector: 'aem-responsivegrid', host: { '[class]': 'classNames', '[attr.data-cq-data-path]': 'path' }, template: `<div [class]="gridClasses"> <ng-container *ngFor="let itemKey of itemsOrder"> <ng-container [aemComponent] [cqModel]='getItem(itemKey)' [pagePath]='getPagePath()' [path]='getDataPath(itemKey)' [modelName]='itemKey'></ng-container> </ng-container> <div *ngIf="isInEditMode" [attr.data-cq-data-path]="placeholdePath" [class]="placeholderClass"></div> </div> `, },] }, ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class SpaAngularEditableComponentsModule { } SpaAngularEditableComponentsModule.decorators = [ { type: NgModule, args: [{ imports: [CommonModule], declarations: [AEMContainerComponent, AEMResponsiveGridComponent, AEMComponentDirective], exports: [AEMContainerComponent, AEMResponsiveGridComponent, AEMComponentDirective] },] }, ]; /** * @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+XG48L25nLWNvbnRhaW5lcj5cbmBcbn0pXG5leHBvcnQgY2xhc3MgQUVNQ29udGFpbmVyQ29tcG9uZW50IHtcbiAgQElucHV0KCkgY3FNb2RlbDphbnk7XG4gIEBJbnB1dCgpIHBhdGg6c3RyaW5nID0gJyc7XG4gIEBJbnB1dCgpIHBhZ2VQYXRoOnN0cmluZyA9ICcnO1xuICBASW5wdXQoKSBtb2RlbE5hbWU6c3RyaW5nID0gJyc7XG5cbiAgY29uc3RydWN0b3IoKSB7fVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBhZ2dyZWdhdGVkIHBhdGggb2YgdGhpcyBjb250YWluZXIgcGF0aCBhbmQgdGhlIHByb3ZpZGVkIHBhdGhcbiAgICpcbiAgICogQHBhcmFtIHBhdGggLSB0aGUgcHJvdmlkZWQgcGF0aCB0byBhZ2dyZWdhdGUgd2l0aCB0aGUgY29udGFpbmVyIHBhdGhcbiAgICovXG4gIGdldERhdGFQYXRoKHBhdGgpIHtcbiAgICByZXR1cm4gdGhpcy5wYXRoID8gdGhpcy5wYXRoICsgXCIvXCIgKyBwYXRoIDogcGF0aDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIHBhZ2UgcGF0aCBmcm9tIHRoZSBkYXRhLCBkZWZhdWx0aW5nIHRvIHRoZSBwcm92aWRlZCBwYWdlUGF0aCB0byB0aGUgY29udGFpbmVyLlxuICAgKi9cbiAgZ2V0UGFnZVBhdGgoKSB7XG4gICAgcmV0dXJuIHRoaXMuY3FNb2RlbFtDb25zdGFudHMuUEFUSF9QUk9QXSB8fCB0aGlzLnBhZ2VQYXRoO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGl0ZW0gZGF0YSBmcm9tIHRoZSBjcU1vZGVsXG4gICAqXG4gICAqIEBwYXJhbSBpdGVtS2V5IC0gdGhlIGl0ZW1LZXkgdG8gbG9vayBmb3IgaW4gdGhlIGl0ZW1zLlxuICAgKi9cbiAgZ2V0SXRlbShpdGVtS2V5KSB7XG4gICAgcmV0dXJuIHRoaXMuY3FNb2RlbFtDb25zdGFudHMuSVRFTVNfUFJPUF1baXRlbUtleV07XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgaXRlbXNPcmRlciBhcnJheSBmcm9tIHRoZSBjcU1vZGVsXG4gICAqL1xuICBnZXQgaXRlbXNPcmRlcigpIHtcbiAgICByZXR1cm4gdGhpcy5jcU1vZGVsICYmIHRoaXMuY3FNb2RlbFtDb25zdGFudHMuSVRFTVNfT1JERVJfUFJPUF07XG4gIH1cbn1cblxuIiwiLypcbiAqIEFET0JFIENPTkZJREVOVElBTFxuICpcbiAqIENvcHlyaWdodCAyMDE4IEFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkXG4gKiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIE5PVElDRTogIEFsbCBpbmZvcm1hdGlvbiBjb250YWluZWQgaGVyZWluIGlzLCBhbmQgcmVtYWluc1xuICogdGhlIHByb3BlcnR5IG9mIEFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkIGFuZCBpdHMgc3VwcGxpZXJzLFxuICogaWYgYW55LiAgVGhlIGludGVsbGVjdHVhbCBhbmQgdGVjaG5pY2FsIGNvbmNlcHRzIGNvbnRhaW5lZFxuICogaGVyZWluIGFyZSBwcm9wcmlldGFyeSB0byBBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZCBhbmQgaXRzXG4gKiBzdXBwbGllcnMgYW5kIG1heSBiZSBjb3ZlcmVkIGJ5IFUuUy4gYW5kIEZvcmVpZ24gUGF0ZW50cyxcbiAqIHBhdGVudHMgaW4gcHJvY2VzcywgYW5kIGFyZSBwcm90ZWN0ZWQgYnkgdHJhZGUgc2VjcmV0IG9yIGNvcHlyaWdodCBsYXcuXG4gKiBEaXNzZW1pbmF0aW9uIG9mIHRoaXMgaW5mb3JtYXRpb24gb3IgcmVwcm9kdWN0aW9uIG9mIHRoaXMgbWF0ZXJpYWxcbiAqIGlzIHN0cmljdGx5IGZvcmJpZGRlbiB1bmxlc3MgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uIGlzIG9idGFpbmVkXG4gKiBmcm9tIEFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkLlxuICovXG5cbmltcG9ydCB7IENvbXBvbmVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQUVNQ29udGFpbmVyQ29tcG9uZW50IH0gZnJvbSAnLi4vYWVtLWNvbnRhaW5lci9hZW0tY29udGFpbmVyLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBVdGlscyB9IGZyb20gXCIuLi91dGlsc1wiO1xuaW1wb3J0IHsgQ29uc3RhbnRzIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuXG5jb25zdCBDT05UQUlORVJfQ0xBU1NfTkFNRVMgPSAnYWVtLWNvbnRhaW5lcic7XG5jb25zdCBQTEFDRUhPTERFUl9DTEFTU19OQU1FUyA9IENvbnN0YW50cy5ORVdfU0VDVElPTl9DTEFTU19OQU1FUyArICcgYWVtLUdyaWQtbmV3Q29tcG9uZW50JztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYWVtLXJlc3BvbnNpdmVncmlkJyxcbiAgaG9zdDoge1xuICAgICAgJ1tjbGFzc10nOiAnY2xhc3NOYW1lcycsXG4gICAgICAnW2F0dHIuZGF0YS1jcS1kYXRhLXBhdGhdJzoncGF0aCdcbiAgfSxcbiAgdGVtcGxhdGU6IGA8ZGl2IFtjbGFzc109XCJncmlkQ2xhc3Nlc1wiPlxuICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBpdGVtS2V5IG9mIGl0ZW1zT3JkZXJcIj5cbiAgICA8bmctY29udGFpbmVyIFthZW1Db21wb25lbnRdIFtjcU1vZGVsXT0nZ2V0SXRlbShpdGVtS2V5KScgW3BhZ2VQYXRoXT0nZ2V0UGFnZVBhdGgoKScgW3BhdGhdPSdnZXREYXRhUGF0aChpdGVtS2V5KScgW21vZGVsTmFtZV09J2l0ZW1LZXknPjwvbmctY29udGFpbmVyPlxuICA8L25nLWNvbnRhaW5lcj5cbiAgPGRpdiAqbmdJZj1cImlzSW5FZGl0TW9kZVwiIFthdHRyLmRhdGEtY3EtZGF0YS1wYXRoXT1cInBsYWNlaG9sZGVQYXRoXCIgW2NsYXNzXT1cInBsYWNlaG9sZGVyQ2xhc3NcIj48L2Rpdj5cbjwvZGl2PlxuYCxcbn0pXG5leHBvcnQgY2xhc3MgQUVNUmVzcG9uc2l2ZUdyaWRDb21wb25lbnQgZXh0ZW5kcyBBRU1Db250YWluZXJDb21wb25lbnQge1xuICAvKipcbiAgICogUmV0dXJucyB3ZWF0aGVyIG9mIG5vdCB3ZSBhcmUgaW4gdGhlIGVkaXRvclxuICAgKi9cbiAgZ2V0IGlzSW5FZGl0TW9kZSgpIHtcbiAgICByZXR1cm4gVXRpbHMuaXNJbkVkaXRvcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHBsYWNlaG9sZGVyIGNsYXNzZXNcbiAgICovXG4gIGdldCBwbGFjZWhvbGRlckNsYXNzKCkge1xuICAgIHJldHVybiBQTEFDRUhPTERFUl9DTEFTU19OQU1FUztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBwbGFjZWhvbGRlciBwYXRoXG4gICAqL1xuICBnZXQgcGxhY2Vob2xkZVBhdGgoKSB7XG4gICAgcmV0dXJuIHRoaXMucGF0aCAmJiB0aGlzLnBhdGggKyBcIi8qXCI7XG4gIH1cblxuICAgIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBncmlkQ2xhc3NlcyBmb3IgdGhlIGNxTW9kZWwgb2YgdGhlIHJlc3BvbnNpdmUgZ3JpZFxuICAgKi9cbiAgZ2V0IGdyaWRDbGFzc2VzKCkge1xuICAgIHJldHVybiB0aGlzLmNxTW9kZWwgJiYgKHRoaXMuY3FNb2RlbFtcImdyaWRDbGFzc05hbWVzXCJdIHx8ICcnKTtcbiAgfVxuXG4gICAgLyoqXG4gICAqIFJldHVybnMgdGhlIGNsYXNzIG5hbWVzIG9mIHRoZSByZXNwb25zaXZlIGdyaWQgYmFzZWQgb24gdGhlIGRhdGEgZnJvbSB0aGUgY3FNb2RlbFxuICAgKi9cbiAgZ2V0IGNsYXNzTmFtZXMoKSB7XG4gICAgaWYgKCF0aGlzLmNxTW9kZWwpIHtcbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIGxldCBjbGFzc05hbWVzID0gQ09OVEFJTkVSX0NMQVNTX05BTUVTO1xuXG4gICAgaWYgKHRoaXMuY3FNb2RlbC5jbGFzc05hbWVzKSB7XG4gICAgICAgIGNsYXNzTmFtZXMgKz0gJyAnICsgKHRoaXMuY3FNb2RlbC5jbGFzc05hbWVzIHx8ICcnKSA7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuY3FNb2RlbC5jb2x1bW5DbGFzc05hbWVzKSB7XG4gICAgICAgIGNsYXNzTmFtZXMgKz0gJyAnICsgKHRoaXMuY3FNb2RlbC5jb2x1bW5DbGFzc05hbWVzIHx8ICcnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2xhc3NOYW1lcztcbiAgfVxufVxuIiwiLypcbiAqICBDb3B5cmlnaHQgMjAxOCBBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZC4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqICBUaGlzIGZpbGUgaXMgbGljZW5zZWQgdG8geW91IHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiAgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLiBZb3UgbWF5IG9idGFpbiBhIGNvcHlcbiAqICBvZiB0aGUgTGljZW5zZSBhdCBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiAgVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZSBkaXN0cmlidXRlZCB1bmRlclxuICogIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTIE9SIFJFUFJFU0VOVEFUSU9OU1xuICogIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZVxuICogIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQgbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IE5nTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBRU1Db21wb25lbnREaXJlY3RpdmUgfSBmcm9tIFwiLi9sYXlvdXQvYWVtLWNvbXBvbmVudC5kaXJlY3RpdmVcIjtcbmltcG9ydCB7IEFFTUNvbnRhaW5lckNvbXBvbmVudCB9IGZyb20gXCIuL2xheW91dC9hZW0tY29udGFpbmVyL2FlbS1jb250YWluZXIuY29tcG9uZW50XCI7XG5pbXBvcnQgeyBBRU1SZXNwb25zaXZlR3JpZENvbXBvbmVudCB9IGZyb20gXCIuL2xheW91dC9hZW0tcmVzcG9uc2l2ZWdyaWQvYWVtLXJlc3BvbnNpdmVncmlkLmNvbXBvbmVudFwiO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcblxuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZV0sXG5cbiAgZGVjbGFyYXRpb25zOiBbQUVNQ29udGFpbmVyQ29tcG9uZW50LCBBRU1SZXNwb25zaXZlR3JpZENvbXBvbmVudCwgQUVNQ29tcG9uZW50RGlyZWN0aXZlXSxcbiAgZXhwb3J0czogW0FFTUNvbnRhaW5lckNvbXBvbmVudCwgQUVNUmVzcG9uc2l2ZUdyaWRDb21wb25lbnQsIEFFTUNvbXBvbmVudERpcmVjdGl2ZV1cbn0pXG5leHBvcnQgY2xhc3MgU3BhQW5ndWxhckVkaXRhYmxlQ29tcG9uZW50c01vZHVsZSB7IH1cbiJdLCJuYW1lcyI6WyJTUEFDb21wb25lbnRNYXBwaW5nIiwiQ29uc3RhbnRzIiwiUE1Db25zdGFudHMiLCJDb21wb25lbnRNYXBwaW5nIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7O0lBc0JFLFlBQW9CLFVBQThCO1FBQTlCLGVBQVUsR0FBVixVQUFVLENBQW9COzZCQUZQLElBQUksT0FBTyxFQUFFO0tBRUY7Ozs7Ozs7SUFFdEQsR0FBRyxDQUFDLGFBQWEsRUFBRSxLQUFLLEVBQUUsVUFBVSxHQUFHLElBQUk7UUFDdkMscUJBQUksVUFBVSxHQUFHLEtBQUssQ0FBQztRQUV2QixJQUFJLFVBQVUsRUFBRTtZQUNaLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxVQUFVLENBQUMsQ0FBQztTQUM3QztRQUNELElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxVQUFVLENBQUMsQ0FBQztLQUNsRDs7Ozs7O0lBRUQsR0FBRyxDQUFDLFlBQVk7UUFDZCxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFDO0tBQzFDOzs7OztJQUVELGFBQWEsQ0FBQyxTQUFTO1FBQ3JCLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFD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