UNPKG

@webdev-tools/ng-nested-reactive-forms

Version:
496 lines (481 loc) 68.5 kB
import { EventEmitter, Injectable, Directive, HostListener, Input, Optional, Output, Renderer2, TemplateRef, ViewContainerRef, NgModule } from '@angular/core'; import { FormGroup, FormsModule, ReactiveFormsModule, Validators, FormArray, FormControl } from '@angular/forms'; import { __spread, __assign } from 'tslib'; import { ReplaySubject } from 'rxjs/internal/ReplaySubject'; import { takeWhile } from 'rxjs/operators'; import { CommonModule } from '@angular/common'; var NrfFormContext = (function () { function NrfFormContext(nrfForm) { this.nrfForm = nrfForm; this.$implicit = nrfForm; this.formGroup = nrfForm.formGroup; } return NrfFormContext; }()); var NrfSubmitData = (function () { function NrfSubmitData(nrfForm, $event) { this.nrfForm = nrfForm; this.event = $event; this.formData = nrfForm.formData; this.entity = nrfForm.nrfEntity; this.formGroup = nrfForm.formGroup; } return NrfSubmitData; }()); function cloneDeep(target) { if (!target || typeof target !== 'object') { return target; } if (target instanceof Date) { return new Date(target); } if (Array.isArray(target)) { return target.map(cloneDeep); } return Object.keys(target).reduce(function (props, key) { props[key] = cloneDeep(target[key]); return props; }, {}); } var NrfFormService = (function () { function NrfFormService() { this.formGroup = new FormGroup({}); this.submit$ = new EventEmitter(); } Object.defineProperty(NrfFormService.prototype, "entity", { get: function () { return this.privateEntity; }, set: function (entity) { this.privateEntity = entity; this.formData = cloneDeep(entity); }, enumerable: true, configurable: true }); NrfFormService.decorators = [ { type: Injectable } ]; return NrfFormService; }()); function newNrfFormService() { return new NrfFormService(); } var NRF_FORM_SERVICE_PROVIDER = { provide: NrfFormService, useFactory: newNrfFormService, }; var NrfFormDirective = (function () { function NrfFormDirective(templateRef, viewContainerRef, formService, renderer) { this.templateRef = templateRef; this.viewContainerRef = viewContainerRef; this.formService = formService; this.renderer = renderer; if (!formService) { this.formService = new NrfFormService(); } } Object.defineProperty(NrfFormDirective.prototype, "nrfEntity", { get: function () { return this.formService.entity; }, set: function (entity) { this.formService.entity = entity; }, enumerable: true, configurable: true }); Object.defineProperty(NrfFormDirective.prototype, "formData", { get: function () { return this.formService.formData; }, enumerable: true, configurable: true }); Object.defineProperty(NrfFormDirective.prototype, "formGroup", { get: function () { return this.formService.formGroup; }, enumerable: true, configurable: true }); Object.defineProperty(NrfFormDirective.prototype, "nrfSubmit", { get: function () { return this.formService.submit$; }, enumerable: true, configurable: true }); NrfFormDirective.prototype.ngOnInit = function () { if (!this.nrfEntity) { this.nrfEntity = {}; } this.renderView(); }; NrfFormDirective.prototype.ngOnDestroy = function () { this.nrfSubmit.complete(); }; NrfFormDirective.prototype.renderView = function () { var _this = this; if (this.templateRef && this.viewContainerRef) { var embeddedViewRef = this.viewContainerRef.createEmbeddedView(this.templateRef, new NrfFormContext(this)); var formNative = embeddedViewRef.rootNodes[0]; this.renderer.listen(formNative, 'submit', function (event) { return _this.formSubmitWrapper(event); }); } }; NrfFormDirective.prototype.formSubmitWrapper = function ($event) { $event.preventDefault(); if (!this.formGroup.valid) { return; } this.nrfSubmit.emit(new NrfSubmitData(this, $event)); }; NrfFormDirective.decorators = [ { type: Directive, args: [{ selector: '[nrfForm]', exportAs: 'nrfForm', },] } ]; NrfFormDirective.ctorParameters = function () { return [ { type: TemplateRef, decorators: [{ type: Optional }] }, { type: ViewContainerRef, decorators: [{ type: Optional }] }, { type: NrfFormService, decorators: [{ type: Optional }] }, { type: Renderer2 } ]; }; NrfFormDirective.propDecorators = { nrfEntity: [{ type: Input }], nrfSubmit: [{ type: Output }], formSubmitWrapper: [{ type: HostListener, args: ['submit', ['$event'],] }] }; return NrfFormDirective; }()); var NrfFormModule = (function () { function NrfFormModule() { } NrfFormModule.decorators = [ { type: NgModule, args: [{ imports: [FormsModule, ReactiveFormsModule], exports: [FormsModule, ReactiveFormsModule, NrfFormDirective], declarations: [NrfFormDirective], },] } ]; return NrfFormModule; }()); var NrfControlOptionsComponent = (function () { function NrfControlOptionsComponent() { this.disabled = null; this.min = null; this.max = null; this.required = null; this.email = null; this.minLength = null; this.maxLength = null; this.pattern = null; this.updateOn = null; } NrfControlOptionsComponent.prototype.ngOnInit = function () { this.controlOptions = this.generateControlOptions(); }; NrfControlOptionsComponent.prototype.generateControlOptions = function () { var _this = this; return { validators: Object.keys(Validators) .filter(function (key) { return _this[key]; }) .map(function (key) { return Validators[key]; }), updateOn: this.updateOn, disabled: this.disabled, }; }; NrfControlOptionsComponent.propDecorators = { disabled: [{ type: Input, args: ['disabled',] }], min: [{ type: Input, args: ['min',] }], max: [{ type: Input, args: ['max',] }], required: [{ type: Input, args: ['required',] }], email: [{ type: Input, args: ['email',] }], minLength: [{ type: Input, args: ['minLength',] }], maxLength: [{ type: Input, args: ['maxLength',] }], pattern: [{ type: Input, args: ['pattern',] }], updateOn: [{ type: Input, args: ['updateOn',] }] }; return NrfControlOptionsComponent; }()); var NrfNestedControlContext = (function () { function NrfNestedControlContext(formControl, formGroup, nrfNestedControl) { this.formControl = formControl; this.formGroup = formGroup; this.nrfNestedControl = nrfNestedControl; this.$implicit = formControl; } return NrfNestedControlContext; }()); var NrfFormHierarchyService = (function () { function NrfFormHierarchyService() { } NrfFormHierarchyService.prototype.getNestedControl = function (rootFormGroup, fullPath) { var parentControl = ((rootFormGroup.get(fullPath))); if (!parentControl) { var pathPieces = Array.isArray(fullPath) ? fullPath : fullPath.split('.'); parentControl = pathPieces.reduce(this.createFormGroupHierarchy, rootFormGroup); } if (parentControl instanceof FormControl) { parentControl = parentControl.parent; } return parentControl; }; NrfFormHierarchyService.prototype.createFormGroupHierarchy = function (parentControl, path, index, pathPieces) { if (index === pathPieces.length - 1) { return parentControl; } var control = ((parentControl.get(path))); if (!control) { var nextPath = pathPieces[index + 1] || path; var isArray = nextPath && !isNaN(((nextPath))); control = isArray ? new FormArray([]) : new FormGroup({}); } if (parentControl instanceof FormGroup) { parentControl.addControl(path, control); } else if (parentControl instanceof FormArray) { parentControl.insert(parseInt(path, 10) || 0, control); } return control; }; NrfFormHierarchyService.decorators = [ { type: Injectable } ]; return NrfFormHierarchyService; }()); var NrfModelSetterService = (function () { function NrfModelSetterService() { var _this = this; this.getTargetPropToSet = function (obj, key, i, pathPieces) { var nextKey = pathPieces[i + 1]; var isLast = nextKey == null; nextKey = nextKey || pathPieces['finalKey']; var isArrayKey = _this.isArrayKey(nextKey); var prop = obj[key]; if (!prop) { prop = isArrayKey ? [] : {}; obj[key] = prop; } else if (isLast) { prop = isArrayKey ? __spread(prop) : __assign({}, prop); obj[key] = prop; } return prop; }; } NrfModelSetterService.prototype.getValue = function (path, model, separator) { if (separator === void 0) { separator = '.'; } if (path == null || !model) { return null; } try { var pathPieces = this.generatePathPieces(path, separator); return pathPieces.reduce(this.piecesReducer, model) || null; } catch (err) { return null; } }; NrfModelSetterService.prototype.piecesReducer = function (obj, key) { return key === '' ? obj.slice(-1)[0] : obj[key]; }; NrfModelSetterService.prototype.setValue = function (path, value, model, separator) { if (separator === void 0) { separator = '.'; } if (!(path && model)) { return null; } try { var pathPieces = this.generatePathPieces(path, separator); var finalKey = pathPieces.pop(); (((pathPieces)))['finalKey'] = finalKey; var targetProp = pathPieces.reduce(this.getTargetPropToSet, model) || null; if (finalKey === '') { targetProp.push(value); } else { targetProp[finalKey] = value; } } catch (err) { console.error('NestedProps setValue error: ', err); } }; NrfModelSetterService.prototype.isArrayKey = function (key) { return key === '' || !isNaN(parseInt(key, 10)); }; NrfModelSetterService.prototype.generatePathPieces = function (path, separator) { return path .replace('[', separator) .replace(']', '') .split(separator); }; NrfModelSetterService.decorators = [ { type: Injectable } ]; return NrfModelSetterService; }()); var NrfNestedControlDirective = (function () { function NrfNestedControlDirective(modelSetter, templateRef, viewContainerRef, nrfForm, nrfFormService, formHierarchy) { this.modelSetter = modelSetter; this.templateRef = templateRef; this.viewContainerRef = viewContainerRef; this.formHierarchy = formHierarchy; this.isDestroyed = false; this.ready$ = new ReplaySubject(1); this.formOrService = nrfFormService || nrfForm; } NrfNestedControlDirective.prototype.ngOnInit = function () { this.modelPath = this.getModelPathWithoutFirstPart(); this.modelPieces = this.modelPath && this.modelPath.split('.'); this.controlName = this.getControlName(); this.formControl = this.getFormControl(); this.registerToFormGroup(); this.subscribeToUpdateEntityValue(); this.showViewContent(); this.emitReadyState(); }; NrfNestedControlDirective.prototype.ngOnDestroy = function () { this.isDestroyed = true; this.ready$.complete(); if (this.parentFormGroup) { this.removeFromParentFormGroup(); } }; NrfNestedControlDirective.prototype.removeFromParentFormGroup = function () { var _this = this; if (this.parentFormGroup instanceof FormGroup) { this.parentFormGroup.removeControl(this.nrfModelName); } else { var index = this.parentFormGroup.controls.findIndex(function (control) { return _this.formControl === control; }); this.parentFormGroup.removeAt(index); } }; NrfNestedControlDirective.prototype.getModelPathWithoutFirstPart = function () { var modelName = this.nrfModelName; return modelName && modelName.substr(modelName.indexOf('.') + 1); }; NrfNestedControlDirective.prototype.getControlName = function () { var modelPieces = this.modelPieces; return modelPieces && modelPieces[modelPieces.length - 1]; }; NrfNestedControlDirective.prototype.getNewFormControl = function () { var disabled = this.controlOptions && this.controlOptions.disabled; var value = this.getInitialValue(); return new FormControl({ value: value, disabled: disabled }, this.controlOptions); }; NrfNestedControlDirective.prototype.getInitialValue = function () { if (this.formOrService && this.modelPath) { return this.modelSetter.getValue(this.modelPath, this.formOrService.formData); } return null; }; NrfNestedControlDirective.prototype.showViewContent = function () { var context = new NrfNestedControlContext(this.formControl, this.formOrService && this.formOrService.formGroup, this); this.viewContainerRef.createEmbeddedView(this.templateRef, context); }; NrfNestedControlDirective.prototype.registerToFormGroup = function () { if (this.parentFormGroup) { return; } this.parentFormGroup = this.getParentFormGroup(); if (this.parentFormGroup) { if (this.parentFormGroup instanceof FormGroup) { this.parentFormGroup.addControl(this.modelPath, this.formControl); } else { var index = this.controlName; this.parentFormGroup.insert(parseInt(index, 10), this.formControl); } } }; NrfNestedControlDirective.prototype.getParentFormGroup = function () { var rootFormGroup = this.formOrService && this.formOrService.formGroup; if (!rootFormGroup || !this.modelPath) { return null; } var formGroupPath = Array.from(this.modelPieces); return this.formHierarchy.getNestedControl(rootFormGroup, formGroupPath); }; NrfNestedControlDirective.prototype.getFormControl = function () { var formGroup = this.getParentFormGroup(); var formControl = formGroup && this.nrfModelName && ((formGroup.get(this.nrfModelName))); if (!formControl) { formControl = this.getNewFormControl(); } return formControl; }; NrfNestedControlDirective.prototype.subscribeToUpdateEntityValue = function () { var _this = this; this.formControl.valueChanges .pipe(takeWhile(function () { return !_this.isDestroyed; })) .subscribe(function (newValue) { return _this.setModelValue(newValue); }); }; NrfNestedControlDirective.prototype.setModelValue = function (newValue) { if (this.formOrService && this.modelPath) { return this.modelSetter.setValue(this.modelPath, newValue || '', this.formOrService.formData); } }; NrfNestedControlDirective.prototype.emitReadyState = function () { this.ready$.next(this); }; NrfNestedControlDirective.decorators = [ { type: Directive, args: [{ selector: '[nrfNestedControl]', exportAs: 'nrfNestedControl', },] } ]; NrfNestedControlDirective.ctorParameters = function () { return [ { type: NrfModelSetterService }, { type: TemplateRef }, { type: ViewContainerRef }, { type: NrfFormDirective, decorators: [{ type: Optional }] }, { type: NrfFormService, decorators: [{ type: Optional }] }, { type: NrfFormHierarchyService } ]; }; NrfNestedControlDirective.propDecorators = { nrfModelName: [{ type: Input, args: ['nrfNestedControl',] }], controlOptions: [{ type: Input, args: ['nrfNestedControlControlOptions',] }], ready$: [{ type: Output }] }; return NrfNestedControlDirective; }()); var NrfModelModule = (function () { function NrfModelModule() { } NrfModelModule.decorators = [ { type: NgModule, args: [{ imports: [ CommonModule, ], providers: [ NrfModelSetterService, NrfFormHierarchyService, ], declarations: [ NrfNestedControlDirective, ], exports: [ NrfNestedControlDirective, ], },] } ]; return NrfModelModule; }()); var NrFormsModule = (function () { function NrFormsModule() { } NrFormsModule.decorators = [ { type: NgModule, args: [{ exports: [ NrfFormModule, NrfModelModule, ], },] } ]; return NrFormsModule; }()); export { NrFormsModule, cloneDeep, NrfFormDirective, NrfFormContext, NrfSubmitData, NrfFormService, NRF_FORM_SERVICE_PROVIDER, NrfFormModule, NrfNestedControlDirective, NrfNestedControlContext, NrfModelSetterService, NrfControlOptionsComponent, NrfFormHierarchyService, NrfModelModule, newNrfFormService as ɵa }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViZGV2LXRvb2xzLW5nLW5lc3RlZC1yZWFjdGl2ZS1mb3Jtcy5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vQHdlYmRldi10b29scy9uZy1uZXN0ZWQtcmVhY3RpdmUtZm9ybXMvbGliL2Zvcm0vZm9ybS1jb250ZXh0LmNsYXNzLnRzIiwibmc6Ly9Ad2ViZGV2LXRvb2xzL25nLW5lc3RlZC1yZWFjdGl2ZS1mb3Jtcy9saWIvZm9ybS9mb3JtLXN1Ym1pdC1kYXRhLmNsYXNzLnRzIiwibmc6Ly9Ad2ViZGV2LXRvb2xzL25nLW5lc3RlZC1yZWFjdGl2ZS1mb3Jtcy9saWIvdXRpbHMvY2xvbmUtZGVlcC50cyIsIm5nOi8vQHdlYmRldi10b29scy9uZy1uZXN0ZWQtcmVhY3RpdmUtZm9ybXMvbGliL2Zvcm0vZm9ybS5zZXJ2aWNlLnRzIiwibmc6Ly9Ad2ViZGV2LXRvb2xzL25nLW5lc3RlZC1yZWFjdGl2ZS1mb3Jtcy9saWIvZm9ybS9mb3JtLmRpcmVjdGl2ZS50cyIsIm5nOi8vQHdlYmRldi10b29scy9uZy1uZXN0ZWQtcmVhY3RpdmUtZm9ybXMvbGliL2Zvcm0vZm9ybS5tb2R1bGUudHMiLCJuZzovL0B3ZWJkZXYtdG9vbHMvbmctbmVzdGVkLXJlYWN0aXZlLWZvcm1zL2xpYi9uZXN0ZWQtY29udHJvbC9jb250cm9sLW9wdGlvbnMuY29tcG9uZW50LnRzIiwibmc6Ly9Ad2ViZGV2LXRvb2xzL25nLW5lc3RlZC1yZWFjdGl2ZS1mb3Jtcy9saWIvbmVzdGVkLWNvbnRyb2wvbmVzdGVkLWNvbnRyb2wtY29udGV4dC5jbGFzcy50cyIsIm5nOi8vQHdlYmRldi10b29scy9uZy1uZXN0ZWQtcmVhY3RpdmUtZm9ybXMvbGliL25lc3RlZC1jb250cm9sL3NlcnZpY2VzL2Zvcm0taGllcmFyY2h5LnNlcnZpY2UudHMiLCJuZzovL0B3ZWJkZXYtdG9vbHMvbmctbmVzdGVkLXJlYWN0aXZlLWZvcm1zL2xpYi9uZXN0ZWQtY29udHJvbC9zZXJ2aWNlcy9tb2RlbC1zZXR0ZXIuc2VydmljZS50cyIsIm5nOi8vQHdlYmRldi10b29scy9uZy1uZXN0ZWQtcmVhY3RpdmUtZm9ybXMvbGliL25lc3RlZC1jb250cm9sL25lc3RlZC1jb250cm9sLmRpcmVjdGl2ZS50cyIsIm5nOi8vQHdlYmRldi10b29scy9uZy1uZXN0ZWQtcmVhY3RpdmUtZm9ybXMvbGliL25lc3RlZC1jb250cm9sL25lc3RlZC1jb250cm9sLm1vZHVsZS50cyIsIm5nOi8vQHdlYmRldi10b29scy9uZy1uZXN0ZWQtcmVhY3RpdmUtZm9ybXMvbGliL2Zvcm1zLm1vZHVsZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBGb3JtR3JvdXAgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmltcG9ydCB7IE5yZkZvcm1EaXJlY3RpdmUgfSBmcm9tICcuL2Zvcm0uZGlyZWN0aXZlJztcblxuZXhwb3J0IGNsYXNzIE5yZkZvcm1Db250ZXh0IHtcbiAgJGltcGxpY2l0OiBOcmZGb3JtRGlyZWN0aXZlO1xuICBmb3JtR3JvdXA6IEZvcm1Hcm91cDtcblxuICBjb25zdHJ1Y3RvcihwdWJsaWMgbnJmRm9ybTogTnJmRm9ybURpcmVjdGl2ZSkge1xuICAgIHRoaXMuJGltcGxpY2l0ID0gbnJmRm9ybTtcbiAgICB0aGlzLmZvcm1Hcm91cCA9IG5yZkZvcm0uZm9ybUdyb3VwO1xuICB9XG59XG4iLCJpbXBvcnQgeyBGb3JtR3JvdXAgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmltcG9ydCB7IE5yZkZvcm1EaXJlY3RpdmUgfSBmcm9tICcuL2Zvcm0uZGlyZWN0aXZlJztcblxuZXhwb3J0IGNsYXNzIE5yZlN1Ym1pdERhdGEge1xuICBucmZGb3JtOiBOcmZGb3JtRGlyZWN0aXZlO1xuICBmb3JtRGF0YTogYW55O1xuICBlbnRpdHk6IGFueTtcbiAgZm9ybUdyb3VwOiBGb3JtR3JvdXA7XG4gIGV2ZW50OiBFdmVudDtcblxuICBjb25zdHJ1Y3RvcihucmZGb3JtOiBOcmZGb3JtRGlyZWN0aXZlLCAkZXZlbnQ6IEV2ZW50KSB7XG4gICAgdGhpcy5ucmZGb3JtID0gbnJmRm9ybTtcbiAgICB0aGlzLmV2ZW50ID0gJGV2ZW50O1xuICAgIHRoaXMuZm9ybURhdGEgPSBucmZGb3JtLmZvcm1EYXRhO1xuICAgIHRoaXMuZW50aXR5ID0gbnJmRm9ybS5ucmZFbnRpdHk7XG4gICAgdGhpcy5mb3JtR3JvdXAgPSBucmZGb3JtLmZvcm1Hcm91cDtcbiAgfVxufVxuIiwiZXhwb3J0IGZ1bmN0aW9uIGNsb25lRGVlcCh0YXJnZXQ6IGFueSB8IGFueVtdKTogYW55IHtcbiAgaWYgKCF0YXJnZXQgfHwgdHlwZW9mIHRhcmdldCAhPT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm4gdGFyZ2V0O1xuICB9XG5cbiAgaWYgKHRhcmdldCBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICByZXR1cm4gbmV3IERhdGUodGFyZ2V0KTtcbiAgfVxuXG4gIGlmIChBcnJheS5pc0FycmF5KHRhcmdldCkpIHtcbiAgICByZXR1cm4gdGFyZ2V0Lm1hcChjbG9uZURlZXApO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5rZXlzKHRhcmdldCkucmVkdWNlKFxuICAgIChwcm9wcywga2V5KSA9PiB7XG4gICAgICBwcm9wc1trZXldID0gY2xvbmVEZWVwKHRhcmdldFtrZXldKTtcbiAgICAgIHJldHVybiBwcm9wcztcbiAgICB9LFxuICAgIHt9LFxuICApO1xufVxuIiwiaW1wb3J0IHsgRXZlbnRFbWl0dGVyLCBJbmplY3RhYmxlLCBQcm92aWRlciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUdyb3VwIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQgeyBjbG9uZURlZXAgfSBmcm9tICcuLi91dGlscy9jbG9uZS1kZWVwJztcbmltcG9ydCB7IE5yZlN1Ym1pdERhdGEgfSBmcm9tICcuL2Zvcm0tc3VibWl0LWRhdGEuY2xhc3MnO1xuXG4vKiB0c2xpbnQ6ZGlzYWJsZSB0ZXItcGFkZGVkLWJsb2NrcyAqL1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgTnJmRm9ybVNlcnZpY2Uge1xuICAvKipcbiAgICogRm9ybSBncm91cCB3aWxsIGhvbGQgYWxsIGlucHV0cyB3aXRoaW4gdGhpcyBmb3JtLlxuICAgKlxuICAgKiBFdmVyeSBpbnB1dCBzaG91bGQgcmVnaXN0ZXIgaXRzZWxmIHRvIHRoaXMgZm9ybSBncm91cC5cbiAgICpcbiAgICogVGhlIGRhdGEgaW4gdGhpcyBmb3JtIGdyb3VwIHdpbGwgbm90IGJlIHNlbnQgdG8gYmFja2VuZCwganVzdCBmb3JtIHZhbGlkYXRpb25zIGFuZCBpbnB1dCBtYW5hZ2VtZW50LlxuICAgKi9cbiAgcmVhZG9ubHkgZm9ybUdyb3VwOiBGb3JtR3JvdXAgPSBuZXcgRm9ybUdyb3VwKHt9KTtcblxuICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6dmFyaWFibGUtbmFtZVxuICBwcml2YXRlIHByaXZhdGVFbnRpdHk6IGFueTtcblxuICBzZXQgZW50aXR5KGVudGl0eTogYW55KSB7XG4gICAgdGhpcy5wcml2YXRlRW50aXR5ID0gZW50aXR5O1xuICAgIHRoaXMuZm9ybURhdGEgPSBjbG9uZURlZXAoZW50aXR5KTsgLy8gVE9ETyBtZXJnZSB3aXRoIGV4aXN0ZW50IGZvcm1EYXRhXG4gIH1cbiAgZ2V0IGVudGl0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5wcml2YXRlRW50aXR5O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcHJlc2VudHMgdGhlIGRhdGEgaW5wdXR0ZWQgYnkgdGhlIHVzZXIgb24gdGhlIGZpZWxkc1xuICAgKi9cbiAgZm9ybURhdGE6IGFueTtcblxuICAvKipcbiAgICogSW50ZXJuYWwgZW1pdHRlciB0byBoYW5kbGUgZm9ybSBzdWJtaXRcbiAgICovXG4gIHJlYWRvbmx5IHN1Ym1pdCQgPSBuZXcgRXZlbnRFbWl0dGVyPE5yZlN1Ym1pdERhdGE+KCk7XG59XG5cbi8qKlxuICogQGlnbm9yZVxuICovXG5leHBvcnQgZnVuY3Rpb24gbmV3TnJmRm9ybVNlcnZpY2UoKSB7XG4gIHJldHVybiBuZXcgTnJmRm9ybVNlcnZpY2UoKTtcbn1cblxuLyoqXG4gKiBVc2UgdGhpcyB0byBwcm92aWRlIGZvcm0tc2VydmljZSB0byBDb21wb25lbnRzIHRoYXQgd3JhcHMgbnJmRm9ybSBhbmQgcHV0IGlucHV0cyBpbnNpZGUgPG5nLWNvbnRlbnQ+XG4gKi9cbmV4cG9ydCBjb25zdCBOUkZfRk9STV9TRVJWSUNFX1BST1ZJREVSOiBQcm92aWRlciA9IHtcbiAgcHJvdmlkZTogTnJmRm9ybVNlcnZpY2UsXG4gIHVzZUZhY3Rvcnk6IG5ld05yZkZvcm1TZXJ2aWNlLFxufTtcbiIsImltcG9ydCB7XG4gIERpcmVjdGl2ZSxcbiAgRXZlbnRFbWl0dGVyLFxuICBIb3N0TGlzdGVuZXIsXG4gIElucHV0LFxuICBPbkRlc3Ryb3ksXG4gIE9uSW5pdCxcbiAgT3B0aW9uYWwsXG4gIE91dHB1dCxcbiAgUmVuZGVyZXIyLFxuICBUZW1wbGF0ZVJlZixcbiAgVmlld0NvbnRhaW5lclJlZixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGb3JtR3JvdXAgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmltcG9ydCB7IE5yZkZvcm1Db250ZXh0IH0gZnJvbSAnLi9mb3JtLWNvbnRleHQuY2xhc3MnO1xuaW1wb3J0IHsgTnJmU3VibWl0RGF0YSB9IGZyb20gJy4vZm9ybS1zdWJtaXQtZGF0YS5jbGFzcyc7XG5pbXBvcnQgeyBOcmZGb3JtU2VydmljZSB9IGZyb20gJy4vZm9ybS5zZXJ2aWNlJztcblxuLyogdHNsaW50OmRpc2FibGU6IHRlci1wYWRkZWQtYmxvY2tzICovXG4vKipcbiAqIEEgY29tcG9uZW50IHRvIGFic3RyYWN0IHRoZSBmb3JtIGltcGxlbWVudGF0aW9uXG4gKlxuICogSXQgaG9sZHMgdGhlIHZhbGlkYXRpb24gYW5kIHRoZSBzdWJtaXQgbG9naWNcbiAqXG4gKiBAZXhhbXBsZVxuICogPGZvcm0gbnJmRm9ybSAobnJmU3VibWl0KT1cImFDYWxsYmFjaygkZXZlbnQpXCI+XG4gKiAgLy8gSW5wdXRzXG4gKiA8L2Zvcm0+XG4gKi9cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ1tucmZGb3JtXScsXG4gIGV4cG9ydEFzOiAnbnJmRm9ybScsXG59KVxuZXhwb3J0IGNsYXNzIE5yZkZvcm1EaXJlY3RpdmUgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gIC8qKlxuICAgKiBAaWdub3JlXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICBAT3B0aW9uYWwoKSBwcml2YXRlIHJlYWRvbmx5IHRlbXBsYXRlUmVmOiBUZW1wbGF0ZVJlZjxhbnk+LFxuICAgIEBPcHRpb25hbCgpIHByaXZhdGUgcmVhZG9ubHkgdmlld0NvbnRhaW5lclJlZjogVmlld0NvbnRhaW5lclJlZixcbiAgICBAT3B0aW9uYWwoKSBwcml2YXRlIHJlYWRvbmx5IGZvcm1TZXJ2aWNlOiBOcmZGb3JtU2VydmljZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHJlbmRlcmVyOiBSZW5kZXJlcjIsXG4gICkge1xuICAgIGlmICghZm9ybVNlcnZpY2UpIHtcbiAgICAgIHRoaXMuZm9ybVNlcnZpY2UgPSBuZXcgTnJmRm9ybVNlcnZpY2UoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVwcmVzZW50cyBhbiBFbnRpdHkgTW9kZWwgdGhhdCBjb21lcyBmcm9tIERhdGFiYXNlXG4gICAqL1xuICBASW5wdXQoKVxuICBzZXQgbnJmRW50aXR5KGVudGl0eTogYW55KSB7XG4gICAgdGhpcy5mb3JtU2VydmljZS5lbnRpdHkgPSBlbnRpdHk7XG4gIH1cbiAgZ2V0IG5yZkVudGl0eSgpOiBhbnkge1xuICAgIHJldHVybiB0aGlzLmZvcm1TZXJ2aWNlLmVudGl0eTtcbiAgfVxuXG4gIGdldCBmb3JtRGF0YSgpOiBhbnkge1xuICAgIHJldHVybiB0aGlzLmZvcm1TZXJ2aWNlLmZvcm1EYXRhO1xuICB9XG5cbiAgZ2V0IGZvcm1Hcm91cCgpOiBGb3JtR3JvdXAge1xuICAgIHJldHVybiB0aGlzLmZvcm1TZXJ2aWNlLmZvcm1Hcm91cDtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBjYWxsZWQgd2hlbiB0aGUgZm9ybSBpcyB2YWxpZCBhbmQgYSBzdWJtaXQgZXZlbnQgaXMgdHJpZ2dlcmVkXG4gICAqIGJ5IGEgYnV0dG9uIGNsaWNrIG9yIHByb2dyYW1tYXRpY2FsbHkuXG4gICAqL1xuICBAT3V0cHV0KClcbiAgZ2V0IG5yZlN1Ym1pdCgpOiBFdmVudEVtaXR0ZXI8TnJmU3VibWl0RGF0YT4ge1xuICAgIHJldHVybiB0aGlzLmZvcm1TZXJ2aWNlLnN1Ym1pdCQ7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBJbml0IGFuIGVtcHR5IG5yZkVudGl0eSwgaW4gY2FzZSBub25lIHdoZXJlIHByb3ZpZGVkLlxuICAgKi9cbiAgbmdPbkluaXQoKSB7XG4gICAgaWYgKCF0aGlzLm5yZkVudGl0eSkge1xuICAgICAgdGhpcy5ucmZFbnRpdHkgPSB7fTtcbiAgICB9XG5cbiAgICB0aGlzLnJlbmRlclZpZXcoKTtcbiAgfVxuXG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5ucmZTdWJtaXQuY29tcGxldGUoKTtcbiAgfVxuXG5cbiAgcHJpdmF0ZSByZW5kZXJWaWV3KCkge1xuICAgIGlmICh0aGlzLnRlbXBsYXRlUmVmICYmIHRoaXMudmlld0NvbnRhaW5lclJlZikge1xuICAgICAgY29uc3QgZW1iZWRkZWRWaWV3UmVmID0gdGhpcy52aWV3Q29udGFpbmVyUmVmLmNyZWF0ZUVtYmVkZGVkVmlldyh0aGlzLnRlbXBsYXRlUmVmLCBuZXcgTnJmRm9ybUNvbnRleHQodGhpcykpO1xuICAgICAgY29uc3QgZm9ybU5hdGl2ZSA9IGVtYmVkZGVkVmlld1JlZi5yb290Tm9kZXNbMF07XG4gICAgICB0aGlzLnJlbmRlcmVyLmxpc3Rlbihmb3JtTmF0aXZlLCAnc3VibWl0JywgZXZlbnQgPT4gdGhpcy5mb3JtU3VibWl0V3JhcHBlcihldmVudCkpO1xuICAgIH1cbiAgfVxuXG5cbiAgLyoqXG4gICAqICMgU2hvdWxkIG5vdCBiZSBjYWxsZWQgZGlyZWN0bHkhXG4gICAqIFRoaXMgbWV0aG9kIHdyYXBzIHRoZSBmb3JtIHZhbGlkYXRpb24gYW5kIGNhbGwgW25yZlN1Ym1pdF17QGxpbmsgTnJmRm9ybURpcmVjdGl2ZSNucmZTdWJtaXR9XG4gICAqL1xuICBASG9zdExpc3RlbmVyKCdzdWJtaXQnLCBbJyRldmVudCddKVxuICBmb3JtU3VibWl0V3JhcHBlcigkZXZlbnQ6IEV2ZW50KSB7XG4gICAgJGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICBpZiAoIXRoaXMuZm9ybUdyb3VwLnZhbGlkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5ucmZTdWJtaXQuZW1pdChuZXcgTnJmU3VibWl0RGF0YSh0aGlzLCAkZXZlbnQpKTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgTmdNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1zTW9kdWxlLCBSZWFjdGl2ZUZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQgeyBOcmZGb3JtQ29udGV4dCB9IGZyb20gJy4vZm9ybS1jb250ZXh0LmNsYXNzJztcbmltcG9ydCB7IE5yZlN1Ym1pdERhdGEgfSBmcm9tICcuL2Zvcm0tc3VibWl0LWRhdGEuY2xhc3MnO1xuaW1wb3J0IHsgTnJmRm9ybURpcmVjdGl2ZSB9IGZyb20gJy4vZm9ybS5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgTlJGX0ZPUk1fU0VSVklDRV9QUk9WSURFUiwgTnJmRm9ybVNlcnZpY2UgfSBmcm9tICcuL2Zvcm0uc2VydmljZSc7XG5cbmV4cG9ydCB7IE5yZkZvcm1EaXJlY3RpdmUsIE5yZkZvcm1Db250ZXh0LCBOcmZTdWJtaXREYXRhLCBOcmZGb3JtU2VydmljZSwgTlJGX0ZPUk1fU0VSVklDRV9QUk9WSURFUiB9O1xuXG4vKiB0c2xpbnQ6ZGlzYWJsZTogdGVyLXBhZGRlZC1ibG9ja3MgKi9cbi8qKlxuICogVGhpcyBtb2R1bGUgb25seSBoYW5kbGUgZm9ybSBBYnN0cmFjdGlvbiBhbmQgc3VibWl0IGhhbmRsZXJcbiAqIE5vIGlucHV0cyBhcmUgcHJvdmlkZWQgYnkgdGhpcyBtb2R1bGUuXG4gKi9cbkBOZ01vZHVsZSh7XG4gIGltcG9ydHM6IFtGb3Jtc01vZHVsZSwgUmVhY3RpdmVGb3Jtc01vZHVsZV0sXG4gIGV4cG9ydHM6IFtGb3Jtc01vZHVsZSwgUmVhY3RpdmVGb3Jtc01vZHVsZSwgTnJmRm9ybURpcmVjdGl2ZV0sXG4gIGRlY2xhcmF0aW9uczogW05yZkZvcm1EaXJlY3RpdmVdLFxufSlcbmV4cG9ydCBjbGFzcyBOcmZGb3JtTW9kdWxlIHt9XG4iLCJpbXBvcnQgeyBJbnB1dCwgT25Jbml0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBYnN0cmFjdENvbnRyb2xPcHRpb25zLCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG4vKiB0c2xpbnQ6ZGlzYWJsZTogdGVyLXBhZGRlZC1ibG9ja3MgKi9cblxuZXhwb3J0IGludGVyZmFjZSBOcmZDb250cm9sT3B0aW9ucyBleHRlbmRzIEFic3RyYWN0Q29udHJvbE9wdGlvbnMge1xuICBkaXNhYmxlZDogYm9vbGVhbjtcbn1cblxuLy8gdHNsaW50OmRpc2FibGUgbm8taW5wdXQtcmVuYW1lXG5cbi8qKlxuICogSW5wdXQgd3JhcHBlcnMgY29tcG9uZW50cyBzaG91bGQgZXh0ZW5kcyB0aGlzIGNsYXNzIHRvIHBhc3MgY29uc3RyYWludHMgZG93bndhcmRzXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBOcmZDb250cm9sT3B0aW9uc0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIC8qKlxuICAgKiBBIGxpc3Qgb2YgVmFsaWRhdG9ycyB0byB2YWxpZGF0ZSB0aGUgaW5wdXQgYW5kIHRoZSB1cGRhdGUtb24gc3RyYXRlZ3lcbiAgICovXG4gIGNvbnRyb2xPcHRpb25zOiBOcmZDb250cm9sT3B0aW9ucztcblxuICAvKipcbiAgICogU2V0cyB0aGlzIGlucHV0IHRvIHJlYWRvbmx5IGFuZCBibG9jayBhbnkgY2hhbmdlc1xuICAgKi9cbiAgQElucHV0KCdkaXNhYmxlZCcpIGRpc2FibGVkOiBib29sZWFuID0gbnVsbDtcblxuICAvKipcbiAgICogRGVmaW5lIHRoZSBsb3dlc3QgbnVtYmVyIHZhbHVlIHRoYXQgdGhpcyBpbnB1dCBzaG91bGQgYWNjZXB0XG4gICAqL1xuICBASW5wdXQoJ21pbicpIG1pbjogc3RyaW5nIHwgbnVtYmVyID0gbnVsbDtcblxuICAvKipcbiAgICogRGVmaW5lIHRoZSBtYXhpbXVtIG51bWJlciB2YWx1ZSB0aGF0IHRoaXMgaW5wdXQgc2hvdWxkIGFjY2VwdFxuICAgKi9cbiAgQElucHV0KCdtYXgnKSBtYXg6IHN0cmluZyB8IG51bWJlciA9IG51bGw7XG5cbiAgLyoqXG4gICAqIFNldCB0aGlzIGlucHV0IGFzIHJlcXVpcmVkIGFuZCBmYWlscyB3aGVuIGVtcHR5XG4gICAqL1xuICBASW5wdXQoJ3JlcXVpcmVkJykgcmVxdWlyZWQ6IGJvb2xlYW4gPSBudWxsO1xuXG4gIC8vIEBJbnB1dCgnUmVxdWlyZWRUcnVlJykgcmVxdWlyZWRUcnVlOiBzdHJpbmcgPSBudWxsO1xuXG4gIC8qKlxuICAgKiBTZXQgdGhpcyBpbnB1dCBhcyBhbiBlLW1haWwgYW5kIHZhbGlkYXRlcyB0aGUgZS1tYWlsIHBhdHRlclxuICAgKi9cbiAgQElucHV0KCdlbWFpbCcpIGVtYWlsOiBib29sZWFuID0gbnVsbDtcblxuICAvKipcbiAgICogRGVmaW5lIHRoZSBtaW5pbXVtIGNoYXJhY3RlcnMgcXVhbnRpdHkgdGhpcyBpbnB1dCBzaG91bGQgYWNjZXB0XG4gICAqL1xuICBASW5wdXQoJ21pbkxlbmd0aCcpIG1pbkxlbmd0aDogc3RyaW5nIHwgbnVtYmVyID0gbnVsbDtcblxuICAvKipcbiAgICogRGVmaW5lIHRoZSBtYXhpbXVtIGNoYXJhY3RlcnMgcXVhbnRpdHkgdGhpcyBpbnB1dCBzaG91bGQgYWNjZXB0XG4gICAqL1xuICBASW5wdXQoJ21heExlbmd0aCcpIG1heExlbmd0aDogc3RyaW5nIHwgbnVtYmVyID0gbnVsbDtcblxuICAvKipcbiAgICogU2V0IGEgUmVndWxhciBFeHByZXNzaW9uIHRvIG1hdGNoIHRoZSBpbnB1dCB2YWx1ZSBhZ2FpbnN0IGFuZCBmYWlscyBpZiBub3QgbWF0Y2hcbiAgICovXG4gIEBJbnB1dCgncGF0dGVybicpIHBhdHRlcm46IHN0cmluZyB8IFJlZ0V4cCA9IG51bGw7XG5cbiAgLyoqXG4gICAqIFRoZSBldmVudCBuYW1lIGZvciBjb250cm9sIHRvIHVwZGF0ZSB1cG9uLlxuICAgKi9cbiAgQElucHV0KCd1cGRhdGVPbicpIHVwZGF0ZU9uOiAnY2hhbmdlJyB8ICdibHVyJyB8ICdzdWJtaXQnID0gbnVsbDtcblxuICAvKipcbiAgICogQ2FjaGUgdGhlIHZhbGlkYXRvcnMgdG8gZW5oYW5jZSB0aGUgcGVyZm9ybWFuY2VcbiAgICovXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuY29udHJvbE9wdGlvbnMgPSB0aGlzLmdlbmVyYXRlQ29udHJvbE9wdGlvbnMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZSB0aGUgY29udHJvbCBvcHRpb25zIGJhc2VkIG9uIHRoZSBwcm9wZXJ0aWVzIHNldCBpbiB0aGlzIGNvbXBvbmVudFxuICAgKi9cbiAgZ2VuZXJhdGVDb250cm9sT3B0aW9ucygpOiBOcmZDb250cm9sT3B0aW9ucyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHZhbGlkYXRvcnM6IE9iamVjdC5rZXlzKFZhbGlkYXRvcnMpXG4gICAgICAgIC5maWx0ZXIoKGtleSkgPT4gdGhpc1trZXldKVxuICAgICAgICAubWFwKChrZXkpID0+IFZhbGlkYXRvcnNba2V5XSksXG4gICAgICB1cGRhdGVPbjogdGhpcy51cGRhdGVPbixcbiAgICAgIGRpc2FibGVkOiB0aGlzLmRpc2FibGVkLFxuICAgIH07XG4gIH1cbn1cbiIsImltcG9ydCB7IEZvcm1Db250cm9sLCBGb3JtR3JvdXAgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmltcG9ydCB7IE5yZk5lc3RlZENvbnRyb2xEaXJlY3RpdmUgfSBmcm9tICcuL25lc3RlZC1jb250cm9sLmRpcmVjdGl2ZSc7XG5cbmV4cG9ydCBjbGFzcyBOcmZOZXN0ZWRDb250cm9sQ29udGV4dCB7XG4gICRpbXBsaWNpdDogRm9ybUNvbnRyb2w7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHVibGljIGZvcm1Db250cm9sOiBGb3JtQ29udHJvbCxcbiAgICBwdWJsaWMgZm9ybUdyb3VwOiBGb3JtR3JvdXAsXG4gICAgcHVibGljIG5yZk5lc3RlZENvbnRyb2w6IE5yZk5lc3RlZENvbnRyb2xEaXJlY3RpdmUsXG4gICkge1xuICAgIHRoaXMuJGltcGxpY2l0ID0gZm9ybUNvbnRyb2w7XG4gIH1cbn1cbiIsImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1BcnJheSwgRm9ybUNvbnRyb2wsIEZvcm1Hcm91cCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcblxuLyogdHNsaW50OmRpc2FibGUgdGVyLXBhZGRlZC1ibG9ja3MgKi9cblxuQEluamVjdGFibGUoKVxuLyoqXG4gKiBDb250cm9scyB0aGUgSGllcmFyY2h5IG9mIEZvcm1Hcm91cHMgYW5kIEZvcm1BcnJheXNcbiAqL1xuZXhwb3J0IGNsYXNzIE5yZkZvcm1IaWVyYXJjaHlTZXJ2aWNlIHtcbiAgLyoqXG4gICAqIEdldCBhIG5lc3RlZCBjb250cm9sIGlmIGl0IGV4aXN0cyBvciBjcmVhdGUgdGhlIGl0cyBuZWNlc3NhcnkgaGllcmFyY2h5XG4gICAqXG4gICAqIEBwYXJhbSBmdWxsUGF0aCBEb3Qgbm90YXRpb24gcGF0aCBvZiB0aGUgZGVzaXJlZCBjb250cm9sLCBpbmNsdWRpbmcgdGhlIGxhc3QgcGFydCwgdGhhdCBpcyB0aGUgdmFsdWUsIG5vdCB0aGUgZ3JvdXAuXG4gICAqL1xuICBnZXROZXN0ZWRDb250cm9sKHJvb3RGb3JtR3JvdXA6IEZvcm1Hcm91cCB8IEZvcm1BcnJheSwgZnVsbFBhdGg6IHN0cmluZyB8IHN0cmluZ1tdKTogRm9ybUdyb3VwIHwgRm9ybUFycmF5IHtcbiAgICBsZXQgcGFyZW50Q29udHJvbCA9IDxGb3JtR3JvdXAgfCBGb3JtQXJyYXk+cm9vdEZvcm1Hcm91cC5nZXQoZnVsbFBhdGgpO1xuXG4gICAgaWYgKCFwYXJlbnRDb250cm9sKSB7XG4gICAgICBjb25zdCBwYXRoUGllY2VzID0gQXJyYXkuaXNBcnJheShmdWxsUGF0aCkgPyBmdWxsUGF0aCA6IGZ1bGxQYXRoLnNwbGl0KCcuJyk7XG4gICAgICBwYXJlbnRDb250cm9sID0gcGF0aFBpZWNlcy5yZWR1Y2U8Rm9ybUdyb3VwIHwgRm9ybUFycmF5Pih0aGlzLmNyZWF0ZUZvcm1Hcm91cEhpZXJhcmNoeSwgcm9vdEZvcm1Hcm91cCk7XG4gICAgfVxuXG4gICAgaWYgKHBhcmVudENvbnRyb2wgaW5zdGFuY2VvZiBGb3JtQ29udHJvbCkge1xuICAgICAgcGFyZW50Q29udHJvbCA9IHBhcmVudENvbnRyb2wucGFyZW50O1xuICAgIH1cblxuICAgIHJldHVybiBwYXJlbnRDb250cm9sO1xuICB9XG5cbiAgLyoqXG4gICAqIEl0ZXJhdGUgb3ZlciBhbGwgcGF0aCBwaWVjZXMgY3JlYXRpbmcgdGhlIG5lZWRlZCBjb250cm9scyBpZiB0aGV5IGRvIG5vdCBleGlzdHMuXG4gICAqL1xuICBwcml2YXRlIGNyZWF0ZUZvcm1Hcm91cEhpZXJhcmNoeShcbiAgICBwYXJlbnRDb250cm9sOiBGb3JtR3JvdXAgfCBGb3JtQXJyYXksXG4gICAgcGF0aDogc3RyaW5nLFxuICAgIGluZGV4OiBudW1iZXIsXG4gICAgcGF0aFBpZWNlczogc3RyaW5nW10sXG4gICk6IEZvcm1Hcm91cCB8IEZvcm1BcnJheSB7XG4gICAgaWYgKGluZGV4ID09PSBwYXRoUGllY2VzLmxlbmd0aCAtIDEpIHtcbiAgICAgIHJldHVybiBwYXJlbnRDb250cm9sO1xuICAgIH1cblxuICAgIGxldCBjb250cm9sID0gPEZvcm1Hcm91cCB8IEZvcm1BcnJheT5wYXJlbnRDb250cm9sLmdldChwYXRoKTtcblxuICAgIGlmICghY29udHJvbCkge1xuICAgICAgY29uc3QgbmV4dFBhdGggPSBwYXRoUGllY2VzW2luZGV4ICsgMV0gfHwgcGF0aDtcblxuICAgICAgY29uc3QgaXNBcnJheSA9IG5leHRQYXRoICYmICFpc05hTig8YW55Pm5leHRQYXRoKTtcbiAgICAgIGNvbnRyb2wgPSBpc0FycmF5ID8gbmV3IEZvcm1BcnJheShbXSkgOiBuZXcgRm9ybUdyb3VwKHt9KTtcbiAgICB9XG5cbiAgICBpZiAocGFyZW50Q29udHJvbCBpbnN0YW5jZW9mIEZvcm1Hcm91cCkge1xuICAgICAgcGFyZW50Q29udHJvbC5hZGRDb250cm9sKHBhdGgsIGNvbnRyb2wpO1xuICAgIH0gZWxzZSBpZiAocGFyZW50Q29udHJvbCBpbnN0YW5jZW9mIEZvcm1BcnJheSkge1xuICAgICAgcGFyZW50Q29udHJvbC5pbnNlcnQocGFyc2VJbnQocGF0aCwgMTApIHx8IDAsIGNvbnRyb2wpO1xuICAgIH1cblxuICAgIHJldHVybiBjb250cm9sO1xuICB9XG59XG4iLCJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbi8qIHRzbGludDpkaXNhYmxlIHRlci1wYWRkZWQtYmxvY2tzICovXG5cbi8qKlxuICogQ2xhc3MgdG8gYWJzdHJhY3QgZ2V0IGFuZCBzZXQgdmFsdWVzIGZyb20gYW4gb2JqZWN0IG9yIGFuIGFycmF5XG4gKiB1c2luZyBkb3Qtbm90YXRpb24gc3RyaW5nIGFzIHRoZSBwYXRoIHRvIHRoZSBwcm9wZXJ0eVxuICpcbiAqL1xuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIE5yZk1vZGVsU2V0dGVyU2VydmljZSB7XG4gIC8qKlxuICAgKiBHZXQgYSB2YWx1ZSB1c2luZyBhIGRvdC1ub3RhdGlvbiBzdHJpbmcgdG8gZmluZCB0aGUgbmVzdGVkIHByb3BlcnR5XG4gICAqXG4gICAqIEBwYXJhbSBwYXRoIERvdCBub3RhdGlvbiBvZiB0aGUgdmFsdWUgdG8gYmUgZ2V0XG4gICAqIEBwYXJhbSBtb2RlbCBBbiBvYmplY3Qgb3IgYW4gQXJyYXlcbiAgICogQHBhcmFtIHNlcGFyYXRvciBBbiBvcHRpb25hbCBwYXJhbSB0byBzcGVjaWZ5IGEgZGlmZmVyZW50IHNlcGFyYXRvciwgZGVmYXVsdCAnLidcbiAgICpcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCBucmZFbnRpdHkgPSB7XG4gICAqICAgIHVzZXI6IHtcbiAgICogICAgICAgIG5hbWU6ICdKb2huIERvZSdcbiAgICogICAgfVxuICAgKiB9O1xuICAgKiBuZXN0ZWRQcm9wcy5nZXRWYWx1ZSgndXNlci5uYW1lJywgbnJmRW50aXR5KTtcbiAgICogLy8gPT4gJ0pvaG4gRG9lJ1xuICAgKlxuICAgKiBuZXN0ZWRQcm9wcy5nZXRWYWx1ZSgndXNlci5lbWFpbCcsIG5yZkVudGl0eSk7XG4gICAqIC8vID0+IG51bGxcbiAgICogYGBgXG4gICAqL1xuICBnZXRWYWx1ZShwYXRoOiBzdHJpbmcsIG1vZGVsOiBhbnkgfCBhbnlbXSwgc2VwYXJhdG9yID0gJy4nKTogYW55IHwgbnVsbCB7XG4gICAgaWYgKHBhdGggPT0gbnVsbCB8fCAhbW9kZWwpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBwYXRoUGllY2VzID0gdGhpcy5nZW5lcmF0ZVBhdGhQaWVjZXMocGF0aCwgc2VwYXJhdG9yKTtcbiAgICAgIHJldHVybiBwYXRoUGllY2VzLnJlZHVjZSh0aGlzLnBpZWNlc1JlZHVjZXIsIG1vZGVsKSB8fCBudWxsO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBpZ25vcmVcbiAgICpcbiAgICogUmV0dXJuIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHRvIHRoZSBnaXZlbiBrZXkuXG4gICAqXG4gICAqIElmIHRoZSBrZXkgaXMgZW1wdHksIHRoZSBsYXN0IGVsZW1lbnQgb2YgYW4gYXJyYXkgaXMgcmV0dXJuZWRcbiAgICovXG4gIHByaXZhdGUgcGllY2VzUmVkdWNlcihvYmo6IGFueVtdIHwgYW55LCBrZXk6IHN0cmluZyk6IGFueSB8IGFueVtdIHtcbiAgICByZXR1cm4ga2V5ID09PSAnJyA/IG9iai5zbGljZSgtMSlbMF0gOiBvYmpba2V5XTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgYSB2YWx1ZSB1c2luZyBhIGRvdC1ub3RhdGlvbiBzdHJpbmcuXG4gICAqXG4gICAqIElmIHRoZSBwcm9wZXJ0eSBkb2VzIG5vdCBleGlzdHMsIHRoZSBlbnRpcmUgcGF0aCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAqXG4gICAqIEBwYXJhbSBwYXRoIERvdCBub3RhdGlvbiBvZiB0aGUgdmFsdWUgdG8gYmUgZ2V0XG4gICAqIEBwYXJhbSB2YWx1ZSBUaGUgdmFsdWUgdG8gYmUgc2V0XG4gICAqIEBwYXJhbSBtb2RlbCBBbiBvYmplY3Qgb3IgYW4gQXJyYXlcbiAgICogQHBhcmFtIHNlcGFyYXRvciBBbiBvcHRpb25hbCBwYXJhbSB0byBzcGVjaWZ5IGEgZGlmZmVyZW50IHNlcGFyYXRvciwgZGVmYXVsdCAnLidcbiAgICpcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBuZXN0ZWRQcm9wcy5zZXRWYWx1ZSgndXNlci5hZ2UnLCAzNSwgeyB1c2VyOiB7IG5hbWU6ICdKb2huIERvZScgfSB9KTtcbiAgICogYGBgXG4gICAqL1xuICBzZXRWYWx1ZShwYXRoOiBzdHJpbmcsIHZhbHVlOiBhbnksIG1vZGVsOiBvYmplY3QgfCBhbnlbXSwgc2VwYXJhdG9yID0gJy4nKTogdm9pZCB7XG4gICAgLy8gVE9ETyByZW1vdmUgdGhlIGVtcHR5IGtleSBmZWF0dXJlLCBmb3JjZSB1c2VycyB0byBkZWZpbmUgdGhlIGRlc2lyZWQgYXJyYXkga2V5XG4gICAgaWYgKCEocGF0aCAmJiBtb2RlbCkpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBwYXRoUGllY2VzID0gdGhpcy5nZW5lcmF0ZVBhdGhQaWVjZXMocGF0aCwgc2VwYXJhdG9yKTtcbiAgICAgIGNvbnN0IGZpbmFsS2V5ID0gcGF0aFBpZWNlcy5wb3AoKTtcbiAgICAgICg8YW55PnBhdGhQaWVjZXMpWydmaW5hbEtleSddID0gZmluYWxLZXk7XG5cbiAgICAgIGNvbnN0IHRhcmdldFByb3AgPSBwYXRoUGllY2VzLnJlZHVjZSh0aGlzLmdldFRhcmdldFByb3BUb1NldCwgbW9kZWwpIHx8IG51bGw7XG5cbiAgICAgIGlmIChmaW5hbEtleSA9PT0gJycpIHtcbiAgICAgICAgdGFyZ2V0UHJvcC5wdXNoKHZhbHVlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRhcmdldFByb3BbZmluYWxLZXldID0gdmFsdWU7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdOZXN0ZWRQcm9wcyBzZXRWYWx1ZSBlcnJvcjogJywgZXJyKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBmaW5hbCBwcm9wZXJ0eSBvZiB0aGUgZG90IG5vdGF0aW9uIHBhdGguXG4gICAqIFRoaXMgd2lsbCBiZSB0aGUgcHJvcGVydHkgdGhhdCB3aWxsIHJlY2VpdmUgdGhlIG5ldyB2YWx1ZVxuICAgKi9cbiAgcHJpdmF0ZSBnZXRUYXJnZXRQcm9wVG9TZXQgPSAob2JqOiBhbnksIGtleTogc3RyaW5nLCBpOiBudW1iZXIsIHBhdGhQaWVjZXM6IGFueSk6IGFueVtdIHwgYW55ID0+IHtcbiAgICBsZXQgbmV4dEtleSA9IHBhdGhQaWVjZXNbaSArIDFdO1xuICAgIGNvbnN0IGlzTGFzdCA9IG5leHRLZXkgPT0gbnVsbDtcblxuICAgIG5leHRLZXkgPSBuZXh0S2V5IHx8IHBhdGhQaWVjZXNbJ2ZpbmFsS2V5J107XG5cbiAgICBjb25zdCBpc0FycmF5S2V5ID0gdGhpcy5pc0FycmF5S2V5KG5leHRLZXkpO1xuICAgIGxldCBwcm9wID0gb2JqW2tleV07XG5cbiAgICBpZiAoIXByb3ApIHtcbiAgICAgIHByb3AgPSBpc0FycmF5S2V5ID8gW10gOiB7fTtcbiAgICAgIG9ialtrZXldID0gcHJvcDtcbiAgICB9IGVsc2UgaWYgKGlzTGFzdCkge1xuICAgICAgcHJvcCA9IGlzQXJyYXlLZXkgPyBbLi4ucHJvcF0gOiB7IC4uLnByb3AgfTtcbiAgICAgIG9ialtrZXldID0gcHJvcDtcbiAgICB9XG5cbiAgICByZXR1cm4gcHJvcDtcbiAgfTtcblxuICAvKipcbiAgICogQGlnbm9yZVxuICAgKiBJbnRlcm5hbCBmdW5jdGlvbiB0byBkZWZpbmUgaWYgYSBnaXZlbiBrZXkgaXMgZm9yIGFuIGFycmF5IG9yIGFuIG9iamVjdFxuICAgKi9cbiAgcHJpdmF0ZSBpc0FycmF5S2V5KGtleTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGtleSA9PT0gJycgfHwgIWlzTmFOKHBhcnNlSW50KGtleSwgMTApKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZSB0aGUgZG90LW5vdGF0aW9uIHBhdGggYXMgYW4gQXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKi9cbiAgcHJpdmF0ZSBnZW5lcmF0ZVBhdGhQaWVjZXMocGF0aDogc3RyaW5nLCBzZXBhcmF0b3I6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gcGF0aFxuICAgICAgLnJlcGxhY2UoJ1snLCBzZXBhcmF0b3IpXG4gICAgICAucmVwbGFjZSgnXScsICcnKVxuICAgICAgLnNwbGl0KHNlcGFyYXRvcik7XG4gIH1cbn1cbiIsImltcG9ydCB7IERpcmVjdGl2ZSwgSW5wdXQsIE9uRGVzdHJveSwgT25Jbml0LCBPcHRpb25hbCwgT3V0cHV0LCBUZW1wbGF0ZVJlZiwgVmlld0NvbnRhaW5lclJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUFycmF5LCBGb3JtQ29udHJvbCwgRm9ybUdyb3VwIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQgeyBSZXBsYXlTdWJqZWN0IH0gZnJvbSAncnhqcy9pbnRlcm5hbC9SZXBsYXlTdWJqZWN0JztcbmltcG9ydCB7IHRha2VXaGlsZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHsgTnJmRm9ybURpcmVjdGl2ZSB9IGZyb20gJy4uL2Zvcm0vZm9ybS5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgTnJmRm9ybVNlcnZpY2UgfSBmcm9tICcuLi9mb3JtL2Zvcm0uc2VydmljZSc7XG5pbXBvcnQgeyBOcmZDb250cm9sT3B0aW9ucyB9IGZyb20gJy4vY29udHJvbC1vcHRpb25zLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBOcmZOZXN0ZWRDb250cm9sQ29udGV4dCB9IGZyb20gJy4vbmVzdGVkLWNvbnRyb2wtY29udGV4dC5jbGFzcyc7XG5pbXBvcnQgeyBOcmZGb3JtSGllcmFyY2h5U2VydmljZSB9IGZyb20gJy4vc2VydmljZXMvZm9ybS1oaWVyYXJjaHkuc2VydmljZSc7XG5pbXBvcnQgeyBOcmZNb2RlbFNldHRlclNlcnZpY2UgfSBmcm9tICcuL3NlcnZpY2VzL21vZGVsLXNldHRlci5zZXJ2aWNlJztcblxuLyogdHNsaW50OmRpc2FibGUgdGVyLXBhZGRlZC1ibG9ja3MgKi9cblxuLyoqXG4gKiBUaGlzIGRpcmVjdGl2ZSBjb250cm9sIG5lc3RlZCBpbnB1dHMgYW5kIHNldHMgdmFsdWVzIG9uIHRoZSBPcmlnaW5hbCBNb2RlbCBzZXQgYXQge0BsaW5rIE5yZkZvcm1EaXJlY3RpdmUjbnJmRW50aXR5fVxuICpcbiAqICMjIyMgR2l2ZW4gYW4gbnJmRW50aXR5IG9uIHRoZSBjb250cm9sbGVyOlxuICogYGBgdHlwZXNjcmlwdFxuICogdGhpcy51c2VyTW9kZWwgPSB7XG4gKiAgICBmaXJzdE5hbWU6ICdKb2huJyxcbiAqICAgIGFkZHJlc3M6IHtcbiAqICAgICAgICBzdHJlZXQ6ICdDYXJuYWJ5IFN0cmVldCdcbiAqICAgIH1cbiAqIH07XG4gKiBgYGBcbiAqXG4gKiAjIyMjIFVzZSBpdCBvbiB0aGUgZm9ybVxuICogYGBgaHRtbFxuICogPGZvcm0gW25yZkVudGl0eV09XCJ1c2VyTW9kZWxcIj5cbiAqICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAqICAgICAgPGxhYmVsIGZvcj1cIm5hbWVcIj5OYW1lOjwvbGFiZWw+XG4gKlxuICogICAgICA8ZGl2ICpucmZOZXN0ZWRDb250cm9sPVwiJ3VzZXJNb2RlbC5maXJzdE5hbWUnOyBsZXQgY29udHJvbD1mb3JtQ29udHJvbFwiPlxuICogICAgICAgIDxpbnB1dCBbZm9ybUNvbnRyb2xdPVwiY29udHJvbFwiIC8+XG4gKiAgICAgIDwvZGl2PlxuICogICA8L2Rpdj5cbiAqIDwvZm9ybT5cbiAqIGBgYFxuICovXG5ARGlyZWN0aXZlKHtcbiAgc2VsZWN0b3I6ICdbbnJmTmVzdGVkQ29udHJvbF0nLFxuICBleHBvcnRBczogJ25yZk5lc3RlZENvbnRyb2wnLFxufSlcbmV4cG9ydCBjbGFzcyBOcmZOZXN0ZWRDb250cm9sRGlyZWN0aXZlIGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuICBpc0Rlc3Ryb3llZCA9IGZhbHNlO1xuICBwYXJlbnRGb3JtR3JvdXA6IEZvcm1Hcm91cCB8IEZvcm1BcnJheTtcbiAgZm9ybUNvbnRyb2w6IEZvcm1Db250cm9sO1xuXG4gIC8qKlxuICAgKiBVc2VkIHRvIHNldCBhbmQgZ2V0IHZhbHVlIG9uIHRoZSBlbnRpdHkgbW9kZWxcbiAgICovXG4gIG1vZGVsUGF0aDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBcnJheSBmcm9tIG1vZGVsIHBhdGggc3BsaXQgYnkgJy4nXG4gICAqL1xuICBwcml2YXRlIG1vZGVsUGllY2VzOiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogVGhlIGxhc3QgcGFydCBvZiB0aGUgZG90LW5vdGF0aW9uIHBhdGggcHJvdmlkZWQgb24gW25yZk1vZGVsTmFtZV17QGxpbmsgbnJmTW9kZWxOYW1lfSBwcm9wZXJ0eS5cbiAgICogQ2FuIGJlIHVzZWQgd2l0aCBmb3JtQ29udHJvbE5hbWUgcHJvcGVydHlcbiAgICovXG4gIGNvbnRyb2xOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEhvbGRzIGFuIGluc3RhbmNlIG9mIGEgTnJmRm9ybSBvciBhIE5yZlNlcnZpY2UuXG4gICAqIElmIHRoZSBmb3JtIGlzIHdyYXBwZWQgaW5zaWRlIGEgZGlyZWN0aXZlIHdpdGggbmctY29udGVudCwgdGhlIE5yZkZvcm1TZXJ2aWNlIE1VU1QgYmUgcHJvdmlkZWQuXG4gICAqIE90aGVyd2lzZSB0aGUgbnJmRm9ybSB3aWxsIGJlIHVzZWQuXG4gICAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGZvcm1PclNlcnZpY2U6IE5yZkZvcm1EaXJlY3RpdmUgfCBOcmZGb3JtU2VydmljZTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IG1vZGVsU2V0dGVyOiBOcmZNb2RlbFNldHRlclNlcnZpY2UsXG4gICAgcHJpdmF0ZSByZWFkb25seSB0ZW1wbGF0ZVJlZjogVGVtcGxhdGVSZWY8YW55PixcbiAgICBwcml2YXRlIHJlYWRvbmx5IHZpZXdDb250YWluZXJSZWY6IFZpZXdDb250YWluZXJSZWYsXG4gICAgQE9wdGlvbmFsKCkgbnJmRm9ybTogTnJmRm9ybURpcmVjdGl2ZSxcbiAgICBAT3B0aW9uYWwoKSBucmZGb3JtU2VydmljZTogTnJmRm9ybVNlcnZpY2UsXG4gICAgcHJpdmF0ZSByZWFkb25seSBmb3JtSGllcmFyY2h5OiBOcmZGb3JtSGllcmFyY2h5U2VydmljZSxcbiAgKSB7XG4gICAgdGhpcy5mb3JtT3JTZXJ2aWNlID0gbnJmRm9ybVNlcnZpY2UgfHwgbnJmRm9ybTtcbiAgfVxuXG4gIC8vIHRzbGludDpkaXNhYmxlIG5vLWlucHV0LXJlbmFtZVxuICAvKipcbiAgICogVGhlIGRvdCBub3RhdGlvbiBmdWxsIG5hbWUgb2YgdGhlIG5yZkVudGl0eVxuICAgKi9cbiAgQElucHV0KCducmZOZXN0ZWRDb250cm9sJykgbnJmTW9kZWxOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFtBYnN0cmFjdENvbnRyb2xPcHRpb25zXXtAbGluayBodHRwczovL2FuZ3VsYXIuaW8vYXBpL2Zvcm1zL0Fic3RyYWN0Q29udHJvbE9wdGlvbnN9XG4gICAqIGNvbnRhaW5pbmcgdGhlIHZhbGlkYXRvcnMgbGlzdCBhbmQgdGhlIHVwZGF0ZS1vbiBzdHJhdGVneVxuICAgKlxuICAgKiBJdCB3aWxsIGJlIHNldCBvbiB0aGUgZm9ybUNvbnRyb2wgd2hpbGUgaW5pdGlhdGluZyBhIG5ldyBvbmUuXG4gICAqL1xuICBASW5wdXQoJ25yZk5lc3RlZENvbnRyb2xDb250cm9sT3B0aW9ucycpIGNvbnRyb2xPcHRpb25zOiBOcmZDb250cm9sT3B0aW9ucztcblxuICAvKipcbiAgICogRW1pdCByaWdodCBhZnRlciB0aGUgdmlldyB3ZXJlIHJlbmRlcmVkIGFuZCB0aGUgY29tcG9uZW50IGFuZCBpdHMgdmFyaWFibGVzIGFyYSBhdmFpbGFibGUuXG4gICAqL1xuICBAT3V0cHV0KCkgcmVhZG9ubHkgcmVhZHkkID0gbmV3IFJlcGxheVN1YmplY3QoMSk7XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVyIHRoaXMgaW5wdXQgY29tcG9uZW50IHRvIGl0cyBwYXJlbnQgZm9ybSBbRm9ybUdyb3VwXXtAbGluayBodHRwczovL2FuZ3VsYXIuaW8vYXBpL2Zvcm1zL0Zvcm1Hcm91cH1cbiAgICpcbiAgICogQW5kIHN0YXJ0cyB0byBlbWl0IHRoZSBpbnB1dCdzIHZhbHVlIHdoZW4gaXQgY2hhbmdlcy5cbiAgICovXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMubW9kZWxQYXRoID0gdGhpcy5nZXRNb2RlbFBhdGhXaXRob3V0Rmlyc3RQYXJ0KCk7XG4gICAgdGhpcy5tb2RlbFBpZWNlcyA9IHRoaXMubW9kZWxQYXRoICYmIHRoaXMubW9kZWxQYXRoLnNwbGl0KCcuJyk7XG4gICAgdGhpcy5jb250cm9sTmFtZSA9IHRoaXMuZ2V0Q29udHJvbE5hbWUoKTtcbiAgICB0aGlzLmZvcm1Db250cm9sID0gdGhpcy5nZXRGb3JtQ29udHJvbCgpO1xuICAgIHRoaXMucmVnaXN0ZXJUb0Zvcm1Hcm91cCgpO1xuICAgIHRoaXMuc3Vic2NyaWJlVG9VcGRhdGVFbnRpdHlWYWx1ZSgpO1xuICAgIHRoaXMuc2hvd1ZpZXdDb250ZW50KCk7XG4gICAgdGhpcy5lbWl0UmVhZHlTdGF0ZSgpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5pc0Rlc3Ryb3llZCA9IHRydWU7XG4gICAgdGhpcy5yZWFkeSQuY29tcGxldGUoKTtcblxuICAgIGlmICh0aGlzLnBhcmVudEZvcm1Hcm91cCkge1xuICAgICAgdGhpcy5yZW1vdmVGcm9tUGFyZW50Rm9ybUdyb3VwKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZW1vdmVGcm9tUGFyZW50Rm9ybUdyb3VwKCkge1xuICAgIGlmICh0aGlzLnBhcmVudEZvcm1Hcm91cCBpbnN0YW5jZW9mIEZvcm1Hcm91cCkge1xuICAgICAgdGhpcy5wYXJlbnRGb3JtR3JvdXAucmVtb3ZlQ29udHJvbCh0aGlzLm5yZk1vZGVsTmFtZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5wYXJlbnRGb3JtR3JvdXAuY29udHJvbHMuZmluZEluZGV4KChjb250cm9sOiBhbnkpID0+IHRoaXMuZm9ybUNvbnRyb2wgPT09IGNvbnRyb2wpO1xuICAgICAgdGhpcy5wYXJlbnRGb3JtR3JvdXAucmVtb3ZlQXQoaW5kZXgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIGRvdCBub3RhdGlvbiBwYXRoIG9mIHRoZSBFbnRpdHksIHdpdGhvdXQgdGhlIGZpcnN0IHBhcnQsXG4gICAqIGJlY2F1c2UgaXQgaXMgdGhlIEVudGl0eSBpdHNlbGYuXG4gICAqL1xuICBwcml2YXRlIGdldE1vZGVsUGF0aFdpdGhvdXRGaXJzdFBhcnQoKTogc3RyaW5nIHtcbiAgICBjb25zdCBtb2RlbE5hbWUgPSB0aGlzLm5yZk1vZGVsTmFtZTtcbiAgICByZXR1cm4gbW9kZWxOYW1lICYmIG1vZGVsTmFtZS5zdWJzdHIobW9kZWxOYW1lLmluZGV4T2YoJy4nKSArIDEpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGxhc3QgcGFydCBvZiB0aGUgZG90LW5vdGF0aW9uIHBhdGgsIHRoYXQgaW5kaWNhdGVzIHRoZSBjb250cm9sIG5hbWUgaXRzZWxmLlxuICAgKi9cbiAgcHJpdmF0ZSBnZXRDb250cm9sTmFtZSgpOiBzdHJpbmcge1xuICAgIGNvbnN0IG1vZGVsUGllY2VzID0gdGhpcy5tb2RlbFBpZWNlcztcbiAgICByZXR1cm4gbW9kZWxQaWVjZXMgJiYgbW9kZWxQaWVjZXNbbW9kZWxQaWVjZXMubGVuZ3RoIC0gMV07XG4gIH1cblxuICAvKipcbiAgICogSW5zdGFudGlhdGUgYSBuZXcgW0Zvcm1Db250cm9sXXtAbGluayBodHRwczovL2FuZ3VsYXIuaW8vYXBpL2Zvcm1zL0Zvcm1Db250cm9sfSBhbmQgcmV0dXJuIGl0XG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0TmV3Rm9ybUNvbnRyb2woKTogRm9ybUNvbnRyb2wge1xuICAgIGNvbnN0IGRpc2FibGVkID0gdGhpcy5jb250cm9sT3B0aW9ucyAmJiB0aGlzLmNvbnRyb2xPcHRpb25zLmRpc2FibGVkO1xuICAgIGNvbnN0IHZhbHVlID0gdGhpcy5nZXRJbml0aWFsVmFsdWUoKTtcblxuICAgIHJldHVybiBuZXcgRm9ybUNvbnRyb2woeyB2YWx1ZSwgZGlzYWJsZWQgfSwgdGhpcy5jb250cm9sT3B0aW9ucyk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSB2YWx1ZSBmcm9tIHRoZSBbbnJmRW50aXR5XXtAbGluayBOcmZGb3JtRGlyZWN0aXZlI25yZkVudGl0eX1cbiAgICovXG4gIHByb3RlY3RlZCBnZXRJbml0aWFsVmFsdWUoKTogYW55IHwgbnVsbCB7XG4gICAgaWYgKHRoaXMuZm9ybU9yU2VydmljZSAmJiB0aGlzLm1vZGVsUGF0aCkge1xuICAgICAgcmV0dXJuIHRoaXMubW9kZWxTZXR0ZXIuZ2V0VmFsdWUodGhpcy5tb2RlbFBhdGgsIHRoaXMuZm9ybU9yU2VydmljZS5mb3JtRGF0YSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBwcml2YXRlIHNob3dWaWV3Q29udGVudCgpIHtcbiAgICBjb25zdCBjb250ZXh0ID0gbmV3IE5yZk5lc3RlZENvbnRyb2xDb250ZXh0KFxuICAgICAgdGhpcy5mb3JtQ29udHJvbCxcbiAgICAgIHRoaXMuZm9ybU9yU2VydmljZSAmJiB0aGlzLmZvcm1PclNlcnZpY2UuZm9ybUdyb3VwLFxuICAgICAgdGhpcyxcbiAgICApO1xuXG4gICAgdGhpcy52aWV3Q29udGFpbmVyUmVmLmNyZWF0ZUVtYmVkZGVkVmlldyh0aGlzLnRlbXBsYXRlUmVmLCBjb250ZXh0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlciB0aGlzIGlucHV0IHRvIGl0cyBwYXJlbnQgW0Zvcm1Hcm91cF17QGxpbmsgaHR0cHM6Ly9hbmd1bGFyLmlvL2FwaS9mb3Jtcy9Gb3JtR3JvdXB9XG4gICAqIHRvIGVuYWJsZSB2YWxpZGF0aW9ucyBhbmQgZGF0YSBtYW5pcHVsYXRpb25cbiAgICovXG4gIHByaXZhdGUgcmVnaXN0ZXJUb0Zvcm1Hcm91cCgpIHtcbiAgICBpZiAodGhpcy5wYXJlbnRGb3JtR3JvdXApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnBhcmVudEZvcm1Hcm91cCA9IHRoaXMuZ2V0UGFyZW50Rm9ybUdyb3VwKCk7XG5cbiAgICBpZiAodGhpcy5wYXJlbnRGb3JtR3JvdXApIHtcbiAgICAgIGlmICh0aGlzLnBhcmVudEZvcm1Hcm91cCBpbnN0YW5jZW9mIEZvcm1Hcm91cCkge1xuICAgICAgICB0aGlzLnBhcmVudEZvcm1Hcm91cC5hZGRDb250cm9sKHRoaXMubW9kZWxQYXRoLCB0aGlzLmZvcm1Db250cm9sKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5jb250cm9sTmFtZTtcbiAgICAgICAgdGhpcy5wYXJlbnRGb3JtR3JvdXAuaW5zZXJ0KHBhcnNlSW50KGluZGV4LCAxMCksIHRoaXMuZm9ybUNvbnRyb2wpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBWZXJpZnkgaWYgdGhpcyBpbnB1dCBpcyBpbnNpZGUgYSBbTnJmRm9ybURpcmVjdGl2ZV17QGxpbmsgTnJmRm9ybURpcmVjdGl2ZX1cbiAgICogYW5kIHJldHVybiBpdHMgW0Zvcm1Hcm91cF17QGxpbmsgaHR0cHM6Ly9hbmd1bGFyLmlvL2FwaS9mb3Jtcy9Gb3JtR3JvdXB9XG4gICAqXG4gICAqIE90aGVyd2lzZSBhIG5ldyBlbXB0eSBbRm9ybUdyb3VwXXtAbGluayBodHRwczovL2FuZ3VsYXIuaW8vYXBpL2Zvcm1zL0Zvcm1Hcm91cH1cbiAgICovXG4gIHByaXZhdGUgZ2V0UGFyZW50Rm9ybUdyb3VwKCk6IEZvcm1Hcm91cCB8IEZvcm1BcnJheSB7XG4gICAgY29uc3Qgcm9vdEZvcm1Hcm91cCA9IHRoaXMuZm9ybU9yU2VydmljZSAmJiB0aGlzLmZvcm1PclNlcnZpY2UuZm9ybUdyb3VwO1xuXG4gICAgaWYgKCFyb290Rm9ybUdyb3VwIHx8ICF0aGlzLm1vZGVsUGF0aCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgY29uc3QgZm9ybUdyb3VwUGF0aCA9IEFycmF5LmZyb20odGhpcy5tb2RlbFBpZWNlcyk7XG4gICAgcmV0dXJuIHRoaXMuZm9ybUhpZXJhcmNoeS5nZXROZXN0ZWRDb250cm9sKHJvb3RGb3JtR3JvdXAsIGZvcm1Hcm91cFBhdGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZlcmlmeSBpZiB0aGUgW0Zvcm1Hcm91cF17QGxpbmsg