UNPKG

@hxui/angular

Version:

* * *

523 lines 51.8 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ import { Directive, ElementRef, EventEmitter, HostListener, Input, Output, Renderer2, TemplateRef, ViewContainerRef } from '@angular/core'; import { NgControl } from '@angular/forms'; import { TypeaheadContainerComponent } from './typeahead-container.component'; import { getValueFromObject, latinize, tokenize } from './typeahead-utils'; import { Observable, from } from 'rxjs'; import { debounceTime, mergeMap, filter, toArray } from 'rxjs/operators'; import { TypeaheadMatch } from './typeahead-match.class'; import { ComponentLoaderFactory } from '../component-loader/component-loader.factory'; export class TypeaheadDirective { /** * @param {?} control * @param {?} viewContainerRef * @param {?} element * @param {?} renderer * @param {?} cis */ constructor(control, viewContainerRef, element, renderer, cis) { /** * minimal no of characters that needs to be entered before typeahead kicks-in. When set to 0, typeahead shows on focus with full list of options (limited as normal by typeaheadOptionsLimit) */ this.typeaheadMinLength = void 0; /** * should be used only in case of typeahead attribute is array. If true - loading of options will be async, otherwise - sync. true make sense if options array is large. */ this.typeaheadAsync = void 0; /** * match latin symbols. If true the word súper would match super and vice versa. */ this.typeaheadLatinize = true; /** * break words with spaces. If true the text "exact phrase" here match would match with match exact phrase here but not with phrase here exact match (kind of "google style"). */ this.typeaheadSingleWords = true; /** * should be used only in case typeaheadSingleWords attribute is true. Sets the word delimiter to break words. Defaults to space. */ this.typeaheadWordDelimiters = ' '; /** * should be used only in case typeaheadSingleWords attribute is true. Sets the word delimiter to match exact phrase. Defaults to simple and double quotes. */ this.typeaheadPhraseDelimiters = '\'"'; /** * fired when 'busy' state of this component was changed, fired on async mode only, returns boolean */ this.typeaheadLoading = new EventEmitter(); /** * fired on every key event and returns true in case of matches are not detected */ this.typeaheadNoResults = new EventEmitter(); /** * fired when option was selected, return object with data of this option */ this.typeaheadOnSelect = new EventEmitter(); /** * fired when blur event occurres. returns the active item */ this.typeaheadOnBlur = new EventEmitter(); this.isTypeaheadOptionsListActive = false; this.keyUpEventEmitter = new EventEmitter(); this.placement = 'bottom-left'; this.element = element; this.ngControl = control; this.viewContainerRef = viewContainerRef; this.renderer = renderer; this._typeahead = cis .createLoader(element, viewContainerRef, renderer); } /** * @param {?} e * @return {?} */ onChange(e) { if (this._container) { // esc if (e.keyCode === 27) { this.hide(); return; } // up if (e.keyCode === 38) { this._container.prevActiveMatch(); return; } // down if (e.keyCode === 40) { this._container.nextActiveMatch(); return; } // enter if (e.keyCode === 13) { this._container.selectActiveMatch(); return; } } // For `<input>`s, use the `value` property. For others that don't have a // `value` (such as `<span contenteditable="true">`, use `innerText`. /** @type {?} */ const value = e.target.value !== undefined ? e.target.value : e.target.innerText; if (value.trim().length >= this.typeaheadMinLength) { this.typeaheadLoading.emit(true); this.keyUpEventEmitter.emit(e.target.value); } else { this.typeaheadLoading.emit(false); this.typeaheadNoResults.emit(false); this.hide(); } } /** * @return {?} */ onFocus() { if (this.typeaheadMinLength === 0) { this.typeaheadLoading.emit(true); this.keyUpEventEmitter.emit(''); } } /** * @return {?} */ onBlur() { if (this._container && !this._container.isFocused) { this.typeaheadOnBlur.emit(this._container.active); this.hide(); } } /** * @param {?} e * @return {?} */ onKeydown(e) { // no container - no problems if (!this._container) { return; } // if items is visible - prevent form submition if (e.keyCode === 13) { e.preventDefault(); return; } } /** * @return {?} */ ngOnInit() { this.typeaheadOptionsLimit = this.typeaheadOptionsLimit || 20; this.typeaheadMinLength = this.typeaheadMinLength === void 0 ? 1 : this.typeaheadMinLength; this.typeaheadWaitMs = this.typeaheadWaitMs || 0; // async should be false in case of array if (this.typeaheadAsync === undefined && !(this.typeahead instanceof Observable)) { this.typeaheadAsync = false; } if (this.typeahead instanceof Observable) { this.typeaheadAsync = true; } if (this.typeaheadAsync) { this.asyncActions(); } else { this.syncActions(); } } /** * @param {?} match * @return {?} */ changeModel(match) { /** @type {?} */ const valueStr = match.value; this.ngControl.viewToModelUpdate(valueStr); ((/** @type {?} */ (this.ngControl.control))).setValue(valueStr); this.hide(); } /** * @return {?} */ get matches() { return this._matches; } /** * @return {?} */ show() { this._typeahead .attach(TypeaheadContainerComponent) // todo: add append to body, after updating positioning service .to(this.container) .position({ attachment: 'bottom left' }) .show({ typeaheadRef: this, placement: this.placement, animation: false }); this._container = this._typeahead.instance; this._container.parent = this; // This improves the speed as it won't have to be done for each list item /** @type {?} */ const normalizedQuery = (this.typeaheadLatinize ? latinize(this.ngControl.control.value) : this.ngControl.control.value).toString() .toLowerCase(); this._container.query = this.typeaheadSingleWords ? tokenize(normalizedQuery, this.typeaheadWordDelimiters, this.typeaheadPhraseDelimiters) : normalizedQuery; this._container.matches = this._matches; this.element.nativeElement.focus(); } /** * @return {?} */ hide() { if (this._typeahead.isShown) { this._typeahead.hide(); this._container = null; } } /** * @return {?} */ ngOnDestroy() { this._typeahead.dispose(); } /** * @return {?} */ asyncActions() { this.keyUpEventEmitter.pipe(debounceTime(this.typeaheadWaitMs), mergeMap(() => this.typeahead)).subscribe((matches) => { this.finalizeAsyncCall(matches); }, (err) => { console.error(err); }); } /** * @return {?} */ syncActions() { this.keyUpEventEmitter.pipe(debounceTime(this.typeaheadWaitMs), mergeMap((value) => { /** @type {?} */ const normalizedQuery = this.normalizeQuery(value); return from(this.typeahead).pipe(filter((option) => { return option && this.testMatch(this.normalizeOption(option), normalizedQuery); }), toArray()); })) .subscribe((matches) => { this.finalizeAsyncCall(matches); }, (err) => { console.error(err); }); } /** * @param {?} option * @return {?} */ normalizeOption(option) { /** @type {?} */ const optionValue = getValueFromObject(option, this.typeaheadOptionField); /** @type {?} */ const normalizedOption = this.typeaheadLatinize ? latinize(optionValue) : optionValue; return normalizedOption.toLowerCase(); } /** * @param {?} value * @return {?} */ normalizeQuery(value) { // If singleWords, break model here to not be doing extra work on each // iteration /** @type {?} */ let normalizedQuery = (this.typeaheadLatinize ? latinize(value) : value) .toString() .toLowerCase(); normalizedQuery = this.typeaheadSingleWords ? tokenize(normalizedQuery, this.typeaheadWordDelimiters, this.typeaheadPhraseDelimiters) : normalizedQuery; return normalizedQuery; } /** * @param {?} match * @param {?} test * @return {?} */ testMatch(match, test) { /** @type {?} */ let spaceLength; if (typeof test === 'object') { spaceLength = test.length; for (let i = 0; i < spaceLength; i += 1) { if (test[i].length > 0 && match.indexOf(test[i]) < 0) { return false; } } return true; } else { return match.indexOf(test) >= 0; } } /** * @param {?} matches * @return {?} */ finalizeAsyncCall(matches) { this.prepareMatches(matches); this.typeaheadLoading.emit(false); this.typeaheadNoResults.emit(!this.hasMatches()); if (!this.hasMatches()) { this.hide(); return; } if (this._container) { // This improves the speed as it won't have to be done for each list item /** @type {?} */ const normalizedQuery = (this.typeaheadLatinize ? latinize(this.ngControl.control.value) : this.ngControl.control.value).toString() .toLowerCase(); this._container.query = this.typeaheadSingleWords ? tokenize(normalizedQuery, this.typeaheadWordDelimiters, this.typeaheadPhraseDelimiters) : normalizedQuery; this._container.matches = this._matches; } else { this.show(); } } /** * @param {?} options * @return {?} */ prepareMatches(options) { /** @type {?} */ const limited = options.slice(0, this.typeaheadOptionsLimit); if (this.typeaheadGroupField) { /** @type {?} */ let matches = []; // extract all group names /** @type {?} */ const groups = limited .map((option) => getValueFromObject(option, this.typeaheadGroupField)) .filter((v, i, a) => a.indexOf(v) === i); groups.forEach((group) => { // add group header to array of matches matches.push(new TypeaheadMatch(group, group, true)); // add each item of group to array of matches matches = matches.concat(limited .filter((option) => getValueFromObject(option, this.typeaheadGroupField) === group) .map((option) => new TypeaheadMatch(option, getValueFromObject(option, this.typeaheadOptionField)))); }); this._matches = matches; } else { this._matches = limited.map((option) => new TypeaheadMatch(option, getValueFromObject(option, this.typeaheadOptionField))); } } /** * @return {?} */ hasMatches() { return this._matches.length > 0; } } TypeaheadDirective.decorators = [ { type: Directive, args: [{ selector: '[typeahead]', exportAs: 'hx-typeahead' },] }, ]; /** @nocollapse */ TypeaheadDirective.ctorParameters = () => [ { type: NgControl }, { type: ViewContainerRef }, { type: ElementRef }, { type: Renderer2 }, { type: ComponentLoaderFactory } ]; TypeaheadDirective.propDecorators = { typeahead: [{ type: Input }], typeaheadMinLength: [{ type: Input }], typeaheadWaitMs: [{ type: Input }], typeaheadOptionsLimit: [{ type: Input }], typeaheadOptionField: [{ type: Input }], typeaheadGroupField: [{ type: Input }], typeaheadAsync: [{ type: Input }], typeaheadLatinize: [{ type: Input }], typeaheadSingleWords: [{ type: Input }], typeaheadWordDelimiters: [{ type: Input }], typeaheadPhraseDelimiters: [{ type: Input }], typeaheadItemTemplate: [{ type: Input }], optionsListTemplate: [{ type: Input }], typeaheadLoading: [{ type: Output }], typeaheadNoResults: [{ type: Output }], typeaheadOnSelect: [{ type: Output }], typeaheadOnBlur: [{ type: Output }], container: [{ type: Input }], onChange: [{ type: HostListener, args: ['keyup', ['$event'],] }], onFocus: [{ type: HostListener, args: ['focus',] }], onBlur: [{ type: HostListener, args: ['blur',] }], onKeydown: [{ type: HostListener, args: ['keydown', ['$event'],] }] }; if (false) { /** * options source, can be Array of strings, objects or an Observable for external matching process * @type {?} */ TypeaheadDirective.prototype.typeahead; /** * minimal no of characters that needs to be entered before typeahead kicks-in. When set to 0, typeahead shows on focus with full list of options (limited as normal by typeaheadOptionsLimit) * @type {?} */ TypeaheadDirective.prototype.typeaheadMinLength; /** * minimal wait time after last character typed before typeahead kicks-in * @type {?} */ TypeaheadDirective.prototype.typeaheadWaitMs; /** * maximum length of options items list * @type {?} */ TypeaheadDirective.prototype.typeaheadOptionsLimit; /** * when options source is an array of objects, the name of field that contains the options value, we use array item as option in case of this field is missing. Supports nested properties and methods. * @type {?} */ TypeaheadDirective.prototype.typeaheadOptionField; /** * when options source is an array of objects, the name of field that contains the group value, matches are grouped by this field when set. * @type {?} */ TypeaheadDirective.prototype.typeaheadGroupField; /** * should be used only in case of typeahead attribute is array. If true - loading of options will be async, otherwise - sync. true make sense if options array is large. * @type {?} */ TypeaheadDirective.prototype.typeaheadAsync; /** * match latin symbols. If true the word súper would match super and vice versa. * @type {?} */ TypeaheadDirective.prototype.typeaheadLatinize; /** * break words with spaces. If true the text "exact phrase" here match would match with match exact phrase here but not with phrase here exact match (kind of "google style"). * @type {?} */ TypeaheadDirective.prototype.typeaheadSingleWords; /** * should be used only in case typeaheadSingleWords attribute is true. Sets the word delimiter to break words. Defaults to space. * @type {?} */ TypeaheadDirective.prototype.typeaheadWordDelimiters; /** * should be used only in case typeaheadSingleWords attribute is true. Sets the word delimiter to match exact phrase. Defaults to simple and double quotes. * @type {?} */ TypeaheadDirective.prototype.typeaheadPhraseDelimiters; /** * used to specify a custom item template. Template variables exposed are called item and index; * @type {?} */ TypeaheadDirective.prototype.typeaheadItemTemplate; /** * used to specify a custom options list template. Template variables: matches, itemTemplate, query * @type {?} */ TypeaheadDirective.prototype.optionsListTemplate; /** * fired when 'busy' state of this component was changed, fired on async mode only, returns boolean * @type {?} */ TypeaheadDirective.prototype.typeaheadLoading; /** * fired on every key event and returns true in case of matches are not detected * @type {?} */ TypeaheadDirective.prototype.typeaheadNoResults; /** * fired when option was selected, return object with data of this option * @type {?} */ TypeaheadDirective.prototype.typeaheadOnSelect; /** * fired when blur event occurres. returns the active item * @type {?} */ TypeaheadDirective.prototype.typeaheadOnBlur; /** * A selector specifying the element the typeahead should be appended to. * Currently only supports "body". * @type {?} */ TypeaheadDirective.prototype.container; /** * if false don't focus the input element the typeahead directive is associated with on selection * @type {?} */ TypeaheadDirective.prototype._container; /** @type {?} */ TypeaheadDirective.prototype.isTypeaheadOptionsListActive; /** @type {?} */ TypeaheadDirective.prototype.keyUpEventEmitter; /** @type {?} */ TypeaheadDirective.prototype._matches; /** @type {?} */ TypeaheadDirective.prototype.placement; /** @type {?} */ TypeaheadDirective.prototype.ngControl; /** @type {?} */ TypeaheadDirective.prototype.viewContainerRef; /** @type {?} */ TypeaheadDirective.prototype.element; /** @type {?} */ TypeaheadDirective.prototype.renderer; /** @type {?} */ TypeaheadDirective.prototype._typeahead; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZWFoZWFkLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL0BoeHVpL2FuZ3VsYXIvIiwic291cmNlcyI6WyJsaWIvdHlwZWFoZWFkL3R5cGVhaGVhZC5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUN4RCxNQUFNLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxnQkFBZ0IsRUFDakQsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFlLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3hELE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzlFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFM0UsT0FBTyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDeEMsT0FBTyxFQUFFLFlBQVksRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3pFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSw4Q0FBOEMsQ0FBQztBQUl0RixNQUFNLE9BQU8sa0JBQWtCOzs7Ozs7OztJQWlKN0IsWUFBbUIsT0FBa0IsRUFBRSxnQkFBa0MsRUFBRSxPQUFtQixFQUFFLFFBQW1CLEVBQUUsR0FBMkI7Ozs7UUE3SWhJLHVCQUFrQixHQUFXLEtBQUssQ0FBQyxDQUFDOzs7O1FBVXBDLG1CQUFjLEdBQVksS0FBSyxDQUFDLENBQUM7Ozs7UUFFakMsc0JBQWlCLEdBQUcsSUFBSSxDQUFDOzs7O1FBRXpCLHlCQUFvQixHQUFHLElBQUksQ0FBQzs7OztRQUU1Qiw0QkFBdUIsR0FBRyxHQUFH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QU07aUNBRU4sTUFBTTtnQ0FFTixNQUFNOzhCQUVOLE1BQU07d0JBTU4sS0FBSzt1QkErQkwsWUFBWSxTQUFDLE9BQU8sRUFBRSxDQUFDLFFBQVEsQ0FBQztzQkEyQ2hDLFlBQVksU0FBQyxPQUFPO3FCQVFwQixZQUFZLFNBQUMsTUFBTTt3QkFRbkIsWUFBWSxTQUFDLFNBQVMsRUFBRSxDQUFDLFFBQVEsQ0FBQzs7Ozs7OztJQWpJbkMsdUNBQStCOzs7OztJQUUvQixnREFBb0Q7Ozs7O0lBRXBELDZDQUF3Qzs7Ozs7SUFFeEMsbURBQThDOzs7OztJQUU5QyxrREFBNkM7Ozs7O0lBRTdDLGlEQUE0Qzs7Ozs7SUFFNUMsNENBQWlEOzs7OztJQUVqRCwrQ0FBeUM7Ozs7O0lBRXpDLGtEQUE0Qzs7Ozs7SUFFNUMscURBQThDOzs7OztJQUU5Qyx1REFBa0Q7Ozs7O0lBRWxELG1EQUF3RDs7Ozs7SUFFeEQsaURBQXNEOzs7OztJQUd0RCw4Q0FBOEU7Ozs7O0lBRTlFLGdEQUFnRjs7Ozs7SUFFaEYsK0NBQXNGOzs7OztJQUV0Riw2Q0FBeUU7Ozs7OztJQU16RSx1Q0FBa0M7Ozs7O0lBZ0JsQyx3Q0FBK0M7O0lBQy9DLDBEQUE0Qzs7SUFFNUMsK0NBQW9FOztJQUNwRSxzQ0FBcUM7O0lBQ3JDLHVDQUFvQzs7SUFHcEMsdUNBQStCOztJQUMvQiw4Q0FBNkM7O0lBQzdDLHFDQUE4Qjs7SUFDOUIsc0NBQThCOztJQUU5Qix3Q0FBaUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIERpcmVjdGl2ZSwgRWxlbWVudFJlZiwgRXZlbnRFbWl0dGVyLCBIb3N0TGlzdGVuZXIsIElucHV0LCBPbkRlc3Ryb3ksIE9uSW5pdCxcclxuICBPdXRwdXQsIFJlbmRlcmVyMiwgVGVtcGxhdGVSZWYsIFZpZXdDb250YWluZXJSZWZcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgRm9ybUNvbnRyb2wsIE5nQ29udHJvbCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0IHsgVHlwZWFoZWFkQ29udGFpbmVyQ29tcG9uZW50IH0gZnJvbSAnLi90eXBlYWhlYWQtY29udGFpbmVyLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IGdldFZhbHVlRnJvbU9iamVjdCwgbGF0aW5pemUsIHRva2VuaXplIH0gZnJvbSAnLi90eXBlYWhlYWQtdXRpbHMnO1xyXG5cclxuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgZnJvbSB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBkZWJvdW5jZVRpbWUsIG1lcmdlTWFwLCBmaWx0ZXIsIHRvQXJyYXkgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcbmltcG9ydCB7IFR5cGVhaGVhZE1hdGNoIH0gZnJvbSAnLi90eXBlYWhlYWQtbWF0Y2guY2xhc3MnO1xyXG5pbXBvcnQgeyBDb21wb25lbnRMb2FkZXJGYWN0b3J5IH0gZnJvbSAnLi4vY29tcG9uZW50LWxvYWRlci9jb21wb25lbnQtbG9hZGVyLmZhY3RvcnknO1xyXG5pbXBvcnQgeyBDb21wb25lbnRMb2FkZXIgfSBmcm9tICcuLi9jb21wb25lbnQtbG9hZGVyL2NvbXBvbmVudC1sb2FkZXIuY2xhc3MnO1xyXG5cclxuQERpcmVjdGl2ZSh7c2VsZWN0b3I6ICdbdHlwZWFoZWFkXScsIGV4cG9ydEFzOiAnaHgtdHlwZWFoZWFkJ30pXHJcbmV4cG9ydCBjbGFzcyBUeXBlYWhlYWREaXJlY3RpdmUgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XHJcbiAgLyoqIG9wdGlvbnMgc291cmNlLCBjYW4gYmUgQXJyYXkgb2Ygc3RyaW5ncywgb2JqZWN0cyBvciBhbiBPYnNlcnZhYmxlIGZvciBleHRlcm5hbCBtYXRjaGluZyBwcm9jZXNzICovXHJcbiAgQElucHV0KCkgcHVibGljIHR5cGVhaGVhZDogYW55O1xyXG4gIC8qKiBtaW5pbWFsIG5vIG9mIGNoYXJhY3RlcnMgdGhhdCBuZWVkcyB0byBiZSBlbnRlcmVkIGJlZm9yZSB0eXBlYWhlYWQga2lja3MtaW4uIFdoZW4gc2V0IHRvIDAsIHR5cGVhaGVhZCBzaG93cyBvbiBmb2N1cyB3aXRoIGZ1bGwgbGlzdCBvZiBvcHRpb25zIChsaW1pdGVkIGFzIG5vcm1hbCBieSB0eXBlYWhlYWRPcHRpb25zTGltaXQpICovXHJcbiAgQElucHV0KCkgcHVibGljIHR5cGVhaGVhZE1pbkxlbmd0aDogbnVtYmVyID0gdm9pZCAwO1xyXG4gIC8qKiBtaW5pbWFsIHdhaXQgdGltZSBhZnRlciBsYXN0IGNoYXJhY3RlciB0eXBlZCBiZWZvcmUgdHlwZWFoZWFkIGtpY2tzLWluICovXHJcbiAgQElucHV0KCkgcHVibGljIHR5cGVhaGVhZFdhaXRNczogbnVtYmVyO1xyXG4gIC8qKiBtYXhpbXVtIGxlbmd0aCBvZiBvcHRpb25zIGl0ZW1zIGxpc3QgKi9cclxuICBASW5wdXQoKSBwdWJsaWMgdHlwZWFoZWFkT3B0aW9uc0xpbWl0OiBudW1iZXI7XHJcbiAgLyoqIHdoZW4gb3B0aW9ucyBzb3VyY2UgaXMgYW4gYXJyYXkgb2Ygb2JqZWN0cywgdGhlIG5hbWUgb2YgZmllbGQgdGhhdCBjb250YWlucyB0aGUgb3B0aW9ucyB2YWx1ZSwgd2UgdXNlIGFycmF5IGl0ZW0gYXMgb3B0aW9uIGluIGNhc2Ugb2YgdGhpcyBmaWVsZCBpcyBtaXNzaW5nLiBTdXBwb3J0cyBuZXN0ZWQgcHJvcGVydGllcyBhbmQgbWV0aG9kcy4gKi9cclxuICBASW5wdXQoKSBwdWJsaWMgdHlwZWFoZWFkT3B0aW9uRmllbGQ6IHN0cmluZztcclxuICAvKiogd2hlbiBvcHRpb25zIHNvdXJjZSBpcyBhbiBhcnJheSBvZiBvYmplY3RzLCB0aGUgbmFtZSBvZiBmaWVsZCB0aGF0IGNvbnRhaW5zIHRoZSBncm91cCB2YWx1ZSwgbWF0Y2hlcyBhcmUgZ3JvdXBlZCBieSB0aGlzIGZpZWxkIHdoZW4gc2V0LiAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyB0eXBlYWhlYWRHcm91cEZpZWxkOiBzdHJpbmc7XHJcbiAgLyoqIHNob3VsZCBiZSB1c2VkIG9ubHkgaW4gY2FzZSBvZiB0eXBlYWhlYWQgYXR0cmlidXRlIGlzIGFycmF5LiBJZiB0cnVlIC0gbG9hZGluZyBvZiBvcHRpb25zIHdpbGwgYmUgYXN5bmMsIG90aGVyd2lzZSAtIHN5bmMuIHRydWUgbWFrZSBzZW5zZSBpZiBvcHRpb25zIGFycmF5IGlzIGxhcmdlLiAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyB0eXBlYWhlYWRBc3luYzogYm9vbGVhbiA9IHZvaWQgMDtcclxuICAvKiogbWF0Y2ggbGF0aW4gc3ltYm9scy4gSWYgdHJ1ZSB0aGUgd29yZCBzw7pwZXIgd291bGQgbWF0Y2ggc3VwZXIgYW5kIHZpY2UgdmVyc2EuICovXHJcbiAgQElucHV0KCkgcHVibGljIHR5cGVhaGVhZExhdGluaXplID0gdHJ1ZTtcclxuICAvKiogYnJlYWsgd29yZHMgd2l0aCBzcGFjZXMuIElmIHRydWUgdGhlIHRleHQgXCJleGFjdCBwaHJhc2VcIiBoZXJlIG1hdGNoIHdvdWxkIG1hdGNoIHdpdGggbWF0Y2ggZXhhY3QgcGhyYXNlIGhlcmUgYnV0IG5vdCB3aXRoIHBocmFzZSBoZXJlIGV4YWN0IG1hdGNoIChraW5kIG9mIFwiZ29vZ2xlIHN0eWxlXCIpLiAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyB0eXBlYWhlYWRTaW5nbGVXb3JkcyA9IHRydWU7XHJcbiAgLyoqIHNob3VsZCBiZSB1c2VkIG9ubHkgaW4gY2FzZSB0eXBlYWhlYWRTaW5nbGVXb3JkcyBhdHRyaWJ1dGUgaXMgdHJ1ZS4gU2V0cyB0aGUgd29yZCBkZWxpbWl0ZXIgdG8gYnJlYWsgd29yZHMuIERlZmF1bHRzIHRvIHNwYWNlLiAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyB0eXBlYWhlYWRXb3JkRGVsaW1pdGVycyA9ICcgJztcclxuICAvKiogc2hvdWxkIGJlIHVzZWQgb25seSBpbiBjYXNlIHR5cGVhaGVhZFNpbmdsZVdvcmRzIGF0dHJpYnV0ZSBpcyB0cnVlLiBTZXRzIHRoZSB3b3JkIGRlbGltaXRlciB0byBtYXRjaCBleGFjdCBwaHJhc2UuIERlZmF1bHRzIHRvIHNpbXBsZSBhbmQgZG91YmxlIHF1b3Rlcy4gKi9cclxuICBASW5wdXQoKSBwdWJsaWMgdHlwZWFoZWFkUGhyYXNlRGVsaW1pdGVycyA9ICdcXCdcIic7XHJcbiAgLyoqIHVzZWQgdG8gc3BlY2lmeSBhIGN1c3RvbSBpdGVtIHRlbXBsYXRlLiBUZW1wbGF0ZSB2YXJpYWJsZXMgZXhwb3NlZCBhcmUgY2FsbGVkIGl0ZW0gYW5kIGluZGV4OyAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyB0eXBlYWhlYWRJdGVtVGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47XHJcbiAgLyoqIHVzZWQgdG8gc3BlY2lmeSBhIGN1c3RvbSBvcHRpb25zIGxpc3QgdGVtcGxhdGUuIFRlbXBsYXRlIHZhcmlhYmxlczogbWF0Y2hlcywgaXRlbVRlbXBsYXRlLCBxdWVyeSAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyBvcHRpb25zTGlzdFRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+O1xyXG5cclxuICAvKiogZmlyZWQgd2hlbiAnYnVzeScgc3RhdGUgb2YgdGhpcyBjb21wb25lbnQgd2FzIGNoYW5nZWQsIGZpcmVkIG9uIGFzeW5jIG1vZGUgb25seSwgcmV0dXJucyBib29sZWFuICovXHJcbiAgQE91dHB1dCgpIHB1YmxpYyB0eXBlYWhlYWRMb2FkaW5nOiBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XHJcbiAgLyoqIGZpcmVkIG9uIGV2ZXJ5IGtleSBldmVudCBhbmQgcmV0dXJucyB0cnVlIGluIGNhc2Ugb2YgbWF0Y2hlcyBhcmUgbm90IGRldGVjdGVkICovXHJcbiAgQE91dHB1dCgpIHB1YmxpYyB0eXBlYWhlYWROb1Jlc3VsdHM6IEV2ZW50RW1pdHRlcjxib29sZWFuPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcclxuICAvKiogZmlyZWQgd2hlbiBvcHRpb24gd2FzIHNlbGVjdGVkLCByZXR1cm4gb2JqZWN0IHdpdGggZGF0YSBvZiB0aGlzIG9wdGlvbiAqL1xyXG4gIEBPdXRwdXQoKSBwdWJsaWMgdHlwZWFoZWFkT25TZWxlY3Q6IEV2ZW50RW1pdHRlcjxUeXBlYWhlYWRNYXRjaD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XHJcbiAgLyoqIGZpcmVkIHdoZW4gYmx1ciBldmVudCBvY2N1cnJlcy4gcmV0dXJucyB0aGUgYWN0aXZlIGl0ZW0gKi9cclxuICBAT3V0cHV0KCkgcHVibGljIHR5cGVhaGVhZE9uQmx1cjogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XHJcblxyXG4gIC8qKlxyXG4gICAqIEEgc2VsZWN0b3Igc3BlY2lmeWluZyB0aGUgZWxlbWVudCB0aGUgdHlwZWFoZWFkIHNob3VsZCBiZSBhcHBlbmRlZCB0by5cclxuICAgKiBDdXJyZW50bHkgb25seSBzdXBwb3J0cyBcImJvZHlcIi5cclxuICAgKi9cclxuICBASW5wdXQoKSBwdWJsaWMgY29udGFpbmVyOiBzdHJpbmc7XHJcblxyXG4gIC8vIG5vdCB5ZXQgaW1wbGVtZW50ZWRcclxuICAvKiogaWYgZmFsc2UgcmVzdHJpY3QgbW9kZWwgdmFsdWVzIHRvIHRoZSBvbmVzIHNlbGVjdGVkIGZyb20gdGhlIHBvcHVwIG9ubHkgd2lsbCBiZSBwcm92aWRlZCAqL1xyXG4gIC8vIEBJbnB1dCgpIHByb3RlY3RlZCB0eXBlYWhlYWRFZGl0YWJsZTpib29sZWFuO1xyXG4gIC8qKiBpZiBmYWxzZSB0aGUgZmlyc3QgbWF0Y2ggYXV0b21hdGljYWxseSB3aWxsIG5vdCBiZSBmb2N1c2VkIGFzIHlvdSB0eXBlICovXHJcbiAgLy8gQElucHV0KCkgcHJvdGVjdGVkIHR5cGVhaGVhZEZvY3VzRmlyc3Q6Ym9vbGVhbjtcclxuICAvKiogZm9ybWF0IHRoZSBuZy1tb2RlbCByZXN1bHQgYWZ0ZXIgc2VsZWN0aW9uICovXHJcbiAgLy8gQElucHV0KCkgcHJvdGVjdGVkIHR5cGVhaGVhZElucHV0Rm9ybWF0dGVyOmFueTtcclxuICAvKiogaWYgdHJ1ZSBhdXRvbWF0aWNhbGx5IHNlbGVjdCBhbiBpdGVtIHdoZW4gdGhlcmUgaXMgb25lIG9wdGlvbiB0aGF0IGV4YWN0bHkgbWF0Y2hlcyB0aGUgdXNlciBpbnB1dCAqL1xyXG4gIC8vIEBJbnB1dCgpIHByb3RlY3RlZCB0eXBlYWhlYWRTZWxlY3RPbkV4YWN0OmJvb2xlYW47XHJcbiAgLyoqICBpZiB0cnVlIHNlbGVjdCB0aGUgY3VycmVudGx5IGhpZ2hsaWdodGVkIG1hdGNoIG9uIGJsdXIgKi9cclxuICAvLyBASW5wdXQoKSBwcm90ZWN0ZWQgdHlwZWFoZWFkU2VsZWN0T25CbHVyOmJvb2xlYW47XHJcbiAgLyoqICBpZiBmYWxzZSBkb24ndCBmb2N1cyB0aGUgaW5wdXQgZWxlbWVudCB0aGUgdHlwZWFoZWFkIGRpcmVjdGl2ZSBpcyBhc3NvY2lhdGVkIHdpdGggb24gc2VsZWN0aW9uICovXHJcbiAgICAvLyBASW5wdXQoKSBwcm90ZWN0ZWQgdHlwZWFoZWFkRm9jdXNPblNlbGVjdDpib29sZWFuO1xyXG5cclxuICBwdWJsaWMgX2NvbnRhaW5lcjogVHlwZWFoZWFkQ29udGFpbmVyQ29tcG9uZW50O1xyXG4gIHB1YmxpYyBpc1R5cGVhaGVhZE9wdGlvbnNMaXN0QWN0aXZlID0gZmFsc2U7XHJcblxyXG4gIHByb3RlY3RlZCBrZXlVcEV2ZW50RW1pdHRlcjogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XHJcbiAgcHJvdGVjdGVkIF9tYXRjaGVzOiBUeXBlYWhlYWRNYXRjaFtdO1xyXG4gIHByb3RlY3RlZCBwbGFjZW1lbnQgPSAnYm90dG9tLWxlZnQnO1xyXG4gIC8vIHByb3RlY3RlZCBwb3B1cDpDb21wb25lbnRSZWY8VHlwZWFoZWFkQ29udGFpbmVyQ29tcG9uZW50PjtcclxuXHJcbiAgcHJvdGVjdGVkIG5nQ29udHJvbDogTmdDb250cm9sO1xyXG4gIHByb3RlY3RlZCB2aWV3Q29udGFpbmVyUmVmOiBWaWV3Q29udGFpbmVyUmVmO1xyXG4gIHByb3RlY3RlZCBlbGVtZW50OiBFbGVtZW50UmVmO1xyXG4gIHByb3RlY3RlZCByZW5kZXJlcjogUmVuZGVyZXIyO1xyXG5cclxuICBwcml2YXRlIF90eXBlYWhlYWQ6IENvbXBvbmVudExvYWRlcjxUeXBlYWhlYWRDb250YWluZXJDb21wb25lbnQ+O1xyXG5cclxuICBASG9zdExpc3RlbmVyKCdrZXl1cCcsIFsnJGV2ZW50J10pXHJcbiAgcHVibGljIG9uQ2hhbmdlKGU6IGFueSk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuX2NvbnRhaW5lcikge1xyXG4gICAgICAvLyBlc2NcclxuICAgICAgaWYgKGUua2V5Q29kZSA9PT0gMjcpIHtcclxuICAgICAgICB0aGlzLmhpZGUoKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIHVwXHJcbiAgICAgIGlmIChlLmtleUNvZGUgPT09IDM4KSB7XHJcbiAgICAgICAgdGhpcy5fY29udGFpbmVyLnByZXZBY3RpdmVNYXRjaCgpO1xyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gZG93blxyXG4gICAgICBpZiAoZS5rZXlDb2RlID09PSA0MCkge1xyXG4gICAgICAgIHRoaXMuX2NvbnRhaW5lci5uZXh0QWN0aXZlTWF0Y2goKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIGVudGVyXHJcbiAgICAgIGlmIChlLmtleUNvZGUgPT09IDEzKSB7XHJcbiAgICAgICAgdGhpcy5fY29udGFpbmVyLnNlbGVjdEFjdGl2ZU1hdGNoKCk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gRm9yIGA8aW5wdXQ+YHMsIHVzZSB0aGUgYHZhbHVlYCBwcm9wZXJ0eS4gRm9yIG90aGVycyB0aGF0IGRvbid0IGhhdmUgYVxyXG4gICAgLy8gYHZhbHVlYCAoc3VjaCBhcyBgPHNwYW4gY29udGVudGVkaXRhYmxlPVwidHJ1ZVwiPmAsIHVzZSBgaW5uZXJUZXh0YC5cclxuICAgIGNvbnN0IHZhbHVlID0gZS50YXJnZXQudmFsdWUgIT09IHVuZGVmaW5lZFxyXG4gICAgICA/IGUudGFyZ2V0LnZhbHVlXHJcbiAgICAgIDogZS50YXJnZXQuaW5uZXJUZXh0O1xyXG4gICAgaWYgKHZhbHVlLnRyaW0oKS5sZW5ndGggPj0gdGhpcy50eXBlYWhlYWRNaW5MZW5ndGgpIHtcclxuICAgICAgdGhpcy50eXBlYWhlYWRMb2FkaW5nLmVtaXQodHJ1ZSk7XHJcbiAgICAgIHRoaXMua2V5VXBFdmVudEVtaXR0ZXIuZW1pdChlLnRhcmdldC52YWx1ZSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLnR5cGVhaGVhZExvYWRpbmcuZW1pdChmYWxzZSk7XHJcbiAgICAgIHRoaXMudHlwZWFoZWFkTm9SZXN1bHRzLmVtaXQoZmFsc2UpO1xyXG4gICAgICB0aGlzLmhpZGUoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIEBIb3N0TGlzdGVuZXIoJ2ZvY3VzJylcclxuICBwdWJsaWMgb25Gb2N1cygpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLnR5cGVhaGVhZE1pbkxlbmd0aCA9PT0gMCkge1xyXG4gICAgICB0aGlzLnR5cGVhaGVhZExvYWRpbmcuZW1pdCh0cnVlKTtcclxuICAgICAgdGhpcy5rZXlVcEV2ZW50RW1pdHRlci5lbWl0KCcnKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIEBIb3N0TGlzdGVuZXIoJ2JsdXInKVxyXG4gIHB1YmxpYyBvbkJsdXIoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5fY29udGFpbmVyICYmICF0aGlzLl9jb250YWluZXIuaXNGb2N1c2VkKSB7XHJcbiAgICAgIHRoaXMudHlwZWFoZWFkT25CbHVyLmVtaXQodGhpcy5fY29udGFpbmVyLmFjdGl2ZSk7XHJcbiAgICAgIHRoaXMuaGlkZSgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgQEhvc3RMaXN0ZW5lcigna2V5ZG93bicsIFsnJGV2ZW50J10pXHJcbiAgcHVibGljIG9uS2V5ZG93bihlOiBhbnkpOiB2b2lkIHtcclxuICAgIC8vIG5vIGNvbnRhaW5lciAtIG5vIHByb2JsZW1zXHJcbiAgICBpZiAoIXRoaXMuX2NvbnRhaW5lcikge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgLy8gaWYgaXRlbXMgaXMgdmlzaWJsZSAtIHByZXZlbnQgZm9ybSBzdWJtaXRpb25cclxuICAgIGlmIChlLmtleUNvZGUgPT09IDEzKSB7XHJcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHVibGljIGNvbnN0cnVjdG9yKGNvbnRyb2w6IE5nQ29udHJvbCwgdmlld0NvbnRhaW5lclJlZjogVmlld0NvbnRhaW5lclJlZiwgZWxlbWVudDogRWxlbWVudFJlZiwgcmVuZGVyZXI6IFJlbmRlcmVyMiwgY2lzOiBDb21wb25lbnRMb2FkZXJGYWN0b3J5KSB7XHJcbiAgICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50O1xyXG4gICAgdGhpcy5uZ0NvbnRyb2wgPSBjb250cm9sO1xyXG4gICAgdGhpcy52aWV3Q29udGFpbmVyUmVmID0gdmlld0NvbnRhaW5lclJlZjtcclxuICAgIHRoaXMucmVuZGVyZXIgPSByZW5kZXJlcjtcclxuICAgIHRoaXMuX3R5cGVhaGVhZCA9IGNpc1xyXG4gICAgICAuY3JlYXRlTG9hZGVyPFR5cGVhaGVhZENvbnRhaW5lckNvbXBvbmVudD4oZWxlbWVudCwgdmlld0NvbnRhaW5lclJlZiwgcmVuZGVyZXIpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xyXG4gICAgdGhpcy50eXBlYWhlYWRPcHRpb25zTGltaXQgPSB0aGlzLnR5cGVhaGVhZE9wdGlvbnNMaW1pdCB8fCAyMDtcclxuICAgIHRoaXMudHlwZWFoZWFkTWluTGVuZ3RoID0gdGhpcy50eXBlYWhlYWRNaW5MZW5ndGggPT09IHZvaWQgMFxyXG4gICAgICA/IDFcclxuICAgICAgOiB0aGlzLnR5cGVhaGVhZE1pbkxlbmd0aDtcclxuICAgIHRoaXMudHlwZWFoZWFkV2FpdE1zID0gdGhpcy50eXBlYWhlYWRXYWl0TXMgfHwgMDtcclxuXHJcbiAgICAvLyBhc3luYyBzaG91bGQgYmUgZmFsc2UgaW4gY2FzZSBvZiBhcnJheVxyXG4gICAgaWYgKHRoaXMudHlwZWFoZWFkQXN5bmMgPT09IHVuZGVmaW5lZCAmJiAhKHRoaXMudHlwZWFoZWFkIGluc3RhbmNlb2YgT2JzZXJ2YWJsZSkpIHtcclxuICAgICAgdGhpcy50eXBlYWhlYWRBc3luYyA9IGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLnR5cGVhaGVhZCBpbnN0YW5jZW9mIE9ic2VydmFibGUpIHtcclxuICAgICAgdGhpcy50eXBlYWhlYWRBc3luYyA9IHRydWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMudHlwZWFoZWFkQXN5bmMpIHtcclxuICAgICAgdGhpcy5hc3luY0FjdGlvbnMoKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuc3luY0FjdGlvbnMoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHB1YmxpYyBjaGFuZ2VNb2RlbChtYXRjaDogVHlwZWFoZWFkTWF0Y2gpOiB2b2lkIHtcclxuICAgIGNvbnN0IHZhbHVlU3RyOiBzdHJpbmcgPSBtYXRjaC52YWx1ZTtcclxuICAgIHRoaXMubmdDb250cm9sLnZpZXdUb01vZGVsVXBkYXRlKHZhbHVlU3RyKTtcclxuICAgICh0aGlzLm5nQ29udHJvbC5jb250cm9sIGFzIEZvcm1Db250cm9sKS5zZXRWYWx1ZSh2YWx1ZVN0cik7XHJcbiAgICB0aGlzLmhpZGUoKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBnZXQgbWF0Y2hlcygpOiBhbnlbXSB7XHJcbiAgICByZXR1cm4gdGhpcy5fbWF0Y2hlcztcclxuICB9XHJcblxyXG4gIHB1YmxpYyBzaG93KCk6IHZvaWQge1xyXG4gICAgdGhpcy5fdHlwZWFoZWFkXHJcbiAgICAgIC5hdHRhY2goVHlwZWFoZWFkQ29udGFpbmVyQ29tcG9uZW50KVxyXG4gICAgICAvLyB0b2RvOiBhZGQgYXBwZW5kIHRvIGJvZHksIGFmdGVyIHVwZGF0aW5nIHBvc2l0aW9uaW5nIHNlcnZpY2VcclxuICAgICAgLnRvKHRoaXMuY29udGFpbmVyKVxyXG4gICAgICAucG9zaXRpb24oe2F0dGFjaG1lbnQ6ICdib3R0b20gbGVmdCd9KVxyXG4gICAgICAuc2hvdyh7XHJcbiAgICAgICAgdHlwZWFoZWFkUmVmOiB0aGlzLFxyXG4gICAgICAgIHBsYWNlbWVudDogdGhpcy5wbGFjZW1lbnQsXHJcbiAgICAgICAgYW5pbWF0aW9uOiBmYWxzZVxyXG4gICAgICB9KTtcclxuXHJcbiAgICB0aGlzLl9jb250YWluZXIgPSB0aGlzLl90eXBlYWhlYWQuaW5zdGFuY2U7XHJcbiAgICB0aGlzLl9jb250YWluZXIucGFyZW50ID0gdGhpcztcclxuICAgIC8vIFRoaXMgaW1wcm92ZXMgdGhlIHNwZWVkIGFzIGl0IHdvbid0IGhhdmUgdG8gYmUgZG9uZSBmb3IgZWFjaCBsaXN0IGl0ZW1cclxuICAgIGNvbnN0IG5vcm1hbGl6ZWRRdWVyeSA9ICh0aGlzLnR5cGVhaGVhZExhdGluaXplXHJcbiAgICAgID8gbGF0aW5pemUodGhpcy5uZ0NvbnRyb2wuY29udHJvbC52YWx1ZSlcclxuICAgICAgOiB0aGlzLm5nQ29udHJvbC5jb250cm9sLnZhbHVlKS50b1N0cmluZygpXHJcbiAgICAgIC50b0xvd2VyQ2FzZSgpO1xyXG4gICAgdGhpcy5fY29udGFpbmVyLnF1ZXJ5ID0gdGhpcy50eXBlYWhlYWRTaW5nbGVXb3Jkc1xyXG4gICAgICA/IHRva2VuaXplKG5vcm1hbGl6ZWRRdWVyeSwgdGhpcy50eXBlYWhlYWRXb3JkRGVsaW1pdGVycywgdGhpcy50eXBlYWhlYWRQaHJhc2VEZWxpbWl0ZXJzKVxyXG4gICAgICA6IG5vcm1hbGl6ZWRRdWVyeTtcclxuICAgIHRoaXMuX2NvbnRhaW5lci5tYXRjaGVzID0gdGhpcy5fbWF0Y2hlcztcclxuICAgIHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgaGlkZSgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLl90eXBlYWhlYWQuaXNTaG93bikge1xyXG4gICAgICB0aGlzLl90eXBlYWhlYWQuaGlkZSgpO1xyXG4gICAgICB0aGlzLl9jb250YWluZXIgPSBudWxsO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHVibGljIG5nT25EZXN0cm95KCk6IGFueSB7XHJcbiAgICB0aGlzLl90eXBlYWhlYWQuZGlzcG9zZSgpO1xyXG4gIH1cclxuXHJcbiAgcHJvdGVjdGVkIGFzeW5jQWN0aW9ucygpOiB2b2lkIHtcclxuICAgIHRoaXMua2V5VXBFdmVudEVtaXR0ZXIucGlwZShcclxuICAgICAgZGVib3VuY2VUaW1lKHRoaXMudHlwZWFoZWFkV2FpdE1zKSxcclxuICAgICAgbWVyZ2VNYXAoKCkgPT4gdGhpcy50eXBlYWhlYWQpXHJcbiAgICApLnN1YnNjcmliZShcclxuICAgICAgICAobWF0Y2hlczogYW55W10pID0+IHtcclxuICAgICAgICAgIHRoaXMuZmluYWxpemVBc3luY0NhbGwobWF0Y2hlcyk7XHJcbiAgICAgICAgfSxcclxuICAgICAgICAoZXJyOiBhbnkpID0+IHtcclxuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyKTtcclxuICAgICAgICB9XHJcbiAgICAgICk7XHJcbiAgfVxyXG5cclxuICBwcm90ZWN0ZWQgc3luY0FjdGlvbnMoKTogdm9pZCB7XHJcbiAgICB0aGlzLmtleVVwRXZlbnRFbWl0dGVyLnBpcGUoXHJcbiAgICAgIGRlYm91bmNlVGltZSh0aGlzLnR5cGVhaGVhZFdhaXRNcyksXHJcbiAgICAgIG1lcmdlTWFwKCh2YWx1ZTogc3RyaW5nKSA9PiB7XHJcbiAgICAgICAgY29uc3Qgbm9ybWFsaXplZFF1ZXJ5ID0gdGhpcy5ub3JtYWxpemVRdWVyeSh2YWx1ZSk7XHJcblxyXG4gICAgICAgIHJldHVybiBmcm9tKHRoaXMudHlwZWFoZWFkKS5waXBlKFxyXG4gICAgICAgICAgZmlsdGVyKChvcHRpb246IGFueSkgPT4ge1xyXG4gICAgICAgICAgICByZXR1cm4gb3B0aW9uICYmIHRoaXMudGVzdE1hdGNoKHRoaXMubm9ybWFsaXplT3B0aW9uKG9wdGlvbiksIG5vcm1hbGl6ZWRRdWVyeSk7XHJcbiAgICAgICAgICB9KSxcclxuICAgICAgICAgIHRvQXJyYXkoKVxyXG4gICAgICAgICk7XHJcbiAgICAgIH0pKVxyXG4gICAgICAuc3Vic2NyaWJlKFxyXG4gICAgICAgIChtYXRjaGVzOiBhbnlbXSkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5maW5hbGl6ZUFzeW5jQ2FsbChtYXRjaGVzKTtcclxuICAgICAgICB9LFxyXG4gICAgICAgIChlcnI6IGFueSkgPT4ge1xyXG4gICAgICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xyXG4gICAgICAgIH1cclxuICAgICAgKTtcclxuICB9XHJcblxyXG4gIHByb3RlY3RlZCBub3JtYWxpemVPcHRpb24ob3B0aW9uOiBhbnkpOiBhbnkge1xyXG4gICAgY29uc3Qgb3B0aW9uVmFsdWU6IHN0cmluZyA9IGdldFZhbHVlRnJvbU9iamVjdChvcHRpb24sIHRoaXMudHlwZWFoZWFkT3B0aW9uRmllbGQpO1xyXG4gICAgY29uc3Qgbm9ybWFsaXplZE9wdGlvbiA9IHRoaXMudHlwZWFoZWFkTGF0aW5pemVcclxuICAgICAgPyBsYXRpbml6ZShvcHRpb25WYWx1ZSlcclxuICAgICAgOiBvcHRpb25WYWx1ZTtcclxuXHJcbiAgICByZXR1cm4gbm9ybWFsaXplZE9wdGlvbi50b0xvd2VyQ2FzZSgpO1xyXG4gIH1cclxuXHJcbiAgcHJvdGVjdGVkIG5vcm1hbGl6ZVF1ZXJ5KHZhbHVlOiBzdHJpbmcpOiBhbnkge1xyXG4gICAgLy8gSWYgc2luZ2xlV29yZHMsIGJyZWFrIG1vZGVsIGhlcmUgdG8gbm90IGJlIGRvaW5nIGV4dHJhIHdvcmsgb24gZWFjaFxyXG4gICAgLy8gaXRlcmF0aW9uXHJcbiAgICBsZXQgbm9ybWFsaXplZFF1ZXJ5OiBhbnkgPVxyXG4gICAgICAodGhpcy50eXBlYWhlYWRMYXRpbml6ZSA/IGxhdGluaXplKHZhbHVlKSA6IHZhbHVlKVxyXG4gICAgICAgIC50b1N0cmluZygpXHJcbiAgICAgICAgLnRvTG93ZXJDYXNlKCk7XHJcbiAgICBub3JtYWxpemVkUXVlcnkgPSB0aGlzLnR5cGVhaGVhZFNpbmdsZVdvcmRzXHJcbiAgICAgID8gdG9rZW5pemUobm9ybWFsaXplZFF1ZXJ5LCB0aGlzLnR5cGVhaGVhZFdvcmREZWxpbWl0ZXJzLCB0aGlzLnR5cGVhaGVhZFBocmFzZURlbGltaXRlcnMpXHJcbiAgICAgIDogbm9ybWFsaXplZFF1ZXJ5O1xyXG5cclxuICAgIHJldHVybiBub3JtYWxpemVkUXVlcnk7XHJcbiAgfVxyXG5cclxuICBwcm90ZWN0ZWQgdGVzdE1hdGNoKG1hdGNoOiBzdHJpbmcsIHRlc3Q6IGFueSk6IGJvb2xlYW4ge1xyXG4gICAgbGV0IHNwYWNlTGVuZ3RoOiBudW1iZXI7XHJcblxyXG4gICAgaWYgKHR5cGVvZiB0ZXN0ID09PSAnb2JqZWN0Jykge1xyXG4gICAgICBzcGFjZUxlbmd0aCA9IHRlc3QubGVuZ3RoO1xyXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNwYWNlTGVuZ3RoOyBpICs9IDEpIHtcclxuICAgICAgICBpZiAodGVzdFtpXS5sZW5ndGggPiAwICYmIG1hdGNoLmluZGV4T2YodGVzdFtpXSkgPCAwKSB7XHJcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmV0dXJuIG1hdGNoLmluZGV4T2YodGVzdCkgPj0gMDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByb3RlY3RlZCBmaW5hbGl6ZUFzeW5jQ2FsbChtYXRjaGVzOiBhbnlbXSk6IHZvaWQge1xyXG4gICAgdGhpcy5wcmVwYXJlTWF0Y2hlcyhtYXRjaGVzKTtcclxuXHJcbiAgICB0aGlzLnR5cGVhaGVhZExvYWRpbmcuZW1pdChmYWxzZSk7XHJcbiAgICB0aGlzLnR5cGVhaGVhZE5vUmVzdWx0cy5lbWl0KCF0aGlzLmhhc01hdGNoZXMoKSk7XHJcblxyXG4gICAgaWYgKCF0aGlzLmhhc01hdGNoZXMoKSkge1xyXG4gICAgICB0aGlzLmhpZGUoKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLl9jb250YWluZXIpIHtcclxuICAgICAgLy8gVGhpcyBpbXByb3ZlcyB0aGUgc3BlZWQgYXMgaXQgd29uJ3QgaGF2ZSB0byBiZSBkb25lIGZvciBlYWNoIGxpc3QgaXRlbVxyXG4gICAgICBjb25zdCBub3JtYWxpemVkUXVlcnkgPSAodGhpcy50eXBlYWhlYWRMYXRpbml6ZVxyXG4gICAgICAgID8gbGF0aW5pemUodGhpcy5uZ0NvbnRyb2wuY29udHJvbC52YWx1ZSlcclxuICAgICAgICA6IHRoaXMubmdDb250cm9sLmNvbnRyb2wudmFsdWUpLnRvU3RyaW5nKClcclxuICAgICAgICAudG9Mb3dlckNhc2UoKTtcclxuICAgICAgdGhpcy5fY29udGFpbmVyLnF1ZXJ5ID0gdGhpcy50eXBlYWhlYWRTaW5nbGVXb3Jkc1xyXG4gICAgICAgID8gdG9rZW5pemUobm9ybWFsaXplZFF1ZXJ5LCB0aGlzLnR5cGVhaGVhZFdvcmREZWxpbWl0ZXJzLCB0aGlzLnR5cGVhaGVhZFBocmFzZURlbGltaXRlcnMpXHJcbiAgICAgICAgOiBub3JtYWxpemVkUXVlcnk7XHJcbiAgICAgIHRoaXMuX2NvbnRhaW5lci5tYXRjaGVzID0gdGhpc