@catull/igniteui-angular
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
461 lines • 65.8 kB
JavaScript
import { __decorate, __metadata } from "tslib";
import { Injectable } from '@angular/core';
import { IgxIconService } from '../../icon/icon.service';
import { FilteringExpressionsTree } from '../../data-operations/filtering-expressions-tree';
import icons from './svgIcons';
import { FilteringLogic } from '../../data-operations/filtering-expression.interface';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { GridBaseAPIService } from '../api.service';
import { IgxDatePipeComponent } from '../common/pipes';
const FILTERING_ICONS_FONT_SET = 'filtering-icons';
/**
*@hidden
*/
export class ExpressionUI {
constructor() {
this.isSelected = false;
this.isVisible = true;
}
}
/**
*@hidden
*/
let IgxFilteringService = class IgxFilteringService {
constructor(gridAPI, iconService) {
this.gridAPI = gridAPI;
this.iconService = iconService;
this.columnsWithComplexFilter = new Set();
this.areEventsSubscribed = false;
this.destroy$ = new Subject();
this.isFiltering = false;
this.columnToExpressionsMap = new Map();
this.columnStartIndex = -1;
this._filterIconsRegistered = false;
this.isFilterRowVisible = false;
this.filteredColumn = null;
this.selectedExpression = null;
this.columnToFocus = null;
this.shouldFocusNext = false;
this.columnToMoreIconHidden = new Map();
}
ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.complete();
}
get displayContainerWidth() {
return parseInt(this.grid.parentVirtDir.dc.instance._viewContainer.element.nativeElement.offsetWidth, 10);
}
get displayContainerScrollLeft() {
return this.grid.headerContainer.scrollPosition;
}
get areAllColumnsInView() {
return parseInt(this.grid.parentVirtDir.dc.instance._viewContainer.element.nativeElement.offsetWidth, 10) === 0;
}
get unpinnedFilterableColumns() {
return this.grid.unpinnedColumns.filter(col => !col.columnGroup && col.filterable);
}
get unpinnedColumns() {
return this.grid.unpinnedColumns.filter(col => !col.columnGroup);
}
get datePipe() {
if (!this._datePipe) {
this._datePipe = new IgxDatePipeComponent(this.grid.locale);
}
return this._datePipe;
}
/**
* Subscribe to grid's events.
*/
subscribeToEvents() {
if (!this.areEventsSubscribed) {
this.areEventsSubscribed = true;
this.grid.onColumnResized.pipe(takeUntil(this.destroy$)).subscribe((eventArgs) => {
this.updateFilteringCell(eventArgs.column);
});
this.grid.parentVirtDir.onChunkLoad.pipe(takeUntil(this.destroy$)).subscribe((eventArgs) => {
if (eventArgs.startIndex !== this.columnStartIndex) {
this.columnStartIndex = eventArgs.startIndex;
this.grid.filterCellList.forEach((filterCell) => {
filterCell.updateFilterCellArea();
});
}
if (this.columnToFocus) {
this.focusFilterCellChip(this.columnToFocus, false);
this.columnToFocus = null;
}
});
this.grid.onColumnMovingEnd.pipe(takeUntil(this.destroy$)).subscribe(() => {
this.grid.filterCellList.forEach((filterCell) => {
filterCell.updateFilterCellArea();
});
});
this.grid.onColumnVisibilityChanged.pipe(takeUntil(this.destroy$)).subscribe((eventArgs) => {
if (this.grid.filteringRow && this.grid.filteringRow.column === eventArgs.column) {
this.grid.filteringRow.close();
}
});
}
}
/**
* Internal method to create expressionsTree and filter grid used in both filter modes.
*/
filterInternal(field, expressions = null) {
this.isFiltering = true;
let expressionsTree;
if (expressions instanceof FilteringExpressionsTree) {
expressionsTree = expressions;
}
else {
expressionsTree = this.createSimpleFilteringTree(field, expressions);
}
if (expressionsTree.filteringOperands.length === 0) {
this.clearFilter(field);
}
else {
this.filter(field, null, expressionsTree);
}
this.isFiltering = false;
}
/**
* Execute filtering on the grid.
*/
filter(field, value, conditionOrExpressionTree, ignoreCase) {
const col = this.gridAPI.get_column_by_name(field);
const filteringIgnoreCase = ignoreCase || (col ? col.filteringIgnoreCase : false);
if (conditionOrExpressionTree) {
this.gridAPI.filter(field, value, conditionOrExpressionTree, filteringIgnoreCase);
}
else {
const expressionsTreeForColumn = this.grid.filteringExpressionsTree.find(field);
if (!expressionsTreeForColumn) {
throw new Error('Invalid condition or Expression Tree!');
}
else if (expressionsTreeForColumn instanceof FilteringExpressionsTree) {
this.gridAPI.filter(field, value, expressionsTreeForColumn, filteringIgnoreCase);
}
else {
const expressionForColumn = expressionsTreeForColumn;
this.gridAPI.filter(field, value, expressionForColumn.condition, filteringIgnoreCase);
}
}
// Wait for the change detection to update filtered data through the pipes and then emit the event.
requestAnimationFrame(() => this.grid.onFilteringDone.emit(col.filteringExpressionsTree));
}
/**
* Clear the filter of a given column.
*/
clearFilter(field) {
if (field) {
const column = this.gridAPI.get_column_by_name(field);
if (!column) {
return;
}
}
this.isFiltering = true;
this.gridAPI.clear_filter(field);
// Wait for the change detection to update filtered data through the pipes and then emit the event.
requestAnimationFrame(() => this.grid.onFilteringDone.emit(null));
if (field) {
const expressions = this.getExpressions(field);
expressions.length = 0;
}
this.isFiltering = false;
}
/**
* Filters all the `IgxColumnComponent` in the `IgxGridComponent` with the same condition.
*/
filterGlobal(value, condition, ignoreCase) {
this.gridAPI.filter_global(value, condition, ignoreCase);
// Wait for the change detection to update filtered data through the pipes and then emit the event.
requestAnimationFrame(() => this.grid.onFilteringDone.emit(this.grid.filteringExpressionsTree));
}
/**
* Register filtering SVG icons in the icon service.
*/
registerSVGIcons() {
if (!this._filterIconsRegistered) {
for (const icon of icons) {
if (!this.iconService.isSvgIconCached(icon.name, FILTERING_ICONS_FONT_SET)) {
this.iconService.addSvgIconFromText(icon.name, icon.value, FILTERING_ICONS_FONT_SET);
}
}
this._filterIconsRegistered = true;
}
}
/**
* Returns the ExpressionUI array for a given column.
*/
getExpressions(columnId) {
if (!this.columnToExpressionsMap.has(columnId)) {
const column = this.grid.columns.find((col) => col.field === columnId);
const expressionUIs = new Array();
if (column) {
this.generateExpressionsList(column.filteringExpressionsTree, this.grid.filteringExpressionsTree.operator, expressionUIs);
this.columnToExpressionsMap.set(columnId, expressionUIs);
}
return expressionUIs;
}
return this.columnToExpressionsMap.get(columnId);
}
/**
* Recreates all ExpressionUIs for all columns. Executed after filtering to refresh the cache.
*/
refreshExpressions() {
if (!this.isFiltering) {
this.columnsWithComplexFilter.clear();
this.columnToExpressionsMap.forEach((value, key) => {
const column = this.grid.columns.find((col) => col.field === key);
if (column) {
value.length = 0;
this.generateExpressionsList(column.filteringExpressionsTree, this.grid.filteringExpressionsTree.operator, value);
const isComplex = this.isFilteringTreeComplex(column.filteringExpressionsTree);
if (isComplex) {
this.columnsWithComplexFilter.add(key);
}
this.updateFilteringCell(column);
}
else {
this.columnToExpressionsMap.delete(key);
}
});
}
}
/**
* Remove an ExpressionUI for a given column.
*/
removeExpression(columnId, indexToRemove) {
const expressionsList = this.getExpressions(columnId);
if (indexToRemove === 0 && expressionsList.length > 1) {
expressionsList[1].beforeOperator = null;
}
else if (indexToRemove === expressionsList.length - 1) {
expressionsList[indexToRemove - 1].afterOperator = null;
}
else {
expressionsList[indexToRemove - 1].afterOperator = expressionsList[indexToRemove + 1].beforeOperator;
expressionsList[0].beforeOperator = null;
expressionsList[expressionsList.length - 1].afterOperator = null;
}
expressionsList.splice(indexToRemove, 1);
}
/**
* Generate filtering tree for a given column from existing ExpressionUIs.
*/
createSimpleFilteringTree(columnId, expressionUIList = null) {
const expressionsList = expressionUIList ? expressionUIList : this.getExpressions(columnId);
const expressionsTree = new FilteringExpressionsTree(FilteringLogic.Or, columnId);
let currAndBranch;
let currExpressionUI;
for (let i = 0; i < expressionsList.length; i++) {
currExpressionUI = expressionsList[i];
if (!currExpressionUI.expression.condition.isUnary && currExpressionUI.expression.searchVal === null) {
if (currExpressionUI.afterOperator === FilteringLogic.And && !currAndBranch) {
currAndBranch = new FilteringExpressionsTree(FilteringLogic.And, columnId);
expressionsTree.filteringOperands.push(currAndBranch);
}
continue;
}
if ((currExpressionUI.beforeOperator === undefined || currExpressionUI.beforeOperator === null ||
currExpressionUI.beforeOperator === FilteringLogic.Or) &&
currExpressionUI.afterOperator === FilteringLogic.And) {
currAndBranch = new FilteringExpressionsTree(FilteringLogic.And, columnId);
expressionsTree.filteringOperands.push(currAndBranch);
currAndBranch.filteringOperands.push(currExpressionUI.expression);
}
else if (currExpressionUI.beforeOperator === FilteringLogic.And) {
currAndBranch.filteringOperands.push(currExpressionUI.expression);
}
else {
expressionsTree.filteringOperands.push(currExpressionUI.expression);
currAndBranch = null;
}
}
return expressionsTree;
}
/**
* Returns whether a complex filter is applied to a given column.
*/
isFilterComplex(columnId) {
if (this.columnsWithComplexFilter.has(columnId)) {
return true;
}
const column = this.grid.columns.find((col) => col.field === columnId);
const isComplex = column && this.isFilteringTreeComplex(column.filteringExpressionsTree);
if (isComplex) {
this.columnsWithComplexFilter.add(columnId);
}
return isComplex;
}
/**
* Returns the string representation of the FilteringLogic operator.
*/
getOperatorAsString(operator) {
if (operator === 0) {
return this.grid.resourceStrings.igx_grid_filter_operator_and;
}
else {
return this.grid.resourceStrings.igx_grid_filter_operator_or;
}
}
/**
* Generate the label of a chip from a given filtering expression.
*/
getChipLabel(expression) {
if (expression.condition.isUnary) {
return this.grid.resourceStrings[`igx_grid_filter_${expression.condition.name}`] || expression.condition.name;
}
else if (expression.searchVal instanceof Date) {
return this.datePipe.transform(expression.searchVal, this.grid.locale);
}
else {
return expression.searchVal;
}
}
/**
* Updates the content of a filterCell.
*/
updateFilteringCell(column) {
const filterCell = column.filterCell;
if (filterCell) {
filterCell.updateFilterCellArea();
}
}
/**
* Focus a chip in a filterCell.
*/
focusFilterCellChip(column, focusFirst) {
const filterCell = column.filterCell;
if (filterCell) {
filterCell.focusChip(focusFirst);
}
}
/**
* Focus the close button in the filtering row.
*/
focusFilterRowCloseButton() {
this.grid.filteringRow.closeButton.nativeElement.focus();
}
get filteredData() {
return this.grid.filteredData;
}
/**
* Scrolls to a filterCell.
*/
scrollToFilterCell(column, shouldFocusNext) {
this.grid.nativeElement.focus({ preventScroll: true });
this.columnToFocus = column;
this.shouldFocusNext = shouldFocusNext;
let currentColumnRight = 0;
let currentColumnLeft = 0;
for (let index = 0; index < this.unpinnedColumns.length; index++) {
currentColumnRight += parseInt(this.unpinnedColumns[index].width, 10);
if (this.unpinnedColumns[index] === column) {
currentColumnLeft = currentColumnRight - parseInt(this.unpinnedColumns[index].width, 10);
break;
}
}
const forOfDir = this.grid.headerContainer;
const width = this.displayContainerWidth + this.displayContainerScrollLeft;
if (shouldFocusNext) {
forOfDir.scrollPosition += currentColumnRight - width;
}
else {
forOfDir.scrollPosition = currentColumnLeft;
}
}
isFilteringTreeComplex(expressions) {
if (!expressions) {
return false;
}
if (expressions instanceof FilteringExpressionsTree) {
const expressionsTree = expressions;
if (expressionsTree.operator === FilteringLogic.Or) {
const andOperatorsCount = this.getChildAndOperatorsCount(expressionsTree);
// having more that 'And' and operator in the sub-tree means that the filter could not be represented without parentheses.
return andOperatorsCount > 1;
}
let isComplex = false;
for (let i = 0; i < expressionsTree.filteringOperands.length; i++) {
isComplex = isComplex || this.isFilteringTreeComplex(expressionsTree.filteringOperands[i]);
}
return isComplex;
}
return false;
}
getChildAndOperatorsCount(expressions) {
let count = 0;
let operand;
for (let i = 0; i < expressions.filteringOperands.length; i++) {
operand = expressions[i];
if (operand instanceof FilteringExpressionsTree) {
if (operand.operator === FilteringLogic.And) {
count++;
}
count = count + this.getChildAndOperatorsCount(operand);
}
}
return count;
}
generateExpressionsList(expressions, operator, expressionsUIs) {
this.generateExpressionsListRecursive(expressions, operator, expressionsUIs);
// The beforeOperator of the first expression and the afterOperator of the last expression should be null
if (expressionsUIs.length) {
expressionsUIs[expressionsUIs.length - 1].afterOperator = null;
}
}
generateExpressionsListRecursive(expressions, operator, expressionsUIs) {
if (!expressions) {
return;
}
if (expressions instanceof FilteringExpressionsTree) {
const expressionsTree = expressions;
for (let i = 0; i < expressionsTree.filteringOperands.length; i++) {
this.generateExpressionsListRecursive(expressionsTree.filteringOperands[i], expressionsTree.operator, expressionsUIs);
}
if (expressionsUIs.length) {
expressionsUIs[expressionsUIs.length - 1].afterOperator = operator;
}
}
else {
const exprUI = new ExpressionUI();
exprUI.expression = expressions;
exprUI.afterOperator = operator;
const prevExprUI = expressionsUIs[expressionsUIs.length - 1];
if (prevExprUI) {
exprUI.beforeOperator = prevExprUI.afterOperator;
}
expressionsUIs.push(exprUI);
}
}
isFilteringExpressionsTreeEmpty() {
const expressionTree = this.grid.filteringExpressionsTree;
if (FilteringExpressionsTree.empty(expressionTree)) {
return true;
}
let expr;
for (let i = 0; i < expressionTree.filteringOperands.length; i++) {
expr = expressionTree.filteringOperands[i];
if ((expr instanceof FilteringExpressionsTree)) {
const exprTree = expr;
if (exprTree.filteringOperands && exprTree.filteringOperands.length) {
return false;
}
}
else {
return false;
}
}
return true;
}
};
IgxFilteringService.ctorParameters = () => [
{ type: GridBaseAPIService },
{ type: IgxIconService }
];
IgxFilteringService = __decorate([
Injectable(),
__metadata("design:paramtypes", [GridBaseAPIService, IgxIconService])
], IgxFilteringService);
export { IgxFilteringService };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JpZC1maWx0ZXJpbmcuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL2lnbml0ZXVpLWFuZ3VsYXIvIiwic291cmNlcyI6WyJsaWIvZ3JpZHMvZmlsdGVyaW5nL2dyaWQtZmlsdGVyaW5nLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQWEsTUFBTSxlQUFlLENBQUM7QUFDdEQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3pELE9BQU8sRUFBRSx3QkFBd0IsRUFBNkIsTUFBTSxrREFBa0QsQ0FBQztBQUV2SCxPQUFPLEtBQUssTUFBTSxZQUFZLENBQUM7QUFDL0IsT0FBTyxFQUF3QixjQUFjLEVBQUUsTUFBTSxzREFBc0QsQ0FBQztBQUM1RyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUkzQyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUlwRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUV2RCxNQUFNLHdCQUF3QixHQUFHLGlCQUFpQixDQUFDO0FBRW5EOztHQUVHO0FBQ0gsTUFBTSxPQUFPLFlBQVk7SUFBekI7UUFJVyxlQUFVLEdBQUcsS0FBSyxDQUFDO1FBQ25CLGNBQVMsR0FBRyxJQUFJLENBQUM7SUFDNUIsQ0FBQztDQUFBO0FBRUQ7O0dBRUc7QUFFSCxJQUFhLG1CQUFtQixHQUFoQyxNQUFhLG1CQUFtQjtJQXFCNUIsWUFBb0IsT0FBNEQsRUFBVSxXQUEyQjtRQUFqRyxZQUFPLEdBQVAsT0FBTyxDQUFxRDtRQUFVLGdCQUFXLEdBQVgsV0FBVyxDQUFnQjtRQW5CN0csNkJBQXdCLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztRQUM3Qyx3QkFBbUIsR0FBRyxLQUFLLENBQUM7UUFDNUIsYUFBUSxHQUFH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aWYvQjtTQWpmWSxtQkFBbUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBPbkRlc3Ryb3kgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IElneEljb25TZXJ2aWNlIH0gZnJvbSAnLi4vLi4vaWNvbi9pY29uLnNlcnZpY2UnO1xuaW1wb3J0IHsgRmlsdGVyaW5nRXhwcmVzc2lvbnNUcmVlLCBJRmlsdGVyaW5nRXhwcmVzc2lvbnNUcmVlIH0gZnJvbSAnLi4vLi4vZGF0YS1vcGVyYXRpb25zL2ZpbHRlcmluZy1leHByZXNzaW9ucy10cmVlJztcbmltcG9ydCB7IElneEdyaWRCYXNlRGlyZWN0aXZlIH0gZnJvbSAnLi4vZ3JpZC1iYXNlLmRpcmVjdGl2ZSc7XG5pbXBvcnQgaWNvbnMgZnJvbSAnLi9zdmdJY29ucyc7XG5pbXBvcnQgeyBJRmlsdGVyaW5nRXhwcmVzc2lvbiwgRmlsdGVyaW5nTG9naWMgfSBmcm9tICcuLi8uLi9kYXRhLW9wZXJhdGlvbnMvZmlsdGVyaW5nLWV4cHJlc3Npb24uaW50ZXJmYWNlJztcbmltcG9ydCB7IFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IElGb3JPZlN0YXRlIH0gZnJvbSAnLi4vLi4vZGlyZWN0aXZlcy9mb3Itb2YvZm9yX29mLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBJZ3hDb2x1bW5Db21wb25lbnQgfSBmcm9tICcuLi9jb2x1bW5zL2NvbHVtbi5jb21wb25lbnQnO1xuaW1wb3J0IHsgSUZpbHRlcmluZ09wZXJhdGlvbiB9IGZyb20gJy4uLy4uL2RhdGEtb3BlcmF0aW9ucy9maWx0ZXJpbmctY29uZGl0aW9uJztcbmltcG9ydCB7IEdyaWRCYXNlQVBJU2VydmljZSB9IGZyb20gJy4uL2FwaS5zZXJ2aWNlJztcbmltcG9ydCB7IElDb2x1bW5WaXNpYmlsaXR5Q2hhbmdlZEV2ZW50QXJncyB9IGZyb20gJy4uL2dyaWQnO1xuaW1wb3J0IHsgSUNvbHVtblJlc2l6ZUV2ZW50QXJncyB9IGZyb20gJy4uL2NvbW1vbi9ldmVudHMnO1xuaW1wb3J0IHsgR3JpZFR5cGUgfSBmcm9tICcuLi9jb21tb24vZ3JpZC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgSWd4RGF0ZVBpcGVDb21wb25lbnQgfSBmcm9tICcuLi9jb21tb24vcGlwZXMnO1xuXG5jb25zdCBGSUxURVJJTkdfSUNPTlNfRk9OVF9TRVQgPSAnZmlsdGVyaW5nLWljb25zJztcblxuLyoqXG4gKkBoaWRkZW5cbiAqL1xuZXhwb3J0IGNsYXNzIEV4cHJlc3Npb25VSSB7XG4gICAgcHVibGljIGV4cHJlc3Npb246IElGaWx0ZXJpbmdFeHByZXNzaW9uO1xuICAgIHB1YmxpYyBiZWZvcmVPcGVyYXRvcjogRmlsdGVyaW5nTG9naWM7XG4gICAgcHVibGljIGFmdGVyT3BlcmF0b3I6IEZpbHRlcmluZ0xvZ2ljO1xuICAgIHB1YmxpYyBpc1NlbGVjdGVkID0gZmFsc2U7XG4gICAgcHVibGljIGlzVmlzaWJsZSA9IHRydWU7XG59XG5cbi8qKlxuICpAaGlkZGVuXG4gKi9cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBJZ3hGaWx0ZXJpbmdTZXJ2aWNlIGltcGxlbWVudHMgT25EZXN0cm95IHtcblxuICAgIHByaXZhdGUgY29sdW1uc1dpdGhDb21wbGV4RmlsdGVyID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgcHJpdmF0ZSBhcmVFdmVudHNTdWJzY3JpYmVkID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBkZXN0cm95JCA9IG5ldyBTdWJqZWN0PGJvb2xlYW4+KCk7XG4gICAgcHJpdmF0ZSBpc0ZpbHRlcmluZyA9IGZhbHNlO1xuICAgIHByaXZhdGUgY29sdW1uVG9FeHByZXNzaW9uc01hcCA9IG5ldyBNYXA8c3RyaW5nLCBFeHByZXNzaW9uVUlbXT4oKTtcbiAgICBwcml2YXRlIF9kYXRlUGlwZTogSWd4RGF0ZVBpcGVDb21wb25lbnQ7XG4gICAgcHJpdmF0ZSBjb2x1bW5TdGFydEluZGV4ID0gLTE7XG4gICAgcHJpdmF0ZSBfZmlsdGVySWNvbnNSZWdpc3RlcmVkID0gZmFsc2U7XG5cbiAgICBwdWJsaWMgZ3JpZElkOiBzdHJpbmc7XG4gICAgcHVibGljIGlzRmlsdGVyUm93VmlzaWJsZSA9IGZhbHNlO1xuICAgIHB1YmxpYyBmaWx0ZXJlZENvbHVtbjogSWd4Q29sdW1uQ29tcG9uZW50ID0gbnVsbDtcbiAgICBwdWJsaWMgc2VsZWN0ZWRFeHByZXNzaW9uOiBJRmlsdGVyaW5nRXhwcmVzc2lvbiA9IG51bGw7XG4gICAgcHVibGljIGNvbHVtblRvRm9jdXM6IElneENvbHVtbkNvbXBvbmVudCA9IG51bGw7XG4gICAgcHVibGljIHNob3VsZEZvY3VzTmV4dCA9IGZhbHNlO1xuICAgIHB1YmxpYyBjb2x1bW5Ub01vcmVJY29uSGlkZGVuID0gbmV3IE1hcDxzdHJpbmcsIGJvb2xlYW4+KCk7XG5cbiAgICBncmlkOiBJZ3hHcmlkQmFzZURpcmVjdGl2ZTtcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgZ3JpZEFQSTogR3JpZEJhc2VBUElTZXJ2aWNlPElneEdyaWRCYXNlRGlyZWN0aXZlICYgR3JpZFR5cGU+LCBwcml2YXRlIGljb25TZXJ2aWNlOiBJZ3hJY29uU2VydmljZSkge31cblxuICAgIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgICAgICB0aGlzLmRlc3Ryb3kkLm5leHQodHJ1ZSk7XG4gICAgICAgIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IGRpc3BsYXlDb250YWluZXJXaWR0aCgpIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlSW50KHRoaXMuZ3JpZC5wYXJlbnRWaXJ0RGlyLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudC5vZmZzZXRXaWR0aCwgMTApO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgZGlzcGxheUNvbnRhaW5lclNjcm9sbExlZnQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWQuaGVhZGVyQ29udGFpbmVyLnNjcm9sbFBvc2l0aW9uO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgYXJlQWxsQ29sdW1uc0luVmlldygpIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlSW50KHRoaXMuZ3JpZC5wYXJlbnRWaXJ0RGlyLmRjLmluc3RhbmNlLl92aWV3Q29udGFpbmVyLmVsZW1lbnQubmF0aXZlRWxlbWVudC5vZmZzZXRXaWR0aCwgMTApID09PSAwO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgdW5waW5uZWRGaWx0ZXJhYmxlQ29sdW1ucygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZC51bnBpbm5lZENvbHVtbnMuZmlsdGVyKGNvbCA9PiAhY29sLmNvbHVtbkdyb3VwICYmIGNvbC5maWx0ZXJhYmxlKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IHVucGlubmVkQ29sdW1ucygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZC51bnBpbm5lZENvbHVtbnMuZmlsdGVyKGNvbCA9PiAhY29sLmNvbHVtbkdyb3VwKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IGRhdGVQaXBlKCk6IElneERhdGVQaXBlQ29tcG9uZW50IHtcbiAgICAgICAgaWYgKCF0aGlzLl9kYXRlUGlwZSkge1xuICAgICAgICAgICAgdGhpcy5fZGF0ZVBpcGUgPSBuZXcgSWd4RGF0ZVBpcGVDb21wb25lbnQodGhpcy5ncmlkLmxvY2FsZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX2RhdGVQaXBlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN1YnNjcmliZSB0byBncmlkJ3MgZXZlbnRzLlxuICAgICAqL1xuICAgIHB1YmxpYyBzdWJzY3JpYmVUb0V2ZW50cygpIHtcbiAgICAgICAgaWYgKCF0aGlzLmFyZUV2ZW50c1N1YnNjcmliZWQpIHtcbiAgICAgICAgICAgIHRoaXMuYXJlRXZlbnRzU3Vic2NyaWJlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIHRoaXMuZ3JpZC5vbkNvbHVtblJlc2l6ZWQucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpLnN1YnNjcmliZSgoZXZlbnRBcmdzOiBJQ29sdW1uUmVzaXplRXZlbnRBcmdzKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVGaWx0ZXJpbmdDZWxsKGV2ZW50QXJncy5jb2x1bW4pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHRoaXMuZ3JpZC5wYXJlbnRWaXJ0RGlyLm9uQ2h1bmtMb2FkLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKS5zdWJzY3JpYmUoKGV2ZW50QXJnczogSUZvck9mU3RhdGUpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnRBcmdzLnN0YXJ0SW5kZXggIT09IHRoaXMuY29sdW1uU3RhcnRJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbHVtblN0YXJ0SW5kZXggPSBldmVudEFyZ3Muc3RhcnRJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5ncmlkLmZpbHRlckNlbGxMaXN0LmZvckVhY2goKGZpbHRlckNlbGwpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlckNlbGwudXBkYXRlRmlsdGVyQ2VsbEFyZWEoKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbHVtblRvRm9jdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5mb2N1c0ZpbHRlckNlbGxDaGlwKHRoaXMuY29sdW1uVG9Gb2N1cywgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbHVtblRvRm9jdXMgPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB0aGlzLmdyaWQub25Db2x1bW5Nb3ZpbmdFbmQucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5ncmlkLmZpbHRlckNlbGxMaXN0LmZvckVhY2goKGZpbHRlckNlbGwpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgZmlsdGVyQ2VsbC51cGRhdGVGaWx0ZXJDZWxsQXJlYSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHRoaXMuZ3JpZC5vbkNvbHVtblZpc2liaWxpdHlDaGFuZ2VkLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKS5zdWJzY3JpYmUoKGV2ZW50QXJnczogSUNvbHVtblZpc2liaWxpdHlDaGFuZ2VkRXZlbnRBcmdzKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZ3JpZC5maWx0ZXJpbmdSb3cgJiYgdGhpcy5ncmlkLmZpbHRlcmluZ1Jvdy5jb2x1bW4gPT09IGV2ZW50QXJncy5jb2x1bW4gKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZ3JpZC5maWx0ZXJpbmdSb3cuY2xvc2UoKTtcblxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW50ZXJuYWwgbWV0aG9kIHRvIGNyZWF0ZSBleHByZXNzaW9uc1RyZWUgYW5kIGZpbHRlciBncmlkIHVzZWQgaW4gYm90aCBmaWx0ZXIgbW9kZXMuXG4gICAgICovXG4gICAgcHVibGljIGZpbHRlckludGVybmFsKGZpZWxkOiBzdHJpbmcsIGV4cHJlc3Npb25zOiBGaWx0ZXJpbmdFeHByZXNzaW9uc1RyZWUgfCBBcnJheTxFeHByZXNzaW9uVUk+ID0gbnVsbCk6IHZvaWQge1xuICAgICAgICB0aGlzLmlzRmlsdGVyaW5nID0gdHJ1ZTtcblxuICAgICAgICBsZXQgZXhwcmVzc2lvbnNUcmVlO1xuICAgICAgICBpZiAoZXhwcmVzc2lvbnMgaW5zdGFuY2VvZiBGaWx0ZXJpbmdFeHByZXNzaW9uc1RyZWUpIHtcbiAgICAgICAgICAgIGV4cHJlc3Npb25zVHJlZSA9IGV4cHJlc3Npb25zO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZXhwcmVzc2lvbnNUcmVlID0gdGhpcy5jcmVhdGVTaW1wbGVGaWx0ZXJpbmdUcmVlKGZpZWxkLCBleHByZXNzaW9ucyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZXhwcmVzc2lvbnNUcmVlLmZpbHRlcmluZ09wZXJhbmRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgdGhpcy5jbGVhckZpbHRlcihmaWVsZCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmZpbHRlcihmaWVsZCwgbnVsbCwgZXhwcmVzc2lvbnNUcmVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuaXNGaWx0ZXJpbmcgPSBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFeGVjdXRlIGZpbHRlcmluZyBvbiB0aGUgZ3JpZC5cbiAgICAgKi9cbiAgICBwdWJsaWMgZmlsdGVyKGZpZWxkOiBzdHJpbmcsIHZhbHVlOiBhbnksIGNvbmRpdGlvbk9yRXhwcmVzc2lvblRyZWU/OiBJRmlsdGVyaW5nT3BlcmF0aW9uIHwgSUZpbHRlcmluZ0V4cHJlc3Npb25zVHJlZSxcbiAgICAgICAgaWdub3JlQ2FzZT86IGJvb2xlYW4pIHtcbiAgICAgICAgY29uc3QgY29sID0gdGhpcy5ncmlkQVBJLmdldF9jb2x1bW5fYnlfbmFtZShmaWVsZCk7XG4gICAgICAgIGNvbnN0IGZpbHRlcmluZ0lnbm9yZUNhc2UgPSBpZ25vcmVDYXNlIHx8IChjb2wgPyBjb2wuZmlsdGVyaW5nSWdub3JlQ2FzZSA6IGZhbHNlKTtcblxuICAgICAgICBpZiAoY29uZGl0aW9uT3JFeHByZXNzaW9uVHJlZSkge1xuICAgICAgICAgICAgdGhpcy5ncmlkQVBJLmZpbHRlcihmaWVsZCwgdmFsdWUsIGNvbmRpdGlvbk9yRXhwcmVzc2lvblRyZWUsIGZpbHRlcmluZ0lnbm9yZUNhc2UpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgZXhwcmVzc2lvbnNUcmVlRm9yQ29sdW1uID0gdGhpcy5ncmlkLmZpbHRlcmluZ0V4cHJlc3Npb25zVHJlZS5maW5kKGZpZWxkKTtcbiAgICAgICAgICAgIGlmICghZXhwcmVzc2lvbnNUcmVlRm9yQ29sdW1uKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGNvbmRpdGlvbiBvciBFeHByZXNzaW9uIFRyZWUhJyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGV4cHJlc3Npb25zVHJlZUZvckNvbHVtbiBpbnN0YW5jZW9mIEZpbHRlcmluZ0V4cHJlc3Npb25zVHJlZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZ3JpZEFQSS5maWx0ZXIoZmllbGQsIHZhbHVlLCBleHByZXNzaW9uc1RyZWVGb3JDb2x1bW4sIGZpbHRlcmluZ0lnbm9yZUNhc2UpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBleHByZXNzaW9uRm9yQ29sdW1uID0gZXhwcmVzc2lvbnNUcmVlRm9yQ29sdW1uIGFzIElGaWx0ZXJpbmdFeHByZXNzaW9uO1xuICAgICAgICAgICAgICAgIHRoaXMuZ3JpZEFQSS5maWx0ZXIoZmllbGQsIHZhbHVlLCBleHByZXNzaW9uRm9yQ29sdW1uLmNvbmRpdGlvbiwgZmlsdGVyaW5nSWdub3JlQ2FzZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBXYWl0IGZvciB0aGUgY2hhbmdlIGRldGVjdGlvbiB0byB1cGRhdGUgZmlsdGVyZWQgZGF0YSB0aHJvdWdoIHRoZSBwaXBlcyBhbmQgdGhlbiBlbWl0IHRoZSBldmVudC5cbiAgICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHRoaXMuZ3JpZC5vbkZpbHRlcmluZ0RvbmUuZW1pdChjb2wuZmlsdGVyaW5nRXhwcmVzc2lvbnNUcmVlKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2xlYXIgdGhlIGZpbHRlciBvZiBhIGdpdmVuIGNvbHVtbi5cbiAgICAgKi9cbiAgICBwdWJsaWMgY2xlYXJGaWx0ZXIoZmllbGQ6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBpZiAoZmllbGQpIHtcbiAgICAgICAgICAgIGNvbnN0IGNvbHVtbiA9IHRoaXMuZ3JpZEFQSS5nZXRfY29sdW1uX2J5X25hbWUoZmllbGQpO1xuICAgICAgICAgICAgaWYgKCFjb2x1bW4pIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmlzRmlsdGVyaW5nID0gdHJ1ZTtcblxuICAgICAgICB0aGlzLmdyaWRBUEkuY2xlYXJfZmlsdGVyKGZpZWxkKTtcblxuICAgICAgICAvLyBXYWl0IGZvciB0aGUgY2hhbmdlIGRldGVjdGlvbiB0byB1cGRhdGUgZmlsdGVyZWQgZGF0YSB0aHJvdWdoIHRoZSBwaXBlcyBhbmQgdGhlbiBlbWl0IHRoZSBldmVudC5cbiAgICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHRoaXMuZ3JpZC5vbkZpbHRlcmluZ0RvbmUuZW1pdChudWxsKSk7XG5cbiAgICAgICAgaWYgKGZpZWxkKSB7XG4gICAgICAgICAgICBjb25zdCBleHByZXNzaW9ucyA9IHRoaXMuZ2V0RXhwcmVzc2lvbnMoZmllbGQpO1xuICAgICAgICAgICAgZXhwcmVzc2lvbnMubGVuZ3RoID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuaXNGaWx0ZXJpbmcgPSBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGaWx0ZXJzIGFsbCB0aGUgYElneENvbHVtbkNvbXBvbmVudGAgaW4gdGhlIGBJZ3hHcmlkQ29tcG9uZW50YCB3aXRoIHRoZSBzYW1lIGNvbmRpdGlvbi5cbiAgICAgKi9cbiAgICBwdWJsaWMgZmlsdGVyR2xvYmFsKHZhbHVlOiBhbnksIGNvbmRpdGlvbiwgaWdub3JlQ2FzZT8pIHtcbiAgICAgICAgdGhpcy5ncmlkQVBJLmZpbHRlcl9nbG9iYWwodmFsdWUsIGNvbmRpdGlvbiwgaWdub3JlQ2FzZSk7XG5cbiAgICAgICAgLy8gV2FpdCBmb3IgdGhlIGNoYW5nZSBkZXRlY3Rpb24gdG8gdXBkYXRlIGZpbHRlcmVkIGRhdGEgdGhyb3VnaCB0aGUgcGlwZXMgYW5kIHRoZW4gZW1pdCB0aGUgZXZlbnQuXG4gICAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB0aGlzLmdyaWQub25GaWx0ZXJpbmdEb25lLmVtaXQodGhpcy5ncmlkLmZpbHRlcmluZ0V4cHJlc3Npb25zVHJlZSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVyIGZpbHRlcmluZyBTVkcgaWNvbnMgaW4gdGhlIGljb24gc2VydmljZS5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVnaXN0ZXJTVkdJY29ucygpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLl9maWx0ZXJJY29uc1JlZ2lzdGVyZWQpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgaWNvbiBvZiBpY29ucykge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5pY29uU2VydmljZS5pc1N2Z0ljb25DYWNoZWQoaWNvbi5uYW1lLCBGSUxURVJJTkdfSUNPTlNfRk9OVF9TRVQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaWNvblNlcnZpY2UuYWRkU3ZnSWNvbkZyb21UZXh0KGljb24ubmFtZSwgaWNvbi52YWx1ZSwgRklMVEVSSU5HX0lDT05TX0ZPTlRfU0VUKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9maWx0ZXJJY29uc1JlZ2lzdGVyZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgRXhwcmVzc2lvblVJIGFycmF5IGZvciBhIGdpdmVuIGNvbHVtbi5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0RXhwcmVzc2lvbnMoY29sdW1uSWQ6IHN0cmluZyk6IEV4cHJlc3Npb25VSVtdIHtcbiAgICAgICAgaWYgKCF0aGlzLmNvbHVtblRvRXhwcmVzc2lvbnNNYXAuaGFzKGNvbHVtbklkKSkge1xuICAgICAgICAgICAgY29uc3QgY29