carbon-components-angular
Version:
Next generation components
507 lines • 46.3 kB
JavaScript
import { ChangeDetectionStrategy, Component, EventEmitter, Inject, Input, Optional, Output, TemplateRef, ViewChild, HostListener } from "@angular/core";
import { NG_VALUE_ACCESSOR } from "@angular/forms";
import { CHECKBOX_GROUP_HOST } from "./checkbox-group-host";
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "carbon-components-angular/icon";
/**
* Defines the set of states for a checkbox component.
*/
export var CheckboxState;
(function (CheckboxState) {
CheckboxState[CheckboxState["Init"] = 0] = "Init";
CheckboxState[CheckboxState["Indeterminate"] = 1] = "Indeterminate";
CheckboxState[CheckboxState["Checked"] = 2] = "Checked";
CheckboxState[CheckboxState["Unchecked"] = 3] = "Unchecked";
})(CheckboxState || (CheckboxState = {}));
/**
* Get started with importing the module:
*
* ```typescript
* import { CheckboxModule } from 'carbon-components-angular';
* ```
*
* [See demo](../../?path=/story/components-checkbox--basic)
*/
export class Checkbox {
/**
* Creates an instance of `Checkbox`.
*/
constructor(changeDetectorRef, hostGroup) {
this.changeDetectorRef = changeDetectorRef;
this.hostGroup = hostGroup;
/**
* Set to `true` for a disabled checkbox.
*/
this.disabled = false;
/**
* Set to `true` for a loading checkbox.
*/
this.skeleton = false;
/**
* Set to `true` to hide the checkbox labels.
*/
this.hideLabel = false;
/**
* The unique id for the checkbox component.
*/
this.id = `checkbox-${Checkbox.checkboxCount}`;
/**
* Optional title for the `<label>` element.
*/
this.title = "";
/**
* Emits click event.
*/
this.click = new EventEmitter();
/**
* Emits an event when the value of the checkbox changes.
*
* Allows double biding with the `checked` Input.
*/
this.checkedChange = new EventEmitter();
/**
* Emits event notifying other classes when a change in state occurs specifically
* on an indeterminate checkbox.
*/
this.indeterminateChange = new EventEmitter();
/**
* Set to `true` if the input checkbox is selected (or checked).
*/
this._checked = false;
/**
* Set to `true` if the input checkbox is in state indeterminate.
*/
this._indeterminate = false;
/**
* Keeps a reference to the checkboxes current state, as defined in `CheckboxState`.
*/
this.currentCheckboxState = CheckboxState.Init;
this.helperId = `checkbox-helper-${Checkbox.helperIdCounter++}`;
/**
* Called when checkbox is blurred. Needed to properly implement `ControlValueAccessor`.
*/
this.onTouched = () => { };
/**
* Method set in `registerOnChange` to propagate changes back to the form.
*/
this.propagateChange = (_) => { };
Checkbox.checkboxCount++;
}
/**
* Set the checkbox's indeterminate state to match the parameter and transition the view to reflect the change.
*
* Allows double binding with the `indeterminateChange` Output.
*/
set indeterminate(indeterminate) {
if (indeterminate === this._indeterminate) {
return;
}
this._indeterminate = indeterminate;
if (this._indeterminate) {
this.transitionCheckboxState(CheckboxState.Indeterminate);
}
else {
this.transitionCheckboxState(this.checked ? CheckboxState.Checked : CheckboxState.Unchecked);
}
if (this.inputCheckbox && this.inputCheckbox.nativeElement) {
this.inputCheckbox.nativeElement.indeterminate = indeterminate;
}
this.changeDetectorRef.markForCheck();
this.indeterminateChange.emit(this._indeterminate);
}
/**
* Reflects whether the checkbox state is indeterminate.
*/
get indeterminate() {
return this._indeterminate;
}
/**
* Sets the `checked` state. `true` for checked, `false` for unchecked
*
* Allows double binding with the `checkedChange` Output.
*/
set checked(checked) {
this.setChecked(checked, false);
}
/**
* Returns value `true` if state is selected for the checkbox.
*/
get checked() {
return this._checked;
}
get effectiveReadOnly() {
const own = this.readOnly;
const group = this.hostGroup?.readOnly ?? false;
return !!(own !== undefined ? own : group);
}
get effectiveInvalid() {
const own = this.invalid;
const group = this.hostGroup?.invalid ?? false;
return !!(own !== undefined ? own : group);
}
get effectiveWarn() {
const own = this.warn;
const group = this.hostGroup?.warn ?? false;
return !!(own !== undefined ? own : group);
}
/**
* Toggle the selected state of the checkbox.
*/
toggle() {
if (this.effectiveReadOnly) {
return;
}
// Flip checked and reset indeterminate
this.setChecked(!this.checked, true);
}
/**
* Writes a value from `ngModel` to the component.
*
* In this case the value is the `checked` property.
*
* @param value boolean, corresponds to the `checked` property.
*/
writeValue(value) {
// Set checked and reset indeterminate
this.setChecked(!!value, true);
}
/**
* Sets a method in order to propagate changes back to the form.
*/
registerOnChange(fn) {
this.propagateChange = fn;
}
/**
* Registers a callback to be triggered when the control has been touched.
* @param fn Callback to be triggered when the checkbox is touched.
*/
registerOnTouched(fn) {
this.onTouched = fn;
}
/**
* `ControlValueAccessor` method to programmatically disable the checkbox.
*
* ex: `this.formGroup.get("myCheckbox").disable();`
*
* @param isDisabled `true` to disable the checkbox
*/
setDisabledState(isDisabled) {
this.disabled = isDisabled;
this.changeDetectorRef.markForCheck();
}
/**
* Invoked by `CheckboxGroup` when group `readOnly`, `invalid`, `warn` change so `OnPush`
* checkboxes still refresh inherited state from `CHECKBOX_GROUP_HOST`.
*/
markForCheckFromGroup() {
this.changeDetectorRef.markForCheck();
}
focusOut() {
this.onTouched();
}
/**
* Executes on the event of a change within `Checkbox` to block propagation.
*/
onChange(event) {
event.stopPropagation();
}
/**
* Handles click events on the `Checkbox` and emits changes to other classes.
*/
onClick(event) {
if (this.effectiveReadOnly) {
event.preventDefault();
if (this.click.observers.length) {
this.click.emit();
}
return;
}
if (this.click.observers.length) {
// Disable default checkbox activation behavior which flips checked and resets indeterminate.
// This allows the parent component to control the checked/indeterminate properties.
event.preventDefault();
this.click.emit();
return;
}
if (!this.disabled) {
this.toggle();
this.transitionCheckboxState(this._checked ? CheckboxState.Checked : CheckboxState.Unchecked);
this.emitChangeEvent();
}
}
/**
* Handles changes between checkbox states.
*/
transitionCheckboxState(newState) {
this.currentCheckboxState = newState;
}
/**
* Creates instance of `CheckboxChange` used to propagate the change event.
*/
emitChangeEvent() {
this.checkedChange.emit(this.checked);
this.propagateChange(this.checked);
}
/**
* Updates the checkbox if it is in the indeterminate state.
*/
ngAfterViewInit() {
if (this.indeterminate && this.inputCheckbox && this.inputCheckbox.nativeElement) {
this.inputCheckbox.nativeElement.indeterminate = true;
}
}
/**
* Returns `true` when the provided value is a `TemplateRef`.
*/
isTemplate(value) {
return value instanceof TemplateRef;
}
/**
* Sets checked state and optionally resets indeterminate state.
*/
setChecked(checked, resetIndeterminate) {
if (checked === this._checked) {
return;
}
this._checked = checked;
// Reset indeterminate if requested
if (resetIndeterminate && this._indeterminate) {
this._indeterminate = false;
Promise.resolve().then(() => {
this.indeterminateChange.emit(this._indeterminate);
});
}
this.changeDetectorRef.markForCheck();
}
}
/**
* Variable used for creating unique ids for checkbox components.
*/
Checkbox.checkboxCount = 0;
Checkbox.helperIdCounter = 0;
Checkbox.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: Checkbox, deps: [{ token: i0.ChangeDetectorRef }, { token: CHECKBOX_GROUP_HOST, optional: true }], target: i0.ɵɵFactoryTarget.Component });
Checkbox.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: Checkbox, selector: "cds-checkbox, ibm-checkbox", inputs: { disabled: "disabled", skeleton: "skeleton", hideLabel: "hideLabel", name: "name", id: "id", required: "required", value: "value", ariaLabel: "ariaLabel", ariaLabelledby: "ariaLabelledby", title: "title", helperText: "helperText", invalid: "invalid", invalidText: "invalidText", warn: "warn", warnText: "warnText", readOnly: "readOnly", decorator: "decorator", indeterminate: "indeterminate", checked: "checked" }, outputs: { click: "click", checkedChange: "checkedChange", indeterminateChange: "indeterminateChange" }, host: { listeners: { "focusout": "focusOut()" } }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: Checkbox,
multi: true
}
], viewQueries: [{ propertyName: "inputCheckbox", first: true, predicate: ["inputCheckbox"], descendants: true }], ngImport: i0, template: `
<div class="cds--form-item cds--checkbox-wrapper"
[ngClass]="{
'cds--checkbox-wrapper--invalid': !effectiveReadOnly && effectiveInvalid,
'cds--checkbox-wrapper--warning': !effectiveReadOnly && !effectiveInvalid && effectiveWarn,
'cds--checkbox-wrapper--readonly': effectiveReadOnly,
'cds--checkbox-wrapper--decorator': !!decorator
}">
<input
#inputCheckbox
class="cds--checkbox"
type="checkbox"
[id]="id + '_input'"
[value]="value"
[name]="name"
[required]="required"
[checked]="checked"
[disabled]="disabled"
[attr.data-invalid]="(!effectiveReadOnly && effectiveInvalid) ? true : null"
[attr.aria-readonly]="effectiveReadOnly ? true : null"
[attr.aria-labelledby]="ariaLabelledby"
[attr.aria-describedby]="(helperText && !effectiveInvalid && !effectiveWarn) ? helperId : null"
(change)="onChange($event)"
(click)="onClick($event)">
<label
[for]="id + '_input'"
[attr.aria-label]="ariaLabel"
[attr.title]="title || null"
class="cds--checkbox-label"
[ngClass]="{
'cds--skeleton' : skeleton
}">
<span [ngClass]="{'cds--visually-hidden' : hideLabel}" class="cds--checkbox-label-text">
<ng-content></ng-content>
<ng-container *ngIf="decorator">
<div class="cds--checkbox-wrapper-inner--decorator">
<ng-template [ngTemplateOutlet]="decorator"></ng-template>
</div>
</ng-container>
</span>
</label>
<div class="cds--checkbox__validation-msg">
<ng-container *ngIf="!effectiveReadOnly && effectiveInvalid">
<svg
cdsIcon="warning--filled"
size="16"
class="cds--checkbox__invalid-icon">
</svg>
<div class="cds--form-requirement">
<ng-container *ngIf="!isTemplate(invalidText)">{{invalidText}}</ng-container>
<ng-template *ngIf="isTemplate(invalidText)" [ngTemplateOutlet]="$any(invalidText)"></ng-template>
</div>
</ng-container>
<ng-container *ngIf="!effectiveReadOnly && !effectiveInvalid && effectiveWarn">
<svg
cdsIcon="warning--alt--filled"
size="16"
class="cds--checkbox__invalid-icon cds--checkbox__invalid-icon--warning">
</svg>
<div class="cds--form-requirement">
<ng-container *ngIf="!isTemplate(warnText)">{{warnText}}</ng-container>
<ng-template *ngIf="isTemplate(warnText)" [ngTemplateOutlet]="$any(warnText)"></ng-template>
</div>
</ng-container>
</div>
<div
*ngIf="helperText && !effectiveInvalid && !effectiveWarn"
class="cds--form__helper-text"
[id]="helperId">
<ng-container *ngIf="!isTemplate(helperText)">{{helperText}}</ng-container>
<ng-template *ngIf="isTemplate(helperText)" [ngTemplateOutlet]="$any(helperText)"></ng-template>
</div>
</div>
`, isInline: true, dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: Checkbox, decorators: [{
type: Component,
args: [{
selector: "cds-checkbox, ibm-checkbox",
template: `
<div class="cds--form-item cds--checkbox-wrapper"
[ngClass]="{
'cds--checkbox-wrapper--invalid': !effectiveReadOnly && effectiveInvalid,
'cds--checkbox-wrapper--warning': !effectiveReadOnly && !effectiveInvalid && effectiveWarn,
'cds--checkbox-wrapper--readonly': effectiveReadOnly,
'cds--checkbox-wrapper--decorator': !!decorator
}">
<input
#inputCheckbox
class="cds--checkbox"
type="checkbox"
[id]="id + '_input'"
[value]="value"
[name]="name"
[required]="required"
[checked]="checked"
[disabled]="disabled"
[attr.data-invalid]="(!effectiveReadOnly && effectiveInvalid) ? true : null"
[attr.aria-readonly]="effectiveReadOnly ? true : null"
[attr.aria-labelledby]="ariaLabelledby"
[attr.aria-describedby]="(helperText && !effectiveInvalid && !effectiveWarn) ? helperId : null"
(change)="onChange($event)"
(click)="onClick($event)">
<label
[for]="id + '_input'"
[attr.aria-label]="ariaLabel"
[attr.title]="title || null"
class="cds--checkbox-label"
[ngClass]="{
'cds--skeleton' : skeleton
}">
<span [ngClass]="{'cds--visually-hidden' : hideLabel}" class="cds--checkbox-label-text">
<ng-content></ng-content>
<ng-container *ngIf="decorator">
<div class="cds--checkbox-wrapper-inner--decorator">
<ng-template [ngTemplateOutlet]="decorator"></ng-template>
</div>
</ng-container>
</span>
</label>
<div class="cds--checkbox__validation-msg">
<ng-container *ngIf="!effectiveReadOnly && effectiveInvalid">
<svg
cdsIcon="warning--filled"
size="16"
class="cds--checkbox__invalid-icon">
</svg>
<div class="cds--form-requirement">
<ng-container *ngIf="!isTemplate(invalidText)">{{invalidText}}</ng-container>
<ng-template *ngIf="isTemplate(invalidText)" [ngTemplateOutlet]="$any(invalidText)"></ng-template>
</div>
</ng-container>
<ng-container *ngIf="!effectiveReadOnly && !effectiveInvalid && effectiveWarn">
<svg
cdsIcon="warning--alt--filled"
size="16"
class="cds--checkbox__invalid-icon cds--checkbox__invalid-icon--warning">
</svg>
<div class="cds--form-requirement">
<ng-container *ngIf="!isTemplate(warnText)">{{warnText}}</ng-container>
<ng-template *ngIf="isTemplate(warnText)" [ngTemplateOutlet]="$any(warnText)"></ng-template>
</div>
</ng-container>
</div>
<div
*ngIf="helperText && !effectiveInvalid && !effectiveWarn"
class="cds--form__helper-text"
[id]="helperId">
<ng-container *ngIf="!isTemplate(helperText)">{{helperText}}</ng-container>
<ng-template *ngIf="isTemplate(helperText)" [ngTemplateOutlet]="$any(helperText)"></ng-template>
</div>
</div>
`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: Checkbox,
multi: true
}
],
changeDetection: ChangeDetectionStrategy.OnPush
}]
}], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [CHECKBOX_GROUP_HOST]
}] }]; }, propDecorators: { disabled: [{
type: Input
}], skeleton: [{
type: Input
}], hideLabel: [{
type: Input
}], name: [{
type: Input
}], id: [{
type: Input
}], required: [{
type: Input
}], value: [{
type: Input
}], ariaLabel: [{
type: Input
}], ariaLabelledby: [{
type: Input
}], title: [{
type: Input
}], helperText: [{
type: Input
}], invalid: [{
type: Input
}], invalidText: [{
type: Input
}], warn: [{
type: Input
}], warnText: [{
type: Input
}], readOnly: [{
type: Input
}], decorator: [{
type: Input
}], indeterminate: [{
type: Input
}], checked: [{
type: Input
}], click: [{
type: Output
}], checkedChange: [{
type: Output
}], indeterminateChange: [{
type: Output
}], inputCheckbox: [{
type: ViewChild,
args: ["inputCheckbox"]
}], focusOut: [{
type: HostListener,
args: ["focusout"]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hlY2tib3guY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NoZWNrYm94L2NoZWNrYm94LmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRU4sdUJBQXVCLEVBRXZCLFNBQVMsRUFFVCxZQUFZLEVBQ1osTUFBTSxFQUNOLEtBQUssRUFDTCxRQUFRLEVBQ1IsTUFBTSxFQUNOLFdBQVcsRUFDWCxTQUFTLEVBQ1QsWUFBWSxFQUNaLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxpQkFBaUIsRUFBd0IsTUFBTSxnQkFBZ0IsQ0FBQztBQUV6RSxPQUFPLEVBQUUsbUJBQW1CLEVBQXFCLE1BQU0sdUJBQXVCLENBQUM7Ozs7QUFFL0U7O0dBRUc7QUFDSCxNQUFNLENBQU4sSUFBWSxhQUtYO0FBTEQsV0FBWSxhQUFhO0lBQ3hCLGlEQUFJLENBQUE7SUFDSixtRUFBYSxDQUFBO0lBQ2IsdURBQU8sQ0FBQTtJQUNQLDJEQUFTLENBQUE7QUFDVixDQUFDLEVBTFcsYUFBYSxLQUFiLGFBQWEsUUFLeEI7QUFFRDs7Ozs7Ozs7R0FRRztBQXNGSCxNQUFNLE9BQU8sUUFBUTtJQTBLcEI7O09BRUc7SUFDSCxZQUNXLGlCQUFvQyxFQUNHLFNBQW1DO1FBRDFFLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBbUI7UUFDRyxjQUFTLEdBQVQsU0FBUyxDQUEwQjtRQXZLckY7O1dBRUc7UUFDTSxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBQzFCOztXQUVHO1FBQ00sYUFBUSxHQUFHLEtBQUssQ0FBQztRQUMxQjs7V0FFRztRQUNNLGNBQVMsR0FBRyxLQUFLLENBQUM7UUFLM0I7O1dBRUc7UUFDTSxPQUFFLEdBQUcsWUFBWSxRQUFRLENBQUMsYUFBYSxFQUFFLENBQUM7UUFZbkQ7O1dBRUc7UUFDTSxVQUFLLEdBQUcsRUFBRSxDQUFDO1FBeUZwQjs7V0FFRztRQUNPLFVBQUssR0FBRyxJQUFJLFlB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clZpZXdJbml0LFxuXHRDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcblx0Q2hhbmdlRGV0ZWN0b3JSZWYsXG5cdENvbXBvbmVudCxcblx0RWxlbWVudFJlZixcblx0RXZlbnRFbWl0dGVyLFxuXHRJbmplY3QsXG5cdElucHV0LFxuXHRPcHRpb25hbCxcblx0T3V0cHV0LFxuXHRUZW1wbGF0ZVJlZixcblx0Vmlld0NoaWxkLFxuXHRIb3N0TGlzdGVuZXJcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7IE5HX1ZBTFVFX0FDQ0VTU09SLCBDb250cm9sVmFsdWVBY2Nlc3NvciB9IGZyb20gXCJAYW5ndWxhci9mb3Jtc1wiO1xuaW1wb3J0IHsgQ2hlY2tib3hWYWx1ZSB9IGZyb20gXCIuL2NoZWNrYm94LnR5cGVzXCI7XG5pbXBvcnQgeyBDSEVDS0JPWF9HUk9VUF9IT1NULCBDaGVja2JveEdyb3VwSG9zdCB9IGZyb20gXCIuL2NoZWNrYm94LWdyb3VwLWhvc3RcIjtcblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBzZXQgb2Ygc3RhdGVzIGZvciBhIGNoZWNrYm94IGNvbXBvbmVudC5cbiAqL1xuZXhwb3J0IGVudW0gQ2hlY2tib3hTdGF0ZSB7XG5cdEluaXQsXG5cdEluZGV0ZXJtaW5hdGUsXG5cdENoZWNrZWQsXG5cdFVuY2hlY2tlZFxufVxuXG4vKipcbiAqIEdldCBzdGFydGVkIHdpdGggaW1wb3J0aW5nIHRoZSBtb2R1bGU6XG4gKlxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgQ2hlY2tib3hNb2R1bGUgfSBmcm9tICdjYXJib24tY29tcG9uZW50cy1hbmd1bGFyJztcbiAqIGBgYFxuICpcbiAqIFtTZWUgZGVtb10oLi4vLi4vP3BhdGg9L3N0b3J5L2NvbXBvbmVudHMtY2hlY2tib3gtLWJhc2ljKVxuICovXG5AQ29tcG9uZW50KHtcblx0c2VsZWN0b3I6IFwiY2RzLWNoZWNrYm94LCBpYm0tY2hlY2tib3hcIixcblx0dGVtcGxhdGU6IGBcblx0XHQ8ZGl2IGNsYXNzPVwiY2RzLS1mb3JtLWl0ZW0gY2RzLS1jaGVja2JveC13cmFwcGVyXCJcblx0XHRcdFtuZ0NsYXNzXT1cIntcblx0XHRcdFx0J2Nkcy0tY2hlY2tib3gtd3JhcHBlci0taW52YWxpZCc6ICFlZmZlY3RpdmVSZWFkT25seSAmJiBlZmZlY3RpdmVJbnZhbGlkLFxuXHRcdFx0XHQnY2RzLS1jaGVja2JveC13cmFwcGVyLS13YXJuaW5nJzogIWVmZmVjdGl2ZVJlYWRPbmx5ICYmICFlZmZlY3RpdmVJbnZhbGlkICYmIGVmZmVjdGl2ZVdhcm4sXG5cdFx0XHRcdCdjZHMtLWNoZWNrYm94LXdyYXBwZXItLXJlYWRvbmx5JzogZWZmZWN0aXZlUmVhZE9ubHksXG5cdFx0XHRcdCdjZHMtLWNoZWNrYm94LXdyYXBwZXItLWRlY29yYXRvcic6ICEhZGVjb3JhdG9yXG5cdFx0XHR9XCI+XG5cdFx0XHQ8aW5wdXRcblx0XHRcdFx0I2lucHV0Q2hlY2tib3hcblx0XHRcdFx0Y2xhc3M9XCJjZHMtLWNoZWNrYm94XCJcblx0XHRcdFx0dHlwZT1cImNoZWNrYm94XCJcblx0XHRcdFx0W2lkXT1cImlkICsgJ19pbnB1dCdcIlxuXHRcdFx0XHRbdmFsdWVdPVwidmFsdWVcIlxuXHRcdFx0XHRbbmFtZV09XCJuYW1lXCJcblx0XHRcdFx0W3JlcXVpcmVkXT1cInJlcXVpcmVkXCJcblx0XHRcdFx0W2NoZWNrZWRdPVwiY2hlY2tlZFwiXG5cdFx0XHRcdFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG5cdFx0XHRcdFthdHRyLmRhdGEtaW52YWxpZF09XCIoIWVmZmVjdGl2ZVJlYWRPbmx5ICYmIGVmZmVjdGl2ZUludmFsaWQpID8gdHJ1ZSA6IG51bGxcIlxuXHRcdFx0XHRbYXR0ci5hcmlhLXJlYWRvbmx5XT1cImVmZmVjdGl2ZVJlYWRPbmx5ID8gdHJ1ZSA6IG51bGxcIlxuXHRcdFx0XHRbYXR0ci5hcmlhLWxhYmVsbGVkYnldPVwiYXJpYUxhYmVsbGVkYnlcIlxuXHRcdFx0XHRbYXR0ci5hcmlhLWRlc2NyaWJlZGJ5XT1cIihoZWxwZXJUZXh0ICYmICFlZmZlY3RpdmVJbnZhbGlkICYmICFlZmZlY3RpdmVXYXJuKSA/IGhlbHBlcklkIDogbnVsbFwiXG5cdFx0XHRcdChjaGFuZ2UpPVwib25DaGFuZ2UoJGV2ZW50KVwiXG5cdFx0XHRcdChjbGljayk9XCJvbkNsaWNrKCRldmVudClcIj5cblx0XHRcdDxsYWJlbFxuXHRcdFx0XHRbZm9yXT1cImlkICsgJ19pbnB1dCdcIlxuXHRcdFx0XHRbYXR0ci5hcmlhLWxhYmVsXT1cImFyaWFMYWJlbFwiXG5cdFx0XHRcdFthdHRyLnRpdGxlXT1cInRpdGxlIHx8IG51bGxcIlxuXHRcdFx0XHRjbGFzcz1cImNkcy0tY2hlY2tib3gtbGFiZWxcIlxuXHRcdFx0XHRbbmdDbGFzc109XCJ7XG5cdFx0XHRcdFx0J2Nkcy0tc2tlbGV0b24nIDogc2tlbGV0b25cblx0XHRcdFx0fVwiPlxuXHRcdFx0XHQ8c3BhbiBbbmdDbGFzc109XCJ7J2Nkcy0tdmlzdWFsbHktaGlkZGVuJyA6IGhpZGVMYWJlbH1cIiBjbGFzcz1cImNkcy0tY2hlY2tib3gtbGFiZWwtdGV4dFwiPlxuXHRcdFx0XHRcdDxuZy1jb250ZW50PjwvbmctY29udGVudD5cblx0XHRcdFx0XHQ8bmctY29udGFpbmVyICpuZ0lmPVwiZGVjb3JhdG9yXCI+XG5cdFx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwiY2RzLS1jaGVja2JveC13cmFwcGVyLWlubmVyLS1kZWNvcmF0b3JcIj5cblx0XHRcdFx0XHRcdFx0PG5nLXRlbXBsYXRlIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImRlY29yYXRvclwiPjwvbmctdGVtcGxhdGU+XG5cdFx0XHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0XHQ8L25nLWNvbnRhaW5lcj5cblx0XHRcdFx0PC9zcGFuPlxuXHRcdFx0PC9sYWJlbD5cblx0XHRcdDxkaXYgY2xhc3M9XCJjZHMtLWNoZWNrYm94X192YWxpZGF0aW9uLW1zZ1wiPlxuXHRcdFx0XHQ8bmctY29udGFpbmVyICpuZ0lmPVwiIWVmZmVjdGl2ZVJlYWRPbmx5ICYmIGVmZmVjdGl2ZUludmFsaWRcIj5cblx0XHRcdFx0XHQ8c3ZnXG5cdFx0XHRcdFx0XHRjZHNJY29uPVwid2FybmluZy0tZmlsbGVkXCJcblx0XHRcdFx0XHRcdHNpemU9XCIxNlwiXG5cdFx0XHRcdFx0XHRjbGFzcz1cImNkcy0tY2hlY2tib3hfX2ludmFsaWQtaWNvblwiPlxuXHRcdFx0XHRcdDwvc3ZnPlxuXHRcdFx0XHRcdDxkaXYgY2xhc3M9XCJjZHMtLWZvcm0tcmVxdWlyZW1lbnRcIj5cblx0XHRcdFx0XHRcdDxuZy1jb250YWluZXIgKm5nSWY9XCIhaXNUZW1wbGF0ZShpbnZhbGlkVGV4dClcIj57e2ludmFsaWRUZXh0fX08L25nLWNvbnRhaW5lcj5cblx0XHRcdFx0XHRcdDxuZy10ZW1wbGF0ZSAqbmdJZj1cImlzVGVtcGxhdGUoaW52YWxpZFRleHQpXCIgW25nVGVtcGxhdGVPdXRsZXRdPVwiJGFueShpbnZhbGlkVGV4dClcIj48L25nLXRlbXBsYXRlPlxuXHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHQ8L25nLWNvbnRhaW5lcj5cblx0XHRcdFx0PG5nLWNvbnRhaW5lciAqbmdJZj1cIiFlZmZlY3RpdmVSZWFkT25seSAmJiAhZWZmZWN0aXZlSW52YWxpZCAmJiBlZmZlY3RpdmVXYXJuXCI+XG5cdFx0XHRcdFx0PHN2Z1xuXHRcdFx0XHRcdFx0Y2RzSWNvbj1cIndhcm5pbmctLWFsdC0tZmlsbGVkXCJcblx0XHRcdFx0XHRcdHNpemU9XCIxNlwiXG5cdFx0XHRcdFx0XHRjbGFzcz1cImNkcy0tY2hlY2tib3hfX2ludmFsaWQtaWNvbiBjZHMtLWNoZWNrYm94X19pbnZhbGlkLWljb24tLXdhcm5pbmdcIj5cblx0XHRcdFx0XHQ8L3N2Zz5cblx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwiY2RzLS1mb3JtLXJlcXVpcmVtZW50XCI+XG5cdFx0XHRcdFx0XHQ8bmctY29udGFpbmVyICpuZ0lmPVwiIWlzVGVtcGxhdGUod2FyblRleHQpXCI+e3t3YXJuVGV4dH19PC9uZy1jb250YWluZXI+XG5cdFx0XHRcdFx0XHQ8bmctdGVtcGxhdGUgKm5nSWY9XCJpc1RlbXBsYXRlKHdhcm5UZXh0KVwiIFtuZ1RlbXBsYXRlT3V0bGV0XT1cIiRhbnkod2FyblRleHQpXCI+PC9uZy10ZW1wbGF0ZT5cblx0XHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0PC9uZy1jb250YWluZXI+XG5cdFx0XHQ8L2Rpdj5cblx0XHRcdDxkaXZcblx0XHRcdFx0Km5nSWY9XCJoZWxwZXJUZXh0ICYmICFlZmZlY3RpdmVJbnZhbGlkICYmICFlZmZlY3RpdmVXYXJuXCJcblx0XHRcdFx0Y2xhc3M9XCJjZHMtLWZvcm1fX2hlbHBlci10ZXh0XCJcblx0XHRcdFx0W2lkXT1cImhlbHBlcklkXCI+XG5cdFx0XHRcdDxuZy1jb250YWluZXIgKm5nSWY9XCIhaXNUZW1wbGF0ZShoZWxwZXJUZXh0KVwiPnt7aGVscGVyVGV4dH19PC9uZy1jb250YWluZXI+XG5cdFx0XHRcdDxuZy10ZW1wbGF0ZSAqbmdJZj1cImlzVGVtcGxhdGUoaGVscGVyVGV4dClcIiBbbmdUZW1wbGF0ZU91dGxldF09XCIkYW55KGhlbHBlclRleHQpXCI+PC9uZy10ZW1wbGF0ZT5cblx0XHRcdDwvZGl2PlxuXHRcdDwvZGl2PlxuXHRgLFxuXHRwcm92aWRlcnM6IFtcblx0XHR7XG5cdFx0XHRwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcblx0XHRcdHVzZUV4aXN0aW5nOiBDaGVja2JveCxcblx0XHRcdG11bHRpOiB0cnVlXG5cdFx0fVxuXHRdLFxuXHRjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaFxufSlcbmV4cG9ydCBjbGFzcyBDaGVja2JveCBpbXBsZW1lbnRzIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBBZnRlclZpZXdJbml0IHtcblx0LyoqXG5cdCAqIFZhcmlhYmxlIHVzZWQgZm9yIGNyZWF0aW5nIHVuaXF1ZSBpZHMgZm9yIGNoZWNrYm94IGNvbXBvbmVudHMuXG5cdCAqL1xuXHRzdGF0aWMgY2hlY2tib3hDb3VudCA9IDA7XG5cblx0cHJpdmF0ZSBzdGF0aWMgaGVscGVySWRDb3VudGVyID0gMDtcblxuXHQvKipcblx0ICogU2V0IHRvIGB0cnVlYCBmb3IgYSBkaXNhYmxlZCBjaGVja2JveC5cblx0ICovXG5cdEBJbnB1dCgpIGRpc2FibGVkID0gZmFsc2U7XG5cdC8qKlxuXHQgKiBTZXQgdG8gYHRydWVgIGZvciBhIGxvYWRpbmcgY2hlY2tib3guXG5cdCAqL1xuXHRASW5wdXQoKSBza2VsZXRvbiA9IGZhbHNlO1xuXHQvKipcblx0ICogU2V0IHRvIGB0cnVlYCB0byBoaWRlIHRoZSBjaGVja2JveCBsYWJlbHMuXG5cdCAqL1xuXHRASW5wdXQoKSBoaWRlTGFiZWwgPSBmYWxzZTtcblx0LyoqXG5cdCAqIFNldHMgdGhlIG5hbWUgYXR0cmlidXRlIG9uIHRoZSBgaW5wdXRgIGVsZW1lbnQuXG5cdCAqL1xuXHRASW5wdXQoKSBuYW1lOiBzdHJpbmc7XG5cdC8qKlxuXHQgKiBUaGUgdW5pcXVlIGlkIGZvciB0aGUgY2hlY2tib3ggY29tcG9uZW50LlxuXHQgKi9cblx0QElucHV0KCkgaWQgPSBgY2hlY2tib3gtJHtDaGVja2JveC5jaGVja2JveENvdW50fWA7XG5cdC8qKlxuXHQgKiBSZWZsZWN0cyB0aGUgcmVxdWlyZWQgYXR0cmlidXRlIG9mIHRoZSBgaW5wdXRgIGVsZW1lbnQuXG5cdCAqL1xuXHRASW5wdXQoKSByZXF1aXJlZDogYm9vbGVhbjtcblx0LyoqXG5cdCAqIFNldHMgdGhlIHZhbHVlIGF0dHJpYnV0ZSBvbiB0aGUgYGlucHV0YCBlbGVtZW50LlxuXHQgKi9cblx0QElucHV0KCkgdmFsdWU6IENoZWNrYm94VmFsdWU7XG5cdEBJbnB1dCgpIGFyaWFMYWJlbDogc3RyaW5nO1xuXHRASW5wdXQoKSBhcmlhTGFiZWxsZWRieTogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBPcHRpb25hbCB0aXRsZSBmb3IgdGhlIGA8bGFiZWw+YCBlbGVtZW50LlxuXHQgKi9cblx0QElucHV0KCkgdGl0bGUgPSBcIlwiO1xuXG5cdC8qKlxuXHQgKiBPcHRpb25hbCBoZWxwZXIgdGV4dCBkaXNwbGF5ZWQgYmVsb3cgdGhlIGNoZWNrYm94IGxhYmVsLlxuXHQgKiBOb3Qgc2hvd24gd2hlbiBgaW52YWxpZGAgb3IgYHdhcm5gIGlzIGB0cnVlYC5cblx0ICovXG5cdEBJbnB1dCgpIGhlbHBlclRleHQ6IHN0cmluZyB8IFRlbXBsYXRlUmVmPGFueT47XG5cblx0LyoqXG5cdCAqIFNldCB0byBgdHJ1ZWAgdG8gc2hvdyB0aGUgY2hlY2tib3ggaW4gYW4gaW52YWxpZC9lcnJvciBzdGF0ZS5cblx0ICogV2hlbiBvbWl0dGVkIGluc2lkZSBhIGBjZHMtY2hlY2tib3gtZ3JvdXBgLCB0aGUgZ3JvdXAncyBgaW52YWxpZGAgdmFsdWUgYXBwbGllcy5cblx0ICovXG5cdEBJbnB1dCgpIGludmFsaWQ/OiBib29sZWFuO1xuXG5cdC8qKlxuXHQgKiBUaGUgZXJyb3IgbWVzc2FnZSBkaXNwbGF5ZWQgd2hlbiBgaW52YWxpZGAgaXMgYHRydWVgLlxuXHQgKi9cblx0QElucHV0KCkgaW52YWxpZFRleHQ6IHN0cmluZyB8IFRlbXBsYXRlUmVmPGFueT47XG5cblx0LyoqXG5cdCAqIFNldCB0byBgdHJ1ZWAgdG8gc2hvdyB0aGUgY2hlY2tib3ggaW4gYSB3YXJuaW5nIHN0YXRlLlxuXHQgKiBXaGVuIG9taXR0ZWQgaW5zaWRlIGEgYGNkcy1jaGVja2JveC1ncm91cGAsIHRoZSBncm91cCdzIGB3YXJuYCB2YWx1ZSBhcHBsaWVzLlxuXHQgKi9cblx0QElucHV0KCkgd2Fybj86IGJvb2xlYW47XG5cblx0LyoqXG5cdCAqIFRoZSB3YXJuaW5nIG1lc3NhZ2UgZGlzcGxheWVkIHdoZW4gYHdhcm5gIGlzIGB0cnVlYCBhbmQgYGludmFsaWRgIGlzIGBmYWxzZWAuXG5cdCAqL1xuXHRASW5wdXQoKSB3YXJuVGV4dDogc3RyaW5nIHwgVGVtcGxhdGVSZWY8YW55PjtcblxuXHQvKipcblx0ICogV2hlbiBgdHJ1ZWAsIHRoZSBjaGVja2JveCBjYW5ub3QgYmUgdG9nZ2xlZCAobWF0Y2hlcyBgcmVhZG9ubHlgIGF0dHJpYnV0ZSBzZW1hbnRpY3MgZm9yIGZvcm0gY29udHJvbHMpLlxuXHQgKiBXaGVuIG9taXR0ZWQgaW5zaWRlIGEgYGNkcy1jaGVja2JveC1ncm91cGAsIHRoZSBncm91cCdzIGByZWFkT25seWAgdmFsdWUgYXBwbGllcy5cblx0ICovXG5cdEBJbnB1dCgpIHJlYWRPbmx5PzogYm9vbGVhbjtcblxuXHQvKipcblx0ICogT3B0aW9uYWwgYFRlbXBsYXRlUmVmYCAoZS5nLiBBSSBsYWJlbCkgcmVuZGVyZWQgbmV4dCB0byB0aGUgbGFiZWwgdGV4dC5cblx0ICovXG5cdEBJbnB1dCgpIGRlY29yYXRvcjogVGVtcGxhdGVSZWY8YW55PjtcblxuXHQvKipcblx0ICogU2V0IHRoZSBjaGVja2JveCdzIGluZGV0ZXJtaW5hdGUgc3RhdGUgdG8gbWF0Y2ggdGhlIHBhcmFtZXRlciBhbmQgdHJhbnNpdGlvbiB0aGUgdmlldyB0byByZWZsZWN0IHRoZSBjaGFuZ2UuXG5cdCAqXG5cdCAqIEFsbG93cyBkb3VibGUgYmluZGluZyB3aXRoIHRoZSBgaW5kZXRlcm1pbmF0ZUNoYW5nZWAgT3V0cHV0LlxuXHQgKi9cblx0QElucHV0KCkgc2V0IGluZGV0ZXJtaW5hdGUoaW5kZXRlcm1pbmF0ZTogYm9vbGVhbikge1xuXHRcdGlmIChpbmRldGVybWluYXRlID09PSB0aGlzLl9pbmRldGVybWluYXRlKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dGhpcy5faW5kZXRlcm1pbmF0ZSA9IGluZGV0ZXJtaW5hdGU7XG5cblx0XHRpZiAodGhpcy5faW5kZXRlcm1pbmF0ZSkge1xuXHRcdFx0dGhpcy50cmFuc2l0aW9uQ2hlY2tib3hTdGF0ZShDaGVja2JveFN0YXRlLkluZGV0ZXJtaW5hdGUpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnRyYW5zaXRpb25DaGVja2JveFN0YXRlKHRoaXMuY2hlY2tlZCA/IENoZWNrYm94U3RhdGUuQ2hlY2tlZCA6IENoZWNrYm94U3RhdGUuVW5jaGVja2VkKTtcblx0XHR9XG5cblx0XHRpZiAodGhpcy5pbnB1dENoZWNrYm94ICYmIHRoaXMuaW5wdXRDaGVja2JveC5uYXRpdmVFbGVtZW50KSB7XG5cdFx0XHR0aGlzLmlucHV0Q2hlY2tib3gubmF0aXZlRWxlbWVudC5pbmRldGVybWluYXRlID0gaW5kZXRlcm1pbmF0ZTtcblx0XHR9XG5cdFx0dGhpcy5jaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKTtcblx0XHR0aGlzLmluZGV0ZXJtaW5hdGVDaGFuZ2UuZW1pdCh0aGlzLl9pbmRldGVybWluYXRlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZWZsZWN0cyB3aGV0aGVyIHRoZSBjaGVja2JveCBzdGF0ZSBpcyBpbmRldGVybWluYXRlLlxuXHQgKi9cblx0Z2V0IGluZGV0ZXJtaW5hdGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2luZGV0ZXJtaW5hdGU7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgYGNoZWNrZWRgIHN0YXRlLiBgdHJ1ZWAgZm9yIGNoZWNrZWQsIGBmYWxzZWAgZm9yIHVuY2hlY2tlZFxuXHQgKlxuXHQgKiBBbGxvd3MgZG91YmxlIGJpbmRpbmcgd2l0aCB0aGUgYGNoZWNrZWRDaGFuZ2VgIE91dHB1dC5cblx0ICovXG5cdEBJbnB1dCgpIHNldCBjaGVja2VkIChjaGVja2VkOiBib29sZWFuKSB7XG5cdFx0dGhpcy5zZXRDaGVja2VkKGNoZWNrZWQsIGZhbHNlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHZhbHVlIGB0cnVlYCBpZiBzdGF0ZSBpcyBzZWxlY3RlZCBmb3IgdGhlIGNoZWNrYm94LlxuXHQgKi9cblx0Z2V0IGNoZWNrZWQoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2NoZWNrZWQ7XG5cdH1cblxuXHQvKipcblx0ICogRW1pdHMgY2xpY2sgZXZlbnQuXG5cdCAqL1xuXHRAT3V0cHV0KCkgY2xpY2sgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cblx0LyoqXG5cdCAqIEVtaXRzIGFuIGV2ZW50IHdoZW4gdGhlIHZhbHVlIG9mIHRoZSBjaGVja2JveCBjaGFuZ2VzLlxuXHQgKlxuXHQgKiBBbGxvd3MgZG91YmxlIGJpZGluZyB3aXRoIHRoZSBgY2hlY2tlZGAgSW5wdXQuXG5cdCAqL1xuXHRAT3V0cHV0KCkgY2hlY2tlZENoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTtcblxuXHQvKipcblx0ICogRW1pdHMgZXZlbnQgbm90aWZ5aW5nIG90aGVyIGNsYXNzZXMgd2hlbiBhIGNoYW5nZSBpbiBzdGF0ZSBvY2N1cnMgc3BlY2lmaWNhbGx5XG5cdCAqIG9uIGFuIGluZGV0ZXJtaW5hdGUgY2hlY2tib3guXG5cdCAqL1xuXHRAT3V0cHV0KCkgaW5kZXRlcm1pbmF0ZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTtcblxuXHQvKipcblx0ICogU2V0IHRvIGB0cnVlYCBpZiB0aGUgaW5wdXQgY2hlY2tib3ggaXMgc2VsZWN0ZWQgKG9yIGNoZWNrZWQpLlxuXHQgKi9cblx0X2NoZWNrZWQgPSBmYWxzZTtcblx0LyoqXG5cdCAqIFNldCB0byBgdHJ1ZWAgaWYgdGhlIGlucHV0IGNoZWNrYm94IGlzIGluIHN0YXRlIGluZGV0ZXJtaW5hdGUuXG5cdCAqL1xuXHRfaW5kZXRlcm1pbmF0ZSA9IGZhbHNlO1xuXG5cdC8qKlxuXHQgKiBLZWVwcyBhIHJlZmVyZW5jZSB0byB0aGUgY2hlY2tib3hlcyBjdXJyZW50IHN0YXRlLCBhcyBkZWZpbmVkIGluIGBDaGVja2JveFN0YXRlYC5cblx0ICovXG5cdGN1cnJlbnRDaGVja2JveFN0YXRlID0gQ2hlY2tib3hTdGF0ZS5Jbml0O1xuXG5cdC8qKlxuXHQgKiBNYWludGFpbnMgYSByZWZlcmVuY2UgdG8gdGhlIHZpZXcgRE9NIGVsZW1lbnQgb2YgdGhlIGBDaGVja2JveGAuXG5cdCAqL1xuXHRAVmlld0NoaWxkKFwiaW5wdXRDaGVja2JveFwiKSBpbnB1dENoZWNrYm94OiBFbGVtZW50UmVmO1xuXG5cdHJlYWRvbmx5IGhlbHBlcklkID0gYGNoZWNrYm94LWhlbHBlci0ke0NoZWNrYm94LmhlbHBlcklkQ291bnRlcisrfWA7XG5cblx0LyoqXG5cdCAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgYENoZWNrYm94YC5cblx0ICovXG5cdGNvbnN0cnVjdG9yKFxuXHRcdHByb3RlY3RlZCBjaGFuZ2VEZXRlY3RvclJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG5cdFx0QE9wdGlvbmFsKCkgQEluamVjdChDSEVDS0JPWF9HUk9VUF9IT1NUKSBwcml2YXRlIGhvc3RHcm91cDogQ2hlY2tib3hHcm91cEhvc3QgfCBudWxsXG5cdCkge1xuXHRcdENoZWNrYm94LmNoZWNrYm94Q291bnQrKztcblx0fVxuXG5cdGdldCBlZmZlY3RpdmVSZWFkT25seSgpOiBib29sZWFuIHtcblx0XHRjb25zdCBvd24gPSB0aGlzLnJlYWRPbmx5O1xuXHRcdGNvbnN0IGdyb3VwID0gdGhpcy5ob3N0R3JvdXA/LnJlYWRPbmx5ID8/IGZhbHNlO1xuXHRcdHJldHVybiAhIShvd24gIT09IHVuZGVmaW5lZCA/IG93biA6IGdyb3VwKTtcblx0fVxuXG5cdGdldCBlZmZlY3RpdmVJbnZhbGlkKCk6IGJvb2xlYW4ge1xuXHRcdGNvbnN0IG93biA9IHRoaXMuaW52YWxpZDtcblx0XHRjb25zdCBncm91cCA9IHRoaXMuaG9zdEdyb3VwPy5pbnZhbGlkID8/IGZhbHNlO1xuXHRcdHJldHVybiAhIShvd24gIT09IHVuZGVmaW5lZCA/IG93biA6IGdyb3VwKTtcblx0fVxuXG5cdGdldCBlZmZlY3RpdmVXYXJuKCk6IGJvb2xlYW4ge1xuXHRcdGNvbnN0IG93biA9IHRoaXMud2Fybjtcblx0XHRjb25zdCBncm91cCA9IHRoaXMuaG9zdEdyb3VwPy53YXJuID8/IGZhbHNlO1xuXHRcdHJldHVybiAhIShvd24gIT09IHVuZGVmaW5lZCA/IG93biA6IGdyb3VwKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBUb2dnbGUgdGhlIHNlbGVjdGVkIHN0YXRlIG9mIHRoZSBjaGVja2JveC5cblx0ICovXG5cdHB1YmxpYyB0b2dnbGUoKSB7XG5cdFx0aWYgKHRoaXMuZWZmZWN0aXZlUmVhZE9ubHkpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0Ly8gRmxpcCBjaGVja2VkIGFuZCByZXNldCBpbmRldGVybWluYXRlXG5cdFx0dGhpcy5zZXRDaGVja2VkKCF0aGlzLmNoZWNrZWQsIHRydWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFdyaXRlcyBhIHZhbHVlIGZyb20gYG5nTW9kZWxgIHRvIHRoZSBjb21wb25lbnQuXG5cdCAqXG5cdCAqIEluIHRoaXMgY2FzZSB0aGUgdmFsdWUgaXMgdGhlIGBjaGVja2VkYCBwcm9wZXJ0eS5cblx0ICpcblx0ICogQHBhcmFtIHZhbHVlIGJvb2xlYW4sIGNvcnJlc3BvbmRzIHRvIHRoZSBgY2hlY2tlZGAgcHJvcGVydHkuXG5cdCAqL1xuXHRwdWJsaWMgd3JpdGVWYWx1ZSh2YWx1ZTogYW55KSB7XG5cdFx0Ly8gU2V0IGNoZWNrZWQgYW5kIHJlc2V0IGluZGV0ZXJtaW5hdGVcblx0XHR0aGlzLnNldENoZWNrZWQoISF2YWx1ZSwgdHJ1ZSk7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyBhIG1ldGhvZCBpbiBvcmRlciB0byBwcm9wYWdhdGUgY2hhbmdlcyBiYWNrIHRvIHRoZSBmb3JtLlxuXHQgKi9cblx0cHVibGljIHJlZ2lzdGVyT25DaGFuZ2UoZm46IGFueSkge1xuXHRcdHRoaXMucHJvcGFnYXRlQ2hhbmdlID0gZm47XG5cdH1cblxuXHQvKipcblx0ICogUmVnaXN0ZXJzIGEgY2FsbGJhY2sgdG8gYmUgdHJpZ2dlcmVkIHdoZW4gdGhlIGNvbnRyb2wgaGFzIGJlZW4gdG91Y2hlZC5cblx0ICogQHBhcmFtIGZuIENhbGxiYWNrIHRvIGJlIHRyaWdnZXJlZCB3aGVuIHRoZSBjaGVja2JveCBpcyB0b3VjaGVkLlxuXHQgKi9cblx0cHVibGljIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiBhbnkpIHtcblx0XHR0aGlzLm9uVG91Y2hlZCA9IGZuO1xuXHR9XG5cblx0LyoqXG5cdCAqIGBDb250cm9sVmFsdWVBY2Nlc3NvcmAgbWV0aG9kIHRvIHByb2dyYW1tYXRpY2FsbHkgZGlzYWJsZSB0aGUgY2hlY2tib3guXG5cdCAqXG5cdCAqIGV4OiBgdGhpcy5mb3JtR3JvdXAuZ2V0KFwibXlDaGVja2JveFwiKS5kaXNhYmxlKCk7YFxuXHQgKlxuXHQgKiBAcGFyYW0gaXNEaXNhYmxlZCBgdHJ1ZWAgdG8gZGlzYWJsZSB0aGUgY2hlY2tib3hcblx0ICovXG5cdHNldERpc2FibGVkU3RhdGUoaXNEaXNhYmxlZDogYm9vbGVhbikge1xuXHRcdHRoaXMuZGlzYWJsZWQgPSBpc0Rpc2FibGVkO1xuXHRcdHRoaXMuY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XG5cdH1cblxuXHQvKipcblx0ICogSW52b2tlZCBieSBgQ2hlY2tib3hHcm91cGAgd2hlbiBncm91cCBgcmVhZE9ubHlgLCBgaW52YWxpZGAsIGB3YXJuYCBjaGFuZ2Ugc28gYE9uUHVzaGBcblx0ICogY2hlY2tib3hlcyBzdGlsbCByZWZyZXNoIGluaGVyaXRlZCBzdGF0ZSBmcm9tIGBDSEVDS0JPWF9HUk9VUF9IT1NUYC5cblx0ICovXG5cdG1hcmtGb3JDaGVja0Zyb21Hcm91cCgpOiB2b2lkIHtcblx0XHR0aGlzLmNoYW5nZURldGVjdG9yUmVmLm1hcmtGb3JDaGVjaygpO1xuXHR9XG5cblx0QEhvc3RMaXN0ZW5lcihcImZvY3Vzb3V0XCIpXG5cdGZvY3VzT3V0KCkge1xuXHRcdHRoaXMub25Ub3VjaGVkKCk7XG5cdH1cblxuXHQvKipcblx0ICogRXhlY3V0ZXMgb24gdGhlIGV2ZW50IG9mIGEgY2hhbmdlIHdpdGhpbiBgQ2hlY2tib3hgIHRvIGJsb2NrIHByb3BhZ2F0aW9uLlxuXHQgKi9cblx0b25DaGFuZ2UoZXZlbnQ6IEV2ZW50KSB7XG5cdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdH1cblxuXHQvKipcblx0ICogSGFuZGxlcyBjbGljayBldmVudHMgb24gdGhlIGBDaGVja2JveGAgYW5kIGVtaXRzIGNoYW5nZXMgdG8gb3RoZXIgY2xhc3Nlcy5cblx0ICovXG5cdG9uQ2xpY2soZXZlbnQ6IEV2ZW50KSB7XG5cdFx0aWYgKHRoaXMuZWZmZWN0aXZlUmVhZE9ubHkpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRpZiAodGhpcy5jbGljay5vYnNlcnZlcnMubGVuZ3RoKSB7XG5cdFx0XHRcdHRoaXMuY2xpY2suZW1pdCgpO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRpZiAodGhpcy5jbGljay5vYnNlcnZlcnMubGVuZ3RoKSB7XG5cdFx0XHQvLyBEaXNhYmxlIGRlZmF1bHQgY2hlY2tib3ggYWN0aXZhdGlvbiBiZWhhdmlvciB3aGljaCBmbGlwcyBjaGVja2VkIGFuZCByZXNldHMgaW5kZXRlcm1pbmF0ZS5cblx0XHRcdC8vIFRoaXMgYWxsb3dzIHRoZSBwYXJlbnQgY29tcG9uZW50IHRvIGNvbnRyb2wgdGhlIGNoZWNrZWQvaW5kZXRlcm1pbmF0ZSBwcm9wZXJ0aWVzLlxuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdHRoaXMuY2xpY2suZW1pdCgpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRpZiAoIXRoaXMuZGlzYWJsZWQpIHtcblx0XHRcdHRoaXMudG9nZ2xlKCk7XG5cdFx0XHR0aGlzLnRyYW5zaXRpb25DaGVja2JveFN0YXRlKHRoaXMuX2NoZWNrZWQgPyBDaGVja2JveFN0YXRlLkNoZWNrZWQgOiBDaGVja2JveFN0YXRlLlVuY2hlY2tlZCk7XG5cdFx0XHR0aGlzLmVtaXRDaGFuZ2VFdmVudCgpO1xuXHRcdH1cblx0fVxuXG5cblx0LyoqXG5cdCAqIENhbGxlZCB3aGVuIGNoZWNrYm94IGlzIGJsdXJyZWQuIE5lZWRlZCB0byBwcm9wZXJseSBpbXBsZW1lbnQgYENvbnRyb2xWYWx1ZUFjY2Vzc29yYC5cblx0ICovXG5cdG9uVG91Y2hlZDogKCkgPT4gYW55ID0gKCkgPT4ge307XG5cblx0LyoqXG5cdCAqIEhhbmRsZXMgY2hhbmdlcyBiZXR3ZWVuIGNoZWNrYm94IHN0YXRlcy5cblx0ICovXG5cdHRyYW5zaXRpb25DaGVja2JveFN0YXRlKG5ld1N0YXRlOiBDaGVja2JveFN0YXRlKSB7XG5cdFx0dGhpcy5jdXJyZW50Q2hlY2tib3hTdGF0ZSA9IG5ld1N0YXRlO1xuXHR9XG5cblx0LyoqXG5cdCAqIENyZWF0ZXMgaW5zdGFuY2Ugb2YgYENoZWNrYm94Q2hhbmdlYCB1c2VkIHRvIHByb3BhZ2F0ZSB0aGUgY2hhbmdlIGV2ZW50LlxuXHQgKi9cblx0ZW1pdENoYW5nZUV2ZW50KCkge1xuXHRcdHRoaXMuY2hlY2tlZENoYW5nZS5lbWl0KHRoaXMuY2hlY2tlZCk7XG5cdFx0dGhpcy5wcm9wYWdhdGVDaGFuZ2UodGhpcy5jaGVja2VkKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBVcGRhdGVzIHRoZSBjaGVja2JveCBpZiBpdCBpcyBpbiB0aGUgaW5kZXRlcm1pbmF0ZSBzdGF0ZS5cblx0ICovXG5cdG5nQWZ0ZXJWaWV3SW5pdCgpIHtcblx0XHRpZiAodGhpcy5pbmRldGVybWluYXRlICYmIHRoaXMuaW5wdXRDaGVja2JveCAmJiB0aGlzLmlucHV0Q2hlY2tib3gubmF0aXZlRWxlbWVudCkge1xuXHRcdFx0dGhpcy5pbnB1dENoZWNrYm94Lm5hdGl2ZUVsZW1lbnQuaW5kZXRlcm1pbmF0ZSA9IHRydWU7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIE1ldGhvZCBzZXQgaW4gYHJlZ2lzdGVyT25DaGFuZ2VgIHRvIHByb3BhZ2F0ZSBjaGFuZ2VzIGJhY2sgdG8gdGhlIGZvcm0uXG5cdCAqL1xuXHRwcm9wYWdhdGVDaGFuZ2UgPSAoXzogYW55KSA9PiB7fTtcblxuXHQvKipcblx0ICogUmV0dXJucyBgdHJ1ZWAgd2hlbiB0aGUgcHJvdmlkZWQgdmFsdWUgaXMgYSBgVGVtcGxhdGVSZWZgLlxuXHQgKi9cblx0aXNUZW1wbGF0ZSh2YWx1ZTogYW55KTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVGVtcGxhdGVSZWY7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyBjaGVja2VkIHN0YXRlIGFuZCBvcHRpb25hbGx5IHJlc2V0cyBpbmRldGVybWluYXRlIHN0YXRlLlxuXHQgKi9cblx0cHJpdmF0ZSBzZXRDaGVja2VkKGNoZWNrZWQ6IGJvb2xlYW4sIHJlc2V0SW5kZXRlcm1pbmF0ZTogYm9vbGVhbikge1xuXHRcdGlmIChjaGVja2VkID09PSB0aGlzLl9jaGVja2VkKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHRoaXMuX2NoZWNrZWQgPSBjaGVja2VkO1xuXHRcdC8vIFJlc2V0IGluZGV0ZXJtaW5hdGUgaWYgcmVxdWVzdGVkXG5cdFx0aWYgKHJlc2V0SW5kZXRlcm1pbmF0ZSAmJiB0aGlzLl9pbmRldGVybWluYXRlKSB7XG5cdFx0XHR0aGlzLl9pbmRldGVybWluYXRlID0gZmFsc2U7XG5cdFx0XHRQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IHtcblx0XHRcdFx0dGhpcy5pbmRldGVybWluYXRlQ2hhbmdlLmVtaXQodGhpcy5faW5kZXRlcm1pbmF0ZSk7XG5cdFx0XHR9KTtcblx0XHR9XG5cdFx0dGhpcy5jaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKTtcblx0fVxufVxuIl19