| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc |
| */ |
| import * as tslib_1 from "tslib"; |
| import { Component, Input, Output, EventEmitter, forwardRef, ChangeDetectionStrategy, ChangeDetectorRef, ViewChild, ContentChildren, QueryList, Inject, Optional, ViewChildren, ElementRef } from '@angular/core'; |
| import { DOCUMENT } from '@angular/common'; |
| import { DomSanitizer } from '@angular/platform-browser'; |
| import { NG_VALUE_ACCESSOR } from '@angular/forms'; |
| import { coerceBooleanProperty } from '@angular/cdk/coercion'; |
| import { ENTER, SPACE, UP_ARROW, DOWN_ARROW } from '@angular/cdk/keycodes'; |
| import { Subject } from 'rxjs'; |
| import { debounceTime } from 'rxjs/operators'; |
| import { TdDataTableRowComponent } from './data-table-row/data-table-row.component'; |
| import { TdDataTableTemplateDirective } from './directives/data-table-template.directive'; |
| import { mixinControlValueAccessor } from '@covalent/core/common'; |
| /** @enum {string} */ |
| var TdDataTableSortingOrder = { |
| Ascending: 'ASC', |
| Descending: 'DESC', |
| }; |
| export { TdDataTableSortingOrder }; |
| /** |
| * @record |
| */ |
| export function ITdDataTableColumnWidth() { } |
| if (false) { |
| /** @type {?|undefined} */ |
| ITdDataTableColumnWidth.prototype.min; |
| /** @type {?|undefined} */ |
| ITdDataTableColumnWidth.prototype.max; |
| } |
| /** |
| * @record |
| */ |
| export function ITdDataTableColumn() { } |
| if (false) { |
| /** @type {?} */ |
| ITdDataTableColumn.prototype.name; |
| /** @type {?} */ |
| ITdDataTableColumn.prototype.label; |
| /** @type {?|undefined} */ |
| ITdDataTableColumn.prototype.tooltip; |
| /** @type {?|undefined} */ |
| ITdDataTableColumn.prototype.numeric; |
| /** @type {?|undefined} */ |
| ITdDataTableColumn.prototype.format; |
| /** @type {?|undefined} */ |
| ITdDataTableColumn.prototype.nested; |
| /** @type {?|undefined} */ |
| ITdDataTableColumn.prototype.sortable; |
| /** @type {?|undefined} */ |
| ITdDataTableColumn.prototype.hidden; |
| /** @type {?|undefined} */ |
| ITdDataTableColumn.prototype.filter; |
| /** @type {?|undefined} */ |
| ITdDataTableColumn.prototype.width; |
| } |
| /** |
| * @record |
| */ |
| export function ITdDataTableSelectEvent() { } |
| if (false) { |
| /** @type {?} */ |
| ITdDataTableSelectEvent.prototype.row; |
| /** @type {?} */ |
| ITdDataTableSelectEvent.prototype.selected; |
| /** @type {?} */ |
| ITdDataTableSelectEvent.prototype.index; |
| } |
| /** |
| * @record |
| */ |
| export function ITdDataTableSelectAllEvent() { } |
| if (false) { |
| /** @type {?} */ |
| ITdDataTableSelectAllEvent.prototype.rows; |
| /** @type {?} */ |
| ITdDataTableSelectAllEvent.prototype.selected; |
| } |
| /** |
| * @record |
| */ |
| export function ITdDataTableRowClickEvent() { } |
| if (false) { |
| /** @type {?} */ |
| ITdDataTableRowClickEvent.prototype.row; |
| /** @type {?} */ |
| ITdDataTableRowClickEvent.prototype.index; |
| } |
| /** |
| * @record |
| */ |
| export function IInternalColumnWidth() { } |
| if (false) { |
| /** @type {?} */ |
| IInternalColumnWidth.prototype.value; |
| /** @type {?} */ |
| IInternalColumnWidth.prototype.limit; |
| /** @type {?} */ |
| IInternalColumnWidth.prototype.index; |
| /** @type {?|undefined} */ |
| IInternalColumnWidth.prototype.min; |
| /** @type {?|undefined} */ |
| IInternalColumnWidth.prototype.max; |
| } |
| /** |
| * Constant to set the rows offset before and after the viewport |
| * @type {?} |
| */ |
| var TD_VIRTUAL_OFFSET = 2; |
| /** |
| * Constant to set default row height if none is provided |
| * @type {?} |
| */ |
| var TD_VIRTUAL_DEFAULT_ROW_HEIGHT = 48; |
| var TdDataTableBase = /** @class */ (function () { |
| function TdDataTableBase(_changeDetectorRef) { |
| this._changeDetectorRef = _changeDetectorRef; |
| } |
| return TdDataTableBase; |
| }()); |
| export { TdDataTableBase }; |
| if (false) { |
| /** @type {?} */ |
| TdDataTableBase.prototype._changeDetectorRef; |
| } |
| /* tslint:disable-next-line */ |
| /** @type {?} */ |
| export var _TdDataTableMixinBase = mixinControlValueAccessor(TdDataTableBase, []); |
| var TdDataTableComponent = /** @class */ (function (_super) { |
| tslib_1.__extends(TdDataTableComponent, _super); |
| function TdDataTableComponent(_document, _elementRef, _domSanitizer, _changeDetectorRef) { |
| var _this = _super.call(this, _changeDetectorRef) || this; |
| _this._document = _document; |
| _this._elementRef = _elementRef; |
| _this._domSanitizer = _domSanitizer; |
| _this._hostWidth = 0; |
| /** |
| * manually resizable columns |
| */ |
| _this._resizableColumns = false; |
| _this._columnClientX = 0; |
| _this._onColumnResize = new Subject(); |
| _this._widths = []; |
| _this._onResize = new Subject(); |
| _this._scrollHorizontalOffset = 0; |
| _this._onHorizontalScroll = new Subject(); |
| _this._onVerticalScroll = new Subject(); |
| // Array of cached row heights to allow dynamic row heights |
| _this._rowHeightCache = []; |
| // Total pseudo height of all the elements |
| _this._totalHeight = 0; |
| // Total host height for the viewport |
| _this._hostHeight = 0; |
| // Scrolled vertical pixels |
| _this._scrollVerticalOffset = 0; |
| // Variables that set from and to which rows will be rendered |
| _this._fromRow = 0; |
| _this._toRow = 0; |
| _this._selectable = false; |
| _this._clickable = false; |
| _this._multiple = true; |
| _this._allSelected = false; |
| _this._indeterminate = false; |
| /** |
| * sorting |
| */ |
| _this._sortable = false; |
| _this._sortOrder = TdDataTableSortingOrder.Ascending; |
| /** |
| * shift select |
| */ |
| _this._shiftPreviouslyPressed = false; |
| _this._lastSelectedIndex = -1; |
| _this._firstSelectedIndex = -1; |
| _this._firstCheckboxValue = false; |
| /** |
| * template fetching support |
| */ |
| _this._templateMap = new Map(); |
| /** |
| * sortChange?: function |
| * Event emitted when the column headers are clicked. [sortable] needs to be enabled. |
| * Emits an [ITdDataTableSortChangeEvent] implemented object. |
| */ |
| _this.onSortChange = new EventEmitter(); |
| /** |
| * rowSelect?: function |
| * Event emitted when a row is selected/deselected. [selectable] needs to be enabled. |
| * Emits an [ITdDataTableSelectEvent] implemented object. |
| */ |
| _this.onRowSelect = new EventEmitter(); |
| /** |
| * rowClick?: function |
| * Event emitted when a row is clicked. |
| * Emits an [ITdDataTableRowClickEvent] implemented object. |
| */ |
| _this.onRowClick = new EventEmitter(); |
| /** |
| * selectAll?: function |
| * Event emitted when all rows are selected/deselected by the all checkbox. [selectable] needs to be enabled. |
| * Emits an [ITdDataTableSelectAllEvent] implemented object. |
| */ |
| _this.onSelectAll = new EventEmitter(); |
| /** |
| * compareWith?: function(row, model): boolean |
| * Allows custom comparison between row and model to see if row is selected or not |
| * Default comparation is by reference |
| */ |
| _this.compareWith = function (row, model) { |
| return row === model; |
| }; |
| return _this; |
| } |
| Object.defineProperty(TdDataTableComponent.prototype, "resizingColumn", { |
| get: /** |
| * @return {?} |
| */ |
| function () { |
| return this._resizingColumn; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(TdDataTableComponent.prototype, "hostWidth", { |
| get: /** |
| * @return {?} |
| */ |
| function () { |
| // if the checkboxes are rendered, we need to remove their width |
| // from the total width to calculate properly |
| if (this.selectable) { |
| return this._hostWidth - 42; |
| } |
| return this._hostWidth; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(TdDataTableComponent.prototype, "offsetTransform", { |
| /** |
| * Returns the offset style with a proper calculation on how much it should move |
| * over the y axis of the total height |
| */ |
| get: /** |
| * Returns the offset style with a proper calculation on how much it should move |
| * over the y axis of the total height |
| * @return {?} |
| */ |
| function () { |
| return this._offsetTransform; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(TdDataTableComponent.prototype, "totalHeight", { |
| /** |
| * Returns the assumed total height of the rows |
| */ |
| get: /** |
| * Returns the assumed total height of the rows |
| * @return {?} |
| */ |
| function () { |
| return this._totalHeight; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(TdDataTableComponent.prototype, "fromRow", { |
| /** |
| * Returns the initial row to render in the viewport |
| */ |
| get: /** |
| * Returns the initial row to render in the viewport |
| * @return {?} |
| */ |
| function () { |
| return this._fromRow; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(TdDataTableComponent.prototype, "toRow", { |
| /** |
| * Returns the last row to render in the viewport |
| */ |
| get: /** |
| * Returns the last row to render in the viewport |
| * @return {?} |
| */ |
| function () { |
| return this._toRow; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(TdDataTableComponent.prototype, "columnsLeftScroll", { |
| /** |
| * Returns scroll position to reposition column headers |
| */ |
| get: /** |
| * Returns scroll position to reposition column headers |
| * @return {?} |
| */ |
| function () { |
| return this._scrollHorizontalOffset * -1; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(TdDataTableComponent.prototype, "allSelected", { |
| /** |
| * Returns true if all values are selected. |
| */ |
| get: /** |
| * Returns true if all values are selected. |
| * @return {?} |
| */ |
| function () { |
| return this._allSelected; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(TdDataTableComponent.prototype, "indeterminate", { |
| /** |
| * Returns true if all values are not deselected |
| * and at least one is. |
| */ |
| get: /** |
| * Returns true if all values are not deselected |
| * and at least one is. |
| * @return {?} |
| */ |
| function () { |
| return this._indeterminate; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(TdDataTableComponent.prototype, "data", { |
| get: /** |
| * @return {?} |
| */ |
| function () { |
| return this._data; |
| }, |
| /** |
| * data?: {[key: string]: any}[] |
| * Sets the data to be rendered as rows. |
| */ |
| set: /** |
| * data?: {[key: string]: any}[] |
| * Sets the data to be rendered as rows. |
| * @param {?} data |
| * @return {?} |
| */ |
| function (data) { |
| var _this = this; |
| this._data = data; |
| this._rowHeightCache = []; |
| Promise.resolve().then(function () { |
| _this.refresh(); |
| // scroll back to the top if the data has changed |
| _this._scrollableDiv.nativeElement.scrollTop = 0; |
| }); |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(TdDataTableComponent.prototype, "virtualData", { |
| get: /** |
| * @return {?} |
| */ |
| function () { |
| return this._virtualData; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(TdDataTableComponent.prototype, "columns", { |
| get: /** |
| * @return {?} |
| */ |
| function () { |
| var _this = this; |
| if (this._columns) { |
| return this._columns; |
| } |
| if (this.hasData) { |
| this._columns = []; |
| // if columns is undefined, use key in [data] rows as name and label for column headers. |
| /** @type {?} */ |
| var row = this._data[0]; |
| Object.keys(row).forEach(function (k) { |
| if (!_this._columns.find(function (c) { return c.name === k; })) { |
| _this._columns.push({ name: k, label: k }); |
| } |
| }); |
| return this._columns; |
| } |
| else { |
| return []; |
| } |
| }, |
| /** |
| * columns?: ITdDataTableColumn[] |
| * Sets additional column configuration. [ITdDataTableColumn.name] has to exist in [data] as key. |
| * Defaults to [data] keys. |
| */ |
| set: /** |
| * columns?: ITdDataTableColumn[] |
| * Sets additional column configuration. [ITdDataTableColumn.name] has to exist in [data] as key. |
| * Defaults to [data] keys. |
| * @param {?} cols |
| * @return {?} |
| */ |
| function (cols) { |
| this._columns = cols; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(TdDataTableComponent.prototype, "resizableColumns", { |
| get: /** |
| * @return {?} |
| */ |
| function () { |
| return this._resizableColumns; |
| }, |
| /** |
| * resizableColumns?: boolean |
| * Enables manual column resize. |
| * Defaults to 'false' |
| */ |
| set: /** |
| * resizableColumns?: boolean |
| * Enables manual column resize. |
| * Defaults to 'false' |
| * @param {?} resizableColumns |
| * @return {?} |
| */ |
| function (resizableColumns) { |
| this._resizableColumns = coerceBooleanProperty(resizableColumns); |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(TdDataTableComponent.prototype, "selectable", { |
| get: /** |
| * @return {?} |
| */ |
| function () { |
| return this._selectable; |
| }, |
| /** |
| * selectable?: boolean |
| * Enables row selection events, hover and selected row states. |
| * Defaults to 'false' |
| */ |
| set: /** |
| * selectable?: boolean |
| * Enables row selection events, hover and selected row states. |
| * Defaults to 'false' |
| * @param {?} selectable |
| * @return {?} |
| */ |
| function (selectable) { |
| this._selectable = coerceBooleanProperty(selectable); |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(TdDataTableComponent.prototype, "clickable", { |
| get: /** |
| * @return {?} |
| */ |
| function () { |
| return this._clickable; |
| }, |
| /** |
| * clickable?: boolean |
| * Enables row click events, hover. |
| * Defaults to 'false' |
| */ |
| set: /** |
| * clickable?: boolean |
| * Enables row click events, hover. |
| * Defaults to 'false' |
| * @param {?} clickable |
| * @return {?} |
| */ |
| function (clickable) { |
| this._clickable = coerceBooleanProperty(clickable); |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(TdDataTableComponent.prototype, "multiple", { |
| get: /** |
| * @return {?} |
| */ |
| function () { |
| return this._multiple; |
| }, |
| /** |
| * multiple?: boolean |
| * Enables multiple row selection. [selectable] needs to be enabled. |
| * Defaults to 'false' |
| */ |
| set: /** |
| * multiple?: boolean |
| * Enables multiple row selection. [selectable] needs to be enabled. |
| * Defaults to 'false' |
| * @param {?} multiple |
| * @return {?} |
| */ |
| function (multiple) { |
| this._multiple = coerceBooleanProperty(multiple); |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(TdDataTableComponent.prototype, "sortable", { |
| get: /** |
| * @return {?} |
| */ |
| function () { |
| return this._sortable; |
| }, |
| /** |
| * sortable?: boolean |
| * Enables sorting events, sort icons and active column states. |
| * Defaults to 'false' |
| */ |
| set: /** |
| * sortable?: boolean |
| * Enables sorting events, sort icons and active column states. |
| * Defaults to 'false' |
| * @param {?} sortable |
| * @return {?} |
| */ |
| function (sortable) { |
| this._sortable = coerceBooleanProperty(sortable); |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(TdDataTableComponent.prototype, "sortBy", { |
| /** |
| * sortBy?: string |
| * Sets the active sort column. [sortable] needs to be enabled. |
| */ |
| set: /** |
| * sortBy?: string |
| * Sets the active sort column. [sortable] needs to be enabled. |
| * @param {?} columnName |
| * @return {?} |
| */ |
| function (columnName) { |
| if (!columnName) { |
| return; |
| } |
| /** @type {?} */ |
| var column = this.columns.find(function (c) { return c.name === columnName; }); |
| if (!column) { |
| throw new Error('[sortBy] must be a valid column name'); |
| } |
| this._sortBy = column; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(TdDataTableComponent.prototype, "sortByColumn", { |
| get: /** |
| * @return {?} |
| */ |
| function () { |
| return this._sortBy; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(TdDataTableComponent.prototype, "sortOrder", { |
| /** |
| * sortOrder?: ['ASC' | 'DESC'] or TdDataTableSortingOrder |
| * Sets the sort order of the [sortBy] column. [sortable] needs to be enabled. |
| * Defaults to 'ASC' or TdDataTableSortingOrder.Ascending |
| */ |
| set: /** |
| * sortOrder?: ['ASC' | 'DESC'] or TdDataTableSortingOrder |
| * Sets the sort order of the [sortBy] column. [sortable] needs to be enabled. |
| * Defaults to 'ASC' or TdDataTableSortingOrder.Ascending |
| * @param {?} order |
| * @return {?} |
| */ |
| function (order) { |
| /** @type {?} */ |
| var sortOrder = order ? order.toUpperCase() : 'ASC'; |
| if (sortOrder !== 'DESC' && sortOrder !== 'ASC') { |
| throw new Error('[sortOrder] must be empty, ASC or DESC'); |
| } |
| this._sortOrder = sortOrder === 'ASC' ? |
| TdDataTableSortingOrder.Ascending : TdDataTableSortingOrder.Descending; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(TdDataTableComponent.prototype, "sortOrderEnum", { |
| get: /** |
| * @return {?} |
| */ |
| function () { |
| return this._sortOrder; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(TdDataTableComponent.prototype, "hasData", { |
| get: /** |
| * @return {?} |
| */ |
| function () { |
| return this._data && this._data.length > 0; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| /** |
| * Initialize observable for resize and scroll events |
| */ |
| /** |
| * Initialize observable for resize and scroll events |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype.ngOnInit = /** |
| * Initialize observable for resize and scroll events |
| * @return {?} |
| */ |
| function () { |
| var _this = this; |
| // initialize observable for resize calculations |
| this._resizeSubs = this._onResize.asObservable().subscribe(function () { |
| if (_this._rows) { |
| _this._rows.toArray().forEach(function (row, index) { |
| _this._rowHeightCache[_this.fromRow + index] = row.height + 1; |
| }); |
| } |
| _this._calculateWidths(); |
| _this._calculateVirtualRows(); |
| }); |
| // initialize observable for column resize calculations |
| this._columnResizeSubs = this._onColumnResize.asObservable().pipe(debounceTime(0)).subscribe(function (clientX) { |
| _this._columnClientX = clientX; |
| _this._calculateWidths(); |
| _this._changeDetectorRef.markForCheck(); |
| }); |
| // initialize observable for scroll column header reposition |
| this._horizontalScrollSubs = this._onHorizontalScroll.asObservable() |
| .subscribe(function (horizontalScroll) { |
| _this._scrollHorizontalOffset = horizontalScroll; |
| _this._changeDetectorRef.markForCheck(); |
| }); |
| // initialize observable for virtual scroll rendering |
| this._verticalScrollSubs = this._onVerticalScroll.asObservable() |
| .subscribe(function (verticalScroll) { |
| _this._scrollVerticalOffset = verticalScroll; |
| _this._calculateVirtualRows(); |
| _this._changeDetectorRef.markForCheck(); |
| }); |
| this._valueChangesSubs = this.valueChanges.subscribe(function (value) { |
| _this.refresh(); |
| }); |
| }; |
| /** |
| * Loads templates and sets them in a map for faster access. |
| */ |
| /** |
| * Loads templates and sets them in a map for faster access. |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype.ngAfterContentInit = /** |
| * Loads templates and sets them in a map for faster access. |
| * @return {?} |
| */ |
| function () { |
| for (var i = 0; i < this._templates.toArray().length; i++) { |
| this._templateMap.set(this._templates.toArray()[i].tdDataTableTemplate, this._templates.toArray()[i].templateRef); |
| } |
| }; |
| /** |
| * Checks hosts native elements widths to see if it has changed (resize check) |
| */ |
| /** |
| * Checks hosts native elements widths to see if it has changed (resize check) |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype.ngAfterContentChecked = /** |
| * Checks hosts native elements widths to see if it has changed (resize check) |
| * @return {?} |
| */ |
| function () { |
| var _this = this; |
| // check if the scroll has been reset when element is hidden |
| if (this._scrollVerticalOffset - this._scrollableDiv.nativeElement.scrollTop > 5) { |
| // scroll back to the top if element has been reset |
| this._onVerticalScroll.next(0); |
| } |
| if (this._elementRef.nativeElement) { |
| /** @type {?} */ |
| var newHostWidth_1 = this._elementRef.nativeElement.getBoundingClientRect().width; |
| // if the width has changed then we throw a resize event. |
| if (this._hostWidth !== newHostWidth_1) { |
| setTimeout(function () { |
| _this._hostWidth = newHostWidth_1; |
| _this._onResize.next(); |
| }, 0); |
| } |
| } |
| if (this._scrollableDiv.nativeElement) { |
| /** @type {?} */ |
| var newHostHeight = this._scrollableDiv.nativeElement.getBoundingClientRect().height; |
| // if the height of the viewport has changed, then we mark for check |
| if (this._hostHeight !== newHostHeight) { |
| this._hostHeight = newHostHeight; |
| this._calculateVirtualRows(); |
| this._changeDetectorRef.markForCheck(); |
| } |
| } |
| }; |
| /** |
| * Registers to an observable that checks if all rows have been rendered |
| * so we can start calculating the widths |
| */ |
| /** |
| * Registers to an observable that checks if all rows have been rendered |
| * so we can start calculating the widths |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype.ngAfterViewInit = /** |
| * Registers to an observable that checks if all rows have been rendered |
| * so we can start calculating the widths |
| * @return {?} |
| */ |
| function () { |
| var _this = this; |
| this._rowsChangedSubs = this._rows.changes.pipe(debounceTime(0)).subscribe(function () { |
| _this._onResize.next(); |
| }); |
| this._calculateVirtualRows(); |
| }; |
| /** |
| * Unsubscribes observables when data table is destroyed |
| */ |
| /** |
| * Unsubscribes observables when data table is destroyed |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype.ngOnDestroy = /** |
| * Unsubscribes observables when data table is destroyed |
| * @return {?} |
| */ |
| function () { |
| if (this._resizeSubs) { |
| this._resizeSubs.unsubscribe(); |
| } |
| if (this._columnResizeSubs) { |
| this._columnResizeSubs.unsubscribe(); |
| } |
| if (this._horizontalScrollSubs) { |
| this._horizontalScrollSubs.unsubscribe(); |
| } |
| if (this._verticalScrollSubs) { |
| this._verticalScrollSubs.unsubscribe(); |
| } |
| if (this._rowsChangedSubs) { |
| this._rowsChangedSubs.unsubscribe(); |
| } |
| if (this._valueChangesSubs) { |
| this._valueChangesSubs.unsubscribe(); |
| } |
| }; |
| /** |
| * Method that gets executed every time there is a scroll event |
| * Calls the scroll observable |
| */ |
| /** |
| * Method that gets executed every time there is a scroll event |
| * Calls the scroll observable |
| * @param {?} event |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype.handleScroll = /** |
| * Method that gets executed every time there is a scroll event |
| * Calls the scroll observable |
| * @param {?} event |
| * @return {?} |
| */ |
| function (event) { |
| /** @type {?} */ |
| var element = ((/** @type {?} */ (event.target))); |
| if (element) { |
| /** @type {?} */ |
| var horizontalScroll = element.scrollLeft; |
| if (this._scrollHorizontalOffset !== horizontalScroll) { |
| this._onHorizontalScroll.next(horizontalScroll); |
| } |
| /** @type {?} */ |
| var verticalScroll = element.scrollTop; |
| if (this._scrollVerticalOffset !== verticalScroll) { |
| this._onVerticalScroll.next(verticalScroll); |
| } |
| } |
| }; |
| /** |
| * Returns the width needed for the columns via index |
| */ |
| /** |
| * Returns the width needed for the columns via index |
| * @param {?} index |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype.getColumnWidth = /** |
| * Returns the width needed for the columns via index |
| * @param {?} index |
| * @return {?} |
| */ |
| function (index) { |
| if (this._widths[index]) { |
| return this._widths[index].value; |
| } |
| return undefined; |
| }; |
| /** |
| * @param {?} column |
| * @param {?} value |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype.getCellValue = /** |
| * @param {?} column |
| * @param {?} value |
| * @return {?} |
| */ |
| function (column, value) { |
| if (column.nested === undefined || column.nested) { |
| return this._getNestedValue(column.name, value); |
| } |
| return value[column.name]; |
| }; |
| /** |
| * Getter method for template references |
| */ |
| /** |
| * Getter method for template references |
| * @param {?} name |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype.getTemplateRef = /** |
| * Getter method for template references |
| * @param {?} name |
| * @return {?} |
| */ |
| function (name) { |
| return this._templateMap.get(name); |
| }; |
| /** |
| * Clears model (ngModel) of component by removing all values in array. |
| */ |
| /** |
| * Clears model (ngModel) of component by removing all values in array. |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype.clearModel = /** |
| * Clears model (ngModel) of component by removing all values in array. |
| * @return {?} |
| */ |
| function () { |
| this.value.splice(0, this.value.length); |
| }; |
| /** |
| * Refreshes data table and rerenders [data] and [columns] |
| */ |
| /** |
| * Refreshes data table and rerenders [data] and [columns] |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype.refresh = /** |
| * Refreshes data table and rerenders [data] and [columns] |
| * @return {?} |
| */ |
| function () { |
| this._calculateVirtualRows(); |
| this._calculateWidths(); |
| this._calculateCheckboxState(); |
| this._changeDetectorRef.markForCheck(); |
| }; |
| /** |
| * Selects or clears all rows depending on 'checked' value. |
| */ |
| /** |
| * Selects or clears all rows depending on 'checked' value. |
| * @param {?} checked |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype.selectAll = /** |
| * Selects or clears all rows depending on 'checked' value. |
| * @param {?} checked |
| * @return {?} |
| */ |
| function (checked) { |
| var _this = this; |
| /** @type {?} */ |
| var toggledRows = []; |
| if (checked) { |
| this._data.forEach(function (row) { |
| // skiping already selected rows |
| if (!_this.isRowSelected(row)) { |
| _this.value.push(row); |
| // checking which ones are being toggled |
| toggledRows.push(row); |
| } |
| }); |
| this._allSelected = true; |
| this._indeterminate = true; |
| } |
| else { |
| this._data.forEach(function (row) { |
| // checking which ones are being toggled |
| if (_this.isRowSelected(row)) { |
| toggledRows.push(row); |
| /** @type {?} */ |
| var modelRow = _this.value.filter(function (val) { |
| return _this.compareWith(row, val); |
| })[0]; |
| /** @type {?} */ |
| var index = _this.value.indexOf(modelRow); |
| if (index > -1) { |
| _this.value.splice(index, 1); |
| } |
| } |
| }); |
| this._allSelected = false; |
| this._indeterminate = false; |
| } |
| this.onSelectAll.emit({ rows: toggledRows, selected: checked }); |
| this.onChange(this.value); |
| }; |
| /** |
| * Checks if row is selected |
| */ |
| /** |
| * Checks if row is selected |
| * @param {?} row |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype.isRowSelected = /** |
| * Checks if row is selected |
| * @param {?} row |
| * @return {?} |
| */ |
| function (row) { |
| var _this = this; |
| // compare items by [compareWith] function |
| return this.value ? this.value.filter(function (val) { |
| return _this.compareWith(row, val); |
| }).length > 0 : false; |
| }; |
| /** |
| * Selects or clears a row depending on 'checked' value if the row 'isSelectable' |
| * handles cntrl clicks and shift clicks for multi-select |
| */ |
| /** |
| * Selects or clears a row depending on 'checked' value if the row 'isSelectable' |
| * handles cntrl clicks and shift clicks for multi-select |
| * @param {?} row |
| * @param {?} event |
| * @param {?} currentSelected |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype.select = /** |
| * Selects or clears a row depending on 'checked' value if the row 'isSelectable' |
| * handles cntrl clicks and shift clicks for multi-select |
| * @param {?} row |
| * @param {?} event |
| * @param {?} currentSelected |
| * @return {?} |
| */ |
| function (row, event, currentSelected) { |
| if (this.selectable) { |
| this.blockEvent(event); |
| // Check to see if Shift key is selected and need to select everything in between |
| /** @type {?} */ |
| var mouseEvent = (/** @type {?} */ (event)); |
| if (this.multiple && mouseEvent && mouseEvent.shiftKey && this._lastSelectedIndex > -1) { |
| /** @type {?} */ |
| var firstIndex = currentSelected; |
| /** @type {?} */ |
| var lastIndex = this._lastSelectedIndex; |
| if (currentSelected > this._lastSelectedIndex) { |
| firstIndex = this._lastSelectedIndex; |
| lastIndex = currentSelected; |
| } |
| // if clicking a checkbox behind the initial check, then toggle all selections expect the initial checkbox |
| // else the checkboxes clicked are all after the initial one |
| if ((this._firstSelectedIndex >= currentSelected && this._lastSelectedIndex > this._firstSelectedIndex) || |
| (this._firstSelectedIndex <= currentSelected && this._lastSelectedIndex < this._firstSelectedIndex)) { |
| for (var i = firstIndex; i <= lastIndex; i++) { |
| if (this._firstSelectedIndex !== i) { |
| this._doSelection(this._data[i], i); |
| } |
| } |
| } |
| else if ((this._firstSelectedIndex > currentSelected) || (this._firstSelectedIndex < currentSelected)) { |
| // change indexes depending on where the next checkbox is selected (before or after) |
| if (this._firstSelectedIndex > currentSelected) { |
| lastIndex--; |
| } |
| else if (this._firstSelectedIndex < currentSelected) { |
| firstIndex++; |
| } |
| for (var i = firstIndex; i <= lastIndex; i++) { |
| /** @type {?} */ |
| var rowSelected = this.isRowSelected(this._data[i]); |
| // if row is selected and first checkbox was selected |
| // or if row was unselected and first checkbox was unselected |
| // we ignore the toggle |
| if ((this._firstCheckboxValue && !rowSelected) || |
| (!this._firstCheckboxValue && rowSelected)) { |
| this._doSelection(this._data[i], i); |
| } |
| else if (this._shiftPreviouslyPressed) { |
| // else if the checkbox selected was in the middle of the last selection and the first selection |
| // then we undo the selections |
| if ((currentSelected >= this._firstSelectedIndex && currentSelected <= this._lastSelectedIndex) || |
| (currentSelected <= this._firstSelectedIndex && currentSelected >= this._lastSelectedIndex)) { |
| this._doSelection(this._data[i], i); |
| } |
| } |
| } |
| } |
| this._shiftPreviouslyPressed = true; |
| // if shift wasnt pressed, then we take the element checked as the first row |
| // incase the next click uses shift |
| } |
| else if (mouseEvent && !mouseEvent.shiftKey) { |
| this._firstCheckboxValue = this._doSelection(row, currentSelected); |
| this._shiftPreviouslyPressed = false; |
| this._firstSelectedIndex = currentSelected; |
| } |
| this._lastSelectedIndex = currentSelected; |
| } |
| }; |
| /** |
| * Overrides the onselectstart method of the document so other text on the page |
| * doesn't get selected when doing shift selections. |
| */ |
| /** |
| * Overrides the onselectstart method of the document so other text on the page |
| * doesn't get selected when doing shift selections. |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype.disableTextSelection = /** |
| * Overrides the onselectstart method of the document so other text on the page |
| * doesn't get selected when doing shift selections. |
| * @return {?} |
| */ |
| function () { |
| if (this._document) { |
| this._document.onselectstart = function () { |
| return false; |
| }; |
| } |
| }; |
| /** |
| * Resets the original onselectstart method. |
| */ |
| /** |
| * Resets the original onselectstart method. |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype.enableTextSelection = /** |
| * Resets the original onselectstart method. |
| * @return {?} |
| */ |
| function () { |
| if (this._document) { |
| this._document.onselectstart = undefined; |
| } |
| }; |
| /** |
| * emits the onRowClickEvent when a row is clicked |
| * if clickable is true and selectable is false then select the row |
| */ |
| /** |
| * emits the onRowClickEvent when a row is clicked |
| * if clickable is true and selectable is false then select the row |
| * @param {?} row |
| * @param {?} index |
| * @param {?} event |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype.handleRowClick = /** |
| * emits the onRowClickEvent when a row is clicked |
| * if clickable is true and selectable is false then select the row |
| * @param {?} row |
| * @param {?} index |
| * @param {?} event |
| * @return {?} |
| */ |
| function (row, index, event) { |
| if (this.clickable) { |
| // ignoring linting rules here because attribute it actually null or not there |
| // can't check for undefined |
| /** @type {?} */ |
| var srcElement = event.srcElement || event.currentTarget; |
| /** @type {?} */ |
| var element = (/** @type {?} */ (event.target)); |
| /* tslint:disable-next-line */ |
| if (srcElement.getAttribute('stopRowClick') === null && element.tagName.toLowerCase() !== 'mat-pseudo-checkbox') { |
| this.onRowClick.emit({ |
| row: row, |
| index: index, |
| }); |
| } |
| } |
| }; |
| /** |
| * Method handle for sort click event in column headers. |
| */ |
| /** |
| * Method handle for sort click event in column headers. |
| * @param {?} column |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype.handleSort = /** |
| * Method handle for sort click event in column headers. |
| * @param {?} column |
| * @return {?} |
| */ |
| function (column) { |
| if (this._sortBy === column) { |
| this._sortOrder = this._sortOrder === TdDataTableSortingOrder.Ascending ? |
| TdDataTableSortingOrder.Descending : TdDataTableSortingOrder.Ascending; |
| } |
| else { |
| this._sortBy = column; |
| this._sortOrder = TdDataTableSortingOrder.Ascending; |
| } |
| this.onSortChange.next({ name: this._sortBy.name, order: this._sortOrder }); |
| }; |
| /** |
| * Handle all keyup events when focusing a data table row |
| */ |
| /** |
| * Handle all keyup events when focusing a data table row |
| * @param {?} event |
| * @param {?} row |
| * @param {?} index |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype._rowKeyup = /** |
| * Handle all keyup events when focusing a data table row |
| * @param {?} event |
| * @param {?} row |
| * @param {?} index |
| * @return {?} |
| */ |
| function (event, row, index) { |
| switch (event.keyCode) { |
| case ENTER: |
| case SPACE: |
| /** if user presses enter or space, the row should be selected */ |
| if (this.selectable) { |
| this._doSelection(this._data[this.fromRow + index], this.fromRow + index); |
| } |
| break; |
| case UP_ARROW: |
| /** |
| * if users presses the up arrow, we focus the prev row |
| * unless its the first row |
| */ |
| if (index > 0) { |
| this._rows.toArray()[index - 1].focus(); |
| } |
| this.blockEvent(event); |
| if (this.selectable && this.multiple && event.shiftKey && this.fromRow + index >= 0) { |
| this._doSelection(this._data[this.fromRow + index], this.fromRow + index); |
| } |
| break; |
| case DOWN_ARROW: |
| /** |
| * if users presses the down arrow, we focus the next row |
| * unless its the last row |
| */ |
| if (index < (this._rows.toArray().length - 1)) { |
| this._rows.toArray()[index + 1].focus(); |
| } |
| this.blockEvent(event); |
| if (this.selectable && this.multiple && event.shiftKey && this.fromRow + index < this._data.length) { |
| this._doSelection(this._data[this.fromRow + index], this.fromRow + index); |
| } |
| break; |
| default: |
| // default |
| } |
| }; |
| /** |
| * Sets column index of the dragged column and initial clientX of column |
| */ |
| /** |
| * Sets column index of the dragged column and initial clientX of column |
| * @param {?} index |
| * @param {?} event |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype._handleStartColumnDrag = /** |
| * Sets column index of the dragged column and initial clientX of column |
| * @param {?} index |
| * @param {?} event |
| * @return {?} |
| */ |
| function (index, event) { |
| this._columnClientX = event.clientX; |
| this._resizingColumn = index; |
| }; |
| /** |
| * Calculates new width depending on new clientX of dragger column |
| */ |
| /** |
| * Calculates new width depending on new clientX of dragger column |
| * @param {?} event |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype._handleColumnDrag = /** |
| * Calculates new width depending on new clientX of dragger column |
| * @param {?} event |
| * @return {?} |
| */ |
| function (event) { |
| // check if there was been a separator clicked for resize |
| if (this._resizingColumn !== undefined && event.clientX > 0) { |
| /** @type {?} */ |
| var xPosition = event.clientX; |
| // checks if the separator is being moved to try and resize the column, else dont do anything |
| if (xPosition > 0 && this._columnClientX > 0 && (xPosition - this._columnClientX) !== 0) { |
| // calculate the new width depending if making the column bigger or smaller |
| /** @type {?} */ |
| var proposedManualWidth = this._widths[this._resizingColumn].value + (xPosition - this._columnClientX); |
| // if the proposed new width is less than the projected min width of the column, use projected min width |
| if (proposedManualWidth < this._colElements.toArray()[this._resizingColumn].projectedWidth) { |
| proposedManualWidth = this._colElements.toArray()[this._resizingColumn].projectedWidth; |
| } |
| this.columns[this._resizingColumn].width = proposedManualWidth; |
| // update new x position for the resized column |
| this._onColumnResize.next(xPosition); |
| } |
| } |
| }; |
| /** |
| * Ends dragged flags |
| */ |
| /** |
| * Ends dragged flags |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype._handleEndColumnDrag = /** |
| * Ends dragged flags |
| * @return {?} |
| */ |
| function () { |
| this._columnClientX = undefined; |
| this._resizingColumn = undefined; |
| }; |
| /** |
| * Method to prevent the default events |
| */ |
| /** |
| * Method to prevent the default events |
| * @param {?} event |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype.blockEvent = /** |
| * Method to prevent the default events |
| * @param {?} event |
| * @return {?} |
| */ |
| function (event) { |
| event.preventDefault(); |
| }; |
| /** |
| * @param {?} name |
| * @param {?} value |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype._getNestedValue = /** |
| * @param {?} name |
| * @param {?} value |
| * @return {?} |
| */ |
| function (name, value) { |
| if (!(value instanceof Object) || !name) { |
| return value; |
| } |
| if (name.indexOf('.') > -1) { |
| /** @type {?} */ |
| var splitName = name.split(/\.(.+)/, 2); |
| return this._getNestedValue(splitName[1], value[splitName[0]]); |
| } |
| else { |
| return value[name]; |
| } |
| }; |
| /** |
| * Does the actual Row Selection |
| */ |
| /** |
| * Does the actual Row Selection |
| * @param {?} row |
| * @param {?} rowIndex |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype._doSelection = /** |
| * Does the actual Row Selection |
| * @param {?} row |
| * @param {?} rowIndex |
| * @return {?} |
| */ |
| function (row, rowIndex) { |
| var _this = this; |
| /** @type {?} */ |
| var wasSelected = this.isRowSelected(row); |
| if (!wasSelected) { |
| if (!this._multiple) { |
| this.clearModel(); |
| } |
| this.value.push(row); |
| } |
| else { |
| // compare items by [compareWith] function |
| row = this.value.filter(function (val) { |
| return _this.compareWith(row, val); |
| })[0]; |
| /** @type {?} */ |
| var index = this.value.indexOf(row); |
| if (index > -1) { |
| this.value.splice(index, 1); |
| } |
| } |
| this._calculateCheckboxState(); |
| this.onRowSelect.emit({ row: row, index: rowIndex, selected: !wasSelected }); |
| this.onChange(this.value); |
| return !wasSelected; |
| }; |
| /** |
| * Calculate all the state of all checkboxes |
| */ |
| /** |
| * Calculate all the state of all checkboxes |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype._calculateCheckboxState = /** |
| * Calculate all the state of all checkboxes |
| * @return {?} |
| */ |
| function () { |
| var _this = this; |
| var e_1, _a; |
| if (this._data) { |
| this._allSelected = typeof this._data.find(function (d) { return !_this.isRowSelected(d); }) === 'undefined'; |
| this._indeterminate = false; |
| try { |
| for (var _b = tslib_1.__values(this._data), _c = _b.next(); !_c.done; _c = _b.next()) { |
| var row = _c.value; |
| if (!this.isRowSelected(row)) { |
| continue; |
| } |
| this._indeterminate = true; |
| break; |
| } |
| } |
| catch (e_1_1) { e_1 = { error: e_1_1 }; } |
| finally { |
| try { |
| if (_c && !_c.done && (_a = _b.return)) _a.call(_b); |
| } |
| finally { if (e_1) throw e_1.error; } |
| } |
| } |
| }; |
| /** |
| * Calculates the widths for columns and cells depending on content |
| */ |
| /** |
| * Calculates the widths for columns and cells depending on content |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype._calculateWidths = /** |
| * Calculates the widths for columns and cells depending on content |
| * @return {?} |
| */ |
| function () { |
| var _this = this; |
| if (this._colElements && this._colElements.length) { |
| this._widths = []; |
| this._colElements.forEach(function (col, index) { |
| _this._adjustColumnWidth(index, _this._calculateWidth()); |
| }); |
| this._adjustColumnWidhts(); |
| this._changeDetectorRef.markForCheck(); |
| } |
| }; |
| /** |
| * Adjusts columns after calculation to see if they need to be recalculated. |
| */ |
| /** |
| * Adjusts columns after calculation to see if they need to be recalculated. |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype._adjustColumnWidhts = /** |
| * Adjusts columns after calculation to see if they need to be recalculated. |
| * @return {?} |
| */ |
| function () { |
| var _this = this; |
| /** @type {?} */ |
| var fixedTotalWidth = 0; |
| // get the number of total columns that have flexible widths (not fixed or hidden) |
| /** @type {?} */ |
| var flexibleWidths = this._widths.filter(function (width, index) { |
| if (_this.columns[index].hidden) { |
| return false; |
| } |
| if (width.limit || width.max || width.min) { |
| fixedTotalWidth += width.value; |
| } |
| return !width.limit && !width.max && !width.min; |
| }).length; |
| // calculate how much pixes are left that could be spread across |
| // the flexible columns |
| /** @type {?} */ |
| var recalculateHostWidth = 0; |
| if (fixedTotalWidth < this.hostWidth) { |
| recalculateHostWidth = this.hostWidth - fixedTotalWidth; |
| } |
| // if we have flexible columns and pixels to spare on them |
| // we try and spread the pixels across them |
| if (flexibleWidths && recalculateHostWidth) { |
| /** @type {?} */ |
| var newValue_1 = Math.floor(recalculateHostWidth / flexibleWidths); |
| /** @type {?} */ |
| var adjustedNumber_1 = 0; |
| // adjust the column widths with the spread pixels |
| this._widths.forEach(function (colWidth) { |
| if (_this._widths[colWidth.index].max && _this._widths[colWidth.index].value > newValue_1 || |
| _this._widths[colWidth.index].min && _this._widths[colWidth.index].value < newValue_1 || |
| !_this._widths[colWidth.index].limit) { |
| _this._adjustColumnWidth(colWidth.index, newValue_1); |
| adjustedNumber_1++; |
| } |
| }); |
| // if there are still columns that need to be recalculated, we start over |
| /** @type {?} */ |
| var newFlexibleWidths = this._widths.filter(function (width) { |
| return !width.limit && !width.max; |
| }).length; |
| if (newFlexibleWidths !== adjustedNumber_1 && newFlexibleWidths !== flexibleWidths) { |
| this._adjustColumnWidhts(); |
| } |
| } |
| }; |
| /** |
| * Adjusts a single column to see if it can be recalculated |
| */ |
| /** |
| * Adjusts a single column to see if it can be recalculated |
| * @param {?} index |
| * @param {?} value |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype._adjustColumnWidth = /** |
| * Adjusts a single column to see if it can be recalculated |
| * @param {?} index |
| * @param {?} value |
| * @return {?} |
| */ |
| function (index, value) { |
| this._widths[index] = { |
| value: value, |
| index: index, |
| limit: false, |
| min: false, |
| max: false, |
| }; |
| // flag to see if we need to skip the min width projection |
| // depending if a width or min width has been provided |
| /** @type {?} */ |
| var skipMinWidthProjection = false; |
| if (this.columns[index]) { |
| // if the provided width has min/max, then we check to see if we need to set it |
| if (typeof this.columns[index].width === 'object') { |
| /** @type {?} */ |
| var widthOpts = (/** @type {?} */ (this.columns[index].width)); |
| // if the column width is less than the configured min, we override it |
| skipMinWidthProjection = (widthOpts && !!widthOpts.min); |
| if (widthOpts && widthOpts.min >= this._widths[index].value) { |
| this._widths[index].value = widthOpts.min; |
| this._widths[index].min = true; |
| // if the column width is more than the configured max, we override it |
| } |
| else if (widthOpts && widthOpts.max <= this._widths[index].value) { |
| this._widths[index].value = widthOpts.max; |
| this._widths[index].max = true; |
| } |
| // if it has a fixed width, then we just set it |
| } |
| else if (typeof this.columns[index].width === 'number') { |
| this._widths[index].value = (/** @type {?} */ (this.columns[index].width)); |
| skipMinWidthProjection = this._widths[index].limit = true; |
| } |
| } |
| // if there wasn't any width or min width provided, we set a min to what the column width min should be |
| if (!skipMinWidthProjection && |
| this._widths[index].value < this._colElements.toArray()[index].projectedWidth) { |
| this._widths[index].value = this._colElements.toArray()[index].projectedWidth; |
| this._widths[index].min = true; |
| this._widths[index].limit = false; |
| } |
| }; |
| /** |
| * Generic method to calculate column width |
| */ |
| /** |
| * Generic method to calculate column width |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype._calculateWidth = /** |
| * Generic method to calculate column width |
| * @return {?} |
| */ |
| function () { |
| /** @type {?} */ |
| var renderedColumns = this.columns.filter(function (col) { return !col.hidden; }); |
| return Math.floor(this.hostWidth / renderedColumns.length); |
| }; |
| /** |
| * Method to calculate the rows to be rendered in the viewport |
| */ |
| /** |
| * Method to calculate the rows to be rendered in the viewport |
| * @return {?} |
| */ |
| TdDataTableComponent.prototype._calculateVirtualRows = /** |
| * Method to calculate the rows to be rendered in the viewport |
| * @return {?} |
| */ |
| function () { |
| var _this = this; |
| /** @type {?} */ |
| var scrolledRows = 0; |
| if (this._data) { |
| this._totalHeight = 0; |
| /** @type {?} */ |
| var rowHeightSum_1 = 0; |
| // loop through all rows to see if we have their height cached |
| // and sum them all to calculate the total height |
| this._data.forEach(function (d, i) { |
| // iterate through all rows at first and assume all |
| // rows are the same height as the first one |
| if (!_this._rowHeightCache[i]) { |
| _this._rowHeightCache[i] = _this._rowHeightCache[0] || TD_VIRTUAL_DEFAULT_ROW_HEIGHT; |
| } |
| rowHeightSum_1 += _this._rowHeightCache[i]; |
| // check how many rows have been scrolled |
| if (_this._scrollVerticalOffset - rowHeightSum_1 > 0) { |
| scrolledRows++; |
| } |
| }); |
| this._totalHeight = rowHeightSum_1; |
| // set the initial row to be rendered taking into account the row offset |
| /** @type {?} */ |
| var fromRow = scrolledRows - TD_VIRTUAL_OFFSET; |
| this._fromRow = fromRow > 0 ? fromRow : 0; |
| /** @type {?} */ |
| var hostHeight = this._hostHeight; |
| /** @type {?} */ |
| var index = 0; |
| // calculate how many rows can fit in the viewport |
| while (hostHeight > 0) { |
| hostHeight -= this._rowHeightCache[this.fromRow + index]; |
| index++; |
| } |
| // set the last row to be rendered taking into account the row offset |
| /** @type {?} */ |
| var range = (index - 1) + (TD_VIRTUAL_OFFSET * 2); |
| /** @type {?} */ |
| var toRow = range + this.fromRow; |
| // if last row is greater than the total length, then we use the total length |
| if (isFinite(toRow) && toRow > this._data.length) { |
| toRow = this._data.length; |
| } |
| else if (!isFinite(toRow)) { |
| toRow = TD_VIRTUAL_OFFSET; |
| } |
| this._toRow = toRow; |
| } |
| else { |
| this._totalHeight = 0; |
| this._fromRow = 0; |
| this._toRow = 0; |
| } |
| /** @type {?} */ |
| var offset = 0; |
| // calculate the proper offset depending on how many rows have been scrolled |
| if (scrolledRows > TD_VIRTUAL_OFFSET) { |
| for (var index = 0; index < this.fromRow; index++) { |
| offset += this._rowHeightCache[index]; |
| } |
| } |
| this._offsetTransform = this._domSanitizer.bypassSecurityTrustStyle('translateY(' + (offset - this.totalHeight) + 'px)'); |
| if (this._data) { |
| this._virtualData = this.data.slice(this.fromRow, this.toRow); |
| } |
| // mark for check at the end of the queue so we are sure |
| // that the changes will be marked |
| Promise.resolve().then(function () { |
| _this._changeDetectorRef.markForCheck(); |
| }); |
| }; |
| TdDataTableComponent.decorators = [ |
| { type: Component, args: [{ |
| providers: [{ |
| provide: NG_VALUE_ACCESSOR, |
| useExisting: forwardRef(function () { return TdDataTableComponent; }), |
| multi: true, |
| }], |
| selector: 'td-data-table', |
| template: "<table td-data-table\n [style.left.px]=\"columnsLeftScroll\"\n [class.mat-selectable]=\"selectable\">\n <thead class=\"td-data-table-head\"\n (dragover)=\"_handleColumnDrag($event)\">\n <tr td-data-table-column-row>\n <th td-data-table-column class=\"mat-checkbox-column\" *ngIf=\"selectable\">\n <mat-checkbox\n #checkBoxAll\n *ngIf=\"multiple\"\n [disabled]=\"!hasData\"\n [indeterminate]=\"indeterminate && !allSelected && hasData\"\n [checked]=\"allSelected && hasData\"\n (click)=\"blockEvent($event); selectAll(!checkBoxAll.checked)\"\n (keyup.enter)=\"selectAll(!checkBoxAll.checked)\"\n (keyup.space)=\"selectAll(!checkBoxAll.checked)\"\n (keydown.space)=\"blockEvent($event)\">\n </mat-checkbox>\n </th>\n <th td-data-table-column\n #columnElement\n *ngFor=\"let column of columns; let i = index; let last = last\"\n [style.min-width.px]=\"getColumnWidth(i)\"\n [style.max-width.px]=\"getColumnWidth(i)\"\n [name]=\"column.name\"\n [numeric]=\"column.numeric\"\n [active]=\"(column.sortable || sortable) && column === sortByColumn\"\n [sortable]=\"column.sortable || (sortable && column.sortable !== false)\"\n [sortOrder]=\"sortOrderEnum\"\n [hidden]=\"column.hidden\"\n (sortChange)=\"handleSort(column)\">\n <span [matTooltip]=\"column.tooltip\">{{column.label}}</span>\n <span td-column-resizer\n *ngIf=\"resizableColumns\"\n draggable=\"true\"\n class=\"td-data-table-column-resizer\"\n [class.td-resizing]=\"i === resizingColumn\"\n (mousedown)=\"_handleStartColumnDrag(i, $event)\"\n (dragstart)=\"$event?.dataTransfer?.setData('text', '')\"\n (drag)=\"_handleColumnDrag($event)\"\n (dragend)=\"_handleEndColumnDrag()\"\n (mouseup)=\"_handleEndColumnDrag()\">\n <span class=\"td-data-table-column-separator\"></span>\n </span>\n </th>\n </tr>\n </thead>\n</table>\n<div #scrollableDiv class=\"td-data-table-scrollable\"\n (scroll)=\"handleScroll($event)\">\n <div [style.height.px]=\"totalHeight\"></div>\n <table td-data-table\n [style.transform]=\"offsetTransform\"\n [style.position]=\"'absolute'\"\n [class.mat-selectable]=\"selectable\"\n [class.mat-clickable]=\"clickable\">\n <tbody class=\"td-data-table-body\">\n <tr td-data-table-row\n #dtRow\n [tabIndex]=\"selectable ? 0 : -1\"\n [selected]=\"(clickable || selectable) && isRowSelected(row)\"\n *ngFor=\"let row of virtualData; let rowIndex = index\"\n (click)=\"handleRowClick(row, fromRow + rowIndex, $event)\"\n (keyup)=\"selectable && _rowKeyup($event, row, rowIndex)\"\n (keydown.space)=\"blockEvent($event)\"\n (keydown.shift.space)=\"blockEvent($event)\"\n (keydown.shift)=\"disableTextSelection()\"\n (keyup.shift)=\"enableTextSelection()\">\n <td td-data-table-cell class=\"mat-checkbox-cell\" *ngIf=\"selectable\">\n <mat-pseudo-checkbox\n [state]=\"dtRow.selected ? 'checked' : 'unchecked'\"\n (mousedown)=\"disableTextSelection()\"\n (mouseup)=\"enableTextSelection()\"\n stopRowClick\n (click)=\"select(row, $event, fromRow + rowIndex)\">\n </mat-pseudo-checkbox>\n </td>\n <td td-data-table-cell\n [numeric]=\"column.numeric\"\n [hidden]=\"column.hidden\"\n *ngFor=\"let column of columns; let i = index\"\n [style.min-width.px]=\"getColumnWidth(i)\"\n [style.max-width.px]=\"getColumnWidth(i)\">\n <span *ngIf=\"!getTemplateRef(column.name)\">{{column.format ? column.format(getCellValue(column, row)) : getCellValue(column, row)}}</span>\n <ng-template\n *ngIf=\"getTemplateRef(column.name)\"\n [ngTemplateOutlet]=\"getTemplateRef(column.name)\"\n [ngTemplateOutletContext]=\"{ value: getCellValue(column, row), row: row, column: column.name, index: rowIndex }\">\n </ng-template>\n </td>\n </tr>\n </tbody>\n </table>\n</div>\n<ng-content></ng-content>\n", |
| inputs: ['value'], |
| changeDetection: ChangeDetectionStrategy.OnPush, |
| styles: [":host{display:block;overflow:hidden}:host .td-data-table-scrollable{position:relative;overflow:auto;height:calc(100% - 56px)}.td-data-table-column-resizer{right:0;width:6px;cursor:col-resize}.td-data-table-column-resizer,.td-data-table-column-resizer .td-data-table-column-separator{position:absolute;height:100%;top:0}.td-data-table-column-resizer .td-data-table-column-separator{left:2px}.td-data-table-column-resizer.td-resizing{cursor:-webkit-grabbing}table.td-data-table{width:auto!important}table.td-data-table.mat-selectable tbody>tr.td-data-table-row{-webkit-transition:background-color .2s;transition:background-color .2s}table.td-data-table.mat-selectable .td-data-table-column:first-child>.td-data-table-column-content-wrapper,table.td-data-table.mat-selectable td.td-data-table-cell:first-child>.td-data-table-column-content-wrapper,table.td-data-table.mat-selectable th.td-data-table-column:first-child>.td-data-table-column-content-wrapper{width:18px;min-width:18px;padding:0 24px}table.td-data-table.mat-selectable .td-data-table-column:nth-child(2)>.td-data-table-column-content-wrapper,table.td-data-table.mat-selectable td.td-data-table-cell:nth-child(2)>.td-data-table-column-content-wrapper,table.td-data-table.mat-selectable th.td-data-table-column:nth-child(2)>.td-data-table-column-content-wrapper{padding-left:0}[dir=rtl] table.td-data-table.mat-selectable .td-data-table-column:nth-child(2)>.td-data-table-column-content-wrapper,[dir=rtl] table.td-data-table.mat-selectable td.td-data-table-cell:nth-child(2)>.td-data-table-column-content-wrapper,[dir=rtl] table.td-data-table.mat-selectable th.td-data-table-column:nth-child(2)>.td-data-table-column-content-wrapper{padding-right:0;padding-left:28px}table.td-data-table td.mat-checkbox-cell,table.td-data-table th.mat-checkbox-column{min-width:42px;width:42px;font-size:0!important}table.td-data-table td.mat-checkbox-cell mat-pseudo-checkbox,table.td-data-table th.mat-checkbox-column mat-pseudo-checkbox{width:18px;height:18px}::ng-deep table.td-data-table td.mat-checkbox-cell mat-pseudo-checkbox.mat-pseudo-checkbox-checked::after,::ng-deep table.td-data-table th.mat-checkbox-column mat-pseudo-checkbox.mat-pseudo-checkbox-checked::after{width:11px!important;height:4px!important}table.td-data-table td.mat-checkbox-cell mat-checkbox ::ng-deep .mat-checkbox-inner-container,table.td-data-table th.mat-checkbox-column mat-checkbox ::ng-deep .mat-checkbox-inner-container{width:18px;height:18px;margin:0}"] |
| }] } |
| ]; |
| /** @nocollapse */ |
| TdDataTableComponent.ctorParameters = function () { return [ |
| { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [DOCUMENT,] }] }, |
| { type: ElementRef }, |
| { type: DomSanitizer }, |
| { type: ChangeDetectorRef } |
| ]; }; |
| TdDataTableComponent.propDecorators = { |
| _templates: [{ type: ContentChildren, args: [TdDataTableTemplateDirective,] }], |
| _scrollableDiv: [{ type: ViewChild, args: ['scrollableDiv',] }], |
| _colElements: [{ type: ViewChildren, args: ['columnElement',] }], |
| _rows: [{ type: ViewChildren, args: [TdDataTableRowComponent,] }], |
| data: [{ type: Input, args: ['data',] }], |
| columns: [{ type: Input, args: ['columns',] }], |
| resizableColumns: [{ type: Input, args: ['resizableColumns',] }], |
| selectable: [{ type: Input, args: ['selectable',] }], |
| clickable: [{ type: Input, args: ['clickable',] }], |
| multiple: [{ type: Input, args: ['multiple',] }], |
| sortable: [{ type: Input, args: ['sortable',] }], |
| sortBy: [{ type: Input, args: ['sortBy',] }], |
| sortOrder: [{ type: Input, args: ['sortOrder',] }], |
| onSortChange: [{ type: Output, args: ['sortChange',] }], |
| onRowSelect: [{ type: Output, args: ['rowSelect',] }], |
| onRowClick: [{ type: Output, args: ['rowClick',] }], |
| onSelectAll: [{ type: Output, args: ['selectAll',] }], |
| compareWith: [{ type: Input, args: ['compareWith',] }] |
| }; |
| return TdDataTableComponent; |
| }(_TdDataTableMixinBase)); |
| export { TdDataTableComponent }; |
| if (false) { |
| /** |
| * responsive width calculations |
| * @type {?} |
| */ |
| TdDataTableComponent.prototype._resizeSubs; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._rowsChangedSubs; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._hostWidth; |
| /** |
| * manually resizable columns |
| * @type {?} |
| */ |
| TdDataTableComponent.prototype._resizableColumns; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._columnClientX; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._columnResizeSubs; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._resizingColumn; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._onColumnResize; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._widths; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._onResize; |
| /** |
| * column header reposition and viewpoort |
| * @type {?} |
| */ |
| TdDataTableComponent.prototype._verticalScrollSubs; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._horizontalScrollSubs; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._scrollHorizontalOffset; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._onHorizontalScroll; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._onVerticalScroll; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._rowHeightCache; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._totalHeight; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._hostHeight; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._scrollVerticalOffset; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._offsetTransform; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._fromRow; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._toRow; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._valueChangesSubs; |
| /** |
| * internal attributes |
| * @type {?} |
| */ |
| TdDataTableComponent.prototype._data; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._virtualData; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._columns; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._selectable; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._clickable; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._multiple; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._allSelected; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._indeterminate; |
| /** |
| * sorting |
| * @type {?} |
| */ |
| TdDataTableComponent.prototype._sortable; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._sortBy; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._sortOrder; |
| /** |
| * shift select |
| * @type {?} |
| */ |
| TdDataTableComponent.prototype._shiftPreviouslyPressed; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._lastSelectedIndex; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._firstSelectedIndex; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._firstCheckboxValue; |
| /** |
| * template fetching support |
| * @type {?} |
| */ |
| TdDataTableComponent.prototype._templateMap; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._templates; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._scrollableDiv; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._colElements; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._rows; |
| /** |
| * sortChange?: function |
| * Event emitted when the column headers are clicked. [sortable] needs to be enabled. |
| * Emits an [ITdDataTableSortChangeEvent] implemented object. |
| * @type {?} |
| */ |
| TdDataTableComponent.prototype.onSortChange; |
| /** |
| * rowSelect?: function |
| * Event emitted when a row is selected/deselected. [selectable] needs to be enabled. |
| * Emits an [ITdDataTableSelectEvent] implemented object. |
| * @type {?} |
| */ |
| TdDataTableComponent.prototype.onRowSelect; |
| /** |
| * rowClick?: function |
| * Event emitted when a row is clicked. |
| * Emits an [ITdDataTableRowClickEvent] implemented object. |
| * @type {?} |
| */ |
| TdDataTableComponent.prototype.onRowClick; |
| /** |
| * selectAll?: function |
| * Event emitted when all rows are selected/deselected by the all checkbox. [selectable] needs to be enabled. |
| * Emits an [ITdDataTableSelectAllEvent] implemented object. |
| * @type {?} |
| */ |
| TdDataTableComponent.prototype.onSelectAll; |
| /** |
| * compareWith?: function(row, model): boolean |
| * Allows custom comparison between row and model to see if row is selected or not |
| * Default comparation is by reference |
| * @type {?} |
| */ |
| TdDataTableComponent.prototype.compareWith; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._document; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._elementRef; |
| /** @type {?} */ |
| TdDataTableComponent.prototype._domSanitizer; |
| } |
| //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YS10YWJsZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9AY292YWxlbnQvY29yZS9kYXRhLXRhYmxlLyIsInNvdXJjZXMiOlsiZGF0YS10YWJsZS5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSx1QkFBdUIsRUFDM0UsaUJBQWlCLEVBQUUsU0FBUyxFQUM1QixlQUFlLEVBQWlDLFNBQVMsRUFBRSxNQUFNLEVBQ2pFLFFBQVEsRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUErQixNQUFNLGVBQWUsQ0FBQztBQUNoRyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUFFLFlBQVksRUFBYSxNQUFNLDJCQUEyQixDQUFDO0FBQ3BFLE9BQU8sRUFBRSxpQkFBaUIsRUFBd0IsTUFBTSxnQkFBZ0IsQ0FBQztBQUV6RSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUM5RCxPQUFPLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFM0UsT0FBTyxFQUE0QixPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDekQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTlDLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLDJDQUEyQyxDQUFDO0FBRXBGLE9BQU8sRUFBRSw0QkFBNEIsRUFBRSxNQUFNLDRDQUE0QyxDQUFDO0FBRTFGLE9BQU8sRUFBeUIseUJBQXlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQzs7O0lBR3ZGLFdBQVksS0FBSztJQUNqQixZQUFhLE1BQU07Ozs7OztBQUdyQiw2Q0FHQzs7O0lBRkMsc0NBQWE7O0lBQ2Isc0NBQWE7Ozs7O0FBR2Ysd0NBV0M7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Q3BDLHlDQUFrQzs7SUFDbEMsNENBQXNDOztJQUN0Qyw4Q0FBd0M7Ozs7O0lBR3hDLHlDQUFtQzs7SUFDbkMsdUNBQW9DOztJQUNwQywwQ0FBZ0Y7Ozs7O0lBR2hGLHVEQUFpRDs7SUFDakQsa0RBQXdDOztJQUN4QyxtREFBeUM7O0lBQ3pDLG1EQUE2Qzs7Ozs7SUFHN0MsNENBQTBGOztJQUMxRiwwQ0FBbUc7O0lBRW5HLDhDQUF1RDs7SUFFdkQsNENBQW1GOztJQUVuRixxQ0FBaUY7Ozs7Ozs7SUE0TGpGLDRDQUNvRjs7Ozs7OztJQU9wRiwyQ0FBc0g7Ozs7Ozs7SUFPdEgsMENBQXdIOzs7Ozs7O0lBT3hILDJDQUNpRjs7Ozs7OztJQWNqRiwyQ0FFQzs7SUFkVyx5Q0FBb0Q7O0lBQ3BELDJDQUErQjs7SUFDL0IsNkNBQW1DIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIGZvcndhcmRSZWYsIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICAgICAgICAgQ2hhbmdlRGV0ZWN0b3JSZWYsIFZpZXdDaGlsZCwgT25EZXN0cm95LCBBZnRlclZpZXdJbml0LFxuICAgICAgICAgQ29udGVudENoaWxkcmVuLCBUZW1wbGF0ZVJlZiwgQWZ0ZXJDb250ZW50SW5pdCwgUXVlcnlMaXN0LCBJbmplY3QsXG4gICAgICAgICBPcHRpb25hbCwgVmlld0NoaWxkcmVuLCBFbGVtZW50UmVmLCBPbkluaXQsIEFmdGVyQ29udGVudENoZWNrZWQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IERPQ1VNRU5UIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IERvbVNhbml0aXplciwgU2FmZVN0eWxlIH0gZnJvbSAnQGFuZ3VsYXIvcGxhdGZvcm0tYnJvd3Nlcic7XG5pbXBvcnQgeyBOR19WQUxVRV9BQ0NFU1NPUiwgQ29udHJvbFZhbHVlQWNjZXNzb3IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmltcG9ydCB7IGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eSB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9jb2VyY2lvbic7XG5pbXBvcnQgeyBFTlRFUiwgU1BBQ0UsIFVQX0FSUk9XLCBET1dOX0FSUk9XIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2tleWNvZGVzJztcblxuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgU3Vic2NyaXB0aW9uLCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBkZWJvdW5jZVRpbWUgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IFRkRGF0YVRhYmxlUm93Q29tcG9uZW50IH0gZnJvbSAnLi9kYXRhLXRhYmxlLXJvdy9kYXRhLXRhYmxlLXJvdy5jb21wb25lbnQnO1xuaW1wb3J0IHsgSVRkRGF0YVRhYmxlU29ydENoYW5nZUV2ZW50LCBUZERhdGFUYWJsZUNvbHVtbkNvbXBvbmVudCB9IGZyb20gJy4vZGF0YS10YWJsZS1jb2x1bW4vZGF0YS10YWJsZS1jb2x1bW4uY29tcG9uZW50JztcbmltcG9ydCB7IFRkRGF0YVRhYmxlVGVtcGxhdGVEaXJlY3RpdmUgfSBmcm9tICcuL2RpcmVjdGl2ZXMvZGF0YS10YWJsZS10ZW1wbGF0ZS5kaXJlY3RpdmUnO1xuXG5pbXBvcnQgeyBJQ29udHJvbFZhbHVlQWNjZXNzb3IsIG1peGluQ29udHJvbFZhbHVlQWNjZXNzb3IgfSBmcm9tICdAY292YWxlbnQvY29yZS9jb21tb24nO1xuXG5leHBvcnQgZW51bSBUZERhdGFUYWJsZVNvcnRpbmdPcmRlciB7XG4gIEFzY2VuZGluZyA9ICdBU0MnLFxuICBEZXNjZW5kaW5nID0gJ0RFU0MnLFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIElUZERhdGFUYWJsZUNvbHVtbldpZHRoIHtcbiAgbWluPzogbnVtYmVyO1xuICBtYXg/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSVRkRGF0YVRhYmxlQ29sdW1uIHtcbiAgbmFtZTogc3RyaW5nO1xuICBsYWJlbDogc3RyaW5nO1xuICB0b29sdGlwPzogc3RyaW5nO1xuICBudW1lcmljPzogYm9vbGVhbjtcbiAgZm9ybWF0PzogKHZhbHVlOiBhbnkpID0+IGFueTtcbiAgbmVzdGVkPzogYm9vbGVhbjtcbiAgc29ydGFibGU/OiBib29sZWFuO1xuICBoaWRkZW4/OiBib29sZWFuO1xuICBmaWx0ZXI/OiBib29sZWFuO1xuICB3aWR0aD86IElUZERhdGFUYWJsZUNvbHVtbldpZHRoIHwgbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIElUZERhdGFUYWJsZVNlbGVjdEV2ZW50IHtcbiAgcm93OiBhbnk7XG4gIHNlbGVjdGVkOiBib29sZWFuO1xuICBpbmRleDogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIElUZERhdGFUYWJsZVNlbGVjdEFsbEV2ZW50IHtcbiAgcm93czogYW55W107XG4gIHNlbGVjdGVkOiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIElUZERhdGFUYWJsZVJvd0NsaWNrRXZlbnQge1xuICByb3c6IGFueTtcbiAgaW5kZXg6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJSW50ZXJuYWxDb2x1bW5XaWR0aCB7XG4gIHZhbHVlOiBudW1iZXI7XG4gIGxpbWl0OiBib29sZWFuO1xuICBpbmRleDogbnVtYmVyO1xuICBtaW4/OiBib29sZWFuO1xuICBtYXg/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIENvbnN0YW50IHRvIHNldCB0aGUgcm93cyBvZmZzZXQgYmVmb3JlIGFuZCBhZnRlciB0aGUgdmlld3BvcnRcbiAqL1xuY29uc3QgVERfVklSVFVBTF9PRkZTRVQ6IG51bWJlciA9IDI7XG5cbi8qKlxuICogQ29uc3RhbnQgdG8gc2V0IGRlZmF1bHQgcm93IGhlaWdodCBpZiBub25lIGlzIHByb3ZpZGVkXG4gKi9cbmNvbnN0IFREX1ZJUlRVQUxfREVGQVVMVF9ST1dfSEVJR0hUOiBudW1iZXIgPSA0ODtcblxuZXhwb3J0IGNsYXNzIFRkRGF0YVRhYmxlQmFzZSB7XG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBfY2hhbmdlRGV0ZWN0b3JSZWY6IENoYW5nZURldGVjdG9yUmVmKSB7fVxufVxuXG4vKiB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgKi9cbmV4cG9ydCBjb25zdCBfVGREYXRhVGFibGVNaXhpbkJhc2UgPSBtaXhpbkNvbnRyb2xWYWx1ZUFjY2Vzc29yKFRkRGF0YVRhYmxlQmFzZSwgW10pO1xuXG5AQ29tcG9uZW50KHtcbiAgcHJvdmlkZXJzOiBbe1xuICAgIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxuICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IFRkRGF0YVRhYmxlQ29tcG9uZW50KSxcbiAgICBtdWx0aTogdHJ1ZSxcbiAgfV0sXG4gIHNlbGVjdG9yOiAndGQtZGF0YS10YWJsZScsXG4gIHN0eWxlVXJsczogWycuL2RhdGEtdGFibGUuY29tcG9uZW50LnNjc3MnIF0sXG4gIHRlbXBsYXRlVXJsOiAnLi9kYXRhLXRhYmxlLmNvbXBvbmVudC5odG1sJyxcbiAgaW5wdXRzOiBbJ3ZhbHVlJ10sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBUZERhdGFUYWJsZUNvbXBvbmVudCBleHRlbmRzIF9UZERhdGFUYWJsZU1peGluQmFzZSBpbXBsZW1lbnRzIElDb250cm9sVmFsdWVBY2Nlc3NvciwgT25Jbml0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQWZ0ZXJDb250ZW50SW5pdCwgQWZ0ZXJDb250ZW50Q2hlY2tlZCwgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcblxuICAvKiogcmVzcG9uc2l2ZSB3aWR0aCBjYWxjdWxhdGlvbnMgKi9cbiAgcHJpdmF0ZSBfcmVzaXplU3ViczogU3Vic2NyaXB0aW9uO1xuICBwcml2YXRlIF9yb3dzQ2hhbmdlZFN1YnM6IFN1YnNjcmlwdGlvbjtcbiAgcHJpdmF0ZSBfaG9zdFdpZHRoOiBudW1iZXIgPSAwO1xuXG4gIC8qKiBtYW51YWxseSByZXNpemFibGUgY29sdW1ucyAqL1xuICBwcml2YXRlIF9yZXNpemFibGVDb2x1bW5zOiBib29sZWFuID0gZmFsc2U7XG4gIHByaXZhdGUgX2NvbHVtbkNsaWVudFg6IG51bWJlciA9IDA7XG4gIHByaXZhdGUgX2NvbHVtblJlc2l6ZVN1YnM6IFN1YnNjcmlwdGlvbjtcbiAgcHJpdmF0ZSBfcmVzaXppbmdDb2x1bW46IG51bWJlcjtcbiAgcHJpdmF0ZSBfb25Db2x1bW5SZXNpemU6IFN1YmplY3Q8bnVtYmVyPiA9IG5ldyBTdWJqZWN0PG51bWJlcj4oKTtcblxuICBnZXQgcmVzaXppbmdDb2x1bW4oKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fcmVzaXppbmdDb2x1bW47XG4gIH1cblxuICBnZXQgaG9zdFdpZHRoKCk6IG51bWJlciB7XG4gICAgLy8gaWYgdGhlIGNoZWNrYm94ZXMgYXJlIHJlbmRlcmVkLCB3ZSBuZWVkIHRvIHJlbW92ZSB0aGVpciB3aWR0aFxuICAgIC8vIGZyb20gdGhlIHRvdGFsIHdpZHRoIHRvIGNhbGN1bGF0ZSBwcm9wZXJseVxuICAgIGlmICh0aGlzLnNlbGVjdGFibGUpIHtcbiAgICAgIHJldHVybiB0aGlzLl9ob3N0V2lkdGggLSA0MjtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2hvc3RXaWR0aDtcbiAgfVxuXG4gIHByaXZhdGUgX3dpZHRoczogSUludGVybmFsQ29sdW1uV2lkdGhbXSA9IFtdO1xuICBwcml2YXRlIF9vblJlc2l6ZTogU3ViamVjdDx2b2lkPiA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgLyoqIGNvbHVtbiBoZWFkZXIgcmVwb3NpdGlvbiBhbmQgdmlld3Bvb3J0ICovXG4gIHByaXZhdGUgX3ZlcnRpY2FsU2Nyb2xsU3ViczogU3Vic2NyaXB0aW9uO1xuICBwcml2YXRlIF9ob3Jpem9udGFsU2Nyb2xsU3ViczogU3Vic2NyaXB0aW9uO1xuICBwcml2YXRlIF9zY3JvbGxIb3Jpem9udGFsT2Zmc2V0OiBudW1iZXIgPSAwO1xuXG4gIHByaXZhdGUgX29uSG9yaXpvbnRhbFNjcm9sbDogU3ViamVjdDxudW1iZXI+ID0gbmV3IFN1YmplY3Q8bnVtYmVyPigpO1xuICBwcml2YXRlIF9vblZlcnRpY2FsU2Nyb2xsOiBTdWJqZWN0PG51bWJlcj4gPSBuZXcgU3ViamVjdDxudW1iZXI+KCk7XG5cbiAgLy8gQXJyYXkgb2YgY2FjaGVkIHJvdyBoZWlnaHRzIHRvIGFsbG93IGR5bmFtaWMgcm93IGhlaWdodHNcbiAgcHJpdmF0ZSBfcm93SGVpZ2h0Q2FjaGU6IG51bWJlcltdID0gW107XG4gIC8vIFRvdGFsIHBzZXVkbyBoZWlnaHQgb2YgYWxsIHRoZSBlbGVtZW50c1xuICBwcml2YXRlIF90b3RhbEhlaWdodDogbnVtYmVyID0gMDtcbiAgLy8gVG90YWwgaG9zdCBoZWlnaHQgZm9yIHRoZSB2aWV3cG9ydFxuICBwcml2YXRlIF9ob3N0SGVpZ2h0OiBudW1iZXIgPSAwO1xuICAvLyBTY3JvbGxlZCB2ZXJ0aWNhbCBwaXhlbHNcbiAgcHJpdmF0ZSBfc2Nyb2xsVmVydGljYWxPZmZzZXQ6IG51bWJlciA9IDA7XG4gIC8vIFN0eWxlIHRvIG1vdmUgdGhlIGNvbnRlbnQgYSBjZXJ0YWluIG9mZnNldCBkZXBlbmRpbmcgb24gc2Nyb2xsZWQgb2Zmc2V0XG4gIHByaXZhdGUgX29mZnNldFRyYW5zZm9ybTogU2FmZVN0eWxlO1xuXG4gIC8vIFZhcmlhYmxlcyB0aGF0IHNldCBmcm9tIGFuZCB0byB3aGljaCByb3dzIHdpbGwgYmUgcmVuZGVyZWRcbiAgcHJpdmF0ZSBfZnJvbVJvdzogbnVtYmVyID0gMDtcbiAgcHJpdmF0ZSBfdG9Sb3c6IG51bWJlciA9IDA7XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIG9mZnNldCBzdHlsZSB3aXRoIGEgcHJvcGVyIGNhbGN1bGF0aW9uIG9uIGhvdyBtdWNoIGl0IHNob3VsZCBtb3ZlXG4gICAqIG92ZXIgdGhlIHkgYXhpcyBvZiB0aGUgdG90YWwgaGVpZ2h0XG4gICAqL1xuICBnZXQgb2Zmc2V0VHJhbnNmb3JtKCk6IFNhZmVTdHlsZSB7XG4gICAgcmV0dXJuIHRoaXMuX29mZnNldFRyYW5zZm9ybTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBhc3N1bWVkIHRvdGFsIGhlaWdodCBvZiB0aGUgcm93c1xuICAgKi9cbiAgZ2V0IHRvdGFsSGVpZ2h0KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX3RvdGFsSGVpZ2h0O1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGluaXRpYWwgcm93IHRvIHJlbmRlciBpbiB0aGUgdmlld3BvcnRcbiAgICovXG4gIGdldCBmcm9tUm93KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX2Zyb21Sb3c7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgbGFzdCByb3cgdG8gcmVuZGVyIGluIHRoZSB2aWV3cG9ydFxuICAgKi9cbiAgZ2V0IHRvUm93KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX3RvUm93O1xuICB9XG5cbiAgcHJpdmF0ZSBfdmFsdWVDaGFuZ2VzU3ViczogU3Vic2NyaXB0aW9uO1xuICAvKiogaW50ZXJuYWwgYXR0cmlidXRlcyAqL1xuICBwcml2YXRlIF9kYXRhOiBhbnlbXTtcbiAgLy8gZGF0YSB2aXJ0dWFsbHkgaXRlcmF0ZWQgYnkgY29tcG9uZW50XG4gIHByaXZhdGUgX3ZpcnR1YWxEYXRhOiBhbnlbXTtcbiAgcHJpdmF0ZSBfY29sdW1uczogSVRkRGF0YVRhYmxlQ29sdW1uW107XG4gIHByaXZhdGUgX3NlbGVjdGFibGU6IGJvb2xlYW4gPSBmYWxzZTtcbiAgcHJpdmF0ZSBfY2xpY2thYmxlOiBib29sZWFuID0gZmFsc2U7XG4gIHByaXZhdGUgX211bHRpcGxlOiBib29sZWFuID0gdHJ1ZTtcbiAgcHJpdmF0ZSBfYWxsU2VsZWN0ZWQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgcHJpdmF0ZSBfaW5kZXRlcm1pbmF0ZTogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIC8qKiBzb3J0aW5nICovXG4gIHByaXZhdGUgX3NvcnRhYmxlOiBib29sZWFuID0gZmFsc2U7XG4gIHByaXZhdGUgX3NvcnRCeTogSVRkRGF0YVRhYmxlQ29sdW1uO1xuICBwcml2YXRlIF9zb3J0T3JkZXI6IFRkRGF0YVRhYmxlU29ydGluZ09yZGVyID0gVGREYXRhVGFibGVTb3J0aW5nT3JkZXIuQXNjZW5kaW5nO1xuXG4gIC8qKiBzaGlmdCBzZWxlY3QgKi9cbiAgcHJpdmF0ZSBfc2hpZnRQcmV2aW91c2x5UHJlc3NlZDogYm9vbGVhbiA9IGZhbHNlO1xuICBwcml2YXRlIF9sYXN0U2VsZWN0ZWRJbmRleDogbnVtYmVyID0gLTE7XG4gIHByaXZhdGUgX2ZpcnN0U2VsZWN0ZWRJbmRleDogbnVtYmVyID0gLTE7XG4gIHByaXZhdGUgX2ZpcnN0Q2hlY2tib3hWYWx1ZTogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIC8qKiB0ZW1wbGF0ZSBmZXRjaGluZyBzdXBwb3J0ICovXG4gIHByaXZhdGUgX3RlbXBsYXRlTWFwOiBNYXA8c3RyaW5nLCBUZW1wbGF0ZVJlZjxhbnk+PiA9IG5ldyBNYXA8c3RyaW5nLCBUZW1wbGF0ZVJlZjxhbnk+PigpO1xuICBAQ29udGVudENoaWxkcmVuKFRkRGF0YVRhYmxlVGVtcGxhdGVEaXJlY3RpdmUpIF90ZW1wbGF0ZXM6IFF1ZXJ5TGlzdDxUZERhdGFUYWJsZVRlbXBsYXRlRGlyZWN0aXZlPjtcblxuICBAVmlld0NoaWxkKCdzY3JvbGxhYmxlRGl2JykgX3Njcm9sbGFibGVEaXY6IEVsZW1lbnRSZWY7XG5cbiAgQFZpZXdDaGlsZHJlbignY29sdW1uRWxlbWVudCcpIF9jb2xFbGVtZW50czogUXVlcnlMaXN0PFRkRGF0YVRhYmxlQ29sdW1uQ29tcG9uZW50PjtcblxuICBAVmlld0NoaWxkcmVuKFRkRGF0YVRhYmxlUm93Q29tcG9uZW50KSBfcm93czogUXVlcnlMaXN0PFRkRGF0YVRhYmxlUm93Q29tcG9uZW50PjtcblxuICAvKipcbiAgICogUmV0dXJucyBzY3JvbGwgcG9zaXRpb24gdG8gcmVwb3NpdGlvbiBjb2x1bW4gaGVhZGVyc1xuICAgKi9cbiAgZ2V0IGNvbHVtbnNMZWZ0U2Nyb2xsKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX3Njcm9sbEhvcml6b250YWxPZmZzZXQgKiAtMTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRydWUgaWYgYWxsIHZhbHVlcyBhcmUgc2VsZWN0ZWQuXG4gICAqL1xuICBnZXQgYWxsU2VsZWN0ZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX2FsbFNlbGVjdGVkO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiBhbGwgdmFsdWVzIGFyZSBub3QgZGVzZWxlY3RlZFxuICAgKiBhbmQgYXQgbGVhc3Qgb25lIGlzLlxuICAgKi9cbiAgZ2V0IGluZGV0ZXJtaW5hdGUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX2luZGV0ZXJtaW5hdGU7XG4gIH1cblxuICAvKipcbiAgICogZGF0YT86IHtba2V5OiBzdHJpbmddOiBhbnl9W11cbiAgICogU2V0cyB0aGUgZGF0YSB0byBiZSByZW5kZXJlZCBhcyByb3dzLlxuICAgKi9cbiAgQElucHV0KCdkYXRhJylcbiAgc2V0IGRhdGEoZGF0YTogYW55W10pIHtcbiAgICB0aGlzLl9kYXRhID0gZGF0YTtcbiAgICB0aGlzLl9yb3dIZWlnaHRDYWNoZSA9IFtdO1xuICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgdGhpcy5yZWZyZXNoKCk7XG4gICAgICAvLyBzY3JvbGwgYmFjayB0byB0aGUgdG9wIGlmIHRoZSBkYXRhIGhhcyBjaGFuZ2VkXG4gICAgICB0aGlzLl9zY3JvbGxhYmxlRGl2Lm5hdGl2ZUVsZW1lbnQuc2Nyb2xsVG9wID0gMDtcbiAgICB9KTtcbiAgfVxuICBnZXQgZGF0YSgpOiBhbnlbXSB7XG4gICAgcmV0dXJuIHRoaXMuX2RhdGE7XG4gIH1cblxuICBnZXQgdmlydHVhbERhdGEoKTogYW55W10ge1xuICAgIHJldHVybiB0aGlzLl92aXJ0dWFsRGF0YTtcbiAgfVxuXG4gIC8qKlxuICAgKiBjb2x1bW5zPzogSVRkRGF0YVRhYmxlQ29sdW1uW11cbiAgICogU2V0cyBhZGRpdGlvbmFsIGNvbHVtbiBjb25maWd1cmF0aW9uLiBbSVRkRGF0YVRhYmxlQ29sdW1uLm5hbWVdIGhhcyB0byBleGlzdCBpbiBbZGF0YV0gYXMga2V5LlxuICAgKiBEZWZhdWx0cyB0byBbZGF0YV0ga2V5cy5cbiAgICovXG4gIEBJbnB1dCgnY29sdW1ucycpXG4gIHNldCBjb2x1bW5zKGNvbHM6IElUZERhdGFUYWJsZUNvbHVtbltdKSB7XG4gICAgdGhpcy5fY29sdW1ucyA9IGNvbHM7XG4gIH1cbiAgZ2V0IGNvbHVtbnMoKTogSVRkRGF0YVRhYmxlQ29sdW1uW10ge1xuICAgIGlmICh0aGlzLl9jb2x1bW5zKSB7XG4gICAgICByZXR1cm4gdGhpcy5fY29sdW1ucztcbiAgICB9XG5cbiAgICBpZiAodGhpcy5oYXNEYXRhKSB7XG4gICAgICB0aGlzLl9jb2x1bW5zID0gW107XG4gICAgICAvLyBpZiBjb2x1bW5zIGlzIHVuZGVmaW5lZCwgdXNlIGtleSBpbiBbZGF0YV0gcm93cyBhcyBuYW1lIGFuZCBsYWJlbCBmb3IgY29sdW1uIGhlYWRlcnMuXG4gICAgICBsZXQgcm93OiBhbnkgPSB0aGlzLl9kYXRhWzBdO1xuICAgICAgT2JqZWN0LmtleXMocm93KS5mb3JFYWNoKChrOiBzdHJpbmcpID0+IHtcbiAgICAgICAgaWYgKCF0aGlzLl9jb2x1bW5zLmZpbmQoKGM6IGFueSkgPT4gYy5uYW1lID09PSBrKSkge1xuICAgICAgICAgIHRoaXMuX2NvbHVtbnMucHVzaCh7IG5hbWU6IGssIGxhYmVsOiBrIH0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHJldHVybiB0aGlzLl9jb2x1bW5zO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIHJlc2l6YWJsZUNvbHVtbnM/OiBib29sZWFuXG4gICAqIEVuYWJsZXMgbWFudWFsIGNvbHVtbiByZXNpemUuXG4gICAqIERlZmF1bHRzIHRvICdmYWxzZSdcbiAgICovXG4gIEBJbnB1dCgncmVzaXphYmxlQ29sdW1ucycpXG4gIHNldCByZXNpemFibGVDb2x1bW5zKHJlc2l6YWJsZUNvbHVtbnM6IGJvb2xlYW4pIHtcbiAgICB0aGlzLl9yZXNpemFibGVDb2x1bW5zID0gY29lcmNlQm9vbGVhblByb3BlcnR5KHJlc2l6YWJsZUNvbHVtbnMpO1xuICB9XG4gIGdldCByZXNpemFibGVDb2x1bW5zKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9yZXNpemFibGVDb2x1bW5zO1xuICB9XG5cbiAgLyoqXG4gICAqIHNlbGVjdGFibGU/OiBib29sZWFuXG4gICAqIEVuYWJsZXMgcm93IHNlbGVjdGlvbiBldmVudHMsIGhvdmVyIGFuZCBzZWxlY3RlZCByb3cgc3RhdGVzLlxuICAgKiBEZWZhdWx0cyB0byAnZmFsc2UnXG4gICAqL1xuICBASW5wdXQoJ3NlbGVjdGFibGUnKVxuICBzZXQgc2VsZWN0YWJsZShzZWxlY3RhYmxlOiBib29sZWFuKSB7XG4gICAgdGhpcy5fc2VsZWN0YWJsZSA9IGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eShzZWxlY3RhYmxlKTtcbiAgfVxuICBnZXQgc2VsZWN0YWJsZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fc2VsZWN0YWJsZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBjbGlja2FibGU/OiBib29sZWFuXG4gICAqIEVuYWJsZXMgcm93IGNsaWNrIGV2ZW50cywgaG92ZXIuXG4gICAqIERlZmF1bHRzIHRvICdmYWxzZSdcbiAgICovXG4gIEBJbnB1dCgnY2xpY2thYmxlJylcbiAgc2V0IGNsaWNrYWJsZShjbGlja2FibGU6IGJvb2xlYW4pIHtcbiAgICB0aGlzLl9jbGlja2FibGUgPSBjb2VyY2VCb29sZWFuUHJvcGVydHkoY2xpY2thYmxlKTtcbiAgfVxuICBnZXQgY2xpY2thYmxlKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9jbGlja2FibGU7XG4gIH1cblxuICAvKipcbiAgICogbXVsdGlwbGU/OiBib29sZWFuXG4gICAqIEVuYWJsZXMgbXVsdGlwbGUgcm93IHNlbGVjdGlvbi4gW3NlbGVjdGFibGVdIG5lZWRzIHRvIGJlIGVuYWJsZWQuXG4gICAqIERlZmF1bHRzIHRvICdmYWxzZSdcbiAgICovXG4gIEBJbnB1dCgnbXVsdGlwbGUnKVxuICBzZXQgbXVsdGlwbGUobXVsdGlwbGU6IGJvb2xlYW4pIHtcbiAgICB0aGlzLl9tdWx0aXBsZSA9IGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eShtdWx0aXBsZSk7XG4gIH1cbiAgZ2V0IG11bHRpcGxlKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9tdWx0aXBsZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBzb3J0YWJsZT86IGJvb2xlYW5cbiAgICogRW5hYmxlcyBzb3J0aW5nIGV2ZW50cywgc29ydCBpY29ucyBhbmQgYWN0aXZlIGNvbHVtbiBzdGF0ZXMuXG4gICAqIERlZmF1bHRzIHRvICdmYWxzZSdcbiAgICovXG4gIEBJbnB1dCgnc29ydGFibGUnKVxuICBzZXQgc29ydGFibGUoc29ydGFibGU6IGJvb2xlYW4pIHtcbiAgICB0aGlzLl9zb3J0YWJsZSA9IGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eShzb3J0YWJsZSk7XG4gIH1cbiAgZ2V0IHNvcnRhYmxlKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9zb3J0YWJsZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBzb3J0Qnk/OiBzdHJpbmdcbiAgICogU2V0cyB0aGUgYWN0aXZlIHNvcnQgY29sdW1uLiBbc29ydGFibGVdIG5lZWRzIHRvIGJlIGVuYWJsZWQuXG4gICAqL1xuICBASW5wdXQoJ3NvcnRCeScpXG4gIHNldCBzb3J0QnkoY29sdW1uTmFtZTogc3RyaW5nKSB7XG4gICAgaWYgKCFjb2x1bW5OYW1lKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGNvbHVtbjogSVRkRGF0YVRhYmxlQ29sdW1uID0gdGhpcy5jb2x1bW5zLmZpbmQoKGM6IGFueSkgPT4gYy5uYW1lID09PSBjb2x1bW5OYW1lKTtcbiAgICBpZiAoIWNvbHVtbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdbc29ydEJ5XSBtdXN0IGJlIGEgdmFsaWQgY29sdW1uIG5hbWUnKTtcbiAgICB9XG5cbiAgICB0aGlzLl9zb3J0QnkgPSBjb2x1bW47XG4gIH1cbiAgZ2V0IHNvcnRCeUNvbHVtbigpOiBJVGREYXRhVGFibGVDb2x1bW4ge1xuICAgIHJldHVybiB0aGlzLl9zb3J0Qnk7XG4gIH1cblxuICAvKipcbiAgICogc29ydE9yZGVyPzogWydBU0MnIHwgJ0RFU0MnXSBvciBUZERhdGFUYWJsZVNvcnRpbmdPcmRlclxuICAgKiBTZXRzIHRoZSBzb3J0IG9yZGVyIG9mIHRoZSBbc29ydEJ5XSBjb2x1bW4uIFtzb3J0YWJsZV0gbmVlZHMgdG8gYmUgZW5hYmxlZC5cbiAgICogRGVmYXVsdHMgdG8gJ0FTQycgb3IgVGREYXRhVGFibGVTb3J0aW5nT3JkZXIuQXNjZW5kaW5nXG4gICAqL1xuICBASW5wdXQoJ3NvcnRPcmRlcicpXG4gIHNldCBzb3J0T3JkZXIob3JkZXI6ICdBU0MnIHwgJ0RFU0MnKSB7XG4gICAgbGV0IHNvcnRPcmRlcjogc3RyaW5nID0gb3JkZXIgPyBvcmRlci50b1VwcGVyQ2FzZSgpIDogJ0FTQyc7XG4gICAgaWYgKHNvcnRPcmRlciAhPT0gJ0RFU0MnICYmIHNvcnRPcmRlciAhPT0gJ0FTQycpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignW3NvcnRPcmRlcl0gbXVzdCBiZSBlbXB0eSwgQVNDIG9yIERFU0MnKTtcbiAgICB9XG5cbiAgICB0aGlzLl9zb3J0T3JkZXIgPSBzb3J0T3JkZXIgPT09ICdBU0MnID9cbiAgICAgIFRkRGF0YVRhYmxlU29ydGluZ09yZGVyLkFzY2VuZGluZyA6IFRkRGF0YVRhYmxlU29ydGluZ09yZGVyLkRlc2NlbmRpbmc7XG4gIH1cbiAgZ2V0IHNvcnRPcmRlckVudW0oKTogVGREYXRhVGFibGVTb3J0aW5nT3JkZXIge1xuICAgIHJldHVybiB0aGlzLl9zb3J0T3JkZXI7XG4gIH1cblxuICBnZXQgaGFzRGF0YSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fZGF0YSAmJiB0aGlzLl9kYXRhLmxlbmd0aCA+IDA7XG4gIH1cblxuICAvKipcbiAgICogc29ydENoYW5nZT86IGZ1bmN0aW9uXG4gICAqIEV2ZW50IGVtaXR0ZWQgd2hlbiB0aGUgY29sdW1uIGhlYWRlcnMgYXJlIGNsaWNrZWQuIFtzb3J0YWJsZV0gbmVlZHMgdG8gYmUgZW5hYmxlZC5cbiAgICogRW1pdHMgYW4gW0lUZERhdGFUYWJsZVNvcnRDaGFuZ2VFdmVudF0gaW1wbGVtZW50ZWQgb2JqZWN0LlxuICAgKi9cbiAgQE91dHB1dCgnc29ydENoYW5nZScpIG9uU29ydENoYW5nZTogRXZlbnRFbWl0dGVyPElUZERhdGFUYWJsZVNvcnRDaGFuZ2VFdmVudD4gPVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcgRXZlbnRFbWl0dGVyPElUZERhdGFUYWJsZVNvcnRDaGFuZ2VFdmVudD4oKTtcblxuICAvKipcbiAgICogcm93U2VsZWN0PzogZnVuY3Rpb25cbiAgICogRXZlbnQgZW1pdHRlZCB3aGVuIGEgcm93IGlzIHNlbGVjdGVkL2Rlc2VsZWN0ZWQuIFtzZWxlY3RhYmxlXSBuZWVkcyB0byBiZSBlbmFibGVkLlxuICAgKiBFbWl0cyBhbiBbSVRkRGF0YVRhYmxlU2VsZWN0RXZlbnRdIGltcGxlbWVudGVkIG9iamVjdC5cbiAgICovXG4gIEBPdXRwdXQoJ3Jvd1NlbGVjdCcpIG9uUm93U2VsZWN0OiBFdmVudEVtaXR0ZXI8SVRkRGF0YVRhYmxlU2VsZWN0RXZlbnQ+ID0gbmV3IEV2ZW50RW1pdHRlcjxJVGREYXRhVGFibGVTZWxlY3RFdmVudD4oKTtcblxuICAvKipcbiAgICogcm93Q2xpY2s/OiBmdW5jdGlvblxuICAgKiBFdmVudCBlbWl0dGVkIHdoZW4gYSByb3cgaXMgY2xpY2tlZC5cbiAgICogRW1pdHMgYW4gW0lUZERhdGFUYWJsZVJvd0NsaWNrRXZlbnRdIGltcGxlbWVudGVkIG9iamVjdC5cbiAgICovXG4gIEBPdXRwdXQoJ3Jvd0NsaWNrJykgb25Sb3dDbGljazogRXZlbnRFbWl0dGVyPElUZERhdGFUYWJsZVJvd0NsaWNrRXZlbnQ+ID0gbmV3IEV2ZW50RW1pdHRlcjxJVGREYXRhVGFibGVSb3dDbGlja0V2ZW50PigpO1xuXG4gIC8qKlxuICAgKiBzZWxlY3RBbGw/OiBmdW5jdGlvblxuICAgKiBFdmVudCBlbWl0dGVkIHdoZW4gYWxsIHJvd3MgYXJlIHNlbGVjdGVkL2Rlc2VsZWN0ZWQgYnkgdGhlIGFsbCBjaGVja2JveC4gW3NlbGVjdGFibGVdIG5lZWRzIHRvIGJlIGVuYWJsZWQuXG4gICAqIEVtaXRzIGFuIFtJVGREYXRhVGFibGVTZWxlY3RBbGxFdmVudF0gaW1wbGVtZW50ZWQgb2JqZWN0LlxuICAgKi9cbiAgQE91dHB1dCgnc2VsZWN0QWxsJykgb25TZWxlY3RBbGw6IEV2ZW50RW1pdHRlcjxJVGREYXRhVGFibGVTZWxlY3RBbGxFdmVudD4gPVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3IEV2ZW50RW1pdHRlcjxJVGREYXRhVGFibGVTZWxlY3RBbGxFdmVudD4oKTtcblxuICBjb25zdHJ1Y3RvcihAT3B0aW9uYWwoKSBASW5qZWN0KERPQ1VNRU5UKSBwcml2YXRlIF9kb2N1bWVudDogYW55LFxuICAgICAgICAgICAgICBwcml2YXRlIF9lbGVtZW50UmVmOiBFbGVtZW50UmVmLFxuICAgICAgICAgICAgICBwcml2YXRlIF9kb21TYW5pdGl6ZXI6IERvbVNhbml0aXplcixcbiAgICAgICAgICAgICAgX2NoYW5nZURldGVjdG9yUmVmOiBDaGFuZ2VEZXRlY3RvclJlZikge1xuICAgIHN1cGVyKF9jaGFuZ2VEZXRlY3RvclJlZik7XG4gIH1cblxuICAvKipcbiAgICogY29tcGFyZVdpdGg/OiBmdW5jdGlvbihyb3csIG1vZGVsKTogYm9vbGVhblxuICAgKiBBbGxvd3MgY3VzdG9tIGNvbXBhcmlzb24gYmV0d2VlbiByb3cgYW5kIG1vZGVsIHRvIHNlZSBpZiByb3cgaXMgc2VsZWN0ZWQgb3Igbm90XG4gICAqIERlZmF1bHQgY29tcGFyYXRpb24gaXMgYnkgcmVmZXJlbmNlXG4gICAqL1xuICBASW5wdXQoJ2NvbXBhcmVXaXRoJykgY29tcGFyZVdpdGg6IChyb3c6IGFueSwgbW9kZWw6IGFueSkgPT4gYm9vbGVhbiA9IChyb3c6IGFueSwgbW9kZWw6IGFueSkgPT4ge1xuICAgIHJldHVybiByb3cgPT09IG1vZGVsO1xuICB9XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemUgb2JzZXJ2YWJsZSBmb3IgcmVzaXplIGFuZCBzY3JvbGwgZXZlbnRzXG4gICAqL1xuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAvLyBpbml0aWFsaXplIG9ic2VydmFibGUgZm9yIHJlc2l6ZSBjYWxjdWxhdGlvbnNcbiAgICB0aGlzLl9yZXNpemVTdWJzID0gdGhpcy5fb25SZXNpemUuYXNPYnNlcnZhYmxlKCkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgIGlmICh0aGlzLl9yb3dzKSB7XG4gICAgICAgIHRoaXMuX3Jvd3MudG9BcnJheSgpLmZvckVhY2goKHJvdzogVGREYXRhVGFibGVSb3dDb21wb25lbnQsIGluZGV4OiBudW1iZXIpID0+IHtcbiAgICAgICAgICB0aGlzLl9yb3dIZWlnaHRDYWNoZVt0aGlzLmZyb21Sb3cgKyBpbmRleF0gPSByb3cuaGVpZ2h0ICsgMTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICB0aGlzLl9jYWxjdWxhdGVXaWR0aHMoKTtcbiAgICAgIHRoaXMuX2NhbGN1bGF0ZVZpcnR1YWxSb3dzKCk7XG4gICAgfSk7XG5cbiAgICAvLyBpbml0aWFsaXplIG9ic2VydmFibGUgZm9yIGNvbHVtbiByZXNpemUgY2FsY3VsYXRpb25zXG4gICAgdGhpcy5fY29sdW1uUmVzaXplU3VicyA9IHRoaXMuX29uQ29sdW1uUmVzaXplLmFzT2JzZXJ2YWJsZSgpLnBpcGUoXG4gICAgICBkZWJvdW5jZVRpbWUoMCksXG4gICAgKS5zdWJzY3JpYmUoKGNsaWVudFg6IG51bWJlcikgPT4ge1xuICAgICAgdGhpcy5fY29sdW1uQ2xpZW50WCA9IGNsaWVudFg7XG4gICAgICB0aGlzLl9jYWxjdWxhdGVXaWR0aHMoKTtcbiAgICAgIHRoaXMuX2NoYW5nZURldGVjdG9yUmVmLm1hcmtGb3JDaGVjaygpO1xuICAgIH0pO1xuICAgIC8vIGluaXRpYWxpemUgb2JzZXJ2YWJsZSBmb3Igc2Nyb2xsIGNvbHVtbiBoZWFkZXIgcmVwb3NpdGlvblxuICAgIHRoaXMuX2hvcml6b250YWxTY3JvbGxTdWJzID0gdGhpcy5fb25Ib3Jpem9udGFsU2Nyb2xsLmFzT2JzZXJ2YWJsZSgpXG4gICAgICAuc3Vic2NyaWJlKChob3Jpem9udGFsU2Nyb2xsOiBudW1iZXIpID0+IHtcbiAgICAgIHRoaXMuX3Njcm9sbEhvcml6b250YWxPZmZzZXQgPSBob3Jpem9udGFsU2Nyb2xsO1xuICAgICAgdGhpcy5fY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XG4gICAgfSk7XG4gICAgLy8gaW5pdGlhbGl6ZSBvYnNlcnZhYmxlIGZvciB2aXJ0dWFsIHNjcm9sbCByZW5kZXJpbmdcbiAgICB0aGlzLl92ZXJ0aWNhbFNjcm9sbFN1YnMgPSB0aGlzLl9vblZlcnRpY2FsU2Nyb2xsLmFzT2JzZXJ2YWJsZSgpXG4gICAgICAuc3Vic2NyaWJlKCh2ZXJ0aWNhbFNjcm9sbDogbnVtYmVyKSA9PiB7XG4gICAgICB0aGlzLl9zY3JvbGxWZXJ0aWNhbE9mZnNldCA9IHZlcnRpY2FsU2Nyb2xsO1xuICAgICAgdGhpcy5fY2FsY3VsYXRlVmlydHVhbFJvd3MoKTtcbiAgICAgIHRoaXMuX2NoYW5nZURldGVjdG9yUmVmLm1hcmtGb3JDaGVjaygpO1xuICAgIH0pO1xuICAgIHRoaXMuX3ZhbHVlQ2hhbmdlc1N1YnMgPSB0aGlzLnZhbHVlQ2hhbmdlcy5zdWJzY3JpYmUoKHZhbHVlOiBhbnkpID0+IHtcbiAgICAgIHRoaXMucmVmcmVzaCgpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIExvYWRzIHRlbXBsYXRlcyBhbmQgc2V0cyB0aGVtIGluIGEgbWFwIGZvciBmYXN0ZXIgYWNjZXNzLlxuICAgKi9cbiAgbmdBZnRlckNvbnRlbnRJbml0KCk6IHZvaWQge1xuICAgIGZvciAobGV0IGk6IG51bWJlciA9IDA7IGkgPCB0aGlzLl90ZW1wbGF0ZXMudG9BcnJheSgpLmxlbmd0aDsgaSsrKSB7XG4gICAgICB0aGlzLl90ZW1wbGF0ZU1hcC5zZXQoXG4gICAgICAgIHRoaXMuX3RlbXBsYXRlcy50b0FycmF5KClbaV0udGREYXRhVGFibGVUZW1wbGF0ZSxcbiAgICAgICAgdGhpcy5fdGVtcGxhdGVzLnRvQXJyYXkoKVtpXS50ZW1wbGF0ZVJlZixcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBob3N0cyBuYXRpdmUgZWxlbWVudHMgd2lkdGhzIHRvIHNlZSBpZiBpdCBoYXMgY2hhbmdlZCAocmVzaXplIGNoZWNrKVxuICAgKi9cbiAgbmdBZnRlckNvbnRlbnRDaGVja2VkKCk6IHZvaWQge1xuICAgIC8vIGNoZWNrIGlmIHRoZSBzY3JvbGwgaGFzIGJlZW4gcmVzZXQgd2hlbiBlbGVtZW50IGlzIGhpZGRlblxuICAgIGlmICh0aGlzLl9zY3JvbGxWZXJ0aWNhbE9mZnNldCAtIHRoaXMuX3Njcm9sbGFibGVEaXYubmF0aXZlRWxlbWVudC5zY3JvbGxUb3AgPiA1KSB7XG4gICAgICAvLyBzY3JvbGwgYmFjayB0byB0aGUgdG9wIGlmIGVsZW1lbnQgaGFzIGJlZW4gcmVzZXRcbiAgICAgIHRoaXMuX29uVmVydGljYWxTY3JvbGwubmV4dCgwKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCkge1xuICAgICAgbGV0IG5ld0hvc3RXaWR0aDogbnVtYmVyID0gdGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoO1xuICAgICAgLy8gaWYgdGhlIHdpZHRoIGhhcyBjaGFuZ2VkIHRoZW4gd2UgdGhyb3cgYSByZXNpemUgZXZlbnQuXG4gICAgICBpZiAodGhpcy5faG9zdFdpZHRoICE9PSBuZXdIb3N0V2lkdGgpIHtcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgdGhpcy5faG9zdFdpZHRoID0gbmV3SG9zdFdpZHRoO1xuICAgICAgICAgIHRoaXMuX29uUmVzaXplLm5leHQoKTtcbiAgICAgICAgfSwgMCk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmICh0aGlzLl9zY3JvbGxhYmxlRGl2Lm5hdGl2ZUVsZW1lbnQpIHtcbiAgICAgIGxldCBuZXdIb3N0SGVpZ2h0OiBudW1iZXIgPSB0aGlzLl9zY3JvbGxhYmxlRGl2Lm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0O1xuICAgICAgLy8gaWYgdGhlIGhlaWdodCBvZiB0aGUgdmlld3BvcnQgaGFzIGNoYW5nZWQsIHRoZW4gd2UgbWFyayBmb3IgY2hlY2tcbiAgICAgIGlmICh0aGlzLl9ob3N0SGVpZ2h0ICE9PSBuZXdIb3N0SGVpZ2h0KSB7XG4gICAgICAgIHRoaXMuX2hvc3RIZWlnaHQgPSBuZXdIb3N0SGVpZ2h0O1xuICAgICAgICB0aGlzLl9jYWxjdWxhdGVWaXJ0dWFsUm93cygpO1xuICAgICAgICB0aGlzLl9jaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVnaXN0ZXJzIHRvIGFuIG9ic2VydmFibGUgdGhhdCBjaGVja3MgaWYgYWxsIHJvd3MgaGF2ZSBiZWVuIHJlbmRlcmVkXG4gICAqIHNvIHdlIGNhbiBzdGFydCBjYWxjdWxhdGluZyB0aGUgd2lkdGhzXG4gICAqL1xuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgdGhpcy5fcm93c0NoYW5nZWRTdWJzID0gdGhpcy5fcm93cy5jaGFuZ2VzLnBpcGUoXG4gICAgICBkZWJvdW5jZVRpbWUoMCksXG4gICAgKS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgdGhpcy5fb25SZXNpemUubmV4dCgpO1xuICAgIH0pO1xuICAgIHRoaXMuX2NhbGN1bGF0ZVZpcnR1YWxSb3dzKCk7XG4gIH1cblxuICAvKipcbiAgICogVW5zdWJzY3JpYmVzIG9ic2VydmFibGVzIHdoZW4gZGF0YSB0YWJsZSBpcyBkZXN0cm95ZWRcbiAgICovXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLl9yZXNpemVTdWJzKSB7XG4gICAgICB0aGlzLl9yZXNpemVTdWJzLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9jb2x1bW5SZXNpemVTdWJzKSB7XG4gICAgICB0aGlzLl9jb2x1bW5SZXNpemVTdWJzLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9ob3Jpem9udGFsU2Nyb2xsU3Vicykge1xuICAgICAgdGhpcy5faG9yaXpvbnRhbFNjcm9sbFN1YnMudW5zdWJzY3JpYmUoKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuX3ZlcnRpY2FsU2Nyb2xsU3Vicykge1xuICAgICAgdGhpcy5fdmVydGljYWxTY3JvbGxTdWJzLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9yb3dzQ2hhbmdlZFN1YnMpIHtcbiAgICAgIHRoaXMuX3Jvd3NDaGFuZ2VkU3Vicy51bnN1YnNjcmliZSgpO1xuICAgIH1cbiAgICBpZiAodGhpcy5fdmFsdWVDaGFuZ2VzU3Vicykge1xuICAgICAgdGhpcy5fdmFsdWVDaGFuZ2VzU3Vicy51bnN1YnNjcmliZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgdGhhdCBnZXRzIGV4ZWN1dGVkIGV2ZXJ5IHRpbWUgdGhlcmUgaXMgYSBzY3JvbGwgZXZlbnRcbiAgICogQ2FsbHMgdGhlIHNjcm9sbCBvYnNlcnZhYmxlXG4gICAqL1xuICBoYW5kbGVTY3JvbGwoZXZlbnQ6IEV2ZW50KTogdm9pZCB7XG4gICAgbGV0IGVsZW1lbnQ6IEhUTUxFbGVtZW50ID0gKDxIVE1MRWxlbWVudD5ldmVudC50YXJnZXQpO1xuICAgIGlmIChlbGVtZW50KSB7XG4gICAgICBsZXQgaG9yaXpvbnRhbFNjcm9sbDogbnVtYmVyID0gZWxlbWVudC5zY3JvbGxMZWZ0O1xuICAgICAgaWYgKHRoaXMuX3Njcm9sbEhvcml6b250YWxPZmZzZXQgIT09IGhvcml6b250YWxTY3JvbGwpIHtcbiAgICAgICAgdGhpcy5fb25Ib3Jpem9udGFsU2Nyb2xsLm5leHQoaG9yaXpvbnRhbFNjcm9sbCk7XG4gICAgICB9XG4gICAgICBsZXQgdmVydGljYWxTY3JvbGw6IG51bWJlciA9IGVsZW1lbnQuc2Nyb2xsVG9wO1xuICAgICAgaWYgKHRoaXMuX3Njcm9sbFZlcnRpY2FsT2Zmc2V0ICE9PSB2ZXJ0aWNhbFNjcm9sbCkge1xuICAgICAgICB0aGlzLl9vblZlcnRpY2FsU2Nyb2xsLm5leHQodmVydGljYWxTY3JvbGwpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSB3aWR0aCBuZWVkZWQgZm9yIHRoZSBjb2x1bW5zIHZpYSBpbmRleFxuICAgKi9cbiAgZ2V0Q29sdW1uV2lkdGgoaW5kZXg6IG51bWJlcik6IG51bWJlciB7XG4gICAgaWYgKHRoaXMuX3dpZHRoc1tpbmRleF0pIHtcbiAgICAgIHJldHVybiB0aGlzLl93aWR0aHNbaW5kZXhdLnZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgZ2V0Q2VsbFZhbHVlKGNvbHVtbjogSVRkRGF0YVRhYmxlQ29sdW1uLCB2YWx1ZTogYW55KTogc3RyaW5nIHtcbiAgICBpZiAoY29sdW1uLm5lc3RlZCA9PT0gdW5kZWZpbmVkIHx8IGNvbHVtbi5uZXN0ZWQpIHtcbiAgICAgIHJldHVybiB0aGlzLl9nZXROZXN0ZWRWYWx1ZShjb2x1bW4ubmFtZSwgdmFsdWUpO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWVbY29sdW1uLm5hbWVdO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHRlciBtZXRob2QgZm9yIHRlbXBsYXRlIHJlZmVyZW5jZXNcbiAgICovXG4gICBnZXRUZW1wbGF0ZVJlZihuYW1lOiBzdHJpbmcpOiBUZW1wbGF0ZVJlZjxhbnk+IHtcbiAgICAgcmV0dXJuIHRoaXMuX3RlbXBsYXRlTWFwLmdldChuYW1lKTtcbiAgIH1cblxuICAvKipcbiAgICogQ2xlYXJzIG1vZGVsIChuZ01vZGVsKSBvZiBjb21wb25lbnQgYnkgcmVtb3ZpbmcgYWxsIHZhbHVlcyBpbiBhcnJheS5cbiAgICovXG4gIGNsZWFyTW9kZWwoKTogdm9pZCB7XG4gICAgdGhpcy52YWx1ZS5zcGxpY2UoMCwgdGhpcy52YWx1ZS5sZW5ndGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZnJlc2hlcyBkYXRhIHRhYmxlIGFuZCByZXJlbmRlcnMgW2RhdGFdIGFuZCBbY29sdW1uc11cbiAgICovXG4gIHJlZnJlc2goKTogdm9pZCB7XG4gICAgdGhpcy5fY2FsY3VsYXRlVmlydHVhbFJvd3MoKTtcbiAgICB0aGlzLl9jYWxjdWxhdGVXaWR0aHMoKTtcbiAgICB0aGlzLl9jYWxjdWxhdGVDaGVja2JveFN0YXRlKCk7XG4gICAgdGhpcy5fY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICAvKipcbiAgICogU2VsZWN0cyBvciBjbGVhcnMgYWxsIHJvd3MgZGVwZW5kaW5nIG9uICdjaGVja2VkJyB2YWx1ZS5cbiAgICovXG4gIHNlbGVjdEFsbChjaGVja2VkOiBib29sZWFuKTogdm9pZCB7XG4gICAgbGV0IHRvZ2dsZWRSb3dzOiBhbnlbXSA9IFtdO1xuICAgIGlmIChjaGVja2VkKSB7XG4gICAgICB0aGlzLl9kYXRhLmZvckVhY2goKHJvdzogYW55KSA9PiB7XG4gICAgICAgIC8vIHNraXBpbmcgYWxyZWFkeSBzZWxlY3RlZCByb3dzXG4gICAgICAgIGlmICghdGhpcy5pc1Jvd1NlbGVjdGVkKHJvdykpIHtcbiAgICAgICAgICB0aGlzLnZhbHVlLnB1c2gocm93KTtcbiAgICAgICAgICAvLyBjaGVja2luZyB3aGljaCBvbmVzIGFyZSBiZWluZyB0b2dnbGVkXG4gICAgICAgICAgdG9nZ2xlZFJvd3MucHVzaChyb3cpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHRoaXMuX2FsbFNlbGVjdGVkID0gdHJ1ZTtcbiAgICAgIHRoaXMuX2luZGV0ZXJtaW5hdGUgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9kYXRhLmZvckVhY2goKHJvdzogYW55KSA9PiB7XG4gICAgICAgIC8vIGNoZWNraW5nIHdoaWNoIG9uZXMgYXJlIGJlaW5nIHRvZ2dsZWRcbiAgICAgICAgaWYgKHRoaXMuaXNSb3dTZWxlY3RlZChyb3cpKSB7XG4gICAgICAgICAgdG9nZ2xlZFJvd3MucHVzaChyb3cpO1xuICAgICAgICAgIGxldCBtb2RlbFJvdzogYW55ID0gdGhpcy52YWx1ZS5maWx0ZXIoKHZhbDogYW55KSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb21wYXJlV2l0aChyb3csIHZhbCk7XG4gICAgICAgICAgfSlbMF07XG4gICAgICAgICAgbGV0IGluZGV4OiBudW1iZXIgPSB0aGlzLnZhbHVlLmluZGV4T2YobW9kZWxSb3cpO1xuICAgICAgICAgIGlmIChpbmRleCA+IC0xKSB7XG4gICAgICAgICAgICB0aGlzLnZhbHVlLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHRoaXMuX2FsbFNlbGVjdGVkID0gZmFsc2U7XG4gICAgICB0aGlzLl9pbmRldGVybWluYXRlID0gZmFsc2U7XG4gICAgfVxuICAgIHRoaXMub25TZWxlY3RBbGwuZW1pdCh7cm93czogdG9nZ2xlZFJvd3MsIHNlbGVjdGVkOiBjaGVja2VkfSk7XG4gICAgdGhpcy5vbkNoYW5nZSh0aGlzLnZhbHVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgcm93IGlzIHNlbGVjdGVkXG4gICAqL1xuICBpc1Jvd1NlbGVjdGVkKHJvdzogYW55KTogYm9vbGVhbiB7XG4gICAgLy8gY29tcGFyZSBpdGVtcyBieSBbY29tcGFyZVdpdGhdIGZ1bmN0aW9uXG4gICAgcmV0dXJuIHRoaXMudmFsdWUgPyB0aGlzLnZhbHVlLmZpbHRlcigodmFsOiBhbnkpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmNvbXBhcmVXaXRoKHJvdywgdmFsKTtcbiAgICB9KS5sZW5ndGggPiAwIDogZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogU2VsZWN0cyBvciBjbGVhcnMgYSByb3cgZGVwZW5kaW5nIG9uICdjaGVja2VkJyB2YWx1ZSBpZiB0aGUgcm93ICdpc1NlbGVjdGFibGUnXG4gICAqIGhhbmRsZXMgY250cmwgY2xpY2tzIGFuZCBzaGlmdCBjbGlja3MgZm9yIG11bHRpLXNlbGVjdFxuICAgKi9cbiAgc2VsZWN0KHJvdzogYW55LCBldmVudDogRXZlbnQsIGN1cnJlbnRTZWxlY3RlZDogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc2VsZWN0YWJsZSkge1xuICAgICAgdGhpcy5ibG9ja0V2ZW50KGV2ZW50KTtcbiAgICAgIC8vIENoZWNrIHRvIHNlZSBpZiBTaGlmdCBrZXkgaXMgc2VsZWN0ZWQgYW5kIG5lZWQgdG8gc2VsZWN0IGV2ZXJ5dGhpbmcgaW4gYmV0d2VlblxuICAgICAgbGV0IG1vdXNlRXZlbnQ6IE1vdXNlRXZlbnQgPSBldmVudCBhcyBNb3VzZUV2ZW50O1xuICAgICAgaWYgKHRoaXMubXVsdGlwbGUgJiYgbW91c2VFdmVudCAmJiBtb3VzZUV2ZW50LnNoaWZ0S2V5ICYmIHRoaXMuX2xhc3RTZWxlY3RlZEluZGV4ID4gLTEpIHtcbiAgICAgICAgbGV0IGZpcnN0SW5kZXg6IG51bWJlciA9IGN1cnJlbnRTZWxlY3RlZDtcbiAgICAgICAgbGV0IGxhc3RJbmRleDogbnVtYmVyID0gdGhpcy5fbGFzdFNlbGVjdGVkSW5kZXg7XG4gICAgICAgIGlmIChjdXJyZW50U2VsZWN0ZWQgPiB0aGlzLl9sYXN0U2VsZWN0ZWRJbmRleCkge1xuICAgICAgICAgIGZpcnN0SW5kZXggPSB0aGlzLl9sYXN0U2VsZWN0ZWRJbmRleDtcbiAgICAgICAgICBsYXN0SW5kZXggPSBjdXJyZW50U2VsZWN0ZWQ7XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgY2xpY2tpbmcgYSBjaGVja2JveCBiZWhpbmQgdGhlIGluaXRpYWwgY2hlY2ssIHRoZW4gdG9nZ2xlIGFsbCBzZWxlY3Rpb25zIGV4cGVjdCB0aGUgaW5pdGlhbCBjaGVja2JveFxuICAgICAgICAvLyBlbHNlIHRoZSBjaGVja2JveGVzIGNsaWNrZWQgYXJlIGFsbCBhZnRlciB0aGUgaW5pdGlhbCBvbmVcbiAgICAgICAgaWYgKCh0aGlzLl9maXJzdFNlbGVjdGVkSW5kZXggPj0gY3VycmVudFNlbGVjdGVkICYmIHRoaXMuX2xhc3RTZWxlY3RlZEluZGV4ID4gdGhpcy5fZmlyc3RTZWxlY3RlZEluZGV4KSB8fFxuICAgICAgICAgICAodGhpcy5fZmlyc3RTZWxlY3RlZEluZGV4IDw9IGN1cnJlbnRTZWxlY3RlZCAmJiB0aGlzLl9sYXN0U2VsZWN0ZWRJbmRleCA8IHRoaXMuX2ZpcnN0U2VsZWN0ZWRJbmRleCkpIHtcbiAgICAgICAgICBmb3IgKGxldCBpOiBudW1iZXIgPSBmaXJzdEluZGV4OyBpIDw9IGxhc3RJbmRleDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5fZmlyc3RTZWxlY3RlZEluZGV4ICE9PSBpKSB7XG4gICAgICAgICAgICAgIHRoaXMuX2RvU2VsZWN0aW9uKHRoaXMuX2RhdGFbaV0sIGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICgodGhpcy5fZmlyc3RTZWxlY3RlZEluZGV4ID4gY3VycmVudFNlbGVjdGVkKSB8fCAodGhpcy5fZmlyc3RTZWxlY3RlZEluZGV4IDwgY3VycmVudFNlbGVjdGVkKSkge1xuICAgICAgICAgIC8vIGNoYW5nZSBpbmRleGVzIGRlcGVuZGluZyBvbiB3aGVyZSB0aGUgbmV4dCBjaGVja2JveCBpcyBzZWxlY3RlZCAoYmVmb3JlIG9yIGFmdGVyKVxuICAgICAgICAgIGlmICh0aGlzLl9maXJzdFNlbGVjdGVkSW5kZXggPiBjdXJyZW50U2VsZWN0ZWQpIHtcbiAgICAgICAgICAgIGxhc3RJbmRleC0tO1xuICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5fZmlyc3RTZWxlY3RlZEluZGV4IDwgY3VycmVudFNlbGVjdGVkKSB7XG4gICAgICAgICAgICBmaXJzdEluZGV4Kys7XG4gICAgICAgICAgfVxuICAgICAgICAgIGZvciAobGV0IGk6IG51bWJlciA9IGZpcnN0SW5kZXg7IGkgPD0gbGFzdEluZGV4OyBpKyspIHtcbiAgICAgICAgICAgIGxldCByb3dTZWxlY3RlZDogYm9vbGVhbiA9IHRoaXMuaXNSb3dTZWxlY3RlZCh0aGlzLl9kYXRhW2ldKTtcbiAgICAgICAgICAgIC8vIGlmIHJvdyBpcyBzZWxlY3RlZCBhbmQgZmlyc3QgY2hlY2tib3ggd2FzIHNlbGVjdGVkXG4gICAgICAgICAgICAvLyBvciBpZiByb3cgd2FzIHVuc2VsZWN0ZWQgYW5kIGZpcnN0IGNoZWNrYm94IHdhcyB1bnNlbGVjdGVkXG4gICAgICAgICAgICAvLyB3ZSBpZ25vcmUgdGhlIHRvZ2dsZVxuICAgICAgICAgICAgaWYgKCh0aGlzLl9maXJzdENoZWNrYm94VmFsdWUgJiYgIXJvd1NlbGVjdGVkKSB8fFxuICAgICAgICAgICAgICAgICghdGhpcy5fZmlyc3RDaGVja2JveFZhbHVlICYmIHJvd1NlbGVjdGVkKSkge1xuICAgICAgICAgICAgICB0aGlzLl9kb1NlbGVjdGlvbih0aGlzLl9kYXRhW2ldLCBpKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5fc2hpZnRQcmV2aW91c2x5UHJlc3NlZCkge1xuICAgICAgICAgICAgICAvLyBlbHNlIGlmIHRoZSBjaGVja2JveCBzZWxlY3RlZCB3YXMgaW4gdGhlIG1pZGRsZSBvZiB0aGUgbGFzdCBzZWxlY3Rpb24gYW5kIHRoZSBmaXJzdCBzZWxlY3Rpb25cbiAgICAgICAgICAgICAgLy8gdGhlbiB3ZSB1bmRvIHRoZSBzZWxlY3Rpb25zXG4gICAgICAgICAgICAgIGlmICgoY3VycmVudFNlbGVjdGVkID49IHRoaXMuX2ZpcnN0U2VsZWN0ZWRJbmRleCAmJiBjdXJyZW50U2VsZWN0ZWQgPD0gdGhpcy5fbGFzdFNlbGVjdGVkSW5kZXgpIHx8XG4gICAgICAgICAgICAgICAgICAoY3VycmVudFNlbGVjdGVkIDw9IHRoaXMuX2ZpcnN0U2VsZWN0ZWRJbmRleCAmJiBjdXJyZW50U2VsZWN0ZWQgPj0gdGhpcy5fbGFzdFNlbGVjdGVkSW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZG9TZWxlY3Rpb24odGhpcy5fZGF0YVtpXSwgaSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fc2hpZnRQcmV2aW91c2x5UHJlc3NlZCA9IHRydWU7XG4gICAgICAvLyBpZiBzaGlmdCB3YXNudCBwcmVzc2VkLCB0aGVuIHdlIHRha2UgdGhlIGVsZW1lbnQgY2hlY2tlZCBhcyB0aGUgZmlyc3Qgcm93XG4gICAgICAvLyBpbmNhc2UgdGhlIG5leHQgY2xpY2sgdXNlcyBzaGlmdFxuICAgICAgfSBlbHNlIGlmIChtb3VzZUV2ZW50ICYmICFtb3VzZUV2ZW50LnNoaWZ0S2V5KSB7XG4gICAgICAgIHRoaXMuX2ZpcnN0Q2hlY2tib3hWYWx1ZSA9IHRoaXMuX2RvU2VsZWN0aW9uKHJvdywgY3VycmVudFNlbGVjdGVkKTtcbiAgICAgICAgdGhpcy5fc2hpZnRQcmV2aW91c2x5UHJlc3NlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLl9maXJzdFNlbGVjdGVkSW5kZXggPSBjdXJyZW50U2VsZWN0ZWQ7XG4gICAgICB9XG4gICAgICB0aGlzLl9sYXN0U2VsZWN0ZWRJbmRleCA9IGN1cnJlbnRTZWxlY3RlZDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogT3ZlcnJpZGVzIHRoZSBvbnNlbGVjdHN0YXJ0IG1ldGhvZCBvZiB0aGUgZG9jdW1lbnQgc28gb3RoZXIgdGV4dCBvbiB0aGUgcGFnZVxuICAgKiBkb2Vzbid0IGdldCBzZWxlY3RlZCB3aGVuIGRvaW5nIHNoaWZ0IHNlbGVjdGlvbnMuXG4gICAqL1xuICBkaXNhYmxlVGV4dFNlbGVjdGlvbigpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fZG9jdW1lbnQpIHtcbiAgICAgIHRoaXMuX2RvY3VtZW50Lm9uc2VsZWN0c3RhcnQgPSBmdW5jdGlvbigpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVzZXRzIHRoZSBvcmlnaW5hbCBvbnNlbGVjdHN0YXJ0IG1ldGhvZC5cbiAgICovXG4gIGVuYWJsZVRleHRTZWxlY3Rpb24oKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuX2RvY3VtZW50KSB7XG4gICAgICB0aGlzLl9kb2N1bWVudC5vbnNlbGVjdHN0YXJ0ID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBlbWl0cyB0aGUgb25Sb3dDbGlja0V2ZW50IHdoZW4gYSByb3cgaXMgY2xpY2tlZFxuICAgKiBpZiBjbGlja2FibGUgaXMgdHJ1ZSBhbmQgc2VsZWN0YWJsZSBpcyBmYWxzZSB0aGVuIHNlbGVjdCB0aGUgcm93XG4gICAqL1xuICBoYW5kbGVSb3dDbGljayhyb3c6IGFueSwgaW5kZXg6IG51bWJlciwgZXZlbnQ6IEV2ZW50KTogdm9pZCB7XG4gICAgaWYgKHRoaXMuY2xpY2thYmxlKSB7XG4gICAgICAvLyBpZ25vcmluZyBsaW50aW5nIHJ1bGVzIGhlcmUgYmVjYXVzZSBhdHRyaWJ1dGUgaXQgYWN0dWFsbHkgbnVsbCBvciBub3QgdGhlcmVcbiAgICAgIC8vIGNhbid0IGNoZWNrIGZvciB1bmRlZmluZWRcbiAgICAgIGNvbnN0IHNyY0VsZW1lbnQ6IGFueSA9IGV2ZW50LnNyY0VsZW1lbnQgfHwgZXZlbnQuY3VycmVudFRhcmdldDtcbiAgICAgIGxldCBlbGVtZW50OiBIVE1MRWxlbWVudCA9IGV2ZW50LnRhcmdldCBhcyBIVE1MRWxlbWVudDtcbiAgICAgIC8qIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSAqL1xuICAgICAgaWYgKHNyY0VsZW1lbnQuZ2V0QXR0cmlidXRlKCdzdG9wUm93Q2xpY2snKSA9PT0gbnVsbCAmJiBlbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKSAhPT0gJ21hdC1wc2V1ZG8tY2hlY2tib3gnKSB7XG4gICAgICAgIHRoaXMub25Sb3dDbGljay5lbWl0KHtcbiAgICAgICAgICByb3c6IHJvdyxcbiAgICAgICAgICBpbmRleDogaW5kZXgsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgaGFuZGxlIGZvciBzb3J0IGNsaWNrIGV2ZW50IGluIGNvbHVtbiBoZWFkZXJzLlxuICAgKi9cbiAgaGFuZGxlU29ydChjb2x1bW46IElUZERhdGFUYWJsZUNvbHVtbik6IHZvaWQge1xuICAgIGlmICh0aGlzLl9zb3J0QnkgPT09IGNvbHVtbikge1xuICAgICAgdGhpcy5fc29ydE9yZGVyID0gdGhpcy5fc29ydE9yZGVyID09PSBUZERhdGFUYWJsZVNvcnRpbmdPcmRlci5Bc2NlbmRpbmcgP1xuICAgICAgICBUZERhdGFUYWJsZVNvcnRpbmdPcmRlci5EZXNjZW5kaW5nIDogVGREYXRhVGFibGVTb3J0aW5nT3JkZXIuQXNjZW5kaW5nO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9zb3J0QnkgPSBjb2x1bW47XG4gICAgICB0aGlzLl9zb3J0T3JkZXIgPSBUZERhdGFUYWJsZVNvcnRpbmdPcmRlci5Bc2NlbmRpbmc7XG4gICAgfVxuICAgIHRoaXMub25Tb3J0Q2hhbmdlLm5leHQoeyBuYW1lOiB0aGlzLl9zb3J0QnkubmFtZSwgb3JkZXI6IHRoaXMuX3NvcnRPcmRlciB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGUgYWxsIGtleXVwIGV2ZW50cyB3aGVuIGZvY3VzaW5nIGEgZGF0YSB0YWJsZSByb3dcbiAgICovXG4gIF9yb3dLZXl1cChldmVudDogS2V5Ym9hcmRFdmVudCwgcm93OiBhbnksIGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICBzd2l0Y2ggKGV2ZW50LmtleUNvZGUpIHtcbiAgICAgIGNhc2UgRU5URVI6XG4gICAgICBjYXNlIFNQQUNFOlxuICAgICAgICAvKiogaWYgdXNlciBwcmVzc2VzIGVudGVyIG9yIHNwYWNlLCB0aGUgcm93IHNob3VsZCBiZSBzZWxlY3RlZCAqL1xuICAgICAgICBpZiAodGhpcy5zZWxlY3RhYmxlKSB7XG4gICAgICAgICAgdGhpcy5fZG9TZWxlY3Rpb24odGhpcy5fZGF0YVt0aGlzLmZyb21Sb3cgKyBpbmRleF0sIHRoaXMuZnJvbVJvdyArIGluZGV4KTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgVVBfQVJST1c6XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBpZiB1c2VycyBwcmVzc2VzIHRoZSB1cCBhcnJvdywgd2UgZm9jdXMgdGhlIHByZXYgcm93XG4gICAgICAgICAqIHVubGVzcyBpdHMgdGhlIGZpcnN0IHJvd1xuICAgICAgICAgKi9cbiAgICAgICAgaWYgKGluZGV4ID4gMCkge1xuICAgICAgICAgIHRoaXMuX3Jvd3MudG9BcnJheSgpW2luZGV4IC0gMV0uZm9jdXMoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmJsb2NrRXZlbnQoZXZlbnQpO1xuICAgICAgICBpZiAodGhpcy5zZWxlY3RhYmxlICYmIHRoaXMubXVsdGlwbGUgJiYgZXZlbnQuc2hpZnRLZXkgJiYgdGhpcy5mcm9tUm93ICsgaW5kZXggPj0gMCkge1xuICAgICAgICAgIHRoaXMuX2RvU2VsZWN0aW9uKHRoaXMuX2RhdGFbdGhpcy5mcm9tUm93ICsgaW5kZXhdLCB0aGlzLmZyb21Sb3cgKyBpbmRleCk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIERPV05fQVJST1c6XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBpZiB1c2VycyBwcmVzc2VzIHRoZSBkb3duIGFycm93LCB3ZSBmb2N1cyB0aGUgbmV4dCByb3dcbiAgICAgICAgICogdW5sZXNzIGl0cyB0aGUgbGFzdCByb3dcbiAgICAgICAgICovXG4gICAgICAgIGlmIChpbmRleCA8ICh0aGlzLl9yb3dzLnRvQXJyYXkoKS5sZW5ndGggLSAxKSkge1xuICAgICAgICAgIHRoaXMuX3Jvd3MudG9BcnJheSgpW2luZGV4ICsgMV0uZm9jdXMoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmJsb2NrRXZlbnQoZXZlbnQpO1xuICAgICAgICBpZiAodGhpcy5zZWxlY3RhYmxlICYmIHRoaXMubXVsdGlwbGUgJiYgZXZlbnQuc2hpZnRLZXkgJiYgdGhpcy5mcm9tUm93ICsgaW5kZXggPCB0aGlzLl9kYXRhLmxlbmd0aCkge1xuICAgICAgICAgIHRoaXMuX2RvU2VsZWN0aW9uKHRoaXMuX2RhdGFbdGhpcy5mcm9tUm93ICsgaW5kZXhdLCB0aGlzLmZyb21Sb3cgKyBpbmRleCk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICAvLyBkZWZhdWx0XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgY29sdW1uIGluZGV4IG9mIHRoZSBkcmFnZ2VkIGNvbHVtbiBhbmQgaW5pdGlhbCBjbGllbnRYIG9mIGNvbHVtblxuICAgKi9cbiAgX2hhbmRsZVN0YXJ0Q29sdW1uRHJhZyhpbmRleDogbnVtYmVyLCBldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIHRoaXMuX2NvbHVtbkNsaWVudFggPSBldmVudC5jbGllbnRYO1xuICAgIHRoaXMuX3Jlc2l6aW5nQ29sdW1uID0gaW5kZXg7XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlcyBuZXcgd2lkdGggZGVwZW5kaW5nIG9uIG5ldyBjbGllbnRYIG9mIGRyYWdnZXIgY29sdW1uXG4gICAqL1xuICBfaGFuZGxlQ29sdW1uRHJhZyhldmVudDogTW91c2VFdmVudCB8IERyYWdFdmVudCk6IHZvaWQge1xuICAgIC8vIGNoZWNrIGlmIHRoZXJlIHdhcyBiZWVuIGEgc2VwYXJhdG9yIGNsaWNrZWQgZm9yIHJlc2l6ZVxuICAgIGlmICh0aGlzLl9yZXNpemluZ0NvbHVtbiAhPT0gdW5kZWZpbmVkICYmIGV2ZW50LmNsaWVudFggPiAwKSB7XG4gICAgICBsZXQgeFBvc2l0aW9uOiBudW1iZXIgPSBldmVudC5jbGllbnRYO1xuICAgICAgLy8gY2hlY2tzIGlmIHRoZSBzZXBhcmF0b3IgaXMgYmVpbmcgbW92ZWQgdG8gdHJ5IGFuZCByZXNpemUgdGhlIGNvbHVtbiwgZWxzZSBkb250IGRvIGFueXRoaW5nXG4gICAgICBpZiAoeFBvc2l0aW9uID4gMCAmJiB0aGlzLl9jb2x1bW5DbGllbnRYID4gMCAmJiAoeFBvc2l0aW9uIC0gdGhpcy5fY29sdW1uQ2xpZW50WCkgIT09IDApIHtcbiAgICAgICAgLy8gY2FsY3VsYXRlIHRoZSBuZXcgd2lkdGggZGVwZW5kaW5nIGlmIG1ha2luZyB0aGUgY29sdW1uIGJpZ2dlciBvciBzbWFsbGVyXG4gICAgICAgIGxldCBwcm9wb3NlZE1hbnVhbFdpZHRoOiBudW1iZXIgPSB0aGlzLl93aWR0aHNbdGhpcy5fcmVzaXppbmdDb2x1bW5dLnZhbHVlICsgKHhQb3NpdGlvbiAtIHRoaXMuX2NvbHVtbkNsaWVudFgpO1xuICAgICAgICAvLyBpZiB0aGUgcHJvcG9zZWQgbmV3IHdpZHRoIGlzIGxlc3MgdGhhbiB0aGUgcHJvamVjdGVkIG1pbiB3aWR0aCBvZiB0aGUgY29sdW1uLCB1c2UgcHJvamVjdGVkIG1pbiB3aWR0aFxuICAgICAgICBpZiAocHJvcG9zZWRNYW51YWxXaWR0aCA8IHRoaXMuX2NvbEVsZW1lbnRzLnRvQXJyYXkoKVt0aGlzLl9yZXNpemluZ0NvbHVtbl0ucHJvamVjdGVkV2lkdGgpIHtcbiAgICAgICAgICBwcm9wb3NlZE1hbnVhbFdpZHRoID0gdGhpcy5fY29sRWxlbWVudHMudG9BcnJheSgpW3RoaXMuX3Jlc2l6aW5nQ29sdW1uXS5wcm9qZWN0ZWRXaWR0aDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNvbHVtbnNbdGhpcy5fcmVzaXppbmdDb2x1bW5dLndpZHRoID0gcHJvcG9zZWRNYW51YWxXaWR0aDtcbiAgICAgICAgLy8gdXBkYXRlIG5ldyB4IHBvc2l0aW9uIGZvciB0aGUgcmVzaXplZCBjb2x1bW5cbiAgICAgICAgdGhpcy5fb25Db2x1bW5SZXNpemUubmV4dCh4UG9zaXRpb24pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBFbmRzIGRyYWdnZWQgZmxhZ3NcbiAgICovXG4gIF9oYW5kbGVFbmRDb2x1bW5EcmFnKCk6IHZvaWQge1xuICAgIHRoaXMuX2NvbHVtbkNsaWVudFggPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fcmVzaXppbmdDb2x1bW4gPSB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIHRvIHByZXZlbnQgdGhlIGRlZmF1bHQgZXZlbnRzXG4gICAqL1xuICBibG9ja0V2ZW50KGV2ZW50OiBFdmVudCk6IHZvaWQge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gIH1cblxuICBwcml2YXRlIF9nZXROZXN0ZWRWYWx1ZShuYW1lOiBzdHJpbmcsIHZhbHVlOiBhbnkpOiBzdHJpbmcge1xuICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgT2JqZWN0KSB8fCAhbmFtZSkge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgICBpZiAobmFtZS5pbmRleE9mKCcuJykgPiAtMSkge1xuICAgICAgbGV0IHNwbGl0TmFtZTogc3RyaW5nW10gPSBuYW1lLnNwbGl0KC9cXC4oLispLywgMik7XG4gICAgICByZXR1cm4gdGhpcy5fZ2V0TmVzdGVkVmFsdWUoc3BsaXROYW1lWzFdLCB2YWx1ZVtzcGxpdE5hbWVbMF1dKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHZhbHVlW25hbWVdO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEb2VzIHRoZSBhY3R1YWwgUm93IFNlbGVjdGlvblxuICAgKi9cbiAgcHJpdmF0ZSBfZG9TZWxlY3Rpb24ocm93OiBhbnksIHJvd0luZGV4OiBudW1iZXIpOiBib29sZWFuIHtcbiAgICBsZXQgd2FzU2VsZWN0ZWQ6IGJvb2xlYW4gPSB0aGlzLmlzUm93U2VsZWN0ZWQocm93KTtcbiAgICBpZiAoIXdhc1NlbGVjdGVkKSB7XG4gICAgICBpZiAoIXRoaXMuX211bHRpcGxlKSB7XG4gICAgICAgIHRoaXMuY2xlYXJNb2RlbCgpO1xuICAgICAgfVxuICAgICAgdGhpcy52YWx1ZS5wdXNoKHJvdyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGNvbXBhcmUgaXRlbXMgYnkgW2NvbXBhcmVXaXRoXSBmdW5jdGlvblxuICAgICAgcm93ID0gdGhpcy52YWx1ZS5maWx0ZXIoKHZhbDogYW55KSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbXBhcmVXaXRoKHJvdywgdmFsKTtcbiAgICAgIH0pWzBdO1xuICAgICAgbGV0IGluZGV4OiBudW1iZXIgPSB0aGlzLnZhbHVlLmluZGV4T2Yocm93KTtcbiAgICAgIGlmIChpbmRleCA+IC0xKSB7XG4gICAgICAgIHRoaXMudmFsdWUuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5fY2FsY3VsYXRlQ2hlY2tib3hTdGF0ZSgpO1xuICAgIHRoaXMub25Sb3dTZWxlY3QuZW1pdCh7cm93OiByb3csIGluZGV4OiByb3dJbmRleCwgc2VsZWN0ZWQ6ICF3YXNTZWxlY3RlZH0pO1xuICAgIHRoaXMub25DaGFuZ2UodGhpcy52YWx1ZSk7XG4gICAgcmV0dXJuICF3YXNTZWxlY3RlZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgYWxsIHRoZSBzdGF0ZSBvZiBhbGwgY2hlY2tib3hlc1xuICAgKi9cbiAgcHJpdmF0ZSBfY2FsY3VsYXRlQ2hlY2tib3hTdGF0ZSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fZGF0YSkge1xuICAgICAgdGhpcy5fYWxsU2VsZWN0ZWQgPSB0eXBlb2YgdGhpcy5fZGF0YS5maW5kKChkOiBhbnkpID0+ICF0aGlzLmlzUm93U2VsZWN0ZWQoZCkpID09PSAndW5kZWZpbmVkJztcbiAgICAgIHRoaXMuX2luZGV0ZXJtaW5hdGUgPSBmYWxzZTtcbiAgICAgIGZvciAobGV0IHJvdyBvZiB0aGlzLl9kYXRhKSB7XG4gICAgICAgIGlmICghdGhpcy5pc1Jvd1NlbGVjdGVkKHJvdykpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9pbmRldGVybWluYXRlID0gdHJ1ZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENhbGN1bGF0ZXMgdGhlIHdpZHRocyBmb3IgY29sdW1ucyBhbmQgY2VsbHMgZGVwZW5kaW5nIG9uIGNvbnRlbnRcbiAgICovXG4gIHByaXZhdGUgX2NhbGN1bGF0ZVdpZHRocygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fY29sRWxlbWVudHMgJiYgdGhpcy5fY29sRWxlbWVudHMubGVuZ3RoKSB7XG4gICAgICB0aGlzLl93aWR0aHMgPSBbXTtcbiAgICAgIHRoaXMuX2NvbEVsZW1lbnRzLmZvckVhY2goKGNvbDogVGREYXRhVGFibGVDb2x1bW5Db21wb25lbnQsIGluZGV4OiBudW1iZXIpID0+IHtcbiAgICAgICAgdGhpcy5fYWRqdXN0Q29sdW1uV2lkdGgoaW5kZXgsIHRoaXMuX2NhbGN1bGF0ZVdpZHRoKCkpO1xuICAgICAgfSk7XG4gICAgICB0aGlzLl9hZGp1c3RDb2x1bW5XaWRodHMoKTtcbiAgICAgIHRoaXMuX2NoYW5nZURldGVjdG9yUmVmLm1hcmtGb3JDaGVjaygpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBZGp1c3RzIGNvbHVtbnMgYWZ0ZXIgY2FsY3VsYXRpb24gdG8gc2VlIGlmIHRoZXkgbmVlZCB0byBiZSByZWNhbGN1bGF0ZWQuXG4gICAqL1xuICBwcml2YXRlIF9hZGp1c3RDb2x1bW5XaWRodHMoKTogdm9pZCB7XG4gICAgbGV0IGZpeGVkVG90YWxXaWR0aDogbnVtYmVyID0gMDtcbiAgICAvLyBnZXQgdGhlIG51bWJlciBvZiB0b3RhbCBjb2x1bW5zIHRoYXQgaGF2ZSBmbGV4aWJsZSB3aWR0aHMgKG5vdCBmaXhlZCBvciBoaWRkZW4pXG4gICAgbGV0IGZsZXhpYmxlV2lkdGhzOiBudW1iZXIgPSB0aGlzLl93aWR0aHMuZmlsdGVyKCh3aWR0aDogSUludGVybmFsQ29sdW1uV2lkdGgsIGluZGV4OiBudW1iZXIpID0+IHtcbiAgICAgIGlmICh0aGlzLmNvbHVtbnNbaW5kZXhdLmhpZGRlbikge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBpZiAod2lkdGgubGltaXQgfHwgd2lkdGgubWF4IHx8IHdpZHRoLm1pbikge1xuICAgICAgICBmaXhlZFRvdGFsV2lkdGggKz0gd2lkdGgudmFsdWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gIXdpZHRoLmxpbWl0ICYmICF3aWR0aC5tYXggJiYgIXdpZHRoLm1pbjtcbiAgICB9KS5sZW5ndGg7XG4gICAgLy8gY2FsY3VsYXRlIGhvdyBtdWNoIHBpeGVzIGFyZSBsZWZ0IHRoYXQgY291bGQgYmUgc3ByZWFkIGFjcm9zc1xuICAgIC8vIHRoZSBmbGV4aWJsZSBjb2x1bW5zXG4gICAgbGV0IHJlY2FsY3VsYXRlSG9zdFdpZHRoOiBudW1iZXIgPSAwO1xuICAgIGlmIChmaXhlZFRvdGFsV2lkdGggPCB0aGlzLmhvc3RXaWR0aCkge1xuICAgICAgcmVjYWxjdWxhdGVIb3N0V2lkdGggPSB0aGlzLmhvc3RXaWR0aCAtIGZpeGVkVG90YWxXaWR0aDtcbiAgICB9XG4gICAgLy8gaWYgd2UgaGF2ZSBmbGV4aWJsZSBjb2x1bW5zIGFuZCBwaXhlbHMgdG8gc3BhcmUgb24gdGhlbVxuICAgIC8vIHdlIHRyeSBhbmQgc3ByZWFkIHRoZSBwaXhlbHMgYWNyb3NzIHRoZW1cbiAgICBpZiAoZmxleGlibGVXaWR0aHMgJiYgcmVjYWxjdWxhdGVIb3N0V2lkdGgpIHtcbiAgICAgIGxldCBuZXdWYWx1ZTogbnVtYmVyID0gTWF0aC5mbG9vcihyZWNhbGN1bGF0ZUhvc3RXaWR0aCAvIGZsZXhpYmxlV2lkdGhzKTtcbiAgICAgIGxldCBhZGp1c3RlZE51bWJlcjogbnVtYmVyID0gMDtcbiAgICAgIC8vIGFkanVzdCB0aGUgY29sdW1uIHdpZHRocyB3aXRoIHRoZSBzcHJlYWQgcGl4ZWxzXG4gICAgICB0aGlzLl93aWR0aHMuZm9yRWFjaCgoY29sV2lkdGg6IElJbnRlcm5hbENvbHVtbldpZHRoKSA9PiB7XG4gICAgICAgIGlmICh0aGlzLl93aWR0aHNbY29sV2lkdGguaW5kZXhdLm1heCAmJiB0aGlzLl93aWR0aHNbY29sV2lkdGguaW5kZXhdLnZhbHVlID4gbmV3VmFsdWUgfHxcbiAgICAgICAgICAgIHRoaXMuX3dpZHRoc1tjb2xXaWR0aC5pbmRleF0ubWluICYmIHRoaXMuX3dpZHRoc1tjb2xXaWR0aC5pbmRleF0udmFsdWUgPCBuZXdWYWx1ZSB8fFxuICAgICAgICAgICAgIXRoaXMuX3dpZHRoc1tjb2xXaWR0aC5pbmRleF0ubGltaXQpIHtcbiAgICAgICAgICB0aGlzLl9hZGp1c3RDb2x1bW5XaWR0aChjb2xXaWR0aC5pbmRleCwgbmV3VmFsdWUpO1xuICAgICAgICAgIGFkanVzdGVkTnVtYmVyKys7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgLy8gaWYgdGhlcmUgYXJlIHN0aWxsIGNvbHVtbnMgdGhhdCBuZWVkIHRvIGJlIHJlY2FsY3VsYXRlZCwgd2Ugc3RhcnQgb3ZlclxuICAgICAgbGV0IG5ld0ZsZXhpYmxlV2lkdGhzOiBudW1iZXIgPSB0aGlzLl93aWR0aHMuZmlsdGVyKCh3aWR0aDogSUludGVybmFsQ29sdW1uV2lkdGgpID0+IHtcbiAgICAgICAgcmV0dXJuICF3aWR0aC5saW1pdCAmJiAhd2lkdGgubWF4O1xuICAgICAgfSkubGVuZ3RoO1xuICAgICAgaWYgKG5ld0ZsZXhpYmxlV2lkdGhzICE9PSBhZGp1c3RlZE51bWJlciAmJiBuZXdGbGV4aWJsZVdpZHRocyAhPT0gZmxleGlibGVXaWR0aHMpIHtcbiAgICAgICAgdGhpcy5fYWRqdXN0Q29sdW1uV2lkaHRzKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFkanVzdHMgYSBzaW5nbGUgY29sdW1uIHRvIHNlZSBpZiBpdCBjYW4gYmUgcmVjYWxjdWxhdGVkXG4gICAqL1xuICBwcml2YXRlIF9hZGp1c3RDb2x1bW5XaWR0aChpbmRleDogbnVtYmVyLCB2YWx1ZTogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5fd2lkdGhzW2luZGV4XSA9IHtcbiAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICAgIGluZGV4OiBpbmRleCxcbiAgICAgIGxpbWl0OiBmYWxzZSxcbiAgICAgIG1pbjogZmFsc2UsXG4gICAgICBtYXg6IGZhbHNlLFxuICAgIH07XG4gICAgLy8gZmxhZyB0byBzZWUgaWYgd2UgbmVlZCB0byBza2lwIHRoZSBtaW4gd2lkdGggcHJvamVjdGlvblxuICAgIC8vIGRlcGVuZGluZyBpZiBhIHdpZHRoIG9yIG1pbiB3aWR0aCBoYXMgYmVlbiBwcm92aWRlZFxuICAgIGxldCBza2lwTWluV2lkdGhQcm9qZWN0aW9uOiBib29sZWFuID0gZmFsc2U7XG4gICAgaWYgKHRoaXMuY29sdW1uc1tpbmRleF0pIHtcbiAgICAgIC8vIGlmIHRoZSBwcm92aWRlZCB3aWR0aCBoYXMgbWluL21heCwgdGhlbiB3ZSBjaGVjayB0byBzZWUgaWYgd2UgbmVlZCB0byBzZXQgaXRcbiAgICAgIGlmICh0eXBlb2YgdGhpcy5jb2x1bW5zW2luZGV4XS53aWR0aCA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgbGV0IHdpZHRoT3B0czogSVRkRGF0YVRhYmxlQ29sdW1uV2lkdGggPSA8SVRkRGF0YVRhYmxlQ29sdW1uV2lkdGg+dGhpcy5jb2x1bW5zW2luZGV4XS53aWR0aDtcbiAgICAgICAgLy8gaWYgdGhlIGNvbHVtbiB3aWR0aCBpcyBsZXNzIHRoYW4gdGhlIGNvbmZpZ3VyZWQgbWluLCB3ZSBvdmVycmlkZSBpdFxuICAgICAgICBza2lwTWluV2lkdGhQcm9qZWN0aW9uID0gKHdpZHRoT3B0cyAmJiAhIXdpZHRoT3B0cy5taW4pO1xuICAgICAgICBpZiAod2lkdGhPcHRzICYmIHdpZHRoT3B0cy5taW4gPj0gdGhpcy5fd2lkdGhzW2luZGV4XS52YWx1ZSkge1xuICAgICAgICAgIHRoaXMuX3dpZHRoc1tpbmRleF0udmFsdWUgPSB3aWR0aE9wdHMubWluO1xuICAgICAgICAgIHRoaXMuX3dpZHRoc1tpbmRleF0ubWluID0gdHJ1ZTtcbiAgICAgICAgLy8gaWYgdGhlIGNvbHVtbiB3aWR0aCBpcyBtb3JlIHRoYW4gdGhlIGNvbmZpZ3VyZWQgbWF4LCB3ZSBvdmVycmlkZSBpdFxuICAgICAgICB9IGVsc2UgaWYgKHdpZHRoT3B0cyAmJiB3aWR0aE9wdHMubWF4IDw9IHRoaXMuX3dpZHRoc1tpbmRleF0udmFsdWUpIHtcbiAgICAgICAgICB0aGlzLl93aWR0aHNbaW5kZXhdLnZhbHVlID0gd2lkdGhPcHRzLm1heDtcbiAgICAgICAgICB0aGlzLl93aWR0aHNbaW5kZXhdLm1heCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIC8vIGlmIGl0IGhhcyBhIGZpeGVkIHdpZHRoLCB0aGVuIHdlIGp1c3Qgc2V0IGl0XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiB0aGlzLmNvbHVtbnNbaW5kZXhdLndpZHRoID09PSAnbnVtYmVyJykge1xuICAgICAgICB0aGlzLl93aWR0aHNbaW5kZXhdLnZhbHVlID0gPG51bWJlcj50aGlzLmNvbHVtbnNbaW5kZXhdLndpZHRoO1xuICAgICAgICBza2lwTWluV2lkdGhQcm9qZWN0aW9uID0gdGhpcy5fd2lkdGhzW2luZGV4XS5saW1pdCA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIGlmIHRoZXJlIHdhc24ndCBhbnkgd2lkdGggb3IgbWluIHdpZHRoIHByb3ZpZGVkLCB3ZSBzZXQgYSBtaW4gdG8gd2hhdCB0aGUgY29sdW1uIHdpZHRoIG1pbiBzaG91bGQgYmVcbiAgICBpZiAoIXNraXBNaW5XaWR0aFByb2plY3Rpb24gJiZcbiAgICAgICAgdGhpcy5fd2lkdGhzW2luZGV4XS52YWx1ZSA8IHRoaXMuX2NvbEVsZW1lbnRzLnRvQXJyYXkoKVtpbmRleF0ucHJvamVjdGVkV2lkdGgpIHtcbiAgICAgIHRoaXMuX3dpZHRoc1tpbmRleF0udmFsdWUgPSB0aGlzLl9jb2xFbGVtZW50cy50b0FycmF5KClbaW5kZXhdLnByb2plY3RlZFdpZHRoO1xuICAgICAgdGhpcy5fd2lkdGhzW2luZGV4XS5taW4gPSB0cnVlO1xuICAgICAgdGhpcy5fd2lkdGhzW2luZGV4XS5saW1pdCA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmljIG1ldGhvZCB0byBjYWxjdWxhdGUgY29sdW1uIHdpZHRoXG4gICAqL1xuICBwcml2YXRlIF9jYWxjdWxhdGVXaWR0aCgpOiBudW1iZXIge1xuICAgIGxldCByZW5kZXJlZENvbHVtbnM6IElUZERhdGFUYWJsZUNvbHVtbltdID0gdGhpcy5jb2x1bW5zLmZpbHRlcigoY29sOiBJVGREYXRhVGFibGVDb2x1bW4pID0+ICFjb2wuaGlkZGVuKTtcbiAgICByZXR1cm4gTWF0aC5mbG9vcih0aGlzLmhvc3RXaWR0aCAvIHJlbmRlcmVkQ29sdW1ucy5sZW5ndGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB0byBjYWxjdWxhdGUgdGhlIHJvd3MgdG8gYmUgcmVuZGVyZWQgaW4gdGhlIHZpZXdwb3J0XG4gICAqL1xuICBwcml2YXRlIF9jYWxjdWxhdGVWaXJ0dWFsUm93cygpOiB2b2lkIHtcbiAgICBsZXQgc2Nyb2xsZWRSb3dzOiBudW1iZXIgPSAwO1xuICAgIGlmICh0aGlzLl9kYXRhKSB7XG4gICAgICB0aGlzLl90b3RhbEhlaWdodCA9IDA7XG4gICAgICBsZXQgcm93SGVpZ2h0U3VtOiBudW1iZXIgPSAwO1xuICAgICAgLy8gbG9vcCB0aHJvdWdoIGFsbCByb3dzIHRvIHNlZSBpZiB3ZSBoYXZlIHRoZWlyIGhlaWdodCBjYWNoZWRcbiAgICAgIC8vIGFuZCBzdW0gdGhlbSBhbGwgdG8gY2FsY3VsYXRlIHRoZSB0b3RhbCBoZWlnaHRcbiAgICAgIHRoaXMuX2RhdGEuZm9yRWFjaCgoZDogYW55LCBpOiBudW1iZXIpID0+IHtcbiAgICAgICAgLy8gaXRlcmF0ZSB0aHJvdWdoIGFsbCByb3dzIGF0IGZpcnN0IGFuZCBhc3N1bWUgYWxsXG4gICAgICAgIC8vIHJvd3MgYXJlIHRoZSBzYW1lIGhlaWdodCBhcyB0aGUgZmlyc3Qgb25lXG4gICAgICAgIGlmICghdGhpcy5fcm93SGVpZ2h0Q2FjaGVbaV0pIHtcbiAgICAgICAgICB0aGlzLl9yb3dIZWlnaHRDYWNoZVtpXSA9IHRoaXMuX3Jvd0hlaWdodENhY2hlWzBdIHx8IFREX1ZJUlRVQUxfREVGQVVMVF9ST1dfSEVJR0hUO1xuICAgICAgICB9XG4gICAgICAgIHJvd0hlaWdodFN1bSArPSB0aGlzLl9yb3dIZWlnaHRDYWNoZVtpXTtcbiAgICAgICAgLy8gY2hlY2sgaG93IG1hbnkgcm93cyBoYXZlIGJlZW4gc2Nyb2xsZWRcbiAgICAgICAgaWYgKHRoaXMuX3Njcm9sbFZlcnRpY2FsT2Zmc2V0IC0gcm93SGVpZ2h0U3VtID4gMCkge1xuICAgICAgICAgIHNjcm9sbGVkUm93cysrO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHRoaXMuX3RvdGFsSGVpZ2h0ID0gcm93SGVpZ2h0U3VtO1xuICAgICAgLy8gc2V0IHRoZSBpbml0aWFsIHJvdyB0byBiZSByZW5kZXJlZCB0YWtpbmcgaW50byBhY2NvdW50IHRoZSByb3cgb2Zmc2V0XG4gICAgICBsZXQgZnJvbVJvdzogbnVtYmVyID0gc2Nyb2xsZWRSb3dzIC0gVERfVklSVFVBTF9PRkZTRVQ7XG4gICAgICB0aGlzLl9mcm9tUm93ID0gZnJvbVJvdyA+IDAgPyBmcm9tUm93IDogMDtcblxuICAgICAgbGV0IGhvc3RIZWlnaHQ6IG51bWJlciA9IHRoaXMuX2hvc3RIZWlnaHQ7XG4gICAgICBsZXQgaW5kZXg6IG51bWJlciA9IDA7XG4gICAgICAvLyBjYWxjdWxhdGUgaG93IG1hbnkgcm93cyBjYW4gZml0IGluIHRoZSB2aWV3cG9ydFxuICAgICAgd2hpbGUgKGhvc3RIZWlnaHQgPiAwKSB7XG4gICAgICAgIGhvc3RIZWlnaHQgLT0gdGhpcy5fcm93SGVpZ2h0Q2FjaGVbdGhpcy5mcm9tUm93ICsgaW5kZXhdO1xuICAgICAgICBpbmRleCsrO1xuICAgICAgfVxuICAgICAgLy8gc2V0IHRoZSBsYXN0IHJvdyB0byBiZSByZW5kZXJlZCB0YWtpbmcgaW50byBhY2NvdW50IHRoZSByb3cgb2Zmc2V0XG4gICAgICBsZXQgcmFuZ2U6IG51bWJlciA9IChpbmRleCAtIDEpICsgKFREX1ZJUlRVQUxfT0ZGU0VUICogMik7XG4gICAgICBsZXQgdG9Sb3c6IG51bWJlciA9IHJhbmdlICsgdGhpcy5mcm9tUm93O1xuICAgICAgLy8gaWYgbGFzdCByb3cgaXMgZ3JlYXRlciB0aGFuIHRoZSB0b3RhbCBsZW5ndGgsIHRoZW4gd2UgdXNlIHRoZSB0b3RhbCBsZW5ndGhcbiAgICAgIGlmIChpc0Zpbml0ZSh0b1JvdykgJiYgdG9Sb3cgPiB0aGlzLl9kYXRhLmxlbmd0aCkge1xuICAgICAgICB0b1JvdyA9IHRoaXMuX2RhdGEubGVuZ3RoO1xuICAgICAgfSBlbHNlIGlmICghaXNGaW5pdGUodG9Sb3cpKSB7XG4gICAgICAgIHRvUm93ID0gVERfVklSVFVBTF9PRkZTRVQ7XG4gICAgICB9XG4gICAgICB0aGlzLl90b1JvdyA9IHRvUm93O1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl90b3RhbEhlaWdodCA9IDA7XG4gICAgICB0aGlzLl9mcm9tUm93ID0gMDtcbiAgICAgIHRoaXMuX3RvUm93ID0gMDtcbiAgICB9XG5cbiAgICBsZXQgb2Zmc2V0OiBudW1iZXIgPSAwO1xuICAgIC8vIGNhbGN1bGF0ZSB0aGUgcHJvcGVyIG9mZnNldCBkZXBlbmRpbmcgb24gaG93IG1hbnkgcm93cyBoYXZlIGJlZW4gc2Nyb2xsZWRcbiAgICBpZiAoc2Nyb2xsZWRSb3dzID4gVERfVklSVFVBTF9PRkZTRVQpIHtcbiAgICAgIGZvciAobGV0IGluZGV4OiBudW1iZXIgPSAwOyBpbmRleCA8IHRoaXMuZnJvbVJvdzsgaW5kZXgrKykge1xuICAgICAgICBvZmZzZXQgKz0gdGhpcy5fcm93SGVpZ2h0Q2FjaGVbaW5kZXhdO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuX29mZnNldFRyYW5zZm9ybSA9IHRoaXMuX2RvbVNhbml0aXplci5ieXBhc3NTZWN1cml0eVRydXN0U3R5bGUoJ3RyYW5zbGF0ZVkoJyArIChvZmZzZXQgLSB0aGlzLnRvdGFsSGVpZ2h0KSArICdweCknKTtcbiAgICBpZiAodGhpcy5fZGF0YSkge1xuICAgICAgdGhpcy5fdmlydHVhbERhdGEgPSB0aGlzLmRhdGEuc2xpY2UodGhpcy5mcm9tUm93LCB0aGlzLnRvUm93KTtcbiAgICB9XG4gICAgLy8gbWFyayBmb3IgY2hlY2sgYXQgdGhlIGVuZCBvZiB0aGUgcXVldWUgc28gd2UgYXJlIHN1cmVcbiAgICAvLyB0aGF0IHRoZSBjaGFuZ2VzIHdpbGwgYmUgbWFya2VkXG4gICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiB7XG4gICAgICB0aGlzLl9jaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKTtcbiAgICB9KTtcbiAgfVxufVxuIl19 |