@ux-aspects/ux-aspects
Version:
Open source user interface framework for building modern, responsive, mobile big data applications
184 lines • 31.8 kB
JavaScript
import { Injectable } from '@angular/core';
import { BaseResizableTableService, ResizableTableType } from '../resizable-table-base.service';
import * as i0 from "@angular/core";
export class ResizableTableService extends BaseResizableTableService {
constructor() {
super(...arguments);
/** Define the type of resizing we should use */
this.type = ResizableTableType.Standard;
}
/** Store the size of each column */
setColumns(columns) {
// store the current columns
this._columns = columns;
// store the sizes
this.columns = columns.map(column => (column.getNaturalWidth() / this.tableWidth) * 100);
// check if there is any overflow
this.columns = this.ensureNoOverflow(this.columns);
// ensure all the columns fit
this._columns.forEach((column, idx) => {
if (!column.disabled) {
this.resizeColumn(idx, 0, false);
}
});
// indicate we are now initialised
if (this.isInitialised$.value === false) {
this.isInitialised$.next(true);
}
}
/** Set all resizable columns to the same width */
setUniformWidths() {
// set any disabled columns to their specified width
this.columns = this._columns.map(column => column.disabled ? (column.getNaturalWidth() / this.tableWidth) * 100 : 0);
// check to see if we've reached 100% of the table width
const totalWidth = this.columns.reduce((partial, columnWidth) => partial + columnWidth);
if (totalWidth > 100) {
// remove overflow
this.columns = this.ensureNoOverflow(this.columns);
}
else {
// get the list of resizable columns
const resizableColumns = this._columns.toArray().filter(column => !column.disabled);
// work out what we need to add to each column to make up the full width
const newWidth = (100 - totalWidth) / resizableColumns.length;
// set the non-disabled columns to the new width
this.columns = this._columns.map((column, idx) => column.disabled ? this.columns[idx] : newWidth);
}
// do the resizing
this._columns.forEach((column, idx) => {
if (!column.disabled) {
this.resizeColumn(idx, 0, false);
}
});
}
ensureNoOverflow(columns) {
// get the total width
const total = columns.reduce((width, column) => width + column);
// if we have no overflow then we don't need to do anything
if (total <= 100) {
return columns;
}
// if there is overflow identify which columns can be resized
const variableColumns = this._columns.filter(column => !column.disabled && this.getColumnWidth(column.getCellIndex(), ColumnUnit.Pixel, columns) > column.minWidth);
// if there are no columns that can be resized then stop here
if (variableColumns.length === 0) {
return columns;
}
// determine the total width of the variable columns
const totalWidth = this._columns.reduce((width, column) => width + this.getColumnWidth(column.getCellIndex(), ColumnUnit.Pixel, columns), 0);
// determine to the width of all the variable columns
const variableColumnsWidth = variableColumns.reduce((width, column) => width + this.getColumnWidth(column.getCellIndex(), ColumnUnit.Pixel, columns), 0);
// determine how much the columns are currently too large (ignoring fixed columns)
const targetWidth = this.tableWidth - (totalWidth - variableColumnsWidth);
// determine how much we need to reduce a column by
const difference = variableColumnsWidth - targetWidth;
// find the column with the largest size
const target = variableColumns.reduce((widest, column) => {
const columnWidth = this.getColumnWidth(column.getCellIndex(), ColumnUnit.Pixel, columns);
const widestWidth = this.getColumnWidth(widest.getCellIndex(), ColumnUnit.Pixel, columns);
return columnWidth > widestWidth ? column : widest;
});
// perform the resize
columns = this.setColumnWidth(target.getCellIndex(), this.getColumnWidth(target.getCellIndex(), ColumnUnit.Pixel, columns) - difference, ColumnUnit.Pixel, columns);
// check if we are still over the limit (allow some variance for javascript double precision)
if (columns.reduce((width, column) => width + column) > 100.01) {
return this.ensureNoOverflow(columns);
}
return columns;
}
/** Allow setting the column size in any unit */
setColumnWidth(index, value, unit, columns = this.columns) {
// create a new array so we keep the instance array immutable
const sizes = [...columns];
switch (unit) {
case ColumnUnit.Percentage:
sizes[index] = value;
break;
case ColumnUnit.Pixel:
sizes[index] = (value / this.tableWidth) * 100;
break;
}
// update the instance variable
return sizes;
}
/** Resize a column by a specific pixel amount */
resizeColumn(index, delta, isDragging = true) {
// get the sibling column that will also be resized
const sibling = this.getSiblingColumn(index);
// if there is no sibling that can be resized then stop here
if (!sibling) {
return;
}
// create a new array for the sizes
let columns = [...this.columns];
// resize the column to the desired size
columns = this.setColumnWidth(index, Math.round(this.getColumnWidth(index, ColumnUnit.Pixel) + delta), ColumnUnit.Pixel, columns);
columns = this.setColumnWidth(sibling, Math.round(this.getColumnWidth(sibling, ColumnUnit.Pixel) - delta), ColumnUnit.Pixel, columns);
// if the move is not possible then stop here
if (!this.isWidthValid(index, this.getColumnWidth(index, ColumnUnit.Pixel, columns)) || !this.isWidthValid(sibling, this.getColumnWidth(sibling, ColumnUnit.Pixel, columns))) {
return;
}
// check that we add up to exactly 100%
const total = columns.reduce((count, column) => column + count, 0);
// if the columns to not add to 100 ensure we make them
if (total !== 100) {
// get the column with a variable width
const target = this.getVariableColumn(100 - total);
if (target && !isDragging) {
columns[this._columns.toArray().indexOf(target)] += (100 - total);
}
else {
columns[index] += (100 - total);
}
}
// store the new sizes
this.columns = columns;
// emit the resize event for each column
this.onResize$.next();
}
getVariableColumn(delta) {
// get all variable width columns that are not disabled
const variableColumns = this._columns.filter(column => !column.isFixedWidth && !column.disabled);
// find one that is greater than its min width by enough
return variableColumns.reverse().find(column => this.getColumnWidth(column.getCellIndex(), ColumnUnit.Pixel) >= column.minWidth + delta);
}
getColumn(index) {
return this._columns ? this._columns.toArray()[index] : null;
}
getColumnDisabled(index) {
return this.getColumn(index) ? this.getColumn(index).disabled : false;
}
/** Determine whether a column is above or below its minimum width */
isWidthValid(index, width) {
// get the column at a given position
const column = this.getColumnInstance(index);
// determine if the specified width is greater than the min width
return column && width >= column.minWidth;
}
/** Get the next column in the sequence of columns */
getSiblingColumn(index) {
// find the first sibling that is not disabled
for (let idx = index + 1; idx < this.columns.length; idx++) {
const sibling = this.getColumnInstance(idx);
if (!sibling || !sibling.disabled) {
return idx;
}
}
return null;
}
/** Get the column class from our query list */
getColumnInstance(index) {
return this._columns ? this._columns.toArray()[index] : null;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ResizableTableService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ResizableTableService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ResizableTableService, decorators: [{
type: Injectable
}] });
export var ColumnUnit;
(function (ColumnUnit) {
ColumnUnit[ColumnUnit["Pixel"] = 0] = "Pixel";
ColumnUnit[ColumnUnit["Percentage"] = 1] = "Percentage";
})(ColumnUnit || (ColumnUnit = {}));
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzaXphYmxlLXRhYmxlLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy90YWJsZS90YWJsZS1jb2x1bW4tcmVzaXplL3RhYmxlLWNvbHVtbi1yZXNpemUtc3RhbmRhcmQvcmVzaXphYmxlLXRhYmxlLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBYSxNQUFNLGVBQWUsQ0FBQztBQUV0RCxPQUFPLEVBQUUseUJBQXlCLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQzs7QUFHaEcsTUFBTSxPQUFPLHFCQUFzQixTQUFRLHlCQUF5QjtJQURwRTs7UUFHSSxnREFBZ0Q7UUFDaEQsU0FBSSxHQUF1QixrQkFBa0IsQ0FBQyxRQUFRLENBQUM7S0FrTzFEO0lBN05HLG9DQUFvQztJQUNwQyxVQUFVLENBQUMsT0FBaUQ7UUFFeEQsNEJBQTRCO1FBQzVCLElBQUksQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFDO1FBRXhCLGtCQUFrQjtRQUNsQixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxlQUFlLEVBQUUsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUM7UUFFekYsaUNBQWlDO1FBQ2pDLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVuRCw2QkFBNkI7UUFDN0IsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLEVBQUU7WUFDbEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQkFDbkIsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxF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QWlCLENBQUMsS0FBYTtRQUNuQyxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUNqRSxDQUFDOytHQW5PUSxxQkFBcUI7bUhBQXJCLHFCQUFxQjs7NEZBQXJCLHFCQUFxQjtrQkFEakMsVUFBVTs7QUF3T1gsTUFBTSxDQUFOLElBQVksVUFHWDtBQUhELFdBQVksVUFBVTtJQUNsQiw2Q0FBSyxDQUFBO0lBQ0wsdURBQVUsQ0FBQTtBQUNkLENBQUMsRUFIVyxVQUFVLEtBQVYsVUFBVSxRQUdyQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUsIFF1ZXJ5TGlzdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgUmVzaXphYmxlVGFibGVDb2x1bW5Db21wb25lbnQgfSBmcm9tICcuLi9yZXNpemFibGUtdGFibGUtY29sdW1uLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBCYXNlUmVzaXphYmxlVGFibGVTZXJ2aWNlLCBSZXNpemFibGVUYWJsZVR5cGUgfSBmcm9tICcuLi9yZXNpemFibGUtdGFibGUtYmFzZS5zZXJ2aWNlJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIFJlc2l6YWJsZVRhYmxlU2VydmljZSBleHRlbmRzIEJhc2VSZXNpemFibGVUYWJsZVNlcnZpY2Uge1xuXG4gICAgLyoqIERlZmluZSB0aGUgdHlwZSBvZiByZXNpemluZyB3ZSBzaG91bGQgdXNlICovXG4gICAgdHlwZTogUmVzaXphYmxlVGFibGVUeXBlID0gUmVzaXphYmxlVGFibGVUeXBlLlN0YW5kYXJkO1xuXG4gICAgLyoqIFN0b3JlIHRoZSBRdWVyeUxpc3Qgb2YgY29sdW1ucyAqL1xuICAgIHByaXZhdGUgX2NvbHVtbnM6IFF1ZXJ5TGlzdDxSZXNpemFibGVUYWJsZUNvbHVtbkNvbXBvbmVudD47XG5cbiAgICAvKiogU3RvcmUgdGhlIHNpemUgb2YgZWFjaCBjb2x1bW4gKi9cbiAgICBzZXRDb2x1bW5zKGNvbHVtbnM6IFF1ZXJ5TGlzdDxSZXNpemFibGVUYWJsZUNvbHVtbkNvbXBvbmVudD4pOiB2b2lkIHtcblxuICAgICAgICAvLyBzdG9yZSB0aGUgY3VycmVudCBjb2x1bW5zXG4gICAgICAgIHRoaXMuX2NvbHVtbnMgPSBjb2x1bW5zO1xuXG4gICAgICAgIC8vIHN0b3JlIHRoZSBzaXplc1xuICAgICAgICB0aGlzLmNvbHVtbnMgPSBjb2x1bW5zLm1hcChjb2x1bW4gPT4gKGNvbHVtbi5nZXROYXR1cmFsV2lkdGgoKSAvIHRoaXMudGFibGVXaWR0aCkgKiAxMDApO1xuXG4gICAgICAgIC8vIGNoZWNrIGlmIHRoZXJlIGlzIGFueSBvdmVyZmxvd1xuICAgICAgICB0aGlzLmNvbHVtbnMgPSB0aGlzLmVuc3VyZU5vT3ZlcmZsb3codGhpcy5jb2x1bW5zKTtcblxuICAgICAgICAvLyBlbnN1cmUgYWxsIHRoZSBjb2x1bW5zIGZpdFxuICAgICAgICB0aGlzLl9jb2x1bW5zLmZvckVhY2goKGNvbHVtbiwgaWR4KSA9PiB7XG4gICAgICAgICAgICBpZiAoIWNvbHVtbi5kaXNhYmxlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMucmVzaXplQ29sdW1uKGlkeCwgMCwgZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBpbmRpY2F0ZSB3ZSBhcmUgbm93IGluaXRpYWxpc2VkXG4gICAgICAgIGlmICh0aGlzLmlzSW5pdGlhbGlzZWQkLnZhbHVlID09PSBmYWxzZSkge1xuICAgICAgICAgICAgdGhpcy5pc0luaXRpYWxpc2VkJC5uZXh0KHRydWUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIFNldCBhbGwgcmVzaXphYmxlIGNvbHVtbnMgdG8gdGhlIHNhbWUgd2lkdGggKi9cbiAgICBzZXRVbmlmb3JtV2lkdGhzKCk6IHZvaWQge1xuXG4gICAgICAgIC8vIHNldCBhbnkgZGlzYWJsZWQgY29sdW1ucyB0byB0aGVpciBzcGVjaWZpZWQgd2lkdGhcbiAgICAgICAgdGhpcy5jb2x1bW5zID0gdGhpcy5fY29sdW1ucy5tYXAoY29sdW1uID0+IGNvbHVtbi5kaXNhYmxlZCA/IChjb2x1bW4uZ2V0TmF0dXJhbFdpZHRoKCkgLyB0aGlzLnRhYmxlV2lkdGgpICogMTAwIDogMCk7XG5cbiAgICAgICAgLy8gY2hlY2sgdG8gc2VlIGlmIHdlJ3ZlIHJlYWNoZWQgMTAwJSBvZiB0aGUgdGFibGUgd2lkdGhcbiAgICAgICAgY29uc3QgdG90YWxXaWR0aCA9IHRoaXMuY29sdW1ucy5yZWR1Y2UoKHBhcnRpYWwsIGNvbHVtbldpZHRoKSA9PiBwYXJ0aWFsICsgY29sdW1uV2lkdGgpO1xuXG4gICAgICAgIGlmICh0b3RhbFdpZHRoID4gMTAwKSB7XG4gICAgICAgICAgICAvLyByZW1vdmUgb3ZlcmZsb3dcbiAgICAgICAgICAgIHRoaXMuY29sdW1ucyA9IHRoaXMuZW5zdXJlTm9PdmVyZmxvdyh0aGlzLmNvbHVtbnMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gZ2V0IHRoZSBsaXN0IG9mIHJlc2l6YWJsZSBjb2x1bW5zXG4gICAgICAgICAgICBjb25zdCByZXNpemFibGVDb2x1bW5zID0gdGhpcy5fY29sdW1ucy50b0FycmF5KCkuZmlsdGVyKGNvbHVtbiA9PiAhY29sdW1uLmRpc2FibGVkKTtcblxuICAgICAgICAgICAgLy8gd29yayBvdXQgd2hhdCB3ZSBuZWVkIHRvIGFkZCB0byBlYWNoIGNvbHVtbiB0byBtYWtlIHVwIHRoZSBmdWxsIHdpZHRoXG4gICAgICAgICAgICBjb25zdCBuZXdXaWR0aCA9ICgxMDAgLSB0b3RhbFdpZHRoKSAvIHJlc2l6YWJsZUNvbHVtbnMubGVuZ3RoO1xuXG4gICAgICAgICAgICAvLyBzZXQgdGhlIG5vbi1kaXNhYmxlZCBjb2x1bW5zIHRvIHRoZSBuZXcgd2lkdGhcbiAgICAgICAgICAgIHRoaXMuY29sdW1ucyA9IHRoaXMuX2NvbHVtbnMubWFwKChjb2x1bW4sIGlkeCkgPT4gY29sdW1uLmRpc2FibGVkID8gdGhpcy5jb2x1bW5zW2lkeF0gOiBuZXdXaWR0aCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBkbyB0aGUgcmVzaXppbmdcbiAgICAgICAgdGhpcy5fY29sdW1ucy5mb3JFYWNoKChjb2x1bW4sIGlkeCkgPT4ge1xuICAgICAgICAgICAgaWYgKCFjb2x1bW4uZGlzYWJsZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc2l6ZUNvbHVtbihpZHgsIDAsIGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICB9XG5cbiAgICBlbnN1cmVOb092ZXJmbG93KGNvbHVtbnM6IFJlYWRvbmx5QXJyYXk8bnVtYmVyPik6IFJlYWRvbmx5QXJyYXk8bnVtYmVyPiB7XG5cbiAgICAgICAgLy8gZ2V0IHRoZSB0b3RhbCB3aWR0aFxuICAgICAgICBjb25zdCB0b3RhbCA9IGNvbHVtbnMucmVkdWNlKCh3aWR0aCwgY29sdW1uKSA9PiB3aWR0aCArIGNvbHVtbik7XG5cbiAgICAgICAgLy8gaWYgd2UgaGF2ZSBubyBvdmVyZmxvdyB0aGVuIHdlIGRvbid0IG5lZWQgdG8gZG8gYW55dGhpbmdcbiAgICAgICAgaWYgKHRvdGFsIDw9IDEwMCkge1xuICAgICAgICAgICAgcmV0dXJuIGNvbHVtbnM7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBpZiB0aGVyZSBpcyBvdmVyZmxvdyBpZGVudGlmeSB3aGljaCBjb2x1bW5zIGNhbiBiZSByZXNpemVkXG4gICAgICAgIGNvbnN0IHZhcmlhYmxlQ29sdW1ucyA9IHRoaXMuX2NvbHVtbnMuZmlsdGVyKGNvbHVtbiA9PiAhY29sdW1uLmRpc2FibGVkICYmIHRoaXMuZ2V0Q29sdW1uV2lkdGgoY29sdW1uLmdldENlbGxJbmRleCgpLCBDb2x1bW5Vbml0LlBpeGVsLCBjb2x1bW5zKSA+IGNvbHVtbi5taW5XaWR0aCk7XG5cbiAgICAgICAgLy8gaWYgdGhlcmUgYXJlIG5vIGNvbHVtbnMgdGhhdCBjYW4gYmUgcmVzaXplZCB0aGVuIHN0b3AgaGVyZVxuICAgICAgICBpZiAodmFyaWFibGVDb2x1bW5zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIGNvbHVtbnM7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBkZXRlcm1pbmUgdGhlIHRvdGFsIHdpZHRoIG9mIHRoZSB2YXJpYWJsZSBjb2x1bW5zXG4gICAgICAgIGNvbnN0IHRvdGFsV2lkdGggPSB0aGlzLl9jb2x1bW5zLnJlZHVjZSgod2lkdGgsIGNvbHVtbikgPT4gd2lkdGggKyB0aGlzLmdldENvbHVtbldpZHRoKGNvbHVtbi5nZXRDZWxsSW5kZXgoKSwgQ29sdW1uVW5pdC5QaXhlbCwgY29sdW1ucyksIDApO1xuXG4gICAgICAgIC8vIGRldGVybWluZSB0byB0aGUgd2lkdGggb2YgYWxsIHRoZSB2YXJpYWJsZSBjb2x1bW5zXG4gICAgICAgIGNvbnN0IHZhcmlhYmxlQ29sdW1uc1dpZHRoID0gdmFyaWFibGVDb2x1bW5zLnJlZHVjZSgod2lkdGgsIGNvbHVtbikgPT4gd2lkdGggKyB0aGlzLmdldENvbHVtbldpZHRoKGNvbHVtbi5nZXRDZWxsSW5kZXgoKSwgQ29sdW1uVW5pdC5QaXhlbCwgY29sdW1ucyksIDApO1xuXG4gICAgICAgIC8vIGRldGVybWluZSBob3cgbXVjaCB0aGUgY29sdW1ucyBhcmUgY3VycmVudGx5IHRvbyBsYXJnZSAoaWdub3JpbmcgZml4ZWQgY29sdW1ucylcbiAgICAgICAgY29uc3QgdGFyZ2V0V2lkdGggPSB0aGlzLnRhYmxlV2lkdGggLSAodG90YWxXaWR0aCAtIHZhcmlhYmxlQ29sdW1uc1dpZHRoKTtcblxuICAgICAgICAvLyBkZXRlcm1pbmUgaG93IG11Y2ggd2UgbmVlZCB0byByZWR1Y2UgYSBjb2x1bW4gYnlcbiAgICAgICAgY29uc3QgZGlmZmVyZW5jZSA9IHZhcmlhYmxlQ29sdW1uc1dpZHRoIC0gdGFyZ2V0V2lkdGg7XG5cbiAgICAgICAgLy8gZmluZCB0aGUgY29sdW1uIHdpdGggdGhlIGxhcmdlc3Qgc2l6ZVxuICAgICAgICBjb25zdCB0YXJnZXQgPSB2YXJpYWJsZUNvbHVtbnMucmVkdWNlKCh3aWRlc3QsIGNvbHVtbikgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29sdW1uV2lkdGggPSB0aGlzLmdldENvbHVtbldpZHRoKGNvbHVtbi5nZXRDZWxsSW5kZXgoKSwgQ29sdW1uVW5pdC5QaXhlbCwgY29sdW1ucyk7XG4gICAgICAgICAgICBjb25zdCB3aWRlc3RXaWR0aCA9IHRoaXMuZ2V0Q29sdW1uV2lkdGgod2lkZXN0LmdldENlbGxJbmRleCgpLCBDb2x1bW5Vbml0LlBpeGVsLCBjb2x1bW5zKTtcblxuICAgICAgICAgICAgcmV0dXJuIGNvbHVtbldpZHRoID4gd2lkZXN0V2lkdGggPyBjb2x1bW4gOiB3aWRlc3Q7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIHBlcmZvcm0gdGhlIHJlc2l6ZVxuICAgICAgICBjb2x1bW5zID0gdGhpcy5zZXRDb2x1bW5XaWR0aCh0YXJnZXQuZ2V0Q2VsbEluZGV4KCksIHRoaXMuZ2V0Q29sdW1uV2lkdGgodGFyZ2V0LmdldENlbGxJbmRleCgpLCBDb2x1bW5Vbml0LlBpeGVsLCBjb2x1bW5zKSAtIGRpZmZlcmVuY2UsIENvbHVtblVuaXQuUGl4ZWwsIGNvbHVtbnMpO1xuXG4gICAgICAgIC8vIGNoZWNrIGlmIHdlIGFyZSBzdGlsbCBvdmVyIHRoZSBsaW1pdCAoYWxsb3cgc29tZSB2YXJpYW5jZSBmb3IgamF2YXNjcmlwdCBkb3VibGUgcHJlY2lzaW9uKVxuICAgICAgICBpZiAoY29sdW1ucy5yZWR1Y2UoKHdpZHRoLCBjb2x1bW4pID0+IHdpZHRoICsgY29sdW1uKSA+IDEwMC4wMSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZW5zdXJlTm9PdmVyZmxvdyhjb2x1bW5zKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBjb2x1bW5zO1xuICAgIH1cblxuICAgIC8qKiBBbGxvdyBzZXR0aW5nIHRoZSBjb2x1bW4gc2l6ZSBpbiBhbnkgdW5pdCAqL1xuICAgIHNldENvbHVtbldpZHRoKGluZGV4OiBudW1iZXIsIHZhbHVlOiBudW1iZXIsIHVuaXQ6IENvbHVtblVuaXQsIGNvbHVtbnM6IFJlYWRvbmx5QXJyYXk8bnVtYmVyPiA9IHRoaXMuY29sdW1ucyk6IFJlYWRvbmx5QXJyYXk8bnVtYmVyPiB7XG5cbiAgICAgICAgLy8gY3JlYXRlIGEgbmV3IGFycmF5IHNvIHdlIGtlZXAgdGhlIGluc3RhbmNlIGFycmF5IGltbXV0YWJsZVxuICAgICAgICBjb25zdCBzaXplcyA9IFsuLi5jb2x1bW5zXTtcblxuICAgICAgICBzd2l0Y2ggKHVuaXQpIHtcblxuICAgICAgICAgICAgY2FzZSBDb2x1bW5Vbml0LlBlcmNlbnRhZ2U6XG4gICAgICAgICAgICAgICAgc2l6ZXNbaW5kZXhdID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UgQ29sdW1uVW5pdC5QaXhlbDpcbiAgICAgICAgICAgICAgICBzaXplc1tpbmRleF0gPSAodmFsdWUgLyB0aGlzLnRhYmxlV2lkdGgpICogMTAwO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdXBkYXRlIHRoZSBpbnN0YW5jZSB2YXJpYWJsZVxuICAgICAgICByZXR1cm4gc2l6ZXM7XG4gICAgfVxuXG4gICAgLyoqIFJlc2l6ZSBhIGNvbHVtbiBieSBhIHNwZWNpZmljIHBpeGVsIGFtb3VudCAqL1xuICAgIHJlc2l6ZUNvbHVtbihpbmRleDogbnVtYmVyLCBkZWx0YTogbnVtYmVyLCBpc0RyYWdnaW5nOiBib29sZWFuID0gdHJ1ZSk6IHZvaWQge1xuXG4gICAgICAgIC8vIGdldCB0aGUgc2libGluZyBjb2x1bW4gdGhhdCB3aWxsIGFsc28gYmUgcmVzaXplZFxuICAgICAgICBjb25zdCBzaWJsaW5nID0gdGhpcy5nZXRTaWJsaW5nQ29sdW1uKGluZGV4KTtcblxuICAgICAgICAvLyBpZiB0aGVyZSBpcyBubyBzaWJsaW5nIHRoYXQgY2FuIGJlIHJlc2l6ZWQgdGhlbiBzdG9wIGhlcmVcbiAgICAgICAgaWYgKCFzaWJsaW5nKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjcmVhdGUgYSBuZXcgYXJyYXkgZm9yIHRoZSBzaXplc1xuICAgICAgICBsZXQgY29sdW1ucyA9IFsuLi50aGlzLmNvbHVtbnNdIGFzIG51bWJlcltdO1xuXG4gICAgICAgIC8vIHJlc2l6ZSB0aGUgY29sdW1uIHRvIHRoZSBkZXNpcmVkIHNpemVcbiAgICAgICAgY29sdW1ucyA9IHRoaXMuc2V0Q29sdW1uV2lkdGgoaW5kZXgsIE1hdGgucm91bmQodGhpcy5nZXRDb2x1bW5XaWR0aChpbmRleCwgQ29sdW1uVW5pdC5QaXhlbCkgKyBkZWx0YSksIENvbHVtblVuaXQuUGl4ZWwsIGNvbHVtbnMpIGFzIG51bWJlcltdO1xuICAgICAgICBjb2x1bW5zID0gdGhpcy5zZXRDb2x1bW5XaWR0aChzaWJsaW5nLCBNYXRoLnJvdW5kKHRoaXMuZ2V0Q29sdW1uV2lkdGgoc2libGluZywgQ29sdW1uVW5pdC5QaXhlbCkgLSBkZWx0YSksIENvbHVtblVuaXQuUGl4ZWwsIGNvbHVtbnMpIGFzIG51bWJlcltdO1xuXG4gICAgICAgIC8vIGlmIHRoZSBtb3ZlIGlzIG5vdCBwb3NzaWJsZSB0aGVuIHN0b3AgaGVyZVxuICAgICAgICBpZiAoIXRoaXMuaXNXaWR0aFZhbGlkKGluZGV4LCB0aGlzLmdldENvbHVtbldpZHRoKGluZGV4LCBDb2x1bW5Vbml0LlBpeGVsLCBjb2x1bW5zKSkgfHwgIXRoaXMuaXNXaWR0aFZhbGlkKHNpYmxpbmcsIHRoaXMuZ2V0Q29sdW1uV2lkdGgoc2libGluZywgQ29sdW1uVW5pdC5QaXhlbCwgY29sdW1ucykpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjaGVjayB0aGF0IHdlIGFkZCB1cCB0byBleGFjdGx5IDEwMCVcbiAgICAgICAgY29uc3QgdG90YWwgPSBjb2x1bW5zLnJlZHVjZSgoY291bnQsIGNvbHVtbikgPT4gY29sdW1uICsgY291bnQsIDApO1xuXG4gICAgICAgIC8vIGlmIHRoZSBjb2x1bW5zIHRvIG5vdCBhZGQgdG8gMTAwIGVuc3VyZSB3ZSBtYWtlIHRoZW1cbiAgICAgICAgaWYgKHRvdGFsICE9PSAxMDApIHtcblxuICAgICAgICAgICAgLy8gZ2V0IHRoZSBjb2x1bW4gd2l0aCBhIHZhcmlhYmxlIHdpZHRoXG4gICAgICAgICAgICBjb25zdCB0YXJnZXQgPSB0aGlzLmdldFZhcmlhYmxlQ29sdW1uKDEwMCAtIHRvdGFsKTtcblxuICAgICAgICAgICAgaWYgKHRhcmdldCAmJiAhaXNEcmFnZ2luZykge1xuICAgICAgICAgICAgICAgIGNvbHVtbnNbdGhpcy5fY29sdW1ucy50b0FycmF5KCkuaW5kZXhPZih0YXJnZXQpXSArPSAoMTAwIC0gdG90YWwpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb2x1bW5zW2luZGV4XSArPSAoMTAwIC0gdG90YWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gc3RvcmUgdGhlIG5ldyBzaXplc1xuICAgICAgICB0aGlzLmNvbHVtbnMgPSBjb2x1bW5zO1xuXG4gICAgICAgIC8vIGVtaXQgdGhlIHJlc2l6ZSBldmVudCBmb3IgZWFjaCBjb2x1bW5cbiAgICAgICAgdGhpcy5vblJlc2l6ZSQubmV4dCgpO1xuICAgIH1cblxuICAgIGdldFZhcmlhYmxlQ29sdW1uKGRlbHRhOiBudW1iZXIpOiBSZXNpemFibGVUYWJsZUNvbHVtbkNvbXBvbmVudCB8IG51bGwge1xuXG4gICAgICAgIC8vIGdldCBhbGwgdmFyaWFibGUgd2lkdGggY29sdW1ucyB0aGF0IGFyZSBub3QgZGlzYWJsZWRcbiAgICAgICAgY29uc3QgdmFyaWFibGVDb2x1bW5zID0gdGhpcy5fY29sdW1ucy5maWx0ZXIoY29sdW1uID0+ICFjb2x1bW4uaXNGaXhlZFdpZHRoICYmICFjb2x1bW4uZGlzYWJsZWQpO1xuXG4gICAgICAgIC8vIGZpbmQgb25lIHRoYXQgaXMgZ3JlYXRlciB0aGFuIGl0cyBtaW4gd2lkdGggYnkgZW5vdWdoXG4gICAgICAgIHJldHVybiB2YXJpYWJsZUNvbHVtbnMucmV2ZXJzZSgpLmZpbmQoY29sdW1uID0+IHRoaXMuZ2V0Q29sdW1uV2lkdGgoY29sdW1uLmdldENlbGxJbmRleCgpLCBDb2x1bW5Vbml0LlBpeGVsKSA+PSBjb2x1bW4ubWluV2lkdGggKyBkZWx0YSk7XG4gICAgfVxuXG4gICAgZ2V0Q29sdW1uKGluZGV4OiBudW1iZXIpOiBSZXNpemFibGVUYWJsZUNvbHVtbkNvbXBvbmVudCB8IG51bGwge1xuICAgICAgICByZXR1cm4gdGhpcy5fY29sdW1ucyA/IHRoaXMuX2NvbHVtbnMudG9BcnJheSgpW2luZGV4XSA6IG51bGw7XG4gICAgfVxuXG4gICAgZ2V0Q29sdW1uRGlzYWJsZWQoaW5kZXg6IG51bWJlcik6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRDb2x1bW4oaW5kZXgpID8gdGhpcy5nZXRDb2x1bW4oaW5kZXgpLmRpc2FibGVkIDogZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIGEgY29sdW1uIGlzIGFib3ZlIG9yIGJlbG93IGl0cyBtaW5pbXVtIHdpZHRoICovXG4gICAgcHJpdmF0ZSBpc1dpZHRoVmFsaWQoaW5kZXg6IG51bWJlciwgd2lkdGg6IG51bWJlcik6IGJvb2xlYW4ge1xuXG4gICAgICAgIC8vIGdldCB0aGUgY29sdW1uIGF0IGEgZ2l2ZW4gcG9zaXRpb25cbiAgICAgICAgY29uc3QgY29sdW1uID0gdGhpcy5nZXRDb2x1bW5JbnN0YW5jZShpbmRleCk7XG5cbiAgICAgICAgLy8gZGV0ZXJtaW5lIGlmIHRoZSBzcGVjaWZpZWQgd2lkdGggaXMgZ3JlYXRlciB0aGFuIHRoZSBtaW4gd2lkdGhcbiAgICAgICAgcmV0dXJuIGNvbHVtbiAmJiB3aWR0aCA+PSBjb2x1bW4ubWluV2lkdGg7XG4gICAgfVxuXG4gICAgLyoqIEdldCB0aGUgbmV4dCBjb2x1bW4gaW4gdGhlIHNlcXVlbmNlIG9mIGNvbHVtbnMgKi9cbiAgICBwcml2YXRlIGdldFNpYmxpbmdDb2x1bW4oaW5kZXg6IG51bWJlcik6IG51bWJlciB8IG51bGwge1xuXG4gICAgICAgIC8vIGZpbmQgdGhlIGZpcnN0IHNpYmxpbmcgdGhhdCBpcyBub3QgZGlzYWJsZWRcbiAgICAgICAgZm9yIChsZXQgaWR4ID0gaW5kZXggKyAxOyBpZHggPCB0aGlzLmNvbHVtbnMubGVuZ3RoOyBpZHgrKykge1xuXG4gICAgICAgICAgICBjb25zdCBzaWJsaW5nID0gdGhpcy5nZXRDb2x1bW5JbnN0YW5jZShpZHgpO1xuXG4gICAgICAgICAgICBpZiAoIXNpYmxpbmcgfHwgIXNpYmxpbmcuZGlzYWJsZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaWR4O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLyoqIEdldCB0aGUgY29sdW1uIGNsYXNzIGZyb20gb3VyIHF1ZXJ5IGxpc3QgKi9cbiAgICBwcml2YXRlIGdldENvbHVtbkluc3RhbmNlKGluZGV4OiBudW1iZXIpOiBSZXNpemFibGVUYWJsZUNvbHVtbkNvbXBvbmVudCB8IG51bGwge1xuICAgICAgICByZXR1cm4gdGhpcy5fY29sdW1ucyA/IHRoaXMuX2NvbHVtbnMudG9BcnJheSgpW2luZGV4XSA6IG51bGw7XG4gICAgfVxuXG59XG5cbmV4cG9ydCBlbnVtIENvbHVtblVuaXQge1xuICAgIFBpeGVsLFxuICAgIFBlcmNlbnRhZ2Vcbn0iXX0=