@adobe/cq-angular-editable-components
Version:
* [API](#api) * [Documentation](#documentation) * [Changelog](#changelog)
499 lines (488 loc) • 50.2 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 { 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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