UNPKG

@stratio/egeo

Version:
521 lines 47.4 kB
/** * @fileoverview added by tsickle * Generated from: lib/st-form/st-form.component.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /* * © 2017 Stratio Big Data Inc., Sucursal en España. * * This software is licensed under the Apache License, Version 2.0. * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the terms of the License for more details. * * SPDX-License-Identifier: Apache-2.0. */ import { ChangeDetectionStrategy, Component, EventEmitter, forwardRef, Input, Output, ViewChild } from '@angular/core'; import { NG_VALIDATORS, NG_VALUE_ACCESSOR, NgForm } from '@angular/forms'; import { FORM_UI_COMPONENT } from './st-form-field/st-form-field.interface'; /** * \@description {Component} [Dynamic form] * * The form component allows to generate forms dynamically using a JSON schema. * * \@model * * [Form Schema] {./st-form.model.ts#StFormSchema} * [Form UI Definition] {./st-form.model.ts#StFormUIDefinition} * * \@example * * {html} * * ``` * <st-form [schema]="jsonSchema" [(ngModel)]="model" #formModel="ngModel"> * </st-form> * * ``` * */ export class StFormComponent { constructor() { /** * \@Input {string} [nestingLevel=0] This informs about the nesting level of the form. This input is only used for design purposes */ this.nestingLevel = 0; /** * \@Input {string} [disabledSectionMessage='for this instance is disabled.'] * Message displayed when a section is disabled. This is always displayed after the section name */ this.disabledSectionMessage = 'for this instance is disabled.'; /** * \@Input {number} [sectionDescriptionLevel=-1] Level of the section to which description is displayed. * By default, section descriptions are not displayed. */ this.sectionDescriptionLevel = -1; /** * \@Input {boolean} [showTooltips=-1] Enable or disable displaying of tooltips * By default, tooltips are displayed */ this.showTooltips = true; /** * \@Output {any} [valueChange=] Event emitted when value is changed. This emits the current form value */ this.valueChange = new EventEmitter(); /** * \@Output {string} [clickLink=] Event emitted when link is clicked. It returns the field path */ this.clickLink = new EventEmitter(); this.showCollapsedSectionFields = false; this.innerValue = {}; this._value = {}; this._parentFieldSubscription = []; this.onTouched = (/** * @return {?} */ () => { }); } /** * \@Input {StFormSchema [schema=] Form schema needed to generate the form * @return {?} */ get schema() { return this._schema; } /** * @param {?} schema * @return {?} */ set schema(schema) { this._schema = schema; this._value = {}; if (this._schema.dependencies) { this._parentFields = Object.keys(this._schema.dependencies); } } /** * @return {?} */ ngAfterViewInit() { if (!this.forceValidations) { this.form.form.markAsPristine(); } } /** * @return {?} */ ngAfterViewChecked() { if (this._parentFields && this.form.control && this.form.control.controls) { for (let i = 0; i < this._parentFields.length; ++i) { /** @type {?} */ let parentField = this._parentFields[i]; if (!this._parentFieldSubscription[i] && this.form.control.controls[parentField]) { this._parentFieldSubscription[i] = this.form.control.controls[this._parentFields[i]].valueChanges.subscribe((/** * @param {?} value * @return {?} */ (value) => { if (!value) { /** @type {?} */ let childrenFields = this.schema.dependencies[parentField]; for (let j = 0; j < childrenFields.length; ++j) { if (this.form.controls[childrenFields[j]]) { this._value[childrenFields[j]] = undefined; } } } })); } } } } // Function to call when the value changes. /** * @param {?} _ * @return {?} */ onChange(_) { } /** * @param {?} control * @return {?} */ validate(control) { /** @type {?} */ let errors = null; if (this.form) { Object.keys(this.form.controls).forEach((/** * @param {?} propertyName * @return {?} */ (propertyName) => { if (this.form.controls[propertyName] && this.form.controls[propertyName].errors) { if (!errors) { errors = {}; } errors[propertyName] = this.form.controls[propertyName].errors; } })); this.form.control.setErrors(errors); } return errors; } /** * @param {?} propertyName * @return {?} */ isRequired(propertyName) { return propertyName && this.schema.required && this.schema.required.indexOf(propertyName) !== -1; } /** * @return {?} */ isCollapsedSection() { return this.schema.type === 'object' && this.schema.ui && (this.schema.ui.component === FORM_UI_COMPONENT.SHOW_MORE || this.schema.ui.component === FORM_UI_COMPONENT.ACCORDION); } /** * @return {?} */ iShowMoreSection() { return this.schema.type === 'object' && this.schema.ui && this.schema.ui.component === FORM_UI_COMPONENT.SHOW_MORE; } /** * @param {?} propertyName * @return {?} */ isAParentField(propertyName) { return this.schema.dependencies && this.schema.dependencies[propertyName] && this.schema.dependencies[propertyName].length > 0; } /** * @return {?} */ getOptionalButtonLabel() { /** @type {?} */ let label = 'Additional options'; if (this.parentName || this.schema.title) { label += ' of '; label += this.parentName || this.schema.title; } return label; } /** * @return {?} */ onChangeOptionalFieldsVisibility() { this.showCollapsedSectionFields = !this.showCollapsedSectionFields; } /** * @param {?} propertyName * @return {?} */ getFieldClasses(propertyName) { return { 'hidden': this.isCollapsedSection() && !this.showCollapsedSectionFields, 'parent-field': this.isAParentField(propertyName) || (this.isASwitchSection() && this.isTheFirstField(propertyName)) }; } /** * @param {?} propertyName * @return {?} */ fieldHasToBeCreated(propertyName) { /** @type {?} */ let createField = true; /** @type {?} */ let parentField = this.getParentField(propertyName); if (((parentField && !this._value[parentField]) || (this.isInADisabledSection() && !this.isTheFirstField(propertyName))) || !this.fulfillDependencyVisibility(propertyName)) { createField = false; this._value[propertyName] = undefined; } return createField; } /** * @param {?} propertyName * @return {?} */ isRelatedField(propertyName) { return this._schema.properties[propertyName].ui && this.schema.properties[propertyName].ui.relatedTo && this.schema.properties[propertyName].ui.relatedTo.length > 0; } // When value is received from outside /** * @param {?} value * @return {?} */ writeValue(value) { if (value) { this.onChange(value); this.innerValue = value; } } /** * @param {?} value * @param {?} property * @return {?} */ onChangeProperty(value, property) { this._value[property] = value; this.valueChange.emit(this._value); setTimeout((/** * @return {?} */ () => { this.onChange(this._value); })); } // Registry the change function to propagate internal model changes /** * @param {?} fn * @return {?} */ registerOnChange(fn) { this.onChange = fn; } // Registry the touch function to propagate internal touch events TODO: make this function. /** * @param {?} fn * @return {?} */ registerOnTouched(fn) { this.onTouched = fn; } // Allows Angular to disable the form. /** * @param {?} disable * @return {?} */ setDisabledState(disable) { if (disable) { this.form.control.disable(); } else { this.form.control.enable(); } } /** * @return {?} */ ngOnDestroy() { if (this._parentFieldSubscription) { for (let i = 0; i < this._parentFieldSubscription.length; ++i) { this._parentFieldSubscription[i].unsubscribe(); } } } /** * @return {?} */ isInADisabledSection() { if (this.isASwitchSection()) { /** @type {?} */ let sectionEnabler = Object.keys(this.schema.properties)[0]; return !(this.form && this.form.controls[sectionEnabler] && this.form.controls[sectionEnabler].value); } return false; } /** * @return {?} */ isASwitchSection() { return this.schema.ui && this.schema.ui.component === FORM_UI_COMPONENT.SWITCH; } /** * @return {?} */ isAnAccordion() { return this.schema.ui && this.schema.ui.component === FORM_UI_COMPONENT.ACCORDION; } /** * @return {?} */ onClickTitle() { if (this.isAnAccordion()) { this.onChangeOptionalFieldsVisibility(); } } /** * @param {?} propertyName * @return {?} */ isTheFirstField(propertyName) { return propertyName === Object.keys(this.schema.properties)[0]; } /** * @param {?} fieldKey * @return {?} */ onClickLink(fieldKey) { this.clickLink.emit(fieldKey); } /** * @private * @param {?} propertyName * @return {?} */ getParentField(propertyName) { /** @type {?} */ let parentField = undefined; if (this.schema.dependencies) { Object.keys(this.schema.dependencies).forEach((/** * @param {?} key * @return {?} */ (key) => { if (this.schema.dependencies[key].indexOf(propertyName) !== -1) { parentField = key; } })); } return parentField; } /** * @private * @param {?} propertyName * @return {?} */ fulfillDependencyVisibility(propertyName) { /** @type {?} */ let propertySchema = this.schema.properties[propertyName]; /** @type {?} */ let fulfill = !propertySchema.ui || propertySchema.ui.visible !== false; if (propertySchema.ui && propertySchema.ui.visible) { /** @type {?} */ const keys = Object.keys(propertySchema.ui.visible); /** @type {?} */ let i = 0; while (fulfill && i < keys.length && propertySchema.ui.visible.hasOwnProperty(keys[i])) { if (this._value[keys[i]] !== propertySchema.ui.visible[keys[i]]) { fulfill = false; } ++i; } } return fulfill; } } StFormComponent.decorators = [ { type: Component, args: [{ selector: 'st-form', template: "<!--\n\n \u00A9 2017 Stratio Big Data Inc., Sucursal en Espa\u00F1a.\n\n This software is licensed under the Apache License, Version 2.0.\n This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;\n without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n See the terms of the License for more details.\n\n SPDX-License-Identifier: Apache-2.0.\n\n-->\n\n<form #form=\"ngForm\" *ngIf=\"innerValue\"\n [ngClass]=\"{'category': nestingLevel === 0,\n 'section': nestingLevel === 1,\n 'subsection': nestingLevel > 1,\n 'accordion': isAnAccordion(),\n 'accordion--open': isAnAccordion() && showCollapsedSectionFields}\"\n novalidate>\n <h1 *ngIf=\"schema.title && !isASwitchSection()\" class=\"title\" (click)=\"onClickTitle()\">{{schema.title}}</h1>\n <p *ngIf=\"schema.description && nestingLevel <= sectionDescriptionLevel\" class=\"description\">\n {{schema.description}}</p>\n <span class=\"optional-fields-button\" *ngIf=\"iShowMoreSection()\">\n <button class=\"button button-link\"\n (click)=\"onChangeOptionalFieldsVisibility()\">\n <span> <i\n [ngClass]=\"{'icon-arrow2_down': showCollapsedSectionFields, 'icon-arrow2_right': !showCollapsedSectionFields}\"></i> {{getOptionalButtonLabel()}}</span>\n </button>\n </span>\n <ng-container *ngFor=\"let property of schema.properties | stObjectToArray; let index = index;\">\n <div class=\"form-field-container\">\n <st-form-field *ngIf=\"property.value.type !== 'object' && fieldHasToBeCreated(property.key)\" class=\"form-field\"\n [schema]=\"property\"\n [name]=\"property.key\"\n [maxWidth]=\"textFieldMaxWidth\"\n [ngModel]=\"innerValue[property.key]\"\n [forceValidations]=\"forceValidations\"\n (ngModelChange)=\"onChangeProperty($event, property.key)\"\n [required]=\"isRequired(property.key)\"\n [hasDependencies]=\"isAParentField(property.key) || (isASwitchSection() && isTheFirstField(property.key))\"\n [ngClass]=\"getFieldClasses(property.key)\"\n [showTooltip]=\"showTooltips\"\n [qaTag]=\"property.key\"\n [errorMessages]=\"errorMessages\"\n [translations]=\"translations\"\n [attr.id]=\"property.key + '-form-field'\"\n (clickLink)=\"onClickLink($event)\">\n </st-form-field>\n\n <div *ngIf=\"property.value.type === 'object' && fieldHasToBeCreated(property.key)\">\n <st-form\n [hidden]=\"isCollapsedSection() && !showCollapsedSectionFields\"\n [schema]=\"property.value\"\n [parentName]=\"schema.title\"\n [name]=\"property.key\"\n [textFieldMaxWidth]=\"textFieldMaxWidth\"\n [ngModel]=\"innerValue[property.key]\"\n [attr.id]=\"property.key + '-section'\"\n [nestingLevel]=\"nestingLevel + 1\"\n [showTooltips]=\"showTooltips\"\n [sectionDescriptionLevel]=\"sectionDescriptionLevel\"\n [errorMessages]=\"errorMessages\"\n [translations]=\"translations\"\n (clickLink)=\"onClickLink(property.key + '.' + $event)\"\n (ngModelChange)=\"onChangeProperty($event, property.key)\">\n </st-form>\n </div>\n </div>\n <span class=\"line-break\" *ngIf=\"!isRelatedField(property.key)\"></span>\n </ng-container>\n\n <p *ngIf=\"isInADisabledSection()\" class=\"disabled-section-info\"> {{schema.title}} {{disabledSectionMessage}}</p>\n</form>\n", host: { class: 'st-form' }, changeDetection: ChangeDetectionStrategy.OnPush, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef((/** * @return {?} */ () => StFormComponent)), multi: true }, { provide: NG_VALIDATORS, useExisting: forwardRef((/** * @return {?} */ () => StFormComponent)), multi: true } ], styles: ["@charset \"UTF-8\";.form-field{display:block}.form-field.hidden{visibility:hidden;position:absolute}.section-title{padding:10px 0 20px}"] }] } ]; StFormComponent.propDecorators = { parentName: [{ type: Input }], nestingLevel: [{ type: Input }], forceValidations: [{ type: Input }], disabledSectionMessage: [{ type: Input }], sectionDescriptionLevel: [{ type: Input }], textFieldMaxWidth: [{ type: Input }], errorMessages: [{ type: Input }], showTooltips: [{ type: Input }], translations: [{ type: Input }], valueChange: [{ type: Output }], clickLink: [{ type: Output }], form: [{ type: ViewChild, args: ['form', { static: false },] }], schema: [{ type: Input }] }; if (false) { /** * \@Input {string} [parentName=] Name of the parent section. By default, it is undefined * @type {?} */ StFormComponent.prototype.parentName; /** * \@Input {string} [nestingLevel=0] This informs about the nesting level of the form. This input is only used for design purposes * @type {?} */ StFormComponent.prototype.nestingLevel; /** * \@Input {boolean} [forceValidations=] Boolean to force the field validations * @type {?} */ StFormComponent.prototype.forceValidations; /** * \@Input {string} [disabledSectionMessage='for this instance is disabled.'] * Message displayed when a section is disabled. This is always displayed after the section name * @type {?} */ StFormComponent.prototype.disabledSectionMessage; /** * \@Input {number} [sectionDescriptionLevel=-1] Level of the section to which description is displayed. * By default, section descriptions are not displayed. * @type {?} */ StFormComponent.prototype.sectionDescriptionLevel; /** * \@Input {number} [textFieldMaxWidth=] Maximum width of a field needed to paint a input or textarea * @type {?} */ StFormComponent.prototype.textFieldMaxWidth; /** * \@Input {StInputError} [errorMessages=] Field error translations * @type {?} */ StFormComponent.prototype.errorMessages; /** * \@Input {boolean} [showTooltips=-1] Enable or disable displaying of tooltips * By default, tooltips are displayed * @type {?} */ StFormComponent.prototype.showTooltips; /** * \@Input {StFormFieldTranslations} [translations=] Field translations * @type {?} */ StFormComponent.prototype.translations; /** * \@Output {any} [valueChange=] Event emitted when value is changed. This emits the current form value * @type {?} */ StFormComponent.prototype.valueChange; /** * \@Output {string} [clickLink=] Event emitted when link is clicked. It returns the field path * @type {?} */ StFormComponent.prototype.clickLink; /** @type {?} */ StFormComponent.prototype.form; /** @type {?} */ StFormComponent.prototype.showCollapsedSectionFields; /** @type {?} */ StFormComponent.prototype.innerValue; /** * @type {?} * @private */ StFormComponent.prototype._value; /** * @type {?} * @private */ StFormComponent.prototype._parentFieldSubscription; /** * @type {?} * @private */ StFormComponent.prototype._parentFields; /** * @type {?} * @private */ StFormComponent.prototype._schema; /** @type {?} */ StFormComponent.prototype.onTouched; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3QtZm9ybS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9Ac3RyYXRpby9lZ2VvLyIsInNvdXJjZXMiOlsibGliL3N0LWZvcm0vc3QtZm9ybS5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7O0FBVUEsT0FBTyxFQUdKLHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsWUFBWSxFQUNaLFVBQVUsRUFDVixLQUFLLEVBRUwsTUFBTSxFQUNOLFNBQVMsRUFDWCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQXFDLGFBQWEsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQU03RyxPQUFPLEVBQUUsaUJBQWlCLEVBQTJCLE1BQU0seUNBQXlDLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFtQ3JHLE1BQU0sT0FBTyxlQUFlO0lBWjVCOzs7O1FBZ0JZLGlCQUFZLEdBQVcsQ0FBQyxDQUFDOzs7OztRQU16QiwyQkFBc0IsR0FBVyxnQ0FBZ0MsQ0FBQzs7Ozs7UUFLbEUsNEJBQXVCLEdBQVcsQ0FBQyxDQUFDLENBQUM7Ozs7O1FBV3JDLGlCQUFZLEdBQVksSUFBSSxDQUFDOzs7O1FBTTVCLGdCQUFXLEdBQXNCLElBQUksWUFBWSxFQUFPLENBQUM7Ozs7UUFFekQsY0FBUyxHQUF5QixJQUFJLFlBQVksRUFBVSxDQUFDO1FBSWhFLCtCQUEwQixHQUFZLEtBQUssQ0FBQztRQUM1QyxlQUFVLEdBQVEsRUFBRSxDQUFDO1FBQ3BCLFdBQU0sR0FBUSxFQUFFLENBQUM7UUFDakIsNkJBQXdCLEdBQW1CLEVBQUUsQ0FBQztRQWdEdEQsY0FBUzs7O1FBQUcsR0FBRyxFQUFFO1FBQ2pCLENBQUMsRUFBQTtJQThLSixDQUFDOzs7OztJQTFORSxJQUFhLE1BQU07UUFDaEIsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDO0lBQ3ZCLENBQUM7Ozs7O0lBRUQsSUFBSSxNQUFNLENBQUMsTUFBb0I7UUFD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Qjs7Ozs7SUFFNUIsdUNBQWtDOzs7OztJQUVsQywyQ0FBbUM7Ozs7OztJQUluQyxpREFBMkU7Ozs7OztJQUszRSxrREFBOEM7Ozs7O0lBRzlDLDRDQUFtQzs7Ozs7SUFHbkMsd0NBQXFDOzs7Ozs7SUFLckMsdUNBQXNDOzs7OztJQUd0Qyx1Q0FBZ0Q7Ozs7O0lBR2hELHNDQUFtRTs7Ozs7SUFFbkUsb0NBQXVFOztJQUV2RSwrQkFBbUQ7O0lBRW5ELHFEQUFtRDs7SUFDbkQscUNBQTRCOzs7OztJQUM1QixpQ0FBeUI7Ozs7O0lBQ3pCLG1EQUFzRDs7Ozs7SUFDdEQsd0NBQWdDOzs7OztJQUNoQyxrQ0FBOEI7O0lBOEM5QixvQ0FDQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiDCqSAyMDE3IFN0cmF0aW8gQmlnIERhdGEgSW5jLiwgU3VjdXJzYWwgZW4gRXNwYcOxYS5cbiAqXG4gKiBUaGlzIHNvZnR3YXJlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAuXG4gKiBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZO1xuICogd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS5cbiAqIFNlZSB0aGUgdGVybXMgb2YgdGhlIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMC5cbiAqL1xuaW1wb3J0IHtcbiAgIEFmdGVyVmlld0NoZWNrZWQsXG4gICBBZnRlclZpZXdJbml0LFxuICAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gICBDb21wb25lbnQsXG4gICBFdmVudEVtaXR0ZXIsXG4gICBmb3J3YXJkUmVmLFxuICAgSW5wdXQsXG4gICBPbkRlc3Ryb3ksXG4gICBPdXRwdXQsXG4gICBWaWV3Q2hpbGRcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb250cm9sVmFsdWVBY2Nlc3NvciwgRm9ybUNvbnRyb2wsIE5HX1ZBTElEQVRPUlMsIE5HX1ZBTFVFX0FDQ0VTU09SLCBOZ0Zvcm0gfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcblxuaW1wb3J0IHsgSlNPTlNjaGVtYTQgfSBmcm9tICdqc29uLXNjaGVtYSc7XG5pbXBvcnQgeyBTdElucHV0RXJyb3IgfSBmcm9tICcuLi9zdC1pbnB1dC9zdC1pbnB1dC5lcnJvci5tb2RlbCc7XG5pbXBvcnQgeyBTdEZvcm1TY2hlbWEgfSBmcm9tICcuL3N0LWZvcm0ubW9kZWwnO1xuaW1wb3J0IHsgRk9STV9VSV9DT01QT05FTlQsIFN0Rm9ybUZpZWxkVHJhbnNsYXRpb25zIH0gZnJvbSAnLi9zdC1mb3JtLWZpZWxkL3N0LWZvcm0tZmllbGQuaW50ZXJmYWNlJztcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24ge0NvbXBvbmVudH0gW0R5bmFtaWMgZm9ybV1cbiAqXG4gKiBUaGUgZm9ybSBjb21wb25lbnQgYWxsb3dzIHRvIGdlbmVyYXRlIGZvcm1zIGR5bmFtaWNhbGx5IHVzaW5nIGEgSlNPTiBzY2hlbWEuXG4gKlxuICogQG1vZGVsXG4gKlxuICogICBbRm9ybSBTY2hlbWFdIHsuL3N0LWZvcm0ubW9kZWwudHMjU3RGb3JtU2NoZW1hfVxuICogICBbRm9ybSBVSSBEZWZpbml0aW9uXSB7Li9zdC1mb3JtLm1vZGVsLnRzI1N0Rm9ybVVJRGVmaW5pdGlvbn1cbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqIHtodG1sfVxuICpcbiAqIGBgYFxuICogPHN0LWZvcm0gW3NjaGVtYV09XCJqc29uU2NoZW1hXCIgWyhuZ01vZGVsKV09XCJtb2RlbFwiICNmb3JtTW9kZWw9XCJuZ01vZGVsXCI+XG4gKiA8L3N0LWZvcm0+XG4gKlxuICogYGBgXG4gKlxuICovXG5AQ29tcG9uZW50KHtcbiAgIHNlbGVjdG9yOiAnc3QtZm9ybScsXG4gICB0ZW1wbGF0ZVVybDogJy4vc3QtZm9ybS5jb21wb25lbnQuaHRtbCcsXG4gICBzdHlsZVVybHM6IFsnLi9zdC1mb3JtLmNvbXBvbmVudC5zY3NzJ10sXG4gICBob3N0OiB7IGNsYXNzOiAnc3QtZm9ybScgfSxcbiAgIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICAgcHJvdmlkZXJzOiBbXG4gICAgICB7IHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLCB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBTdEZvcm1Db21wb25lbnQpLCBtdWx0aTogdHJ1ZSB9LFxuICAgICAgeyBwcm92aWRlOiBOR19WQUxJREFUT1JTLCB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBTdEZvcm1Db21wb25lbnQpLCBtdWx0aTogdHJ1ZSB9XG4gICBdXG59KVxuXG5leHBvcnQgY2xhc3MgU3RGb3JtQ29tcG9uZW50IGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgQWZ0ZXJWaWV3Q2hlY2tlZCwgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE9uRGVzdHJveSB7XG4gICAvKiogQElucHV0IHtzdHJpbmd9IFtwYXJlbnROYW1lPV0gTmFtZSBvZiB0aGUgcGFyZW50IHNlY3Rpb24uIEJ5IGRlZmF1bHQsIGl0IGlzIHVuZGVmaW5lZCAqL1xuICAgQElucHV0KCkgcGFyZW50TmFtZTogc3RyaW5nO1xuICAgLyoqIEBJbnB1dCB7c3RyaW5nfSBbbmVzdGluZ0xldmVsPTBdIFRoaXMgaW5mb3JtcyBhYm91dCB0aGUgbmVzdGluZyBsZXZlbCBvZiB0aGUgZm9ybS4gVGhpcyBpbnB1dCBpcyBvbmx5IHVzZWQgZm9yIGRlc2lnbiBwdXJwb3NlcyAqL1xuICAgQElucHV0KCkgbmVzdGluZ0xldmVsOiBudW1iZXIgPSAwO1xuICAgLyoqIEBJbnB1dCB7Ym9vbGVhbn0gW2ZvcmNlVmFsaWRhdGlvbnM9XSBCb29sZWFuIHRvIGZvcmNlIHRoZSBmaWVsZCB2YWxpZGF0aW9ucyAqL1xuICAgQElucHV0KCkgZm9yY2VWYWxpZGF0aW9uczogYm9vbGVhbjtcbiAgIC8qKiBASW5wdXQge3N0cmluZ30gW2Rpc2FibGVkU2VjdGlvbk1lc3NhZ2U9J2ZvciB0aGlzIGluc3RhbmNlIGlzIGRpc2FibGVkLiddXG4gICAgKiAgTWVzc2FnZSBkaXNwbGF5ZWQgd2hlbiBhIHNlY3Rpb24gaXMgZGlzYWJsZWQuIFRoaXMgaXMgYWx3YXlzIGRpc3BsYXllZCBhZnRlciB0aGUgc2VjdGlvbiBuYW1lXG4gICAgKi9cbiAgIEBJbnB1dCgpIGRpc2FibGVkU2VjdGlvbk1lc3NhZ2U6IHN0cmluZyA9ICdmb3IgdGhpcyBpbnN0YW5jZSBpcyBkaXNhYmxlZC4nO1xuXG4gICAvKiogQElucHV0IHtudW1iZXJ9IFtzZWN0aW9uRGVzY3JpcHRpb25MZXZlbD0tMV0gTGV2ZWwgb2YgdGhlIHNlY3Rpb24gdG8gd2hpY2ggZGVzY3JpcHRpb24gaXMgZGlzcGxheWVkLlxuICAgICogQnkgZGVmYXVsdCwgc2VjdGlvbiBkZXNjcmlwdGlvbnMgYXJlIG5vdCBkaXNwbGF5ZWQuXG4gICAgKi9cbiAgIEBJbnB1dCgpIHNlY3Rpb25EZXNjcmlwdGlvbkxldmVsOiBudW1iZXIgPSAtMTtcblxuICAgLyoqIEBJbnB1dCB7bnVtYmVyfSBbdGV4dEZpZWxkTWF4V2lkdGg9XSBNYXhpbXVtIHdpZHRoIG9mIGEgZmllbGQgbmVlZGVkIHRvIHBhaW50IGEgaW5wdXQgb3IgdGV4dGFyZWEgKi9cbiAgIEBJbnB1dCgpIHRleHRGaWVsZE1heFdpZHRoOiBudW1iZXI7XG5cbiAgIC8qKiBASW5wdXQge1N0SW5wdXRFcnJvcn0gW2Vycm9yTWVzc2FnZXM9XSBGaWVsZCBlcnJvciB0cmFuc2xhdGlvbnMgKi9cbiAgIEBJbnB1dCgpIGVycm9yTWVzc2FnZXM6IFN0SW5wdXRFcnJvcjtcblxuICAgLyoqIEBJbnB1dCB7Ym9vbGVhbn0gW3Nob3dUb29sdGlwcz0tMV0gRW5hYmxlIG9yIGRpc2FibGUgZGlzcGxheWluZyBvZiB0b29sdGlwc1xuICAgICogQnkgZGVmYXVsdCwgdG9vbHRpcHMgYXJlIGRpc3BsYXllZFxuICAgICovXG4gICBASW5wdXQoKSBzaG93VG9vbHRpcHM6IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAvKiogQElucHV0IHtTdEZvcm1GaWVsZFRyYW5zbGF0aW9uc30gW3RyYW5zbGF0aW9ucz1dIEZpZWxkIHRyYW5zbGF0aW9ucyAqL1xuICAgQElucHV0KCkgdHJhbnNsYXRpb25zPzogU3RGb3JtRmllbGRUcmFuc2xhdGlvbnM7XG5cbiAgIC8qKiBAT3V0cHV0IHthbnl9IFt2YWx1ZUNoYW5nZT1dIEV2ZW50IGVtaXR0ZWQgd2hlbiB2YWx1ZSBpcyBjaGFuZ2VkLiBUaGlzIGVtaXRzIHRoZSBjdXJyZW50IGZvcm0gdmFsdWUgKi9cbiAgIEBPdXRwdXQoKSB2YWx1ZUNoYW5nZTogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcbiAgIC8qKiBAT3V0cHV0IHtzdHJpbmd9IFtjbGlja0xpbms9XSBFdmVudCBlbWl0dGVkIHdoZW4gbGluayBpcyBjbGlja2VkLiBJdCByZXR1cm5zIHRoZSBmaWVsZCBwYXRoICovXG4gICBAT3V0cHV0KCkgY2xpY2tMaW5rOiBFdmVudEVtaXR0ZXI8c3RyaW5nPiA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuXG4gICBAVmlld0NoaWxkKCdmb3JtJywgeyBzdGF0aWM6IGZhbHNlIH0pIGZvcm06IE5nRm9ybTtcblxuICAgcHVibGljIHNob3dDb2xsYXBzZWRTZWN0aW9uRmllbGRzOiBib29sZWFuID0gZmFsc2U7XG4gICBwdWJsaWMgaW5uZXJWYWx1ZTogYW55ID0ge307XG4gICBwcml2YXRlIF92YWx1ZTogYW55ID0ge307XG4gICBwcml2YXRlIF9wYXJlbnRGaWVsZFN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uW10gPSBbXTtcbiAgIHByaXZhdGUgX3BhcmVudEZpZWxkczogc3RyaW5nW107XG4gICBwcml2YXRlIF9zY2hlbWE6IFN0Rm9ybVNjaGVtYTtcblxuICAgLyoqIEBJbnB1dCB7U3RGb3JtU2NoZW1hIFtzY2hlbWE9XSBGb3JtIHNjaGVtYSBuZWVkZWQgdG8gZ2VuZXJhdGUgdGhlIGZvcm0gKi9cbiAgIEBJbnB1dCgpIGdldCBzY2hlbWEoKTogU3RGb3JtU2NoZW1hIHtcbiAgICAgIHJldHVybiB0aGlzLl9zY2hlbWE7XG4gICB9XG5cbiAgIHNldCBzY2hlbWEoc2NoZW1hOiBTdEZvcm1TY2hlbWEpIHtcbiAgICAgIHRoaXMuX3NjaGVtYSA9IHNjaGVtYTtcbiAgICAgIHRoaXMuX3ZhbHVlID0ge307XG4gICAgICBpZiAodGhpcy5fc2NoZW1hLmRlcGVuZGVuY2llcykge1xuICAgICAgICAgdGhpcy5fcGFyZW50RmllbGRzID0gT2JqZWN0LmtleXModGhpcy5fc2NoZW1hLmRlcGVuZGVuY2llcyk7XG4gICAgICB9XG4gICB9XG5cbiAgIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICAgIGlmICghdGhpcy5mb3JjZVZhbGlkYXRpb25zKSB7XG4gICAgICAgICB0aGlzLmZvcm0uZm9ybS5tYXJrQXNQcmlzdGluZSgpO1xuICAgICAgfVxuICAgfVxuXG4gICBuZ0FmdGVyVmlld0NoZWNrZWQoKTogdm9pZCB7XG4gICAgICBpZiAodGhpcy5fcGFyZW50RmllbGRzICYmIHRoaXMuZm9ybS5jb250cm9sICYmIHRoaXMuZm9ybS5jb250cm9sLmNvbnRyb2xzKSB7XG4gICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuX3BhcmVudEZpZWxkcy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgbGV0IHBhcmVudEZpZWxkOiBzdHJpbmcgPSB0aGlzLl9wYXJlbnRGaWVsZHNbaV07XG4gICAgICAgICAgICBpZiAoIXRoaXMuX3BhcmVudEZpZWxkU3Vic2NyaXB0aW9uW2ldICYmIHRoaXMuZm9ybS5jb250cm9sLmNvbnRyb2xzW3BhcmVudEZpZWxkXSkge1xuXG4gICAgICAgICAgICAgICB0aGlzLl9wYXJlbnRGaWVsZFN1YnNjcmlwdGlvbltpXSA9IHRoaXMuZm9ybS5jb250cm9sLmNvbnRyb2xzW3RoaXMuX3BhcmVudEZpZWxkc1tpXV0udmFsdWVDaGFuZ2VzLnN1YnNjcmliZSgodmFsdWUpID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmICghdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgIGxldCBjaGlsZHJlbkZpZWxkczogSlNPTlNjaGVtYTQgfCBzdHJpbmdbXSA9IHRoaXMuc2NoZW1hLmRlcGVuZGVuY2llc1twYXJlbnRGaWVsZF07XG4gICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGNoaWxkcmVuRmllbGRzLmxlbmd0aDsgKytqKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5mb3JtLmNvbnRyb2xzW2NoaWxkcmVuRmllbGRzW2pdXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdmFsdWVbY2hpbGRyZW5GaWVsZHNbal1dID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICB9XG4gICAgICB9XG4gICB9XG5cbiAgIC8vIEZ1bmN0aW9uIHRvIGNhbGwgd2hlbiB0aGUgdmFsdWUgY2hhbmdlcy5cbiAgIG9uQ2hhbmdlKF86IGFueSk6IHZvaWQge1xuICAgfVxuXG4gICBvblRvdWNoZWQgPSAoKSA9PiB7XG4gICB9XG5cbiAgIHZhbGlkYXRlKGNvbnRyb2w6IEZvcm1Db250cm9sKTogYW55IHtcbiAgICAgIGxldCBlcnJvcnM6IGFueSA9IG51bGw7XG4gICAgICBpZiAodGhpcy5mb3JtKSB7XG4gICAgICAgICBPYmplY3Qua2V5cyh0aGlzLmZvcm0uY29udHJvbHMpLmZvckVhY2goKHByb3BlcnR5TmFtZSkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuZm9ybS5jb250cm9sc1twcm9wZXJ0eU5hbWVdICYmIHRoaXMuZm9ybS5jb250cm9sc1twcm9wZXJ0eU5hbWVdLmVycm9ycykge1xuICAgICAgICAgICAgICAgaWYgKCFlcnJvcnMpIHtcbiAgICAgICAgICAgICAgICAgIGVycm9ycyA9IHt9O1xuICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgZXJyb3JzW3Byb3BlcnR5TmFtZV0gPSB0aGlzLmZvcm0uY29udHJvbHNbcHJvcGVydHlOYW1lXS5lcnJvcnM7XG4gICAgICAgICAgICB9XG4gICAgICAgICB9KTtcblxuICAgICAgICAgdGhpcy5mb3JtLmNvbnRyb2wuc2V0RXJyb3JzKGVycm9ycyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZXJyb3JzO1xuICAgfVxuXG4gICBpc1JlcXVpcmVkKHByb3BlcnR5TmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICByZXR1cm4gcHJvcGVydHlOYW1lICYmIHRoaXMuc2NoZW1hLnJlcXVpcmVkICYmIHRoaXMuc2NoZW1hLnJlcXVpcmVkLmluZGV4T2YocHJvcGVydHlOYW1lKSAhPT0gLTE7XG4gICB9XG5cbiAgIGlzQ29sbGFwc2VkU2VjdGlvbigpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiB0aGlzLnNjaGVtYS50eXBlID09PSAnb2JqZWN0JyAmJiB0aGlzLnNjaGVtYS51aSAmJlxuICAgICAgICAgKHRoaXMuc2NoZW1hLnVpLmNvbXBvbmVudCA9PT0gRk9STV9VSV9DT01QT05FTlQuU0hPV19NT1JFIHx8IHRoaXMuc2NoZW1hLnVpLmNvbXBvbmVudCA9PT0gRk9STV9VSV9DT01QT05FTlQuQUNDT1JESU9OKTtcbiAgIH1cblxuICAgaVNob3dNb3JlU2VjdGlvbigpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiB0aGlzLnNjaGVtYS50eXBlID09PSAnb2JqZWN0JyAmJiB0aGlzLnNjaGVtYS51aSAmJiB0aGlzLnNjaGVtYS51aS5jb21wb25lbnQgPT09IEZPUk1fVUlfQ09NUE9ORU5ULlNIT1dfTU9SRTtcbiAgIH1cblxuICAgaXNBUGFyZW50RmllbGQocHJvcGVydHlOYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiB0aGlzLnNjaGVtYS5kZXBlbmRlbmNpZXMgJiYgdGhpcy5zY2hlbWEuZGVwZW5kZW5jaWVzW3Byb3BlcnR5TmFtZV0gJiYgdGhpcy5zY2hlbWEuZGVwZW5kZW5jaWVzW3Byb3BlcnR5TmFtZV0ubGVuZ3RoID4gMDtcbiAgIH1cblxuICAgZ2V0T3B0aW9uYWxCdXR0b25MYWJlbCgpOiBzdHJpbmcge1xuICAgICAgbGV0IGxhYmVsOiBzdHJpbmcgPSAnQWRkaXRpb25hbCBvcHRpb25zJztcblxuICAgICAgaWYgKHRoaXMucGFyZW50TmFtZSB8fCB0aGlzLnNjaGVtYS50aXRsZSkge1xuICAgICAgICAgbGFiZWwgKz0gJyBvZiAnO1xuICAgICAgICAgbGFiZWwgKz0gdGhpcy5wYXJlbnROYW1lIHx8IHRoaXMuc2NoZW1hLnRpdGxlO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gbGFiZWw7XG4gICB9XG5cbiAgIG9uQ2hhbmdlT3B0aW9uYWxGaWVsZHNWaXNpYmlsaXR5KCk6IHZvaWQge1xuICAgICAgdGhpcy5zaG93Q29sbGFwc2VkU2VjdGlvbkZpZWxkcyA9ICF0aGlzLnNob3dDb2xsYXBzZWRTZWN0aW9uRmllbGRzO1xuICAgfVxuXG4gICBnZXRGaWVsZENsYXNzZXMocHJvcGVydHlOYW1lOiBzdHJpbmcpOiBhbnkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgICdoaWRkZW4nOiB0aGlzLmlzQ29sbGFwc2VkU2VjdGlvbigpICYmICF0aGlzLnNob3dDb2xsYXBzZWRTZWN0aW9uRmllbGRzLFxuICAgICAgICAgJ3BhcmVudC1maWVsZCc6IHRoaXMuaXNBUGFyZW50RmllbGQocHJvcGVydHlOYW1lKSB8fCAodGhpcy5pc0FTd2l0Y2hTZWN0aW9uKCkgJiYgdGhpcy5pc1RoZUZpcnN0RmllbGQocHJvcGVydHlOYW1lKSlcbiAgICAgIH07XG4gICB9XG5cbiAgIGZpZWxkSGFzVG9CZUNyZWF0ZWQocHJvcGVydHlOYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAgIGxldCBjcmVhdGVGaWVsZDogYm9vbGVhbiA9IHRydWU7XG4gICAgICBsZXQgcGFyZW50RmllbGQ6IHN0cmluZyA9IHRoaXMuZ2V0UGFyZW50RmllbGQocHJvcGVydHlOYW1lKTtcbiAgICAgIGlmICgoKHBhcmVudEZpZWxkICYmICF0aGlzLl92YWx1ZVtwYXJlbnRGaWVsZF0pIHx8ICh0aGlzLmlzSW5BRGlzYWJsZWRTZWN0aW9uKCkgJiYgIXRoaXMuaXNUaGVGaXJzdEZpZWxkKHByb3BlcnR5TmFtZSkpKVxuICAgICAgICAgfHwgIXRoaXMuZnVsZmlsbERlcGVuZGVuY3lWaXNpYmlsaXR5KHByb3BlcnR5TmFtZSkpIHtcbiAgICAgICAgIGNyZWF0ZUZpZWxkID0gZmFsc2U7XG4gICAgICAgICB0aGlzLl92YWx1ZVtwcm9wZXJ0eU5hbWVdID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGNyZWF0ZUZpZWxkO1xuICAgfVxuXG4gICBpc1JlbGF0ZWRGaWVsZChwcm9wZXJ0eU5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuIHRoaXMuX3NjaGVtYS5wcm9wZXJ0aWVzW3Byb3BlcnR5TmFtZV0udWkgJiYgdGhpcy5zY2hlbWEucHJvcGVydGllc1twcm9wZXJ0eU5hbWVdLnVpLnJlbGF0ZWRUb1xuICAgICAgICAgJiYgdGhpcy5zY2hlbWEucHJvcGVydGllc1twcm9wZXJ0eU5hbWVdLnVpLnJlbGF0ZWRUby5sZW5ndGggPiAwO1xuICAgfVxuXG4gICAvLyBXaGVuIHZhbHVlIGlzIHJlY2VpdmVkIGZyb20gb3V0c2lkZVxuICAgd3JpdGVWYWx1ZSh2YWx1ZTogYW55KTogdm9pZCB7XG4gICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgIHRoaXMub25DaGFuZ2UodmFsdWUpO1xuICAgICAgICAgdGhpcy5pbm5lclZhbHVlID0gdmFsdWU7XG4gICAgICB9XG4gICB9XG5cbiAgIG9uQ2hhbmdlUHJvcGVydHkodmFsdWU6IGFueSwgcHJvcGVydHk6IHN0cmluZyk6IHZvaWQge1xuICAgICAgdGhpcy5fdmFsdWVbcHJvcGVydHldID0gdmFsdWU7XG4gICAgICB0aGlzLnZhbHVlQ2hhbmdlLmVtaXQodGhpcy5fdmFsdWUpO1xuICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICB0aGlzLm9uQ2hhbmdlKHRoaXMuX3ZhbHVlKTtcbiAgICAgIH0pO1xuICAgfVxuXG4gICAvLyBSZWdpc3RyeSB0aGUgY2hhbmdlIGZ1bmN0aW9uIHRvIHByb3BhZ2F0ZSBpbnRlcm5hbCBtb2RlbCBjaGFuZ2VzXG4gICByZWdpc3Rlck9uQ2hhbmdlKGZuOiAoXzogYW55KSA9PiB2b2lkKTogdm9pZCB7XG4gICAgICB0aGlzLm9uQ2hhbmdlID0gZm47XG4gICB9XG5cbiAgIC8vIFJlZ2lzdHJ5IHRoZSB0b3VjaCBmdW5jdGlvbiB0byBwcm9wYWdhdGUgaW50ZXJuYWwgdG91Y2ggZXZlbnRzIFRPRE86IG1ha2UgdGhpcyBmdW5jdGlvbi5cbiAgIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiAoKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgICB0aGlzLm9uVG91Y2hlZCA9IGZuO1xuICAgfVxuXG4gICAvLyBBbGxvd3MgQW5ndWxhciB0byBkaXNhYmxlIHRoZSBmb3JtLlxuICAgc2V0RGlzYWJsZWRTdGF0ZShkaXNhYmxlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICBpZiAoZGlzYWJsZSkge1xuICAgICAgICAgdGhpcy5mb3JtLmNvbnRyb2wuZGlzYWJsZSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgIHRoaXMuZm9ybS5jb250cm9sLmVuYWJsZSgpO1xuICAgICAgfVxuICAgfVxuXG4gICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICAgIGlmICh0aGlzLl9wYXJlbnRGaWVsZFN1YnNjcmlwdGlvbikge1xuICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLl9wYXJlbnRGaWVsZFN1YnNjcmlwdGlvbi5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgdGhpcy5fcGFyZW50RmllbGRTdWJzY3JpcHRpb25baV0udW5zdWJzY3JpYmUoKTtcbiAgICAgICAgIH1cbiAgICAgIH1cbiAgIH1cblxuICAgaXNJbkFEaXNhYmxlZFNlY3Rpb24oKTogYm9vbGVhbiB7XG4gICAgICBpZiAodGhpcy5pc0FTd2l0Y2hTZWN0aW9uKCkpIHtcbiAgICAgICAgIGxldCBzZWN0aW9uRW5hYmxlcjogc3RyaW5nID0gT2JqZWN0LmtleXModGhpcy5zY2hlbWEucHJvcGVydGllcylbMF07XG4gICAgICAgICByZXR1cm4gISh0aGlzLmZvcm0gJiYgdGhpcy5mb3JtLmNvbnRyb2xzW3NlY3Rpb25FbmFibGVyXSAmJiB0aGlzLmZvcm0uY29udHJvbHNbc2VjdGlvbkVuYWJsZXJdLnZhbHVlKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgIH1cblxuICAgaXNBU3dpdGNoU2VjdGlvbigpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiB0aGlzLnNjaGVtYS51aSAmJiB0aGlzLnNjaGVtYS51aS5jb21wb25lbnQgPT09IEZPUk1fVUlfQ09NUE9ORU5ULlNXSVRDSDtcbiAgIH1cblxuICAgaXNBbkFjY29yZGlvbigpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiB0aGlzLnNjaGVtYS51aSAmJiB0aGlzLnNjaGVtYS51aS5jb21wb25lbnQgPT09IEZPUk1fVUlfQ09NUE9ORU5ULkFDQ09SRElPTjtcbiAgIH1cblxuICAgb25DbGlja1RpdGxlKCk6IHZvaWQge1xuICAgICAgaWYgKHRoaXMuaXNBbkFjY29yZGlvbigpKSB7XG4gICAgICAgICB0aGlzLm9uQ2hhbmdlT3B0aW9uYWxGaWVsZHNWaXNpYmlsaXR5KCk7XG4gICAgICB9XG4gICB9XG5cbiAgIGlzVGhlRmlyc3RGaWVsZChwcm9wZXJ0eU5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuIHByb3BlcnR5TmFtZSA9PT0gT2JqZWN0LmtleXModGhpcy5zY2hlbWEucHJvcGVydGllcylbMF07XG4gICB9XG5cbiAgIG9uQ2xpY2tMaW5rKGZpZWxkS2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgIHRoaXMuY2xpY2tMaW5rLmVtaXQoZmllbGRLZXkpO1xuICAgfVxuXG4gICBwcml2YXRlIGdldFBhcmVudEZpZWxkKHByb3BlcnR5TmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgIGxldCBwYXJlbnRGaWVsZDogc3RyaW5nID0gdW5kZWZpbmVkO1xuICAgICAgaWYgKHRoaXMuc2NoZW1hLmRlcGVuZGVuY2llcykge1xuICAgICAgICAgT2JqZWN0LmtleXModGhpcy5zY2hlbWEuZGVwZW5kZW5jaWVzKS5mb3JFYWNoKChrZXk6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc2NoZW1hLmRlcGVuZGVuY2llc1trZXldLmluZGV4T2YocHJvcGVydHlOYW1lKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgIHBhcmVudEZpZWxkID0ga2V5O1xuICAgICAgICAgICAgfVxuICAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcGFyZW50RmllbGQ7XG4gICB9XG5cbiAgIHByaXZhdGUgZnVsZmlsbERlcGVuZGVuY3lWaXNpYmlsaXR5KHByb3BlcnR5TmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICBsZXQgcHJvcGVydHlTY2hlbWE6IFN0Rm9ybVNjaGVtYSA9IHRoaXMuc2NoZW1hLnByb3BlcnRpZXNbcHJvcGVydHlOYW1lXTtcbiAgICAgIGxldCBmdWxmaWxsOiBib29sZWFuID0gIXByb3BlcnR5U2NoZW1hLnVpIHx8IHByb3BlcnR5U2NoZW1hLnVpLnZpc2libGUgIT09IGZhbHNlO1xuICAgICAgaWYgKHByb3BlcnR5U2NoZW1hLnVpICYmIHByb3BlcnR5U2NoZW1hLnVpLnZpc2libGUpIHtcbiAgICAgICAgIGNvbnN0IGtleXM6IHN0cmluZ1tdID0gT2JqZWN0LmtleXMocHJvcGVydHlTY2hlbWEudWkudmlzaWJsZSk7XG4gICAgICAgICBsZXQgaSA9IDA7XG4gICAgICAgICB3aGlsZSAoZnVsZmlsbCAmJiBpIDwga2V5cy5sZW5ndGggJiYgcHJvcGVydHlTY2hlbWEudWkudmlzaWJsZS5oYXNPd25Qcm9wZXJ0eShrZXlzW2ldKSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuX3ZhbHVlW2tleXNbaV1dICE9PSBwcm9wZXJ0eVNjaGVtYS51aS52aXNpYmxlW2tleXNbaV1dKSB7XG4gICAgICAgICAgICAgICBmdWxmaWxsID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICArK2k7XG4gICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gZnVsZmlsbDtcbiAgIH1cbn1cbiJdfQ==