igniteui-angular
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
667 lines • 69.7 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
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 { IgxGridSortingPipe } from '../grid/grid.pipes';
import { IgxDatePipeComponent } from '../grid.common';
import { GridBaseAPIService } from '../api.service';
/** @type {?} */
const FILTERING_ICONS_FONT_SET = 'filtering-icons';
/**
* @hidden
*/
export class ExpressionUI {
constructor() {
this.isSelected = false;
this.isVisible = true;
}
}
if (false) {
/** @type {?} */
ExpressionUI.prototype.expression;
/** @type {?} */
ExpressionUI.prototype.beforeOperator;
/** @type {?} */
ExpressionUI.prototype.afterOperator;
/** @type {?} */
ExpressionUI.prototype.isSelected;
/** @type {?} */
ExpressionUI.prototype.isVisible;
}
/**
* @hidden
*/
export class IgxFilteringService {
/**
* @param {?} gridAPI
* @param {?} iconService
*/
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.isFilterRowVisible = false;
this.filteredColumn = null;
this.selectedExpression = null;
this.columnToFocus = null;
this.shouldFocusNext = false;
this.columnToMoreIconHidden = new Map();
}
/**
* @return {?}
*/
ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.complete();
}
/**
* @return {?}
*/
get displayContainerWidth() {
return parseInt(this.grid.parentVirtDir.dc.instance._viewContainer.element.nativeElement.offsetWidth, 10);
}
/**
* @return {?}
*/
get displayContainerScrollLeft() {
return parseInt(this.grid.parentVirtDir.getHorizontalScroll().scrollLeft, 10);
}
/**
* @return {?}
*/
get areAllColumnsInView() {
return parseInt(this.grid.parentVirtDir.dc.instance._viewContainer.element.nativeElement.offsetWidth, 10) === 0;
}
/**
* @return {?}
*/
get unpinnedFilterableColumns() {
return this.grid.unpinnedColumns.filter(col => !col.columnGroup && col.filterable);
}
/**
* @return {?}
*/
get unpinnedColumns() {
return this.grid.unpinnedColumns.filter(col => !col.columnGroup);
}
/**
* @return {?}
*/
get datePipe() {
if (!this._datePipe) {
this._datePipe = new IgxDatePipeComponent(this.grid.locale);
}
return this._datePipe;
}
/**
* Subscribe to grid's events.
* @return {?}
*/
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();
});
});
}
}
/**
* Internal method to create expressionsTree and filter grid used in both filter modes.
* @param {?} field
* @param {?=} expressions
* @return {?}
*/
filterInternal(field, expressions = null) {
this.isFiltering = true;
/** @type {?} */
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.
* @param {?} field
* @param {?} value
* @param {?=} conditionOrExpressionTree
* @param {?=} ignoreCase
* @return {?}
*/
filter(field, value, conditionOrExpressionTree, ignoreCase) {
/** @type {?} */
const col = this.gridAPI.get_column_by_name(field);
/** @type {?} */
const filteringIgnoreCase = ignoreCase || (col ? col.filteringIgnoreCase : false);
if (conditionOrExpressionTree) {
this.gridAPI.filter(field, value, conditionOrExpressionTree, filteringIgnoreCase);
}
else {
/** @type {?} */
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 {
/** @type {?} */
const expressionForColumn = (/** @type {?} */ (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.
* @param {?} field
* @return {?}
*/
clearFilter(field) {
if (field) {
/** @type {?} */
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) {
/** @type {?} */
const expressions = this.getExpressions(field);
expressions.length = 0;
}
this.isFiltering = false;
}
/**
* Filters all the `IgxColumnComponent` in the `IgxGridComponent` with the same condition.
* @param {?} value
* @param {?} condition
* @param {?=} ignoreCase
* @return {?}
*/
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.
* @return {?}
*/
registerSVGIcons() {
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);
}
}
}
/**
* Returns the ExpressionUI array for a given column.
* @param {?} columnId
* @return {?}
*/
getExpressions(columnId) {
if (!this.columnToExpressionsMap.has(columnId)) {
/** @type {?} */
const column = this.grid.columns.find((col) => col.field === columnId);
/** @type {?} */
const expressionUIs = new Array();
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.
* @return {?}
*/
refreshExpressions() {
if (!this.isFiltering) {
this.columnsWithComplexFilter.clear();
this.columnToExpressionsMap.forEach((value, key) => {
/** @type {?} */
const column = this.grid.columns.find((col) => col.field === key);
if (column) {
value.length = 0;
this.generateExpressionsList(column.filteringExpressionsTree, this.grid.filteringExpressionsTree.operator, value);
/** @type {?} */
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.
* @param {?} columnId
* @param {?} indexToRemove
* @return {?}
*/
removeExpression(columnId, indexToRemove) {
/** @type {?} */
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.
* @param {?} columnId
* @param {?=} expressionUIList
* @return {?}
*/
createSimpleFilteringTree(columnId, expressionUIList = null) {
/** @type {?} */
const expressionsList = expressionUIList ? expressionUIList : this.getExpressions(columnId);
/** @type {?} */
const expressionsTree = new FilteringExpressionsTree(FilteringLogic.Or, columnId);
/** @type {?} */
let currAndBranch;
/** @type {?} */
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.
* @param {?} columnId
* @return {?}
*/
isFilterComplex(columnId) {
if (this.columnsWithComplexFilter.has(columnId)) {
return true;
}
/** @type {?} */
const column = this.grid.columns.find((col) => col.field === columnId);
/** @type {?} */
const isComplex = this.isFilteringTreeComplex(column.filteringExpressionsTree);
if (isComplex) {
this.columnsWithComplexFilter.add(columnId);
}
return isComplex;
}
/**
* Returns the string representation of the FilteringLogic operator.
* @param {?} operator
* @return {?}
*/
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.
* @param {?} expression
* @return {?}
*/
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.
* @param {?} column
* @return {?}
*/
updateFilteringCell(column) {
/** @type {?} */
const filterCell = column.filterCell;
if (filterCell) {
filterCell.updateFilterCellArea();
}
}
/**
* Focus a chip in a filterCell.
* @param {?} column
* @param {?} focusFirst
* @return {?}
*/
focusFilterCellChip(column, focusFirst) {
/** @type {?} */
const filterCell = column.filterCell;
if (filterCell) {
filterCell.focusChip(focusFirst);
}
}
/**
* Focus the close button in the filtering row.
* @return {?}
*/
focusFilterRowCloseButton() {
this.grid.filteringRow.closeButton.nativeElement.focus();
}
/**
* @return {?}
*/
get filteredData() {
return this.grid.filteredData;
}
/**
* @return {?}
*/
get sortedData() {
/** @type {?} */
const sortData = new IgxGridSortingPipe(((/** @type {?} */ (this.grid))).gridAPI)
.transform(this.grid.data, this.grid.sortingExpressions, this.gridId, 0);
return sortData;
}
/**
* Scrolls to a filterCell.
* @param {?} column
* @param {?} shouldFocusNext
* @return {?}
*/
scrollToFilterCell(column, shouldFocusNext) {
this.grid.nativeElement.focus({ preventScroll: true });
this.columnToFocus = column;
this.shouldFocusNext = shouldFocusNext;
/** @type {?} */
let currentColumnRight = 0;
/** @type {?} */
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;
}
}
/** @type {?} */
const forOfDir = this.grid.headerContainer;
/** @type {?} */
const width = this.displayContainerWidth + this.displayContainerScrollLeft;
if (shouldFocusNext) {
forOfDir.getHorizontalScroll().scrollLeft += currentColumnRight - width;
}
else {
forOfDir.getHorizontalScroll().scrollLeft = currentColumnLeft;
}
}
/**
* @private
* @param {?} expressions
* @return {?}
*/
isFilteringTreeComplex(expressions) {
if (!expressions) {
return false;
}
if (expressions instanceof FilteringExpressionsTree) {
/** @type {?} */
const expressionsTree = (/** @type {?} */ (expressions));
if (expressionsTree.operator === FilteringLogic.Or) {
/** @type {?} */
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;
}
/** @type {?} */
let isComplex = false;
for (let i = 0; i < expressionsTree.filteringOperands.length; i++) {
isComplex = isComplex || this.isFilteringTreeComplex(expressionsTree.filteringOperands[i]);
}
return isComplex;
}
return false;
}
/**
* @private
* @param {?} expressions
* @return {?}
*/
getChildAndOperatorsCount(expressions) {
/** @type {?} */
let count = 0;
/** @type {?} */
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;
}
/**
* @param {?} expressions
* @param {?} operator
* @param {?} expressionsUIs
* @return {?}
*/
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;
}
}
/**
* @private
* @param {?} expressions
* @param {?} operator
* @param {?} expressionsUIs
* @return {?}
*/
generateExpressionsListRecursive(expressions, operator, expressionsUIs) {
if (!expressions) {
return;
}
if (expressions instanceof FilteringExpressionsTree) {
/** @type {?} */
const expressionsTree = (/** @type {?} */ (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 {
/** @type {?} */
const exprUI = new ExpressionUI();
exprUI.expression = (/** @type {?} */ (expressions));
exprUI.afterOperator = operator;
/** @type {?} */
const prevExprUI = expressionsUIs[expressionsUIs.length - 1];
if (prevExprUI) {
exprUI.beforeOperator = prevExprUI.afterOperator;
}
expressionsUIs.push(exprUI);
}
}
/**
* @return {?}
*/
isFilteringExpressionsTreeEmpty() {
/** @type {?} */
const expressionTree = this.grid.filteringExpressionsTree;
if (!expressionTree.filteringOperands || !expressionTree.filteringOperands.length) {
return true;
}
/** @type {?} */
let expr;
for (let i = 0; i < expressionTree.filteringOperands.length; i++) {
expr = expressionTree.filteringOperands[i];
if ((expr instanceof FilteringExpressionsTree)) {
/** @type {?} */
const exprTree = (/** @type {?} */ (expr));
if (exprTree.filteringOperands && exprTree.filteringOperands.length) {
return false;
}
}
else {
return false;
}
}
return true;
}
}
IgxFilteringService.decorators = [
{ type: Injectable }
];
/** @nocollapse */
IgxFilteringService.ctorParameters = () => [
{ type: GridBaseAPIService },
{ type: IgxIconService }
];
if (false) {
/**
* @type {?}
* @private
*/
IgxFilteringService.prototype.columnsWithComplexFilter;
/**
* @type {?}
* @private
*/
IgxFilteringService.prototype.areEventsSubscribed;
/**
* @type {?}
* @private
*/
IgxFilteringService.prototype.destroy$;
/**
* @type {?}
* @private
*/
IgxFilteringService.prototype.isFiltering;
/**
* @type {?}
* @private
*/
IgxFilteringService.prototype.columnToExpressionsMap;
/**
* @type {?}
* @private
*/
IgxFilteringService.prototype._datePipe;
/**
* @type {?}
* @private
*/
IgxFilteringService.prototype.columnStartIndex;
/** @type {?} */
IgxFilteringService.prototype.gridId;
/** @type {?} */
IgxFilteringService.prototype.isFilterRowVisible;
/** @type {?} */
IgxFilteringService.prototype.filteredColumn;
/** @type {?} */
IgxFilteringService.prototype.selectedExpression;
/** @type {?} */
IgxFilteringService.prototype.columnToFocus;
/** @type {?} */
IgxFilteringService.prototype.shouldFocusNext;
/** @type {?} */
IgxFilteringService.prototype.columnToMoreIconHidden;
/** @type {?} */
IgxFilteringService.prototype.grid;
/**
* @type {?}
* @private
*/
IgxFilteringService.prototype.gridAPI;
/**
* @type {?}
* @private
*/
IgxFilteringService.prototype.iconService;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JpZC1maWx0ZXJpbmcuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL2lnbml0ZXVpLWFuZ3VsYXIvIiwic291cmNlcyI6WyJsaWIvZ3JpZHMvZmlsdGVyaW5nL2dyaWQtZmlsdGVyaW5nLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQWEsTUFBTSxlQUFlLENBQUM7QUFDdEQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3pELE9BQU8sRUFBRSx3QkFBd0IsRUFBNkIsTUFBTSxrREFBa0QsQ0FBQztBQUV2SCxPQUFPLEtBQUssTUFBTSxZQUFZLENBQUM7QUFDL0IsT0FBTyxFQUF3QixjQUFjLEVBQUUsTUFBTSxzREFBc0QsQ0FBQztBQUM1RyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUUzQyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN4RCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUd0RCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7TUFFOUMsd0JBQXdCLEdBQUcsaUJBQWlCOzs7O0FBS2xELE1BQU0sT0FBTyxZQUFZO0lBQXpCO1FBSVcsZUFBVSxHQUFHLEtBQUssQ0FBQztRQUNuQixjQUFTLEdBQUcsSUFBSSxDQUFDO0lBQzVCLENBQUM7Q0FBQTs7O0lBTEcsa0NBQXdDOztJQUN4QyxzQ0FBc0M7O0lBQ3RDLHFDQUFxQzs7SUFDckMsa0NBQTBCOztJQUMxQixpQ0FBd0I7Ozs7O0FBTzVCLE1BQU0sT0FBTyxtQkFBbUI7Ozs7O0lBb0I1QixZQUFvQixPQUFxRSxFQUFVLFdBQTJCO1FBQTFHLFlBQU8sR0FBUCxPQUFPLENBQThEO1FBQVUsZ0JBQVcsR0FBWCxXQUFXLENB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LGlCQUFpQixJQUFJLENBQUMsY0FBYyxDQUFDLGlCQUFpQixDQUFDLE1BQU0sRUFBRTtZQUMvRSxPQUFPLElBQUksQ0FBQztTQUNmOztZQUVHLElBQVM7UUFFYixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsY0FBYyxDQUFDLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUM5RCxJQUFJLEdBQUcsY0FBYyxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRTNDLElBQUksQ0FBQyxJQUFJLFlBQVksd0JBQXdCLENBQUMsRUFBRTs7c0JBQ3RDLFFBQVEsR0FBRyxtQkFBQSxJQUFJLEVBQTRCO2dCQUNqRCxJQUFJLFFBQVEsQ0FBQyxpQkFBaUIsSUFBSSxRQUFRLENBQUMsaUJBQWlCLENBQUMsTUFBTSxFQUFFO29CQUNqRSxPQUFPLEtBQUssQ0FBQztpQkFDaEI7YUFDSjtpQkFBTTtnQkFDSCxPQUFPLEtBQUssQ0FBQzthQUNoQjtTQUNKO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQzs7O1lBNWVKLFVBQVU7Ozs7WUFsQkYsa0JBQWtCO1lBWmxCLGNBQWM7Ozs7Ozs7SUFpQ25CLHVEQUFxRDs7Ozs7SUFDckQsa0RBQW9DOzs7OztJQUNwQyx1Q0FBMEM7Ozs7O0lBQzFDLDBDQUE0Qjs7Ozs7SUFDNUIscURBQW1FOzs7OztJQUNuRSx3Q0FBd0M7Ozs7O0lBQ3hDLCtDQUE4Qjs7SUFFOUIscUNBQXNCOztJQUN0QixpREFBa0M7O0lBQ2xDLDZDQUFpRDs7SUFDakQsaURBQXVEOztJQUN2RCw0Q0FBZ0Q7O0lBQ2hELDhDQUErQjs7SUFDL0IscURBQTJEOztJQUUzRCxtQ0FBMkI7Ozs7O0lBRWYsc0NBQTZFOzs7OztJQUFFLDBDQUFtQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUsIE9uRGVzdHJveSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgSWd4SWNvblNlcnZpY2UgfSBmcm9tICcuLi8uLi9pY29uL2ljb24uc2VydmljZSc7XG5pbXBvcnQgeyBGaWx0ZXJpbmdFeHByZXNzaW9uc1RyZWUsIElGaWx0ZXJpbmdFeHByZXNzaW9uc1RyZWUgfSBmcm9tICcuLi8uLi9kYXRhLW9wZXJhdGlvbnMvZmlsdGVyaW5nLWV4cHJlc3Npb25zLXRyZWUnO1xuaW1wb3J0IHsgSWd4R3JpZEJhc2VDb21wb25lbnQsIElDb2x1bW5SZXNpemVFdmVudEFyZ3MsIElHcmlkRGF0YUJpbmRhYmxlIH0gZnJvbSAnLi4vZ3JpZC1iYXNlLmNvbXBvbmVudCc7XG5pbXBvcnQgaWNvbnMgZnJvbSAnLi9zdmdJY29ucyc7XG5pbXBvcnQgeyBJRmlsdGVyaW5nRXhwcmVzc2lvbiwgRmlsdGVyaW5nTG9naWMgfSBmcm9tICcuLi8uLi9kYXRhLW9wZXJhdGlvbnMvZmlsdGVyaW5nLWV4cHJlc3Npb24uaW50ZXJmYWNlJztcbmltcG9ydCB7IFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IElGb3JPZlN0YXRlIH0gZnJvbSAnLi4vLi4vZGlyZWN0aXZlcy9mb3Itb2YvZm9yX29mLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBJZ3hHcmlkU29ydGluZ1BpcGUgfSBmcm9tICcuLi9ncmlkL2dyaWQucGlwZXMnO1xuaW1wb3J0IHsgSWd4RGF0ZVBpcGVDb21wb25lbnQgfSBmcm9tICcuLi9ncmlkLmNvbW1vbic7XG5pbXBvcnQgeyBJZ3hDb2x1bW5Db21wb25lbnQgfSBmcm9tICcuLi9jb2x1bW4uY29tcG9uZW50JztcbmltcG9ydCB7IElGaWx0ZXJpbmdPcGVyYXRpb24gfSBmcm9tICcuLi8uLi9kYXRhLW9wZXJhdGlvbnMvZmlsdGVyaW5nLWNvbmRpdGlvbic7XG5pbXBvcnQgeyBHcmlkQmFzZUFQSVNlcnZpY2UgfSBmcm9tICcuLi9hcGkuc2VydmljZSc7XG5cbmNvbnN0IEZJTFRFUklOR19JQ09OU19GT05UX1NFVCA9ICdmaWx0ZXJpbmctaWNvbnMnO1xuXG4vKipcbiAqQGhpZGRlblxuICovXG5leHBvcnQgY2xhc3MgRXhwcmVzc2lvblVJIHtcbiAgICBwdWJsaWMgZXhwcmVzc2lvbjogSUZpbHRlcmluZ0V4cHJlc3Npb247XG4gICAgcHVibGljIGJlZm9yZU9wZXJhdG9yOiBGaWx0ZXJpbmdMb2dpYztcbiAgICBwdWJsaWMgYWZ0ZXJPcGVyYXRvcjogRmlsdGVyaW5nTG9naWM7XG4gICAgcHVibGljIGlzU2VsZWN0ZWQgPSBmYWxzZTtcbiAgICBwdWJsaWMgaXNWaXNpYmxlID0gdHJ1ZTtcbn1cblxuLyoqXG4gKkBoaWRkZW5cbiAqL1xuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIElneEZpbHRlcmluZ1NlcnZpY2UgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuXG4gICAgcHJpdmF0ZSBjb2x1bW5zV2l0aENvbXBsZXhGaWx0ZXIgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBwcml2YXRlIGFyZUV2ZW50c1N1YnNjcmliZWQgPSBmYWxzZTtcbiAgICBwcml2YXRlIGRlc3Ryb3kkID0gbmV3IFN1YmplY3Q8Ym9vbGVhbj4oKTtcbiAgICBwcml2YXRlIGlzRmlsdGVyaW5nID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBjb2x1bW5Ub0V4cHJlc3Npb25zTWFwID0gbmV3IE1hcDxzdHJpbmcsIEV4cHJlc3Npb25VSVtdPigpO1xuICAgIHByaXZhdGUgX2RhdGVQaXBlOiBJZ3hEYXRlUGlwZUNvbXBvbmVudDtcbiAgICBwcml2YXRlIGNvbHVtblN0YXJ0SW5kZXggPSAtMTtcblxuICAgIHB1YmxpYyBncmlkSWQ6IHN0cmluZztcbiAgICBwdWJsaWMgaXNGaWx0ZXJSb3dWaXNpYmxlID0gZmFsc2U7XG4gICAgcHVibGljIGZpbHRlcmVkQ29sdW1uOiBJZ3hDb2x1bW5Db21wb25lbnQgPSBudWxsO1xuICAgIHB1YmxpYyBzZWxlY3RlZEV4cHJlc3Npb246IElGaWx0ZXJpbmdFeHByZXNzaW9uID0gbnVsbDtcbiAgICBwdWJsaWMgY29sdW1uVG9Gb2N1czogSWd4Q29sdW1uQ29tcG9uZW50ID0gbnVsbDtcbiAgICBwdWJsaWMgc2hvdWxkRm9jdXNOZXh0ID0gZmFsc2U7XG4gICAgcHVibGljIGNvbHVtblRvTW9yZUljb25IaWRkZW4gPSBuZXcgTWFwPHN0cmluZywgYm9vbGVhbj4oKTtcblxuICAgIGdyaWQ6IElneEdyaWRCYXNlQ29tcG9uZW50O1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBncmlkQVBJOiBHcmlkQmFzZUFQSVNlcnZpY2U8SWd4R3JpZEJhc2VDb21wb25lbnQgJiBJR3JpZERhdGFCaW5kYWJsZT4sIHByaXZhdGUgaWNvblNlcnZpY2U6IElneEljb25TZXJ2aWNlKSB7fVxuXG4gICAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZGVzdHJveSQubmV4dCh0cnVlKTtcbiAgICAgICAgdGhpcy5kZXN0cm95JC5jb21wbGV0ZSgpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgZGlzcGxheUNvbnRhaW5lcldpZHRoKCkge1xuICAgICAgICByZXR1cm4gcGFyc2VJbnQodGhpcy5ncmlkLnBhcmVudFZpcnREaXIuZGMuaW5zdGFuY2UuX3ZpZXdDb250YWluZXIuZWxlbWVudC5uYXRpdmVFbGVtZW50Lm9mZnNldFdpZHRoLCAxMCk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCBkaXNwbGF5Q29udGFpbmVyU2Nyb2xsTGVmdCgpIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlSW50KHRoaXMuZ3JpZC5wYXJlbnRWaXJ0RGlyLmdldEhvcml6b250YWxTY3JvbGwoKS5zY3JvbGxMZWZ0LCAxMCk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCBhcmVBbGxDb2x1bW5zSW5WaWV3KCkge1xuICAgICAgICByZXR1cm4gcGFyc2VJbnQodGhpcy5ncmlkLnBhcmVudFZpcnREaXIuZGMuaW5zdGFuY2UuX3ZpZXdDb250YWluZXIuZWxlbWVudC5uYXRpdmVFbGVtZW50Lm9mZnNldFdpZHRoLCAxMCkgPT09IDA7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCB1bnBpbm5lZEZpbHRlcmFibGVDb2x1bW5zKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkLnVucGlubmVkQ29sdW1ucy5maWx0ZXIoY29sID0+ICFjb2wuY29sdW1uR3JvdXAgJiYgY29sLmZpbHRlcmFibGUpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgdW5waW5uZWRDb2x1bW5zKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkLnVucGlubmVkQ29sdW1ucy5maWx0ZXIoY29sID0+ICFjb2wuY29sdW1uR3JvdXApO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgZGF0ZVBpcGUoKTogSWd4RGF0ZVBpcGVDb21wb25lbnQge1xuICAgICAgICBpZiAoIXRoaXMuX2RhdGVQaXBlKSB7XG4gICAgICAgICAgICB0aGlzLl9kYXRlUGlwZSA9IG5ldyBJZ3hEYXRlUGlwZUNvbXBvbmVudCh0aGlzLmdyaWQubG9jYWxlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5fZGF0ZVBpcGU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIHRvIGdyaWQncyBldmVudHMuXG4gICAgICovXG4gICAgcHVibGljIHN1YnNjcmliZVRvRXZlbnRzKCkge1xuICAgICAgICBpZiAoIXRoaXMuYXJlRXZlbnRzU3Vic2NyaWJlZCkge1xuICAgICAgICAgICAgdGhpcy5hcmVFdmVudHNTdWJzY3JpYmVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgdGhpcy5ncmlkLm9uQ29sdW1uUmVzaXplZC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSkuc3Vic2NyaWJlKChldmVudEFyZ3M6IElDb2x1bW5SZXNpemVFdmVudEFyZ3MpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUZpbHRlcmluZ0NlbGwoZXZlbnRBcmdzLmNvbHVtbik7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdGhpcy5ncmlkLnBhcmVudFZpcnREaXIub25DaHVua0xvYWQucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpLnN1YnNjcmliZSgoZXZlbnRBcmdzOiBJRm9yT2ZTdGF0ZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChldmVudEFyZ3Muc3RhcnRJbmRleCAhPT0gdGhpcy5jb2x1bW5TdGFydEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29sdW1uU3RhcnRJbmRleCA9IGV2ZW50QXJncy5zdGFydEluZGV4O1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmdyaWQuZmlsdGVyQ2VsbExpc3QuZm9yRWFjaCgoZmlsdGVyQ2VsbCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyQ2VsbC51cGRhdGVGaWx0ZXJDZWxsQXJlYSgpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29sdW1uVG9Gb2N1cykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmZvY3VzRmlsdGVyQ2VsbENoaXAodGhpcy5jb2x1bW5Ub0ZvY3VzLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29sdW1uVG9Gb2N1cyA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHRoaXMuZ3JpZC5vbkNvbHVtbk1vdmluZ0VuZC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmdyaWQuZmlsdGVyQ2VsbExpc3QuZm9yRWFjaCgoZmlsdGVyQ2VsbCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBmaWx0ZXJDZWxsLnVwZGF0ZUZpbHRlckNlbGxBcmVhKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEludGVybmFsIG1ldGhvZCB0byBjcmVhdGUgZXhwcmVzc2lvbnNUcmVlIGFuZCBmaWx0ZXIgZ3JpZCB1c2VkIGluIGJvdGggZmlsdGVyIG1vZGVzLlxuICAgICAqL1xuICAgIHB1YmxpYyBmaWx0ZXJJbnRlcm5hbChmaWVsZDogc3RyaW5nLCBleHByZXNzaW9uczogRmlsdGVyaW5nRXhwcmVzc2lvbnNUcmVlIHwgQXJyYXk8RXhwcmVzc2lvblVJPiA9IG51bGwpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5pc0ZpbHRlcmluZyA9IHRydWU7XG5cbiAgICAgICAgbGV0IGV4cHJlc3Npb25zVHJlZTtcbiAgICAgICAgaWYgKGV4cHJlc3Npb25zIGluc3RhbmNlb2YgRmlsdGVyaW5nRXhwcmVzc2lvbnNUcmVlKSB7XG4gICAgICAgICAgICBleHByZXNzaW9uc1RyZWUgPSBleHByZXNzaW9ucztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGV4cHJlc3Npb25zVHJlZSA9IHRoaXMuY3JlYXRlU2ltcGxlRmlsdGVyaW5nVHJlZShmaWVsZCwgZXhwcmVzc2lvbnMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGV4cHJlc3Npb25zVHJlZS5maWx0ZXJpbmdPcGVyYW5kcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHRoaXMuY2xlYXJGaWx0ZXIoZmllbGQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5maWx0ZXIoZmllbGQsIG51bGwsIGV4cHJlc3Npb25zVHJlZSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmlzRmlsdGVyaW5nID0gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXhlY3V0ZSBmaWx0ZXJpbmcgb24gdGhlIGdyaWQuXG4gICAgICovXG4gICAgcHVibGljIGZpbHRlcihmaWVsZDogc3RyaW5nLCB2YWx1ZTogYW55LCBjb25kaXRpb25PckV4cHJlc3Npb25UcmVlPzogSUZpbHRlcmluZ09wZXJhdGlvbiB8IElGaWx0ZXJpbmdFeHByZXNzaW9uc1RyZWUsXG4gICAgICAgIGlnbm9yZUNhc2U/OiBib29sZWFuKSB7XG4gICAgICAgIGNvbnN0IGNvbCA9IHRoaXMuZ3JpZEFQSS5nZXRfY29sdW1uX2J5X25hbWUoZmllbGQpO1xuICAgICAgICBjb25zdCBmaWx0ZXJpbmdJZ25vcmVDYXNlID0gaWdub3JlQ2FzZSB8fCAoY29sID8gY29sLmZpbHRlcmluZ0lnbm9yZUNhc2UgOiBmYWxzZSk7XG5cbiAgICAgICAgaWYgKGNvbmRpdGlvbk9yRXhwcmVzc2lvblRyZWUpIHtcbiAgICAgICAgICAgIHRoaXMuZ3JpZEFQSS5maWx0ZXIoZmllbGQ