@covalent/code-editor
Version:
Teradata UI Platform Code Editor Module
370 lines • 44.2 kB
JavaScript
import { Component, Input, Output, EventEmitter, ViewChild, ElementRef, forwardRef, ChangeDetectorRef, NgZone, Inject, PLATFORM_ID, } from '@angular/core';
import { isPlatformServer } from '@angular/common';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { of, Subject } from 'rxjs';
import { fromEvent, merge, timer } from 'rxjs';
import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';
// Use esm version to support shipping subset of languages and features
import { editor, languages } from 'monaco-editor';
import { mixinControlValueAccessor, mixinDisabled, } from '@covalent/core/common';
import * as i0 from "@angular/core";
const noop = () => {
// empty method
};
// counter for ids to allow for multiple editors on one page
let uniqueCounter = 0;
export class TdCodeEditorBase {
constructor(_changeDetectorRef) {
this._changeDetectorRef = _changeDetectorRef;
}
}
export const _TdCodeEditorMixinBase = mixinControlValueAccessor(mixinDisabled(TdCodeEditorBase), []);
export class TdCodeEditorComponent extends _TdCodeEditorMixinBase {
/**
* value?: string
*/
set value(value) {
this._value = value;
if (this._componentInitialized) {
this.applyValue();
}
}
get value() {
return this._value;
}
applyValue() {
if (!this._fromEditor) {
this._editor.setValue(this._value || '');
}
this._fromEditor = false;
this.propagateChange(this._value);
this.editorValueChange.emit();
}
registerOnChange(fn) {
this.propagateChange = fn;
}
registerOnTouched(fn) {
this.onTouched = fn;
}
/**
* getEditorContent?: function
* Returns the content within the editor
*/
getValue() {
if (!this._componentInitialized) {
return of('');
}
setTimeout(() => {
this._subject.next(this._value);
this._subject.complete();
this._subject = new Subject();
});
return this._subject.asObservable();
}
/**
* language?: string
* language used in editor
*/
set language(language) {
this._language = language;
if (this._componentInitialized) {
this.applyLanguage();
}
}
get language() {
return this._language;
}
applyLanguage() {
if (this._language) {
editor.setModelLanguage(this._editor.getModel(), this._language);
this.editorLanguageChanged.emit();
}
}
/**
* registerLanguage?: function
* Registers a custom Language within the editor
*/
registerLanguage(language) {
if (this._componentInitialized) {
languages.register({ id: language.id });
this._disposables.push(languages.setMonarchTokensProvider(language.id, {
tokenizer: {
root: language.monarchTokensProvider,
},
}));
// Define a new theme that constains only rules that match this language
editor.defineTheme(language.customTheme.id, language.customTheme.theme);
this._theme = language.customTheme.id;
this._disposables.push(languages.registerCompletionItemProvider(language.id, {
provideCompletionItems: () => {
return language.completionItemProvider;
},
}));
const css = document.createElement('style');
css.type = 'text/css';
css.innerHTML = language.monarchTokensProviderCSS;
document.body.appendChild(css);
this.editorConfigurationChanged.emit();
this._registeredLanguagesStyles = [
...this._registeredLanguagesStyles,
css,
];
}
}
/**
* style?: string
* css style of the editor on the page
*/
set editorStyle(editorStyle) {
this._editorStyle = editorStyle;
if (this._componentInitialized) {
this.applyStyle();
}
}
get editorStyle() {
return this._editorStyle;
}
applyStyle() {
if (this._editorStyle) {
const containerDiv = this._editorContainer.nativeElement;
containerDiv.setAttribute('style', this._editorStyle);
}
}
/**
* theme?: string
* Theme to be applied to editor
*/
set theme(theme) {
this._theme = theme;
if (this._componentInitialized) {
this._editor.updateOptions({ theme });
this.editorConfigurationChanged.emit();
}
}
get theme() {
return this._theme;
}
/**
* fullScreenKeyBinding?: number
* See here for key bindings https://microsoft.github.io/monaco-editor/api/enums/keycode.html
* Sets the KeyCode for shortcutting to Fullscreen mode
*/
set fullScreenKeyBinding(keycode) {
this._keycode = keycode;
}
get fullScreenKeyBinding() {
return this._keycode;
}
/**
* editorOptions?: object
* Options used on editor instantiation. Available options listed here:
* https://microsoft.github.io/monaco-editor/api/interfaces/editor.ieditoroptions.html
*/
set editorOptions(editorOptions) {
this._editorOptions = editorOptions;
if (this._componentInitialized) {
this._editor.updateOptions(editorOptions);
this.editorConfigurationChanged.emit();
}
}
get editorOptions() {
return this._editorOptions;
}
/**
* layout method that calls layout method of editor and instructs the editor to remeasure its container
*/
layout() {
if (this._componentInitialized) {
this._editor.layout();
}
}
/**
* Returns if in Full Screen Mode or not
*/
get isFullScreen() {
return this._isFullScreen;
}
// tslint:disable-next-line:member-ordering
constructor(_changeDetectorRef, _elementRef, _ngZone, platformId) {
super(_changeDetectorRef);
this._elementRef = _elementRef;
this._ngZone = _ngZone;
this.platformId = platformId;
this._destroy = new Subject();
this._widthSubject = new Subject();
this._heightSubject = new Subject();
this._editorStyle = 'width:100%;height:100%;';
this._value = '';
this._theme = 'vs';
this._language = 'javascript';
this._subject = new Subject();
this._editorInnerContainer = 'editorInnerContainer' + uniqueCounter++;
this._fromEditor = false;
this._componentInitialized = false;
this._editorOptions = {};
this._isFullScreen = false;
this._registeredLanguagesStyles = [];
this._disposables = [];
/**
* editorInitialized: function($event)
* Event emitted when editor is first initialized
*/
this.editorInitialized = new EventEmitter();
/**
* editorConfigurationChanged: function($event)
* Event emitted when editor's configuration changes
*/
this.editorConfigurationChanged = new EventEmitter();
/**
* editorLanguageChanged: function($event)
* Event emitted when editor's Language changes
*/
this.editorLanguageChanged = new EventEmitter();
/**
* editorValueChange: function($event)
* Event emitted any time something changes the editor value
*/
this.editorValueChange = new EventEmitter();
this.propagateChange = (_) => noop;
}
ngOnInit() {
if (isPlatformServer(this.platformId)) {
return;
}
const containerDiv = this._editorContainer.nativeElement;
containerDiv.id = this._editorInnerContainer;
this._editor = editor.create(containerDiv, Object.assign({
value: this._value,
language: this.language,
theme: this._theme,
}, this.editorOptions));
this._componentInitialized = true;
setTimeout(() => {
this.applyLanguage();
this._fromEditor = true;
this.applyValue();
this.applyStyle();
this.editorInitialized.emit(this._editor);
this.editorConfigurationChanged.emit();
});
// The `onDidChangeContent` returns a disposable object (an object with `dispose()` method) which will cleanup
// the listener. The callback, that we pass to `onDidChangeContent`, captures `this`. This leads to a circular reference
// (`td-code-editor -> monaco -> td-code-editor`) and prevents the `td-code-editor` from being GC'd.
this._disposables.push(this._editor.getModel().onDidChangeContent(() => {
this._fromEditor = true;
this.writeValue(this._editor.getValue());
this.layout();
}));
this.addFullScreenModeCommand();
this._ngZone.runOutsideAngular(() => merge(fromEvent(window, 'resize').pipe(debounceTime(100)), this._widthSubject.asObservable().pipe(distinctUntilChanged()), this._heightSubject.asObservable().pipe(distinctUntilChanged()))
.pipe(debounceTime(100), takeUntil(this._destroy))
.subscribe(() => {
// Note: this is being called outside of the Angular zone since we don't have to
// run change detection whenever the editor resizes itself.
this.layout();
}));
this._ngZone.runOutsideAngular(() => timer(500, 250)
.pipe(takeUntil(this._destroy))
.subscribe(() => {
const { width, height } = this._elementRef.nativeElement.getBoundingClientRect();
this._widthSubject.next(width);
this._heightSubject.next(height);
}));
}
ngOnDestroy() {
this._changeDetectorRef.detach();
this._registeredLanguagesStyles.forEach((style) => style.remove());
while (this._disposables.length) {
this._disposables.pop()?.dispose();
}
if (this._editor) {
this._editor.dispose();
}
this._destroy.next(true);
this._destroy.unsubscribe();
}
/**
* showFullScreenEditor request for full screen of Code Editor based on its browser type.
*/
showFullScreenEditor() {
if (this._componentInitialized) {
const codeEditorElement = this._editorContainer
.nativeElement;
codeEditorElement.requestFullscreen();
}
this._isFullScreen = true;
}
/**
* exitFullScreenEditor request to exit full screen of Code Editor based on its browser type.
*/
exitFullScreenEditor() {
if (this._componentInitialized) {
document.exitFullscreen();
}
this._isFullScreen = false;
}
/**
* addFullScreenModeCommand used to add the fullscreen option to the context menu
*/
addFullScreenModeCommand() {
this._disposables.push(this._editor.addAction({
// An unique identifier of the contributed action.
id: 'fullScreen',
// A label of the action that will be presented to the user.
label: 'Full Screen',
// An optional array of keybindings for the action.
contextMenuGroupId: 'navigation',
keybindings: this._keycode,
contextMenuOrder: 1.5,
// Method that will be executed when the action is triggered.
run: () => {
this.showFullScreenEditor();
},
}));
}
}
TdCodeEditorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TdCodeEditorComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: i0.NgZone }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component });
TdCodeEditorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TdCodeEditorComponent, selector: "td-code-editor", inputs: { value: "value", language: "language", editorStyle: "editorStyle", theme: "theme", fullScreenKeyBinding: "fullScreenKeyBinding", editorOptions: "editorOptions" }, outputs: { editorInitialized: "editorInitialized", editorConfigurationChanged: "editorConfigurationChanged", editorLanguageChanged: "editorLanguageChanged", editorValueChange: "editorValueChange" }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TdCodeEditorComponent),
multi: true,
},
], viewQueries: [{ propertyName: "_editorContainer", first: true, predicate: ["editorContainer"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"editor-container\" #editorContainer></div>\n", styles: [":host{display:block;position:relative}:host .editor-container{position:absolute;inset:0}::ng-deep .monaco-aria-container{display:none}\n"] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TdCodeEditorComponent, decorators: [{
type: Component,
args: [{ selector: 'td-code-editor', providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TdCodeEditorComponent),
multi: true,
},
], template: "<div class=\"editor-container\" #editorContainer></div>\n", styles: [":host{display:block;position:relative}:host .editor-container{position:absolute;inset:0}::ng-deep .monaco-aria-container{display:none}\n"] }]
}], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: i0.NgZone }, { type: undefined, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }]; }, propDecorators: { _editorContainer: [{
type: ViewChild,
args: ['editorContainer', { static: true }]
}], editorInitialized: [{
type: Output
}], editorConfigurationChanged: [{
type: Output
}], editorLanguageChanged: [{
type: Output
}], editorValueChange: [{
type: Output
}], value: [{
type: Input
}], language: [{
type: Input
}], editorStyle: [{
type: Input
}], theme: [{
type: Input
}], fullScreenKeyBinding: [{
type: Input
}], editorOptions: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29kZS1lZGl0b3IuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vbGlicy9hbmd1bGFyLWNvZGUtZWRpdG9yL3NyYy9saWIvY29kZS1lZGl0b3IuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vbGlicy9hbmd1bGFyLWNvZGUtZWRpdG9yL3NyYy9saWIvY29kZS1lZGl0b3IuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFDVCxLQUFLLEVBQ0wsTUFBTSxFQUNOLFlBQVksRUFFWixTQUFTLEVBQ1QsVUFBVSxFQUNWLFVBQVUsRUFDVixpQkFBaUIsRUFFakIsTUFBTSxFQUNOLE1BQU0sRUFDTixXQUFXLEdBQ1osTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDbkQsT0FBTyxFQUFFLGlCQUFpQixFQUF3QixNQUFNLGdCQUFnQixDQUFDO0FBQ3pFLE9BQU8sRUFBYyxFQUFFLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9DLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMvQyxPQUFPLEVBQUUsWUFBWSxFQUFFLG9CQUFvQixFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRS9FLHVFQUF1RTtBQUN2RSxPQUFPLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBZSxNQUFNLGVBQWUsQ0FBQztBQUUvRCxPQUFPLEVBQ0wseUJBQXlCLEVBQ3pCLGFBQWEsR0FDZCxNQUFNLHVCQUF1QixDQUFDOztBQUUvQixNQUFNLElBQUksR0FBRyxHQUFHLEVBQUU7SUFDaEIsZUFBZTtBQUNqQixDQUFDLENBQUM7QUFFRiw0REFBNEQ7QUFDNUQsSUFBSSxhQUFhLEdBQUcsQ0FBQyxDQUFDO0FBRXRCLE1BQU0sT0FBTyxnQkFBZ0I7SUFDM0IsWUFBbUIsa0JBQXFDO1FBQXJDLHVCQUFrQixHQUFsQixrQkFBa0IsQ0FBbUI7SUFBRyxDQUFDO0NBQzdEO0FBRUQsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQUcseUJBQXlCLENBQzdELGFBQWEsQ0FBQyxnQkFBZ0IsQ0FBQyxFQUMvQixFQUFFLENBQ0gsQ0FBQztBQWNGLE1BQU0sT0FBTyxxQkFDWCxTQUFRLHNCQUFzQjtJQXVEOUI7O09BRUc7SUFDSCxJQUNhLEtBQUssQ0FBQyxLQUFhO1FBQzlCLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO1FBRXBCLElBQUksSUFBSSxDQUFDLHFCQUFxQixFQUFFO1lBQzlCLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztTQUNuQjtJQUNILENBQUM7SUFDRCxJQUFhLEtBQUs7UUFDaEIsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQ3JCLENBQUM7SUFFRCxVQUFVO1FBQ1IsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDckIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUMsQ0FBQztTQUMxQztRQUNELElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDO1FBQ3pCLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ2xDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNoQyxDQUFDO0lBRVEsZ0JBQWdCLENBQUMsRUFBTztRQUMvQixJQUFJLENBQUMsZUFBZSxHQUFHLEVBQUUsQ0FBQztJQUM1QixDQUFDO0lBQ1EsaUJBQWlCLENBQUMsRUFBTztRQUNoQyxJQUFJLENBQUMsU0FBUyxHQUFHLEVBQUUsQ0FBQztJQUN0QixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsUUFBUTtRQUNOLElBQUksQ0FBQyxJQUFJLENBQUMscUJBQXFCLEVBQUU7WUFDL0IsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7U0FDZjtRQUNELFVBQVUsQ0FBQyxHQUFHLEVBQUU7WUFDZCxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDaEMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksT0FBTyxFQUFFLENBQUM7UUFDaEMsQ0FBQyxDQUFDLENBQUM7UUFDSCxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDdEMsQ0FBQztJQUVEOzs7T0FHRztJQUNILElBQ0ksUUFBUSxDQUFDLFFBQWdCO1FBQzNCLElBQUksQ0FBQyxTQUFTLEdBQUcsUUFBUSxDQUFDO1FBQzFCLElBQUksSUFBSSxDQUFDLHFCQUFxQixFQUFFO1lBQzlCLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztTQUN0QjtJQUNILENBQUM7SUFFRCxJQUFJLFFBQVE7UUFDVixPQUFPLElBQUksQ0FBQyxTQUFTLENBQUM7SUFDeEIsQ0FBQztJQUVELGFBQWE7UUFDWCxJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDbEIsTUFBTSxDQUFDLGdCQUFnQixDQUNyQixJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBdUIsRUFDNUMsSUFBSSxDQUFDLFNBQVMsQ0FDZixDQUFDO1lBQ0YsSUFBSSxDQUFDLHFCQUFxQixDQUFDLElBQUksRUFBRSxDQUFDO1NBQ25DO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNILGdCQUFnQixDQUFDLFFBQWE7UUFDNUIsSUFBSSxJQUFJLENBQUMscUJBQXFCLEVBQUU7WUFDOUIsU0FBUyxDQUFDLFFBQVEsQ0FBQyxFQUFFLEVBQUUsRUFBRSxRQUFRLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUV4QyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FDcEIsU0FBUyxDQUFDLHdCQUF3QixDQUFDLFFBQVEsQ0FBQyxFQUFFLEVBQUU7Z0JBQzlDLFNBQVMsRUFBRTtvQkFDVCxJQUFJLEVBQUUsUUFBUSxDQUFDLHFCQUFxQjtpQkFDckM7YUFDRixDQUFDLENBQ0gsQ0FBQztZQUVGLHdFQUF3RTtZQUN4RSxNQUFNLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsRUFBRSxFQUFFLFFBQVEsQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDeEUsSUFBSSxDQUFDLE1BQU0sR0FBRyxRQUFRLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztZQUV0QyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FDcEIsU0FBUyxDQUFDLDhCQUE4QixDQUFDLFFBQVEsQ0FBQyxFQUFFLEVBQUU7Z0JBQ3BELHNCQUFzQixFQUFFLEdBQUcsRUFBRTtvQkFDM0IsT0FBTyxRQUFRLENBQUMsc0JBQXNCLENBQUM7Z0JBQ3pDLENBQUM7YUFDRixDQUFDLENBQ0gsQ0FBQztZQUVGLE1BQU0sR0FBRyxHQUFxQixRQUFRLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzlELEdBQUcsQ0FBQyxJQUFJLEdBQUcsVUFBVSxDQUFDO1lBQ3RCLEdBQUcsQ0FBQyxTQUFTLEdBQUcsUUFBUSxDQUFDLHdCQUF3QixDQUFDO1lBQ2xELFFBQVEsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQy9CLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUN2QyxJQUFJLENBQUMsMEJBQTBCLEdBQUc7Z0JBQ2hDLEdBQUcsSUFBSSxDQUFDLDBCQUEwQjtnQkFDbEMsR0FBRzthQUNKLENBQUM7U0FDSDtJQUNILENBQUM7SUFFRDs7O09BR0c7SUFDSCxJQUNJLFdBQVcsQ0FBQyxXQUFtQjtRQUNqQyxJQUFJLENBQUMsWUFBWSxHQUFHLFdBQVcsQ0FBQztRQUNoQyxJQUFJLElBQUksQ0FBQyxxQkFBcUIsRUFBRTtZQUM5QixJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7U0FDbkI7SUFDSCxDQUFDO0lBRUQsSUFBSSxXQUFXO1FBQ2IsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDO0lBQzNCLENBQUM7SUFFRCxVQUFVO1FBQ1IsSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFO1lBQ3JCLE1BQU0sWUFBWSxHQUFtQixJQUFJLENBQUMsZ0JBQWdCLENBQUMsYUFBYSxDQUFDO1lBQ3pFLFlBQVksQ0FBQyxZQUFZLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztTQUN2RDtJQUNILENBQUM7SUFFRDs7O09BR0c7SUFDSCxJQUNJLEtBQUssQ0FBQyxLQUFhO1FBQ3JCLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO1FBQ3BCLElBQUksSUFBSSxDQUFDLHFCQUFxQixFQUFFO1lBQzlCLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztZQUN0QyxJQUFJLENBQUMsMEJBQTBCLENBQUMsSUFBSSxFQUFFLENBQUM7U0FDeEM7SUFDSCxDQUFDO0lBQ0QsSUFBSSxLQUFLO1FBQ1AsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQ3JCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsSUFDSSxvQkFBb0IsQ0FBQyxPQUFpQjtRQUN4QyxJQUFJLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQztJQUMxQixDQUFDO0lBQ0QsSUFBSSxvQkFBb0I7UUFDdEIsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDO0lBQ3ZCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsSUFDSSxhQUFhLENBQUMsYUFBa0I7UUFDbEMsSUFBSSxDQUFDLGNBQWMsR0FBRyxhQUFhLENBQUM7UUFDcEMsSUFBSSxJQUFJLENBQUMscUJBQXFCLEVBQUU7WUFDOUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDMUMsSUFBSSxDQUFDLDBCQUEwQixDQUFDLElBQUksRUFBRSxDQUFDO1NBQ3hDO0lBQ0gsQ0FBQztJQUNELElBQUksYUFBYTtRQUNmLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQztJQUM3QixDQUFDO0lBRUQ7O09BRUc7SUFDSCxNQUFNO1FBQ0osSUFBSSxJQUFJLENBQUMscUJBQXFCLEVBQUU7WUFDOUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztTQUN2QjtJQUNILENBQUM7SUFFRDs7T0FFRztJQUNILElBQUksWUFBWTtRQUNkLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQztJQUM1QixDQUFDO0lBRUQsMkNBQTJDO0lBQzNDLFlBQ0Usa0JBQXFDLEVBQzdCLFdBQW9DLEVBQ3BDLE9BQWUsRUFDTSxVQUFrQjtRQUUvQyxLQUFLLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUpsQixnQkFBVyxHQUFYLFdBQVcsQ0FBeUI7UUFDcEMsWUFBTyxHQUFQLE9BQU8sQ0FBUTtRQUNNLGVBQVUsR0FBVixVQUFVLENBQVE7UUEvUHpDLGFBQVEsR0FBcUIsSUFBSSxPQUFPLEVBQVcsQ0FBQztRQUNwRCxrQkFBYSxHQUFvQixJQUFJLE9BQU8sRUFBVSxDQUFDO1FBQ3ZELG1CQUFjLEdBQW9CLElBQUksT0FBTyxFQUFVLENBQUM7UUFFeEQsaUJBQVksR0FBRyx5QkFBeUIsQ0FBQztRQUN6QyxXQUFNLEdBQUcsRUFBRSxDQUFDO1FBQ1osV0FBTSxHQUFHLElBQUksQ0FBQztRQUNkLGNBQVMsR0FBRyxZQUFZLENBQUM7UUFDekIsYUFBUSxHQUFvQixJQUFJLE9BQU8sRUFBRSxDQUFDO1FBQzFDLDBCQUFxQixHQUMzQixzQkFBc0IsR0FBRyxhQUFhLEVBQUUsQ0FBQztRQUVuQyxnQkFBVyxHQUFHLEtBQUssQ0FBQztRQUNwQiwwQkFBcUIsR0FBRyxLQUFLLENBQUM7UUFDOUIsbUJBQWMsR0FBUSxFQUFFLENBQUM7UUFDekIsa0JBQWEsR0FBRyxLQUFLLENBQUM7UUFFdEIsK0JBQTBCLEdBQXVCLEVBQUUsQ0FBQztRQUNwRCxpQkFBWSxHQUFrQixFQUFFLENBQUM7UUFJekM7OztXQUdHO1FBRUgsc0JBQWlCLEdBQ2YsSUFBSSxZQUFZLEVBQWdDLENBQUM7UUFFbkQ7OztXQUdHO1FBQ08sK0JBQTBCLEdBQ2xDLElBQUksWUFBWSxFQUFRLENBQUM7UUFFM0I7OztXQUdHO1FBQ08sMEJBQXFCLEdBQzdCLElBQUksWUFBWSxFQUFRLENBQUM7UUFFM0I7OztXQUdHO1FBQ08sc0JBQWlCLEdBQXVCLElBQUksWUFBWSxFQUFRLENBQUM7UUFFM0Usb0JBQWUsR0FBRyxDQUFDLENBQU0sRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDO0lBZ05uQyxDQUFDO0lBRUQsUUFBUTtRQUNOLElBQUksZ0JBQWdCLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFO1lBQ3JDLE9BQU87U0FDUjtRQUVELE1BQU0sWUFBWSxHQUFtQixJQUFJLENBQUMsZ0JBQWdCLENBQUMsYUFBYSxDQUFDO1FBQ3pFLFlBQVksQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixDQUFDO1FBRTdDLElBQUksQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FDMUIsWUFBWSxFQUNaLE1BQU0sQ0FBQyxNQUFNLENBQ1g7WUFDRSxLQUFLLEVBQUUsSUFBSSxDQUFDLE1BQU07WUFDbEIsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRO1lBQ3ZCLEtBQUssRUFBRSxJQUFJLENBQUMsTUFBTTtTQUNuQixFQUNELElBQUksQ0FBQyxhQUFhLENBQ25CLENBQ0YsQ0FBQztRQUNGLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxJQUFJLENBQUM7UUFDbEMsVUFBVSxDQUFDLEdBQUcsRUFBRTtZQUNkLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUNyQixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQztZQUN4QixJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDbEIsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ2xCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzFDLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUN6QyxDQUFDLENBQUMsQ0FBQztRQUNILDhHQUE4RztRQUM5Ryx3SEFBd0g7UUFDeEgsb0dBQW9HO1FBQ3BHLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUNuQixJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBd0IsQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLEVBQUU7WUFDckUsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUM7WUFDeEIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7WUFDekMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ2hCLENBQUMsQ0FBQyxDQUNILENBQUM7UUFDRixJQUFJLENBQUMsd0JBQXdCLEVBQUUsQ0FBQztRQUVoQyxJQUFJLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDLEdBQUcsRUFBRSxDQUNsQyxLQUFLLENBQ0gsU0FBUyxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQ25ELElBQUksQ0FBQyxhQUFhLENBQUMsWUFBWSxFQUFFLENBQUMsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUMsRUFDOUQsSUFBSSxDQUFDLGNBQWMsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQyxDQUNoRTthQUNFLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLEVBQUUsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQzthQUNqRCxTQUFTLENBQUMsR0FBRyxFQUFFO1lBQ2QsZ0ZBQWdGO1lBQ2hGLDJEQUEyRDtZQUMzRCxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDaEIsQ0FBQyxDQUFDLENBQ0wsQ0FBQztRQUNGLElBQUksQ0FBQyxPQUFPLENBQUMsaUJBQWlCLENBQUMsR0FBRyxFQUFFLENBQ2xDLEtBQUssQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDO2FBQ1osSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7YUFDOUIsU0FBUyxDQUFDLEdBQUcsRUFBRTtZQUNkLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEdBQ3JCLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLHFCQUFxQixFQUFFLENBQUM7WUFDekQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDL0IsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDbkMsQ0FBQyxDQUFDLENBQ0wsQ0FBQztJQUNKLENBQUM7SUFFRCxXQUFXO1FBQ1QsSUFBSSxDQUFDLGtCQUFrQixDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ2pDLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUF1QixFQUFFLEVBQUUsQ0FDbEUsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUNmLENBQUM7UUFDRixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxFQUFFO1lBQy9CLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxFQUFFLEVBQUUsT0FBTyxFQUFFLENBQUM7U0FDcEM7UUFDRCxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDaEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztTQUN4QjtRQUNELElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3pCLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDOUIsQ0FBQztJQUVEOztPQUVHO0lBQ0ksb0JBQW9CO1FBQ3pCLElBQUksSUFBSSxDQUFDLHFCQUFxQixFQUFFO1lBQzlCLE1BQU0saUJBQWlCLEdBQW1CLElBQUksQ0FBQyxnQkFBZ0I7aUJBQzVELGFBQStCLENBQUM7WUFDbkMsaUJBQWlCLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztTQUN2QztRQUNELElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDO0lBQzVCLENBQUM7SUFFRDs7T0FFRztJQUNJLG9CQUFvQjtRQUN6QixJQUFJLElBQUksQ0FBQyxxQkFBcUIsRUFBRTtZQUM5QixRQUFRLENBQUMsY0FBYyxFQUFFLENBQUM7U0FDM0I7UUFDRCxJQUFJLENBQUMsYUFBYSxHQUFHLEtBQUssQ0FBQztJQUM3QixDQUFDO0lBRUQ7O09BRUc7SUFDSyx3QkFBd0I7UUFDOUIsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQ3BCLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDO1lBQ3JCLGtEQUFrRDtZQUNsRCxFQUFFLEVBQUUsWUFBWTtZQUNoQiw0REFBNEQ7WUFDNUQsS0FBSyxFQUFFLGFBQWE7WUFDcEIsbURBQW1EO1lBQ25ELGtCQUFrQixFQUFFLFlBQVk7WUFDaEMsV0FBVyxFQUFFLElBQUksQ0FBQyxRQUFRO1lBQzFCLGdCQUFnQixFQUFFLEdBQUc7WUFDckIsNkRBQTZEO1lBQzdELEdBQUcsRUFBRSxHQUFHLEVBQUU7Z0JBQ1IsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7WUFDOUIsQ0FBQztTQUNGLENBQUMsQ0FDSCxDQUFDO0lBQ0osQ0FBQzs7bUhBbFlVLHFCQUFxQixtR0FtUXRCLFdBQVc7dUdBblFWLHFCQUFxQiw0WkFSckI7UUFDVDtZQUNFLE9BQU8sRUFBRSxpQkFBaUI7WUFDMUIsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQztZQUNwRCxLQUFLLEVBQUUsSUFBSTtTQUNaO0tBQ0Ysb0xDdkRILDJEQUNBOzRGRHdEYSxxQkFBcUI7a0JBWmpDLFNBQVM7K0JBQ0UsZ0JBQWdCLGFBR2Y7d0JBQ1Q7NEJBQ0UsT0FBTyxFQUFFLGlCQUFpQjs0QkFDMUIsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsc0JBQXNCLENBQUM7NEJBQ3BELEtBQUssRUFBRSxJQUFJO3lCQUNaO3FCQUNGOzswQkFxUUUsTUFBTTsyQkFBQyxXQUFXOzRDQTNPMkIsZ0JBQWdCO3NCQUEvRCxTQUFTO3VCQUFDLGlCQUFpQixFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkFPOUMsaUJBQWlCO3NCQURoQixNQUFNO2dCQVFHLDBCQUEwQjtzQkFBbkMsTUFBTTtnQkFPRyxxQkFBcUI7c0JBQTlCLE1BQU07Z0JBT0csaUJBQWlCO3NCQUExQixNQUFNO2dCQVFNLEtBQUs7c0JBRGpCLEtBQUs7Z0JBaURGLFFBQVE7c0JBRFgsS0FBSztnQkFtRUYsV0FBVztzQkFEZCxLQUFLO2dCQXdCRixLQUFLO3NCQURSLEtBQUs7Z0JBa0JGLG9CQUFvQjtzQkFEdkIsS0FBSztnQkFjRixhQUFhO3NCQURoQixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBJbnB1dCxcbiAgT3V0cHV0LFxuICBFdmVudEVtaXR0ZXIsXG4gIE9uSW5pdCxcbiAgVmlld0NoaWxkLFxuICBFbGVtZW50UmVmLFxuICBmb3J3YXJkUmVmLFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgT25EZXN0cm95LFxuICBOZ1pvbmUsXG4gIEluamVjdCxcbiAgUExBVEZPUk1fSUQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgaXNQbGF0Zm9ybVNlcnZlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBOR19WQUxVRV9BQ0NFU1NPUiwgQ29udHJvbFZhbHVlQWNjZXNzb3IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBvZiwgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZnJvbUV2ZW50LCBtZXJnZSwgdGltZXIgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGRlYm91bmNlVGltZSwgZGlzdGluY3RVbnRpbENoYW5nZWQsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuLy8gVXNlIGVzbSB2ZXJzaW9uIHRvIHN1cHBvcnQgc2hpcHBpbmcgc3Vic2V0IG9mIGxhbmd1YWdlcyBhbmQgZmVhdHVyZXNcbmltcG9ydCB7IGVkaXRvciwgbGFuZ3VhZ2VzLCBJRGlzcG9zYWJsZSB9IGZyb20gJ21vbmFjby1lZGl0b3InO1xuXG5pbXBvcnQge1xuICBtaXhpbkNvbnRyb2xWYWx1ZUFjY2Vzc29yLFxuICBtaXhpbkRpc2FibGVkLFxufSBmcm9tICdAY292YWxlbnQvY29yZS9jb21tb24nO1xuXG5jb25zdCBub29wID0gKCkgPT4ge1xuICAvLyBlbXB0eSBtZXRob2Rcbn07XG5cbi8vIGNvdW50ZXIgZm9yIGlkcyB0byBhbGxvdyBmb3IgbXVsdGlwbGUgZWRpdG9ycyBvbiBvbmUgcGFnZVxubGV0IHVuaXF1ZUNvdW50ZXIgPSAwO1xuXG5leHBvcnQgY2xhc3MgVGRDb2RlRWRpdG9yQmFzZSB7XG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBfY2hhbmdlRGV0ZWN0b3JSZWY6IENoYW5nZURldGVjdG9yUmVmKSB7fVxufVxuXG5leHBvcnQgY29uc3QgX1RkQ29kZUVkaXRvck1peGluQmFzZSA9IG1peGluQ29udHJvbFZhbHVlQWNjZXNzb3IoXG4gIG1peGluRGlzYWJsZWQoVGRDb2RlRWRpdG9yQmFzZSksXG4gIFtdXG4pO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd0ZC1jb2RlLWVkaXRvcicsXG4gIHRlbXBsYXRlVXJsOiAnLi9jb2RlLWVkaXRvci5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2NvZGUtZWRpdG9yLmNvbXBvbmVudC5zY3NzJ10sXG4gIHByb3ZpZGVyczogW1xuICAgIHtcbiAgICAgIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxuICAgICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gVGRDb2RlRWRpdG9yQ29tcG9uZW50KSxcbiAgICAgIG11bHRpOiB0cnVlLFxuICAgIH0sXG4gIF0sXG59KVxuZXhwb3J0IGNsYXNzIFRkQ29kZUVkaXRvckNvbXBvbmVudFxuICBleHRlbmRzIF9UZENvZGVFZGl0b3JNaXhpbkJhc2VcbiAgaW1wbGVtZW50cyBPbkluaXQsIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBPbkRlc3Ryb3lcbntcbiAgcHJpdmF0ZSBfZGVzdHJveTogU3ViamVjdDxib29sZWFuPiA9IG5ldyBTdWJqZWN0PGJvb2xlYW4+KCk7XG4gIHByaXZhdGUgX3dpZHRoU3ViamVjdDogU3ViamVjdDxudW1iZXI+ID0gbmV3IFN1YmplY3Q8bnVtYmVyPigpO1xuICBwcml2YXRlIF9oZWlnaHRTdWJqZWN0OiBTdWJqZWN0PG51bWJlcj4gPSBuZXcgU3ViamVjdDxudW1iZXI+KCk7XG5cbiAgcHJpdmF0ZSBfZWRpdG9yU3R5bGUgPSAnd2lkdGg6MTAwJTtoZWlnaHQ6MTAwJTsnO1xuICBwcml2YXRlIF92YWx1ZSA9ICcnO1xuICBwcml2YXRlIF90aGVtZSA9ICd2cyc7XG4gIHByaXZhdGUgX2xhbmd1YWdlID0gJ2phdmFzY3JpcHQnO1xuICBwcml2YXRlIF9zdWJqZWN0OiBTdWJqZWN0PHN0cmluZz4gPSBuZXcgU3ViamVjdCgpO1xuICBwcml2YXRlIF9lZGl0b3JJbm5lckNvbnRhaW5lcjogc3RyaW5nID1cbiAgICAnZWRpdG9ySW5uZXJDb250YWluZXInICsgdW5pcXVlQ291bnRlcisrO1xuICBwcml2YXRlIF9lZGl0b3IhOiBlZGl0b3IuSVN0YW5kYWxvbmVDb2RlRWRpdG9yO1xuICBwcml2YXRlIF9mcm9tRWRpdG9yID0gZmFsc2U7XG4gIHByaXZhdGUgX2NvbXBvbmVudEluaXRpYWxpemVkID0gZmFsc2U7XG4gIHByaXZhdGUgX2VkaXRvck9wdGlvbnM6IGFueSA9IHt9O1xuICBwcml2YXRlIF9pc0Z1bGxTY3JlZW4gPSBmYWxzZTtcbiAgcHJpdmF0ZSBfa2V5Y29kZTogYW55O1xuICBwcml2YXRlIF9yZWdpc3RlcmVkTGFuZ3VhZ2VzU3R5bGVzOiBIVE1MU3R5bGVFbGVtZW50W10gPSBbXTtcbiAgcHJpdmF0ZSBfZGlzcG9zYWJsZXM6IElEaXNwb3NhYmxlW10gPSBbXTtcblxuICBAVmlld0NoaWxkKCdlZGl0b3JDb250YWluZXInLCB7IHN0YXRpYzogdHJ1ZSB9KSBfZWRpdG9yQ29udGFpbmVyITogRWxlbWVudFJlZjtcblxuICAvKipcbiAgICogZWRpdG9ySW5pdGlhbGl6ZWQ6IGZ1bmN0aW9uKCRldmVudClcbiAgICogRXZlbnQgZW1pdHRlZCB3aGVuIGVkaXRvciBpcyBmaXJzdCBpbml0aWFsaXplZFxuICAgKi9cbiAgQE91dHB1dCgpXG4gIGVkaXRvckluaXRpYWxpemVkOiBFdmVudEVtaXR0ZXI8ZWRpdG9yLklTdGFuZGFsb25lQ29kZUVkaXRvcj4gPVxuICAgIG5ldyBFdmVudEVtaXR0ZXI8ZWRpdG9yLklTdGFuZGFsb25lQ29kZUVkaXRvcj4oKTtcblxuICAvKipcbiAgICogZWRpdG9yQ29uZmlndXJhdGlvbkNoYW5nZWQ6IGZ1bmN0aW9uKCRldmVudClcbiAgICogRXZlbnQgZW1pdHRlZCB3aGVuIGVkaXRvcidzIGNvbmZpZ3VyYXRpb24gY2hhbmdlc1xuICAgKi9cbiAgQE91dHB1dCgpIGVkaXRvckNvbmZpZ3VyYXRpb25DaGFuZ2VkOiBFdmVudEVtaXR0ZXI8dm9pZD4gPVxuICAgIG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICAvKipcbiAgICogZWRpdG9yTGFuZ3VhZ2VDaGFuZ2VkOiBmdW5jdGlvbigkZXZlbnQpXG4gICAqIEV2ZW50IGVtaXR0ZWQgd2hlbiBlZGl0b3IncyBMYW5ndWFnZSBjaGFuZ2VzXG4gICAqL1xuICBAT3V0cHV0KCkgZWRpdG9yTGFuZ3VhZ2VDaGFuZ2VkOiBFdmVudEVtaXR0ZXI8dm9pZD4gPVxuICAgIG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICAvKipcbiAgICogZWRpdG9yVmFsdWVDaGFuZ2U6IGZ1bmN0aW9uKCRldmVudClcbiAgICogRXZlbnQgZW1pdHRlZCBhbnkgdGltZSBzb21ldGhpbmcgY2hhbmdlcyB0aGUgZWRpdG9yIHZhbHVlXG4gICAqL1xuICBAT3V0cHV0KCkgZWRpdG9yVmFsdWVDaGFuZ2U6IEV2ZW50RW1pdHRlcjx2b2lkPiA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICBwcm9wYWdhdGVDaGFuZ2UgPSAoXzogYW55KSA9PiBub29wO1xuXG4gIC8qKlxuICAgKiB2YWx1ZT86IHN0cmluZ1xuICAgKi9cbiAgQElucHV0KClcbiAgb3ZlcnJpZGUgc2V0IHZhbHVlKHZhbHVlOiBzdHJpbmcpIHtcbiAgICB0aGlzLl92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKHRoaXMuX2NvbXBvbmVudEluaXRpYWxpemVkKSB7XG4gICAgICB0aGlzLmFwcGx5VmFsdWUoKTtcbiAgICB9XG4gIH1cbiAgb3ZlcnJpZGUgZ2V0IHZhbHVlKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX3ZhbHVlO1xuICB9XG5cbiAgYXBwbHlWYWx1ZSgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuX2Zyb21FZGl0b3IpIHtcbiAgICAgIHRoaXMuX2VkaXRvci5zZXRWYWx1ZSh0aGlzLl92YWx1ZSB8fCAnJyk7XG4gICAgfVxuICAgIHRoaXMuX2Zyb21FZGl0b3IgPSBmYWxzZTtcbiAgICB0aGlzLnByb3BhZ2F0ZUNoYW5nZSh0aGlzLl92YWx1ZSk7XG4gICAgdGhpcy5lZGl0b3JWYWx1ZUNoYW5nZS5lbWl0KCk7XG4gIH1cblxuICBvdmVycmlkZSByZWdpc3Rlck9uQ2hhbmdlKGZuOiBhbnkpOiB2b2lkIHtcbiAgICB0aGlzLnByb3BhZ2F0ZUNoYW5nZSA9IGZuO1xuICB9XG4gIG92ZXJyaWRlIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiBhbnkpOiB2b2lkIHtcbiAgICB0aGlzLm9uVG91Y2hlZCA9IGZuO1xuICB9XG5cbiAgLyoqXG4gICAqIGdldEVkaXRvckNvbnRlbnQ/OiBmdW5jdGlvblxuICAgKiBSZXR1cm5zIHRoZSBjb250ZW50IHdpdGhpbiB0aGUgZWRpdG9yXG4gICAqL1xuICBnZXRWYWx1ZSgpOiBPYnNlcnZhYmxlPHN0cmluZz4ge1xuICAgIGlmICghdGhpcy5fY29tcG9uZW50SW5pdGlhbGl6ZWQpIHtcbiAgICAgIHJldHVybiBvZignJyk7XG4gICAgfVxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5fc3ViamVjdC5uZXh0KHRoaXMuX3ZhbHVlKTtcbiAgICAgIHRoaXMuX3N1YmplY3QuY29tcGxldGUoKTtcbiAgICAgIHRoaXMuX3N1YmplY3QgPSBuZXcgU3ViamVjdCgpO1xuICAgIH0pO1xuICAgIHJldHVybiB0aGlzLl9zdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIGxhbmd1YWdlPzogc3RyaW5nXG4gICAqIGxhbmd1YWdlIHVzZWQgaW4gZWRpdG9yXG4gICAqL1xuICBASW5wdXQoKVxuICBzZXQgbGFuZ3VhZ2UobGFuZ3VhZ2U6IHN0cmluZykge1xuICAgIHRoaXMuX2xhbmd1YWdlID0gbGFuZ3VhZ2U7XG4gICAgaWYgKHRoaXMuX2NvbXBvbmVudEluaXRpYWxpemVkKSB7XG4gICAgICB0aGlzLmFwcGx5TGFuZ3VhZ2UoKTtcbiAgICB9XG4gIH1cblxuICBnZXQgbGFuZ3VhZ2UoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fbGFuZ3VhZ2U7XG4gIH1cblxuICBhcHBseUxhbmd1YWdlKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLl9sYW5ndWFnZSkge1xuICAgICAgZWRpdG9yLnNldE1vZGVsTGFuZ3VhZ2UoXG4gICAgICAgIHRoaXMuX2VkaXRvci5nZXRNb2RlbCgpIGFzIGVkaXRvci5JVGV4dE1vZGVsLFxuICAgICAgICB0aGlzLl9sYW5ndWFnZVxuICAgICAgKTtcbiAgICAgIHRoaXMuZWRpdG9yTGFuZ3VhZ2VDaGFuZ2VkLmVtaXQoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogcmVnaXN0ZXJMYW5ndWFnZT86IGZ1bmN0aW9uXG4gICAqIFJlZ2lzdGVycyBhIGN1c3RvbSBMYW5ndWFnZSB3aXRoaW4gdGhlIGVkaXRvclxuICAgKi9cbiAgcmVnaXN0ZXJMYW5ndWFnZShsYW5ndWFnZTogYW55KTogdm9pZCB7XG4gICAgaWYgKHRoaXMuX2NvbXBvbmVudEluaXRpYWxpemVkKSB7XG4gICAgICBsYW5ndWFnZXMucmVnaXN0ZXIoeyBpZDogbGFuZ3VhZ2UuaWQgfSk7XG5cbiAgICAgIHRoaXMuX2Rpc3Bvc2FibGVzLnB1c2goXG4gICAgICAgIGxhbmd1YWdlcy5zZXRNb25hcmNoVG9rZW5zUHJvdmlkZXIobGFuZ3VhZ2UuaWQsIHtcbiAgICAgICAgICB0b2tlbml6ZXI6IHtcbiAgICAgICAgICAgIHJvb3Q6IGxhbmd1YWdlLm1vbmFyY2hUb2tlbnNQcm92aWRlcixcbiAgICAgICAgICB9LFxuICAgICAgICB9KVxuICAgICAgKTtcblxuICAgICAgLy8gRGVmaW5lIGEgbmV3IHRoZW1lIHRoYXQgY29uc3RhaW5zIG9ubHkgcnVsZXMgdGhhdCBtYXRjaCB0aGlzIGxhbmd1YWdlXG4gICAgICBlZGl0b3IuZGVmaW5lVGhlbWUobGFuZ3VhZ2UuY3VzdG9tVGhlbWUuaWQsIGxhbmd1YWdlLmN1c3RvbVRoZW1lLnRoZW1lKTtcbiAgICAgIHRoaXMuX3RoZW1lID0gbGFuZ3VhZ2UuY3VzdG9tVGhlbWUuaWQ7XG5cbiAgICAgIHRoaXMuX2Rpc3Bvc2FibGVzLnB1c2goXG4gICAgICAgIGxhbmd1YWdlcy5yZWdpc3RlckNvbXBsZXRpb25JdGVtUHJvdmlkZXIobGFuZ3VhZ2UuaWQsIHtcbiAgICAgICAgICBwcm92aWRlQ29tcGxldGlvbkl0ZW1zOiAoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gbGFuZ3VhZ2UuY29tcGxldGlvbkl0ZW1Qcm92aWRlcjtcbiAgICAgICAgICB9LFxuICAgICAgICB9KVxuICAgICAgKTtcblxuICAgICAgY29uc3QgY3NzOiBIVE1MU3R5bGVFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3R5bGUnKTtcbiAgICAgIGNzcy50eXBlID0gJ3RleHQvY3NzJztcbiAgICAgIGNzcy5pbm5lckhUTUwgPSBsYW5ndWFnZS5tb25hcmNoVG9rZW5zUHJvdmlkZXJDU1M7XG4gICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGNzcyk7XG4gICAgICB0aGlzLmVkaXRvckNvbmZpZ3VyYXRpb25DaGFuZ2VkLmVtaXQoKTtcbiAgICAgIHRoaXMuX3JlZ2lzdGVyZWRMYW5ndWFnZXNTdHlsZXMgPSBbXG4gICAgICAgIC4uLnRoaXMuX3JlZ2lzdGVyZWRMYW5ndWFnZXNTdHlsZXMsXG4gICAgICAgIGNzcyxcbiAgICAgIF07XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIHN0eWxlPzogc3RyaW5nXG4gICAqIGNzcyBzdHlsZSBvZiB0aGUgZWRpdG9yIG9uIHRoZSBwYWdlXG4gICAqL1xuICBASW5wdXQoKVxuICBzZXQgZWRpdG9yU3R5bGUoZWRpdG9yU3R5bGU6IHN0cmluZykge1xuICAgIHRoaXMuX2VkaXRvclN0eWxlID0gZWRpdG9yU3R5bGU7XG4gICAgaWYgKHRoaXMuX2NvbXBvbmVudEluaXRpYWxpemVkKSB7XG4gICAgICB0aGlzLmFwcGx5U3R5bGUoKTtcbiAgICB9XG4gIH1cblxuICBnZXQgZWRpdG9yU3R5bGUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fZWRpdG9yU3R5bGU7XG4gIH1cblxuICBhcHBseVN0eWxlKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLl9lZGl0b3JTdHlsZSkge1xuICAgICAgY29uc3QgY29udGFpbmVyRGl2OiBIVE1MRGl2RWxlbWVudCA9IHRoaXMuX2VkaXRvckNvbnRhaW5lci5uYXRpdmVFbGVtZW50O1xuICAgICAgY29udGFpbmVyRGl2LnNldEF0dHJpYnV0ZSgnc3R5bGUnLCB0aGlzLl9lZGl0b3JTdHlsZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIHRoZW1lPzogc3RyaW5nXG4gICAqIFRoZW1lIHRvIGJlIGFwcGxpZWQgdG8gZWRpdG9yXG4gICAqL1xuICBASW5wdXQoKVxuICBzZXQgdGhlbWUodGhlbWU6IHN0cmluZykge1xuICAgIHRoaXMuX3RoZW1lID0gdGhlbWU7XG4gICAgaWYgKHRoaXMuX2NvbXBvbmVudEluaXRpYWxpemVkKSB7XG4gICAgICB0aGlzLl9lZGl0b3IudXBkYXRlT3B0aW9ucyh7IHRoZW1lIH0pO1xuICAgICAgdGhpcy5lZGl0b3JDb25maWd1cmF0aW9uQ2hhbmdlZC5lbWl0KCk7XG4gICAgfVxuICB9XG4gIGdldCB0aGVtZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLl90aGVtZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBmdWxsU2NyZWVuS2V5QmluZGluZz86IG51bWJlclxuICAgKiBTZWUgaGVyZSBmb3Iga2V5IGJpbmRpbmdzIGh0dHBzOi8vbWljcm9zb2Z0LmdpdGh1Yi5pby9tb25hY28tZWRpdG9yL2FwaS9lbnVtcy9rZXljb2RlLmh0bWxcbiAgICogU2V0cyB0aGUgS2V5Q29kZSBmb3Igc2hvcnRjdXR0aW5nIHRvIEZ1bGxzY3JlZW4gbW9kZVxuICAgKi9cbiAgQElucHV0KClcbiAgc2V0IGZ1bGxTY3JlZW5LZXlCaW5kaW5nKGtleWNvZGU6IG51bWJlcltdKSB7XG4gICAgdGhpcy5fa2V5Y29kZSA9IGtleWNvZGU7XG4gIH1cbiAgZ2V0IGZ1bGxTY3JlZW5LZXlCaW5kaW5nKCk6IG51bWJlcltdIHtcbiAgICByZXR1cm4gdGhpcy5fa2V5Y29kZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBlZGl0b3JPcHRpb25zPzogb2JqZWN0XG4gICAqIE9wdGlvbnMgdXNlZCBvbiBlZGl0b3IgaW5zdGFudGlhdGlvbi4gQXZhaWxhYmxlIG9wdGlvbnMgbGlzdGVkIGhlcmU6XG4gICAqIGh0dHBzOi8vbWljcm9zb2Z0LmdpdGh1Yi5pby9tb25hY28tZWRpdG9yL2FwaS9pbnRlcmZhY2VzL2VkaXRvci5pZWRpdG9yb3B0aW9ucy5odG1sXG4gICAqL1xuICBASW5wdXQoKVxuICBzZXQgZWRpdG9yT3B0aW9ucyhlZGl0b3JPcHRpb25zOiBhbnkpIHtcbiAgICB0aGlzLl9lZGl0b3JPcHRpb25zID0gZWRpdG9yT3B0aW9ucztcbiAgICBpZiAodGhpcy5fY29tcG9uZW50SW5pdGlhbGl6ZWQpIHtcbiAgICAgIHRoaXMuX2VkaXRvci51cGRhdGVPcHRpb25zKGVkaXRvck9wdGlvbnMpO1xuICAgICAgdGhpcy5lZGl0b3JDb25maWd1cmF0aW9uQ2hhbmdlZC5lbWl0KCk7XG4gICAgfVxuICB9XG4gIGdldCBlZGl0b3JPcHRpb25zKCk6IGFueSB7XG4gICAgcmV0dXJuIHRoaXMuX2VkaXRvck9wdGlvbnM7XG4gIH1cblxuICAvKipcbiAgICogbGF5b3V0IG1ldGhvZCB0aGF0IGNhbGxzIGxheW91dCBtZXRob2Qgb2YgZWRpdG9yIGFuZCBpbnN0cnVjdHMgdGhlIGVkaXRvciB0byByZW1lYXN1cmUgaXRzIGNvbnRhaW5lclxuICAgKi9cbiAgbGF5b3V0KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLl9jb21wb25lbnRJbml0aWFsaXplZCkge1xuICAgICAgdGhpcy5fZWRpdG9yLmxheW91dCgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGlmIGluIEZ1bGwgU2NyZWVuIE1vZGUgb3Igbm90XG4gICAqL1xuICBnZXQgaXNGdWxsU2NyZWVuKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9pc0Z1bGxTY3JlZW47XG4gIH1cblxuICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bWVtYmVyLW9yZGVyaW5nXG4gIGNvbnN0cnVjdG9yKFxuICAgIF9jaGFuZ2VEZXRlY3RvclJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgcHJpdmF0ZSBfZWxlbWVudFJlZjogRWxlbWVudFJlZjxIVE1MRWxlbWVudD4sXG4gICAgcHJpdmF0ZSBfbmdab25lOiBOZ1pvbmUsXG4gICAgQEluamVjdChQTEFURk9STV9JRCkgcHJpdmF0ZSBwbGF0Zm9ybUlkOiBzdHJpbmdcbiAgKSB7XG4gICAgc3VwZXIoX2NoYW5nZURldGVjdG9yUmVmKTtcbiAgfVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIGlmIChpc1BsYXRmb3JtU2VydmVyKHRoaXMucGxhdGZvcm1JZCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBjb250YWluZXJEaXY6IEhUTUxEaXZFbGVtZW50ID0gdGhpcy5fZWRpdG9yQ29udGFpbmVyLm5hdGl2ZUVsZW1lbnQ7XG4gICAgY29udGFpbmVyRGl2LmlkID0gdGhpcy5fZWRpdG9ySW5uZXJDb250YWluZXI7XG5cbiAgICB0aGlzLl9lZGl0b3IgPSBlZGl0b3IuY3JlYXRlKFxuICAgICAgY29udGFpbmVyRGl2LFxuICAgICAgT2JqZWN0LmFzc2lnbihcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiB0aGlzLl92YWx1ZSxcbiAgICAgICAgICBsYW5ndWFnZTogdGhpcy5sYW5ndWFnZSxcbiAgICAgICAgICB0aGVtZTogdGhpcy5fdGhlbWUsXG4gICAgICAgIH0sXG4gICAgICAgIHRoaXMuZWRpdG9yT3B0aW9uc1xuICAgICAgKVxuICAgICk7XG4gICAgdGhpcy5fY29tcG9uZW50SW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5hcHBseUxhbmd1YWdlKCk7XG4gICAgICB0aGlzLl9mcm9tRWRpdG9yID0gdHJ1ZTtcbiAgICAgIHRoaXMuYXBwbHlWYWx1ZSgpO1xuICAgICAgdGhpcy5hcHBseVN0eWxlKCk7XG4gICAgICB0aGlzLmVkaXRvckluaXRpYWxpemVkLmVtaXQodGhpcy5fZWRpdG9yKTtcbiAgICAgIHRoaXMuZWRpdG9yQ29uZmlndXJhdGlvbkNoYW5nZWQuZW1pdCgpO1xuICAgIH0pO1xuICAgIC8vIFRoZSBgb25EaWRDaGFuZ2VDb250ZW50YCByZXR1cm5zIGEgZGlzcG9zYWJsZSBvYmplY3QgKGFuIG9iamVjdCB3aXRoIGBkaXNwb3NlKClgIG1ldGhvZCkgd2hpY2ggd2lsbCBjbGVhbnVwXG4gICAgLy8gdGhlIGxpc3RlbmVyLiBUaGUgY2FsbGJhY2ssIHRoYXQgd2UgcGFzcyB0byBgb25EaWRDaGFuZ2VDb250ZW50YCwgY2FwdHVyZXMgYHRoaXNgLiBUaGlzIGxlYWRzIHRvIGEgY2lyY3VsYXIgcmVmZXJlbmNlXG4gICAgLy8gKGB0ZC1jb2RlLWVkaXRvciAtPiBtb25hY28gLT4gdGQtY29kZS1lZGl0b3JgKSBhbmQgcHJldmVudHMgdGhlIGB0ZC1jb2RlLWVkaXRvcmAgZnJvbSBiZWluZyBHQydkLlxuICAgIHRoaXMuX2Rpc3Bvc2FibGVzLnB1c2goXG4gICAgICAodGhpcy5fZWRpdG9yLmdldE1vZGVsKCkgYXMgZWRpdG9yLklUZXh0TW9kZWwpLm9uRGlkQ2hhbmdlQ29udGVudCgoKSA9PiB7XG4gICAgICAgIHRoaXMuX2Zyb21FZGl0b3IgPSB0cnVlO1xuICAgICAgICB0aGlzLndyaXRlVmFsdWUodGhpcy5fZWRpdG9yLmdldFZhbHVlKCkpO1xuICAgICAgICB0aGlzLmxheW91dCgpO1xuICAgICAgfSlcbiAgICApO1xuICAgIHRoaXMuYWRkRnVsbFNjcmVlbk1vZGVDb21tYW5kKCk7XG5cbiAgICB0aGlzLl9uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT5cbiAgICAgIG1lcmdlKFxuICAgICAgICBmcm9tRXZlbnQod2luZG93LCAncmVzaXplJykucGlwZShkZWJvdW5jZVRpbWUoMTAwKSksXG4gICAgICAgIHRoaXMuX3dpZHRoU3ViamVjdC5hc09ic2VydmFibGUoKS5waXBlKGRpc3RpbmN0VW50aWxDaGFuZ2VkKCkpLFxuICAgICAgICB0aGlzLl9oZWlnaHRTdWJqZWN0LmFzT2JzZXJ2YWJsZSgpLnBpcGUoZGlzdGluY3RVbnRpbENoYW5nZWQoKSlcbiAgICAgIClcbiAgICAgICAgLnBpcGUoZGVib3VuY2VUaW1lKDEwMCksIHRha2VVbnRpbCh0aGlzLl9kZXN0cm95KSlcbiAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgLy8gTm90ZTogdGhpcyBpcyBiZWluZyBjYWxsZWQgb3V0c2lkZSBvZiB0aGUgQW5ndWxhciB6b25lIHNpbmNlIHdlIGRvbid0IGhhdmUgdG9cbiAgICAgICAgICAvLyBydW4gY2hhbmdlIGRldGVjdGlvbiB3aGVuZXZlciB0aGUgZWRpdG9yIHJlc2l6ZXMgaXRzZWxmLlxuICAgICAgICAgIHRoaXMubGF5b3V0KCk7XG4gICAgICAgIH0pXG4gICAgKTtcbiAgICB0aGlzLl9uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT5cbiAgICAgIHRpbWVyKDUwMCwgMjUwKVxuICAgICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5fZGVzdHJveSkpXG4gICAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgd2lkdGgsIGhlaWdodCB9ID1cbiAgICAgICAgICAgIHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICB0aGlzLl93aWR0aFN1YmplY3QubmV4dCh3aWR0aCk7XG4gICAgICAgICAgdGhpcy5faGVpZ2h0U3ViamVjdC5uZXh0KGhlaWdodCk7XG4gICAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuX2NoYW5nZURldGVjdG9yUmVmLmRldGFjaCgpO1xuICAgIHRoaXMuX3JlZ2lzdGVyZWRMYW5ndWFnZXNTdHlsZXMuZm9yRWFjaCgoc3R5bGU6IEhUTUxTdHlsZUVsZW1lbnQpID0+XG4gICAgICBzdHlsZS5yZW1vdmUoKVxuICAgICk7XG4gICAgd2hpbGUgKHRoaXMuX2Rpc3Bvc2FibGVzLmxlbmd0aCkge1xuICAgICAgdGhpcy5fZGlzcG9zYWJsZXMucG9wKCk/LmRpc3Bvc2UoKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuX2VkaXRvcikge1xuICAgICAgdGhpcy5fZWRpdG9yLmRpc3Bvc2UoKTtcbiAgICB9XG4gICAgdGhpcy5fZGVzdHJveS5uZXh0KHRydWUpO1xuICAgIHRoaXMuX2Rlc3Ryb3kudW5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBzaG93RnVsbFNjcmVlbkVkaXRvciByZXF1ZXN0IGZvciBmdWxsIHNjcmVlbiBvZiBDb2RlIEVkaXRvciBiYXNlZCBvbiBpdHMgYnJvd3NlciB0eXBlLlxuICAgKi9cbiAgcHVibGljIHNob3dGdWxsU2NyZWVuRWRpdG9yKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLl9jb21wb25lbnRJbml0aWFsaXplZCkge1xuICAgICAgY29uc3QgY29kZUVkaXRvckVsZW1lbnQ6IEhUTUxEaXZFbGVtZW50ID0gdGhpcy5fZWRpdG9yQ29udGFpbmVyXG4gICAgICAgIC5uYXRpdmVFbGVtZW50IGFzIEhUTUxEaXZFbGVtZW50O1xuICAgICAgY29kZUVkaXRvckVsZW1lbnQucmVxdWVzdEZ1bGxzY3JlZW4oKTtcbiAgICB9XG4gICAgdGhpcy5faXNGdWxsU2NyZWVuID0gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBleGl0RnVsbFNjcmVlbkVkaXRvciByZXF1ZXN0IHRvIGV4aXQgZnVsbCBzY3JlZW4gb2YgQ29kZSBFZGl0b3IgYmFzZWQgb24gaXRzIGJyb3dzZXIgdHlwZS5cbiAgICovXG4gIHB1YmxpYyBleGl0RnVsbFNjcmVlbkVkaXRvcigpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fY29tcG9uZW50SW5pdGlhbGl6ZWQpIHtcbiAgICAgIGRvY3VtZW50LmV4aXRGdWxsc2NyZWVuKCk7XG4gICAgfVxuICAgIHRoaXMuX2lzRnVsbFNjcmVlbiA9IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIGFkZEZ1bGxTY3JlZW5Nb2RlQ29tbWFuZCB1c2VkIHRvIGFkZCB0aGUgZnVsbHNjcmVlbiBvcHRpb24gdG8gdGhlIGNvbnRleHQgbWVudVxuICAgKi9cbiAgcHJpdmF0ZSBhZGRGdWxsU2NyZWVuTW9kZUNvbW1hbmQoKTogdm9pZCB7XG4gICAgdGhpcy5fZGlzcG9zYWJsZXMucHVzaChcbiAgICAgIHRoaXMuX2VkaXRvci5hZGRBY3Rpb24oe1xuICAgICAgICAvLyBBbiB1bmlxdWUgaWRlbnRpZmllciBvZiB0aGUgY29udHJpYnV0ZWQgYWN0aW9uLlxuICAgICAgICBpZDogJ2Z1bGxTY3JlZW4nLFxuICAgICAgICAvLyBBIGxhYmVsIG9mIHRoZSBhY3Rpb24gdGhhdCB3aWxsIGJlIHByZXNlbnRlZCB0byB0aGUgdXNlci5cbiAgICAgICAgbGFiZWw6ICdGdWxsIFNjcmVlbicsXG4gICAgICAgIC8vIEFuIG9wdGlvbmFsIGFycmF5IG9mIGtleWJpbmRpbmdzIGZvciB0aGUgYWN0aW9uLlxuICAgICAgICBjb250ZXh0TWVudUdyb3VwSWQ6ICduYXZpZ2F0aW9uJyxcbiAgICAgICAga2V5YmluZGluZ3M6IHRoaXMuX2tleWNvZGUsXG4gICAgICAgIGNvbnRleHRNZW51T3JkZXI6IDEuNSxcbiAgICAgICAgLy8gTWV0aG9kIHRoYXQgd2lsbCBiZSBleGVjdXRlZCB3aGVuIHRoZSBhY3Rpb24gaXMgdHJpZ2dlcmVkLlxuICAgICAgICBydW46ICgpID0+IHtcbiAgICAgICAgICB0aGlzLnNob3dGdWxsU2NyZWVuRWRpdG9yKCk7XG4gICAgICAgIH0sXG4gICAgICB9KVxuICAgICk7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJlZGl0b3ItY29udGFpbmVyXCIgI2VkaXRvckNvbnRhaW5lcj48L2Rpdj5cbiJdfQ==