UNPKG

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

Version:
577 lines (557 loc) 89.2 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/forms'), require('rxjs/internal/ReplaySubject'), require('rxjs/operators'), require('@angular/common')) : typeof define === 'function' && define.amd ? define('@webdev-tools/ng-nested-reactive-forms', ['exports', '@angular/core', '@angular/forms', 'rxjs/internal/ReplaySubject', 'rxjs/operators', '@angular/common'], factory) : (factory((global['webdev-tools'] = global['webdev-tools'] || {}, global['webdev-tools']['ng-nested-reactive-forms'] = {}),global.ng.core,global.ng.forms,global.rxjs['internal/ReplaySubject'],global.rxjs.operators,global.ng.common)); }(this, (function (exports,core,forms,ReplaySubject,operators,common) { 'use strict'; 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 forms.FormGroup({}); this.submit$ = new core.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: core.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: core.Directive, args: [{ selector: '[nrfForm]', exportAs: 'nrfForm', },] } ]; NrfFormDirective.ctorParameters = function () { return [ { type: core.TemplateRef, decorators: [{ type: core.Optional }] }, { type: core.ViewContainerRef, decorators: [{ type: core.Optional }] }, { type: NrfFormService, decorators: [{ type: core.Optional }] }, { type: core.Renderer2 } ]; }; NrfFormDirective.propDecorators = { nrfEntity: [{ type: core.Input }], nrfSubmit: [{ type: core.Output }], formSubmitWrapper: [{ type: core.HostListener, args: ['submit', ['$event'],] }] }; return NrfFormDirective; }()); var NrfFormModule = (function () { function NrfFormModule() { } NrfFormModule.decorators = [ { type: core.NgModule, args: [{ imports: [forms.FormsModule, forms.ReactiveFormsModule], exports: [forms.FormsModule, forms.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(forms.Validators) .filter(function (key) { return _this[key]; }) .map(function (key) { return forms.Validators[key]; }), updateOn: this.updateOn, disabled: this.disabled, }; }; NrfControlOptionsComponent.propDecorators = { disabled: [{ type: core.Input, args: ['disabled',] }], min: [{ type: core.Input, args: ['min',] }], max: [{ type: core.Input, args: ['max',] }], required: [{ type: core.Input, args: ['required',] }], email: [{ type: core.Input, args: ['email',] }], minLength: [{ type: core.Input, args: ['minLength',] }], maxLength: [{ type: core.Input, args: ['maxLength',] }], pattern: [{ type: core.Input, args: ['pattern',] }], updateOn: [{ type: core.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 forms.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 forms.FormArray([]) : new forms.FormGroup({}); } if (parentControl instanceof forms.FormGroup) { parentControl.addControl(path, control); } else if (parentControl instanceof forms.FormArray) { parentControl.insert(parseInt(path, 10) || 0, control); } return control; }; NrfFormHierarchyService.decorators = [ { type: core.Injectable } ]; return NrfFormHierarchyService; }()); /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ var __assign = function () { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; function __read(o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; } function __spread() { for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); return ar; } 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: core.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.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 forms.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 forms.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 forms.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(operators.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: core.Directive, args: [{ selector: '[nrfNestedControl]', exportAs: 'nrfNestedControl', },] } ]; NrfNestedControlDirective.ctorParameters = function () { return [ { type: NrfModelSetterService }, { type: core.TemplateRef }, { type: core.ViewContainerRef }, { type: NrfFormDirective, decorators: [{ type: core.Optional }] }, { type: NrfFormService, decorators: [{ type: core.Optional }] }, { type: NrfFormHierarchyService } ]; }; NrfNestedControlDirective.propDecorators = { nrfModelName: [{ type: core.Input, args: ['nrfNestedControl',] }], controlOptions: [{ type: core.Input, args: ['nrfNestedControlControlOptions',] }], ready$: [{ type: core.Output }] }; return NrfNestedControlDirective; }()); var NrfModelModule = (function () { function NrfModelModule() { } NrfModelModule.decorators = [ { type: core.NgModule, args: [{ imports: [ common.CommonModule, ], providers: [ NrfModelSetterService, NrfFormHierarchyService, ], declarations: [ NrfNestedControlDirective, ], exports: [ NrfNestedControlDirective, ], },] } ]; return NrfModelModule; }()); var NrFormsModule = (function () { function NrFormsModule() { } NrFormsModule.decorators = [ { type: core.NgModule, args: [{ exports: [ NrfFormModule, NrfModelModule, ], },] } ]; return NrFormsModule; }()); exports.NrFormsModule = NrFormsModule; exports.cloneDeep = cloneDeep; exports.NrfFormDirective = NrfFormDirective; exports.NrfFormContext = NrfFormContext; exports.NrfSubmitData = NrfSubmitData; exports.NrfFormService = NrfFormService; exports.NRF_FORM_SERVICE_PROVIDER = NRF_FORM_SERVICE_PROVIDER; exports.NrfFormModule = NrfFormModule; exports.NrfNestedControlDirective = NrfNestedControlDirective; exports.NrfNestedControlContext = NrfNestedControlContext; exports.NrfModelSetterService = NrfModelSetterService; exports.NrfControlOptionsComponent = NrfControlOptionsComponent; exports.NrfFormHierarchyService = NrfFormHierarchyService; exports.NrfModelModule = NrfModelModule; exports.ɵa = newNrfFormService; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViZGV2LXRvb2xzLW5nLW5lc3RlZC1yZWFjdGl2ZS1mb3Jtcy51bWQuanMubWFwIiwic291cmNlcyI6WyJuZzovL0B3ZWJkZXYtdG9vbHMvbmctbmVzdGVkLXJlYWN0aXZlLWZvcm1zL2xpYi9mb3JtL2Zvcm0tY29udGV4dC5jbGFzcy50cyIsIm5nOi8vQHdlYmRldi10b29scy9uZy1uZXN0ZWQtcmVhY3RpdmUtZm9ybXMvbGliL2Zvcm0vZm9ybS1zdWJtaXQtZGF0YS5jbGFzcy50cyIsIm5nOi8vQHdlYmRldi10b29scy9uZy1uZXN0ZWQtcmVhY3RpdmUtZm9ybXMvbGliL3V0aWxzL2Nsb25lLWRlZXAudHMiLCJuZzovL0B3ZWJkZXYtdG9vbHMvbmctbmVzdGVkLXJlYWN0aXZlLWZvcm1zL2xpYi9mb3JtL2Zvcm0uc2VydmljZS50cyIsIm5nOi8vQHdlYmRldi10b29scy9uZy1uZXN0ZWQtcmVhY3RpdmUtZm9ybXMvbGliL2Zvcm0vZm9ybS5kaXJlY3RpdmUudHMiLCJuZzovL0B3ZWJkZXYtdG9vbHMvbmctbmVzdGVkLXJlYWN0aXZlLWZvcm1zL2xpYi9mb3JtL2Zvcm0ubW9kdWxlLnRzIiwibmc6Ly9Ad2ViZGV2LXRvb2xzL25nLW5lc3RlZC1yZWFjdGl2ZS1mb3Jtcy9saWIvbmVzdGVkLWNvbnRyb2wvY29udHJvbC1vcHRpb25zLmNvbXBvbmVudC50cyIsIm5nOi8vQHdlYmRldi10b29scy9uZy1uZXN0ZWQtcmVhY3RpdmUtZm9ybXMvbGliL25lc3RlZC1jb250cm9sL25lc3RlZC1jb250cm9sLWNvbnRleHQuY2xhc3MudHMiLCJuZzovL0B3ZWJkZXYtdG9vbHMvbmctbmVzdGVkLXJlYWN0aXZlLWZvcm1zL2xpYi9uZXN0ZWQtY29udHJvbC9zZXJ2aWNlcy9mb3JtLWhpZXJhcmNoeS5zZXJ2aWNlLnRzIiwibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsIm5nOi8vQHdlYmRldi10b29scy9uZy1uZXN0ZWQtcmVhY3RpdmUtZm9ybXMvbGliL25lc3RlZC1jb250cm9sL3NlcnZpY2VzL21vZGVsLXNldHRlci5zZXJ2aWNlLnRzIiwibmc6Ly9Ad2ViZGV2LXRvb2xzL25nLW5lc3RlZC1yZWFjdGl2ZS1mb3Jtcy9saWIvbmVzdGVkLWNvbnRyb2wvbmVzdGVkLWNvbnRyb2wuZGlyZWN0aXZlLnRzIiwibmc6Ly9Ad2ViZGV2LXRvb2xzL25nLW5lc3RlZC1yZWFjdGl2ZS1mb3Jtcy9saWIvbmVzdGVkLWNvbnRyb2wvbmVzdGVkLWNvbnRyb2wubW9kdWxlLnRzIiwibmc6Ly9Ad2ViZGV2LXRvb2xzL25nLW5lc3RlZC1yZWFjdGl2ZS1mb3Jtcy9saWIvZm9ybXMubW9kdWxlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEZvcm1Hcm91cCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcblxuaW1wb3J0IHsgTnJmRm9ybURpcmVjdGl2ZSB9IGZyb20gJy4vZm9ybS5kaXJlY3RpdmUnO1xuXG5leHBvcnQgY2xhc3MgTnJmRm9ybUNvbnRleHQge1xuICAkaW1wbGljaXQ6IE5yZkZvcm1EaXJlY3RpdmU7XG4gIGZvcm1Hcm91cDogRm9ybUdyb3VwO1xuXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBucmZGb3JtOiBOcmZGb3JtRGlyZWN0aXZlKSB7XG4gICAgdGhpcy4kaW1wbGljaXQgPSBucmZGb3JtO1xuICAgIHRoaXMuZm9ybUdyb3VwID0gbnJmRm9ybS5mb3JtR3JvdXA7XG4gIH1cbn1cbiIsImltcG9ydCB7IEZvcm1Hcm91cCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcblxuaW1wb3J0IHsgTnJmRm9ybURpcmVjdGl2ZSB9IGZyb20gJy4vZm9ybS5kaXJlY3RpdmUnO1xuXG5leHBvcnQgY2xhc3MgTnJmU3VibWl0RGF0YSB7XG4gIG5yZkZvcm06IE5yZkZvcm1EaXJlY3RpdmU7XG4gIGZvcm1EYXRhOiBhbnk7XG4gIGVudGl0eTogYW55O1xuICBmb3JtR3JvdXA6IEZvcm1Hcm91cDtcbiAgZXZlbnQ6IEV2ZW50O1xuXG4gIGNvbnN0cnVjdG9yKG5yZkZvcm06IE5yZkZvcm1EaXJlY3RpdmUsICRldmVudDogRXZlbnQpIHtcbiAgICB0aGlzLm5yZkZvcm0gPSBucmZGb3JtO1xuICAgIHRoaXMuZXZlbnQgPSAkZXZlbnQ7XG4gICAgdGhpcy5mb3JtRGF0YSA9IG5yZkZvcm0uZm9ybURhdGE7XG4gICAgdGhpcy5lbnRpdHkgPSBucmZGb3JtLm5yZkVudGl0eTtcbiAgICB0aGlzLmZvcm1Hcm91cCA9IG5yZkZvcm0uZm9ybUdyb3VwO1xuICB9XG59XG4iLCJleHBvcnQgZnVuY3Rpb24gY2xvbmVEZWVwKHRhcmdldDogYW55IHwgYW55W10pOiBhbnkge1xuICBpZiAoIXRhcmdldCB8fCB0eXBlb2YgdGFyZ2V0ICE9PSAnb2JqZWN0Jykge1xuICAgIHJldHVybiB0YXJnZXQ7XG4gIH1cblxuICBpZiAodGFyZ2V0IGluc3RhbmNlb2YgRGF0ZSkge1xuICAgIHJldHVybiBuZXcgRGF0ZSh0YXJnZXQpO1xuICB9XG5cbiAgaWYgKEFycmF5LmlzQXJyYXkodGFyZ2V0KSkge1xuICAgIHJldHVybiB0YXJnZXQubWFwKGNsb25lRGVlcCk7XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmtleXModGFyZ2V0KS5yZWR1Y2UoXG4gICAgKHByb3BzLCBrZXkpID0+IHtcbiAgICAgIHByb3BzW2tleV0gPSBjbG9uZURlZXAodGFyZ2V0W2tleV0pO1xuICAgICAgcmV0dXJuIHByb3BzO1xuICAgIH0sXG4gICAge30sXG4gICk7XG59XG4iLCJpbXBvcnQgeyBFdmVudEVtaXR0ZXIsIEluamVjdGFibGUsIFByb3ZpZGVyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGb3JtR3JvdXAgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmltcG9ydCB7IGNsb25lRGVlcCB9IGZyb20gJy4uL3V0aWxzL2Nsb25lLWRlZXAnO1xuaW1wb3J0IHsgTnJmU3VibWl0RGF0YSB9IGZyb20gJy4vZm9ybS1zdWJtaXQtZGF0YS5jbGFzcyc7XG5cbi8qIHRzbGludDpkaXNhYmxlIHRlci1wYWRkZWQtYmxvY2tzICovXG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBOcmZGb3JtU2VydmljZSB7XG4gIC8qKlxuICAgKiBGb3JtIGdyb3VwIHdpbGwgaG9sZCBhbGwgaW5wdXRzIHdpdGhpbiB0aGlzIGZvcm0uXG4gICAqXG4gICAqIEV2ZXJ5IGlucHV0IHNob3VsZCByZWdpc3RlciBpdHNlbGYgdG8gdGhpcyBmb3JtIGdyb3VwLlxuICAgKlxuICAgKiBUaGUgZGF0YSBpbiB0aGlzIGZvcm0gZ3JvdXAgd2lsbCBub3QgYmUgc2VudCB0byBiYWNrZW5kLCBqdXN0IGZvcm0gdmFsaWRhdGlvbnMgYW5kIGlucHV0IG1hbmFnZW1lbnQuXG4gICAqL1xuICByZWFkb25seSBmb3JtR3JvdXA6IEZvcm1Hcm91cCA9IG5ldyBGb3JtR3JvdXAoe30pO1xuXG4gIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTp2YXJpYWJsZS1uYW1lXG4gIHByaXZhdGUgcHJpdmF0ZUVudGl0eTogYW55O1xuXG4gIHNldCBlbnRpdHkoZW50aXR5OiBhbnkpIHtcbiAgICB0aGlzLnByaXZhdGVFbnRpdHkgPSBlbnRpdHk7XG4gICAgdGhpcy5mb3JtRGF0YSA9IGNsb25lRGVlcChlbnRpdHkpOyAvLyBUT0RPIG1lcmdlIHdpdGggZXhpc3RlbnQgZm9ybURhdGFcbiAgfVxuICBnZXQgZW50aXR5KCkge1xuICAgIHJldHVybiB0aGlzLnByaXZhdGVFbnRpdHk7XG4gIH1cblxuICAvKipcbiAgICogUmVwcmVzZW50cyB0aGUgZGF0YSBpbnB1dHRlZCBieSB0aGUgdXNlciBvbiB0aGUgZmllbGRzXG4gICAqL1xuICBmb3JtRGF0YTogYW55O1xuXG4gIC8qKlxuICAgKiBJbnRlcm5hbCBlbWl0dGVyIHRvIGhhbmRsZSBmb3JtIHN1Ym1pdFxuICAgKi9cbiAgcmVhZG9ubHkgc3VibWl0JCA9IG5ldyBFdmVudEVtaXR0ZXI8TnJmU3VibWl0RGF0YT4oKTtcbn1cblxuLyoqXG4gKiBAaWdub3JlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBuZXdOcmZGb3JtU2VydmljZSgpIHtcbiAgcmV0dXJuIG5ldyBOcmZGb3JtU2VydmljZSgpO1xufVxuXG4vKipcbiAqIFVzZSB0aGlzIHRvIHByb3ZpZGUgZm9ybS1zZXJ2aWNlIHRvIENvbXBvbmVudHMgdGhhdCB3cmFwcyBucmZGb3JtIGFuZCBwdXQgaW5wdXRzIGluc2lkZSA8bmctY29udGVudD5cbiAqL1xuZXhwb3J0IGNvbnN0IE5SRl9GT1JNX1NFUlZJQ0VfUFJPVklERVI6IFByb3ZpZGVyID0ge1xuICBwcm92aWRlOiBOcmZGb3JtU2VydmljZSxcbiAgdXNlRmFjdG9yeTogbmV3TnJmRm9ybVNlcnZpY2UsXG59O1xuIiwiaW1wb3J0IHtcbiAgRGlyZWN0aXZlLFxuICBFdmVudEVtaXR0ZXIsXG4gIEhvc3RMaXN0ZW5lcixcbiAgSW5wdXQsXG4gIE9uRGVzdHJveSxcbiAgT25Jbml0LFxuICBPcHRpb25hbCxcbiAgT3V0cHV0LFxuICBSZW5kZXJlcjIsXG4gIFRlbXBsYXRlUmVmLFxuICBWaWV3Q29udGFpbmVyUmVmLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1Hcm91cCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcblxuaW1wb3J0IHsgTnJmRm9ybUNvbnRleHQgfSBmcm9tICcuL2Zvcm0tY29udGV4dC5jbGFzcyc7XG5pbXBvcnQgeyBOcmZTdWJtaXREYXRhIH0gZnJvbSAnLi9mb3JtLXN1Ym1pdC1kYXRhLmNsYXNzJztcbmltcG9ydCB7IE5yZkZvcm1TZXJ2aWNlIH0gZnJvbSAnLi9mb3JtLnNlcnZpY2UnO1xuXG4vKiB0c2xpbnQ6ZGlzYWJsZTogdGVyLXBhZGRlZC1ibG9ja3MgKi9cbi8qKlxuICogQSBjb21wb25lbnQgdG8gYWJzdHJhY3QgdGhlIGZvcm0gaW1wbGVtZW50YXRpb25cbiAqXG4gKiBJdCBob2xkcyB0aGUgdmFsaWRhdGlvbiBhbmQgdGhlIHN1Ym1pdCBsb2dpY1xuICpcbiAqIEBleGFtcGxlXG4gKiA8Zm9ybSBucmZGb3JtIChucmZTdWJtaXQpPVwiYUNhbGxiYWNrKCRldmVudClcIj5cbiAqICAvLyBJbnB1dHNcbiAqIDwvZm9ybT5cbiAqL1xuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnW25yZkZvcm1dJyxcbiAgZXhwb3J0QXM6ICducmZGb3JtJyxcbn0pXG5leHBvcnQgY2xhc3MgTnJmRm9ybURpcmVjdGl2ZSBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgLyoqXG4gICAqIEBpZ25vcmVcbiAgICovXG4gIGNvbnN0cnVjdG9yKFxuICAgIEBPcHRpb25hbCgpIHByaXZhdGUgcmVhZG9ubHkgdGVtcGxhdGVSZWY6IFRlbXBsYXRlUmVmPGFueT4sXG4gICAgQE9wdGlvbmFsKCkgcHJpdmF0ZSByZWFkb25seSB2aWV3Q29udGFpbmVyUmVmOiBWaWV3Q29udGFpbmVyUmVmLFxuICAgIEBPcHRpb25hbCgpIHByaXZhdGUgcmVhZG9ubHkgZm9ybVNlcnZpY2U6IE5yZkZvcm1TZXJ2aWNlLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgcmVuZGVyZXI6IFJlbmRlcmVyMixcbiAgKSB7XG4gICAgaWYgKCFmb3JtU2VydmljZSkge1xuICAgICAgdGhpcy5mb3JtU2VydmljZSA9IG5ldyBOcmZGb3JtU2VydmljZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRzIGFuIEVudGl0eSBNb2RlbCB0aGF0IGNvbWVzIGZyb20gRGF0YWJhc2VcbiAgICovXG4gIEBJbnB1dCgpXG4gIHNldCBucmZFbnRpdHkoZW50aXR5OiBhbnkpIHtcbiAgICB0aGlzLmZvcm1TZXJ2aWNlLmVudGl0eSA9IGVudGl0eTtcbiAgfVxuICBnZXQgbnJmRW50aXR5KCk6IGFueSB7XG4gICAgcmV0dXJuIHRoaXMuZm9ybVNlcnZpY2UuZW50aXR5O1xuICB9XG5cbiAgZ2V0IGZvcm1EYXRhKCk6IGFueSB7XG4gICAgcmV0dXJuIHRoaXMuZm9ybVNlcnZpY2UuZm9ybURhdGE7XG4gIH1cblxuICBnZXQgZm9ybUdyb3VwKCk6IEZvcm1Hcm91cCB7XG4gICAgcmV0dXJuIHRoaXMuZm9ybVNlcnZpY2UuZm9ybUdyb3VwO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGNhbGxlZCB3aGVuIHRoZSBmb3JtIGlzIHZhbGlkIGFuZCBhIHN1Ym1pdCBldmVudCBpcyB0cmlnZ2VyZWRcbiAgICogYnkgYSBidXR0b24gY2xpY2sgb3IgcHJvZ3JhbW1hdGljYWxseS5cbiAgICovXG4gIEBPdXRwdXQoKVxuICBnZXQgbnJmU3VibWl0KCk6IEV2ZW50RW1pdHRlcjxOcmZTdWJtaXREYXRhPiB7XG4gICAgcmV0dXJuIHRoaXMuZm9ybVNlcnZpY2Uuc3VibWl0JDtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIEluaXQgYW4gZW1wdHkgbnJmRW50aXR5LCBpbiBjYXNlIG5vbmUgd2hlcmUgcHJvdmlkZWQuXG4gICAqL1xuICBuZ09uSW5pdCgpIHtcbiAgICBpZiAoIXRoaXMubnJmRW50aXR5KSB7XG4gICAgICB0aGlzLm5yZkVudGl0eSA9IHt9O1xuICAgIH1cblxuICAgIHRoaXMucmVuZGVyVmlldygpO1xuICB9XG5cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICB0aGlzLm5yZlN1Ym1pdC5jb21wbGV0ZSgpO1xuICB9XG5cblxuICBwcml2YXRlIHJlbmRlclZpZXcoKSB7XG4gICAgaWYgKHRoaXMudGVtcGxhdGVSZWYgJiYgdGhpcy52aWV3Q29udGFpbmVyUmVmKSB7XG4gICAgICBjb25zdCBlbWJlZGRlZFZpZXdSZWYgPSB0aGlzLnZpZXdDb250YWluZXJSZWYuY3JlYXRlRW1iZWRkZWRWaWV3KHRoaXMudGVtcGxhdGVSZWYsIG5ldyBOcmZGb3JtQ29udGV4dCh0aGlzKSk7XG4gICAgICBjb25zdCBmb3JtTmF0aXZlID0gZW1iZWRkZWRWaWV3UmVmLnJvb3ROb2Rlc1swXTtcbiAgICAgIHRoaXMucmVuZGVyZXIubGlzdGVuKGZvcm1OYXRpdmUsICdzdWJtaXQnLCBldmVudCA9PiB0aGlzLmZvcm1TdWJtaXRXcmFwcGVyKGV2ZW50KSk7XG4gICAgfVxuICB9XG5cblxuICAvKipcbiAgICogIyBTaG91bGQgbm90IGJlIGNhbGxlZCBkaXJlY3RseSFcbiAgICogVGhpcyBtZXRob2Qgd3JhcHMgdGhlIGZvcm0gdmFsaWRhdGlvbiBhbmQgY2FsbCBbbnJmU3VibWl0XXtAbGluayBOcmZGb3JtRGlyZWN0aXZlI25yZlN1Ym1pdH1cbiAgICovXG4gIEBIb3N0TGlzdGVuZXIoJ3N1Ym1pdCcsIFsnJGV2ZW50J10pXG4gIGZvcm1TdWJtaXRXcmFwcGVyKCRldmVudDogRXZlbnQpIHtcbiAgICAkZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgIGlmICghdGhpcy5mb3JtR3JvdXAudmFsaWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLm5yZlN1Ym1pdC5lbWl0KG5ldyBOcmZTdWJtaXREYXRhKHRoaXMsICRldmVudCkpO1xuICB9XG59XG4iLCJpbXBvcnQgeyBOZ01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybXNNb2R1bGUsIFJlYWN0aXZlRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmltcG9ydCB7IE5yZkZvcm1Db250ZXh0IH0gZnJvbSAnLi9mb3JtLWNvbnRleHQuY2xhc3MnO1xuaW1wb3J0IHsgTnJmU3VibWl0RGF0YSB9IGZyb20gJy4vZm9ybS1zdWJtaXQtZGF0YS5jbGFzcyc7XG5pbXBvcnQgeyBOcmZGb3JtRGlyZWN0aXZlIH0gZnJvbSAnLi9mb3JtLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBOUkZfRk9STV9TRVJWSUNFX1BST1ZJREVSLCBOcmZGb3JtU2VydmljZSB9IGZyb20gJy4vZm9ybS5zZXJ2aWNlJztcblxuZXhwb3J0IHsgTnJmRm9ybURpcmVjdGl2ZSwgTnJmRm9ybUNvbnRleHQsIE5yZlN1Ym1pdERhdGEsIE5yZkZvcm1TZXJ2aWNlLCBOUkZfRk9STV9TRVJWSUNFX1BST1ZJREVSIH07XG5cbi8qIHRzbGludDpkaXNhYmxlOiB0ZXItcGFkZGVkLWJsb2NrcyAqL1xuLyoqXG4gKiBUaGlzIG1vZHVsZSBvbmx5IGhhbmRsZSBmb3JtIEFic3RyYWN0aW9uIGFuZCBzdWJtaXQgaGFuZGxlclxuICogTm8gaW5wdXRzIGFyZSBwcm92aWRlZCBieSB0aGlzIG1vZHVsZS5cbiAqL1xuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW0Zvcm1zTW9kdWxlLCBSZWFjdGl2ZUZvcm1zTW9kdWxlXSxcbiAgZXhwb3J0czogW0Zvcm1zTW9kdWxlLCBSZWFjdGl2ZUZvcm1zTW9kdWxlLCBOcmZGb3JtRGlyZWN0aXZlXSxcbiAgZGVjbGFyYXRpb25zOiBbTnJmRm9ybURpcmVjdGl2ZV0sXG59KVxuZXhwb3J0IGNsYXNzIE5yZkZvcm1Nb2R1bGUge31cbiIsImltcG9ydCB7IElucHV0LCBPbkluaXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFic3RyYWN0Q29udHJvbE9wdGlvbnMsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbi8qIHRzbGludDpkaXNhYmxlOiB0ZXItcGFkZGVkLWJsb2NrcyAqL1xuXG5leHBvcnQgaW50ZXJmYWNlIE5yZkNvbnRyb2xPcHRpb25zIGV4dGVuZHMgQWJzdHJhY3RDb250cm9sT3B0aW9ucyB7XG4gIGRpc2FibGVkOiBib29sZWFuO1xufVxuXG4vLyB0c2xpbnQ6ZGlzYWJsZSBuby1pbnB1dC1yZW5hbWVcblxuLyoqXG4gKiBJbnB1dCB3cmFwcGVycyBjb21wb25lbnRzIHNob3VsZCBleHRlbmRzIHRoaXMgY2xhc3MgdG8gcGFzcyBjb25zdHJhaW50cyBkb3dud2FyZHNcbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIE5yZkNvbnRyb2xPcHRpb25zQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcbiAgLyoqXG4gICAqIEEgbGlzdCBvZiBWYWxpZGF0b3JzIHRvIHZhbGlkYXRlIHRoZSBpbnB1dCBhbmQgdGhlIHVwZGF0ZS1vbiBzdHJhdGVneVxuICAgKi9cbiAgY29udHJvbE9wdGlvbnM6IE5yZkNvbnRyb2xPcHRpb25zO1xuXG4gIC8qKlxuICAgKiBTZXRzIHRoaXMgaW5wdXQgdG8gcmVhZG9ubHkgYW5kIGJsb2NrIGFueSBjaGFuZ2VzXG4gICAqL1xuICBASW5wdXQoJ2Rpc2FibGVkJykgZGlzYWJsZWQ6IGJvb2xlYW4gPSBudWxsO1xuXG4gIC8qKlxuICAgKiBEZWZpbmUgdGhlIGxvd2VzdCBudW1iZXIgdmFsdWUgdGhhdCB0aGlzIGlucHV0IHNob3VsZCBhY2NlcHRcbiAgICovXG4gIEBJbnB1dCgnbWluJykgbWluOiBzdHJpbmcgfCBudW1iZXIgPSBudWxsO1xuXG4gIC8qKlxuICAgKiBEZWZpbmUgdGhlIG1heGltdW0gbnVtYmVyIHZhbHVlIHRoYXQgdGhpcyBpbnB1dCBzaG91bGQgYWNjZXB0XG4gICAqL1xuICBASW5wdXQoJ21heCcpIG1heDogc3RyaW5nIHwgbnVtYmVyID0gbnVsbDtcblxuICAvKipcbiAgICogU2V0IHRoaXMgaW5wdXQgYXMgcmVxdWlyZWQgYW5kIGZhaWxzIHdoZW4gZW1wdHlcbiAgICovXG4gIEBJbnB1dCgncmVxdWlyZWQnKSByZXF1aXJlZDogYm9vbGVhbiA9IG51bGw7XG5cbiAgLy8gQElucHV0KCdSZXF1aXJlZFRydWUnKSByZXF1aXJlZFRydWU6IHN0cmluZyA9IG51bGw7XG5cbiAgLyoqXG4gICAqIFNldCB0aGlzIGlucHV0IGFzIGFuIGUtbWFpbCBhbmQgdmFsaWRhdGVzIHRoZSBlLW1haWwgcGF0dGVyXG4gICAqL1xuICBASW5wdXQoJ2VtYWlsJykgZW1haWw6IGJvb2xlYW4gPSBudWxsO1xuXG4gIC8qKlxuICAgKiBEZWZpbmUgdGhlIG1pbmltdW0gY2hhcmFjdGVycyBxdWFudGl0eSB0aGlzIGlucHV0IHNob3VsZCBhY2NlcHRcbiAgICovXG4gIEBJbnB1dCgnbWluTGVuZ3RoJykgbWluTGVuZ3RoOiBzdHJpbmcgfCBudW1iZXIgPSBudWxsO1xuXG4gIC8qKlxuICAgKiBEZWZpbmUgdGhlIG1heGltdW0gY2hhcmFjdGVycyBxdWFudGl0eSB0aGlzIGlucHV0IHNob3VsZCBhY2NlcHRcbiAgICovXG4gIEBJbnB1dCgnbWF4TGVuZ3RoJykgbWF4TGVuZ3RoOiBzdHJpbmcgfCBudW1iZXIgPSBudWxsO1xuXG4gIC8qKlxuICAgKiBTZXQgYSBSZWd1bGFyIEV4cHJlc3Npb24gdG8gbWF0Y2ggdGhlIGlucHV0IHZhbHVlIGFnYWluc3QgYW5kIGZhaWxzIGlmIG5vdCBtYXRjaFxuICAgKi9cbiAgQElucHV0KCdwYXR0ZXJuJykgcGF0dGVybjogc3RyaW5nIHwgUmVnRXhwID0gbnVsbDtcblxuICAvKipcbiAgICogVGhlIGV2ZW50IG5hbWUgZm9yIGNvbnRyb2wgdG8gdXBkYXRlIHVwb24uXG4gICAqL1xuICBASW5wdXQoJ3VwZGF0ZU9uJykgdXBkYXRlT246ICdjaGFuZ2UnIHwgJ2JsdXInIHwgJ3N1Ym1pdCcgPSBudWxsO1xuXG4gIC8qKlxuICAgKiBDYWNoZSB0aGUgdmFsaWRhdG9ycyB0byBlbmhhbmNlIHRoZSBwZXJmb3JtYW5jZVxuICAgKi9cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5jb250cm9sT3B0aW9ucyA9IHRoaXMuZ2VuZXJhdGVDb250cm9sT3B0aW9ucygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlIHRoZSBjb250cm9sIG9wdGlvbnMgYmFzZWQgb24gdGhlIHByb3BlcnRpZXMgc2V0IGluIHRoaXMgY29tcG9uZW50XG4gICAqL1xuICBnZW5lcmF0ZUNvbnRyb2xPcHRpb25zKCk6IE5yZkNvbnRyb2xPcHRpb25zIHtcbiAgICByZXR1cm4ge1xuICAgICAgdmFsaWRhdG9yczogT2JqZWN0LmtleXMoVmFsaWRhdG9ycylcbiAgICAgICAgLmZpbHRlcigoa2V5KSA9PiB0aGlzW2tleV0pXG4gICAgICAgIC5tYXAoKGtleSkgPT4gVmFsaWRhdG9yc1trZXldKSxcbiAgICAgIHVwZGF0ZU9uOiB0aGlzLnVwZGF0ZU9uLFxuICAgICAgZGlzYWJsZWQ6IHRoaXMuZGlzYWJsZWQsXG4gICAgfTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgRm9ybUNvbnRyb2wsIEZvcm1Hcm91cCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcblxuaW1wb3J0IHsgTnJmTmVzdGVkQ29udHJvbERpcmVjdGl2ZSB9IGZyb20gJy4vbmVzdGVkLWNvbnRyb2wuZGlyZWN0aXZlJztcblxuZXhwb3J0IGNsYXNzIE5yZk5lc3RlZENvbnRyb2xDb250ZXh0IHtcbiAgJGltcGxpY2l0OiBGb3JtQ29udHJvbDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgZm9ybUNvbnRyb2w6IEZvcm1Db250cm9sLFxuICAgIHB1YmxpYyBmb3JtR3JvdXA6IEZvcm1Hcm91cCxcbiAgICBwdWJsaWMgbnJmTmVzdGVkQ29udHJvbDogTnJmTmVzdGVkQ29udHJvbERpcmVjdGl2ZSxcbiAgKSB7XG4gICAgdGhpcy4kaW1wbGljaXQgPSBmb3JtQ29udHJvbDtcbiAgfVxufVxuIiwiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUFycmF5LCBGb3JtQ29udHJvbCwgRm9ybUdyb3VwIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG4vKiB0c2xpbnQ6ZGlzYWJsZSB0ZXItcGFkZGVkLWJsb2NrcyAqL1xuXG5ASW5qZWN0YWJsZSgpXG4vKipcbiAqIENvbnRyb2xzIHRoZSBIaWVyYXJjaHkgb2YgRm9ybUdyb3VwcyBhbmQgRm9ybUFycmF5c1xuICovXG5leHBvcnQgY2xhc3MgTnJmRm9ybUhpZXJhcmNoeVNlcnZpY2Uge1xuICAvKipcbiAgICogR2V0IGEgbmVzdGVkIGNvbnRyb2wgaWYgaXQgZXhpc3RzIG9yIGNyZWF0ZSB0aGUgaXRzIG5lY2Vzc2FyeSBoaWVyYXJjaHlcbiAgICpcbiAgICogQHBhcmFtIGZ1bGxQYXRoIERvdCBub3RhdGlvbiBwYXRoIG9mIHRoZSBkZXNpcmVkIGNvbnRyb2wsIGluY2x1ZGluZyB0aGUgbGFzdCBwYXJ0LCB0aGF0IGlzIHRoZSB2YWx1ZSwgbm90IHRoZSBncm91cC5cbiAgICovXG4gIGdldE5lc3RlZENvbnRyb2wocm9vdEZvcm1Hcm91cDogRm9ybUdyb3VwIHwgRm9ybUFycmF5LCBmdWxsUGF0aDogc3RyaW5nIHwgc3RyaW5nW10pOiBGb3JtR3JvdXAgfCBGb3JtQXJyYXkge1xuICAgIGxldCBwYXJlbnRDb250cm9sID0gPEZvcm1Hcm91cCB8IEZvcm1BcnJheT5yb290Rm9ybUdyb3VwLmdldChmdWxsUGF0aCk7XG5cbiAgICBpZiAoIXBhcmVudENvbnRyb2wpIHtcbiAgICAgIGNvbnN0IHBhdGhQaWVjZXMgPSBBcnJheS5pc0FycmF5KGZ1bGxQYXRoKSA/IGZ1bGxQYXRoIDogZnVsbFBhdGguc3BsaXQoJy4nKTtcbiAgICAgIHBhcmVudENvbnRyb2wgPSBwYXRoUGllY2VzLnJlZHVjZTxGb3JtR3JvdXAgfCBGb3JtQXJyYXk+KHRoaXMuY3JlYXRlRm9ybUdyb3VwSGllcmFyY2h5LCByb290Rm9ybUdyb3VwKTtcbiAgICB9XG5cbiAgICBpZiAocGFyZW50Q29udHJvbCBpbnN0YW5jZW9mIEZvcm1Db250cm9sKSB7XG4gICAgICBwYXJlbnRDb250cm9sID0gcGFyZW50Q29udHJvbC5wYXJlbnQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHBhcmVudENvbnRyb2w7XG4gIH1cblxuICAvKipcbiAgICogSXRlcmF0ZSBvdmVyIGFsbCBwYXRoIHBpZWNlcyBjcmVhdGluZyB0aGUgbmVlZGVkIGNvbnRyb2xzIGlmIHRoZXkgZG8gbm90IGV4aXN0cy5cbiAgICovXG4gIHByaXZhdGUgY3JlYXRlRm9ybUdyb3VwSGllcmFyY2h5KFxuICAgIHBhcmVudENvbnRyb2w6IEZvcm1Hcm91cCB8IEZvcm1BcnJheSxcbiAgICBwYXRoOiBzdHJpbmcsXG4gICAgaW5kZXg6IG51bWJlcixcbiAgICBwYXRoUGllY2VzOiBzdHJpbmdbXSxcbiAgKTogRm9ybUdyb3VwIHwgRm9ybUFycmF5IHtcbiAgICBpZiAoaW5kZXggPT09IHBhdGhQaWVjZXMubGVuZ3RoIC0gMSkge1xuICAgICAgcmV0dXJuIHBhcmVudENvbnRyb2w7XG4gICAgfVxuXG4gICAgbGV0IGNvbnRyb2wgPSA8Rm9ybUdyb3VwIHwgRm9ybUFycmF5PnBhcmVudENvbnRyb2wuZ2V0KHBhdGgpO1xuXG4gICAgaWYgKCFjb250cm9sKSB7XG4gICAgICBjb25zdCBuZXh0UGF0aCA9IHBhdGhQaWVjZXNbaW5kZXggKyAxXSB8fCBwYXRoO1xuXG4gICAgICBjb25zdCBpc0FycmF5ID0gbmV4dFBhdGggJiYgIWlzTmFOKDxhbnk+bmV4dFBhdGgpO1xuICAgICAgY29udHJvbCA9IGlzQXJyYXkgPyBuZXcgRm9ybUFycmF5KFtdKSA6IG5ldyBGb3JtR3JvdXAoe30pO1xuICAgIH1cblxuICAgIGlmIChwYXJlbnRDb250cm9sIGluc3RhbmNlb2YgRm9ybUdyb3VwKSB7XG4gICAgICBwYXJlbnRDb250cm9sLmFkZENvbnRyb2wocGF0aCwgY29udHJvbCk7XG4gICAgfSBlbHNlIGlmIChwYXJlbnRDb250cm9sIGluc3RhbmNlb2YgRm9ybUFycmF5KSB7XG4gICAgICBwYXJlbnRDb250cm9sLmluc2VydChwYXJzZUludChwYXRoLCAxMCkgfHwgMCwgY29udHJvbCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbnRyb2w7XG4gIH1cbn1cbiIsIi8qISAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTsgeW91IG1heSBub3QgdXNlXHJcbnRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlXHJcbkxpY2Vuc2UgYXQgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXHJcblxyXG5USElTIENPREUgSVMgUFJPVklERUQgT04gQU4gKkFTIElTKiBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZXHJcbktJTkQsIEVJVEhFUiBFWFBSRVNTIE9SIElNUExJRUQsIElOQ0xVRElORyBXSVRIT1VUIExJTUlUQVRJT04gQU5ZIElNUExJRURcclxuV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIFRJVExFLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSxcclxuTUVSQ0hBTlRBQkxJVFkgT1IgTk9OLUlORlJJTkdFTUVOVC5cclxuXHJcblNlZSB0aGUgQXBhY2hlIFZlcnNpb24gMi4wIExpY2Vuc2UgZm9yIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9uc1xyXG5hbmQgbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlICovXHJcblxyXG52YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcclxuICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XHJcbiAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XHJcbiAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2V4dGVuZHMoZCwgYikge1xyXG4gICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxuICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxyXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xyXG59XHJcblxyXG5leHBvcnQgdmFyIF9fYXNzaWduID0gZnVuY3Rpb24oKSB7XHJcbiAgICBfX2Fzc2lnbiA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gX19hc3NpZ24odCkge1xyXG4gICAgICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xyXG4gICAgICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xyXG4gICAgICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpIHRbcF0gPSBzW3BdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdDtcclxuICAgIH1cclxuICAgIHJldHVybiBfX2Fzc2lnbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZXN0KHMsIGUpIHtcclxuICAgIHZhciB0ID0ge307XHJcbiAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkgJiYgZS5pbmRleE9mKHApIDwgMClcclxuICAgICAgICB0W3BdID0gc1twXTtcclxuICAgIGlmIChzICE9IG51bGwgJiYgdHlwZW9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMgPT09IFwiZnVuY3Rpb25cIilcclxuICAgICAgICBmb3IgKHZhciBpID0gMCwgcCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocyk7IGkgPCBwLmxlbmd0aDsgaSsrKSBpZiAoZS5pbmRleE9mKHBbaV0pIDwgMClcclxuICAgICAgICAgICAgdFtwW2ldXSA9IHNbcFtpXV07XHJcbiAgICByZXR1cm4gdDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcclxuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xyXG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcclxuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3BhcmFtKHBhcmFtSW5kZXgsIGRlY29yYXRvcikge1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uICh0YXJnZXQsIGtleSkgeyBkZWNvcmF0b3IodGFyZ2V0LCBrZXksIHBhcmFtSW5kZXgpOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX21ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKSB7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QubWV0YWRhdGEgPT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIFJlZmxlY3QubWV0YWRhdGEobWV0YWRhdGFLZXksIG1ldGFkYXRhVmFsdWUpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hd2FpdGVyKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xyXG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XHJcbiAgICAgICAgZnVuY3Rpb24gZnVsZmlsbGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yLm5leHQodmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxyXG4gICAgICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yW1widGhyb3dcIl0odmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxyXG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZShyZXN1bHQudmFsdWUpOyB9KS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XHJcbiAgICAgICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpO1xyXG4gICAgfSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2dlbmVyYXRvcih0aGlzQXJnLCBib2R5KSB7XHJcbiAgICB2YXIgXyA9IHsgbGFiZWw6IDAsIHNlbnQ6IGZ1bmN0aW9uKCkgeyBpZiAodFswXSAmIDEpIHRocm93IHRbMV07IHJldHVybiB0WzFdOyB9LCB0cnlzOiBbXSwgb3BzOiBbXSB9LCBmLCB5LCB0LCBnO1xyXG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHN0ZXAob3ApIHtcclxuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XHJcbiAgICAgICAgd2hpbGUgKF8pIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChmID0gMSwgeSAmJiAodCA9IG9wWzBdICYgMiA/IHlbXCJyZXR1cm5cIl0gOiBvcFswXSA/IHlbXCJ0aHJvd1wiXSB8fCAoKHQgPSB5W1wicmV0dXJuXCJdKSAmJiB0LmNhbGwoeSksIDApIDogeS5uZXh0KSAmJiAhKHQgPSB0LmNhbGwoeSwgb3BbMV0pKS5kb25lKSByZXR1cm4gdDtcclxuICAgICAgICAgICAgaWYgKHkgPSAwLCB0KSBvcCA9IFtvcFswXSAmIDIsIHQudmFsdWVdO1xyXG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDA6IGNhc2UgMTogdCA9IG9wOyBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgNDogXy5sYWJlbCsrOyByZXR1cm4geyB2YWx1ZTogb3BbMV0sIGRvbmU6IGZhbHNlIH07XHJcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDc6IG9wID0gXy5vcHMucG9wKCk7IF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gMyAmJiAoIXQgfHwgKG9wWzFdID4gdFswXSAmJiBvcFsxXSA8IHRbM10pKSkgeyBfLmxhYmVsID0gb3BbMV07IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSA2ICYmIF8ubGFiZWwgPCB0WzFdKSB7IF8ubGFiZWwgPSB0WzFdOyB0ID0gb3A7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0WzJdKSBfLm9wcy5wb3AoKTtcclxuICAgICAgICAgICAgICAgICAgICBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIG9wID0gYm9keS5jYWxsKHRoaXNBcmcsIF8pO1xyXG4gICAgICAgIH0gY2F0Y2ggKGUpIHsgb3AgPSBbNiwgZV07IHkgPSAwOyB9IGZpbmFsbHkgeyBmID0gdCA9IDA7IH1cclxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXhwb3J0U3RhcihtLCBleHBvcnRzKSB7XHJcbiAgICBmb3IgKHZhciBwIGluIG0pIGlmICghZXhwb3J0cy5oYXNPd25Qcm9wZXJ0eShwKSkgZXhwb3J0c1twXSA9IG1bcF07XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3ZhbHVlcyhvKSB7XHJcbiAgICB2YXIgbSA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl0sIGkgPSAwO1xyXG4gICAgaWYgKG0pIHJldHVybiBtLmNhbGwobyk7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICAgIG5leHQ6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKG8gJiYgaSA+PSBvLmxlbmd0aCkgbyA9IHZvaWQgMDtcclxuICAgICAgICAgICAgcmV0dXJuIHsgdmFsdWU6IG8gJiYgb1tpKytdLCBkb25lOiAhbyB9O1xyXG4gICAgICAgIH1cclxuICAgIH07XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3JlYWQobywgbikge1xyXG4gICAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb1tTeW1ib2wuaXRlcmF0b3JdO1xyXG4gICAgaWYgKCFtKSByZXR1cm4gbztcclxuICAgIHZhciBpID0gbS5jYWxsKG8pLCByLCBhciA9IFtdLCBlO1xyXG4gICAgdHJ5IHtcclxuICAgICAgICB3aGlsZSAoKG4gPT09IHZvaWQgMCB8fCBuLS0gPiAwKSAmJiAhKHIgPSBpLm5leHQoKSkuZG9uZSkgYXIucHVzaChyLnZhbHVlKTtcclxuICAgIH1cclxuICAgIGNhdGNoIChlcnJvcikgeyBlID0geyBlcnJvcjogZXJyb3IgfTsgfVxyXG4gICAgZmluYWxseSB7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKHIgJiYgIXIuZG9uZSAmJiAobSA9IGlbXCJyZXR1cm5cIl0pKSBtLmNhbGwoaSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGZpbmFsbHkgeyBpZiAoZSkgdGhyb3cgZS5lcnJvcjsgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIGFyO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19zcHJlYWQoKSB7XHJcbiAgICBmb3IgKHZhciBhciA9IFtdLCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKylcclxuICAgICAgICBhciA9IGFyLmNvbmNhdChfX3JlYWQoYXJndW1lbnRzW2ldKSk7XHJcbiAgICByZXR1cm4gYXI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2F3YWl0KHYpIHtcclxuICAgIHJldHVybiB0aGlzIGluc3RhbmNlb2YgX19hd2FpdCA/ICh0aGlzLnYgPSB2LCB0aGlzKSA6IG5ldyBfX2F3YWl0KHYpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hc3luY0dlbmVyYXRvcih0aGlzQXJnLCBfYXJndW1lbnRzLCBnZW5lcmF0b3IpIHtcclxuICAgIGlmICghU3ltYm9sLmFzeW5jSXRlcmF0b3IpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTeW1ib2wuYXN5bmNJd