igniteui-angular
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
774 lines • 57.5 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Component, ChangeDetectorRef, EventEmitter, ElementRef, HostBinding, Input, Output, ViewChild, Renderer2, TemplateRef, Inject, Optional } from '@angular/core';
import { DisplayDensityToken, DisplayDensityBase } from '../core/displayDensity';
import { IgxDragDirective } from '../directives/dragdrop/dragdrop.directive';
/**
* @record
*/
export function IBaseChipEventArgs() { }
if (false) {
/** @type {?} */
IBaseChipEventArgs.prototype.originalEvent;
/** @type {?} */
IBaseChipEventArgs.prototype.owner;
}
/**
* @record
*/
export function IChipClickEventArgs() { }
if (false) {
/** @type {?} */
IChipClickEventArgs.prototype.cancel;
}
/**
* @record
*/
export function IChipKeyDownEventArgs() { }
if (false) {
/** @type {?} */
IChipKeyDownEventArgs.prototype.originalEvent;
/** @type {?} */
IChipKeyDownEventArgs.prototype.cancel;
}
/**
* @record
*/
export function IChipEnterDragAreaEventArgs() { }
if (false) {
/** @type {?} */
IChipEnterDragAreaEventArgs.prototype.dragChip;
}
/**
* @record
*/
export function IChipSelectEventArgs() { }
if (false) {
/** @type {?} */
IChipSelectEventArgs.prototype.cancel;
/** @type {?} */
IChipSelectEventArgs.prototype.selected;
}
/** @type {?} */
let CHIP_ID = 0;
export class IgxChipComponent extends DisplayDensityBase {
/**
* @param {?} cdr
* @param {?} elementRef
* @param {?} renderer
* @param {?} _displayDensityOptions
*/
constructor(cdr, elementRef, renderer, _displayDensityOptions) {
super(_displayDensityOptions);
this.cdr = cdr;
this.elementRef = elementRef;
this.renderer = renderer;
this._displayDensityOptions = _displayDensityOptions;
/**
* An \@Input property that sets the value of `id` attribute. If not provided it will be automatically generated.
* ```html
* <igx-chip [id]="'igx-chip-1'"></igx-chip>
* ```
*/
this.id = `igx-chip-${CHIP_ID++}`;
/**
* An \@Input property that defines if the `IgxChipComponent` can be dragged in order to change it's position.
* By default it is set to false.
* ```html
* <igx-chip [id]="'igx-chip-1'" [draggable]="true"></igx-chip>
* ```
*/
this.draggable = false;
/**
* An \@Input property that defines if the `IgxChipComponent` should render remove button and throw remove events.
* By default it is set to false.
* ```html
* <igx-chip [id]="'igx-chip-1'" [draggable]="true" [removable]="true"></igx-chip>
* ```
*/
this.removable = false;
/**
* An \@Input property that defines if the `IgxChipComponent` can be selected on click or through navigation,
* By default it is set to false.
* ```html
* <igx-chip [id]="chip.id" [draggable]="true" [removable]="true" [selectable]="true"></igx-chip>
* ```
*/
this.selectable = false;
/**
* @hidden
*/
this.class = '';
/**
* An \@Input property that defines if the `IgxChipComponent` is disabled. When disabled it restricts user interactions
* like focusing on click or tab, selection on click or Space, dragging.
* By default it is set to false.
* ```html
* <igx-chip [id]="chip.id" [disabled]="true"></igx-chip>
* ```
*/
this.disabled = false;
/**
* Emits an event when the `IgxChipComponent` moving starts.
* Returns the moving `IgxChipComponent`.
* ```typescript
* moveStarted(event: IBaseChipEventArgs){
* let movingChip = event.owner;
* }
* ```
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (onMoveStart)="moveStarted($event)">
* ```
*/
this.onMoveStart = new EventEmitter();
/**
* Emits an event when the `IgxChipComponent` moving ends.
* Returns the moved `IgxChipComponent`.
* ```typescript
* moveEnded(event: IBaseChipEventArgs){
* let movedChip = event.owner;
* }
* ```
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (onMoveEnd)="moveEnded($event)">
* ```
*/
this.onMoveEnd = new EventEmitter();
/**
* Emits an event when the `IgxChipComponent` is removed.
* Returns the removed `IgxChipComponent`.
* ```typescript
* remove(event: IBaseChipEventArgs){
* let removedChip = event.owner;
* }
* ```
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (onRemove)="remove($event)">
* ```
*/
this.onRemove = new EventEmitter();
/**
* Emits an event when the `IgxChipComponent` is clicked.
* Returns the clicked `IgxChipComponent`, whether the event should be canceled.
* ```typescript
* chipClick(event: IChipClickEventArgs){
* let clickedChip = event.owner;
* }
* ```
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (onClick)="chipClick($event)">
* ```
*/
this.onClick = new EventEmitter();
/**
* Emits event when the `IgxChipComponent` is selected/deselected.
* Returns the selected chip reference, whether the event should be canceled, what is the next selection state and
* when the event is triggered by interaction `originalEvent` is provided, otherwise `originalEvent` is `null`.
* ```typescript
* chipSelect(event: IChipSelectEventArgs){
* let selectedChip = event.owner;
* }
* ```
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (onSelection)="chipSelect($event)">
* ```
*/
this.onSelection = new EventEmitter();
/**
* Emits an event when the `IgxChipComponent` keyboard navigation is being used.
* Returns the focused/selected `IgxChipComponent`, whether the event should be canceled,
* if the `alt`, `shift` or `control` key is pressed and the pressed key name.
* ```typescript
* chipKeyDown(event: IChipKeyDownEventArgs){
* let keyDown = event.key;
* }
* ```
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (onKeyDown)="chipKeyDown($event)">
* ```
*/
this.onKeyDown = new EventEmitter();
/**
* Emits an event when the `IgxChipComponent` has entered the `IgxChipsAreaComponent`.
* Returns the target `IgxChipComponent`, the drag `IgxChipComponent`, as well as
* the original drop event arguments.
* ```typescript
* chipEnter(event: IChipEnterDragAreaEventArgs){
* let targetChip = event.targetChip;
* }
* ```
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (onDragEnter)="chipEnter($event)">
* ```
*/
this.onDragEnter = new EventEmitter();
this._selected = false;
this._selectedItemClass = 'igx-chip__item--selected';
this._movedWhileRemoving = false;
}
/**
* Sets the `IgxChipComponent` selected state.
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [selectable]="true" [selected]="true">
* ```
* @param {?} newValue
* @return {?}
*/
set selected(newValue) {
this.changeSelection(newValue);
}
/**
* Returns if the `IgxChipComponent` is selected.
* ```typescript
* \@ViewChild('myChip')
* public chip: IgxChipComponent;
* selectedChip(){
* let selectedChip = this.chip.selected;
* }
* ```
* @return {?}
*/
get selected() {
return this._selected;
}
/**
* An \@Input property that sets the `IgxChipComponent` background color.
* The `color` property supports string, rgb, hex.
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [color]="'#ff0000'"></igx-chip>
* ```
* @param {?} newColor
* @return {?}
*/
set color(newColor) {
this.chipArea.nativeElement.style.backgroundColor = newColor;
}
/**
* Returns the background color of the `IgxChipComponent`.
* ```typescript
* \@ViewChild('myChip')
* public chip: IgxChipComponent;
* ngAfterViewInit(){
* let chipColor = this.chip.color;
* }
* ```
* @return {?}
*/
get color() {
return this.chipArea.nativeElement.style.backgroundColor;
}
/**
* @hidden
* @return {?}
*/
get hostClass() {
/** @type {?} */
const classes = [this.getComponentDensityClass('igx-chip')];
classes.push(this.disabled ? 'igx-chip--disabled' : '');
// The custom classes should be at the end.
classes.push(this.class);
return classes.join(' ');
}
/**
* @hidden
* @return {?}
*/
get removeButtonTemplate() {
return this.removeIcon || this.defaultRemoveIcon;
}
/**
* @hidden
* @return {?}
*/
get selectIconTemplate() {
return this.selectIcon || this.defaultSelectIcon;
}
/**
* @hidden
* @return {?}
*/
get ghostClass() {
return this.getComponentDensityClass('igx-chip__ghost');
}
/**
* @return {?}
*/
get chipTabindex() {
return !this.disabled ? 0 : '';
}
/**
* @hidden
* @param {?} condition
* @return {?}
*/
selectClass(condition) {
/** @type {?} */
const SELECT_CLASS = 'igx-chip__select';
return {
[SELECT_CLASS]: condition,
[`${SELECT_CLASS}--hidden`]: !condition
};
}
/**
* @protected
* @param {?} newValue
* @param {?=} srcEvent
* @return {?}
*/
changeSelection(newValue, srcEvent = null) {
/** @type {?} */
const onSelectArgs = {
originalEvent: srcEvent,
owner: this,
selected: false,
cancel: false
};
if (newValue && !this._selected) {
onSelectArgs.selected = true;
this.onSelection.emit(onSelectArgs);
if (!onSelectArgs.cancel) {
this.renderer.addClass(this.chipArea.nativeElement, this._selectedItemClass);
this._selected = newValue;
}
}
else if (!newValue && this._selected) {
this.onSelection.emit(onSelectArgs);
if (!onSelectArgs.cancel) {
this.renderer.removeClass(this.chipArea.nativeElement, this._selectedItemClass);
this._selected = newValue;
}
}
}
/**
* @hidden
* @param {?} event
* @return {?}
*/
onChipKeyDown(event) {
/** @type {?} */
const keyDownArgs = {
originalEvent: event,
owner: this,
cancel: false
};
this.onKeyDown.emit(keyDownArgs);
if (keyDownArgs.cancel) {
return;
}
if ((event.key === 'Delete' || event.key === 'Del') && this.removable) {
this.onRemove.emit({
originalEvent: event,
owner: this
});
}
if ((event.key === ' ' || event.key === 'Spacebar') && this.selectable && !this.disabled) {
this.changeSelection(!this.selected, event);
}
if (event.key !== 'Tab') {
event.preventDefault();
}
}
/**
* @hidden
* @param {?} event
* @return {?}
*/
onRemoveBtnKeyDown(event) {
if (event.key === ' ' || event.key === 'Spacebar' || event.key === 'Enter') {
this.onRemove.emit({
originalEvent: event,
owner: this
});
event.preventDefault();
event.stopPropagation();
}
}
/**
* @param {?} event
* @return {?}
*/
onRemoveMouseDown(event) {
event.stopPropagation();
}
/**
* @hidden
* @param {?} event
* @return {?}
*/
onRemoveClick(event) {
this.onRemove.emit({
originalEvent: event,
owner: this
});
}
/**
* @hidden
* @return {?}
*/
onRemoveTouchMove() {
// We don't remove chip if user starting touch interacting on the remove button moves the chip
this._movedWhileRemoving = true;
}
/**
* @hidden
* @param {?} event
* @return {?}
*/
onRemoveTouchEnd(event) {
if (!this._movedWhileRemoving) {
this.onRemoveClick(event);
}
this._movedWhileRemoving = false;
}
/**
* @hidden
* @param {?} event
* @return {?}
*/
// -----------------------------
// Start chip igxDrag behaviour
onChipDragStart(event) {
this.onMoveStart.emit({
originalEvent: event.originalEvent,
owner: this
});
event.cancel = !this.draggable || this.disabled;
}
/**
* @hidden
* @return {?}
*/
onChipDragEnd() {
this.dragDir.dropFinished();
}
/**
* @hidden
* @param {?} event
* @return {?}
*/
onChipMoveEnd(event) {
// moveEnd is triggered after return animation has finished. This happen when we drag and release the chip.
this.onMoveEnd.emit({
originalEvent: event.originalEvent,
owner: this
});
if (this.selected) {
this.chipArea.nativeElement.focus();
}
}
/**
* @hidden
* @param {?} event
* @return {?}
*/
onChipDragClicked(event) {
/** @type {?} */
const clickEventArgs = {
originalEvent: event.originalEvent,
owner: this,
cancel: false
};
this.onClick.emit(clickEventArgs);
if (!clickEventArgs.cancel && this.selectable && !this.disabled) {
this.changeSelection(!this.selected, event.originalEvent);
}
}
// End chip igxDrag behaviour
/**
* @hidden
* @param {?} event
* @return {?}
*/
// -----------------------------
// Start chip igxDrop behaviour
onChipDragEnterHandler(event) {
if (this.dragDir === event.drag || !event.dragData || !event.dragData.chip) {
return;
}
/** @type {?} */
const eventArgs = {
owner: this,
dragChip: event.dragData.chip,
originalEvent: event
};
this.onDragEnter.emit(eventArgs);
}
/**
* @hidden
* @param {?} event
* @return {?}
*/
onChipDrop(event) {
// Cancel the default drop logic
event.cancel = true;
}
}
IgxChipComponent.decorators = [
{ type: Component, args: [{
selector: 'igx-chip',
template: "<div #chipArea class=\"igx-chip__item\"\n [attr.tabindex]=\"chipTabindex\"\n (keydown)=\"onChipKeyDown($event)\"\n [igxDrag]=\"{chip: this}\"\n [hideBaseOnDrag]=\"true\"\n [animateOnRelease]=\"true\"\n [ghostImageClass]=\"ghostClass\"\n (dragStart)=\"onChipDragStart($event)\"\n (dragEnd)=\"onChipDragEnd()\"\n (returnMoveEnd)=\"onChipMoveEnd($event)\"\n (dragClicked)=\"onChipDragClicked($event)\"\n igxDrop\n (onEnter)=\"onChipDragEnterHandler($event)\"\n (onDrop)=\"onChipDrop($event)\">\n\n <div [ngClass]=\"selectClass(selected)\">\n <ng-container *ngTemplateOutlet=\"selectIconTemplate\"></ng-container>\n </div>\n\n <ng-content select=\"igx-prefix,[igxPrefix]\"></ng-content>\n\n <div class=\"igx-chip__content\">\n <ng-content></ng-content>\n </div>\n\n <ng-content select=\"igx-suffix,[igxSuffix]\"></ng-content>\n\n <div class=\"igx-chip__remove\" *ngIf=\"removable\"\n tabindex=\"0\"\n (keydown)=\"onRemoveBtnKeyDown($event)\"\n (pointerdown)=\"onRemoveMouseDown($event)\"\n (mousedown)=\"onRemoveMouseDown($event)\"\n (click)=\"onRemoveClick($event)\"\n (touchmove)=\"onRemoveTouchMove()\"\n (touchend)=\"onRemoveTouchEnd($event)\">\n <ng-container *ngTemplateOutlet=\"removeButtonTemplate\"></ng-container>\n </div>\n</div>\n\n<ng-template #defaultSelectIcon>\n <igx-icon>done</igx-icon>\n</ng-template>\n\n<ng-template #defaultRemoveIcon>\n <igx-icon>cancel</igx-icon>\n</ng-template>\n"
}] }
];
/** @nocollapse */
IgxChipComponent.ctorParameters = () => [
{ type: ChangeDetectorRef },
{ type: ElementRef },
{ type: Renderer2 },
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [DisplayDensityToken,] }] }
];
IgxChipComponent.propDecorators = {
id: [{ type: HostBinding, args: ['attr.id',] }, { type: Input }],
data: [{ type: Input }],
draggable: [{ type: Input }],
removable: [{ type: Input }],
removeIcon: [{ type: Input }],
selectable: [{ type: Input }],
selectIcon: [{ type: Input }],
class: [{ type: Input }],
disabled: [{ type: Input }],
selected: [{ type: Input }],
color: [{ type: Input }],
onMoveStart: [{ type: Output }],
onMoveEnd: [{ type: Output }],
onRemove: [{ type: Output }],
onClick: [{ type: Output }],
onSelection: [{ type: Output }],
onKeyDown: [{ type: Output }],
onDragEnter: [{ type: Output }],
hostClass: [{ type: HostBinding, args: ['attr.class',] }],
chipArea: [{ type: ViewChild, args: ['chipArea', { read: ElementRef },] }],
dragDir: [{ type: ViewChild, args: ['chipArea', { read: IgxDragDirective },] }],
defaultRemoveIcon: [{ type: ViewChild, args: ['defaultRemoveIcon', { read: TemplateRef },] }],
defaultSelectIcon: [{ type: ViewChild, args: ['defaultSelectIcon', { read: TemplateRef },] }]
};
if (false) {
/**
* An \@Input property that sets the value of `id` attribute. If not provided it will be automatically generated.
* ```html
* <igx-chip [id]="'igx-chip-1'"></igx-chip>
* ```
* @type {?}
*/
IgxChipComponent.prototype.id;
/**
* An \@Input property that stores data related to the chip.
* ```html
* <igx-chip [data]="{ value: 'Country' }"></igx-chip>
* ```
* @type {?}
*/
IgxChipComponent.prototype.data;
/**
* An \@Input property that defines if the `IgxChipComponent` can be dragged in order to change it's position.
* By default it is set to false.
* ```html
* <igx-chip [id]="'igx-chip-1'" [draggable]="true"></igx-chip>
* ```
* @type {?}
*/
IgxChipComponent.prototype.draggable;
/**
* An \@Input property that defines if the `IgxChipComponent` should render remove button and throw remove events.
* By default it is set to false.
* ```html
* <igx-chip [id]="'igx-chip-1'" [draggable]="true" [removable]="true"></igx-chip>
* ```
* @type {?}
*/
IgxChipComponent.prototype.removable;
/**
* An \@Input property that overrides the default icon that the chip applies to the remove button.
* ```html
* <igx-chip [id]="chip.id" [removable]="true" [removeIcon]="iconTemplate"></igx-chip>
* <ng-template #iconTemplate><igx-icon>delete</igx-icon></ng-template>
* ```
* @type {?}
*/
IgxChipComponent.prototype.removeIcon;
/**
* An \@Input property that defines if the `IgxChipComponent` can be selected on click or through navigation,
* By default it is set to false.
* ```html
* <igx-chip [id]="chip.id" [draggable]="true" [removable]="true" [selectable]="true"></igx-chip>
* ```
* @type {?}
*/
IgxChipComponent.prototype.selectable;
/**
* An \@Input property that overrides the default icon that the chip applies when it is selected.
* ```html
* <igx-chip [id]="chip.id" [selectable]="true" [selectIcon]="iconTemplate"></igx-chip>
* <ng-template #iconTemplate><igx-icon>done_outline</igx-icon></ng-template>
* ```
* @type {?}
*/
IgxChipComponent.prototype.selectIcon;
/**
* @hidden
* @type {?}
*/
IgxChipComponent.prototype.class;
/**
* An \@Input property that defines if the `IgxChipComponent` is disabled. When disabled it restricts user interactions
* like focusing on click or tab, selection on click or Space, dragging.
* By default it is set to false.
* ```html
* <igx-chip [id]="chip.id" [disabled]="true"></igx-chip>
* ```
* @type {?}
*/
IgxChipComponent.prototype.disabled;
/**
* Emits an event when the `IgxChipComponent` moving starts.
* Returns the moving `IgxChipComponent`.
* ```typescript
* moveStarted(event: IBaseChipEventArgs){
* let movingChip = event.owner;
* }
* ```
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (onMoveStart)="moveStarted($event)">
* ```
* @type {?}
*/
IgxChipComponent.prototype.onMoveStart;
/**
* Emits an event when the `IgxChipComponent` moving ends.
* Returns the moved `IgxChipComponent`.
* ```typescript
* moveEnded(event: IBaseChipEventArgs){
* let movedChip = event.owner;
* }
* ```
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (onMoveEnd)="moveEnded($event)">
* ```
* @type {?}
*/
IgxChipComponent.prototype.onMoveEnd;
/**
* Emits an event when the `IgxChipComponent` is removed.
* Returns the removed `IgxChipComponent`.
* ```typescript
* remove(event: IBaseChipEventArgs){
* let removedChip = event.owner;
* }
* ```
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (onRemove)="remove($event)">
* ```
* @type {?}
*/
IgxChipComponent.prototype.onRemove;
/**
* Emits an event when the `IgxChipComponent` is clicked.
* Returns the clicked `IgxChipComponent`, whether the event should be canceled.
* ```typescript
* chipClick(event: IChipClickEventArgs){
* let clickedChip = event.owner;
* }
* ```
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (onClick)="chipClick($event)">
* ```
* @type {?}
*/
IgxChipComponent.prototype.onClick;
/**
* Emits event when the `IgxChipComponent` is selected/deselected.
* Returns the selected chip reference, whether the event should be canceled, what is the next selection state and
* when the event is triggered by interaction `originalEvent` is provided, otherwise `originalEvent` is `null`.
* ```typescript
* chipSelect(event: IChipSelectEventArgs){
* let selectedChip = event.owner;
* }
* ```
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (onSelection)="chipSelect($event)">
* ```
* @type {?}
*/
IgxChipComponent.prototype.onSelection;
/**
* Emits an event when the `IgxChipComponent` keyboard navigation is being used.
* Returns the focused/selected `IgxChipComponent`, whether the event should be canceled,
* if the `alt`, `shift` or `control` key is pressed and the pressed key name.
* ```typescript
* chipKeyDown(event: IChipKeyDownEventArgs){
* let keyDown = event.key;
* }
* ```
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (onKeyDown)="chipKeyDown($event)">
* ```
* @type {?}
*/
IgxChipComponent.prototype.onKeyDown;
/**
* Emits an event when the `IgxChipComponent` has entered the `IgxChipsAreaComponent`.
* Returns the target `IgxChipComponent`, the drag `IgxChipComponent`, as well as
* the original drop event arguments.
* ```typescript
* chipEnter(event: IChipEnterDragAreaEventArgs){
* let targetChip = event.targetChip;
* }
* ```
* ```html
* <igx-chip #myChip [id]="'igx-chip-1'" [draggable]="true" (onDragEnter)="chipEnter($event)">
* ```
* @type {?}
*/
IgxChipComponent.prototype.onDragEnter;
/**
* @hidden
* @type {?}
*/
IgxChipComponent.prototype.chipArea;
/**
* @hidden
* @type {?}
*/
IgxChipComponent.prototype.dragDir;
/**
* @hidden
* @type {?}
*/
IgxChipComponent.prototype.defaultRemoveIcon;
/**
* @hidden
* @type {?}
*/
IgxChipComponent.prototype.defaultSelectIcon;
/**
* @type {?}
* @protected
*/
IgxChipComponent.prototype._selected;
/**
* @type {?}
* @protected
*/
IgxChipComponent.prototype._selectedItemClass;
/**
* @type {?}
* @protected
*/
IgxChipComponent.prototype._movedWhileRemoving;
/** @type {?} */
IgxChipComponent.prototype.cdr;
/** @type {?} */
IgxChipComponent.prototype.elementRef;
/**
* @type {?}
* @private
*/
IgxChipComponent.prototype.renderer;
/**
* @type {?}
* @protected
*/
IgxChipComponent.prototype._displayDensityOptions;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hpcC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9pZ25pdGV1aS1hbmd1bGFyLyIsInNvdXJjZXMiOlsibGliL2NoaXBzL2NoaXAuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQ0gsU0FBUyxFQUNULGlCQUFpQixFQUNqQixZQUFZLEVBQ1osVUFBVSxFQUNWLFdBQVcsRUFDWCxLQUFLLEVBQ0wsTUFBTSxFQUNOLFNBQVMsRUFDVCxTQUFTLEVBQ1QsV0FBVyxFQUNYLE1BQU0sRUFDTixRQUFRLEVBQ1gsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUEwQyxtQkFBbUIsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3pILE9BQU8sRUFDSCxnQkFBZ0IsRUFLbkIsTUFBTSwyQ0FBMkMsQ0FBQzs7OztBQUduRCx3Q0FHQzs7O0lBRkcsMkNBQThGOztJQUM5RixtQ0FBd0I7Ozs7O0FBRzVCLHlDQUVDOzs7SUFERyxxQ0FBZ0I7Ozs7O0FBR3BCLDJDQUdDOzs7SUFGRyw4Q0FBNkI7O0lBQzdCLHVDQUFnQjs7Ozs7QUFHcEIsaURBRUM7OztJQURHLCtDQUEyQjs7Ozs7QUFHL0IsMENBR0M7OztJQUZHLHNDQUFnQjs7SUFDaEIsd0NBQWtCOzs7SUFHbEIsT0FBTyxHQUFHLENBQUM7QUFNZixNQUFNLE9BQU8sZ0JBQWlCLFNBQVEsa0JBQWtCOzs7Ozs7O0lBd1RwRCxZQUFtQixHQUFzQixFQUFTLFVBQXNCLEVBQVUsUUFBbUIsRUFDOUMsc0JBQThDO1FBQzdGLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1FBRm5CLFFBQUcsR0FBSCxHQUFHLENBQW1CO1FBQVMsZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQUFVLGFBQVEsR0FBUixRQUFRLENBQVc7UUFDOUMsMkJBQXNCLEdBQXRCLHNCQUFzQixDQUF3Qjs7Ozs7OztRQS9TOUYsT0FBRSxHQUFHLFlBQVksT0FBTyxFQUFFLEVBQUUsQ0FB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MEQ7Ozs7O0lBQzFELCtDQUFzQzs7SUFFMUIsK0JBQTZCOztJQUFFLHNDQUE2Qjs7Ozs7SUFBRSxvQ0FBMkI7Ozs7O0lBQ2pHLGtEQUFpRyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gICAgQ29tcG9uZW50LFxuICAgIENoYW5nZURldGVjdG9yUmVmLFxuICAgIEV2ZW50RW1pdHRlcixcbiAgICBFbGVtZW50UmVmLFxuICAgIEhvc3RCaW5kaW5nLFxuICAgIElucHV0LFxuICAgIE91dHB1dCxcbiAgICBWaWV3Q2hpbGQsXG4gICAgUmVuZGVyZXIyLFxuICAgIFRlbXBsYXRlUmVmLFxuICAgIEluamVjdCxcbiAgICBPcHRpb25hbFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IERpc3BsYXlEZW5zaXR5LCBJRGlzcGxheURlbnNpdHlPcHRpb25zLCBEaXNwbGF5RGVuc2l0eVRva2VuLCBEaXNwbGF5RGVuc2l0eUJhc2UgfSBmcm9tICcuLi9jb3JlL2Rpc3BsYXlEZW5zaXR5JztcbmltcG9ydCB7XG4gICAgSWd4RHJhZ0RpcmVjdGl2ZSxcbiAgICBJRHJhZ0Jhc2VFdmVudEFyZ3MsXG4gICAgSURyYWdTdGFydEV2ZW50QXJncyxcbiAgICBJZ3hEcm9wRW50ZXJFdmVudEFyZ3MsXG4gICAgSWd4RHJvcEV2ZW50QXJnc1xufSBmcm9tICcuLi9kaXJlY3RpdmVzL2RyYWdkcm9wL2RyYWdkcm9wLmRpcmVjdGl2ZSc7XG5cblxuZXhwb3J0IGludGVyZmFjZSBJQmFzZUNoaXBFdmVudEFyZ3Mge1xuICAgIG9yaWdpbmFsRXZlbnQ6IFBvaW50ZXJFdmVudCB8IE1vdXNlRXZlbnQgfCBUb3VjaEV2ZW50IHwgS2V5Ym9hcmRFdmVudCB8IElneERyb3BFbnRlckV2ZW50QXJncztcbiAgICBvd25lcjogSWd4Q2hpcENvbXBvbmVudDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJQ2hpcENsaWNrRXZlbnRBcmdzIGV4dGVuZHMgSUJhc2VDaGlwRXZlbnRBcmdzIHtcbiAgICBjYW5jZWw6IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSUNoaXBLZXlEb3duRXZlbnRBcmdzIGV4dGVuZHMgSUJhc2VDaGlwRXZlbnRBcmdzIHtcbiAgICBvcmlnaW5hbEV2ZW50OiBLZXlib2FyZEV2ZW50O1xuICAgIGNhbmNlbDogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJQ2hpcEVudGVyRHJhZ0FyZWFFdmVudEFyZ3MgZXh0ZW5kcyBJQmFzZUNoaXBFdmVudEFyZ3Mge1xuICAgIGRyYWdDaGlwOiBJZ3hDaGlwQ29tcG9uZW50O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIElDaGlwU2VsZWN0RXZlbnRBcmdzIGV4dGVuZHMgSUJhc2VDaGlwRXZlbnRBcmdzIHtcbiAgICBjYW5jZWw6IGJvb2xlYW47XG4gICAgc2VsZWN0ZWQ6IGJvb2xlYW47XG59XG5cbmxldCBDSElQX0lEID0gMDtcblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICdpZ3gtY2hpcCcsXG4gICAgdGVtcGxhdGVVcmw6ICdjaGlwLmNvbXBvbmVudC5odG1sJ1xufSlcbmV4cG9ydCBjbGFzcyBJZ3hDaGlwQ29tcG9uZW50IGV4dGVuZHMgRGlzcGxheURlbnNpdHlCYXNlIHtcblxuICAgIC8qKlxuICAgICAqIEFuIEBJbnB1dCBwcm9wZXJ0eSB0aGF0IHNldHMgdGhlIHZhbHVlIG9mIGBpZGAgYXR0cmlidXRlLiBJZiBub3QgcHJvdmlkZWQgaXQgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlZC5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPGlneC1jaGlwIFtpZF09XCInaWd4LWNoaXAtMSdcIj48L2lneC1jaGlwPlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBIb3N0QmluZGluZygnYXR0ci5pZCcpXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgaWQgPSBgaWd4LWNoaXAtJHtDSElQX0lEKyt9YDtcblxuICAgIC8qKlxuICAgICAqIEFuIEBJbnB1dCBwcm9wZXJ0eSB0aGF0IHN0b3JlcyBkYXRhIHJlbGF0ZWQgdG8gdGhlIGNoaXAuXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxpZ3gtY2hpcCBbZGF0YV09XCJ7IHZhbHVlOiAnQ291bnRyeScgfVwiPjwvaWd4LWNoaXA+XG4gICAgICogYGBgXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgZGF0YTogYW55O1xuXG4gICAgLyoqXG4gICAgICogQW4gQElucHV0IHByb3BlcnR5IHRoYXQgZGVmaW5lcyBpZiB0aGUgYElneENoaXBDb21wb25lbnRgIGNhbiBiZSBkcmFnZ2VkIGluIG9yZGVyIHRvIGNoYW5nZSBpdCdzIHBvc2l0aW9uLlxuICAgICAqIEJ5IGRlZmF1bHQgaXQgaXMgc2V0IHRvIGZhbHNlLlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8aWd4LWNoaXAgW2lkXT1cIidpZ3gtY2hpcC0xJ1wiIFtkcmFnZ2FibGVdPVwidHJ1ZVwiPjwvaWd4LWNoaXA+XG4gICAgICogYGBgXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgZHJhZ2dhYmxlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdGhhdCBkZWZpbmVzIGlmIHRoZSBgSWd4Q2hpcENvbXBvbmVudGAgc2hvdWxkIHJlbmRlciByZW1vdmUgYnV0dG9uIGFuZCB0aHJvdyByZW1vdmUgZXZlbnRzLlxuICAgICAqIEJ5IGRlZmF1bHQgaXQgaXMgc2V0IHRvIGZhbHNlLlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8aWd4LWNoaXAgW2lkXT1cIidpZ3gtY2hpcC0xJ1wiIFtkcmFnZ2FibGVdPVwidHJ1ZVwiIFtyZW1vdmFibGVdPVwidHJ1ZVwiPjwvaWd4LWNoaXA+XG4gICAgICogYGBgXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgcmVtb3ZhYmxlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBBbiBASW5wdXQgcHJvcGVydHkgdGhhdCBvdmVycmlkZXMgdGhlIGRlZmF1bHQgaWNvbiB0aGF0IHRoZSBjaGlwIGFwcGxpZXMgdG8gdGhlIHJlbW92ZSBidXR0b24uXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxpZ3gtY2hpcCBbaWRdPVwiY2hpcC5pZFwiIFtyZW1vdmFibGVdPVwidHJ1ZVwiIFtyZW1vdmVJY29uXT1cImljb25UZW1wbGF0ZVwiPjwvaWd4LWNoaXA+XG4gICAgICogPG5nLXRlbXBsYXRlICNpY29uVGVtcGxhdGU+PGlneC1pY29uPmRlbGV0ZTwvaWd4LWljb24+PC9uZy10ZW1wbGF0ZT5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyByZW1vdmVJY29uOiBUZW1wbGF0ZVJlZjxhbnk+O1xuXG4gICAgLyoqXG4gICAgICogQW4gQElucHV0IHByb3BlcnR5IHRoYXQgZGVmaW5lcyBpZiB0aGUgYElneENoaXBDb21wb25lbnRgIGNhbiBiZSBzZWxlY3RlZCBvbiBjbGljayBvciB0aHJvdWdoIG5hdmlnYXRpb24sXG4gICAgICogQnkgZGVmYXVsdCBpdCBpcyBzZXQgdG8gZmFsc2UuXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxpZ3gtY2hpcCBbaWRdPVwiY2hpcC5pZFwiIFtkcmFnZ2FibGVdPVwidHJ1ZVwiIFtyZW1vdmFibGVdPVwidHJ1ZVwiIFtzZWxlY3RhYmxlXT1cInRydWVcIj48L2lneC1jaGlwPlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIHNlbGVjdGFibGUgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEFuIEBJbnB1dCBwcm9wZXJ0eSB0aGF0IG92ZXJyaWRlcyB0aGUgZGVmYXVsdCBpY29uIHRoYXQgdGhlIGNoaXAgYXBwbGllcyB3aGVuIGl0IGlzIHNlbGVjdGVkLlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8aWd4LWNoaXAgW2lkXT1cImNoaXAuaWRcIiBbc2VsZWN0YWJsZV09XCJ0cnVlXCIgW3NlbGVjdEljb25dPVwiaWNvblRlbXBsYXRlXCI+PC9pZ3gtY2hpcD5cbiAgICAgKiA8bmctdGVtcGxhdGUgI2ljb25UZW1wbGF0ZT48aWd4LWljb24+ZG9uZV9vdXRsaW5lPC9pZ3gtaWNvbj48L25nLXRlbXBsYXRlPlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIHNlbGVjdEljb246IFRlbXBsYXRlUmVmPGFueT47XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgY2xhc3MgPSAnJztcblxuICAgIC8qKlxuICAgICAqIEFuIEBJbnB1dCBwcm9wZXJ0eSB0aGF0IGRlZmluZXMgaWYgdGhlIGBJZ3hDaGlwQ29tcG9uZW50YCBpcyBkaXNhYmxlZC4gV2hlbiBkaXNhYmxlZCBpdCByZXN0cmljdHMgdXNlciBpbnRlcmFjdGlvbnNcbiAgICAgKiBsaWtlIGZvY3VzaW5nIG9uIGNsaWNrIG9yIHRhYiwgc2VsZWN0aW9uIG9uIGNsaWNrIG9yIFNwYWNlLCBkcmFnZ2luZy5cbiAgICAgKiBCeSBkZWZhdWx0IGl0IGlzIHNldCB0byBmYWxzZS5cbiAgICAgKiBgYGBodG1sXG4gICAgICogPGlneC1jaGlwIFtpZF09XCJjaGlwLmlkXCIgW2Rpc2FibGVkXT1cInRydWVcIj48L2lneC1jaGlwPlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIGRpc2FibGVkID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBgSWd4Q2hpcENvbXBvbmVudGAgc2VsZWN0ZWQgc3RhdGUuXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxpZ3gtY2hpcCAjbXlDaGlwIFtpZF09XCInaWd4LWNoaXAtMSdcIiBbc2VsZWN0YWJsZV09XCJ0cnVlXCIgW3NlbGVjdGVkXT1cInRydWVcIj5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBzZXQgc2VsZWN0ZWQobmV3VmFsdWU6IGJvb2xlYW4pIHtcbiAgICAgICAgdGhpcy5jaGFuZ2VTZWxlY3Rpb24obmV3VmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgaWYgdGhlIGBJZ3hDaGlwQ29tcG9uZW50YCBpcyBzZWxlY3RlZC5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogQFZpZXdDaGlsZCgnbXlDaGlwJylcbiAgICAgKiBwdWJsaWMgY2hpcDogSWd4Q2hpcENvbXBvbmVudDtcbiAgICAgKiBzZWxlY3RlZENoaXAoKXtcbiAgICAgKiAgICAgbGV0IHNlbGVjdGVkQ2hpcCA9IHRoaXMuY2hpcC5zZWxlY3RlZDtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIGdldCBzZWxlY3RlZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NlbGVjdGVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFuIEBJbnB1dCBwcm9wZXJ0eSB0aGF0IHNldHMgdGhlIGBJZ3hDaGlwQ29tcG9uZW50YCBiYWNrZ3JvdW5kIGNvbG9yLlxuICAgICAqIFRoZSBgY29sb3JgIHByb3BlcnR5IHN1cHBvcnRzIHN0cmluZywgcmdiLCBoZXguXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxpZ3gtY2hpcCAjbXlDaGlwIFtpZF09XCInaWd4LWNoaXAtMSdcIiBbY29sb3JdPVwiJyNmZjAwMDAnXCI+PC9pZ3gtY2hpcD5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBzZXQgY29sb3IobmV3Q29sb3IpIHtcbiAgICAgICAgdGhpcy5jaGlwQXJlYS5uYXRpdmVFbGVtZW50LnN0eWxlLmJhY2tncm91bmRDb2xvciA9IG5ld0NvbG9yO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGJhY2tncm91bmQgY29sb3Igb2YgdGhlIGBJZ3hDaGlwQ29tcG9uZW50YC5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogQFZpZXdDaGlsZCgnbXlDaGlwJylcbiAgICAgKiBwdWJsaWMgY2hpcDogSWd4Q2hpcENvbXBvbmVudDtcbiAgICAgKiBuZ0FmdGVyVmlld0luaXQoKXtcbiAgICAgKiAgICAgbGV0IGNoaXBDb2xvciA9IHRoaXMuY2hpcC5jb2xvcjtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGljIGdldCBjb2xvcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2hpcEFyZWEubmF0aXZlRWxlbWVudC5zdHlsZS5iYWNrZ3JvdW5kQ29sb3I7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRW1pdHMgYW4gZXZlbnQgd2hlbiB0aGUgYElneENoaXBDb21wb25lbnRgIG1vdmluZyBzdGFydHMuXG4gICAgICogUmV0dXJucyB0aGUgbW92aW5nIGBJZ3hDaGlwQ29tcG9uZW50YC5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogbW92ZVN0YXJ0ZWQoZXZlbnQ6IElCYXNlQ2hpcEV2ZW50QXJncyl7XG4gICAgICogICAgIGxldCBtb3ZpbmdDaGlwID0gZXZlbnQub3duZXI7XG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8aWd4LWNoaXAgI215Q2hpcCBbaWRdPVwiJ2lneC1jaGlwLTEnXCIgW2RyYWdnYWJsZV09XCJ0cnVlXCIgKG9uTW92ZVN0YXJ0KT1cIm1vdmVTdGFydGVkKCRldmVudClcIj5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25Nb3ZlU3RhcnQgPSBuZXcgRXZlbnRFbWl0dGVyPElCYXNlQ2hpcEV2ZW50QXJncz4oKTtcblxuICAgIC8qKlxuICAgICAqIEVtaXRzIGFuIGV2ZW50IHdoZW4gdGhlIGBJZ3hDaGlwQ29tcG9uZW50YCBtb3ZpbmcgZW5kcy5cbiAgICAgKiBSZXR1cm5zIHRoZSBtb3ZlZCBgSWd4Q2hpcENvbXBvbmVudGAuXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIG1vdmVFbmRlZChldmVudDogSUJhc2VDaGlwRXZlbnRBcmdzKXtcbiAgICAgKiAgICAgbGV0IG1vdmVkQ2hpcCA9IGV2ZW50Lm93bmVyO1xuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBgYGBodG1sXG4gICAgICogPGlneC1jaGlwICNteUNoaXAgW2lkXT1cIidpZ3gtY2hpcC0xJ1wiIFtkcmFnZ2FibGVdPVwidHJ1ZVwiIChvbk1vdmVFbmQpPVwibW92ZUVuZGVkKCRldmVudClcIj5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25Nb3ZlRW5kID0gbmV3IEV2ZW50RW1pdHRlcjxJQmFzZUNoaXBFdmVudEFyZ3M+KCk7XG5cbiAgICAvKipcbiAgICAgKiBFbWl0cyBhbiBldmVudCB3aGVuIHRoZSBgSWd4Q2hpcENvbXBvbmVudGAgaXMgcmVtb3ZlZC5cbiAgICAgKiBSZXR1cm5zIHRoZSByZW1vdmVkIGBJZ3hDaGlwQ29tcG9uZW50YC5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogcmVtb3ZlKGV2ZW50OiBJQmFzZUNoaXBFdmVudEFyZ3Mpe1xuICAgICAqICAgICBsZXQgcmVtb3ZlZENoaXAgPSBldmVudC5vd25lcjtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxpZ3gtY2hpcCAjbXlDaGlwIFtpZF09XCInaWd4LWNoaXAtMSdcIiBbZHJhZ2dhYmxlXT1cInRydWVcIiAob25SZW1vdmUpPVwicmVtb3ZlKCRldmVudClcIj5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25SZW1vdmUgPSBuZXcgRXZlbnRFbWl0dGVyPElCYXNlQ2hpcEV2ZW50QXJncz4oKTtcblxuICAgIC8qKlxuICAgICAqIEVtaXRzIGFuIGV2ZW50IHdoZW4gdGhlIGBJZ3hDaGlwQ29tcG9uZW50YCBpcyBjbGlja2VkLlxuICAgICAqIFJldHVybnMgdGhlIGNsaWNrZWQgYElneENoaXBDb21wb25lbnRgLCB3aGV0aGVyIHRoZSBldmVudCBzaG91bGQgYmUgY2FuY2VsZWQuXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGNoaXBDbGljayhldmVudDogSUNoaXBDbGlja0V2ZW50QXJncyl7XG4gICAgICogICAgIGxldCBjbGlja2VkQ2hpcCA9IGV2ZW50Lm93bmVyO1xuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBgYGBodG1sXG4gICAgICogPGlneC1jaGlwICNteUNoaXAgW2lkXT1cIidpZ3gtY2hpcC0xJ1wiIFtkcmFnZ2FibGVdPVwidHJ1ZVwiIChvbkNsaWNrKT1cImNoaXBDbGljaygkZXZlbnQpXCI+XG4gICAgICogYGBgXG4gICAgICovXG4gICAgQE91dHB1dCgpXG4gICAgcHVibGljIG9uQ2xpY2sgPSBuZXcgRXZlbnRFbWl0dGVyPElDaGlwQ2xpY2tFdmVudEFyZ3M+KCk7XG5cbiAgICAvKipcbiAgICAgKiBFbWl0cyBldmVudCB3aGVuIHRoZSBgSWd4Q2hpcENvbXBvbmVudGAgaXMgc2VsZWN0ZWQvZGVzZWxlY3RlZC5cbiAgICAgKiBSZXR1cm5zIHRoZSBzZWxlY3RlZCBjaGlwIHJlZmVyZW5jZSwgd2hldGhlciB0aGUgZXZlbnQgc2hvdWxkIGJlIGNhbmNlbGVkLCB3aGF0IGlzIHRoZSBuZXh0IHNlbGVjdGlvbiBzdGF0ZSBhbmRcbiAgICAgKiB3aGVuIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQgYnkgaW50ZXJhY3Rpb24gYG9yaWdpbmFsRXZlbnRgIGlzIHByb3ZpZGVkLCBvdGhlcndpc2UgYG9yaWdpbmFsRXZlbnRgIGlzIGBudWxsYC5cbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogY2hpcFNlbGVjdChldmVudDogSUNoaXBTZWxlY3RFdmVudEFyZ3Mpe1xuICAgICAqICAgICBsZXQgc2VsZWN0ZWRDaGlwID0gZXZlbnQub3duZXI7XG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8aWd4LWNoaXAgI215Q2hpcCBbaWRdPVwiJ2lneC1jaGlwLTEnXCIgW2RyYWdnYWJsZV09XCJ0cnVlXCIgKG9uU2VsZWN0aW9uKT1cImNoaXBTZWxlY3QoJGV2ZW50KVwiPlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBPdXRwdXQoKVxuICAgIHB1YmxpYyBvblNlbGVjdGlvbiA9IG5ldyBFdmVudEVtaXR0ZXI8SUNoaXBTZWxlY3RFdmVudEFyZ3M+KCk7XG5cbiAgICAvKipcbiAgICAgKiBFbWl0cyBhbiBldmVudCB3aGVuIHRoZSBgSWd4Q2hpcENvbXBvbmVudGAga2V5Ym9hcmQgbmF2aWdhdGlvbiBpcyBiZWluZyB1c2VkLlxuICAgICAqIFJldHVybnMgdGhlIGZvY3VzZWQvc2VsZWN0ZWQgYElneENoaXBDb21wb25lbnRgLCB3aGV0aGVyIHRoZSBldmVudCBzaG91bGQgYmUgY2FuY2VsZWQsXG4gICAgICogaWYgdGhlIGBhbHRgLCBgc2hpZnRgIG9yIGBjb250cm9sYCBrZXkgaXMgcHJlc3NlZCBhbmQgdGhlIHByZXNzZWQga2V5IG5hbWUuXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGNoaXBLZXlEb3duKGV2ZW50OiBJQ2hpcEtleURvd25FdmVudEFyZ3Mpe1xuICAgICAqICAgICBsZXQga2V5RG93biA9IGV2ZW50LmtleTtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogYGBgaHRtbFxuICAgICAqIDxpZ3gtY2hpcCAjbXlDaGlwIFtpZF09XCInaWd4LWNoaXAtMSdcIiBbZHJhZ2dhYmxlXT1cInRydWVcIiAob25LZXlEb3duKT1cImNoaXBLZXlEb3duKCRldmVudClcIj5cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25LZXlEb3duID0gbmV3IEV2ZW50RW1pdHRlcjxJQ2hpcEtleURvd25FdmVudEFyZ3M+KCk7XG5cbiAgICAvKipcbiAgICAgKiBFbWl0cyBhbiBldmVudCB3aGVuIHRoZSBgSWd4Q2hpcENvbXBvbmVudGAgaGFzIGVudGVyZWQgdGhlIGBJZ3hDaGlwc0FyZWFDb21wb25lbnRgLlxuICAgICAqIFJldHVybnMgdGhlIHRhcmdldCBgSWd4Q2hpcENvbXBvbmVudGAsIHRoZSBkcmFnIGBJZ3hDaGlwQ29tcG9uZW50YCwgYXMgIHdlbGwgYXNcbiAgICAgKiB0aGUgb3JpZ2luYWwgZHJvcCBldmVudCBhcmd1bWVudHMuXG4gICAgICogYGBgdHlwZXNjcmlwdFxuICAgICAqIGNoaXBFbnRlcihldmVudDogSUNoaXBFbnRlckRyYWdBcmVhRXZlbnRBcmdzKXtcbiAgICAgKiAgICAgbGV0IHRhcmdldENoaXAgPSBldmVudC50YXJnZXRDaGlwO1xuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBgYGBodG1sXG4gICAgICogPGlneC1jaGlwICNteUNoaXAgW2lkXT1cIidpZ3gtY2hpcC0xJ1wiIFtkcmFnZ2FibGVdPVwidHJ1ZVwiIChvbkRyYWdFbnRlcik9XCJjaGlwRW50ZXIoJGV2ZW50KVwiPlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIEBPdXRwdXQoKVxuICAgIHB1YmxpYyBvbkRyYWdFbnRlciA9IG5ldyBFdmVudEVtaXR0ZXI8SUNoaXBFbnRlckRyYWdBcmVhRXZlbnRBcmdzPigpO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIEBIb3N0QmluZGluZygnYXR0ci5jbGFzcycpXG4gICAgZ2V0IGhvc3RDbGFzcygpOiBzdHJpbmcge1xuICAgICAgICBjb25zdCBjbGFzc2VzID0gW3RoaXMuZ2V0Q29tcG9uZW50RGVuc2l0eUNsYXNzKCdpZ3gtY2hpcCcpXTtcbiAgICAgICAgY2xhc3Nlcy5wdXNoKHRoaXMuZGlzYWJsZWQgPyAnaWd4LWNoaXAtLWRpc2FibGVkJyA6ICcnKTtcbiAgICAgICAgLy8gVGhlIGN1c3RvbSBjbGFzc2VzIHNob3VsZCBiZSBhdCB0aGUgZW5kLlxuICAgICAgICBjbGFzc2VzLnB1c2godGhpcy5jbGFzcyk7XG4gICAgICAgIHJldHVybiBjbGFzc2VzLmpvaW4oJyAnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgQFZpZXdDaGlsZCgnY2hpcEFyZWEnLCB7IHJlYWQ6IEVsZW1lbnRSZWYgfSlcbiAgICBwdWJsaWMgY2hpcEFyZWE6IEVsZW1lbnRSZWY7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgQFZpZXdDaGlsZCgnY2hpcEFyZWEnLCB7IHJlYWQ6IElneERyYWdEaXJlY3RpdmUgfSlcbiAgICBwdWJsaWMgZHJhZ0RpcjogSWd4RHJhZ0RpcmVjdGl2ZTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBAVmlld0NoaWxkKCdkZWZhdWx0UmVtb3ZlSWNvbicsIHsgcmVhZDogVGVtcGxhdGVSZWYgfSlcbiAgICBwdWJsaWMgZGVmYXVsdFJlbW92ZUljb246IFRlbXBsYXRlUmVmPGFueT47XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgQFZpZXdDaGlsZCgnZGVmYXVsdFNlbGVjdEljb24nLCB7IHJlYWQ6IFRlbXBsYXRlUmVmIH0pXG4gICAgcHVibGljIGRlZmF1bHRTZWxlY3RJY29uOiBUZW1wbGF0ZVJlZjxhbnk+O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgcmVtb3ZlQnV0dG9uVGVtcGxhdGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJlbW92ZUljb24gfHwgdGhpcy5kZWZhdWx0UmVtb3ZlSWNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIGdldCBzZWxlY3RJY29uVGVtcGxhdGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNlbGVjdEljb24gfHwgdGhpcy5kZWZhdWx0U2VsZWN0SWNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGljIGdldCBnaG9zdENsYXNzKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldENvbXBvbmVudERlbnNpdHlDbGFzcygnaWd4LWNoaXBfX2dob3N0Jyk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCBjaGlwVGFiaW5kZXgoKSB7XG4gICAgICAgIHJldHVybiAhdGhpcy5kaXNhYmxlZCA/IDAgOiAnJztcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgX3NlbGVjdGVkID0gZmFsc2U7XG4gICAgcHJvdGVjdGVkIF9zZWxlY3RlZEl0ZW1DbGFzcyA9ICdpZ3gtY2hpcF9faXRlbS0tc2VsZWN0ZWQnO1xuICAgIHByb3R