carbon-components-angular
Version:
Next generation components
693 lines • 77.7 kB
JavaScript
import { EventEmitter } from "@angular/core";
import { TableHeaderItem } from "./table-header-item.class";
import { TableItem } from "./table-item.class";
import { Subject } from "rxjs";
/**
* TableModel represents a data model for two-dimensional data. It's used for all things table
* (table component, table toolbar, pagination, etc)
*
* TableModel manages its internal data integrity very well if you use the provided helper
* functions for modifying rows and columns and assigning header and data in that order.
*
* It also provides direct access to the data so you can read and modify it.
* If you change the structure of the data (by directly pushing into the arrays or otherwise),
* keep in mind to keep the data structure intact.
*
* Header length and length of every line in the data should be equal.
*
* If they are not consistent, unexpected things will happen.
*
* Use the provided functions when in doubt.
*/
export class TableModel {
constructor() {
this.dataChange = new EventEmitter();
this.rowsSelectedChange = new EventEmitter();
this.rowsExpandedChange = new EventEmitter();
this.rowsExpandedAllChange = new EventEmitter();
this.rowsCollapsedAllChange = new EventEmitter();
/**
* Gets emitted when `selectAll` is called. Emits false if all rows are deselected and true if
* all rows are selected.
*/
this.selectAllChange = new Subject();
/**
* Contains information about selection state of rows in the table.
*/
this.rowsSelected = [];
/**
* Contains information about expanded state of rows in the table.
*/
this.rowsExpanded = [];
/**
* Contains information about initial index of rows in the table
*/
this.rowsIndices = [];
/**
* Contains information about the context of the row.
*
* It affects styling of the row to reflect the context.
*
* string can be one of `"success" | "warning" | "info" | "error" | ""` and it's
* empty or undefined by default
*/
this.rowsContext = [];
/**
* Contains class name(s) of the row.
*
* It affects styling of the row to reflect the appended class name(s).
*
* It's empty or undefined by default
*/
this.rowsClass = [];
/**
* Contains information about the header cells of the table.
*/
this.header = [];
/**
* Tracks the current page.
*/
this.currentPage = 1;
/**
* Length of page.
*/
this.pageLength = 10;
/**
* Set to true when there is no more data to load in the table
*/
this.isEnd = false;
/**
* Set to true when lazy loading to show loading indicator
*/
this.isLoading = false;
/**
* Used in `data`
*/
this._data = [[]];
/**
* The number of models instantiated, this is to make sure each table has a different
* model count for unique id generation.
*/
this.tableModelCount = 0;
this.tableModelCount = TableModel.COUNT++;
}
/**
* Sets data of the table.
*
* Make sure all rows are the same length to keep the column count accurate.
*/
set data(newData) {
if (!newData || (Array.isArray(newData) && newData.length === 0)) {
newData = [[]];
}
this._data = newData;
// init rowsSelected
this.rowsSelected = new Array(this._data.length).fill(false);
this.rowsExpanded = new Array(this._data.length).fill(false);
// init rows indices
this.rowsIndices = [...Array(this._data.length).keys()];
// init rowsContext
this.rowsContext = new Array(this._data.length);
// init rowsClass
this.rowsClass = new Array(this._data.length);
// only create a fresh header if necessary (header doesn't exist or differs in length)
if (this.header == null || (this.header.length !== this._data[0].length && this._data[0].length > 0)) {
let header = new Array();
for (let i = 0; i < this._data[0].length; i++) {
header.push(new TableHeaderItem());
}
this.header = header;
}
this.dataChange.emit();
}
/**
* Gets the full data.
*
* You can use it to alter individual `TableItem`s but if you need to change
* table structure, use `addRow()` and/or `addColumn()`
*/
get data() {
return this._data;
}
/**
* Manually set data length in case the data in the table doesn't
* correctly reflect all the data that table is to display.
*
* Example: if you have multiple pages of data that table will display
* but you're loading one at a time.
*
* Set to `null` to reset to default behavior.
*/
set totalDataLength(length) {
// if this function is called without a parameter we need to set to null to avoid having undefined != null
this._totalDataLength = isNaN(length) ? null : length;
}
/**
* Total length of data that table has access to, or the amount manually set
*/
get totalDataLength() {
// if manually set data length
if (this._totalDataLength !== null && this._totalDataLength >= 0) {
return this._totalDataLength;
}
// if empty dataset
if (this.data && this.data.length === 1 && this.data[0].length === 0) {
return 0;
}
return this.data.length;
}
/**
* Returns an id for the given column
*
* @param column the column to generate an id for
* @param row the row of the header to generate an id for
*/
getId(column, row = 0) {
return `table-header-${row}-${column}-${this.tableModelCount}`;
}
/**
* Returns the id of the header. Used to link the cells with headers (or headers with headers)
*
* @param column the column to start getting headers for
* @param colSpan the number of columns to get headers for (defaults to 1)
*/
getHeaderId(column, colSpan = 1) {
if (column === "select" || column === "expand") {
return this.getId(column);
}
let ids = [];
for (let i = column; i >= 0; i--) {
if (this.header[i]) {
for (let j = 0; j < colSpan; j++) {
ids.push(this.getId(i + j));
}
break;
}
}
return ids.join(" ");
}
/**
* Finds closest header by trying the `column` and then working its way to the left
*
* @param column the target column
*/
getHeader(column) {
if (!this.header) {
return null;
}
for (let i = column; i >= 0; i--) {
const headerCell = this.header[i];
if (headerCell) {
return headerCell;
}
}
return null;
}
/**
* Returns how many rows is currently selected
*/
selectedRowsCount() {
let count = 0;
if (this.rowsSelected) {
this.rowsSelected.forEach(rowSelected => {
if (rowSelected) {
count++;
}
});
}
return count;
}
/**
* Returns how many rows is currently expanded
*/
expandedRowsCount() {
let count = 0;
if (this.rowsExpanded) {
this.rowsExpanded.forEach(rowExpanded => {
if (rowExpanded) {
count++;
}
});
}
return count;
}
/**
* Returns `index`th row of the table.
*
* Negative index starts from the end. -1 being the last element.
*
* @param index
*/
row(index) {
return this.data[this.realRowIndex(index)];
}
/**
* Adds a row to the `index`th row or appends to table if index not provided.
*
* If row is shorter than other rows or not provided, it will be padded with
* empty `TableItem` elements.
*
* If row is longer than other rows, others will be extended to match so no data is lost.
*
* If called on an empty table with no parameters, it creates a 1x1 table.
*
* Negative index starts from the end. -1 being the last element.
*
* @param [row]
* @param [index]
*/
addRow(row, index) {
// if table empty create table with row
if (!this.data || this.data.length === 0 || this.data[0].length === 0) {
let newData = new Array();
newData.push(row ? row : [new TableItem()]); // row or one empty one column row
this.data = newData;
return;
}
let realRow = row;
const columnCount = this.data[0].length;
if (row == null) {
realRow = new Array();
for (let i = 0; i < columnCount; i++) {
realRow.push(new TableItem());
}
}
if (realRow.length < columnCount) {
// extend the length of realRow
const difference = columnCount - realRow.length;
for (let i = 0; i < difference; i++) {
realRow.push(new TableItem());
}
}
else if (realRow.length > columnCount) {
// extend the length of header
let difference = realRow.length - this.header.length;
for (let j = 0; j < difference; j++) {
this.header.push(new TableHeaderItem());
}
// extend the length of every other row
for (let i = 0; i < this.data.length; i++) {
let currentRow = this.data[i];
difference = realRow.length - currentRow.length;
for (let j = 0; j < difference; j++) {
currentRow.push(new TableItem());
}
}
}
if (index == null) {
this.data.push(realRow);
// update rowsSelected property for length
this.rowsSelected.push(false);
// update rowsExpanded property for length
this.rowsExpanded.push(false);
// update rowsContext property for length
this.rowsContext.push(undefined);
// update rowsClass property for length
this.rowsClass.push(undefined);
// update rowsIndices property for length
this.rowsIndices.push(this.data.length - 1);
}
else {
const ri = this.realRowIndex(index);
this.data.splice(ri, 0, realRow);
// update rowsSelected property for length
this.rowsSelected.splice(ri, 0, false);
// update rowsExpanded property for length
this.rowsExpanded.splice(ri, 0, false);
// update rowsContext property for length
this.rowsContext.splice(ri, 0, undefined);
// update rowsClass property for length
this.rowsClass.splice(ri, 0, undefined);
// update rowsIndices property for length
this.rowsIndices.splice(ri, 0, this.data.length - 1);
}
this.dataChange.emit();
}
/**
* Deletes `index`th row.
*
* Negative index starts from the end. -1 being the last element.
*
* @param index
*/
deleteRow(index) {
const rri = this.realRowIndex(index);
this.data.splice(rri, 1);
this.rowsSelected.splice(rri, 1);
this.rowsExpanded.splice(rri, 1);
this.rowsContext.splice(rri, 1);
this.rowsClass.splice(rri, 1);
const rowIndex = this.rowsIndices[rri];
this.rowsIndices.splice(rri, 1);
this.rowsIndices = this.rowsIndices.map((value) => (value > rowIndex) ? --value : value);
this.dataChange.emit();
}
/**
* Deletes all rows.
*/
deleteAllRows() {
this.data = [];
}
hasExpandableRows() {
return this.data.some(data => data.some(d => d && d.expandedData)); // checking for some in 2D array
}
/**
* Number of rows that can be expanded.
*
* @returns number
*/
expandableRowsCount() {
return this.data.reduce((counter, _, index) => {
counter = (this.isRowExpandable(index)) ? counter + 1 : counter;
return counter;
}, 0);
}
isRowExpandable(index) {
return this.data[index].some(d => d && d.expandedData);
}
isRowExpanded(index) {
return this.rowsExpanded[index];
}
getRowContext(index) {
return this.rowsContext[index];
}
/**
* Returns `index`th column of the table.
*
* Negative index starts from the end. -1 being the last element.
*
* @param index
*/
column(index) {
let column = new Array();
const ri = this.realColumnIndex(index);
const rc = this.data.length;
for (let i = 0; i < rc; i++) {
const row = this.data[i];
column.push(row[ri]);
}
return column;
}
/**
* Adds a column to the `index`th column or appends to table if index not provided.
*
* If column is shorter than other columns or not provided, it will be padded with
* empty `TableItem` elements.
*
* If column is longer than other columns, others will be extended to match so no data is lost.
*
* If called on an empty table with no parameters, it creates a 1x1 table.
*
* Negative index starts from the end. -1 being the last element.
*
* @param [column]
* @param [index]
*/
addColumn(column, index) {
// if table empty create table with row
if (!this.data || this.data.length === 0 || this.data[0].length === 0) {
let newData = new Array();
if (column == null) {
newData.push([new TableItem()]);
}
else {
for (let i = 0; i < column.length; i++) {
let item = column[i];
newData.push([item]);
}
}
this.data = newData;
return;
}
let rc = this.data.length; // row count
let ci = this.realColumnIndex(index);
// append missing rows
for (let i = 0; column != null && i < column.length - rc; i++) {
this.addRow();
}
rc = this.data.length;
if (index == null) {
// append to end
for (let i = 0; i < rc; i++) {
let row = this.data[i];
row.push(column == null || column[i] == null ? new TableItem() : column[i]);
}
// update header if not already set by user
if (this.header.length < this.data[0].length) {
this.header.push(new TableHeaderItem());
}
}
else {
if (index >= this.data[0].length) {
// if trying to append
ci++;
}
// insert
for (let i = 0; i < rc; i++) {
let row = this.data[i];
row.splice(ci, 0, column == null || column[i] == null ? new TableItem() : column[i]);
}
// update header if not already set by user
if (this.header.length < this.data[0].length) {
this.header.splice(ci, 0, new TableHeaderItem());
}
}
this.dataChange.emit();
}
/**
* Deletes `index`th column.
*
* Negative index starts from the end. -1 being the last element.
*
* @param index
*/
deleteColumn(index) {
const rci = this.realColumnIndex(index);
const rowCount = this.data.length;
for (let i = 0; i < rowCount; i++) {
this.data[i].splice(rci, 1);
}
// update header if not already set by user
if (this.header.length > this.data[0].length) {
this.header.splice(rci, 1);
}
this.dataChange.emit();
}
moveColumn(indexFrom, indexTo) {
const headerFrom = this.header[indexFrom];
this.addColumn(this.column(indexFrom), indexTo);
this.deleteColumn(indexFrom + (indexTo < indexFrom ? 1 : 0));
this.header[indexTo + (indexTo > indexFrom ? -1 : 0)] = headerFrom;
}
/**
* cycle through the three sort states
* @param index
*/
cycleSortState(index) {
// no sort provided so do the simple sort
switch (this.header[index].sortDirection) {
case "ASCENDING":
this.header[index].sortDirection = "DESCENDING";
break;
case "DESCENDING":
this.header[index].sortDirection = "NONE";
break;
default:
this.header[index].sortDirection = "ASCENDING";
break;
}
}
/**
* Sorts the data currently present in the model based on `compare()`
*
* Direction is set by `ascending` and `descending` properties of `TableHeaderItem`
* in `index`th column.
*
* @param index The column based on which it's sorting
*/
sort(index) {
this.pushRowStateToModelData();
const headerSorted = this.header[index].sorted;
// We only allow sorting by a single column, so reset sort state for all columns before specifying new sort state
this.header.forEach(column => column.sorted = false);
if (this.header[index].sortDirection === "NONE" && headerSorted) {
// Restore initial order of rows
const oldData = this._data;
this._data = [];
for (let i = 0; i < this.rowsIndices.length; i++) {
const ri = this.rowsIndices[i];
this._data[ri] = oldData[i];
}
}
else {
const descending = this.header[index].sortDirection === "DESCENDING" ? -1 : 1;
this.data.sort((a, b) => {
return descending * this.header[index].compare(a[index], b[index]);
});
this.header[index].sorted = true;
}
this.popRowStateFromModelData();
}
/**
* Appends `rowsSelected` and `rowsExpanded` info to model data.
*
* When sorting rows, do this first so information about row selection
* gets sorted with the other row info.
*
* Call `popRowSelectionFromModelData()` after sorting to make everything
* right with the world again.
*/
pushRowStateToModelData() {
for (let i = 0; i < this.data.length; i++) {
const rowSelectedMark = new TableItem();
rowSelectedMark.data = this.rowsSelected[i];
this.data[i].push(rowSelectedMark);
const rowExpandedMark = new TableItem();
rowExpandedMark.data = this.rowsExpanded[i];
this.data[i].push(rowExpandedMark);
const rowContext = new TableItem();
rowContext.data = this.rowsContext[i];
this.data[i].push(rowContext);
const rowClass = new TableItem();
rowClass.data = this.rowsClass[i];
this.data[i].push(rowClass);
const rowIndex = new TableItem();
rowIndex.data = this.rowsIndices[i];
this.data[i].push(rowIndex);
}
}
/**
* Restores `rowsSelected` from data pushed by `pushRowSelectionToModelData()`
*
* Call after sorting data (if you previously pushed to maintain selection order)
* to make everything right with the world again.
*/
popRowStateFromModelData() {
for (let i = 0; i < this.data.length; i++) {
this.rowsIndices[i] = this.data[i].pop().data;
this.rowsClass[i] = this.data[i].pop().data;
this.rowsContext[i] = this.data[i].pop().data;
this.rowsExpanded[i] = !!this.data[i].pop().data;
this.rowsSelected[i] = !!this.data[i].pop().data;
}
}
/**
* Checks if row is filtered out.
*
* @param index
* @returns true if any of the filters in header filters out the `index`th row
*/
isRowFiltered(index) {
const realIndex = this.realRowIndex(index);
return this.header.some((item, i) => item && item.filter(this.row(realIndex)[i]));
}
/**
* Select/deselect `index`th row based on value
*
* @param index index of the row to select
* @param value state to set the row to. Defaults to `true`
*/
selectRow(index, value = true) {
if (this.isRowDisabled(index)) {
return;
}
this.rowsSelected[index] = value;
this.rowsSelectedChange.emit(index);
}
/**
* Selects or deselects all rows in the model
*
* @param value state to set all rows to. Defaults to `true`
*/
selectAll(value = true) {
if (this.data.length >= 1 && this.data[0].length >= 1) {
for (let i = 0; i < this.rowsSelected.length; i++) {
this.selectRow(i, value);
}
}
this.selectAllChange.next(value);
}
isRowSelected(index) {
return this.rowsSelected[index];
}
/**
* Checks if row is disabled or not.
*/
isRowDisabled(index) {
const row = this.data[index];
return !!row.disabled;
}
/**
* Expands/Collapses `index`th row based on value
*
* @param index index of the row to expand or collapse
* @param value expanded state of the row. `true` is expanded and `false` is collapsed
*/
expandRow(index, value = true) {
this.rowsExpanded[index] = value;
this.rowsExpandedChange.emit(index);
}
/**
* Expands / collapses all rows
*
* @param value expanded state of the rows. `true` is expanded and `false` is collapsed
*/
expandAllRows(value = true) {
if (this.data.length > 0) {
for (let i = 0; i < this.data.length; i++) {
if (this.isRowExpandable(i)) {
this.rowsExpanded[i] = value;
}
}
if (value) {
this.rowsExpandedAllChange.emit();
}
else {
this.rowsCollapsedAllChange.emit();
}
}
}
/**
* Gets the true index of a row based on it's relative position.
* Like in Python, positive numbers start from the top and
* negative numbers start from the bottom.
*
* @param index
*/
realRowIndex(index) {
return this.realIndex(index, this.data.length);
}
/**
* Gets the true index of a column based on it's relative position.
* Like in Python, positive numbers start from the top and
* negative numbers start from the bottom.
*
* @param index
*/
realColumnIndex(index) {
return this.realIndex(index, this.data[0].length);
}
/**
* Generic function to calculate the real index of something.
* Used by `realRowIndex()` and `realColumnIndex()`
*
* @param index
* @param length
*/
realIndex(index, length) {
if (index == null) {
return length - 1;
}
else if (index >= 0) {
return index >= length ? length - 1 : index;
}
else {
return -index >= length ? 0 : length + index;
}
}
}
/**
* The number of models instantiated, used for (among other things) unique id generation
*/
TableModel.COUNT = 0;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUtbW9kZWwuY2xhc3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdGFibGUvdGFibGUtbW9kZWwuY2xhc3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUc3QyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDNUQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRS9DLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFJL0I7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFDSCxNQUFNLE9BQU8sVUFBVTtJQXdLdEI7UUEvSEEsZUFBVSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFDaEMsdUJBQWtCLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQztRQUNoRCx1QkFBa0IsR0FBRyxJQUFJLFlBQVksRUFBVSxDQUFDO1FBQ2hELDBCQUFxQixHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFDM0MsMkJBQXNCLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUM1Qzs7O1dBR0c7UUFDSCxvQkFBZSxHQUFHLElBQUksT0FBTyxFQUFXLENBQUM7UUFZekM7O1dBRUc7UUFDSCxpQkFBWSxHQUFjLEVBQUUsQ0FBQztRQUU3Qjs7V0FFRztRQUNILGlCQUFZLEdBQWMsRUFBRSxDQUFDO1FBRTdCOztXQUVHO1FBQ0gsZ0JBQVcsR0FBYSxFQUFFLENBQUM7UUFFM0I7Ozs7Ozs7V0FPRztRQUNILGdCQUFXLEdBQWEsRUFBRSxDQUFDO1FBRTNCOzs7Ozs7V0FNRztRQUNILGNBQVMsR0FBYSxFQUFFLENBQUM7UUFFekI7O1dBRUc7UUFDSCxXQUFNLEdBQXNCLEVBQUUsQ0FBQztRQUUvQjs7V0FFRztRQUNILGdCQUFXLEdBQUcsQ0FBQyxDQUFDO1FBRWhCOztXQUVHO1FBQ0gsZUFBVSxHQUFHLEVBQUUs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O0lBQ25ELENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDTyxTQUFTLENBQUMsS0FBYSxFQUFFLE1BQWM7UUFDaEQsSUFBSSxLQUFLLElBQUksSUFBSSxFQUFFO1lBQ2xCLE9BQU8sTUFBTSxHQUFHLENBQUMsQ0FBQztTQUNsQjthQUFNLElBQUksS0FBSyxJQUFJLENBQUMsRUFBRTtZQUN0QixPQUFPLEtBQUssSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztTQUM1QzthQUFNO1lBQ04sT0FBTyxDQUFDLEtBQUssSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQztTQUM3QztJQUNGLENBQUM7O0FBdHZCRDs7R0FFRztBQUNjLGdCQUFLLEdBQUcsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRXZlbnRFbWl0dGVyIH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcblxuaW1wb3J0IHsgUGFnaW5hdGlvbk1vZGVsIH0gZnJvbSBcImNhcmJvbi1jb21wb25lbnRzLWFuZ3VsYXIvcGFnaW5hdGlvblwiO1xuaW1wb3J0IHsgVGFibGVIZWFkZXJJdGVtIH0gZnJvbSBcIi4vdGFibGUtaGVhZGVyLWl0ZW0uY2xhc3NcIjtcbmltcG9ydCB7IFRhYmxlSXRlbSB9IGZyb20gXCIuL3RhYmxlLWl0ZW0uY2xhc3NcIjtcbmltcG9ydCB7IFRhYmxlUm93IH0gZnJvbSBcIi4vdGFibGUtcm93LmNsYXNzXCI7XG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSBcInJ4anNcIjtcblxuZXhwb3J0IHR5cGUgSGVhZGVyVHlwZSA9IG51bWJlciB8IFwic2VsZWN0XCIgfCBcImV4cGFuZFwiO1xuXG4vKipcbiAqIFRhYmxlTW9kZWwgcmVwcmVzZW50cyBhIGRhdGEgbW9kZWwgZm9yIHR3by1kaW1lbnNpb25hbCBkYXRhLiBJdCdzIHVzZWQgZm9yIGFsbCB0aGluZ3MgdGFibGVcbiAqICh0YWJsZSBjb21wb25lbnQsIHRhYmxlIHRvb2xiYXIsIHBhZ2luYXRpb24sIGV0YylcbiAqXG4gKiBUYWJsZU1vZGVsIG1hbmFnZXMgaXRzIGludGVybmFsIGRhdGEgaW50ZWdyaXR5IHZlcnkgd2VsbCBpZiB5b3UgdXNlIHRoZSBwcm92aWRlZCBoZWxwZXJcbiAqIGZ1bmN0aW9ucyBmb3IgbW9kaWZ5aW5nIHJvd3MgYW5kIGNvbHVtbnMgYW5kIGFzc2lnbmluZyBoZWFkZXIgYW5kIGRhdGEgaW4gdGhhdCBvcmRlci5cbiAqXG4gKiBJdCBhbHNvIHByb3ZpZGVzIGRpcmVjdCBhY2Nlc3MgdG8gdGhlIGRhdGEgc28geW91IGNhbiByZWFkIGFuZCBtb2RpZnkgaXQuXG4gKiBJZiB5b3UgY2hhbmdlIHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIGRhdGEgKGJ5IGRpcmVjdGx5IHB1c2hpbmcgaW50byB0aGUgYXJyYXlzIG9yIG90aGVyd2lzZSksXG4gKiBrZWVwIGluIG1pbmQgdG8ga2VlcCB0aGUgZGF0YSBzdHJ1Y3R1cmUgaW50YWN0LlxuICpcbiAqIEhlYWRlciBsZW5ndGggYW5kIGxlbmd0aCBvZiBldmVyeSBsaW5lIGluIHRoZSBkYXRhIHNob3VsZCBiZSBlcXVhbC5cbiAqXG4gKiBJZiB0aGV5IGFyZSBub3QgY29uc2lzdGVudCwgdW5leHBlY3RlZCB0aGluZ3Mgd2lsbCBoYXBwZW4uXG4gKlxuICogVXNlIHRoZSBwcm92aWRlZCBmdW5jdGlvbnMgd2hlbiBpbiBkb3VidC5cbiAqL1xuZXhwb3J0IGNsYXNzIFRhYmxlTW9kZWwgaW1wbGVtZW50cyBQYWdpbmF0aW9uTW9kZWwge1xuXHQvKipcblx0ICogVGhlIG51bWJlciBvZiBtb2RlbHMgaW5zdGFudGlhdGVkLCB1c2VkIGZvciAoYW1vbmcgb3RoZXIgdGhpbmdzKSB1bmlxdWUgaWQgZ2VuZXJhdGlvblxuXHQgKi9cblx0cHJvdGVjdGVkIHN0YXRpYyBDT1VOVCA9IDA7XG5cblx0LyoqXG5cdCAqIFNldHMgZGF0YSBvZiB0aGUgdGFibGUuXG5cdCAqXG5cdCAqIE1ha2Ugc3VyZSBhbGwgcm93cyBhcmUgdGhlIHNhbWUgbGVuZ3RoIHRvIGtlZXAgdGhlIGNvbHVtbiBjb3VudCBhY2N1cmF0ZS5cblx0ICovXG5cdHNldCBkYXRhKG5ld0RhdGE6IFRhYmxlSXRlbVtdW10pIHtcblx0XHRpZiAoIW5ld0RhdGEgfHwgKEFycmF5LmlzQXJyYXkobmV3RGF0YSkgJiYgbmV3RGF0YS5sZW5ndGggPT09IDApKSB7XG5cdFx0XHRuZXdEYXRhID0gW1tdXTtcblx0XHR9XG5cblx0XHR0aGlzLl9kYXRhID0gbmV3RGF0YTtcblxuXHRcdC8vIGluaXQgcm93c1NlbGVjdGVkXG5cdFx0dGhpcy5yb3dzU2VsZWN0ZWQgPSBuZXcgQXJyYXk8Ym9vbGVhbj4odGhpcy5fZGF0YS5sZW5ndGgpLmZpbGwoZmFsc2UpO1xuXHRcdHRoaXMucm93c0V4cGFuZGVkID0gbmV3IEFycmF5PGJvb2xlYW4+KHRoaXMuX2RhdGEubGVuZ3RoKS5maWxsKGZhbHNlKTtcblx0XHQvLyBpbml0IHJvd3MgaW5kaWNlc1xuXHRcdHRoaXMucm93c0luZGljZXMgPSBbLi4uQXJyYXkodGhpcy5fZGF0YS5sZW5ndGgpLmtleXMoKV07XG5cdFx0Ly8gaW5pdCByb3dzQ29udGV4dFxuXHRcdHRoaXMucm93c0NvbnRleHQgPSBuZXcgQXJyYXk8c3RyaW5nPih0aGlzLl9kYXRhLmxlbmd0aCk7XG5cblx0XHQvLyBpbml0IHJvd3NDbGFzc1xuXHRcdHRoaXMucm93c0NsYXNzID0gbmV3IEFycmF5PHN0cmluZz4odGhpcy5f