UNPKG

carbon-components-angular

Version:
290 lines 32.1 kB
/** * An abstract class that represents a cell in a table */ export class TableCellAdapter { } /** * An abstract class that represents a row in a table */ export class TableRowAdapter { } /** * An abstract representation of a table that provides * a standard interface to query 2d tables for cell and row information. */ export class TableAdapter { /** * The last accessible column in the table */ get lastColumnIndex() { return; } /** * The last accessible row in the table */ get lastRowIndex() { return; } /** * Returns a cell from the table * * @param row index of the row * @param column index of the column */ getCell(row, column) { return; } /** * Returns a row from the table * * @param column index of the column */ getColumn(column) { return; } /** * Returns a row from the table * * @param row index of the row */ getRow(row) { return; } /** * Finds the column index of a given cell * * @param cell the cell to search for */ findColumnIndex(cell) { return; } /** * Finds the row index of a given cell * * @param cell the cell to search for */ findRowIndex(cell) { return; } /** * Finds the row and column index of a given cell * * @param cell the cell to search for * @returns a tuple that follows the `[row, column]` convention */ findIndex(cell) { return; } } var TableDomSpanDirection; (function (TableDomSpanDirection) { TableDomSpanDirection["colSpan"] = "colSpan"; TableDomSpanDirection["rowSpan"] = "rowSpan"; })(TableDomSpanDirection || (TableDomSpanDirection = {})); /** * A concrete implementation of `TableAdapter` * * Provides standard and consistent access to table cells and rows */ export class TableDomAdapter { /** * `TableDomAdapter` works on a normal HTML table structure. * Custom tables that don't follow the standard structure should use a custom implementation of `TableAdapter`. * * The standard structure allows us to directly query rows for cells and indexes - though we do have to handle colspans specially. * * @param tableElement the root HTML table element. */ constructor(tableElement) { this.tableElement = tableElement; } /** * The last accessible column in the table */ get lastColumnIndex() { return this.getRealRowLength(this.tableElement.rows[0]); } /** * The last accessible row in the table */ get lastRowIndex() { return this.tableElement.rows.length - 1; } /** * Returns a cell from the table taking colspans in to account. * * @param row index of the row * @param column index of the column */ getCell(row, column) { const col = this.getColumn(column); return this.findCellInColumn(col, row).cell; } /** * Returns a column from the table, using the `id` and `headers` attributes * * See here for more detail these attributes: https://www.w3.org/TR/WCAG20-TECHS/H43.html * * @param column the index of the column */ getColumn(column) { const firstHeader = Array.from(this.tableElement.rows[0].cells); const { cell: header, realIndex: realColumnIndex } = this.findCellInRow(firstHeader, column); const linkedCells = []; for (let i = 1; i < this.tableElement.rows.length; i++) { const row = this.tableElement.rows[i]; // query for any cells that are linked to the given header id // `~=` matches values in space separated lists - so `[headers~='foo']` would match `headers="foo bar"` and `headers="foo"` // but not `headers="bar"` or `headers="bar baz"` const linkedRowCells = row.querySelectorAll(`[headers~='${header.id}']`); // if we have more than one cell, get the one that is closest to the column if (linkedRowCells.length > 1) { const { cell } = this.findCellInRow(Array.from(linkedRowCells), column - realColumnIndex); linkedCells.push(cell); } else if (linkedRowCells[0]) { linkedCells.push(linkedRowCells[0]); } } // return an empty array if we can't find any linked cells // returning anything else would be a lie if (!linkedCells) { return []; } return [header, ...linkedCells]; } /** * Returns a row from the table * * @param row index of the row */ getRow(row) { return this.tableElement.rows[row]; } /** * Finds the column index of a given cell * * @param cell the cell to search for */ findColumnIndex(cell) { const row = this.getRow(this.findRowIndex(cell)); if (!row) { return; } // if the cell has linked headers we can do a more accurate lookup if (cell && cell.headers) { const ids = cell.headers.split(" "); const headerRows = Array.from(this.tableElement.tHead.rows); const indexes = []; // start from the last row and work up for (const headerRow of headerRows.reverse()) { const headerCells = Array.from(headerRow.cells); const header = headerCells.find(headerCell => ids.includes(headerCell.id)); // if we have a matching header, find it's index (adjusting for colspans) if (header) { // this is borrowed from below let cellIndex = 0; for (const c of headerCells) { if (c === header) { break; } cellIndex += c.colSpan; } indexes.push(cellIndex); } } // sort the indexes largest to smallest to find the closest matching header index const firstIndex = indexes.sort((a, b) => b - a)[0]; // search the row for cells that share the header let similarCells = []; for (const id of ids) { // there's no selector that will match two space separated lists, // so we have to iterate through the ids and query the row for each const rowCells = Array.from(row.querySelectorAll(`[headers~='${id}']`)); for (const rowCell of rowCells) { // only keep one set of cells if (!similarCells.includes(rowCell)) { similarCells.push(rowCell); } } } // DOM order is not preserved, so we have to sort the row similarCells = similarCells.sort((a, b) => a.cellIndex - b.cellIndex); // return the header index plus any adjustment within that headers column return firstIndex + similarCells.indexOf(cell); } // fallback if the cell isn't linked to any headers let cellIndex = 0; for (const c of Array.from(row.cells)) { if (c === cell) { break; } cellIndex += c.colSpan; } return cellIndex; } /** * Finds the row index of a given cell * * @param cell the cell to search for */ findRowIndex(cell) { for (const row of Array.from(this.tableElement.rows)) { if (row.contains(cell)) { return row.rowIndex; } } } /** * Finds the row and column index of a given cell * * @param cell the cell to search for * @returns a tuple that follows the `[row, column]` convention */ findIndex(cell) { return [this.findRowIndex(cell), this.findColumnIndex(cell)]; } /** * Helper function that returns the "real" length of a row. * Only accurate with regard to colspans (though that's sufficient for it's uses here) * * TODO: Take rowSpan into account * * @param row the row to get the length of */ getRealRowLength(row) { // start at -1 since the colspans will sum to 1 index greater than the total return Array.from(row.cells).reduce((count, cell) => count + cell.colSpan, -1); } /** * Finds a cell and it's real index given an array of cells, a target index, and the spanning direction * * @param cells An array of cells to search * @param targetIndex The index we think the cell is located at * @param spanDirection The direction of the cell spans. Should be `"colSpan"` for a row and `"rowSpan"` for a column */ findCell(cells, targetIndex, spanDirection) { // rows/cols can have fewer total cells than the actual table // the model pretends all rows/cols behave the same (with col/row spans > 1 being N cells long) // this maps that view to the HTML view (col/row spans > 1 are one element, so the array is shorter) let realIndex = 0; // i is only used for iterating the cells for (let i = 0; i < targetIndex;) { // skip the next N cells i += cells[realIndex][spanDirection]; // don't bump realIndex if i now exceeds the cell we're shooting for if (i > targetIndex) { break; } // finally, increment realIndex (to keep it generally in step with i) realIndex++; } return { cell: cells[realIndex], realIndex }; } /** * Helper method around `findCell`, searches based on a row of cells * * @param row the row of elements to search * @param index the index of the element */ findCellInRow(row, index) { return this.findCell(row, index, TableDomSpanDirection.colSpan); } /** * Helper method around `findCell`, searches based on a column of cells * * @param col the column of elements to search * @param index the index of the element */ findCellInColumn(col, index) { return this.findCell(col, index, TableDomSpanDirection.rowSpan); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUtYWRhcHRlci5jbGFzcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90YWJsZS90YWJsZS1hZGFwdGVyLmNsYXNzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxPQUFnQixnQkFBZ0I7Q0FhckM7QUFFRDs7R0FFRztBQUNILE1BQU0sT0FBZ0IsZUFBZTtDQVNwQztBQUVEOzs7R0FHRztBQUNILE1BQU0sT0FBZ0IsWUFBWTtJQUNqQzs7T0FFRztJQUNILElBQVcsZUFBZSxLQUFhLE9BQU8sQ0FBQyxDQUFDO0lBRWhEOztPQUVHO0lBQ0gsSUFBVyxZQUFZLEtBQWEsT0FBTyxDQUFDLENBQUM7SUFFN0M7Ozs7O09BS0c7SUFDSCxPQUFPLENBQUMsR0FBVyxFQUFFLE1BQWMsSUFBc0IsT0FBTyxDQUFDLENBQUM7SUFFbEU7Ozs7T0FJRztJQUNILFNBQVMsQ0FBQyxNQUFjLElBQXdCLE9BQU8sQ0FBQyxDQUFDO0lBRXpEOzs7O09BSUc7SUFDSCxNQUFNLENBQUMsR0FBVyxJQUFxQixPQUFPLENBQUMsQ0FBQztJQUVoRDs7OztPQUlHO0lBQ0gsZUFBZSxDQUFDLElBQXNCLElBQVksT0FBTyxDQUFDLENBQUM7SUFFM0Q7Ozs7T0FJRztJQUNILFlBQVksQ0FBQyxJQUFzQixJQUFZLE9BQU8sQ0FBQyxDQUFDO0lBRXhEOzs7OztPQUtHO0lBQ0gsU0FBUyxDQUFDLElBQXNCLElBQXNCLE9BQU8sQ0FBQyxDQUFDO0NBQy9EO0FBRUQsSUFBSyxxQkFHSjtBQUhELFdBQUsscUJBQXFCO0lBQ3pCLDRDQUFtQixDQUFBO0lBQ25CLDRDQUFtQixDQUFBO0FBQ3BCLENBQUMsRUFISSxxQkFBcUIsS0FBckIscUJBQXFCLFFBR3pCO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sT0FBTyxlQUFlO0lBZTNCOzs7Ozs7O09BT0c7SUFDSCxZQUFtQixZQUE4QjtRQUE5QixpQkFBWSxHQUFaLFlBQVksQ0FBa0I7SUFBSSxDQUFDO0lBdEJ0RDs7T0FFRztJQUNILElBQVcsZUFBZTtRQUN6QixPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3pELENBQUM7SUFFRDs7T0FFRztJQUNILElBQVcsWUFBWTtRQUN0QixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQVlEOzs7OztPQUtHO0lBQ0gsT0FBTyxDQUFDLEdBQVcsRUFBRSxNQUFjO1FBQ2xDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFbkMsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUM3QyxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsU0FBUyxDQUFDLE1BQWM7UUFDdkIsTUFBTSxXQUFXLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUVoRSxNQUFNLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsZUFBZSxFQUFFLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxXQUFXLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFN0YsTUFBTSxXQUFXLEdBQTJCLEVBQUUsQ0FBQztRQUUvQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ3ZELE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3RDLDZEQUE2RDtZQUM3RCwySEFBMkg7WUFDM0gsaURBQWlEO1lBQ2pELE1BQU0sY0FBYyxHQUFxQyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsY0FBYyxNQUFNLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUMzRywyRUFBMkU7WUFDM0UsSUFBSSxjQUFjLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtnQkFDOUIsTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsRUFBRSxNQUFNLEdBQUcsZUFBZSxDQUFDLENBQUM7Z0JBQzFGLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7YUFDdkI7aUJBQU0sSUFBSSxjQUFjLENBQUMsQ0FBQyxDQUFDLEVBQUU7Z0JBQzdCLFdBQVcsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDcEM7U0FDRDtRQUVELDBEQUEwRDtRQUMxRCx5Q0FBeUM7UUFDekMsSUFBSSxDQUFDLFdBQVcsRUFBRTtZQUNqQixPQUFPLEVBQUUsQ0FBQztTQUNWO1FBRUQsT0FBTyxDQUFDLE1BQU0sRUFBRSxHQUFHLFdBQVcsQ0FBQyxDQUFDO0lBQ2pDLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsTUFBTSxDQUFDLEdBQVc7UUFDakIsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILGVBQWUsQ0FBQyxJQUEwQjtRQUN6QyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUNqRCxJQUFJLENBQUMsR0FBRyxFQUFFO1lBQ1QsT0FBTztTQUNQO1FBQ0Qsa0VBQWtFO1FBQ2xFLElBQUksSUFBSSxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDekIsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDcEMsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM1RCxNQUFNLE9BQU8sR0FBRyxFQUFFLENBQUM7WUFFbkIsc0NBQXNDO1lBQ3RDLEtBQUssTUFBTSxTQUFTLElBQUksVUFBVSxDQUFDLE9BQU8sRUFBRSxFQUFFO2dCQUM3QyxNQUFNLFdBQVcsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDaEQsTUFBTSxNQUFNLEdBQUcsV0FBVyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQzNFLHlFQUF5RTtnQkFDekUsSUFBSSxNQUFNLEVBQUU7b0JBQ1gsOEJBQThCO29CQUM5QixJQUFJLFNBQVMsR0FBRyxDQUFDLENBQUM7b0JBQ2xCLEtBQUssTUFBTSxDQUFDLElBQUksV0FBVyxFQUFFO3dCQUM1QixJQUFJLENBQUMsS0FBSyxNQUFNLEVBQUU7NEJBQUUsTUFBTTt5QkFBRTt3QkFDNUIsU0FBUyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUM7cUJBQ3ZCO29CQUNELE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7aUJBQ3hCO2FBQ0Q7WUFFRCxpRkFBaUY7WUFDakYsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUVwRCxpREFBaUQ7WUFDakQsSUFBSSxZQUFZLEdBQUcsRUFBRSxDQUFDO1lBQ3RCLEtBQUssTUFBTSxFQUFFLElBQUksR0FBRyxFQUFFO2dCQUNyQixpRUFBaUU7Z0JBQ2pFLG1FQUFtRTtnQkFDbkUsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsY0FBYyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7Z0JBQ3hFLEtBQUssTUFBTSxPQUFPLElBQUksUUFBUSxFQUFFO29CQUMvQiw2QkFBNkI7b0JBQzdCLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFO3dCQUNwQyxZQUFZLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO3FCQUMzQjtpQkFDRDthQUNEO1lBRUQseURBQXlEO1lBQ3pELFlBQVksR0FBRyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBdUIsRUFBRSxDQUF1QixFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUVsSCx5RUFBeUU7WUFDekUsT0FBTyxVQUFVLEdBQUcsWUFBWSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUMvQztRQUVELG1EQUFtRDtRQUNuRCxJQUFJLFNBQVMsR0FBRyxDQUFDLENBQUM7UUFDbEIsS0FBSyxNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRTtZQUN0QyxJQUFJLENBQUMsS0FBSyxJQUFJLEVBQUU7Z0JBQUUsTUFBTTthQUFFO1lBQzFCLFNBQVMsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDO1NBQ3ZCO1FBQ0QsT0FBTyxTQUFTLENBQUM7SUFDbEIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxZQUFZLENBQUMsSUFBMEI7UUFDdEMsS0FBSyxNQUFNLEdBQUcsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDckQsSUFBSSxHQUFHLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFO2dCQUN2QixPQUFPLEdBQUcsQ0FBQyxRQUFRLENBQUM7YUFDcEI7U0FDRDtJQUNGLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILFNBQVMsQ0FBQyxJQUEwQjtRQUNuQyxPQUFPLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDOUQsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDTyxnQkFBZ0IsQ0FBQyxHQUF3QjtRQUNsRCw0RUFBNEU7UUFDNUUsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2hGLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDTyxRQUFRLENBQUMsS0FBNkIsRUFBRSxXQUFtQixFQUFFLGFBQW9DO1FBQzFHLDZEQUE2RDtRQUM3RCwrRkFBK0Y7UUFDL0Ysb0dBQW9HO1FBQ3BHLElBQUksU0FBUyxHQUFHLENBQUMsQ0FBQztRQUNsQix5Q0FBeUM7UUFDekMsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFdBQVcsR0FBRztZQUNqQyx3QkFBd0I7WUFDeEIsQ0FBQyxJQUFJLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUNyQyxvRUFBb0U7WUFDcEUsSUFBSSxDQUFDLEdBQUcsV0FBVyxFQUFFO2dCQUFFLE1BQU07YUFBRTtZQUMvQixxRUFBcUU7WUFDckUsU0FBUyxFQUFFLENBQUM7U0FDWjtRQUVELE9BQU87WUFDTixJQUFJLEVBQUUsS0FBSyxDQUFDLFNBQVMsQ0FBQztZQUN0QixTQUFTO1NBQ1QsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7T0FLRztJQUNPLGFBQWEsQ0FBQyxHQUEyQixFQUFFLEtBQWE7UUFDakUsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUscUJBQXFCLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDakUsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ08sZ0JBQWdCLENBQUMsR0FBMkIsRUFBRSxLQUFhO1FBQ3BFLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLHFCQUFxQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ2pFLENBQUM7Q0FDRCIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQW4gYWJzdHJhY3QgY2xhc3MgdGhhdCByZXByZXNlbnRzIGEgY2VsbCBpbiBhIHRhYmxlXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBUYWJsZUNlbGxBZGFwdGVyIHtcblx0LyoqXG5cdCAqIFRoZSBpbmRleCBvZiB0aGUgY2VsbCBpbiB0aGUgdGFibGVcblx0ICovXG5cdGNlbGxJbmRleDogbnVtYmVyO1xuXHQvKipcblx0ICogVGhlIG51bWJlciBvZiBjb2x1bW5zIHNwYW5uZWQgYnkgdGhpcyBjZWxsXG5cdCAqL1xuXHRjb2xTcGFuOiBudW1iZXI7XG5cdC8qKlxuXHQgKiBUaGUgbnVtYmVyIG9mIHJvd3Mgc3Bhbm5lZCBieSB0aGlzIGNlbGxcblx0ICovXG5cdHJvd1NwYW46IG51bWJlcjtcbn1cblxuLyoqXG4gKiBBbiBhYnN0cmFjdCBjbGFzcyB0aGF0IHJlcHJlc2VudHMgYSByb3cgaW4gYSB0YWJsZVxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgVGFibGVSb3dBZGFwdGVyIHtcblx0LyoqXG5cdCAqIFRoZSBpbmRleCBvZiB0aGUgcm93IGluIHRoZSB0YWJsZVxuXHQgKi9cblx0cm93SW5kZXg6IG51bWJlcjtcblx0LyoqXG5cdCAqIEFuIGFycmF5IChvciBgSFRNTENvbGxlY3Rpb25gKSBvZiBgVGFibGVDZWxsQWRhcHRlcmBzXG5cdCAqL1xuXHRjZWxsczogSFRNTENvbGxlY3Rpb24gfCBUYWJsZUNlbGxBZGFwdGVyW107XG59XG5cbi8qKlxuICogQW4gYWJzdHJhY3QgcmVwcmVzZW50YXRpb24gb2YgYSB0YWJsZSB0aGF0IHByb3ZpZGVzXG4gKiBhIHN0YW5kYXJkIGludGVyZmFjZSB0byBxdWVyeSAyZCB0YWJsZXMgZm9yIGNlbGwgYW5kIHJvdyBpbmZvcm1hdGlvbi5cbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFRhYmxlQWRhcHRlciB7XG5cdC8qKlxuXHQgKiBUaGUgbGFzdCBhY2Nlc3NpYmxlIGNvbHVtbiBpbiB0aGUgdGFibGVcblx0ICovXG5cdHB1YmxpYyBnZXQgbGFzdENvbHVtbkluZGV4KCk6IG51bWJlciB7IHJldHVybjsgfVxuXG5cdC8qKlxuXHQgKiBUaGUgbGFzdCBhY2Nlc3NpYmxlIHJvdyBpbiB0aGUgdGFibGVcblx0ICovXG5cdHB1YmxpYyBnZXQgbGFzdFJvd0luZGV4KCk6IG51bWJlciB7IHJldHVybjsgfVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGEgY2VsbCBmcm9tIHRoZSB0YWJsZVxuXHQgKlxuXHQgKiBAcGFyYW0gcm93IGluZGV4IG9mIHRoZSByb3dcblx0ICogQHBhcmFtIGNvbHVtbiBpbmRleCBvZiB0aGUgY29sdW1uXG5cdCAqL1xuXHRnZXRDZWxsKHJvdzogbnVtYmVyLCBjb2x1bW46IG51bWJlcik6IFRhYmxlQ2VsbEFkYXB0ZXIgeyByZXR1cm47IH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhIHJvdyBmcm9tIHRoZSB0YWJsZVxuXHQgKlxuXHQgKiBAcGFyYW0gY29sdW1uIGluZGV4IG9mIHRoZSBjb2x1bW5cblx0ICovXG5cdGdldENvbHVtbihjb2x1bW46IG51bWJlcik6IFRhYmxlQ2VsbEFkYXB0ZXJbXSB7IHJldHVybjsgfVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGEgcm93IGZyb20gdGhlIHRhYmxlXG5cdCAqXG5cdCAqIEBwYXJhbSByb3cgaW5kZXggb2YgdGhlIHJvd1xuXHQgKi9cblx0Z2V0Um93KHJvdzogbnVtYmVyKTogVGFibGVSb3dBZGFwdGVyIHsgcmV0dXJuOyB9XG5cblx0LyoqXG5cdCAqIEZpbmRzIHRoZSBjb2x1bW4gaW5kZXggb2YgYSBnaXZlbiBjZWxsXG5cdCAqXG5cdCAqIEBwYXJhbSBjZWxsIHRoZSBjZWxsIHRvIHNlYXJjaCBmb3Jcblx0ICovXG5cdGZpbmRDb2x1bW5JbmRleChjZWxsOiBUYWJsZUNlbGxBZGFwdGVyKTogbnVtYmVyIHsgcmV0dXJuOyB9XG5cblx0LyoqXG5cdCAqIEZpbmRzIHRoZSByb3cgaW5kZXggb2YgYSBnaXZlbiBjZWxsXG5cdCAqXG5cdCAqIEBwYXJhbSBjZWxsIHRoZSBjZWxsIHRvIHNlYXJjaCBmb3Jcblx0ICovXG5cdGZpbmRSb3dJbmRleChjZWxsOiBUYWJsZUNlbGxBZGFwdGVyKTogbnVtYmVyIHsgcmV0dXJuOyB9XG5cblx0LyoqXG5cdCAqIEZpbmRzIHRoZSByb3cgYW5kIGNvbHVtbiBpbmRleCBvZiBhIGdpdmVuIGNlbGxcblx0ICpcblx0ICogQHBhcmFtIGNlbGwgdGhlIGNlbGwgdG8gc2VhcmNoIGZvclxuXHQgKiBAcmV0dXJucyBhIHR1cGxlIHRoYXQgZm9sbG93cyB0aGUgYFtyb3csIGNvbHVtbl1gIGNvbnZlbnRpb25cblx0ICovXG5cdGZpbmRJbmRleChjZWxsOiBUYWJsZUNlbGxBZGFwdGVyKTogW251bWJlciwgbnVtYmVyXSB7IHJldHVybjsgfVxufVxuXG5lbnVtIFRhYmxlRG9tU3BhbkRpcmVjdGlvbiB7XG5cdGNvbFNwYW4gPSBcImNvbFNwYW5cIixcblx0cm93U3BhbiA9IFwicm93U3BhblwiXG59XG5cbi8qKlxuICogQSBjb25jcmV0ZSBpbXBsZW1lbnRhdGlvbiBvZiBgVGFibGVBZGFwdGVyYFxuICpcbiAqIFByb3ZpZGVzIHN0YW5kYXJkIGFuZCBjb25zaXN0ZW50IGFjY2VzcyB0byB0YWJsZSBjZWxscyBhbmQgcm93c1xuICovXG5leHBvcnQgY2xhc3MgVGFibGVEb21BZGFwdGVyIGltcGxlbWVudHMgVGFibGVBZGFwdGVyIHtcblx0LyoqXG5cdCAqIFRoZSBsYXN0IGFjY2Vzc2libGUgY29sdW1uIGluIHRoZSB0YWJsZVxuXHQgKi9cblx0cHVibGljIGdldCBsYXN0Q29sdW1uSW5kZXgoKSB7XG5cdFx0cmV0dXJuIHRoaXMuZ2V0UmVhbFJvd0xlbmd0aCh0aGlzLnRhYmxlRWxlbWVudC5yb3dzWzBdKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBUaGUgbGFzdCBhY2Nlc3NpYmxlIHJvdyBpbiB0aGUgdGFibGVcblx0ICovXG5cdHB1YmxpYyBnZXQgbGFzdFJvd0luZGV4KCkge1xuXHRcdHJldHVybiB0aGlzLnRhYmxlRWxlbWVudC5yb3dzLmxlbmd0aCAtIDE7XG5cdH1cblxuXHQvKipcblx0ICogYFRhYmxlRG9tQWRhcHRlcmAgd29ya3Mgb24gYSBub3JtYWwgSFRNTCB0YWJsZSBzdHJ1Y3R1cmUuXG5cdCAqIEN1c3RvbSB0YWJsZXMgdGhhdCBkb24ndCBmb2xsb3cgdGhlIHN0YW5kYXJkIHN0cnVjdHVyZSBzaG91bGQgdXNlIGEgY3VzdG9tIGltcGxlbWVudGF0aW9uIG9mIGBUYWJsZUFkYXB0ZXJgLlxuXHQgKlxuXHQgKiBUaGUgc3RhbmRhcmQgc3RydWN0dXJlIGFsbG93cyB1cyB0byBkaXJlY3RseSBxdWVyeSByb3dzIGZvciBjZWxscyBhbmQgaW5kZXhlcyAtIHRob3VnaCB3ZSBkbyBoYXZlIHRvIGhhbmRsZSBjb2xzcGFucyBzcGVjaWFsbHkuXG5cdCAqXG5cdCAqIEBwYXJhbSB0YWJsZUVsZW1lbnQgdGhlIHJvb3QgSFRNTCB0YWJsZSBlbGVtZW50LlxuXHQgKi9cblx0Y29uc3RydWN0b3IocHVibGljIHRhYmxlRWxlbWVudDogSFRNTFRhYmxlRWxlbWVudCkgeyB9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgYSBjZWxsIGZyb20gdGhlIHRhYmxlIHRha2luZyBjb2xzcGFucyBpbiB0byBhY2NvdW50LlxuXHQgKlxuXHQgKiBAcGFyYW0gcm93IGluZGV4IG9mIHRoZSByb3dcblx0ICogQHBhcmFtIGNvbHVtbiBpbmRleCBvZiB0aGUgY29sdW1uXG5cdCAqL1xuXHRnZXRDZWxsKHJvdzogbnVtYmVyLCBjb2x1bW46IG51bWJlcik6IEhUTUxUYWJsZUNlbGxFbGVtZW50IHtcblx0XHRjb25zdCBjb2wgPSB0aGlzLmdldENvbHVtbihjb2x1bW4pO1xuXG5cdFx0cmV0dXJuIHRoaXMuZmluZENlbGxJbkNvbHVtbihjb2wsIHJvdykuY2VsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGEgY29sdW1uIGZyb20gdGhlIHRhYmxlLCB1c2luZyB0aGUgYGlkYCBhbmQgYGhlYWRlcnNgIGF0dHJpYnV0ZXNcblx0ICpcblx0ICogU2VlIGhlcmUgZm9yIG1vcmUgZGV0YWlsIHRoZXNlIGF0dHJpYnV0ZXM6IGh0dHBzOi8vd3d3LnczLm9yZy9UUi9XQ0FHMjAtVEVDSFMvSDQzLmh0bWxcblx0ICpcblx0ICogQHBhcmFtIGNvbHVtbiB0aGUgaW5kZXggb2YgdGhlIGNvbHVtblxuXHQgKi9cblx0Z2V0Q29sdW1uKGNvbHVtbjogbnVtYmVyKTogSFRNTFRhYmxlQ2VsbEVsZW1lbnRbXSB7XG5cdFx0Y29uc3QgZmlyc3RIZWFkZXIgPSBBcnJheS5mcm9tKHRoaXMudGFibGVFbGVtZW50LnJvd3NbMF0uY2VsbHMpO1xuXG5cdFx0Y29uc3QgeyBjZWxsOiBoZWFkZXIsIHJlYWxJbmRleDogcmVhbENvbHVtbkluZGV4IH0gPSB0aGlzLmZpbmRDZWxsSW5Sb3coZmlyc3RIZWFkZXIsIGNvbHVtbik7XG5cblx0XHRjb25zdCBsaW5rZWRDZWxsczogSFRNTFRhYmxlQ2VsbEVsZW1lbnRbXSA9IFtdO1xuXG5cdFx0Zm9yIChsZXQgaSA9IDE7IGkgPCB0aGlzLnRhYmxlRWxlbWVudC5yb3dzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRjb25zdCByb3cgPSB0aGlzLnRhYmxlRWxlbWVudC5yb3dzW2ldO1xuXHRcdFx0Ly8gcXVlcnkgZm9yIGFueSBjZWxscyB0aGF0IGFyZSBsaW5rZWQgdG8gdGhlIGdpdmVuIGhlYWRlciBpZFxuXHRcdFx0Ly8gYH49YCBtYXRjaGVzIHZhbHVlcyBpbiBzcGFjZSBzZXBhcmF0ZWQgbGlzdHMgLSBzbyBgW2hlYWRlcnN+PSdmb28nXWAgd291bGQgbWF0Y2ggYGhlYWRlcnM9XCJmb28gYmFyXCJgIGFuZCBgaGVhZGVycz1cImZvb1wiYFxuXHRcdFx0Ly8gYnV0IG5vdCBgaGVhZGVycz1cImJhclwiYCBvciBgaGVhZGVycz1cImJhciBiYXpcImBcblx0XHRcdGNvbnN0IGxpbmtlZFJvd0NlbGxzOiBOb2RlTGlzdE9mPEhUTUxUYWJsZUNlbGxFbGVtZW50PiA9IHJvdy5xdWVyeVNlbGVjdG9yQWxsKGBbaGVhZGVyc349JyR7aGVhZGVyLmlkfSddYCk7XG5cdFx0XHQvLyBpZiB3ZSBoYXZlIG1vcmUgdGhhbiBvbmUgY2VsbCwgZ2V0IHRoZSBvbmUgdGhhdCBpcyBjbG9zZXN0IHRvIHRoZSBjb2x1bW5cblx0XHRcdGlmIChsaW5rZWRSb3dDZWxscy5sZW5ndGggPiAxKSB7XG5cdFx0XHRcdGNvbnN0IHsgY2VsbCB9ID0gdGhpcy5maW5kQ2VsbEluUm93KEFycmF5LmZyb20obGlua2VkUm93Q2VsbHMpLCBjb2x1bW4gLSByZWFsQ29sdW1uSW5kZXgpO1xuXHRcdFx0XHRsaW5rZWRDZWxscy5wdXNoKGNlbGwpO1xuXHRcdFx0fSBlbHNlIGlmIChsaW5rZWRSb3dDZWxsc1swXSkge1xuXHRcdFx0XHRsaW5rZWRDZWxscy5wdXNoKGxpbmtlZFJvd0NlbGxzWzBdKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyByZXR1cm4gYW4gZW1wdHkgYXJyYXkgaWYgd2UgY2FuJ3QgZmluZCBhbnkgbGlua2VkIGNlbGxzXG5cdFx0Ly8gcmV0dXJuaW5nIGFueXRoaW5nIGVsc2Ugd291bGQgYmUgYSBsaWVcblx0XHRpZiAoIWxpbmtlZENlbGxzKSB7XG5cdFx0XHRyZXR1cm4gW107XG5cdFx0fVxuXG5cdFx0cmV0dXJuIFtoZWFkZXIsIC4uLmxpbmtlZENlbGxzXTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGEgcm93IGZyb20gdGhlIHRhYmxlXG5cdCAqXG5cdCAqIEBwYXJhbSByb3cgaW5kZXggb2YgdGhlIHJvd1xuXHQgKi9cblx0Z2V0Um93KHJvdzogbnVtYmVyKTogSFRNTFRhYmxlUm93RWxlbWVudCB7XG5cdFx0cmV0dXJuIHRoaXMudGFibGVFbGVtZW50LnJvd3Nbcm93XTtcblx0fVxuXG5cdC8qKlxuXHQgKiBGaW5kcyB0aGUgY29sdW1uIGluZGV4IG9mIGEgZ2l2ZW4gY2VsbFxuXHQgKlxuXHQgKiBAcGFyYW0gY2VsbCB0aGUgY2VsbCB0byBzZWFyY2ggZm9yXG5cdCAqL1xuXHRmaW5kQ29sdW1uSW5kZXgoY2VsbDogSFRNTFRhYmxlQ2VsbEVsZW1lbnQpOiBudW1iZXIge1xuXHRcdGNvbnN0IHJvdyA9IHRoaXMuZ2V0Um93KHRoaXMuZmluZFJvd0luZGV4KGNlbGwpKTtcblx0XHRpZiAoIXJvdykge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHQvLyBpZiB0aGUgY2VsbCBoYXMgbGlua2VkIGhlYWRlcnMgd2UgY2FuIGRvIGEgbW9yZSBhY2N1cmF0ZSBsb29rdXBcblx0XHRpZiAoY2VsbCAmJiBjZWxsLmhlYWRlcnMpIHtcblx0XHRcdGNvbnN0IGlkcyA9IGNlbGwuaGVhZGVycy5zcGxpdChcIiBcIik7XG5cdFx0XHRjb25zdCBoZWFkZXJSb3dzID0gQXJyYXkuZnJvbSh0aGlzLnRhYmxlRWxlbWVudC50SGVhZC5yb3dzKTtcblx0XHRcdGNvbnN0IGluZGV4ZXMgPSBbXTtcblxuXHRcdFx0Ly8gc3RhcnQgZnJvbSB0aGUgbGFzdCByb3cgYW5kIHdvcmsgdXBcblx0XHRcdGZvciAoY29uc3QgaGVhZGVyUm93IG9mIGhlYWRlclJvd3MucmV2ZXJzZSgpKSB7XG5cdFx0XHRcdGNvbnN0IGhlYWRlckNlbGxzID0gQXJyYXkuZnJvbShoZWFkZXJSb3cuY2VsbHMpO1xuXHRcdFx0XHRjb25zdCBoZWFkZXIgPSBoZWFkZXJDZWxscy5maW5kKGhlYWRlckNlbGwgPT4gaWRzLmluY2x1ZGVzKGhlYWRlckNlbGwuaWQpKTtcblx0XHRcdFx0Ly8gaWYgd2UgaGF2ZSBhIG1hdGNoaW5nIGhlYWRlciwgZmluZCBpdCdzIGluZGV4IChhZGp1c3RpbmcgZm9yIGNvbHNwYW5zKVxuXHRcdFx0XHRpZiAoaGVhZGVyKSB7XG5cdFx0XHRcdFx0Ly8gdGhpcyBpcyBib3Jyb3dlZCBmcm9tIGJlbG93XG5cdFx0XHRcdFx0bGV0IGNlbGxJbmRleCA9IDA7XG5cdFx0XHRcdFx0Zm9yIChjb25zdCBjIG9mIGhlYWRlckNlbGxzKSB7XG5cdFx0XHRcdFx0XHRpZiAoYyA9PT0gaGVhZGVyKSB7IGJyZWFrOyB9XG5cdFx0XHRcdFx0XHRjZWxsSW5kZXggKz0gYy5jb2xTcGFuO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRpbmRleGVzLnB1c2goY2VsbEluZGV4KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBzb3J0IHRoZSBpbmRleGVzIGxhcmdlc3QgdG8gc21hbGxlc3QgdG8gZmluZCB0aGUgY2xvc2VzdCBtYXRjaGluZyBoZWFkZXIgaW5kZXhcblx0XHRcdGNvbnN0IGZpcnN0SW5kZXggPSBpbmRleGVzLnNvcnQoKGEsIGIpID0+IGIgLSBhKVswXTtcblxuXHRcdFx0Ly8gc2VhcmNoIHRoZSByb3cgZm9yIGNlbGxzIHRoYXQgc2hhcmUgdGhlIGhlYWRlclxuXHRcdFx0bGV0IHNpbWlsYXJDZWxscyA9IFtdO1xuXHRcdFx0Zm9yIChjb25zdCBpZCBvZiBpZHMpIHtcblx0XHRcdFx0Ly8gdGhlcmUncyBubyBzZWxlY3RvciB0aGF0IHdpbGwgbWF0Y2ggdHdvIHNwYWNlIHNlcGFyYXRlZCBsaXN0cyxcblx0XHRcdFx0Ly8gc28gd2UgaGF2ZSB0byBpdGVyYXRlIHRocm91Z2ggdGhlIGlkcyBhbmQgcXVlcnkgdGhlIHJvdyBmb3IgZWFjaFxuXHRcdFx0XHRjb25zdCByb3dDZWxscyA9IEFycmF5LmZyb20ocm93LnF1ZXJ5U2VsZWN0b3JBbGwoYFtoZWFkZXJzfj0nJHtpZH0nXWApKTtcblx0XHRcdFx0Zm9yIChjb25zdCByb3dDZWxsIG9mIHJvd0NlbGxzKSB7XG5cdFx0XHRcdFx0Ly8gb25seSBrZWVwIG9uZSBzZXQgb2YgY2VsbHNcblx0XHRcdFx0XHRpZiAoIXNpbWlsYXJDZWxscy5pbmNsdWRlcyhyb3dDZWxsKSkge1xuXHRcdFx0XHRcdFx0c2ltaWxhckNlbGxzLnB1c2gocm93Q2VsbCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vIERPTSBvcmRlciBpcyBub3QgcHJlc2VydmVkLCBzbyB3ZSBoYXZlIHRvIHNvcnQgdGhlIHJvd1xuXHRcdFx0c2ltaWxhckNlbGxzID0gc2ltaWxhckNlbGxzLnNvcnQoKGE6IEhUTUxUYWJsZUNlbGxFbGVtZW50LCBiOiBIVE1MVGFibGVDZWxsRWxlbWVudCkgPT4gYS5jZWxsSW5kZXggLSBiLmNlbGxJbmRleCk7XG5cblx0XHRcdC8vIHJldHVybiB0aGUgaGVhZGVyIGluZGV4IHBsdXMgYW55IGFkanVzdG1lbnQgd2l0aGluIHRoYXQgaGVhZGVycyBjb2x1bW5cblx0XHRcdHJldHVybiBmaXJzdEluZGV4ICsgc2ltaWxhckNlbGxzLmluZGV4T2YoY2VsbCk7XG5cdFx0fVxuXG5cdFx0Ly8gZmFsbGJhY2sgaWYgdGhlIGNlbGwgaXNuJ3QgbGlua2VkIHRvIGFueSBoZWFkZXJzXG5cdFx0bGV0IGNlbGxJbmRleCA9IDA7XG5cdFx0Zm9yIChjb25zdCBjIG9mIEFycmF5LmZyb20ocm93LmNlbGxzKSkge1xuXHRcdFx0aWYgKGMgPT09IGNlbGwpIHsgYnJlYWs7IH1cblx0XHRcdGNlbGxJbmRleCArPSBjLmNvbFNwYW47XG5cdFx0fVxuXHRcdHJldHVybiBjZWxsSW5kZXg7XG5cdH1cblxuXHQvKipcblx0ICogRmluZHMgdGhlIHJvdyBpbmRleCBvZiBhIGdpdmVuIGNlbGxcblx0ICpcblx0ICogQHBhcmFtIGNlbGwgdGhlIGNlbGwgdG8gc2VhcmNoIGZvclxuXHQgKi9cblx0ZmluZFJvd0luZGV4KGNlbGw6IEhUTUxUYWJsZUNlbGxFbGVtZW50KTogbnVtYmVyIHtcblx0XHRmb3IgKGNvbnN0IHJvdyBvZiBBcnJheS5mcm9tKHRoaXMudGFibGVFbGVtZW50LnJvd3MpKSB7XG5cdFx0XHRpZiAocm93LmNvbnRhaW5zKGNlbGwpKSB7XG5cdFx0XHRcdHJldHVybiByb3cucm93SW5kZXg7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEZpbmRzIHRoZSByb3cgYW5kIGNvbHVtbiBpbmRleCBvZiBhIGdpdmVuIGNlbGxcblx0ICpcblx0ICogQHBhcmFtIGNlbGwgdGhlIGNlbGwgdG8gc2VhcmNoIGZvclxuXHQgKiBAcmV0dXJucyBhIHR1cGxlIHRoYXQgZm9sbG93cyB0aGUgYFtyb3csIGNvbHVtbl1gIGNvbnZlbnRpb25cblx0ICovXG5cdGZpbmRJbmRleChjZWxsOiBIVE1MVGFibGVDZWxsRWxlbWVudCk6IFtudW1iZXIsIG51bWJlcl0ge1xuXHRcdHJldHVybiBbdGhpcy5maW5kUm93SW5kZXgoY2VsbCksIHRoaXMuZmluZENvbHVtbkluZGV4KGNlbGwpXTtcblx0fVxuXG5cdC8qKlxuXHQgKiBIZWxwZXIgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZSBcInJlYWxcIiBsZW5ndGggb2YgYSByb3cuXG5cdCAqIE9ubHkgYWNjdXJhdGUgd2l0aCByZWdhcmQgdG8gY29sc3BhbnMgKHRob3VnaCB0aGF0J3Mgc3VmZmljaWVudCBmb3IgaXQncyB1c2VzIGhlcmUpXG5cdCAqXG5cdCAqIFRPRE86IFRha2Ugcm93U3BhbiBpbnRvIGFjY291bnRcblx0ICpcblx0ICogQHBhcmFtIHJvdyB0aGUgcm93IHRvIGdldCB0aGUgbGVuZ3RoIG9mXG5cdCAqL1xuXHRwcm90ZWN0ZWQgZ2V0UmVhbFJvd0xlbmd0aChyb3c6IEhUTUxUYWJsZVJvd0VsZW1lbnQpOiBudW1iZXIge1xuXHRcdC8vIHN0YXJ0IGF0IC0xIHNpbmNlIHRoZSBjb2xzcGFucyB3aWxsIHN1bSB0byAxIGluZGV4IGdyZWF0ZXIgdGhhbiB0aGUgdG90YWxcblx0XHRyZXR1cm4gQXJyYXkuZnJvbShyb3cuY2VsbHMpLnJlZHVjZSgoY291bnQsIGNlbGwpID0+IGNvdW50ICsgY2VsbC5jb2xTcGFuLCAtMSk7XG5cdH1cblxuXHQvKipcblx0ICogRmluZHMgYSBjZWxsIGFuZCBpdCdzIHJlYWwgaW5kZXggZ2l2ZW4gYW4gYXJyYXkgb2YgY2VsbHMsIGEgdGFyZ2V0IGluZGV4LCBhbmQgdGhlIHNwYW5uaW5nIGRpcmVjdGlvblxuXHQgKlxuXHQgKiBAcGFyYW0gY2VsbHMgQW4gYXJyYXkgb2YgY2VsbHMgdG8gc2VhcmNoXG5cdCAqIEBwYXJhbSB0YXJnZXRJbmRleCBUaGUgaW5kZXggd2UgdGhpbmsgdGhlIGNlbGwgaXMgbG9jYXRlZCBhdFxuXHQgKiBAcGFyYW0gc3BhbkRpcmVjdGlvbiBUaGUgZGlyZWN0aW9uIG9mIHRoZSBjZWxsIHNwYW5zLiBTaG91bGQgYmUgYFwiY29sU3BhblwiYCBmb3IgYSByb3cgYW5kIGBcInJvd1NwYW5cImAgZm9yIGEgY29sdW1uXG5cdCAqL1xuXHRwcm90ZWN0ZWQgZmluZENlbGwoY2VsbHM6IEhUTUxUYWJsZUNlbGxFbGVtZW50W10sIHRhcmdldEluZGV4OiBudW1iZXIsIHNwYW5EaXJlY3Rpb246IFRhYmxlRG9tU3BhbkRpcmVjdGlvbikge1xuXHRcdC8vIHJvd3MvY29scyBjYW4gaGF2ZSBmZXdlciB0b3RhbCBjZWxscyB0aGFuIHRoZSBhY3R1YWwgdGFibGVcblx0XHQvLyB0aGUgbW9kZWwgcHJldGVuZHMgYWxsIHJvd3MvY29scyBiZWhhdmUgdGhlIHNhbWUgKHdpdGggY29sL3JvdyBzcGFucyA+IDEgYmVpbmcgTiBjZWxscyBsb25nKVxuXHRcdC8vIHRoaXMgbWFwcyB0aGF0IHZpZXcgdG8gdGhlIEhUTUwgdmlldyAoY29sL3JvdyBzcGFucyA+IDEgYXJlIG9uZSBlbGVtZW50LCBzbyB0aGUgYXJyYXkgaXMgc2hvcnRlcilcblx0XHRsZXQgcmVhbEluZGV4ID0gMDtcblx0XHQvLyBpIGlzIG9ubHkgdXNlZCBmb3IgaXRlcmF0aW5nIHRoZSBjZWxsc1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgdGFyZ2V0SW5kZXg7KSB7XG5cdFx0XHQvLyBza2lwIHRoZSBuZXh0IE4gY2VsbHNcblx0XHRcdGkgKz0gY2VsbHNbcmVhbEluZGV4XVtzcGFuRGlyZWN0aW9uXTtcblx0XHRcdC8vIGRvbid0IGJ1bXAgcmVhbEluZGV4IGlmIGkgbm93IGV4Y2VlZHMgdGhlIGNlbGwgd2UncmUgc2hvb3RpbmcgZm9yXG5cdFx0XHRpZiAoaSA+IHRhcmdldEluZGV4KSB7IGJyZWFrOyB9XG5cdFx0XHQvLyBmaW5hbGx5LCBpbmNyZW1lbnQgcmVhbEluZGV4ICh0byBrZWVwIGl0IGdlbmVyYWxseSBpbiBzdGVwIHdpdGggaSlcblx0XHRcdHJlYWxJbmRleCsrO1xuXHRcdH1cblxuXHRcdHJldHVybiB7XG5cdFx0XHRjZWxsOiBjZWxsc1tyZWFsSW5kZXhdLFxuXHRcdFx0cmVhbEluZGV4XG5cdFx0fTtcblx0fVxuXG5cdC8qKlxuXHQgKiBIZWxwZXIgbWV0aG9kIGFyb3VuZCBgZmluZENlbGxgLCBzZWFyY2hlcyBiYXNlZCBvbiBhIHJvdyBvZiBjZWxsc1xuXHQgKlxuXHQgKiBAcGFyYW0gcm93IHRoZSByb3cgb2YgZWxlbWVudHMgdG8gc2VhcmNoXG5cdCAqIEBwYXJhbSBpbmRleCB0aGUgaW5kZXggb2YgdGhlIGVsZW1lbnRcblx0ICovXG5cdHByb3RlY3RlZCBmaW5kQ2VsbEluUm93KHJvdzogSFRNTFRhYmxlQ2VsbEVsZW1lbnRbXSwgaW5kZXg6IG51bWJlcikge1xuXHRcdHJldHVybiB0aGlzLmZpbmRDZWxsKHJvdywgaW5kZXgsIFRhYmxlRG9tU3BhbkRpcmVjdGlvbi5jb2xTcGFuKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBIZWxwZXIgbWV0aG9kIGFyb3VuZCBgZmluZENlbGxgLCBzZWFyY2hlcyBiYXNlZCBvbiBhIGNvbHVtbiBvZiBjZWxsc1xuXHQgKlxuXHQgKiBAcGFyYW0gY29sIHRoZSBjb2x1bW4gb2YgZWxlbWVudHMgdG8gc2VhcmNoXG5cdCAqIEBwYXJhbSBpbmRleCB0aGUgaW5kZXggb2YgdGhlIGVsZW1lbnRcblx0ICovXG5cdHByb3RlY3RlZCBmaW5kQ2VsbEluQ29sdW1uKGNvbDogSFRNTFRhYmxlQ2VsbEVsZW1lbnRbXSwgaW5kZXg6IG51bWJlcikge1xuXHRcdHJldHVybiB0aGlzLmZpbmRDZWxsKGNvbCwgaW5kZXgsIFRhYmxlRG9tU3BhbkRpcmVjdGlvbi5yb3dTcGFuKTtcblx0fVxufVxuIl19