From 1b0c5ecc3464374d9e449ce96d0334df04fc30b7 Mon Sep 17 00:00:00 2001 From: chvostek Date: Wed, 15 Jul 2026 13:01:20 +0200 Subject: [PATCH 01/55] [NAE-2466] Advanced search for PFQL - add todos --- .../src/lib/search/models/category/case/case-author.ts | 1 + .../search/models/category/case/case-creation-date-time.ts | 2 ++ .../lib/search/models/category/case/case-creation-date.ts | 1 + .../src/lib/search/models/category/case/case-process.ts | 1 + .../src/lib/search/models/category/case/case-role.ts | 2 ++ .../src/lib/search/models/category/case/case-string-id.ts | 3 ++- .../src/lib/search/models/category/case/case-task.ts | 2 ++ .../src/lib/search/models/category/case/case-title.ts | 3 ++- .../src/lib/search/models/category/case/case-visual-id.ts | 2 ++ .../src/lib/search/models/category/task/task-assignee.ts | 7 ++++++- .../src/lib/search/models/category/task/task-process.ts | 1 + .../src/lib/search/models/category/task/task-role.ts | 2 ++ .../src/lib/search/models/category/task/task-task.ts | 1 + 13 files changed, 25 insertions(+), 3 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-author.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-author.ts index 37bd553bf9..1c2b87808f 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-author.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-author.ts @@ -15,6 +15,7 @@ export class CaseAuthor extends NoConfigurationUserAutocompleteCategory { constructor(operators: OperatorService, logger: LoggerService, optionalDependencies: OptionalDependencies) { super([CaseSearch.AUTHOR], [operators.getOperator(Equals), operators.getOperator(NotEquals)], + // todo 2466 contains, lt, gt, lte, gte, in list `${CaseAuthor._i18n}.name`, logger, operators, diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date-time.ts index e0d006ee49..46af77e85c 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date-time.ts @@ -18,6 +18,8 @@ import {NotEqualsDateTime} from '../../operator/not-equals-date-time'; export class CaseCreationDateTime extends NoConfigurationCategory { + // todo 2466 mb only one creationDate component is enough? + private static readonly _i18n = 'search.category.case.creationDateTime'; constructor(operators: OperatorService, logger: LoggerService) { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date.ts index 73c3210b21..fff5f83ed6 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date.ts @@ -30,6 +30,7 @@ export class CaseCreationDate extends NoConfigurationCategory { operators.getOperator(LessThanEqualDate), operators.getOperator(InRangeDate) ], + // todo 2466 in list `${CaseCreationDate._i18n}.name`, SearchInputType.DATE, logger, diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts index 2d77def9a3..570fa873d8 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts @@ -21,6 +21,7 @@ export class CaseProcess extends NoConfigurationAutocompleteCategory { constructor(operators: OperatorService, logger: LoggerService, protected _optionalDependencies: OptionalDependencies) { super([CaseSearch.PROCESS_IDENTIFIER], [operators.getOperator(Equals), operators.getOperator(NotEquals)], + // todo 2466 contains, lt, gt, lte, gte, in list `${CaseProcess._i18n}.name`, logger, operators); diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-role.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-role.ts index f72654a3a5..b57b3cd45a 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-role.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-role.ts @@ -11,6 +11,8 @@ import {CaseSearch} from './case-search.enum'; export class CaseRole extends CaseNetAttributeAutocompleteCategory { + // todo 2466 impossible in pfql + private static readonly _i18n = 'search.category.case.role'; constructor(operators: OperatorService, logger: LoggerService, optionalDependencies: OptionalDependencies) { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-string-id.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-string-id.ts index 2d71fbc51b..cccb25d146 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-string-id.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-string-id.ts @@ -15,10 +15,11 @@ export class CaseStringId extends NoConfigurationCategory { constructor(operators: OperatorService, logger: LoggerService) { super([CaseSearch.STRING_ID], [ - operators.getOperator(Substring), + operators.getOperator(Substring),// todo 2466 pfql has missing substring operator on case id operators.getOperator(Equals), operators.getOperator(NotEquals) ], + // todo 2466 in list `${CaseStringId._i18n}.name`, SearchInputType.TEXT, logger, diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-task.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-task.ts index ff749335a7..969564ca53 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-task.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-task.ts @@ -11,6 +11,8 @@ import {CaseSearch} from './case-search.enum'; export class CaseTask extends CaseNetAttributeAutocompleteCategory { + // todo 2466 impossible in PFQL + private static readonly _i18n = 'search.category.case.task'; constructor(operators: OperatorService, logger: LoggerService, optionalDependencies: OptionalDependencies) { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.ts index 2239e23bf2..2683ba7db2 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.ts @@ -20,8 +20,9 @@ export class CaseTitle extends NoConfigurationCategory { operators.getOperator(Substring), operators.getOperator(Equals), operators.getOperator(NotEquals), - operators.getOperator(Like) + operators.getOperator(Like) // todo 2466 no such operat Like in pfql ], + // todo 2466 in list, lt, gt, lte, gte `${CaseTitle._i18n}.name`, SearchInputType.TEXT, logger, diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.ts index d009b9fed9..c804f05248 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.ts @@ -11,6 +11,8 @@ import {OptionalDependencies} from '../../../category-factory/optional-dependenc export class CaseVisualId extends NoConfigurationCategory { + // todo 2466 impossible in pfql + private static readonly _i18n = 'search.category.case.visualId'; constructor(operators: OperatorService, logger: LoggerService, protected _optionalDependencies?: OptionalDependencies) { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-assignee.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-assignee.ts index 803cbe8a59..712554342a 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-assignee.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-assignee.ts @@ -14,7 +14,12 @@ export class TaskAssignee extends NoConfigurationUserAutocompleteCategory { constructor(operators: OperatorService, logger: LoggerService, optionalDependencies: OptionalDependencies) { super(['userId'], - [operators.getOperator(Equals), operators.getOperator(NotEquals), operators.getOperator(IsNull)], + [ + operators.getOperator(Equals), + operators.getOperator(NotEquals), + operators.getOperator(IsNull) // todo 2466 no such operator IsNull in PFQL + ], + // todo 2466 contains, lt, gt, lte, gte, in list `${TaskAssignee._i18n}.name`, logger, operators, diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts index a5647f3281..078a021834 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts @@ -19,6 +19,7 @@ export class TaskProcess extends NoConfigurationAutocompleteCategory { constructor(operators: OperatorService, logger: LoggerService, protected _optionalDependencies: OptionalDependencies) { super(['processId'], [operators.getOperator(Equals), operators.getOperator(NotEquals)], + // todo 2466 contains, lt, gt, lte, gte, in list `${TaskProcess._i18n}.name`, logger, operators); diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-role.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-role.ts index c2fbc37133..80191d60be 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-role.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-role.ts @@ -10,6 +10,8 @@ import {Categories} from '../categories'; export class TaskRole extends TaskNetAttributeAutocompleteCategory { + // todo 2466 impossible in pfql + private static readonly _i18n = 'search.category.task.role'; constructor(operators: OperatorService, logger: LoggerService, optionalDependencies: OptionalDependencies) { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts index 22f1a5ecd2..bcf370b828 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts @@ -16,6 +16,7 @@ export class TaskTask extends TaskNetAttributeAutocompleteCategory { constructor(operators: OperatorService, logger: LoggerService, optionalDependencies: OptionalDependencies) { super(['transitionId'], [operators.getOperator(Equals), operators.getOperator(NotEquals)], + // todo 2466 contains, lt, gt, lte, gte, in list, in range `${TaskTask._i18n}.name`, logger, operators, From d619953f511182f1d43ba13a354d721e47b9cc31 Mon Sep 17 00:00:00 2001 From: chvostek Date: Sat, 18 Jul 2026 10:43:07 +0200 Subject: [PATCH 02/55] [NAE-2466] Advanced search for PFQL - update advanced search to use PFQL query --- .../category-resolver.service.ts | 10 +- .../default-categories-factories.ts | 6 +- .../default-search-categories.module.ts | 4 - .../models/category/autocomplete-category.ts | 8 +- .../models/category/case/case-author.ts | 5 +- .../category/case/case-creation-date-time.ts | 6 +- .../category/case/case-creation-date.ts | 5 +- .../models/category/case/case-dataset.ts | 105 ++++++-------- ...ase-net-attribute-autocomplete-category.ts | 6 +- .../models/category/case/case-process.ts | 9 +- .../search/models/category/case/case-role.ts | 4 +- .../models/category/case/case-search.enum.ts | 4 +- .../category/case/case-simple-dataset.ts | 58 ++------ .../models/category/case/case-string-id.ts | 7 +- .../models/category/case/case-task.spec.ts | 136 ------------------ .../search/models/category/case/case-task.ts | 42 ------ .../search/models/category/case/case-title.ts | 24 ++-- .../models/category/case/case-visual-id.ts | 8 +- .../lib/search/models/category/categories.ts | 1 - .../lib/search/models/category/category.ts | 26 ++-- .../net-attribute-autocomplete-category.ts | 13 +- .../no-configuration-autocomplete-category.ts | 8 +- .../category/no-configuration-category.ts | 7 +- ...onfiguration-user-autocomplete-category.ts | 11 +- .../category/resource-type-query-prefix.ts | 9 ++ .../models/category/task/task-assignee.ts | 7 +- ...ask-net-attribute-autocomplete-category.ts | 8 +- .../models/category/task/task-process.ts | 9 +- .../search/models/category/task/task-role.ts | 4 +- .../search/models/category/task/task-task.ts | 5 +- .../models/category/user-autocomplete.ts | 2 +- .../lib/search/models/datafield-map-key.ts | 2 +- .../models/operator/equals-date-time.ts | 4 +- .../lib/search/models/operator/equals-date.ts | 4 +- .../src/lib/search/models/operator/equals.ts | 2 +- .../models/operator/in-range-date-time.ts | 8 +- .../search/models/operator/in-range-date.ts | 11 +- .../lib/search/models/operator/in-range.ts | 4 +- .../src/lib/search/models/operator/is-null.ts | 5 +- .../models/operator/less-than-date-time.ts | 4 +- .../search/models/operator/less-than-date.ts | 6 +- .../operator/less-than-equal-date-time.ts | 6 +- .../models/operator/less-than-equal-date.ts | 4 +- .../search/models/operator/less-than-equal.ts | 6 +- .../lib/search/models/operator/less-than.ts | 6 +- .../src/lib/search/models/operator/like.ts | 4 +- .../models/operator/more-than-date-time.ts | 4 +- .../search/models/operator/more-than-date.ts | 6 +- .../operator/more-than-equal-date-time.ts | 4 +- .../models/operator/more-than-equal-date.ts | 6 +- .../search/models/operator/more-than-equal.ts | 6 +- .../lib/search/models/operator/more-than.ts | 6 +- .../models/operator/not-equals-date-time.ts | 6 +- .../search/models/operator/not-equals-date.ts | 6 +- .../lib/search/models/operator/not-equals.ts | 19 +-- .../lib/search/models/operator/operator.ts | 39 ++--- .../lib/search/models/operator/operators.ts | 4 +- .../lib/search/models/operator/substring.ts | 12 +- .../filter-metadata-allowed-nets.ts | 1 + .../models/persistance/filter-metadata.ts | 1 + .../persistance/saved-filter-metadata.ts | 1 + .../src/lib/search/models/query/query.ts | 82 +++++++++-- .../src/lib/search/models/search-index.ts | 1 + .../operator-resolver.service.ts | 8 +- .../src/lib/search/public-api.ts | 2 +- .../search-index-resolver.service.ts | 2 + ...abstract-search-operand-input.component.ts | 10 ++ .../utility/clear-time-information.spec.ts | 32 ----- .../src/lib/utility/clear-time-information.ts | 12 -- .../src/lib/utility/public-api.ts | 1 - .../search-operand-input.component.html | 4 +- .../search-operand-input.component.ts | 3 - 72 files changed, 357 insertions(+), 554 deletions(-) delete mode 100644 projects/netgrif-components-core/src/lib/search/models/category/case/case-task.spec.ts delete mode 100644 projects/netgrif-components-core/src/lib/search/models/category/case/case-task.ts create mode 100644 projects/netgrif-components-core/src/lib/search/models/category/resource-type-query-prefix.ts delete mode 100644 projects/netgrif-components-core/src/lib/utility/clear-time-information.spec.ts delete mode 100644 projects/netgrif-components-core/src/lib/utility/clear-time-information.ts diff --git a/projects/netgrif-components-core/src/lib/search/category-factory/category-resolver.service.ts b/projects/netgrif-components-core/src/lib/search/category-factory/category-resolver.service.ts index f7ae93913f..533ae48a52 100644 --- a/projects/netgrif-components-core/src/lib/search/category-factory/category-resolver.service.ts +++ b/projects/netgrif-components-core/src/lib/search/category-factory/category-resolver.service.ts @@ -7,9 +7,7 @@ import {CaseDataset} from '../models/category/case/case-dataset'; import {CaseProcess} from '../models/category/case/case-process'; import {CaseRole} from '../models/category/case/case-role'; import {CaseSimpleDataset} from '../models/category/case/case-simple-dataset'; -import {CaseTask} from '../models/category/case/case-task'; import {CaseTitle} from '../models/category/case/case-title'; -import {CaseVisualId} from '../models/category/case/case-visual-id'; import {CaseStringId} from '../models/category/case/case-string-id'; import {TaskAssignee} from '../models/category/task/task-assignee'; import {TaskProcess} from '../models/category/task/task-process'; @@ -36,7 +34,7 @@ export class CategoryResolverService { } /** - * Registers the default class - serialisation pairings for all the {@link Category} classes provided by this library. + * Registers the default class - serialization pairings for all the {@link Category} classes provided by this library. */ private registerDefaultPairings(): void { [ @@ -62,15 +60,9 @@ export class CategoryResolverService { }, { classReference: CaseSimpleDataset, serialized: Categories.CASE_SIMPLE_DATASET - }, { - classReference: CaseTask, - serialized: Categories.CASE_TASK }, { classReference: CaseTitle, serialized: Categories.CASE_TITLE - }, { - classReference: CaseVisualId, - serialized: Categories.CASE_VISUAL_ID }, { classReference: CaseStringId, serialized: Categories.CASE_STRING_ID diff --git a/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.ts b/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.ts index 66f9ffefce..8a382433dc 100644 --- a/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.ts +++ b/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.ts @@ -1,11 +1,9 @@ import {Category} from '../models/category/category'; import {CategoryFactory} from './category-factory'; import {CaseTitle} from '../models/category/case/case-title'; -import {CaseVisualId} from '../models/category/case/case-visual-id'; import {CaseStringId} from '../models/category/case/case-string-id'; import {CaseAuthor} from '../models/category/case/case-author'; import {CaseProcess} from '../models/category/case/case-process'; -import {CaseTask} from '../models/category/case/case-task'; import {CaseCreationDate} from '../models/category/case/case-creation-date'; import {CaseDataset} from '../models/category/case/case-dataset'; import {TaskAssignee} from '../models/category/task/task-assignee'; @@ -24,7 +22,7 @@ import {CaseCreationDateTime} from '../models/category/case/case-creation-date-t * [duplicate()]{@link Category#duplicate} method. * * @returns an Array containing the default case search categories: {@link CaseDataset}, {@link CaseTitle}, {@link CaseCreationDate}, - * {@link CaseProcess}, {@link CaseTask}, {@link CaseAuthor}, {@link CaseVisualId} and {@link CaseStringId} + * {@link CaseProcess}, {@link CaseAuthor}, and {@link CaseStringId} * * @deprecated in 5.6.0 - Use the {@link NAE_DEFAULT_CASE_SEARCH_CATEGORIES} injection token instead */ @@ -35,9 +33,7 @@ export function defaultCaseSearchCategoriesFactory(factory: CategoryFactory): Ar factory.get(CaseCreationDate), factory.get(CaseCreationDateTime), factory.get(CaseProcess), - factory.get(CaseTask), factory.get(CaseAuthor), - factory.get(CaseVisualId), factory.get(CaseStringId), ]; cats.forEach(cat => cat.destroy()); diff --git a/projects/netgrif-components-core/src/lib/search/category-factory/default-search-categories.module.ts b/projects/netgrif-components-core/src/lib/search/category-factory/default-search-categories.module.ts index a8e5c6b9bf..5d408be1f0 100644 --- a/projects/netgrif-components-core/src/lib/search/category-factory/default-search-categories.module.ts +++ b/projects/netgrif-components-core/src/lib/search/category-factory/default-search-categories.module.ts @@ -4,9 +4,7 @@ import {CaseDataset} from '../models/category/case/case-dataset'; import {CaseTitle} from '../models/category/case/case-title'; import {CaseCreationDate} from '../models/category/case/case-creation-date'; import {CaseProcess} from '../models/category/case/case-process'; -import {CaseTask} from '../models/category/case/case-task'; import {CaseAuthor} from '../models/category/case/case-author'; -import {CaseVisualId} from '../models/category/case/case-visual-id'; import {TaskAssignee} from '../models/category/task/task-assignee'; import {TaskTask} from '../models/category/task/task-task'; import {TaskProcess} from '../models/category/task/task-process'; @@ -27,9 +25,7 @@ import {CaseStringId} from '../models/category/case/case-string-id'; CaseCreationDate, CaseCreationDateTime, CaseProcess, - CaseTask, CaseAuthor, - CaseVisualId, CaseStringId, ] }, { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/autocomplete-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/autocomplete-category.ts index 1b7ac3d492..c6c05e236b 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/autocomplete-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/autocomplete-category.ts @@ -8,6 +8,7 @@ import {filter, map, startWith, take} from 'rxjs/operators'; import {AutocompleteOptions} from './autocomplete-options'; import {FormControl} from '@angular/forms'; import {OperatorService} from '../../operator-service/operator.service'; +import {ResourceTypeQueryPrefix} from "./resource-type-query-prefix"; /** * Represents a Search Category whose values are a known set. The value selection is done with an autocomplete field. @@ -31,12 +32,13 @@ export abstract class AutocompleteCategory extends Category> impleme private readonly _timeoutId: number; - protected constructor(elasticKeywords: Array, + protected constructor(pfqlKeywords: Array, allowedOperators: Array>, translationPath: string, log: LoggerService, - operatorService: OperatorService) { - super(elasticKeywords, allowedOperators, translationPath, SearchInputType.AUTOCOMPLETE, log, operatorService); + operatorService: OperatorService, + resourceTypePrefix: ResourceTypeQueryPrefix) { + super(pfqlKeywords, allowedOperators, translationPath, SearchInputType.AUTOCOMPLETE, log, operatorService, resourceTypePrefix); this._optionsMap = new Map>(); this._options$ = new BehaviorSubject>>>([]); // timeout is used to bypass javascript object initialization bugs. diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-author.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-author.ts index 1c2b87808f..0df914db8e 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-author.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-author.ts @@ -6,6 +6,7 @@ import {Categories} from '../categories'; import {CaseSearch} from './case-search.enum'; import {OptionalDependencies} from '../../../category-factory/optional-dependencies'; import {NoConfigurationUserAutocompleteCategory} from '../no-configuration-user-autocomplete-category'; +import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; export class CaseAuthor extends NoConfigurationUserAutocompleteCategory { @@ -15,12 +16,12 @@ export class CaseAuthor extends NoConfigurationUserAutocompleteCategory { constructor(operators: OperatorService, logger: LoggerService, optionalDependencies: OptionalDependencies) { super([CaseSearch.AUTHOR], [operators.getOperator(Equals), operators.getOperator(NotEquals)], - // todo 2466 contains, lt, gt, lte, gte, in list `${CaseAuthor._i18n}.name`, logger, operators, 'CaseAuthor', - optionalDependencies); + optionalDependencies, + ResourceTypeQueryPrefix.CASES); } get inputPlaceholder(): string { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date-time.ts index 46af77e85c..f7f07a81d1 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date-time.ts @@ -14,12 +14,11 @@ import {InRangeDateTime} from '../../operator/in-range-date-time'; import {LessThanDateTime} from '../../operator/less-than-date-time'; import {CaseSearch} from './case-search.enum'; import {NotEqualsDateTime} from '../../operator/not-equals-date-time'; +import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; export class CaseCreationDateTime extends NoConfigurationCategory { - // todo 2466 mb only one creationDate component is enough? - private static readonly _i18n = 'search.category.case.creationDateTime'; constructor(operators: OperatorService, logger: LoggerService) { @@ -36,7 +35,8 @@ export class CaseCreationDateTime extends NoConfigurationCategory { `${CaseCreationDateTime._i18n}.name`, SearchInputType.DATE_TIME, logger, - operators); + operators, + ResourceTypeQueryPrefix.CASES); } get inputPlaceholder(): string { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date.ts index fff5f83ed6..70a1822f07 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date.ts @@ -14,6 +14,7 @@ import {Observable, of} from 'rxjs'; import {MoreThanEqualDate} from '../../operator/more-than-equal-date'; import {LessThanEqualDate} from '../../operator/less-than-equal-date'; import {CaseSearch} from './case-search.enum'; +import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; export class CaseCreationDate extends NoConfigurationCategory { @@ -30,11 +31,11 @@ export class CaseCreationDate extends NoConfigurationCategory { operators.getOperator(LessThanEqualDate), operators.getOperator(InRangeDate) ], - // todo 2466 in list `${CaseCreationDate._i18n}.name`, SearchInputType.DATE, logger, - operators); + operators, + ResourceTypeQueryPrefix.CASES); } get inputPlaceholder(): string { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts index 3f8202c32a..c4434d36de 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts @@ -18,8 +18,6 @@ import { NotEquals } from '../../operator/not-equals'; import { MoreThan } from '../../operator/more-than'; import { LessThan } from '../../operator/less-than'; import { InRange } from '../../operator/in-range'; -import { IsNull } from '../../operator/is-null'; -import { Like } from '../../operator/like'; import { NotEqualsDate } from '../../operator/not-equals-date'; import { MoreThanDate } from '../../operator/more-than-date'; import { LessThanDate } from '../../operator/less-than-date'; @@ -29,7 +27,6 @@ import { LessThanDateTime } from '../../operator/less-than-date-time'; import { InRangeDateTime } from '../../operator/in-range-date-time'; import { AutocompleteOptions } from '../autocomplete-options'; import { ConfigurationInput } from '../../configuration-input'; -import { SearchIndex } from '../../search-index'; import { Categories } from '../categories'; import { FormControl } from '@angular/forms'; import moment, { Moment } from 'moment'; @@ -42,6 +39,8 @@ import { MoreThanEqualDateTime } from '../../operator/more-than-equal-date-time' import { LessThanEqualDateTime } from '../../operator/less-than-equal-date-time'; import { FilterTextSegment } from '../../persistance/filter-text-segment'; import { UserAutocomplete } from '../user-autocomplete'; +import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; +import {FieldTypeResource} from "../../../../task-content/model/field-type-resource"; interface Datafield { netIdentifier: string; @@ -52,7 +51,9 @@ interface Datafield { export class CaseDataset extends Category implements AutocompleteOptions { private static readonly _i18n = 'search.category.case.dataset'; - protected static DISABLED_TYPES = ['button', 'taskRef', 'caseRef', 'filter']; + protected static DISABLED_TYPES = [FieldTypeResource.BOOLEAN.valueOf(), FieldTypeResource.TASK_REF.valueOf(), + FieldTypeResource.CASE_REF.valueOf(), FieldTypeResource.CASE_FILTER.valueOf(), FieldTypeResource.TASK_FILTER.valueOf(), + FieldTypeResource.PROCESS_FILTER.valueOf()]; protected static readonly DATAFIELD_METADATA = 'datafield'; private static readonly AUTOCOMPLETE_ICON = 'account_circle'; @@ -70,15 +71,15 @@ export class CaseDataset extends Category implements AutocompleteOpti public static FieldTypeToInputType(fieldType: string): SearchInputType { switch (fieldType) { - case 'date': + case FieldTypeResource.DATE.valueOf(): return SearchInputType.DATE; - case 'dateTime': + case FieldTypeResource.DATE_TIME.valueOf(): return SearchInputType.DATE_TIME; - case 'number': + case FieldTypeResource.NUMBER.valueOf(): return SearchInputType.NUMBER; - case 'boolean': + case FieldTypeResource.BOOLEAN.valueOf(): return SearchInputType.BOOLEAN; - case 'user': + case FieldTypeResource.USER.valueOf(): return SearchInputType.AUTOCOMPLETE; default: return SearchInputType.TEXT; @@ -91,7 +92,8 @@ export class CaseDataset extends Category implements AutocompleteOpti `${CaseDataset._i18n}.name`, undefined, logger, - operators); + operators, + ResourceTypeQueryPrefix.CASES); this._processCategory = this._optionalDependencies.categoryFactory.get(CaseProcess) as CaseProcess; this._processCategory.selectDefaultOperator(); @@ -157,7 +159,7 @@ export class CaseDataset extends Category implements AutocompleteOpti return []; } switch (this._selectedDatafields[0].fieldType) { - case 'number': + case FieldTypeResource.NUMBER.valueOf(): return [ this._operatorService.getOperator(Equals), this._operatorService.getOperator(NotEquals), @@ -166,21 +168,21 @@ export class CaseDataset extends Category implements AutocompleteOpti this._operatorService.getOperator(LessThan), this._operatorService.getOperator(LessThanEqual), this._operatorService.getOperator(InRange), - this._operatorService.getOperator(IsNull) + // this._operatorService.getOperator(IsNull) todo 2466 ]; - case 'boolean': + case FieldTypeResource.BOOLEAN.valueOf(): return [ this._operatorService.getOperator(Equals), this._operatorService.getOperator(NotEquals) ]; - case 'user': - case 'userList': + case FieldTypeResource.USER.valueOf(): + case FieldTypeResource.USER_LIST.valueOf(): return [ this._operatorService.getOperator(Equals), this._operatorService.getOperator(NotEquals), - this._operatorService.getOperator(IsNull) + // this._operatorService.getOperator(IsNull) todo 2466 ]; - case 'date': + case FieldTypeResource.DATE.valueOf(): return [ this._operatorService.getOperator(EqualsDate), this._operatorService.getOperator(NotEqualsDate), @@ -189,9 +191,9 @@ export class CaseDataset extends Category implements AutocompleteOpti this._operatorService.getOperator(LessThanDate), this._operatorService.getOperator(LessThanEqualDate), this._operatorService.getOperator(InRangeDate), - this._operatorService.getOperator(IsNull) + // this._operatorService.getOperator(IsNull) todo 2466 ]; - case 'dateTime': + case FieldTypeResource.DATE_TIME.valueOf(): return [ this._operatorService.getOperator(EqualsDateTime), this._operatorService.getOperator(MoreThanDateTime), @@ -199,15 +201,19 @@ export class CaseDataset extends Category implements AutocompleteOpti this._operatorService.getOperator(LessThanDateTime), this._operatorService.getOperator(LessThanEqualDateTime), this._operatorService.getOperator(InRangeDateTime), - this._operatorService.getOperator(IsNull) + // this._operatorService.getOperator(IsNull) todo 2466 ]; default: return [ this._operatorService.getOperator(Substring), this._operatorService.getOperator(Equals), this._operatorService.getOperator(NotEquals), - this._operatorService.getOperator(IsNull), - this._operatorService.getOperator(Like) + this._operatorService.getOperator(MoreThan), + this._operatorService.getOperator(MoreThanEqual), + this._operatorService.getOperator(LessThan), + this._operatorService.getOperator(LessThanEqual), + // this._operatorService.getOperator(IsNull), todo 2466 + // this._operatorService.getOperator(Like) ]; } } @@ -236,39 +242,11 @@ export class CaseDataset extends Category implements AutocompleteOpti return new CaseDataset(this._operatorService, this._log, this._optionalDependencies); } - protected get elasticKeywords(): Array { + protected get pfqlKeywords(): Array { if (!this.hasSelectedDatafields) { return []; } else { - return this._selectedDatafields.map(datafield => this.resolveElasticKeyword(datafield)); - } - } - - protected resolveElasticKeyword(datafield: Datafield): string { - const resolver = this._optionalDependencies.searchIndexResolver; - switch (datafield.fieldType) { - case 'number': - return resolver.getIndex(datafield.fieldId, SearchIndex.NUMBER); - case 'date': - case 'dateTime': - return resolver.getIndex(datafield.fieldId, SearchIndex.TIMESTAMP); - case 'boolean': - return resolver.getIndex(datafield.fieldId, SearchIndex.BOOLEAN); - case 'file': - case 'fileList': - return resolver.getIndex(datafield.fieldId, SearchIndex.FILE_NAME, - this.isSelectedOperator(Equals) || this.isSelectedOperator(NotEquals) || this.isSelectedOperator(Substring) - || this.isSelectedOperator(IsNull)); - case 'user': - case 'userList': - return resolver.getIndex(datafield.fieldId, SearchIndex.USER_ID); - case 'i18n': - return resolver.getIndex(datafield.fieldId, SearchIndex.TEXT, this.isSelectedOperator(Equals) || this.isSelectedOperator(NotEquals) || this.isSelectedOperator(Substring) - || this.isSelectedOperator(IsNull)); - default: - return resolver.getIndex(datafield.fieldId, SearchIndex.FULLTEXT, - this.isSelectedOperator(Equals) || this.isSelectedOperator(NotEquals) || this.isSelectedOperator(Substring) - || this.isSelectedOperator(IsNull)); + return this._selectedDatafields.map(dataField => `data.${dataField.fieldId}.value`); } } @@ -285,9 +263,10 @@ export class CaseDataset extends Category implements AutocompleteOpti protected generateQuery(userInput: Array): Query { let queryGenerationStrategy; - if (this.isSelectedOperator(IsNull)) { + // todo 2466 remove if + /*if (this.isSelectedOperator(IsNull)) { queryGenerationStrategy = (d, _) => this.isNullOperatorQueryGenerationStrategy(d); - } else if (this.inputType === SearchInputType.AUTOCOMPLETE) { + } else*/ if (this.inputType === SearchInputType.AUTOCOMPLETE) { queryGenerationStrategy = (d, ui) => this.standardQueryGenerationStrategy(d, ui[0], false); } else { queryGenerationStrategy = (d, ui) => this.standardQueryGenerationStrategy(d, ui); @@ -298,15 +277,17 @@ export class CaseDataset extends Category implements AutocompleteOpti } protected standardQueryGenerationStrategy(datafield: Datafield, userInput: Array, escapeInput = true): Query { - const valueQuery = this.selectedOperator.createQuery(this.elasticKeywords, userInput, escapeInput); + const valueQuery = this.selectedOperator.createQuery(this.pfqlKeywords, userInput, escapeInput); const netQuery = this.generateNetConstraint(datafield); - return Query.combineQueries([valueQuery, netQuery], BooleanOperator.AND); + const query: Query = Query.combineQueries([valueQuery, netQuery], BooleanOperator.AND); + return query.addPrefixAndGet(ResourceTypeQueryPrefix.CASES); } - protected isNullOperatorQueryGenerationStrategy(datafield: Datafield): Query { - const constraint = this.generateNetConstraint(datafield); - return (this._operatorService.getOperator(IsNull) as IsNull).createQueryWithConstraint(this.elasticKeywords, constraint); - } + // todo 2466 + // protected isNullOperatorQueryGenerationStrategy(datafield: Datafield): Query { + // const constraint = this.generateNetConstraint(datafield); + // return (this._operatorService.getOperator(IsNull) as IsNull).createQueryWithConstraint(this.pfqlKeywords, constraint); + // } protected generateNetConstraint(datafield: Datafield): Query { return this._processCategory.generatePredicate([[datafield.netIdentifier]]).query; @@ -326,9 +307,9 @@ export class CaseDataset extends Category implements AutocompleteOpti let type = immediateData.type; // for search purposes, enumeration and multichoice maps are equivalent to their simpler counterparts - if (type === 'enumeration_map') { + if (type === FieldTypeResource.ENUMERATION_MAP.valueOf()) { type = 'enumeration'; - } else if (type === 'multichoice_map') { + } else if (type === FieldTypeResource.MULTICHOICE_MAP.valueOf()) { type = 'multichoice'; } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-net-attribute-autocomplete-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-net-attribute-autocomplete-category.ts index f8c61c5280..3ae57e55db 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-net-attribute-autocomplete-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-net-attribute-autocomplete-category.ts @@ -6,6 +6,7 @@ import {CaseProcess} from './case-process'; import {Net} from '../../../../process/net'; import {Category} from '../category'; import {OperatorService} from '../../../operator-service/operator.service'; +import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; /** * Utility class with the same use as its parent but witch Case search specific methods implemented. @@ -19,8 +20,9 @@ export abstract class CaseNetAttributeAutocompleteCategory extends NetAttributeA translationPath: string, log: LoggerService, operatorService: OperatorService, - optionalDependencies: OptionalDependencies) { - super(elasticKeywords, allowedOperators, translationPath, log, operatorService, optionalDependencies); + optionalDependencies: OptionalDependencies, + resourceTypePrefix: ResourceTypeQueryPrefix) { + super(elasticKeywords, allowedOperators, translationPath, log, operatorService, optionalDependencies, resourceTypePrefix); this._processCategory = optionalDependencies.categoryFactory.get(CaseProcess) as CaseProcess; this._processCategory.selectDefaultOperator(); } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts index 570fa873d8..48922f7d9a 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts @@ -9,6 +9,7 @@ import {NotEquals} from '../../operator/not-equals'; import {Categories} from '../categories'; import {Subscription} from 'rxjs'; import {CaseSearch} from './case-search.enum'; +import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; export class CaseProcess extends NoConfigurationAutocompleteCategory { @@ -21,10 +22,10 @@ export class CaseProcess extends NoConfigurationAutocompleteCategory { constructor(operators: OperatorService, logger: LoggerService, protected _optionalDependencies: OptionalDependencies) { super([CaseSearch.PROCESS_IDENTIFIER], [operators.getOperator(Equals), operators.getOperator(NotEquals)], - // todo 2466 contains, lt, gt, lte, gte, in list `${CaseProcess._i18n}.name`, logger, - operators); + operators, + ResourceTypeQueryPrefix.CASES); this._uniqueOptionsMap = new Map>(); } @@ -76,8 +77,8 @@ export class CaseProcess extends NoConfigurationAutocompleteCategory { throw new Error('Only unary operators are currently supported by the CaseProcess implementation'); } const operand = userInput[0]; - const queries = operand.map(id => this.selectedOperator.createQuery(this.elasticKeywords, [id])); - return Query.combineQueries(queries, BooleanOperator.OR); + const queries = operand.map(id => this.selectedOperator.createQuery(this.pfqlKeywords, [id])); + return Query.combineQueries(queries, BooleanOperator.OR).addPrefixAndGet(ResourceTypeQueryPrefix.CASES); } get inputPlaceholder(): string { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-role.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-role.ts index b57b3cd45a..5c910e03b7 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-role.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-role.ts @@ -8,6 +8,7 @@ import {NameIdPair} from '../name-id-pair'; import {CaseNetAttributeAutocompleteCategory} from './case-net-attribute-autocomplete-category'; import {Categories} from '../categories'; import {CaseSearch} from './case-search.enum'; +import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; export class CaseRole extends CaseNetAttributeAutocompleteCategory { @@ -21,7 +22,8 @@ export class CaseRole extends CaseNetAttributeAutocompleteCategory { `${CaseRole._i18n}.name`, logger, operators, - optionalDependencies); + optionalDependencies, + ResourceTypeQueryPrefix.CASES); } protected extractAttributes(petriNet: Net): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-search.enum.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-search.enum.ts index fdd0823c0d..35616cbc91 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-search.enum.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-search.enum.ts @@ -2,12 +2,12 @@ * Contains the identifiers of the queried elastic search indices. */ export enum CaseSearch { - CREATION_DATE = 'creationDateSortable', + CREATION_DATE = 'creationDate', PROCESS_IDENTIFIER = 'processIdentifier', TASK_ID = 'taskIds', TITLE = 'title', VISUAL_ID = 'visualId', ENABLED_ROLES = 'enabledRoles', AUTHOR = 'author', - STRING_ID = 'stringId', + STRING_ID = 'id', } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-simple-dataset.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-simple-dataset.ts index a5e42592e2..a509916e61 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-simple-dataset.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-simple-dataset.ts @@ -12,11 +12,11 @@ import {BooleanOperator} from '../../boolean-operator'; import {NoConfigurationCategory} from '../no-configuration-category'; import {CaseDataset} from './case-dataset'; import {DatafieldMapKey} from '../../datafield-map-key'; -import {SearchIndex} from '../../search-index'; import {Categories} from '../categories'; import {CategoryGeneratorMetadata} from '../../persistance/generator-metadata'; import {Observable} from 'rxjs'; -import { NotEquals } from '../../operator/not-equals'; +import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; +import {FieldTypeResource} from "../../../../task-content/model/field-type-resource"; /** * This class aims to be a simpler more limited version of the {@link CaseDataset} {@link Category} implementation. @@ -35,7 +35,7 @@ export class CaseSimpleDataset extends NoConfigurationCategory { protected _fieldId: string; protected _fieldType: string; protected _netIdentifiers: Array; - protected _elasticKeyword: string; + protected _pfqlKeyword: string; protected _processCategory: CaseProcess; @@ -47,7 +47,8 @@ export class CaseSimpleDataset extends NoConfigurationCategory { `${CaseSimpleDataset._i18n}.name`, undefined, logger, - operators); + operators, + ResourceTypeQueryPrefix.CASES); this._processCategory = _optionalDependencies.categoryFactory.getWithDefaultOperator(CaseProcess) as CaseProcess; } @@ -69,57 +70,28 @@ export class CaseSimpleDataset extends NoConfigurationCategory { this._fieldId = fieldId; this._fieldType = fieldType; this._netIdentifiers = netIdentifiers; - this.resolveElasticKeyword(); + this._pfqlKeyword = `data.${fieldId}.value` } - protected resolveElasticKeyword(): void { - const resolver = this._optionalDependencies.searchIndexResolver; - switch (this._fieldType) { - case 'number': - this._elasticKeyword = resolver.getIndex(this._fieldId, SearchIndex.NUMBER); - break; - case 'date': - case 'dateTime': - this._elasticKeyword = resolver.getIndex(this._fieldId, SearchIndex.TIMESTAMP); - break; - case 'boolean': - this._elasticKeyword = resolver.getIndex(this._fieldId, SearchIndex.BOOLEAN); - break; - case 'file': - case 'fileList': - this._elasticKeyword = resolver.getIndex(this._fieldId, SearchIndex.FILE_NAME, this.isSelectedOperator(Substring)); - break; - case 'user': - case 'userList': - this._elasticKeyword = resolver.getIndex(this._fieldId, SearchIndex.USER_ID); - break; - case 'i18n': - this._elasticKeyword = resolver.getIndex(this._fieldId, SearchIndex.TEXT, this.isSelectedOperator(Equals) || this.isSelectedOperator(NotEquals) || this.isSelectedOperator(Substring)) - break; - default: - this._elasticKeyword = resolver.getIndex(this._fieldId, SearchIndex.FULLTEXT, this.isSelectedOperator(Substring)); - } - } - - protected get elasticKeywords(): Array { + protected get pfqlKeywords(): Array { if (!this._fieldId) { return []; } else { - return [this._elasticKeyword]; + return [this._pfqlKeyword]; } } public get selectedOperator(): Operator { switch (this._fieldType) { - case 'number': + case FieldTypeResource.NUMBER.valueOf(): return this._operatorService.getOperator(Equals); - case 'boolean': + case FieldTypeResource.BOOLEAN.valueOf(): return this._operatorService.getOperator(Equals); - case 'user': + case FieldTypeResource.USER.valueOf(): return this._operatorService.getOperator(Equals); - case 'date': + case FieldTypeResource.DATE.valueOf(): return this._operatorService.getOperator(EqualsDate); - case 'dateTime': + case FieldTypeResource.DATE_TIME.valueOf(): return this._operatorService.getOperator(EqualsDateTime); default: return this._operatorService.getOperator(Substring); @@ -147,12 +119,12 @@ export class CaseSimpleDataset extends NoConfigurationCategory { } protected generateQuery(userInput: Array): Query { - const valueQuery = this.selectedOperator.createQuery(this.elasticKeywords, userInput); + const valueQuery = this.selectedOperator.createQuery(this.pfqlKeywords, userInput); const netsQuery = Query.combineQueries( this._netIdentifiers.map(id => this._processCategory.generatePredicate([[id]]).query), BooleanOperator.OR ); - return Query.combineQueries([valueQuery, netsQuery], BooleanOperator.AND); + return Query.combineQueries([valueQuery, netsQuery], BooleanOperator.AND).addPrefixAndGet(ResourceTypeQueryPrefix.CASES); } serializeClass(): Categories | string { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-string-id.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-string-id.ts index cccb25d146..c52421bbe9 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-string-id.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-string-id.ts @@ -1,12 +1,12 @@ import {OperatorService} from '../../../operator-service/operator.service'; import {LoggerService} from '../../../../logger/services/logger.service'; -import {Substring} from '../../operator/substring'; import {SearchInputType} from '../search-input-type'; import {NoConfigurationCategory} from '../no-configuration-category'; import {Equals} from '../../operator/equals'; import {NotEquals} from '../../operator/not-equals'; import {Categories} from '../categories'; import {CaseSearch} from './case-search.enum'; +import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; export class CaseStringId extends NoConfigurationCategory { @@ -15,15 +15,14 @@ export class CaseStringId extends NoConfigurationCategory { constructor(operators: OperatorService, logger: LoggerService) { super([CaseSearch.STRING_ID], [ - operators.getOperator(Substring),// todo 2466 pfql has missing substring operator on case id operators.getOperator(Equals), operators.getOperator(NotEquals) ], - // todo 2466 in list `${CaseStringId._i18n}.name`, SearchInputType.TEXT, logger, - operators); + operators, + ResourceTypeQueryPrefix.CASES); } get inputPlaceholder(): string { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-task.spec.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-task.spec.ts deleted file mode 100644 index dcc0a03e37..0000000000 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-task.spec.ts +++ /dev/null @@ -1,136 +0,0 @@ -import {CaseTask} from './case-task'; -import {OperatorService} from '../../../operator-service/operator.service'; -import {createMockDependencies} from '../../../../utility/tests/search-category-mock-dependencies'; -import {TestBed, waitForAsync} from '@angular/core/testing'; -import {ReplaySubject} from 'rxjs'; -import {OperatorResolverService} from '../../../operator-service/operator-resolver.service'; -import {Net} from '../../../../process/net'; -import {createMockNet} from '../../../../utility/tests/utility/create-mock-net'; -import {configureCategory} from '../../../../utility/tests/utility/configure-category'; -import {Equals} from '../../operator/equals'; -import {Categories} from '../categories'; -import {Operators} from '../../operator/operators'; -import {filter, take} from 'rxjs/operators'; - -describe('CaseTask', () => { - let operatorService: OperatorService; - let category: CaseTask; - let allowedNets$: ReplaySubject>; - - beforeAll(() => { - operatorService = new OperatorService(new OperatorResolverService()); - }); - - beforeEach(waitForAsync(async () => { - allowedNets$ = new ReplaySubject>(1); - category = await new CaseTask(operatorService, null, createMockDependencies(allowedNets$, operatorService)); - })); - - afterEach(() => { - allowedNets$.complete(); - category.destroy(); - TestBed.resetTestingModule(); - }); - - it('should create an instance', waitForAsync(async () => { - allowedNets$.next([]); - expect(category).toBeTruthy(); - })); - - it('should select default operator', () => { - allowedNets$.next([]); - expect(category.isOperatorSelected()).toBeFalse(); - category.selectDefaultOperator(); - expect(category.isOperatorSelected()).toBeTrue(); - }); - - it('should generate options with unique names only', () => { - allowedNets$.next([ - createMockNet('', 'A', 'A', undefined, [{title: 'transition1', stringId: 'sid1'}, {title: 'transition2', stringId: 'sid2'}]), - createMockNet('', 'B', 'B', undefined, [{title: 'transition2', stringId: 'sid3'}]), - ]); - category.selectDefaultOperator(); - - const options = category.options; - expect(options).toBeTruthy(); - expect(Array.isArray(options)).toBeTrue(); - expect(options.length).toBe(2); - - const option1 = options.find(o => o.text === 'transition1'); - const option2 = options.find(o => o.text === 'transition2'); - - expect(option1).toBeTruthy(); - expect(option1.value).toBeTruthy(); - expect(Array.isArray(option1.value)).toBeTrue(); - expect(option1.value.length).toBe(1); - expect(option1.value[0].attributeId).toBe('sid1'); - - expect(option2).toBeTruthy(); - expect(option2.value).toBeTruthy(); - expect(Array.isArray(option2.value)).toBeTrue(); - expect(option2.value.length).toBe(2); - expect(option2.value.some(o => o.attributeId === 'sid2')).toBeTrue(); - expect(option2.value.some(o => o.attributeId === 'sid3')).toBeTrue(); - }); - - it('should not serialize incomplete instance', () => { - allowedNets$.next([]); - expect(category.createMetadata()).toBeUndefined(); - }); - - it('should serialize complete instance', () => { - allowedNets$.next([ - createMockNet('', 'A', 'A', undefined, [{title: 'transition1', stringId: 'sid1'}]), - createMockNet('', 'B', 'B', undefined, [{title: 'transition1', stringId: 'sid2'}]), - ]); - - const options = category.options; - expect(options.length).toBe(1); - const option = options[0]; - expect(option.text).toBe('transition1'); - - configureCategory(category, operatorService, Equals, [option]); - - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - expect(metadata.values).toEqual([option.text]); - expect(metadata.category).toBe(Categories.CASE_TASK); - expect(metadata.configuration?.operator).toBe(Operators.EQUALS); - }); - - it('should deserialize stored instance', (done) => { - allowedNets$.next([ - createMockNet('', 'A', 'A', undefined, [{title: 'transition1', stringId: 'sid1'}]), - createMockNet('', 'B', 'B', undefined, [{title: 'transition1', stringId: 'sid2'}]), - ]); - - const options = category.options; - expect(options.length).toBe(1); - const option = options[0]; - expect(option.text).toBe('transition1'); - - configureCategory(category, operatorService, Equals, [option]); - - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - const deserialized = new CaseTask(operatorService, null, createMockDependencies(allowedNets$, operatorService)); - - // wait for autocomplete options to initialize - deserialized.options$.pipe(filter(o => o.length > 0), take(1)).subscribe(() => { - deserialized.loadFromMetadata(metadata).subscribe(() => { - expect(deserialized.isOperatorSelected()).toBeTrue(); - expect(deserialized.providesPredicate).toBeTrue(); - - expect((deserialized as any)._operandsFormControls[0].value).toEqual((category as any)._operandsFormControls[0].value); - - const deserializedMetadata = deserialized.createMetadata(); - expect(deserializedMetadata).toBeTruthy(); - expect(deserializedMetadata.configuration).toEqual(metadata.configuration); - expect(deserializedMetadata.category).toEqual(metadata.category); - expect(deserializedMetadata.values).toEqual(metadata.values); - - done(); - }); - }); - }); -}); diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-task.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-task.ts deleted file mode 100644 index 969564ca53..0000000000 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-task.ts +++ /dev/null @@ -1,42 +0,0 @@ -import {OperatorService} from '../../../operator-service/operator.service'; -import {LoggerService} from '../../../../logger/services/logger.service'; -import {OptionalDependencies} from '../../../category-factory/optional-dependencies'; -import {Equals} from '../../operator/equals'; -import {NotEquals} from '../../operator/not-equals'; -import {NameIdPair} from '../name-id-pair'; -import {Net} from '../../../../process/net'; -import {CaseNetAttributeAutocompleteCategory} from './case-net-attribute-autocomplete-category'; -import {Categories} from '../categories'; -import {CaseSearch} from './case-search.enum'; - -export class CaseTask extends CaseNetAttributeAutocompleteCategory { - - // todo 2466 impossible in PFQL - - private static readonly _i18n = 'search.category.case.task'; - - constructor(operators: OperatorService, logger: LoggerService, optionalDependencies: OptionalDependencies) { - super([CaseSearch.TASK_ID], - [operators.getOperator(Equals), operators.getOperator(NotEquals)], - `${CaseTask._i18n}.name`, - logger, - operators, - optionalDependencies); - } - - protected extractAttributes(petriNet: Net): Array { - return petriNet.transitions.map(t => ({id: t.stringId, name: t.title})); - } - - get inputPlaceholder(): string { - return `${CaseTask._i18n}.placeholder`; - } - - duplicate(): CaseTask { - return new CaseTask(this._operatorService, this._log, this._optionalDependencies); - } - - serializeClass(): Categories | string { - return Categories.CASE_TASK; - } -} diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.ts index 2683ba7db2..4ddeb4c734 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.ts @@ -9,6 +9,11 @@ import {Like} from '../../operator/like'; import {Categories} from '../categories'; import {CaseSearch} from './case-search.enum'; import {OptionalDependencies} from '../../../category-factory/optional-dependencies'; +import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; +import {MoreThan} from "../../operator/more-than"; +import {MoreThanEqual} from "../../operator/more-than-equal"; +import {LessThan} from "../../operator/less-than"; +import {LessThanEqual} from "../../operator/less-than-equal"; export class CaseTitle extends NoConfigurationCategory { @@ -20,13 +25,17 @@ export class CaseTitle extends NoConfigurationCategory { operators.getOperator(Substring), operators.getOperator(Equals), operators.getOperator(NotEquals), - operators.getOperator(Like) // todo 2466 no such operat Like in pfql + operators.getOperator(MoreThan), + operators.getOperator(MoreThanEqual), + operators.getOperator(LessThan), + operators.getOperator(LessThanEqual), + // operators.getOperator(Like) todo 2466 impossible in PFQL ], - // todo 2466 in list, lt, gt, lte, gte `${CaseTitle._i18n}.name`, SearchInputType.TEXT, logger, - operators); + operators, + ResourceTypeQueryPrefix.CASES); } get inputPlaceholder(): string { @@ -41,12 +50,7 @@ export class CaseTitle extends NoConfigurationCategory { return Categories.CASE_TITLE; } - protected get elasticKeywords(): Array { - if (!!this._optionalDependencies) { - const resolver = this._optionalDependencies.searchIndexResolver; - return [resolver.getCoreIndex(CaseSearch.TITLE, this.isSelectedOperator(Substring))]; - } else { - return this._elasticKeywords; - } + protected get pfqlKeywords(): Array { + return this._pfqlKeywords; } } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.ts index c804f05248..0d6af217ba 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.ts @@ -8,6 +8,7 @@ import {NotEquals} from '../../operator/not-equals'; import {Categories} from '../categories'; import {CaseSearch} from './case-search.enum'; import {OptionalDependencies} from '../../../category-factory/optional-dependencies'; +import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; export class CaseVisualId extends NoConfigurationCategory { @@ -21,7 +22,8 @@ export class CaseVisualId extends NoConfigurationCategory { `${CaseVisualId._i18n}.name`, SearchInputType.TEXT, logger, - operators); + operators, + ResourceTypeQueryPrefix.CASES); } get inputPlaceholder(): string { @@ -36,12 +38,12 @@ export class CaseVisualId extends NoConfigurationCategory { return Categories.CASE_VISUAL_ID; } - protected get elasticKeywords(): Array { + protected get pfqlKeywords(): Array { if (!!this._optionalDependencies) { const resolver = this._optionalDependencies.searchIndexResolver; return [resolver.getCoreIndex(CaseSearch.VISUAL_ID, this.isSelectedOperator(Substring))]; } else { - return this._elasticKeywords; + return this._pfqlKeywords; } } } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/categories.ts b/projects/netgrif-components-core/src/lib/search/models/category/categories.ts index 6978cd9657..ac4f46d6f1 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/categories.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/categories.ts @@ -10,7 +10,6 @@ export enum Categories { CASE_PROCESS = 'case_process', CASE_ROLE = 'case_role', CASE_SIMPLE_DATASET = 'case_simple_dataset', - CASE_TASK = 'case_task', CASE_TITLE = 'case_title', CASE_VISUAL_ID = 'case_visual_id', CASE_STRING_ID = 'case_string_id', diff --git a/projects/netgrif-components-core/src/lib/search/models/category/category.ts b/projects/netgrif-components-core/src/lib/search/models/category/category.ts index 420e5989b3..9f6935e2d7 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/category.ts @@ -17,10 +17,11 @@ import {ofVoid} from '../../../utility/of-void'; import {FilterTextSegment} from '../persistance/filter-text-segment'; import {DATE_FORMAT_STRING, DATE_TIME_FORMAT_STRING} from '../../../moment/time-formats'; import {Type} from '@angular/core'; +import {ResourceTypeQueryPrefix} from "./resource-type-query-prefix"; /** * The top level of abstraction in search query generation. Represents a set of indexed fields that can be searched. - * Encapsulates the the state and logic of the query construction process. + * Encapsulates the state and logic of the query construction process. * * As opposed to {@link Operator}s Categories are not stateless and shouldn't be shared. * A single Category instance is capable of holding the state of one {@link EditablePredicate}, @@ -84,19 +85,21 @@ export abstract class Category { * The constructor fills the values of all protected fields and then calls the [initializeCategory()]{@link Category#initializeCategory} * method. If you want to override the category creation behavior override that method. * - * @param _elasticKeywords Elasticsearch keywords that should be queried by queries generated with this category + * @param _pfqlKeywords PFQL keywords that should be queried by queries generated with this category * @param _allowedOperators Operators that can be used to generated queries on the above keywords * @param translationPath path to the translation string * @param _inputType input field type that should be used to enter operator arguments for this category * @param _log used to record information about incorrect use of this class * @param _operatorService used to resolve serialized operators during deserialization + * @param _resourceTypePrefix resource type prefix in PFQL query */ - protected constructor(protected readonly _elasticKeywords: Array, + protected constructor(protected readonly _pfqlKeywords: Array, protected readonly _allowedOperators: Array>, public readonly translationPath: string, protected readonly _inputType: SearchInputType, protected _log: LoggerService, - protected _operatorService: OperatorService) { + protected _operatorService: OperatorService, + protected _resourceTypePrefix: ResourceTypeQueryPrefix) { this._OPERATOR_INPUT = new ConfigurationInput( SearchInputType.OPERATOR, 'search.operator.name', @@ -237,12 +240,12 @@ export abstract class Category { } /** - * @returns the set of Elasticsearch keywords that should be queried by queries generated with this category. + * @returns the set of PFQL keywords that should be queried by queries generated with this category. * The method can be overridden if the keywords are not static and change based on some additional selection (eg. Data fields) */ - protected get elasticKeywords(): Array { + protected get pfqlKeywords(): Array { const result = []; - result.push(...this._elasticKeywords); + result.push(...this._pfqlKeywords); return result; } @@ -251,7 +254,7 @@ export abstract class Category { */ protected get selectedOperatorArity(): number { if (!this.isOperatorSelected()) { - throw new Error('An operator mus be selected before its arity can be resolved!'); + throw new Error('An operator must be selected before its arity can be resolved!'); } return this.selectedOperator.numberOfOperands; } @@ -324,7 +327,8 @@ export abstract class Category { if (!this.isOperatorSelected()) { throw new Error('Category cannot generate a Query if no Operator is selected'); } - return this._operatorFormControl.value.createQuery(this.elasticKeywords, userInput as unknown as Array); + let query: Query = this._operatorFormControl.value.createQuery(this.pfqlKeywords, userInput as unknown as Array); + return query.addPrefixAndGet(this._resourceTypePrefix); } /** @@ -485,7 +489,9 @@ export abstract class Category { } } - this._generatedPredicate$.next(this.generatePredicate(this._operandsFormControls.map(fc => this.transformCategoryValue(fc.value)))); + this._generatedPredicate$.next(this.generatePredicate(this._operandsFormControls + .filter(fc => !!fc) + .map(fc => this.transformCategoryValue(fc.value)))); } /** diff --git a/projects/netgrif-components-core/src/lib/search/models/category/net-attribute-autocomplete-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/net-attribute-autocomplete-category.ts index 639cbb171d..8eef9e749b 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/net-attribute-autocomplete-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/net-attribute-autocomplete-category.ts @@ -10,6 +10,7 @@ import {Category} from './category'; import {Subscription} from 'rxjs'; import {OperatorService} from '../../operator-service/operator.service'; import {OptionalDependencies} from '../../category-factory/optional-dependencies'; +import {ResourceTypeQueryPrefix} from "./resource-type-query-prefix"; /** * A utility class for autocomplete search categories that are net specific, such as searching by roles, or tasks. @@ -21,13 +22,14 @@ export abstract class NetAttributeAutocompleteCategory extends NoConfigurationAu private _allowedNetsSub: Subscription; private _destroyed: boolean; - protected constructor(elasticKeywords: Array, + protected constructor(pfqlKeywords: Array, allowedOperators: Array>, translationPath: string, log: LoggerService, operatorService: OperatorService, - protected _optionalDependencies: OptionalDependencies) { - super(elasticKeywords, allowedOperators, translationPath, log, operatorService); + protected _optionalDependencies: OptionalDependencies, + resourceTypePrefix: ResourceTypeQueryPrefix) { + super(pfqlKeywords, allowedOperators, translationPath, log, operatorService, resourceTypePrefix); } destroy() { @@ -101,10 +103,11 @@ export abstract class NetAttributeAutocompleteCategory extends NoConfigurationAu const matchingPairs = userInput[0]; const queries = matchingPairs.map(pair => { - const taskQuery = this.selectedOperator.createQuery(this.elasticKeywords, [pair.attributeId]); + const taskQuery = this.selectedOperator.createQuery(this.pfqlKeywords, [pair.attributeId]); const netQuery = this.getProcessCategory().generatePredicate([[pair.netId]]).query; return Query.combineQueries([taskQuery, netQuery], BooleanOperator.AND); }); - return Query.combineQueries(queries, BooleanOperator.OR); + const query: Query = Query.combineQueries(queries, BooleanOperator.OR); + return query.addPrefixAndGet(this._resourceTypePrefix); } } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-autocomplete-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-autocomplete-category.ts index 3ee0eb911f..c110250ede 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-autocomplete-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-autocomplete-category.ts @@ -6,6 +6,7 @@ import {FormControl} from '@angular/forms'; import {ConfigurationInput} from '../configuration-input'; import {OperatorService} from '../../operator-service/operator.service'; import {FilterTextSegment} from '../persistance/filter-text-segment'; +import {ResourceTypeQueryPrefix} from "./resource-type-query-prefix"; /** * A utility class that exists for inheritance by simpler category instances. @@ -16,9 +17,10 @@ import {FilterTextSegment} from '../persistance/filter-text-segment'; */ export abstract class NoConfigurationAutocompleteCategory extends AutocompleteCategory { - protected constructor(elasticKeywords: Array, allowedOperators: Array>, - translationPath: string, log: LoggerService, operatorService: OperatorService) { - super(elasticKeywords, allowedOperators, translationPath, log, operatorService); + protected constructor(pfqlKeywords: Array, allowedOperators: Array>, + translationPath: string, log: LoggerService, operatorService: OperatorService, + resourceTypePrefix: ResourceTypeQueryPrefix) { + super(pfqlKeywords, allowedOperators, translationPath, log, operatorService, resourceTypePrefix); } /** diff --git a/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-category.ts index 8eef0b8af1..22c333d389 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-category.ts @@ -7,6 +7,7 @@ import {FormControl} from '@angular/forms'; import {ConfigurationInput} from '../configuration-input'; import {OperatorService} from '../../operator-service/operator.service'; import {FilterTextSegment} from '../persistance/filter-text-segment'; +import {ResourceTypeQueryPrefix} from "./resource-type-query-prefix"; /** * A utility class that exists for inheritance by simpler category instances. @@ -17,10 +18,10 @@ import {FilterTextSegment} from '../persistance/filter-text-segment'; */ export abstract class NoConfigurationCategory extends Category { - protected constructor(elasticKeywords: Array, allowedOperators: Array>, + protected constructor(pfqlKeywords: Array, allowedOperators: Array>, translationPath: string, inputType: SearchInputType, log: LoggerService, - operatorService: OperatorService) { - super(elasticKeywords, allowedOperators, translationPath, inputType, log, operatorService); + operatorService: OperatorService, resourceTypePrefix: ResourceTypeQueryPrefix) { + super(pfqlKeywords, allowedOperators, translationPath, inputType, log, operatorService, resourceTypePrefix); } /** diff --git a/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts index d198ee019c..3acbfa819e 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts @@ -8,15 +8,17 @@ import {Observable} from 'rxjs'; import {SearchAutocompleteOption} from './search-autocomplete-option'; import {Query} from '../query/query'; import {FormControl} from '@angular/forms'; +import {ResourceTypeQueryPrefix} from "./resource-type-query-prefix"; export abstract class NoConfigurationUserAutocompleteCategory extends NoConfigurationAutocompleteCategory { private _userAutocomplete: UserAutocomplete; - protected constructor(elasticKeywords: Array, allowedOperators: Array>, + protected constructor(pfqlKeywords: Array, allowedOperators: Array>, translationPath: string, log: LoggerService, operatorService: OperatorService, - private _className, protected _optionalDependencies: OptionalDependencies) { - super(elasticKeywords, allowedOperators, translationPath, log, operatorService); + private _className, protected _optionalDependencies: OptionalDependencies, + resourceTypePrefix: ResourceTypeQueryPrefix) { + super(pfqlKeywords, allowedOperators, translationPath, log, operatorService, resourceTypePrefix); this._userAutocomplete = new UserAutocomplete(this._optionalDependencies); } @@ -33,7 +35,8 @@ export abstract class NoConfigurationUserAutocompleteCategory extends NoConfigur if (this.selectedOperator.numberOfOperands !== 1) { throw new Error(`Only unary operators are currently supported by the ${this._className} implementation`); } - return this.selectedOperator.createQuery(this.elasticKeywords, Array.isArray(userInput[0]) ? userInput[0] : userInput, false); + return this.selectedOperator.createQuery(this.pfqlKeywords, Array.isArray(userInput[0]) ? userInput[0] : userInput, false) + .addPrefixAndGet(this._resourceTypePrefix); } protected serializeOperandValue(valueFormControl: FormControl): any { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/resource-type-query-prefix.ts b/projects/netgrif-components-core/src/lib/search/models/category/resource-type-query-prefix.ts new file mode 100644 index 0000000000..29a5f19fcf --- /dev/null +++ b/projects/netgrif-components-core/src/lib/search/models/category/resource-type-query-prefix.ts @@ -0,0 +1,9 @@ +/** + * Resource type prefix in PFQL query + */ +export enum ResourceTypeQueryPrefix { + CASES = 'cases', + TASKS = 'tasks', + PROCESSES = 'processes', + USERS = 'users' +} diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-assignee.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-assignee.ts index 712554342a..216394959a 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-assignee.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-assignee.ts @@ -6,6 +6,7 @@ import {NotEquals} from '../../operator/not-equals'; import {IsNull} from '../../operator/is-null'; import {Categories} from '../categories'; import {NoConfigurationUserAutocompleteCategory} from '../no-configuration-user-autocomplete-category'; +import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; export class TaskAssignee extends NoConfigurationUserAutocompleteCategory { @@ -17,14 +18,14 @@ export class TaskAssignee extends NoConfigurationUserAutocompleteCategory { [ operators.getOperator(Equals), operators.getOperator(NotEquals), - operators.getOperator(IsNull) // todo 2466 no such operator IsNull in PFQL + // operators.getOperator(IsNull) todo 2466 impossible in PFQL ], - // todo 2466 contains, lt, gt, lte, gte, in list `${TaskAssignee._i18n}.name`, logger, operators, 'TaskAssignee', - optionalDependencies); + optionalDependencies, + ResourceTypeQueryPrefix.TASKS); } get inputPlaceholder(): string { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-net-attribute-autocomplete-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-net-attribute-autocomplete-category.ts index 492064b776..74ee8bf36b 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-net-attribute-autocomplete-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-net-attribute-autocomplete-category.ts @@ -6,6 +6,7 @@ import {Net} from '../../../../process/net'; import {Category} from '../category'; import {TaskProcess} from './task-process'; import {OperatorService} from '../../../operator-service/operator.service'; +import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; /** * Utility class with the same use as its parent but witch Task search specific methods implemented. @@ -13,13 +14,14 @@ import {OperatorService} from '../../../operator-service/operator.service'; export abstract class TaskNetAttributeAutocompleteCategory extends NetAttributeAutocompleteCategory { protected _processCategory: TaskProcess; - protected constructor(elasticKeywords: Array, + protected constructor(pfqlKeywords: Array, allowedOperators: Array>, translationPath: string, log: LoggerService, operatorService: OperatorService, - optionalDependencies: OptionalDependencies) { - super(elasticKeywords, allowedOperators, translationPath, log, operatorService, optionalDependencies); + optionalDependencies: OptionalDependencies, + resourceTypePrefix: ResourceTypeQueryPrefix) { + super(pfqlKeywords, allowedOperators, translationPath, log, operatorService, optionalDependencies, resourceTypePrefix); this._processCategory = optionalDependencies.categoryFactory.get(TaskProcess) as TaskProcess; this._processCategory.selectDefaultOperator(); } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts index 078a021834..c64eae2253 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts @@ -8,6 +8,7 @@ import {NoConfigurationAutocompleteCategory} from '../no-configuration-autocompl import {NotEquals} from '../../operator/not-equals'; import {Categories} from '../categories'; import {Subscription} from 'rxjs'; +import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; export class TaskProcess extends NoConfigurationAutocompleteCategory { @@ -19,10 +20,10 @@ export class TaskProcess extends NoConfigurationAutocompleteCategory { constructor(operators: OperatorService, logger: LoggerService, protected _optionalDependencies: OptionalDependencies) { super(['processId'], [operators.getOperator(Equals), operators.getOperator(NotEquals)], - // todo 2466 contains, lt, gt, lte, gte, in list `${TaskProcess._i18n}.name`, logger, - operators); + operators, + ResourceTypeQueryPrefix.TASKS); } destroy() { @@ -52,8 +53,8 @@ export class TaskProcess extends NoConfigurationAutocompleteCategory { throw new Error('Only unary operators are currently supported by the TaskProcess implementation'); } const operand = userInput[0]; - const queries = operand.map(id => this.selectedOperator.createQuery(this.elasticKeywords, [id])); - return Query.combineQueries(queries, BooleanOperator.OR); + const queries = operand.map(id => this.selectedOperator.createQuery(this.pfqlKeywords, [id])); + return Query.combineQueries(queries, BooleanOperator.OR).addPrefixAndGet(ResourceTypeQueryPrefix.TASKS); } get inputPlaceholder(): string { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-role.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-role.ts index 80191d60be..5ae8a62b88 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-role.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-role.ts @@ -7,6 +7,7 @@ import {TaskNetAttributeAutocompleteCategory} from './task-net-attribute-autocom import {Net} from '../../../../process/net'; import {NameIdPair} from '../name-id-pair'; import {Categories} from '../categories'; +import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; export class TaskRole extends TaskNetAttributeAutocompleteCategory { @@ -20,7 +21,8 @@ export class TaskRole extends TaskNetAttributeAutocompleteCategory { `${TaskRole._i18n}.name`, logger, operators, - optionalDependencies); + optionalDependencies, + ResourceTypeQueryPrefix.TASKS); } protected extractAttributes(petriNet: Net): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts index bcf370b828..7a504e77a5 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts @@ -7,6 +7,7 @@ import {TaskNetAttributeAutocompleteCategory} from './task-net-attribute-autocom import {Net} from '../../../../process/net'; import {NameIdPair} from '../name-id-pair'; import {Categories} from '../categories'; +import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; export class TaskTask extends TaskNetAttributeAutocompleteCategory { @@ -16,11 +17,11 @@ export class TaskTask extends TaskNetAttributeAutocompleteCategory { constructor(operators: OperatorService, logger: LoggerService, optionalDependencies: OptionalDependencies) { super(['transitionId'], [operators.getOperator(Equals), operators.getOperator(NotEquals)], - // todo 2466 contains, lt, gt, lte, gte, in list, in range `${TaskTask._i18n}.name`, logger, operators, - optionalDependencies); + optionalDependencies, + ResourceTypeQueryPrefix.TASKS); } protected extractAttributes(petriNet: Net): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/user-autocomplete.ts b/projects/netgrif-components-core/src/lib/search/models/category/user-autocomplete.ts index 9869c7b6bd..d1ee8458de 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/user-autocomplete.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/user-autocomplete.ts @@ -18,7 +18,7 @@ export class UserAutocomplete implements AutocompleteOptions { public static readonly USER_ME_ICON = 'person_pin_circle'; // person_pin, person_pin_circle - public static readonly USER_ME_TEMPLATE = '<>'; + public static readonly USER_ME_TEMPLATE = 'loggedUser.id'; private static readonly _i18n = 'search.category.userMe'; diff --git a/projects/netgrif-components-core/src/lib/search/models/datafield-map-key.ts b/projects/netgrif-components-core/src/lib/search/models/datafield-map-key.ts index e57b017e55..bbc0638c31 100644 --- a/projects/netgrif-components-core/src/lib/search/models/datafield-map-key.ts +++ b/projects/netgrif-components-core/src/lib/search/models/datafield-map-key.ts @@ -5,7 +5,7 @@ import {SearchAutocompleteOption} from './category/search-autocomplete-option'; * * Since javascript maps don't support objects as keys this class has a serialized form, that is used as a `string` key. * - * This class also acts as an autocomplete option when the target datafield is selected. The real data fields are then extracted from the + * This class also acts as an autocomplete option when the target data field is selected. The real data fields are then extracted from the * map to which this object is a key. */ export class DatafieldMapKey implements SearchAutocompleteOption { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/equals-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/equals-date-time.ts index 0885fa062a..7160273bed 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/equals-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/equals-date-time.ts @@ -20,9 +20,9 @@ export class EqualsDateTime extends Operator { this.dateTimeRange = operators.getOperator(InRangeDateTime) as InRangeDateTime; } - createQuery(elasticKeywords: Array, args: Array): Query { + createQuery(pfqlKeywords: Array, args: Array): Query { this.checkArgumentsCount(args); - return this.dateTimeRange.createQuery(elasticKeywords, [args[0], args[0]]); + return this.dateTimeRange.createQuery(pfqlKeywords, [args[0], args[0]]); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/equals-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/equals-date.ts index 45bb7838a5..bd28764e37 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/equals-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/equals-date.ts @@ -20,9 +20,9 @@ export class EqualsDate extends Operator { this.dateRange = operators.getOperator(InRangeDate) as InRangeDate; } - createQuery(elasticKeywords: Array, args: Array): Query { + createQuery(pfqlKeywords: Array, args: Array): Query { this.checkArgumentsCount(args); - return this.dateRange.createQuery(elasticKeywords, [args[0], args[0]]); + return this.dateRange.createQuery(pfqlKeywords, [args[0], args[0]]); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/equals.ts b/projects/netgrif-components-core/src/lib/search/models/operator/equals.ts index 0d1eb66e22..a1b646a58a 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/equals.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/equals.ts @@ -10,7 +10,7 @@ import {Operators} from './operators'; export class Equals extends Operator { constructor() { // query string queries don't use a special symbol for strict equality - super(1, ''); + super(1, 'eq'); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date-time.ts index 2b5a928bfd..2f689442b8 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date-time.ts @@ -17,12 +17,12 @@ export class InRangeDateTime extends Operator { /** * Creates a query as specified by the [classes]{@link InRangeDate} documentation. * See [super.createQuery()]{@link Operator#createQuery} for more information. - * @param elasticKeywords keywords of the fields that should be queried. + * @param pfqlKeywords keywords of the fields that should be queried. * If more than one is provided then queries for every keyword will be generated and combined with an OR operator. * @param args start and end date for the range. If you want to ignore the time information use {@link InRangeDate} * Operator instead. The two date time objects must be in ascending order, if not the behavior is undefined. */ - createQuery(elasticKeywords: Array, args: Array): Query { + createQuery(pfqlKeywords: Array, args: Array): Query { this.checkArgumentsCount(args); const arg1 = moment(args[0]); arg1.milliseconds(0); @@ -31,8 +31,8 @@ export class InRangeDateTime extends Operator { arg2.milliseconds(0); arg2.seconds(0); arg2.minutes(arg2.minutes() + 1); // moment handles rollover - return Operator.forEachKeyword(elasticKeywords, (keyword: string) => { - return new Query(`(${keyword}:[${arg1.valueOf()} TO ${arg2.valueOf()}})`); + return Operator.forEachKeyword(pfqlKeywords, (keyword: string) => { + return new Query(`${keyword} in (${arg1.format('YYYY-MM-DDTHH:mm:ss')} : ${arg2.format('YYYY-MM-DDTHH:mm:ss')})`); }); } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date.ts index df1f362952..d635cef42b 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date.ts @@ -2,7 +2,6 @@ import {Operator} from './operator'; import {Moment} from 'moment'; import {Query} from '../query/query'; import moment from 'moment'; -import {clearTimeInformation} from '../../../utility/clear-time-information'; import {Operators} from './operators'; /** @@ -19,20 +18,18 @@ export class InRangeDate extends Operator { /** * Creates a query as specified by the [classes]{@link InRangeDate} documentation. * See [super.createQuery()]{@link Operator#createQuery} for more information. - * @param elasticKeywords keywords of the fields that should be queried. + * @param pfqlKeywords keywords of the fields that should be queried. * If more than one is provided then queries for every keyword will be generated and combined with an OR operator. * @param args start and end date for the range. Any time information will be ignored use {@link InRangeDateTime} * if you want a date time query instead. The two dates must be in ascending order, if not the behavior is undefined. */ - createQuery(elasticKeywords: Array, args: Array): Query { + createQuery(pfqlKeywords: Array, args: Array): Query { this.checkArgumentsCount(args); const arg1 = moment(args[0]); - clearTimeInformation(arg1); const arg2 = moment(args[1]); - clearTimeInformation(arg2); arg2.date(arg2.date() + 1); // moment handles rollover - return Operator.forEachKeyword(elasticKeywords, (keyword: string) => { - return new Query(`(${keyword}:[${arg1.valueOf()} TO ${arg2.valueOf()}})`); + return Operator.forEachKeyword(pfqlKeywords, (keyword: string) => { + return new Query(`${keyword} in (${arg1.format('YYYY-MM-DD')} : ${arg2.format('YYYY-MM-DD')})`); }); } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/in-range.ts b/projects/netgrif-components-core/src/lib/search/models/operator/in-range.ts index 6f5ae26d55..746acc475c 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/in-range.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/in-range.ts @@ -10,9 +10,9 @@ export class InRange extends Operator { super(2); } - createQuery(elasticKeywords: Array, args: Array): Query { + createQuery(pfqlKeywords: Array, args: Array): Query { this.checkArgumentsCount(args); - return Operator.forEachKeyword(elasticKeywords, keyword => new Query(`(${keyword}:[${args[0]} TO ${args[1]}])`)); + return Operator.forEachKeyword(pfqlKeywords, keyword => new Query(`${keyword} in (${args[0]} : ${args[1]})`)); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/is-null.ts b/projects/netgrif-components-core/src/lib/search/models/operator/is-null.ts index a89070a671..307fc43489 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/is-null.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/is-null.ts @@ -9,6 +9,8 @@ import {Operators} from './operators'; * Consult the [createQueryWithConstraint()]{@link IsNull#createQueryWithConstraint} method for more information. */ export class IsNull extends Operator { + // todo 2466 impossible in PFQL + constructor() { super(0); } @@ -77,6 +79,7 @@ export class IsNull extends Operator { } serialize(): Operators | string { - return Operators.IS_NULL; + return 'is_null'; + // return Operators.IS_NULL; } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date-time.ts index 13c5c902a4..e31f4f0b2e 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date-time.ts @@ -17,12 +17,12 @@ export class LessThanDateTime extends Operator { this.lessThan = operators.getOperator(LessThan) as LessThan; } - createQuery(elasticKeywords: Array, args: Array): Query { + createQuery(pfqlKeywords: Array, args: Array): Query { this.checkArgumentsCount(args); const arg = moment(args[0]); arg.milliseconds(0); arg.seconds(0); - return this.lessThan.createQuery(elasticKeywords, [arg.valueOf()]); + return this.lessThan.createQuery(pfqlKeywords, [arg.format('YYYY-MM-DDTHH:mm:ss')], false, false); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date.ts index 556851456e..51b067c286 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date.ts @@ -2,7 +2,6 @@ import {Operator} from './operator'; import moment, {Moment} from 'moment'; import {OperatorService} from '../../operator-service/operator.service'; import {Query} from '../query/query'; -import {clearTimeInformation} from '../../../utility/clear-time-information'; import {LessThan} from './less-than'; import {Operators} from './operators'; @@ -18,11 +17,10 @@ export class LessThanDate extends Operator { this.lessThan = operators.getOperator(LessThan) as LessThan; } - createQuery(elasticKeywords: Array, args: Array): Query { + createQuery(pfqlKeywords: Array, args: Array): Query { this.checkArgumentsCount(args); const arg = moment(args[0]); - clearTimeInformation(arg); - return this.lessThan.createQuery(elasticKeywords, [arg.valueOf()]); + return this.lessThan.createQuery(pfqlKeywords, [arg.format('YYYY-MM-DD')], false, false); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date-time.ts index f0cef130c9..0e87b98c67 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date-time.ts @@ -6,7 +6,7 @@ import {Operators} from './operators'; import {Query} from '../query/query'; /** - * Greater or equal than operator for Datetime fields + * Less or equal than operator for Datetime fields */ export class LessThanEqualDateTime extends Operator { @@ -17,12 +17,12 @@ export class LessThanEqualDateTime extends Operator { this.lessThanEqual = operators.getOperator(LessThanEqual) as LessThanEqual; } - createQuery(elasticKeywords: Array, args: Array): Query { + createQuery(pfqlKeywords: Array, args: Array): Query { this.checkArgumentsCount(args); const arg = moment(args[0]); arg.milliseconds(0); arg.seconds(0); - return this.lessThanEqual.createQuery(elasticKeywords, [arg.valueOf()]); + return this.lessThanEqual.createQuery(pfqlKeywords, [arg.format('YYYY-MM-DDTHH:mm:ss')], false, false); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date.ts index 92c714f1b0..d9d1f7f122 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date.ts @@ -17,11 +17,11 @@ export class LessThanEqualDate extends Operator { this.lessThan = operators.getOperator(LessThanDate) as LessThanDate; } - createQuery(elasticKeywords: Array, args: Array): Query { + createQuery(pfqlKeywords: Array, args: Array): Query { this.checkArgumentsCount(args); const arg = moment(args[0]); arg.date(arg.date() + 1); - return this.lessThan.createQuery(elasticKeywords, [arg]); + return this.lessThan.createQuery(pfqlKeywords, [arg]); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal.ts index 0ed5dd98de..da9d13246f 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal.ts @@ -2,12 +2,12 @@ import {Operator} from './operator'; import {Operators} from './operators'; /** - * Less or equal than operator for numeric fields + * Less or equal than operator for numeric or string fields */ -export class LessThanEqual extends Operator { +export class LessThanEqual extends Operator { constructor() { - super(1, '<='); + super(1, 'lte'); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than.ts index 188819991d..6f9fef774d 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than.ts @@ -2,11 +2,11 @@ import {Operator} from './operator'; import {Operators} from './operators'; /** - * A strict less than operator for numeric fields. + * A strict less than operator for numeric or string fields. */ -export class LessThan extends Operator { +export class LessThan extends Operator { constructor() { - super(1, '<'); + super(1, 'lt'); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/like.ts b/projects/netgrif-components-core/src/lib/search/models/operator/like.ts index 96372ba6f2..dc9a4fbeba 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/like.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/like.ts @@ -12,6 +12,7 @@ import {Operators} from './operators'; * for more information. */ export class Like extends Operator { + // todo 2466 impossible in PFQL constructor() { super(1); } @@ -28,6 +29,7 @@ export class Like extends Operator { } serialize(): Operators | string { - return Operators.LIKE; + return 'like'; + // return Operators.LIKE; } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date-time.ts index accf372b8e..38f60939fb 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date-time.ts @@ -17,14 +17,14 @@ export class MoreThanDateTime extends Operator { this.moreThan = operators.getOperator(MoreThan) as MoreThan; } - createQuery(elasticKeywords: Array, args: Array): Query { + createQuery(pfqlKeywords: Array, args: Array): Query { this.checkArgumentsCount(args); const arg = moment(args[0]); arg.milliseconds(0); arg.seconds(0); arg.minutes(arg.minutes() + 1); arg.milliseconds(-1); - return this.moreThan.createQuery(elasticKeywords, [arg.valueOf()]); + return this.moreThan.createQuery(pfqlKeywords, [arg.format('YYYY-MM-DDTHH:mm:ss')], false, false); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date.ts index c79e662c63..929c89517d 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date.ts @@ -3,7 +3,6 @@ import {OperatorService} from '../../operator-service/operator.service'; import {Query} from '../query/query'; import {MoreThan} from './more-than'; import moment, {Moment} from 'moment'; -import {clearTimeInformation} from '../../../utility/clear-time-information'; import {Operators} from './operators'; /** @@ -18,13 +17,12 @@ export class MoreThanDate extends Operator { this.moreThan = operators.getOperator(MoreThan) as MoreThan; } - createQuery(elasticKeywords: Array, args: Array): Query { + createQuery(pfqlKeywords: Array, args: Array): Query { this.checkArgumentsCount(args); const arg = moment(args[0]); - clearTimeInformation(arg); arg.date(arg.date() + 1); arg.milliseconds(-1); - return this.moreThan.createQuery(elasticKeywords, [arg.valueOf()]); + return this.moreThan.createQuery(pfqlKeywords, [arg.format('YYYY-MM-DD')], false, false); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date-time.ts index a738739e7f..5800c861a7 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date-time.ts @@ -17,12 +17,12 @@ export class MoreThanEqualDateTime extends Operator { this.moreThanEqual = operators.getOperator(MoreThanEqual) as MoreThanEqual; } - createQuery(elasticKeywords: Array, args: Array): Query { + createQuery(pfqlKeywords: Array, args: Array): Query { this.checkArgumentsCount(args); const arg = moment(args[0]); arg.milliseconds(0); arg.seconds(0); - return this.moreThanEqual.createQuery(elasticKeywords, [arg.valueOf()]); + return this.moreThanEqual.createQuery(pfqlKeywords, [arg.format('YYYY-MM-DDTHH:mm:ss')], false, false); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date.ts index 6dfcee1a90..57d4743447 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date.ts @@ -4,7 +4,6 @@ import {OperatorService} from '../../operator-service/operator.service'; import {MoreThanEqual} from './more-than-equal'; import {Operators} from './operators'; import {Query} from '../query/query'; -import {clearTimeInformation} from '../../../utility/clear-time-information'; /** * Greater or equal than operator for Date fields @@ -18,11 +17,10 @@ export class MoreThanEqualDate extends Operator { this.moreThanEqual = operators.getOperator(MoreThanEqual) as MoreThanEqual; } - createQuery(elasticKeywords: Array, args: Array): Query { + createQuery(pfqlKeywords: Array, args: Array): Query { this.checkArgumentsCount(args); const arg = moment(args[0]); - clearTimeInformation(arg); - return this.moreThanEqual.createQuery(elasticKeywords, [arg.valueOf()]); + return this.moreThanEqual.createQuery(pfqlKeywords, [arg.format('YYYY-MM-DD')], false, false); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal.ts index 4c8d7a80f3..dd00a26530 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal.ts @@ -2,12 +2,12 @@ import {Operator} from './operator'; import {Operators} from './operators'; /** - * Greater or equal than operator for numeric fields + * Greater or equal than operator for numeric or string fields */ -export class MoreThanEqual extends Operator { +export class MoreThanEqual extends Operator { constructor() { - super(1, '>='); + super(1, 'gte'); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than.ts index 08b8ca194a..a8a99ec469 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than.ts @@ -2,11 +2,11 @@ import {Operator} from './operator'; import {Operators} from './operators'; /** - * A strict greater than operator for numeric fields. + * A strict greater than operator for numeric or string fields. */ -export class MoreThan extends Operator { +export class MoreThan extends Operator { constructor() { - super(1, '>'); + super(1, 'gt'); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date-time.ts index 19c8c92322..8b99698289 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date-time.ts @@ -14,12 +14,12 @@ export class NotEqualsDateTime extends Operator { this.equals = operators.getOperator(EqualsDateTime) as EqualsDateTime; } - createQuery(elasticKeywords: Array, args: Array): Query { - const equalsQuery = this.equals.createQuery(elasticKeywords, args); + createQuery(pfqlKeywords: Array, args: Array): Query { + const equalsQuery = this.equals.createQuery(pfqlKeywords, args); if (equalsQuery.isEmpty) { return equalsQuery; } - return new Query(`(!${equalsQuery.value})`); + return new Query(`not (${equalsQuery.value})`); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date.ts index 42a6ebf4d9..2325158492 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date.ts @@ -17,12 +17,12 @@ export class NotEqualsDate extends Operator { this.equals = operators.getOperator(EqualsDate) as EqualsDate; } - createQuery(elasticKeywords: Array, args: Array): Query { - const equalsQuery = this.equals.createQuery(elasticKeywords, args); + createQuery(pfqlKeywords: Array, args: Array): Query { + const equalsQuery = this.equals.createQuery(pfqlKeywords, args); if (equalsQuery.isEmpty) { return equalsQuery; } - return new Query(`(!${equalsQuery.value})`); + return new Query(`not (${equalsQuery.value})`); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals.ts b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals.ts index e1a24998ca..6fa3813b7b 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals.ts @@ -1,7 +1,4 @@ import {Operator} from './operator'; -import {Equals} from './equals'; -import {OperatorService} from '../../operator-service/operator.service'; -import {Query} from '../query/query'; import {Operators} from './operators'; /** @@ -11,20 +8,8 @@ import {Operators} from './operators'; * For Date needs use {@link NotEqualsDate} instead. */ export class NotEquals extends Operator { - - protected equals: Equals; - - constructor(operators: OperatorService) { - super(1); - this.equals = operators.getOperator(Equals) as Equals; - } - - createQuery(elasticKeywords: Array, args: Array): Query { - const equalsQuery = this.equals.createQuery(elasticKeywords, args); - if (equalsQuery.isEmpty) { - return equalsQuery; - } - return new Query(`(!${equalsQuery.value})`); + constructor() { + super(1, 'neq'); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts b/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts index 4c5487d04d..64d5934c98 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts @@ -3,6 +3,7 @@ import {Query} from '../query/query'; import {BooleanOperator} from '../boolean-operator'; import {WrapResult} from '../wrap-result'; import {Operators} from './operators'; +import {UserAutocomplete} from "../category/user-autocomplete"; /** * Represents the low level abstraction of query generation that is responsible for the creation of queries themselves. @@ -55,6 +56,7 @@ export abstract class Operator { * @returns user input with the escapable characters escaped and the unescapable characters removed */ public static escapeInput(input: string): EscapeResult { + // todo 2466 escaping? if (typeof input === 'string') { let escaped = false; let output = ''; @@ -73,39 +75,37 @@ export abstract class Operator { } /** - * Creates a Query string query string literal with the provided arguments. - * @param elasticKeyword Elasticsearch index keyword for the field you want to query + * Creates a PFQL query with the provided arguments. + * @param pfqlKeyword PFQL keyword for the field you want to query * @param arg The value that you want to query the property for - * @param operator The operator you want to use to query the indexed field. Consult the Elasticsearch's - * [documentation]{@link https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html} - * for more information. - * @returns combines the input strings by this pattern: `([elasticKeyword]:[operator][arg])` + * @param operator The PFQL operator you want to use to query the field. + * @returns combines the input strings by this pattern: `[pfqlKeyword] [operator] [arg]` */ - public static query(elasticKeyword: string, arg: string, operator: string): string { - return `(${elasticKeyword}:${operator}${arg})`; + public static query(pfqlKeyword: string, arg: string, operator: string): string { + return `${pfqlKeyword} ${operator} ${arg}`; } /** * Applies the provided function to all keywords and combines the resulting queries with an `OR` operator. - * @param elasticKeywords keywords that the function is call on + * @param pfqlKeywords keywords that the function is call on * @param queryConstructor function that generates a `Query` object for each keyword */ - public static forEachKeyword(elasticKeywords: Array, queryConstructor: (keyword: string) => Query): Query { + public static forEachKeyword(pfqlKeywords: Array, queryConstructor: (keyword: string) => Query): Query { const simpleQueries = []; - elasticKeywords.forEach(keyword => { + pfqlKeywords.forEach(keyword => { simpleQueries.push(queryConstructor(keyword)); }); return Query.combineQueries(simpleQueries, BooleanOperator.OR); } /** - * If the value contains a space character, or if `force` is set to `true`. + * Wraps the input if the value is of a string type and canWrap is set to true * @param input user input that should be wrapped with double quotes - * @param forceWrap if set to `true` the value will be wrapped regardless of it's content + * @param canWrap is set to true if the wrapping is allowed */ - public static wrapInputWithQuotes(input: string, forceWrap = false): WrapResult { - if (typeof input === 'string' && (input?.includes(' ') || forceWrap)) - return {value: `"${input}"`, wasWrapped: true}; + public static wrapInputWithQuotes(input: string, canWrap: boolean = true): WrapResult { + if (typeof input === 'string' && canWrap && input !== UserAutocomplete.USER_ME_TEMPLATE) + return {value: `'${input}'`, wasWrapped: true}; else return {value: input, wasWrapped: false}; } @@ -124,12 +124,13 @@ export abstract class Operator { * the results with an `OR` operator. * @returns query that wos constructed with the given arguments and keywords. Returns an empty query if no arguments are provided. */ - public createQuery(elasticKeywords: Array, args: Array, escapeArgs = true): Query { + public createQuery(pfqlKeywords: Array, args: Array, escapeArgs = true, wrapInQuotes = true): Query { this.checkArgumentsCount(args); - return Operator.forEachKeyword(elasticKeywords, (keyword: string) => { + return Operator.forEachKeyword(pfqlKeywords, (keyword: string) => { + // todo 2466 escape? const escapedValue = escapeArgs ? Operator.escapeInput(args[0] as unknown as string) : ({value: args[0] as unknown as string, wasEscaped: false}); - const wrappedValue = Operator.wrapInputWithQuotes(escapedValue.value, escapedValue.wasEscaped); + const wrappedValue = Operator.wrapInputWithQuotes(escapedValue.value, wrapInQuotes); const queryString = Operator.query(keyword, wrappedValue.value, this._operatorSymbols); return new Query(queryString); }); diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/operators.ts b/projects/netgrif-components-core/src/lib/search/models/operator/operators.ts index 1cb391d51d..a10a883416 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/operators.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/operators.ts @@ -8,14 +8,14 @@ export enum Operators { IN_RANGE = 'in_range', IN_RANGE_DATE = 'in_range_date', IN_RANGE_DATE_TIME = 'in_range_date_time', - IS_NULL = 'is_null', + // IS_NULL = 'is_null', todo 2466 LESS_THAN = 'less_than', LESS_THAN_DATE = 'less_than_date', LESS_THAN_DATE_TIME = 'less_than_date_time', LESS_THAN_EQUAL = 'less_than_equal', LESS_THAN_EQUAL_DATE = 'less_than_equal_date', LESS_THAN_EQUAL_DATE_TIME = 'less_than_equal_date_time', - LIKE = 'like', + // LIKE = 'like', todo 2466 MORE_THAN = 'more_than', MORE_THAN_DATE = 'more_than_date', MORE_THAN_DATE_TIME = 'more_than_date_time', diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/substring.ts b/projects/netgrif-components-core/src/lib/search/models/operator/substring.ts index cd6eff6089..3c7425865e 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/substring.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/substring.ts @@ -1,5 +1,4 @@ import {Operator} from './operator'; -import {Query} from '../query/query'; import {Operators} from './operators'; /** @@ -8,16 +7,7 @@ import {Operators} from './operators'; */ export class Substring extends Operator { constructor() { - super(1); - } - - createQuery(elasticKeywords: Array, args: Array): Query { - this.checkArgumentsCount(args); - // TODO IMPROVEMENT 27.4.2020 - we could use regular expressions to search for substrings which would solve the unintuitive - // behavior that occurs when we search for strings that contain spaces. We need to escape the input string in a special way - // if we choose to do this - const escapedValue = Operator.escapeInput(args[0]).value?.replace(/ /g, '\\ '); - return Operator.forEachKeyword(elasticKeywords, keyword => new Query(`(${keyword}:*${escapedValue}*)`)); + super(1, 'contains'); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/persistance/filter-metadata-allowed-nets.ts b/projects/netgrif-components-core/src/lib/search/models/persistance/filter-metadata-allowed-nets.ts index 7863e606d4..de2e347b8d 100644 --- a/projects/netgrif-components-core/src/lib/search/models/persistance/filter-metadata-allowed-nets.ts +++ b/projects/netgrif-components-core/src/lib/search/models/persistance/filter-metadata-allowed-nets.ts @@ -4,6 +4,7 @@ import {FilterMetadata} from './filter-metadata'; * The bare minimum of information necessary for the reconstruction of a saved filter */ export interface FilterMetadataAllowedNets { + // todo 2466 remove? /** * Allowed nets used to create the filter */ diff --git a/projects/netgrif-components-core/src/lib/search/models/persistance/filter-metadata.ts b/projects/netgrif-components-core/src/lib/search/models/persistance/filter-metadata.ts index 72c08cf33a..4f9509962c 100644 --- a/projects/netgrif-components-core/src/lib/search/models/persistance/filter-metadata.ts +++ b/projects/netgrif-components-core/src/lib/search/models/persistance/filter-metadata.ts @@ -5,6 +5,7 @@ import {PredicateTreeMetadata} from './generator-metadata'; * Saved filter generated by the {@link AbstractAdvancedSearchComponent}. */ export interface FilterMetadata { + // todo 2466 remove? filterType: FilterType; predicateMetadata: PredicateTreeMetadata; /** diff --git a/projects/netgrif-components-core/src/lib/search/models/persistance/saved-filter-metadata.ts b/projects/netgrif-components-core/src/lib/search/models/persistance/saved-filter-metadata.ts index b21082f233..de15147cc0 100644 --- a/projects/netgrif-components-core/src/lib/search/models/persistance/saved-filter-metadata.ts +++ b/projects/netgrif-components-core/src/lib/search/models/persistance/saved-filter-metadata.ts @@ -6,6 +6,7 @@ import {FilterMetadataAllowedNets} from './filter-metadata-allowed-nets'; * All the necessary data for full reconstruction of a saved filter */ export interface SavedFilterMetadata extends FilterMetadataAllowedNets { + // todo 2466 remove? /** * The view ID of the view the filter was created in */ diff --git a/projects/netgrif-components-core/src/lib/search/models/query/query.ts b/projects/netgrif-components-core/src/lib/search/models/query/query.ts index fa09c3876c..aecb154584 100644 --- a/projects/netgrif-components-core/src/lib/search/models/query/query.ts +++ b/projects/netgrif-components-core/src/lib/search/models/query/query.ts @@ -1,30 +1,47 @@ import {BooleanOperator} from '../boolean-operator'; +import {ResourceTypeQueryPrefix} from "../category/resource-type-query-prefix"; /** * Abstraction of queries, so that their implementation can be replaced as needed. */ export class Query { + private static PREFIX_DELIMETER: string = ': '; + /** * @param _value see [value]{@link Query#value} for the specification of this attribute. + * @param _resourcePrefix resource prefix in a PFQL query * @param _empty use `true` if the Query object represents an empty query */ - constructor(private _value: string, private _empty = false) { + constructor(private _value: string, private _resourcePrefix: string = undefined, private readonly _empty = false) { if (!this._value || this._value === '') { this._empty = true; } + if (!!this._empty) { + this._value = _resourcePrefix; // no filter is going to be applied to search + } } /** - * @returns an Elastic search Query string query wrapped in braces. - * - * See Elasticsearch's - * [documentation]{@link https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html} - * for more information about Query string queries. + * @returns a PFQL search query string. */ public get value(): string { return this._value; } + /** + * @returns the query value without the resource type prefix. If no prefix is present, returns the full value or + * empty string if the query contains only the resource prefix. + */ + public get valueWithoutPrefix(): string { + if (!this._resourcePrefix || !this._value || !this._value.startsWith(this._resourcePrefix + Query.PREFIX_DELIMETER)) { + return this._value; + } + if (this._value === this._resourcePrefix) { + return ''; + } + return this._value.substring(this._resourcePrefix.length + Query.PREFIX_DELIMETER.length); + } + /** * @returns whether this Query object represents an empty query or not */ @@ -45,24 +62,39 @@ export class Query { return Query.emptyQuery(); } if (realQueries.length === 1) { - return new Query(realQueries[0].value); + return new Query(realQueries[0].value, realQueries[0].resourcePrefix); + } + const prefixes = new Set(realQueries.map(q => q.resourcePrefix).filter(p => p !== undefined)); + if (prefixes.size > 1) { + throw new Error(`Cannot combine queries with different resource prefixes: ${[...prefixes].join(', ')}`); + } + const commonPrefix: string = prefixes.size === 1 ? [...prefixes][0] : undefined; + const realQueriesWithoutPrefix: string[] = realQueries.map(q => q.valueWithoutPrefix); + const isWildcard: boolean = realQueriesWithoutPrefix.some(queryValue => queryValue === ''); + if (operator === BooleanOperator.OR && isWildcard) { + // no filter should be applied + return new Query(undefined, commonPrefix); } - const combinedQuery = realQueries.map(q => q.value).join(` ${operator} `); - return new Query(`(${combinedQuery})`); + const combinedQuery = realQueries + .map(q => q.valueWithoutPrefix) + .filter(q => q !== '') + .join(` ${operator} `); + const fullValue = commonPrefix ? commonPrefix + Query.PREFIX_DELIMETER + combinedQuery : combinedQuery; + return new Query(fullValue, commonPrefix); } /** * Returns a `Query` with it's `value` set to an empty string. */ public static emptyQuery(): Query { - return new Query('', true); + return new Query('', undefined, true); } /** * @param query the query that should be compared * @returns `true` if and only if the queries are equal. * Returns `false` if the queries are not equal, or if attempting to tell the queries apart is too complicated. - * More specifically the method can always tell apart empty queries and if poth queries are non-empty then their values are compared. + * More specifically the method can always tell apart empty queries and if both queries are non-empty then their values are compared. */ public equals(query: Query): boolean { if (this.isEmpty && query.isEmpty) { @@ -73,4 +105,32 @@ export class Query { } return this.value === query.value; } + + /** + * Adds a resource type prefix to the query value if it's not already present. + * If the query is empty, sets the value to the provided prefix. + * If the prefix is already present at the start of the value, returns the query unchanged. + * Otherwise, prepends the prefix followed by the delimiter to the existing value. + * @param resourceTypePrefix the resource type prefix to add to the query + * @returns this Query instance with the updated value + */ + public addPrefixAndGet(resourceTypePrefix: ResourceTypeQueryPrefix): Query { + if (this.isEmpty) { + this._value = resourceTypePrefix; + return this; + } + if (this._value.startsWith(resourceTypePrefix + Query.PREFIX_DELIMETER)) { + return this; + } + this._value = resourceTypePrefix + Query.PREFIX_DELIMETER + this._value; + this._resourcePrefix = resourceTypePrefix; + return this; + } + + /** + * @returns Resource prefix in a PFQL query. Might be undefined + */ + public get resourcePrefix(): string | undefined { + return this._resourcePrefix; + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/search-index.ts b/projects/netgrif-components-core/src/lib/search/models/search-index.ts index 5c204be2b7..27c9384217 100644 --- a/projects/netgrif-components-core/src/lib/search/models/search-index.ts +++ b/projects/netgrif-components-core/src/lib/search/models/search-index.ts @@ -1,4 +1,5 @@ export enum SearchIndex { + // todo 2466 later remove? /** * Indexed as TEXT * diff --git a/projects/netgrif-components-core/src/lib/search/operator-service/operator-resolver.service.ts b/projects/netgrif-components-core/src/lib/search/operator-service/operator-resolver.service.ts index a4ceb2f5d5..d58e4934aa 100644 --- a/projects/netgrif-components-core/src/lib/search/operator-service/operator-resolver.service.ts +++ b/projects/netgrif-components-core/src/lib/search/operator-service/operator-resolver.service.ts @@ -55,8 +55,8 @@ export class OperatorResolverService { return InRangeDate; case Operators.IN_RANGE_DATE_TIME: return InRangeDateTime; - case Operators.IS_NULL: - return IsNull; + // case Operators.IS_NULL: todo 2466 + // return IsNull; case Operators.LESS_THAN: return LessThan; case Operators.LESS_THAN_DATE: @@ -69,8 +69,8 @@ export class OperatorResolverService { return LessThanEqualDate; case Operators.LESS_THAN_EQUAL_DATE_TIME: return LessThanEqualDateTime; - case Operators.LIKE: - return Like; + // case Operators.LIKE: todo 2466 + // return Like; case Operators.MORE_THAN: return MoreThan; case Operators.MORE_THAN_DATE: diff --git a/projects/netgrif-components-core/src/lib/search/public-api.ts b/projects/netgrif-components-core/src/lib/search/public-api.ts index b4acab50e4..632c06957e 100644 --- a/projects/netgrif-components-core/src/lib/search/public-api.ts +++ b/projects/netgrif-components-core/src/lib/search/public-api.ts @@ -42,7 +42,6 @@ export * from './models/category/case/case-visual-id'; export * from './models/category/case/case-author'; export * from './models/category/case/case-process'; export * from './models/category/case/case-role'; -export * from './models/category/case/case-task'; export * from './models/category/case/case-creation-date'; export * from './models/category/case/case-creation-date-time'; export * from './models/category/case/case-dataset'; @@ -53,6 +52,7 @@ export * from './models/category/task/task-assignee'; export * from './models/category/task/task-process'; export * from './models/category/task/task-role'; export * from './models/category/task/task-task'; +export * from './models/category/resource-type-query-prefix'; export * from './models/datafield-map-key'; export * from './models/operator-template-part'; diff --git a/projects/netgrif-components-core/src/lib/search/search-keyword-resolver-service/search-index-resolver.service.ts b/projects/netgrif-components-core/src/lib/search/search-keyword-resolver-service/search-index-resolver.service.ts index 141abf53dc..d6911b2802 100644 --- a/projects/netgrif-components-core/src/lib/search/search-keyword-resolver-service/search-index-resolver.service.ts +++ b/projects/netgrif-components-core/src/lib/search/search-keyword-resolver-service/search-index-resolver.service.ts @@ -15,6 +15,8 @@ import {SearchIndex} from '../models/search-index'; }) export class SearchIndexResolverService { + // todo 2466 needed? + public readonly KEYWORD = '.keyword'; constructor() { } diff --git a/projects/netgrif-components-core/src/lib/search/search-operand-input-component/abstract-search-operand-input.component.ts b/projects/netgrif-components-core/src/lib/search/search-operand-input-component/abstract-search-operand-input.component.ts index a735487a94..698b08b806 100644 --- a/projects/netgrif-components-core/src/lib/search/search-operand-input-component/abstract-search-operand-input.component.ts +++ b/projects/netgrif-components-core/src/lib/search/search-operand-input-component/abstract-search-operand-input.component.ts @@ -4,6 +4,8 @@ import {SearchInputType} from '../models/category/search-input-type'; import {Observable, Subscription} from 'rxjs'; import {SearchAutocompleteOption} from '../models/category/search-autocomplete-option'; import {debounceTime} from 'rxjs/operators'; +import moment from "moment/moment"; +import {DATE_FORMAT_STRING, DATE_TIME_FORMAT_STRING} from '../../moment/time-formats' @Component({ selector: 'ncc-abstract-search-operand-input', @@ -120,4 +122,12 @@ export abstract class AbstractSearchOperandInputComponent implements OnInit, OnD return this.inputFormControl.value !== undefined && this.inputFormControl.value !== null; } + + public formatDate(value: string): string { + return moment(value, 'YYYY-MM-DD').format(DATE_FORMAT_STRING); + } + + public formatDateTime(value: string): string { + return moment(value, 'YYYY-MM-DDTHH:mm:ss').format(DATE_TIME_FORMAT_STRING); + } } diff --git a/projects/netgrif-components-core/src/lib/utility/clear-time-information.spec.ts b/projects/netgrif-components-core/src/lib/utility/clear-time-information.spec.ts deleted file mode 100644 index f5feab531a..0000000000 --- a/projects/netgrif-components-core/src/lib/utility/clear-time-information.spec.ts +++ /dev/null @@ -1,32 +0,0 @@ -import moment from 'moment'; -import {clearTimeInformation} from './clear-time-information'; -import {TestBed} from '@angular/core/testing'; - - -describe('clearTimeInformation', () => { - it('should clear information correctly', () => { - const dateTime = moment('2021-01-14 07:50:42.069'); - expect(dateTime).toBeTruthy(); - expect(dateTime.milliseconds()).toEqual(69); - expect(dateTime.seconds()).toEqual(42); - expect(dateTime.minutes()).toEqual(50); - expect(dateTime.hours()).toEqual(7); - expect(dateTime.date()).toEqual(14); - expect(dateTime.month()).toEqual(0); // month is 0 indexed - expect(dateTime.year()).toEqual(2021); - - clearTimeInformation(dateTime); - - expect(dateTime.milliseconds()).toEqual(0); - expect(dateTime.seconds()).toEqual(0); - expect(dateTime.minutes()).toEqual(0); - expect(dateTime.hours()).toEqual(0); - expect(dateTime.date()).toEqual(14); - expect(dateTime.month()).toEqual(0); - expect(dateTime.year()).toEqual(2021); - }); - - afterEach(() => { - TestBed.resetTestingModule(); - }); -}); diff --git a/projects/netgrif-components-core/src/lib/utility/clear-time-information.ts b/projects/netgrif-components-core/src/lib/utility/clear-time-information.ts deleted file mode 100644 index ca44adf3c1..0000000000 --- a/projects/netgrif-components-core/src/lib/utility/clear-time-information.ts +++ /dev/null @@ -1,12 +0,0 @@ -import {Moment} from 'moment'; - -/** - * Sets milliseconds, seconds, minutes and hours of the provided Moment object to 0 - * @param date object that we want to clear time information from - */ -export function clearTimeInformation(date: Moment): void { - date.milliseconds(0); - date.seconds(0); - date.minutes(0); - date.hours(0); -} diff --git a/projects/netgrif-components-core/src/lib/utility/public-api.ts b/projects/netgrif-components-core/src/lib/utility/public-api.ts index 16cf0299a2..cd9101e0fc 100644 --- a/projects/netgrif-components-core/src/lib/utility/public-api.ts +++ b/projects/netgrif-components-core/src/lib/utility/public-api.ts @@ -15,7 +15,6 @@ export * from './incrementing-counter'; export * from './array-to-observable'; export * from './process-message-response'; export * from './result-with-after-actions'; -export * from './clear-time-information'; export * from './refresh-tree'; export * from './destroy-subscription'; export * from './navigation-item-task-filter-factory'; diff --git a/projects/netgrif-components/src/lib/search/advanced-search/search-operand-input-component/search-operand-input.component.html b/projects/netgrif-components/src/lib/search/advanced-search/search-operand-input-component/search-operand-input.component.html index 2ecbf6a44d..e633056139 100644 --- a/projects/netgrif-components/src/lib/search/advanced-search/search-operand-input-component/search-operand-input.component.html +++ b/projects/netgrif-components/src/lib/search/advanced-search/search-operand-input-component/search-operand-input.component.html @@ -103,10 +103,10 @@ {{inputFormControl.value.text | translate}}
- {{inputFormControl.value.format(dateFormat)}} + {{formatDate(inputFormControl.value)}}
- {{inputFormControl.value.format(dateTimeFormat)}} + {{formatDateTime(inputFormControl.value)}}
{{inputFormControl.value}} diff --git a/projects/netgrif-components/src/lib/search/advanced-search/search-operand-input-component/search-operand-input.component.ts b/projects/netgrif-components/src/lib/search/advanced-search/search-operand-input-component/search-operand-input.component.ts index 207ab89171..1ba109fa47 100644 --- a/projects/netgrif-components/src/lib/search/advanced-search/search-operand-input-component/search-operand-input.component.ts +++ b/projects/netgrif-components/src/lib/search/advanced-search/search-operand-input-component/search-operand-input.component.ts @@ -20,9 +20,6 @@ export class SearchOperandInputComponent extends AbstractSearchOperandInputCompo // make enum accessible in HTMl public searchInputType = SearchInputType; - public dateFormat = DATE_FORMAT_STRING; - public dateTimeFormat = DATE_TIME_FORMAT_STRING; - constructor() { super(); } From 9535f55e514b949e2a4fb7fa70395754ccaa2285 Mon Sep 17 00:00:00 2001 From: chvostek Date: Mon, 20 Jul 2026 09:31:44 +0200 Subject: [PATCH 03/55] [NAE-2466] Advanced search for PFQL - fix tests - fix code according to tests --- .../category-factory/default-categories-factories.spec.ts | 2 +- .../src/lib/search/models/category/case/case-dataset.ts | 2 +- .../src/lib/search/models/category/case/case-title.spec.ts | 4 ++-- .../lib/search/models/category/case/case-visual-id.spec.ts | 3 +-- .../src/lib/search/models/category/case/case-visual-id.ts | 3 ++- .../src/lib/search/models/category/categories.ts | 2 +- .../src/lib/search/models/operator/not-equals.spec.ts | 4 +--- .../src/lib/search/search-service/search.service.spec.ts | 7 +------ 8 files changed, 10 insertions(+), 17 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.spec.ts b/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.spec.ts index efb78b69fc..3094616a14 100644 --- a/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.spec.ts @@ -55,7 +55,7 @@ describe('Default search categories factory methods', () => { expect(testService).toBeTruthy(); expect(testService.searchCategories).toBeTruthy(); expect(Array.isArray(testService.searchCategories)).toBeTrue(); - expect(testService.searchCategories.length).toBe(9); + expect(testService.searchCategories.length).toBe(7); for (const category of testService.searchCategories) { expect(category).toBeTruthy(); } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts index c4434d36de..dddddc4453 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts @@ -51,7 +51,7 @@ interface Datafield { export class CaseDataset extends Category implements AutocompleteOptions { private static readonly _i18n = 'search.category.case.dataset'; - protected static DISABLED_TYPES = [FieldTypeResource.BOOLEAN.valueOf(), FieldTypeResource.TASK_REF.valueOf(), + protected static DISABLED_TYPES = [FieldTypeResource.BUTTON.valueOf(), FieldTypeResource.TASK_REF.valueOf(), FieldTypeResource.CASE_REF.valueOf(), FieldTypeResource.CASE_FILTER.valueOf(), FieldTypeResource.TASK_FILTER.valueOf(), FieldTypeResource.PROCESS_FILTER.valueOf()]; protected static readonly DATAFIELD_METADATA = 'datafield'; diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.spec.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.spec.ts index db17b04cc1..8a24b2e31a 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.spec.ts @@ -74,9 +74,9 @@ describe('CaseTitle', () => { }); }); - it('should use keyword index', () => { + it('should generate pfql query', () => { configureCategory(category, operatorService, Substring, ['foo']); const predicate = category.generatePredicate(['input']); - expect(predicate.query.value.includes(`${CaseSearch.TITLE}${deps.searchIndexResolver.KEYWORD}`)).toBeTrue(); + expect(predicate.query.value.includes(`cases: ${CaseSearch.TITLE} contains 'input'`)).toBeTrue(); }); }); diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.spec.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.spec.ts index 463715b8c0..837e9b5fdb 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.spec.ts @@ -3,7 +3,6 @@ import {OperatorService} from '../../../operator-service/operator.service'; import {OperatorResolverService} from '../../../operator-service/operator-resolver.service'; import {configureCategory} from '../../../../utility/tests/utility/configure-category'; import {Equals} from '../../operator/equals'; -import {Categories} from '../categories'; import {Operators} from '../../operator/operators'; import {TestBed} from '@angular/core/testing'; import {Substring} from '../../operator/substring'; @@ -47,7 +46,7 @@ describe('CaseVisualId', () => { const metadata = category.createMetadata(); expect(metadata).toBeTruthy(); expect(metadata.values).toEqual(['foo']); - expect(metadata.category).toBe(Categories.CASE_VISUAL_ID); + expect(metadata.category).toBe("visualId"); expect(metadata.configuration?.operator).toBe(Operators.EQUALS); }); diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.ts index 0d6af217ba..a2438f3259 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.ts @@ -35,7 +35,8 @@ export class CaseVisualId extends NoConfigurationCategory { } serializeClass(): Categories | string { - return Categories.CASE_VISUAL_ID; + return "visualId"; + // return Categories.CASE_VISUAL_ID; todo 2466 } protected get pfqlKeywords(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/categories.ts b/projects/netgrif-components-core/src/lib/search/models/category/categories.ts index ac4f46d6f1..4ddb75890d 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/categories.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/categories.ts @@ -11,7 +11,7 @@ export enum Categories { CASE_ROLE = 'case_role', CASE_SIMPLE_DATASET = 'case_simple_dataset', CASE_TITLE = 'case_title', - CASE_VISUAL_ID = 'case_visual_id', + // CASE_VISUAL_ID = 'case_visual_id', // todo 2466 CASE_STRING_ID = 'case_string_id', // Task categories diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals.spec.ts b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals.spec.ts index d7933ce878..34b248b993 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals.spec.ts @@ -1,11 +1,9 @@ import {NotEquals} from './not-equals'; -import {OperatorService} from '../../operator-service/operator.service'; -import {OperatorResolverService} from '../../operator-service/operator-resolver.service'; import {TestBed} from '@angular/core/testing'; describe('NotEquals', () => { it('should create an instance', () => { - expect(new NotEquals(new OperatorService(new OperatorResolverService()))).toBeTruthy(); + expect(new NotEquals()).toBeTruthy(); }); afterEach(() => { diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts index 923bd270db..08bafee062 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts @@ -86,19 +86,14 @@ describe('SearchService', () => { const predicate2 = categoryFactory.getWithDefaultOperator(CaseCreationDate); predicate2.setOperands([moment('2021-03-31').valueOf()]); - const predicate3 = categoryFactory.getWithDefaultOperator(CaseVisualId); - predicate3.setOperands(['visualId']); - const meta1 = predicate1.createMetadata(); expect(meta1).toBeTruthy(); const meta2 = predicate2.createMetadata(); expect(meta2).toBeTruthy(); - const meta3 = predicate3.createMetadata(); - expect(meta3).toBeTruthy(); serializedSearch = { filterType: FilterType.CASE, - predicateMetadata: [[meta1, meta2], [meta3]], + predicateMetadata: [[meta1, meta2]], searchCategories: [] // they don't play a role for this test }; }); From 1a5f88e28b22150f84bdaa049af2b447b98780ab Mon Sep 17 00:00:00 2001 From: chvostek Date: Mon, 20 Jul 2026 09:50:55 +0200 Subject: [PATCH 04/55] [NAE-2466] Advanced search for PFQL - update tests with some pfql queries --- .../models/category/case/case-creation-date-time.spec.ts | 8 +++++++- .../lib/search/models/category/case/case-process.spec.ts | 6 ++++++ .../search/models/category/case/case-string-id.spec.ts | 6 ++++++ .../lib/search/models/category/case/case-title.spec.ts | 7 ++++++- 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date-time.spec.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date-time.spec.ts index dcad9bbf0c..71edbeac53 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date-time.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date-time.spec.ts @@ -4,10 +4,10 @@ import {configureCategory} from '../../../../utility/tests/utility/configure-cat import {Categories} from '../categories'; import {Operators} from '../../operator/operators'; import moment from 'moment'; -import {EqualsDate} from '../../operator/equals-date'; import {CaseCreationDateTime} from './case-creation-date-time'; import {EqualsDateTime} from '../../operator/equals-date-time'; import {TestBed} from '@angular/core/testing'; +import {InRangeDateTime} from "../../operator/in-range-date-time"; describe('CaseCreationDateTime', () => { let category: CaseCreationDateTime; @@ -73,4 +73,10 @@ describe('CaseCreationDateTime', () => { done(); }); }); + + it('should generate pfql query', () => { + configureCategory(category, operatorService, InRangeDateTime, ['foo']); + const predicate = category.generatePredicate([moment('2021-08-17 15:28'), moment('2021-08-18 15:28')]); + expect(predicate.query.value === `cases: creationDate in (2021-08-17T15:28:00 : 2021-08-18T15:29:00)`).toBeTrue(); + }); }); diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.spec.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.spec.ts index badc3d8d14..03452ac899 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.spec.ts @@ -145,4 +145,10 @@ describe('CaseProcess', () => { }); }); }); + + it('should generate pfql query', () => { + configureCategory(category, operatorService, Equals, ['foo']); + const predicate = category.generatePredicate([['process']]); + expect(predicate.query.value === `cases: processIdentifier eq 'process'`).toBeTrue(); + }); }); diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-string-id.spec.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-string-id.spec.ts index 3da4eab92f..79b67a9042 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-string-id.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-string-id.spec.ts @@ -66,4 +66,10 @@ describe('CaseStringId', () => { done(); }); }); + + it('should generate pfql query', () => { + configureCategory(category, operatorService, Equals, ['foo']); + const predicate = category.generatePredicate(['6a5dc0cd2d68aa051f92cbe5']); + expect(predicate.query.value === `cases: id eq '6a5dc0cd2d68aa051f92cbe5'`).toBeTrue(); + }); }); diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.spec.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.spec.ts index 8a24b2e31a..93d68a0222 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.spec.ts @@ -10,6 +10,7 @@ import {Substring} from '../../operator/substring'; import {CaseSearch} from './case-search.enum'; import {SearchIndexResolverService} from '../../../search-keyword-resolver-service/search-index-resolver.service'; import {OptionalDependencies} from '../../../category-factory/optional-dependencies'; +import {NotEquals} from "../../operator/not-equals"; describe('CaseTitle', () => { let category: CaseTitle; @@ -76,7 +77,11 @@ describe('CaseTitle', () => { it('should generate pfql query', () => { configureCategory(category, operatorService, Substring, ['foo']); - const predicate = category.generatePredicate(['input']); + let predicate = category.generatePredicate(['input']); expect(predicate.query.value.includes(`cases: ${CaseSearch.TITLE} contains 'input'`)).toBeTrue(); + + configureCategory(category, operatorService, NotEquals, ['foo']); + predicate = category.generatePredicate(['loggedUser.id']); + expect(predicate.query.value === `cases: ${CaseSearch.TITLE} neq loggedUser.id`).toBeTrue(); }); }); From 574458b48e7d9d307f06ff491853981e4952996f Mon Sep 17 00:00:00 2001 From: chvostek Date: Tue, 21 Jul 2026 13:45:02 +0200 Subject: [PATCH 05/55] [NAE-2466] Advanced search for PFQL - update operator is-null to work with PFQL --- .../models/category/case/case-dataset.ts | 28 ++++---- .../search/models/category/case/case-role.ts | 2 +- .../models/category/case/case-visual-id.ts | 2 +- .../models/category/task/task-assignee.ts | 2 +- .../search/models/category/task/task-role.ts | 2 +- .../src/lib/search/models/operator/is-null.ts | 72 +++++++++---------- .../lib/search/models/operator/operators.ts | 2 +- .../src/lib/search/models/query/query.ts | 1 + .../operator-resolver.service.ts | 4 +- 9 files changed, 54 insertions(+), 61 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts index dddddc4453..6404c1ca7e 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts @@ -15,6 +15,7 @@ import { Equals } from '../../operator/equals'; import { BehaviorSubject, Observable, of, ReplaySubject, Subscription } from 'rxjs'; import { Category } from '../category'; import { NotEquals } from '../../operator/not-equals'; +import { IsNull } from '../../operator/is-null'; import { MoreThan } from '../../operator/more-than'; import { LessThan } from '../../operator/less-than'; import { InRange } from '../../operator/in-range'; @@ -168,7 +169,7 @@ export class CaseDataset extends Category implements AutocompleteOpti this._operatorService.getOperator(LessThan), this._operatorService.getOperator(LessThanEqual), this._operatorService.getOperator(InRange), - // this._operatorService.getOperator(IsNull) todo 2466 + this._operatorService.getOperator(IsNull) ]; case FieldTypeResource.BOOLEAN.valueOf(): return [ @@ -180,7 +181,7 @@ export class CaseDataset extends Category implements AutocompleteOpti return [ this._operatorService.getOperator(Equals), this._operatorService.getOperator(NotEquals), - // this._operatorService.getOperator(IsNull) todo 2466 + this._operatorService.getOperator(IsNull) ]; case FieldTypeResource.DATE.valueOf(): return [ @@ -191,7 +192,7 @@ export class CaseDataset extends Category implements AutocompleteOpti this._operatorService.getOperator(LessThanDate), this._operatorService.getOperator(LessThanEqualDate), this._operatorService.getOperator(InRangeDate), - // this._operatorService.getOperator(IsNull) todo 2466 + this._operatorService.getOperator(IsNull) ]; case FieldTypeResource.DATE_TIME.valueOf(): return [ @@ -201,7 +202,7 @@ export class CaseDataset extends Category implements AutocompleteOpti this._operatorService.getOperator(LessThanDateTime), this._operatorService.getOperator(LessThanEqualDateTime), this._operatorService.getOperator(InRangeDateTime), - // this._operatorService.getOperator(IsNull) todo 2466 + this._operatorService.getOperator(IsNull) ]; default: return [ @@ -212,8 +213,8 @@ export class CaseDataset extends Category implements AutocompleteOpti this._operatorService.getOperator(MoreThanEqual), this._operatorService.getOperator(LessThan), this._operatorService.getOperator(LessThanEqual), - // this._operatorService.getOperator(IsNull), todo 2466 - // this._operatorService.getOperator(Like) + this._operatorService.getOperator(IsNull) + // this._operatorService.getOperator(Like) todo 2466 ]; } } @@ -263,10 +264,9 @@ export class CaseDataset extends Category implements AutocompleteOpti protected generateQuery(userInput: Array): Query { let queryGenerationStrategy; - // todo 2466 remove if - /*if (this.isSelectedOperator(IsNull)) { + if (this.isSelectedOperator(IsNull)) { queryGenerationStrategy = (d, _) => this.isNullOperatorQueryGenerationStrategy(d); - } else*/ if (this.inputType === SearchInputType.AUTOCOMPLETE) { + } else if (this.inputType === SearchInputType.AUTOCOMPLETE) { queryGenerationStrategy = (d, ui) => this.standardQueryGenerationStrategy(d, ui[0], false); } else { queryGenerationStrategy = (d, ui) => this.standardQueryGenerationStrategy(d, ui); @@ -283,11 +283,11 @@ export class CaseDataset extends Category implements AutocompleteOpti return query.addPrefixAndGet(ResourceTypeQueryPrefix.CASES); } - // todo 2466 - // protected isNullOperatorQueryGenerationStrategy(datafield: Datafield): Query { - // const constraint = this.generateNetConstraint(datafield); - // return (this._operatorService.getOperator(IsNull) as IsNull).createQueryWithConstraint(this.pfqlKeywords, constraint); - // } + protected isNullOperatorQueryGenerationStrategy(datafield: Datafield): Query { + const constraint = this.generateNetConstraint(datafield); + return (this._operatorService.getOperator(IsNull) as IsNull).createQueryWithConstraint(this.pfqlKeywords, constraint) + .addPrefixAndGet(ResourceTypeQueryPrefix.CASES); + } protected generateNetConstraint(datafield: Datafield): Query { return this._processCategory.generatePredicate([[datafield.netIdentifier]]).query; diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-role.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-role.ts index 5c910e03b7..a0beec5d84 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-role.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-role.ts @@ -12,7 +12,7 @@ import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; export class CaseRole extends CaseNetAttributeAutocompleteCategory { - // todo 2466 impossible in pfql + // todo 2466 impossible in pfql - prec private static readonly _i18n = 'search.category.case.role'; diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.ts index a2438f3259..a5ed12c230 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.ts @@ -12,7 +12,7 @@ import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; export class CaseVisualId extends NoConfigurationCategory { - // todo 2466 impossible in pfql + // todo 2466 impossible in pfql - prec private static readonly _i18n = 'search.category.case.visualId'; diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-assignee.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-assignee.ts index 216394959a..7e5f3619cc 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-assignee.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-assignee.ts @@ -18,7 +18,7 @@ export class TaskAssignee extends NoConfigurationUserAutocompleteCategory { [ operators.getOperator(Equals), operators.getOperator(NotEquals), - // operators.getOperator(IsNull) todo 2466 impossible in PFQL + operators.getOperator(IsNull) ], `${TaskAssignee._i18n}.name`, logger, diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-role.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-role.ts index 5ae8a62b88..bd2ffe33e4 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-role.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-role.ts @@ -11,7 +11,7 @@ import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; export class TaskRole extends TaskNetAttributeAutocompleteCategory { - // todo 2466 impossible in pfql + // todo 2466 impossible in pfql - prec private static readonly _i18n = 'search.category.task.role'; diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/is-null.ts b/projects/netgrif-components-core/src/lib/search/models/operator/is-null.ts index 307fc43489..e3ebb07a9b 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/is-null.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/is-null.ts @@ -1,6 +1,7 @@ import {Operator} from './operator'; import {Query} from '../query/query'; import {Operators} from './operators'; +import {BooleanOperator} from "../boolean-operator"; /** * An operator that can be used on any field and matches entries with null or empty string values. @@ -9,69 +10,61 @@ import {Operators} from './operators'; * Consult the [createQueryWithConstraint()]{@link IsNull#createQueryWithConstraint} method for more information. */ export class IsNull extends Operator { - // todo 2466 impossible in PFQL constructor() { super(0); } /** - * @param elasticKeywords the queried fields + * @param pfqlKeywords the queried fields * @returns Generates a query that matches null fields and fields with empty string values. */ - createQuery(elasticKeywords: Array): Query { - return Operator.forEachKeyword(elasticKeywords, - keyword => new Query(`(${this.nullQueryString(keyword)}OR${this.emptyStringQueryString(keyword)})`) + createQuery(pfqlKeywords: Array): Query { + return Operator.forEachKeyword(pfqlKeywords, + keyword => { + const nullQuery = this.nullQuery(keyword); + const emptyQuery = this.emptyQuery(keyword); + return Query.combineQueries([nullQuery, emptyQuery], BooleanOperator.OR) + } ); } /** - * Counterintuitively elasticsearch query string queries behave weirdly when combining the queries with operators such as `AND`. - * Because of this the following query: + * Creates query to check if the fields (in pfqlKeywords) are null or empty. * - * (dataSet.text_0.value:"") + * @param pfqlKeywords attributes that should be null or empty + * @param constraint constraint to match process identifier * - * returns an empty result set. - * - * But query that should be intuitively more constraining: - * - * (dataSet.text_0.value:"") AND (processId:600168ccf68fea5241ae5e62) - * - * will return a non empty and expected result. - * - * This method exists to combat this issue and add the, sometimes necessary, constraint into the query generated by this operator. - * - * @param elasticKeywords the queried fields - * @param constraint a constraining query that is distributively applied into the query generated by this operator. - * If an empty query is provided the result will be the same as calling [createQuery()]{@link IsNull#createQuery}. - * @returns a query with distributively applied constraint query + * @return Query containing the null and empty query with the contraint. */ - createQueryWithConstraint(elasticKeywords: Array, constraint: Query): Query { + createQueryWithConstraint(pfqlKeywords: Array, constraint: Query): Query { if (constraint.isEmpty) { - return this.createQuery(elasticKeywords); + return this.createQuery(pfqlKeywords); } - - return Operator.forEachKeyword(elasticKeywords, - keyword => new Query( - `((${this.nullQueryString(keyword)}AND${constraint.value})OR(${this.emptyStringQueryString(keyword)}AND${constraint.value}))` - ) - ); + return Operator.forEachKeyword(pfqlKeywords, + keyword => { + const nullQuery = this.nullQuery(keyword); + const emptyQuery = this.emptyQuery(keyword); + const nullAndConstraintQuery = Query.combineQueries([nullQuery, constraint], BooleanOperator.AND) + const emptyAndConstraintQuery = Query.combineQueries([emptyQuery, constraint], BooleanOperator.AND) + return Query.combineQueries([nullAndConstraintQuery, emptyAndConstraintQuery], BooleanOperator.OR) + }); } /** - * @param elasticKeyword the queried field - * @returns a string representation of the query that checks whether the field is null + * @param pfqlKeyword the queried field + * @returns a query that checks whether the field is null */ - protected nullQueryString(elasticKeyword: string): string { - return `(!(_exists_:${elasticKeyword}))`; + protected nullQuery(pfqlKeyword: string): Query { + return new Query(`${pfqlKeyword} eq null`); } /** - * @param elasticKeyword the queried field - * @returns a string representation of the query that checks whether the field has an empty string value + * @param pfqlKeyword the queried field + * @returns a query that checks whether the field has an empty string value */ - protected emptyStringQueryString(elasticKeyword: string): string { - return `(${elasticKeyword}:"")`; + protected emptyQuery(pfqlKeyword: string): Query { + return new Query(`${pfqlKeyword} eq ''`); } getOperatorNameTemplate(): Array { @@ -79,7 +72,6 @@ export class IsNull extends Operator { } serialize(): Operators | string { - return 'is_null'; - // return Operators.IS_NULL; + return Operators.IS_NULL; } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/operators.ts b/projects/netgrif-components-core/src/lib/search/models/operator/operators.ts index a10a883416..2ba84974b6 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/operators.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/operators.ts @@ -8,7 +8,7 @@ export enum Operators { IN_RANGE = 'in_range', IN_RANGE_DATE = 'in_range_date', IN_RANGE_DATE_TIME = 'in_range_date_time', - // IS_NULL = 'is_null', todo 2466 + IS_NULL = 'is_null', LESS_THAN = 'less_than', LESS_THAN_DATE = 'less_than_date', LESS_THAN_DATE_TIME = 'less_than_date_time', diff --git a/projects/netgrif-components-core/src/lib/search/models/query/query.ts b/projects/netgrif-components-core/src/lib/search/models/query/query.ts index aecb154584..3052d335e8 100644 --- a/projects/netgrif-components-core/src/lib/search/models/query/query.ts +++ b/projects/netgrif-components-core/src/lib/search/models/query/query.ts @@ -78,6 +78,7 @@ export class Query { const combinedQuery = realQueries .map(q => q.valueWithoutPrefix) .filter(q => q !== '') + .map(q => '(' + q + ')') .join(` ${operator} `); const fullValue = commonPrefix ? commonPrefix + Query.PREFIX_DELIMETER + combinedQuery : combinedQuery; return new Query(fullValue, commonPrefix); diff --git a/projects/netgrif-components-core/src/lib/search/operator-service/operator-resolver.service.ts b/projects/netgrif-components-core/src/lib/search/operator-service/operator-resolver.service.ts index d58e4934aa..eeeb5651f7 100644 --- a/projects/netgrif-components-core/src/lib/search/operator-service/operator-resolver.service.ts +++ b/projects/netgrif-components-core/src/lib/search/operator-service/operator-resolver.service.ts @@ -55,8 +55,8 @@ export class OperatorResolverService { return InRangeDate; case Operators.IN_RANGE_DATE_TIME: return InRangeDateTime; - // case Operators.IS_NULL: todo 2466 - // return IsNull; + case Operators.IS_NULL: + return IsNull; case Operators.LESS_THAN: return LessThan; case Operators.LESS_THAN_DATE: From 8acab54058c15b6f468abeb2362d89fcd729e0f4 Mon Sep 17 00:00:00 2001 From: chvostek Date: Tue, 21 Jul 2026 15:12:09 +0200 Subject: [PATCH 06/55] [NAE-2466] Advanced search for PFQL - remove categories that are impossible to use with PFQL --- .../header/case-header/case-header.service.ts | 1 - .../lib/header/case-header/case-menta-enum.ts | 1 - .../abstract-case-panel.component.ts | 2 - .../category-resolver.service.ts | 8 -- .../default-categories-factories.ts | 5 +- .../default-search-categories.module.ts | 2 - .../header-search.service.ts | 2 - .../models/category/case/case-role.spec.ts | 136 ------------------ .../search/models/category/case/case-role.ts | 44 ------ .../category/case/case-visual-id.spec.ts | 80 ----------- .../models/category/case/case-visual-id.ts | 50 ------- .../lib/search/models/category/categories.ts | 3 - .../models/category/task/task-role.spec.ts | 136 ------------------ .../search/models/category/task/task-role.ts | 43 ------ .../src/lib/search/public-api.ts | 3 - .../case-view/service/case-view-service.ts | 2 - 16 files changed, 1 insertion(+), 517 deletions(-) delete mode 100644 projects/netgrif-components-core/src/lib/search/models/category/case/case-role.spec.ts delete mode 100644 projects/netgrif-components-core/src/lib/search/models/category/case/case-role.ts delete mode 100644 projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.spec.ts delete mode 100644 projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.ts delete mode 100644 projects/netgrif-components-core/src/lib/search/models/category/task/task-role.spec.ts delete mode 100644 projects/netgrif-components-core/src/lib/search/models/category/task/task-role.ts diff --git a/projects/netgrif-components-core/src/lib/header/case-header/case-header.service.ts b/projects/netgrif-components-core/src/lib/header/case-header/case-header.service.ts index 440d88cab6..c51ec454a9 100644 --- a/projects/netgrif-components-core/src/lib/header/case-header/case-header.service.ts +++ b/projects/netgrif-components-core/src/lib/header/case-header/case-header.service.ts @@ -37,7 +37,6 @@ export class CaseHeaderService extends AbstractHeaderService implements OnDestro protected createMetaHeaders(): Array { return [ - new HeaderColumn(HeaderColumnType.META, CaseMetaField.VISUAL_ID, 'headers.caseMeta.visualID', 'text'), new HeaderColumn(HeaderColumnType.META, CaseMetaField.MONGO_ID, 'headers.caseMeta.mongoID', 'text', false), new HeaderColumn(HeaderColumnType.META, CaseMetaField.TITLE, 'headers.caseMeta.title', 'text'), new HeaderColumn(HeaderColumnType.META, CaseMetaField.AUTHOR, 'headers.caseMeta.author', 'user'), diff --git a/projects/netgrif-components-core/src/lib/header/case-header/case-menta-enum.ts b/projects/netgrif-components-core/src/lib/header/case-header/case-menta-enum.ts index 8f09e1b6ea..b3e23a25ba 100644 --- a/projects/netgrif-components-core/src/lib/header/case-header/case-menta-enum.ts +++ b/projects/netgrif-components-core/src/lib/header/case-header/case-menta-enum.ts @@ -1,6 +1,5 @@ export enum CaseMetaField { MONGO_ID = 'mongoId', - VISUAL_ID = 'visualId', TITLE = 'title', AUTHOR = 'author', CREATION_DATE = 'creationDate', diff --git a/projects/netgrif-components-core/src/lib/panel/case-panel/abstract-case-panel.component.ts b/projects/netgrif-components-core/src/lib/panel/case-panel/abstract-case-panel.component.ts index 13345e9306..33d3fdd898 100644 --- a/projects/netgrif-components-core/src/lib/panel/case-panel/abstract-case-panel.component.ts +++ b/projects/netgrif-components-core/src/lib/panel/case-panel/abstract-case-panel.component.ts @@ -65,8 +65,6 @@ export abstract class AbstractCasePanelComponent extends AbstractPanelWithImmedi switch (selectedHeader.fieldIdentifier) { case CaseMetaField.MONGO_ID: return {value: this.case_.stringId, icon: undefined, type: 'meta'}; - case CaseMetaField.VISUAL_ID: - return {value: this.case_.visualId, icon: undefined, type: 'meta'}; case CaseMetaField.TITLE: return {value: this.case_.title, icon: undefined, type: 'meta'}; case CaseMetaField.AUTHOR: diff --git a/projects/netgrif-components-core/src/lib/search/category-factory/category-resolver.service.ts b/projects/netgrif-components-core/src/lib/search/category-factory/category-resolver.service.ts index 533ae48a52..47ded37f3a 100644 --- a/projects/netgrif-components-core/src/lib/search/category-factory/category-resolver.service.ts +++ b/projects/netgrif-components-core/src/lib/search/category-factory/category-resolver.service.ts @@ -5,13 +5,11 @@ import {CaseAuthor} from '../models/category/case/case-author'; import {CaseCreationDate} from '../models/category/case/case-creation-date'; import {CaseDataset} from '../models/category/case/case-dataset'; import {CaseProcess} from '../models/category/case/case-process'; -import {CaseRole} from '../models/category/case/case-role'; import {CaseSimpleDataset} from '../models/category/case/case-simple-dataset'; import {CaseTitle} from '../models/category/case/case-title'; import {CaseStringId} from '../models/category/case/case-string-id'; import {TaskAssignee} from '../models/category/task/task-assignee'; import {TaskProcess} from '../models/category/task/task-process'; -import {TaskRole} from '../models/category/task/task-role'; import {TaskTask} from '../models/category/task/task-task'; import {CaseCreationDateTime} from '../models/category/case/case-creation-date-time'; import {CategorySerialisationPair} from './category-serialisation-pair'; @@ -54,9 +52,6 @@ export class CategoryResolverService { }, { classReference: CaseProcess, serialized: Categories.CASE_PROCESS - }, { - classReference: CaseRole, - serialized: Categories.CASE_ROLE }, { classReference: CaseSimpleDataset, serialized: Categories.CASE_SIMPLE_DATASET @@ -74,9 +69,6 @@ export class CategoryResolverService { }, { classReference: TaskProcess, serialized: Categories.TASK_PROCESS - }, { - classReference: TaskRole, - serialized: Categories.TASK_ROLE }, { classReference: TaskTask, serialized: Categories.TASK_TASK diff --git a/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.ts b/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.ts index 8a382433dc..2a58ede08f 100644 --- a/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.ts +++ b/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.ts @@ -8,7 +8,6 @@ import {CaseCreationDate} from '../models/category/case/case-creation-date'; import {CaseDataset} from '../models/category/case/case-dataset'; import {TaskAssignee} from '../models/category/task/task-assignee'; import {TaskProcess} from '../models/category/task/task-process'; -import {TaskRole} from '../models/category/task/task-role'; import {TaskTask} from '../models/category/task/task-task'; import {CaseCreationDateTime} from '../models/category/case/case-creation-date-time'; @@ -49,8 +48,7 @@ export function defaultCaseSearchCategoriesFactory(factory: CategoryFactory): Ar * caused by uncompleted Subjects. They should only be used to create new Category instances with the help of the * [duplicate()]{@link Category#duplicate} method. * - * @returns an Array containing the default task search categories: {@link TaskAssignee}, {@link TaskTask}, {@link TaskProcess} - * and {@link TaskRole} + * @returns an Array containing the default task search categories: {@link TaskAssignee}, {@link TaskTask} and {@link TaskProcess} * * @deprecated in 5.6.0 - Use the {@link NAE_DEFAULT_TASK_SEARCH_CATEGORIES} injection token instead */ @@ -59,7 +57,6 @@ export function defaultTaskSearchCategoriesFactory(factory: CategoryFactory): Ar factory.get(TaskAssignee), factory.get(TaskTask), factory.get(TaskProcess), - factory.get(TaskRole), ]; cats.forEach(cat => cat.destroy()); return cats; diff --git a/projects/netgrif-components-core/src/lib/search/category-factory/default-search-categories.module.ts b/projects/netgrif-components-core/src/lib/search/category-factory/default-search-categories.module.ts index 5d408be1f0..d27a5c0630 100644 --- a/projects/netgrif-components-core/src/lib/search/category-factory/default-search-categories.module.ts +++ b/projects/netgrif-components-core/src/lib/search/category-factory/default-search-categories.module.ts @@ -8,7 +8,6 @@ import {CaseAuthor} from '../models/category/case/case-author'; import {TaskAssignee} from '../models/category/task/task-assignee'; import {TaskTask} from '../models/category/task/task-task'; import {TaskProcess} from '../models/category/task/task-process'; -import {TaskRole} from '../models/category/task/task-role'; import {CaseCreationDateTime} from '../models/category/case/case-creation-date-time'; import {CaseStringId} from '../models/category/case/case-string-id'; @@ -34,7 +33,6 @@ import {CaseStringId} from '../models/category/case/case-string-id'; TaskAssignee, TaskTask, TaskProcess, - TaskRole, ] } ] diff --git a/projects/netgrif-components-core/src/lib/search/header-search-service/header-search.service.ts b/projects/netgrif-components-core/src/lib/search/header-search-service/header-search.service.ts index fe97d37983..b26d552a74 100644 --- a/projects/netgrif-components-core/src/lib/search/header-search-service/header-search.service.ts +++ b/projects/netgrif-components-core/src/lib/search/header-search-service/header-search.service.ts @@ -10,7 +10,6 @@ import {SearchChangeDescription} from '../../header/models/user-changes/search-c import {HeaderColumnType} from '../../header/models/header-column'; import {CaseMetaField} from '../../header/case-header/case-menta-enum'; import {CategoryFactory} from '../category-factory/category-factory'; -import {CaseVisualId} from '../models/category/case/case-visual-id'; import {Category} from '../models/category/category'; import {CaseAuthor} from '../models/category/case/case-author'; import {CaseCreationDate} from '../models/category/case/case-creation-date'; @@ -73,7 +72,6 @@ export class HeaderSearchService implements OnDestroy { this._columnToConfiguration = new Map(); this._typeToCategory = new Map>(); [ - {k: CaseMetaField.VISUAL_ID, v: CaseVisualId}, {k: CaseMetaField.TITLE, v: CaseTitle}, {k: CaseMetaField.CREATION_DATE, v: CaseCreationDate}, {k: CaseMetaField.AUTHOR, v: CaseAuthor}, diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-role.spec.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-role.spec.ts deleted file mode 100644 index d5645b3da6..0000000000 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-role.spec.ts +++ /dev/null @@ -1,136 +0,0 @@ -import {CaseRole} from './case-role'; -import {OperatorService} from '../../../operator-service/operator.service'; -import {createMockDependencies} from '../../../../utility/tests/search-category-mock-dependencies'; -import {TestBed, waitForAsync} from '@angular/core/testing'; -import {ReplaySubject} from 'rxjs'; -import {OperatorResolverService} from '../../../operator-service/operator-resolver.service'; -import {Net} from '../../../../process/net'; -import {createMockNet} from '../../../../utility/tests/utility/create-mock-net'; -import {configureCategory} from '../../../../utility/tests/utility/configure-category'; -import {Equals} from '../../operator/equals'; -import {Categories} from '../categories'; -import {Operators} from '../../operator/operators'; -import {filter, take} from 'rxjs/operators'; - -describe('CaseRole', () => { - let operatorService: OperatorService; - let category: CaseRole; - let allowedNets$: ReplaySubject>; - - beforeAll(() => { - operatorService = new OperatorService(new OperatorResolverService()); - }); - - beforeEach(waitForAsync(async () => { - allowedNets$ = new ReplaySubject>(1); - category = await new CaseRole(operatorService, null, createMockDependencies(allowedNets$, operatorService)); - })); - - afterEach(() => { - allowedNets$.complete(); - category.destroy(); - TestBed.resetTestingModule(); - }); - - it('should create an instance', () => { - allowedNets$.next([]); - expect(category).toBeTruthy(); - }); - - it('should select default operator', () => { - allowedNets$.next([]); - expect(category.isOperatorSelected()).toBeFalse(); - category.selectDefaultOperator(); - expect(category.isOperatorSelected()).toBeTrue(); - }); - - it('should generate options with unique names only', () => { - allowedNets$.next([ - createMockNet('', 'A', 'A', [{name: 'role1', stringId: 'sid1'}, {name: 'role2', stringId: 'sid2'}]), - createMockNet('', 'B', 'B', [{name: 'role2', stringId: 'sid3'}]), - ]); - category.selectDefaultOperator(); - - const options = category.options; - expect(options).toBeTruthy(); - expect(Array.isArray(options)).toBeTrue(); - expect(options.length).toBe(2); - - const option1 = options.find(o => o.text === 'role1'); - const option2 = options.find(o => o.text === 'role2'); - - expect(option1).toBeTruthy(); - expect(option1.value).toBeTruthy(); - expect(Array.isArray(option1.value)).toBeTrue(); - expect(option1.value.length).toBe(1); - expect(option1.value[0].attributeId).toBe('sid1'); - - expect(option2).toBeTruthy(); - expect(option2.value).toBeTruthy(); - expect(Array.isArray(option2.value)).toBeTrue(); - expect(option2.value.length).toBe(2); - expect(option2.value.some(o => o.attributeId === 'sid2')).toBeTrue(); - expect(option2.value.some(o => o.attributeId === 'sid3')).toBeTrue(); - }); - - it('should not serialize incomplete instance', () => { - allowedNets$.next([]); - expect(category.createMetadata()).toBeUndefined(); - }); - - it('should serialize complete instance', () => { - allowedNets$.next([ - createMockNet('', 'A', 'A', [{name: 'role1', stringId: 'sid1'}]), - createMockNet('', 'B', 'B', [{name: 'role1', stringId: 'sid2'}]), - ]); - - const options = category.options; - expect(options.length).toBe(1); - const option = options[0]; - expect(option.text).toBe('role1'); - - configureCategory(category, operatorService, Equals, [option]); - - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - expect(metadata.values).toEqual([option.text]); - expect(metadata.category).toBe(Categories.CASE_ROLE); - expect(metadata.configuration?.operator).toBe(Operators.EQUALS); - }); - - it('should deserialize stored instance', (done) => { - allowedNets$.next([ - createMockNet('', 'A', 'A', [{name: 'role1', stringId: 'sid1'}]), - createMockNet('', 'B', 'B', [{name: 'role1', stringId: 'sid2'}]), - ]); - - const options = category.options; - expect(options.length).toBe(1); - const option = options[0]; - expect(option.text).toBe('role1'); - - configureCategory(category, operatorService, Equals, [option]); - - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - const deserialized = new CaseRole(operatorService, null, createMockDependencies(allowedNets$, operatorService)); - - // wait for autocomplete options to initialize - deserialized.options$.pipe(filter(o => o.length > 0), take(1)).subscribe(() => { - deserialized.loadFromMetadata(metadata).subscribe(() => { - expect(deserialized.isOperatorSelected()).toBeTrue(); - expect(deserialized.providesPredicate).toBeTrue(); - - expect((deserialized as any)._operandsFormControls[0].value).toEqual((category as any)._operandsFormControls[0].value); - - const deserializedMetadata = deserialized.createMetadata(); - expect(deserializedMetadata).toBeTruthy(); - expect(deserializedMetadata.configuration).toEqual(metadata.configuration); - expect(deserializedMetadata.category).toEqual(metadata.category); - expect(deserializedMetadata.values).toEqual(metadata.values); - - done(); - }); - }); - }); -}); diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-role.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-role.ts deleted file mode 100644 index a0beec5d84..0000000000 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-role.ts +++ /dev/null @@ -1,44 +0,0 @@ -import {OperatorService} from '../../../operator-service/operator.service'; -import {LoggerService} from '../../../../logger/services/logger.service'; -import {Equals} from '../../operator/equals'; -import {OptionalDependencies} from '../../../category-factory/optional-dependencies'; -import {NotEquals} from '../../operator/not-equals'; -import {Net} from '../../../../process/net'; -import {NameIdPair} from '../name-id-pair'; -import {CaseNetAttributeAutocompleteCategory} from './case-net-attribute-autocomplete-category'; -import {Categories} from '../categories'; -import {CaseSearch} from './case-search.enum'; -import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; - -export class CaseRole extends CaseNetAttributeAutocompleteCategory { - - // todo 2466 impossible in pfql - prec - - private static readonly _i18n = 'search.category.case.role'; - - constructor(operators: OperatorService, logger: LoggerService, optionalDependencies: OptionalDependencies) { - super([CaseSearch.ENABLED_ROLES], - [operators.getOperator(Equals), operators.getOperator(NotEquals)], - `${CaseRole._i18n}.name`, - logger, - operators, - optionalDependencies, - ResourceTypeQueryPrefix.CASES); - } - - protected extractAttributes(petriNet: Net): Array { - return petriNet.roles.map(r => ({id: r.stringId, name: r.name})); - } - - get inputPlaceholder(): string { - return `${CaseRole._i18n}.placeholder`; - } - - duplicate(): CaseRole { - return new CaseRole(this._operatorService, this._log, this._optionalDependencies); - } - - serializeClass(): Categories | string { - return Categories.CASE_ROLE; - } -} diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.spec.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.spec.ts deleted file mode 100644 index 837e9b5fdb..0000000000 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.spec.ts +++ /dev/null @@ -1,80 +0,0 @@ -import {CaseVisualId} from './case-visual-id'; -import {OperatorService} from '../../../operator-service/operator.service'; -import {OperatorResolverService} from '../../../operator-service/operator-resolver.service'; -import {configureCategory} from '../../../../utility/tests/utility/configure-category'; -import {Equals} from '../../operator/equals'; -import {Operators} from '../../operator/operators'; -import {TestBed} from '@angular/core/testing'; -import {Substring} from '../../operator/substring'; -import {SearchIndexResolverService} from '../../../search-keyword-resolver-service/search-index-resolver.service'; -import {CaseSearch} from './case-search.enum'; -import {OptionalDependencies} from '../../../category-factory/optional-dependencies'; - -describe('CaseVisualId', () => { - let category: CaseVisualId; - let operatorService: OperatorService; - let deps: OptionalDependencies; - - beforeEach(() => { - operatorService = new OperatorService(new OperatorResolverService()); - deps = {searchIndexResolver: new SearchIndexResolverService()} as OptionalDependencies; - category = new CaseVisualId(operatorService, null, deps); - }); - - afterEach(() => { - category.destroy(); - TestBed.resetTestingModule(); - }); - - it('should create an instance', () => { - expect(category).toBeTruthy(); - }); - - it('should select default operator', () => { - expect(category.isOperatorSelected()).toBeFalse(); - category.selectDefaultOperator(); - expect(category.isOperatorSelected()).toBeTrue(); - }); - - it('should not serialize incomplete instance', () => { - expect(category.createMetadata()).toBeUndefined(); - }); - - it('should serialize complete instance', () => { - configureCategory(category, operatorService, Equals, ['foo']); - - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - expect(metadata.values).toEqual(['foo']); - expect(metadata.category).toBe("visualId"); - expect(metadata.configuration?.operator).toBe(Operators.EQUALS); - }); - - it('should deserialize stored instance', (done) => { - configureCategory(category, operatorService, Equals, ['foo']); - - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - const deserialized = new CaseVisualId(operatorService, null); - deserialized.loadFromMetadata(metadata).subscribe(() => { - expect(deserialized.isOperatorSelected()).toBeTrue(); - expect(deserialized.providesPredicate).toBeTrue(); - - expect((deserialized as any)._operandsFormControls[0].value).toEqual((category as any)._operandsFormControls[0].value); - - const deserializedMetadata = deserialized.createMetadata(); - expect(deserializedMetadata).toBeTruthy(); - expect(deserializedMetadata.configuration).toEqual(metadata.configuration); - expect(deserializedMetadata.category).toEqual(metadata.category); - expect(deserializedMetadata.values).toEqual(metadata.values); - - done(); - }); - }); - - it('should use keyword index', () => { - configureCategory(category, operatorService, Substring, ['foo']); - const predicate = category.generatePredicate(['input']); - expect(predicate.query.value.includes(`${CaseSearch.VISUAL_ID}${deps.searchIndexResolver.KEYWORD}`)).toBeTrue(); - }); -}); diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.ts deleted file mode 100644 index a5ed12c230..0000000000 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-visual-id.ts +++ /dev/null @@ -1,50 +0,0 @@ -import {OperatorService} from '../../../operator-service/operator.service'; -import {LoggerService} from '../../../../logger/services/logger.service'; -import {Substring} from '../../operator/substring'; -import {SearchInputType} from '../search-input-type'; -import {NoConfigurationCategory} from '../no-configuration-category'; -import {Equals} from '../../operator/equals'; -import {NotEquals} from '../../operator/not-equals'; -import {Categories} from '../categories'; -import {CaseSearch} from './case-search.enum'; -import {OptionalDependencies} from '../../../category-factory/optional-dependencies'; -import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; - -export class CaseVisualId extends NoConfigurationCategory { - - // todo 2466 impossible in pfql - prec - - private static readonly _i18n = 'search.category.case.visualId'; - - constructor(operators: OperatorService, logger: LoggerService, protected _optionalDependencies?: OptionalDependencies) { - super([CaseSearch.VISUAL_ID], - [operators.getOperator(Substring), operators.getOperator(Equals), operators.getOperator(NotEquals)], - `${CaseVisualId._i18n}.name`, - SearchInputType.TEXT, - logger, - operators, - ResourceTypeQueryPrefix.CASES); - } - - get inputPlaceholder(): string { - return `${CaseVisualId._i18n}.placeholder`; - } - - duplicate(): CaseVisualId { - return new CaseVisualId(this._operatorService, this._log, this._optionalDependencies); - } - - serializeClass(): Categories | string { - return "visualId"; - // return Categories.CASE_VISUAL_ID; todo 2466 - } - - protected get pfqlKeywords(): Array { - if (!!this._optionalDependencies) { - const resolver = this._optionalDependencies.searchIndexResolver; - return [resolver.getCoreIndex(CaseSearch.VISUAL_ID, this.isSelectedOperator(Substring))]; - } else { - return this._pfqlKeywords; - } - } -} diff --git a/projects/netgrif-components-core/src/lib/search/models/category/categories.ts b/projects/netgrif-components-core/src/lib/search/models/category/categories.ts index 4ddb75890d..350e21f6ba 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/categories.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/categories.ts @@ -8,15 +8,12 @@ export enum Categories { CASE_CREATION_DATE_TIME = 'case_creation_date_time', CASE_DATASET = 'case_dataset', CASE_PROCESS = 'case_process', - CASE_ROLE = 'case_role', CASE_SIMPLE_DATASET = 'case_simple_dataset', CASE_TITLE = 'case_title', - // CASE_VISUAL_ID = 'case_visual_id', // todo 2466 CASE_STRING_ID = 'case_string_id', // Task categories TASK_ASSIGNEE = 'task_assignee', TASK_PROCESS = 'task_process', - TASK_ROLE = 'task_role', TASK_TASK = 'task_task', } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-role.spec.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-role.spec.ts deleted file mode 100644 index 01a692c5d6..0000000000 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-role.spec.ts +++ /dev/null @@ -1,136 +0,0 @@ -import {TaskRole} from './task-role'; -import {OperatorService} from '../../../operator-service/operator.service'; -import {createMockDependencies} from '../../../../utility/tests/search-category-mock-dependencies'; -import {TestBed, waitForAsync} from '@angular/core/testing'; -import {ReplaySubject} from 'rxjs'; -import {OperatorResolverService} from '../../../operator-service/operator-resolver.service'; -import {Net} from '../../../../process/net'; -import {createMockNet} from '../../../../utility/tests/utility/create-mock-net'; -import {configureCategory} from '../../../../utility/tests/utility/configure-category'; -import {Equals} from '../../operator/equals'; -import {Categories} from '../categories'; -import {Operators} from '../../operator/operators'; -import {filter, take} from 'rxjs/operators'; - -describe('TaskRole', () => { - let operatorService: OperatorService; - let category: TaskRole; - let allowedNets$: ReplaySubject>; - - beforeAll(() => { - operatorService = new OperatorService(new OperatorResolverService()); - }); - - beforeEach(waitForAsync(async () => { - allowedNets$ = new ReplaySubject>(1); - category = await new TaskRole(operatorService, null, createMockDependencies(allowedNets$, operatorService)); - })); - - afterEach(() => { - allowedNets$.complete(); - category.destroy(); - TestBed.resetTestingModule(); - }); - - it('should create an instance', () => { - allowedNets$.next([]); - expect(category).toBeTruthy(); - }); - - it('should select default operator', () => { - allowedNets$.next([]); - expect(category.isOperatorSelected()).toBeFalse(); - category.selectDefaultOperator(); - expect(category.isOperatorSelected()).toBeTrue(); - }); - - it('should generate options with unique names only', () => { - allowedNets$.next([ - createMockNet('', 'A', 'A', [{name: 'role1', stringId: 'sid1'}, {name: 'role2', stringId: 'sid2'}]), - createMockNet('', 'B', 'B', [{name: 'role2', stringId: 'sid3'}]), - ]); - category.selectDefaultOperator(); - - const options = category.options; - expect(options).toBeTruthy(); - expect(Array.isArray(options)).toBeTrue(); - expect(options.length).toBe(2); - - const option1 = options.find(o => o.text === 'role1'); - const option2 = options.find(o => o.text === 'role2'); - - expect(option1).toBeTruthy(); - expect(option1.value).toBeTruthy(); - expect(Array.isArray(option1.value)).toBeTrue(); - expect(option1.value.length).toBe(1); - expect(option1.value[0].attributeId).toBe('sid1'); - - expect(option2).toBeTruthy(); - expect(option2.value).toBeTruthy(); - expect(Array.isArray(option2.value)).toBeTrue(); - expect(option2.value.length).toBe(2); - expect(option2.value.some(o => o.attributeId === 'sid2')).toBeTrue(); - expect(option2.value.some(o => o.attributeId === 'sid3')).toBeTrue(); - }); - - it('should not serialize incomplete instance', () => { - allowedNets$.next([]); - expect(category.createMetadata()).toBeUndefined(); - }); - - it('should serialize complete instance', () => { - allowedNets$.next([ - createMockNet('', 'A', 'A', [{name: 'role1', stringId: 'sid1'}]), - createMockNet('', 'B', 'B', [{name: 'role1', stringId: 'sid2'}]), - ]); - - const options = category.options; - expect(options.length).toBe(1); - const option = options[0]; - expect(option.text).toBe('role1'); - - configureCategory(category, operatorService, Equals, [option]); - - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - expect(metadata.values).toEqual([option.text]); - expect(metadata.category).toBe(Categories.TASK_ROLE); - expect(metadata.configuration?.operator).toBe(Operators.EQUALS); - }); - - it('should deserialize stored instance', (done) => { - allowedNets$.next([ - createMockNet('', 'A', 'A', [{name: 'role1', stringId: 'sid1'}]), - createMockNet('', 'B', 'B', [{name: 'role1', stringId: 'sid2'}]), - ]); - - const options = category.options; - expect(options.length).toBe(1); - const option = options[0]; - expect(option.text).toBe('role1'); - - configureCategory(category, operatorService, Equals, [option]); - - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - const deserialized = new TaskRole(operatorService, null, createMockDependencies(allowedNets$, operatorService)); - - // wait for autocomplete options to initialize - deserialized.options$.pipe(filter(o => o.length > 0), take(1)).subscribe(() => { - deserialized.loadFromMetadata(metadata).subscribe(() => { - expect(deserialized.isOperatorSelected()).toBeTrue(); - expect(deserialized.providesPredicate).toBeTrue(); - - expect((deserialized as any)._operandsFormControls[0].value).toEqual((category as any)._operandsFormControls[0].value); - - const deserializedMetadata = deserialized.createMetadata(); - expect(deserializedMetadata).toBeTruthy(); - expect(deserializedMetadata.configuration).toEqual(metadata.configuration); - expect(deserializedMetadata.category).toEqual(metadata.category); - expect(deserializedMetadata.values).toEqual(metadata.values); - - done(); - }); - }); - }); -}); diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-role.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-role.ts deleted file mode 100644 index bd2ffe33e4..0000000000 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-role.ts +++ /dev/null @@ -1,43 +0,0 @@ -import {OperatorService} from '../../../operator-service/operator.service'; -import {LoggerService} from '../../../../logger/services/logger.service'; -import {OptionalDependencies} from '../../../category-factory/optional-dependencies'; -import {Equals} from '../../operator/equals'; -import {NotEquals} from '../../operator/not-equals'; -import {TaskNetAttributeAutocompleteCategory} from './task-net-attribute-autocomplete-category'; -import {Net} from '../../../../process/net'; -import {NameIdPair} from '../name-id-pair'; -import {Categories} from '../categories'; -import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; - -export class TaskRole extends TaskNetAttributeAutocompleteCategory { - - // todo 2466 impossible in pfql - prec - - private static readonly _i18n = 'search.category.task.role'; - - constructor(operators: OperatorService, logger: LoggerService, optionalDependencies: OptionalDependencies) { - super(['roles'], - [operators.getOperator(Equals), operators.getOperator(NotEquals)], - `${TaskRole._i18n}.name`, - logger, - operators, - optionalDependencies, - ResourceTypeQueryPrefix.TASKS); - } - - protected extractAttributes(petriNet: Net): Array { - return petriNet.roles.map(r => ({id: r.stringId, name: r.name})); - } - - get inputPlaceholder(): string { - return `${TaskRole._i18n}.placeholder`; - } - - duplicate(): TaskRole { - return new TaskRole(this._operatorService, this._log, this._optionalDependencies); - } - - serializeClass(): Categories | string { - return Categories.TASK_ROLE; - } -} diff --git a/projects/netgrif-components-core/src/lib/search/public-api.ts b/projects/netgrif-components-core/src/lib/search/public-api.ts index 632c06957e..6505845071 100644 --- a/projects/netgrif-components-core/src/lib/search/public-api.ts +++ b/projects/netgrif-components-core/src/lib/search/public-api.ts @@ -38,10 +38,8 @@ export * from './models/category/no-configuration-user-autocomplete-category'; export * from './models/category/net-attribute-autocomplete-category'; export * from './models/category/case/case-net-attribute-autocomplete-category'; export * from './models/category/case/case-title'; -export * from './models/category/case/case-visual-id'; export * from './models/category/case/case-author'; export * from './models/category/case/case-process'; -export * from './models/category/case/case-role'; export * from './models/category/case/case-creation-date'; export * from './models/category/case/case-creation-date-time'; export * from './models/category/case/case-dataset'; @@ -50,7 +48,6 @@ export * from './models/category/case/case-string-id'; export * from './models/category/task/task-net-attribute-autocomplete-category'; export * from './models/category/task/task-assignee'; export * from './models/category/task/task-process'; -export * from './models/category/task/task-role'; export * from './models/category/task/task-task'; export * from './models/category/resource-type-query-prefix'; diff --git a/projects/netgrif-components-core/src/lib/view/case-view/service/case-view-service.ts b/projects/netgrif-components-core/src/lib/view/case-view/service/case-view-service.ts index ac84fcfc6e..e5f43673db 100644 --- a/projects/netgrif-components-core/src/lib/view/case-view/service/case-view-service.ts +++ b/projects/netgrif-components-core/src/lib/view/case-view/service/case-view-service.ts @@ -327,8 +327,6 @@ export class CaseViewService extends AbstractSortableViewComponent implements On switch (this._lastHeaderSearchState.fieldIdentifier) { case CaseMetaField.TITLE: return 'title.keyword'; - case CaseMetaField.VISUAL_ID: - return 'visualId.keyword'; case CaseMetaField.CREATION_DATE: return 'creationDateSortable'; default: From 1928727442efe6e3a06f4da48912f18b41276b8e Mon Sep 17 00:00:00 2001 From: chvostek Date: Wed, 22 Jul 2026 08:21:00 +0200 Subject: [PATCH 07/55] [NAE-2466] Advanced search for PFQL - update like operator to work with PFQL --- .../search/models/category/case/case-dataset.ts | 5 +++-- .../lib/search/models/category/case/case-title.ts | 2 +- .../src/lib/search/models/operator/like.ts | 14 +++++--------- .../src/lib/search/models/operator/operators.ts | 2 +- .../operator-service/operator-resolver.service.ts | 4 ++-- .../panel/case-panel/case-panel.component.spec.ts | 1 - 6 files changed, 12 insertions(+), 16 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts index 6404c1ca7e..aaf949b963 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts @@ -16,6 +16,7 @@ import { BehaviorSubject, Observable, of, ReplaySubject, Subscription } from 'rx import { Category } from '../category'; import { NotEquals } from '../../operator/not-equals'; import { IsNull } from '../../operator/is-null'; +import { Like } from '../../operator/like'; import { MoreThan } from '../../operator/more-than'; import { LessThan } from '../../operator/less-than'; import { InRange } from '../../operator/in-range'; @@ -213,8 +214,8 @@ export class CaseDataset extends Category implements AutocompleteOpti this._operatorService.getOperator(MoreThanEqual), this._operatorService.getOperator(LessThan), this._operatorService.getOperator(LessThanEqual), - this._operatorService.getOperator(IsNull) - // this._operatorService.getOperator(Like) todo 2466 + this._operatorService.getOperator(IsNull), + this._operatorService.getOperator(Like) ]; } } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.ts index 4ddeb4c734..731cfcd69e 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.ts @@ -29,7 +29,7 @@ export class CaseTitle extends NoConfigurationCategory { operators.getOperator(MoreThanEqual), operators.getOperator(LessThan), operators.getOperator(LessThanEqual), - // operators.getOperator(Like) todo 2466 impossible in PFQL + operators.getOperator(Like) ], `${CaseTitle._i18n}.name`, SearchInputType.TEXT, diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/like.ts b/projects/netgrif-components-core/src/lib/search/models/operator/like.ts index dc9a4fbeba..1f1eab7cec 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/like.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/like.ts @@ -8,20 +8,17 @@ import {Operators} from './operators'; * Behaves differently for strings with spaces and without. * With spaces searches for matches containing the tokenized strings. * Without spaces searches for strings within the default edit distance. - * See [docs]{@link https://www.elastic.co/guide/en/elasticsearch/reference/6.6/query-dsl-query-string-query.html#_fuzziness} - * for more information. */ export class Like extends Operator { - // todo 2466 impossible in PFQL constructor() { super(1); } - createQuery(elasticKeywords: Array, args: Array): Query { + createQuery(pfqlKeywords: Array, args: Array): Query { this.checkArgumentsCount(args); - const escaped = Operator.escapeInput(args[0]); - return Operator.forEachKeyword(elasticKeywords, - keyword => escaped.wasEscaped ? new Query(`(${keyword}:${escaped.value})`) : new Query(`(${keyword}:${escaped.value}~)`)); + const escaped = Operator.escapeInput(args[0]); // todo 2466 escape? + return Operator.forEachKeyword(pfqlKeywords, + keyword => escaped.wasEscaped ? new Query(`${keyword} eq '${escaped.value}'`) : new Query(`${keyword} eq '${escaped.value}'*`)); } getOperatorNameTemplate(): Array { @@ -29,7 +26,6 @@ export class Like extends Operator { } serialize(): Operators | string { - return 'like'; - // return Operators.LIKE; + return Operators.LIKE; } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/operators.ts b/projects/netgrif-components-core/src/lib/search/models/operator/operators.ts index 2ba84974b6..1cb391d51d 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/operators.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/operators.ts @@ -15,7 +15,7 @@ export enum Operators { LESS_THAN_EQUAL = 'less_than_equal', LESS_THAN_EQUAL_DATE = 'less_than_equal_date', LESS_THAN_EQUAL_DATE_TIME = 'less_than_equal_date_time', - // LIKE = 'like', todo 2466 + LIKE = 'like', MORE_THAN = 'more_than', MORE_THAN_DATE = 'more_than_date', MORE_THAN_DATE_TIME = 'more_than_date_time', diff --git a/projects/netgrif-components-core/src/lib/search/operator-service/operator-resolver.service.ts b/projects/netgrif-components-core/src/lib/search/operator-service/operator-resolver.service.ts index eeeb5651f7..a4ceb2f5d5 100644 --- a/projects/netgrif-components-core/src/lib/search/operator-service/operator-resolver.service.ts +++ b/projects/netgrif-components-core/src/lib/search/operator-service/operator-resolver.service.ts @@ -69,8 +69,8 @@ export class OperatorResolverService { return LessThanEqualDate; case Operators.LESS_THAN_EQUAL_DATE_TIME: return LessThanEqualDateTime; - // case Operators.LIKE: todo 2466 - // return Like; + case Operators.LIKE: + return Like; case Operators.MORE_THAN: return MoreThan; case Operators.MORE_THAN_DATE: diff --git a/projects/netgrif-components/src/lib/panel/case-panel/case-panel.component.spec.ts b/projects/netgrif-components/src/lib/panel/case-panel/case-panel.component.spec.ts index 86047b8d68..0932dfd52a 100644 --- a/projects/netgrif-components/src/lib/panel/case-panel/case-panel.component.spec.ts +++ b/projects/netgrif-components/src/lib/panel/case-panel/case-panel.component.spec.ts @@ -83,7 +83,6 @@ describe('CasePanelComponent', () => { }) class TestWrapperComponent { selectedHeaders = of([ - new HeaderColumn(HeaderColumnType.META, CaseMetaField.VISUAL_ID, 'string', 'string'), new HeaderColumn(HeaderColumnType.META, CaseMetaField.AUTHOR, 'string', 'string'), new HeaderColumn(HeaderColumnType.META, CaseMetaField.TITLE, 'string', 'string'), new HeaderColumn(HeaderColumnType.IMMEDIATE, 'date', 'string', 'string', true, 'netid'), From f1cb773a43bb91a8109efa217389333232faa0da Mon Sep 17 00:00:00 2001 From: chvostek Date: Wed, 22 Jul 2026 08:33:38 +0200 Subject: [PATCH 08/55] [NAE-2466] Advanced search for PFQL - fix tests --- .../src/lib/header/case-header/case-header.service.spec.ts | 2 +- .../lib/panel/case-panel/abstract-case-panel.component.spec.ts | 1 - .../category-factory/default-categories-factories.spec.ts | 2 +- .../src/lib/search/search-service/search.service.spec.ts | 1 - 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/header/case-header/case-header.service.spec.ts b/projects/netgrif-components-core/src/lib/header/case-header/case-header.service.spec.ts index b8e33d4d18..93131c614d 100644 --- a/projects/netgrif-components-core/src/lib/header/case-header/case-header.service.spec.ts +++ b/projects/netgrif-components-core/src/lib/header/case-header/case-header.service.spec.ts @@ -105,7 +105,7 @@ describe('CaseHeaderService', () => { expect(res.changeType).toEqual(HeaderChangeType.SEARCH); expect((res.description as SearchChangeDescription).columnIdentifier).toEqual(0); expect((res.description as SearchChangeDescription).searchInput).toEqual('hladaj'); - expect((res.description as SearchChangeDescription).fieldIdentifier).toEqual('visualId'); + expect((res.description as SearchChangeDescription).fieldIdentifier).toEqual('title'); expect((res.description as SearchChangeDescription).type).toEqual(HeaderColumnType.META); expect((res.description as SearchChangeDescription).fieldType).toEqual('text'); done(); diff --git a/projects/netgrif-components-core/src/lib/panel/case-panel/abstract-case-panel.component.spec.ts b/projects/netgrif-components-core/src/lib/panel/case-panel/abstract-case-panel.component.spec.ts index f114b5b7bc..3e68a9d6e3 100644 --- a/projects/netgrif-components-core/src/lib/panel/case-panel/abstract-case-panel.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/panel/case-panel/abstract-case-panel.component.spec.ts @@ -125,7 +125,6 @@ class TestCasePanelComponent extends AbstractCasePanelComponent { }) class TestWrapperComponent { selectedHeaders = of([ - new HeaderColumn(HeaderColumnType.META, CaseMetaField.VISUAL_ID, 'string', 'string'), new HeaderColumn(HeaderColumnType.META, CaseMetaField.AUTHOR, 'string', 'string'), new HeaderColumn(HeaderColumnType.META, CaseMetaField.TITLE, 'string', 'string'), new HeaderColumn(HeaderColumnType.IMMEDIATE, 'date', 'string', 'string', true, 'netid'), diff --git a/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.spec.ts b/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.spec.ts index 3094616a14..27ff0c0be3 100644 --- a/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.spec.ts @@ -93,7 +93,7 @@ describe('Default search categories factory methods', () => { expect(testService).toBeTruthy(); expect(testService.searchCategories).toBeTruthy(); expect(Array.isArray(testService.searchCategories)).toBeTrue(); - expect(testService.searchCategories.length).toBe(4); + expect(testService.searchCategories.length).toBe(3); for (const category of testService.searchCategories) { expect(category).toBeTruthy(); } diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts index 08bafee062..f2c6b51801 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts @@ -12,7 +12,6 @@ import {AllowedNetsService} from '../../allowed-nets/services/allowed-nets.servi import {AllowedNetsServiceFactory} from '../../allowed-nets/services/factory/allowed-nets-service-factory'; import {CaseCreationDate} from '../models/category/case/case-creation-date'; import moment from 'moment'; -import {CaseVisualId} from '../models/category/case/case-visual-id'; import {CaseSearchRequestBody} from '../../filter/models/case-search-request-body'; import {FilterMetadata} from '../models/persistance/filter-metadata'; import {FilterType} from '../../filter/models/filter-type'; From 76d8cfd6e08aeb93fe682072373fe393e6e560c3 Mon Sep 17 00:00:00 2001 From: chvostek Date: Thu, 23 Jul 2026 11:52:11 +0200 Subject: [PATCH 09/55] [NAE-2466] Advanced search for PFQL - add antlr dependency and PFQL grammar --- package.json | 7 +- .../src/lib/pfql/QueryLang.g4 | 415 + .../src/lib/pfql/generated/QueryLang.interp | 256 + .../src/lib/pfql/generated/QueryLang.tokens | 80 + .../lib/pfql/generated/QueryLangLexer.interp | 260 + .../lib/pfql/generated/QueryLangLexer.tokens | 80 + .../src/lib/pfql/generated/QueryLangLexer.ts | 468 + .../src/lib/pfql/generated/QueryLangParser.ts | 12718 ++++++++++++++++ .../lib/pfql/generated/QueryLangVisitor.ts | 1357 ++ 9 files changed, 15639 insertions(+), 2 deletions(-) create mode 100644 projects/netgrif-components-core/src/lib/pfql/QueryLang.g4 create mode 100644 projects/netgrif-components-core/src/lib/pfql/generated/QueryLang.interp create mode 100644 projects/netgrif-components-core/src/lib/pfql/generated/QueryLang.tokens create mode 100644 projects/netgrif-components-core/src/lib/pfql/generated/QueryLangLexer.interp create mode 100644 projects/netgrif-components-core/src/lib/pfql/generated/QueryLangLexer.tokens create mode 100644 projects/netgrif-components-core/src/lib/pfql/generated/QueryLangLexer.ts create mode 100644 projects/netgrif-components-core/src/lib/pfql/generated/QueryLangParser.ts create mode 100644 projects/netgrif-components-core/src/lib/pfql/generated/QueryLangVisitor.ts diff --git a/package.json b/package.json index ec9b8b1e6a..2c0bcbddd8 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "lint": "ng lint", "e2e": "ng e2e", "ncc:clean": "node projects/netgrif-components-core/src/scripts/delete-local-build-link.js", - "ncc:build": "npm run ncc:clean && ng build netgrif-components-core --configuration production && npm run ncc:build-schematics", + "ncc:build": "npm run ncc:clean && ng build netgrif-components-core --configuration production && npm run ncc:build-schematics && npm run pfql:build-grammar", "ncc:local-build": "npm run ncc:build && npm i ./dist/netgrif-components-core --save-optional --legacy-peer-deps", "ncc:build-schematics": "node projects/netgrif-components-core/src/scripts/build-schematics.js", "ncc:lint": "ng lint netgrif-components-core", @@ -65,7 +65,8 @@ "project:sonar": "node scripts/sonar-scanner-analysis.js", "components:start": "npm run nc:local-build && ng serve", "example:start": "ng serve", - "example:build": "ng build nae-example-app --configuration production" + "example:build": "ng build nae-example-app --configuration production", + "pfql:build-grammar": "antlr-ng -Dlanguage=TypeScript -v true -l false -o projects/netgrif-components-core/src/lib/pfql/generated projects/netgrif-components-core/src/lib/pfql/QueryLang.g4" }, "dependencies": { "@angular-material-components/datetime-picker": "~16.0.1", @@ -98,6 +99,7 @@ "angular-resizable-element": "~7.0.0", "angular-resize-event": "~3.2.0", "angular2-hotkeys": "~16.0.0", + "antlr4ng": "^3.0.16", "easymde": "~2.16.1", "escape-string-regexp": "^4.0.0", "hammerjs": "~2.0.8", @@ -138,6 +140,7 @@ "@types/node": "~12.12.29", "@typescript-eslint/eslint-plugin": "~6.21.0", "@typescript-eslint/parser": "~6.21.0", + "antlr-ng": "^1.0.0", "commander": "~4.1.1", "cspell": "~5.18.4", "eslint": "~8.12.0", diff --git a/projects/netgrif-components-core/src/lib/pfql/QueryLang.g4 b/projects/netgrif-components-core/src/lib/pfql/QueryLang.g4 new file mode 100644 index 0000000000..f1b5d5533d --- /dev/null +++ b/projects/netgrif-components-core/src/lib/pfql/QueryLang.g4 @@ -0,0 +1,415 @@ +// todo generate this with plugin +grammar QueryLang; + +query: resource=(PROCESS | PROCESSES) processConditionsAndPaging? EOF # processQuery + | resource=(CASE | CASES) caseConditionsAndPaging? EOF # caseQuery + | resource=(TASK | TASKS) taskConditionsAndPaging? EOF # taskQuery + | resource=(USER | USERS) userConditionsAndPaging? EOF # userQuery + ; + +processConditionsAndPaging: delimeter processConditions? paging? processSorting?; +caseConditionsAndPaging: delimeter caseConditions? paging? caseSorting?; +taskConditionsAndPaging: delimeter taskConditions? paging? taskSorting?; +userConditionsAndPaging: delimeter userConditions? paging? userSorting?; + +processConditions: processOrExpression ; +processOrExpression: processAndExpression (SPACE OR SPACE processAndExpression)* ; +processAndExpression: processConditionGroup (SPACE AND SPACE processConditionGroup)* ; +processConditionGroup: processCondition # processConditionGroupBasic + | (NOT SPACE?)? '(' SPACE? processConditions SPACE? ')' SPACE? # processConditionGroupParenthesis + ; +processCondition: processComparisons SPACE? ; + +caseConditions: caseOrExpression ; +caseOrExpression: caseAndExpression (SPACE OR SPACE caseAndExpression)* ; +caseAndExpression: caseConditionGroup (SPACE AND SPACE caseConditionGroup)* ; +caseConditionGroup: caseCondition # caseConditionGroupBasic + | (NOT SPACE?)? '(' SPACE? caseConditions SPACE? ')' SPACE? # caseConditionGroupParenthesis + ; +caseCondition: caseComparisons SPACE? ; + +taskConditions: taskOrExpression ; +taskOrExpression: taskAndExpression (SPACE OR SPACE taskAndExpression)* ; +taskAndExpression: taskConditionGroup (SPACE AND SPACE taskConditionGroup)* ; +taskConditionGroup: taskCondition # taskConditionGroupBasic + | (NOT SPACE?)? '(' SPACE? taskConditions SPACE? ')' SPACE? # taskConditionGroupParenthesis + ; +taskCondition: taskComparisons SPACE? ; + +userConditions: userOrExpression ; +userOrExpression: userAndExpression (SPACE OR SPACE userAndExpression)* ; +userAndExpression: userConditionGroup (SPACE AND SPACE userConditionGroup)* ; +userConditionGroup: userCondition # userConditionGroupBasic + | (NOT SPACE?)? '(' SPACE? userConditions SPACE? ')' SPACE? # userConditionGroupParenthesis + ; +userCondition: userComparisons SPACE? ; + +// delimeter +delimeter: SPACE WHERE SPACE | SPACE? ':' SPACE ; +WHERE: W H E R E ; + +// paging +paging: PAGE SPACE pageNum=INT (SPACE SIZE SPACE pageSize=INT)? SPACE?; + +// sorting +processSorting: SORT_BY SPACE processAttributeOrdering (',' SPACE? processAttributeOrdering)* SPACE?; +processAttributeOrdering: processAttribute (SPACE ordering=(ASC | DESC))? ; +processAttribute: ID + | IDENTIFIER + | VERSION + | TITLE + | CREATION_DATE + ; + +caseSorting: SORT_BY SPACE caseAttributeOrdering (',' SPACE? caseAttributeOrdering)* SPACE?; +caseAttributeOrdering: caseAttribute (SPACE ordering=(ASC | DESC))? ; +caseAttribute: ID + | PROCESS_ID + | PROCESS_IDENTIFIER + | TITLE + | CREATION_DATE + | AUTHOR + | places + | tasksUserId + | tasksState + | dataValue + | dataOptions + ; + +taskSorting: SORT_BY SPACE taskAttributeOrdering (',' SPACE? taskAttributeOrdering)* SPACE?; +taskAttributeOrdering: taskAttribute (SPACE ordering=(ASC | DESC))? ; +taskAttribute: ID + | TRANSITION_ID + | TITLE + | STATE + | USER_ID + | CASE_ID + | PROCESS_ID + | LAST_ASSIGN + | LAST_FINISH + ; + +userSorting: SORT_BY SPACE userAttributeOrdering (',' SPACE? userAttributeOrdering)* SPACE?; +userAttributeOrdering: userAttribute (SPACE ordering=(ASC | DESC))? ; +userAttribute: ID + | NAME + | SURNAME + | EMAIL + ; + +// resource comparisons +// todo: authorComparison for process? +processComparisons: idComparison + | identifierComparison + | versionComparison + | titleComparison + | creationDateComparison + ; + +caseComparisons: idComparison + | processIdObjIdComparison + | processIdentifierComparison + | titleComparison + | creationDateComparison + | authorComparison + | placesComparison + | tasksStateComparison + | tasksUserIdComparison + | dataValueComparison + | dataOptionsComparison + ; + +taskComparisons: idComparison + | transitionIdComparison + | titleComparison + | stateComparison + | userIdComparison + | caseIdComparison + | processIdComparison + | lastAssignComparison + | lastFinishComparison + ; + +userComparisons: idComparison + | nameComparison + | surnameComparison + | emailComparison + ; + +// attribute comparisons +idComparison: ID SPACE objectIdComparison # idBasic + | ID SPACE inListStringComparison # idList + | ID SPACE nullComparison # idNull + ; +titleComparison: TITLE SPACE stringComparison # titleBasic + | TITLE SPACE stringLikeComparison # titleLike + | TITLE SPACE inListStringComparison # titleList + | TITLE SPACE inRangeStringComparison # titleRange + | TITLE SPACE nullComparison # titleNull + ; +identifierComparison: IDENTIFIER SPACE stringComparison # identifierBasic + | IDENTIFIER SPACE inListStringComparison # identifierList + | IDENTIFIER SPACE inRangeStringComparison # identifierRange + | IDENTIFIER SPACE nullComparison # identifierNull + ; +versionComparison: VERSION SPACE (NOT SPACE?)? op=(EQ | LT | GT | LTE | GTE) SPACE VERSION_NUMBER # versionBasic + | VERSION SPACE inListVersionComparison # versionListCmp + | VERSION SPACE inRangeVersionComparison # versionRangeCmp + | VERSION SPACE nullComparison # versionNull + ; +creationDateComparison: CREATION_DATE SPACE dateComparison # cdDateBasic + | CREATION_DATE SPACE dateTimeComparison # cdDateTimeBasic + | CREATION_DATE SPACE inListDateComparison # cdDateList + | CREATION_DATE SPACE inRangeDateComparison # cdDateRange + | CREATION_DATE SPACE nullComparison # cdNull + ; +processIdComparison: PROCESS_ID SPACE stringComparison # processIdBasic + | PROCESS_ID SPACE inListStringComparison # processIdList + | PROCESS_ID SPACE nullComparison # processIdNull + ; +processIdObjIdComparison: PROCESS_ID SPACE objectIdComparison # processIdObjIdBasic + | PROCESS_ID SPACE inListStringComparison # processIdObjIdList + | PROCESS_ID SPACE nullComparison # processIdObjNull + ; +processIdentifierComparison: PROCESS_IDENTIFIER SPACE stringComparison # processIdentifierBasic + | PROCESS_IDENTIFIER SPACE inListStringComparison # processIdentifierList + | PROCESS_IDENTIFIER SPACE inRangeStringComparison # processIdentifierRange + | PROCESS_IDENTIFIER SPACE nullComparison # processIdentifierNull + ; +authorComparison: AUTHOR SPACE stringComparison # authorBasic + | AUTHOR SPACE inListStringComparison # authorList + | AUTHOR SPACE nullComparison # authorNull + ; +transitionIdComparison: TRANSITION_ID SPACE stringComparison # transitionIdBasic + | TRANSITION_ID SPACE inListStringComparison # transitionIdList + | TRANSITION_ID SPACE inRangeStringComparison # transitionIdRange + | TRANSITION_ID SPACE nullComparison # transitionIdNull + ; +stateComparison: STATE SPACE EQ SPACE state=(ENABLED | DISABLED) ; +userIdComparison: USER_ID SPACE stringComparison # userIdBasic + | USER_ID SPACE inListStringComparison # userIdList + | USER_ID SPACE nullComparison # userIdNull + ; +caseIdComparison: CASE_ID SPACE stringComparison # caseIdBasic + | CASE_ID SPACE inListStringComparison # caseIdList + | CASE_ID SPACE nullComparison # caseIdNull + ; +lastAssignComparison: LAST_ASSIGN SPACE dateComparison # laDateBasic + | LAST_ASSIGN SPACE dateTimeComparison # laDateTimeBasic + | LAST_ASSIGN SPACE inListDateComparison # laDateList + | LAST_ASSIGN SPACE inRangeDateComparison # laDateRange + | LAST_ASSIGN SPACE nullComparison # laNull + ; +lastFinishComparison: LAST_FINISH SPACE dateComparison # lfDateBasic + | LAST_FINISH SPACE dateTimeComparison # lfDateTimeBasic + | LAST_FINISH SPACE inListDateComparison # lfDateList + | LAST_FINISH SPACE inRangeDateComparison # lfDateRange + | LAST_FINISH SPACE nullComparison # lfNull + ; +nameComparison: NAME SPACE stringComparison # nameBasic + | NAME SPACE inListStringComparison # nameList + | NAME SPACE inRangeStringComparison # nameRange + | NAME SPACE nullComparison # nameNull + ; +surnameComparison: SURNAME SPACE stringComparison # surnameBasic + | SURNAME SPACE inListStringComparison # surnameList + | SURNAME SPACE inRangeStringComparison # surnameRange + | SURNAME SPACE nullComparison # surnameNull + ; +emailComparison: EMAIL SPACE stringComparison # emailBasic + | EMAIL SPACE inListStringComparison # emailList + | EMAIL SPACE inRangeStringComparison # emailRange + | EMAIL SPACE nullComparison # emailNull + ; +dataValueComparison: dataValue SPACE stringComparison # dataString + | dataValue SPACE stringLikeComparison # dataStringLike + | dataValue SPACE numberComparison # dataNumber + | dataValue SPACE dateComparison # dataDate + | dataValue SPACE dateTimeComparison # dataDatetime + | dataValue SPACE booleanComparison # dataBoolean + | dataValue SPACE inListStringComparison # dataStringList + | dataValue SPACE inListNumberComparison # dataNumberList + | dataValue SPACE inListDateComparison # dataDateList + | dataValue SPACE inRangeStringComparison # dataStringRange + | dataValue SPACE inRangeNumberComparison # dataNumberRange + | dataValue SPACE inRangeDateComparison # dataDateRange + | dataValue SPACE nullComparison # dataNull + ; +dataOptionsComparison: dataOptions SPACE stringComparison # dataOptionsBasic + | dataOptions SPACE inListStringComparison # dataOptionsList + | dataOptions SPACE inRangeStringComparison # dataOptionsRange + | dataOptions SPACE nullComparison # dataOptionsNull + ; +placesComparison: places SPACE numberComparison # placesBasic + | places SPACE inListNumberComparison # placesList + | places SPACE inRangeNumberComparison # placesRange + | places SPACE nullComparison # placesNull + ; +tasksStateComparison: tasksState SPACE (NOT SPACE?)? op=EQ SPACE state=(ENABLED | DISABLED) ; +tasksUserIdComparison: tasksUserId SPACE stringComparison # tasksUserIdBasic + | tasksUserId SPACE inListStringComparison # tasksUserIdList + | tasksUserId SPACE nullComparison # tasksUserIdNull + ; + +// basic comparisons +objectIdComparison: (NOT SPACE?)? op=(EQ | NEQ) SPACE (STRING | LOGGED_USER_ID) ; +stringComparison: (NOT SPACE?)? op=(EQ | NEQ | CONTAINS | LT | GT | LTE | GTE) SPACE (STRING | loggedUserStringAttribute) ; +stringLikeComparison: stringComparison LIKE ; +numberComparison: (NOT SPACE?)? op=(EQ | NEQ | LT | GT | LTE | GTE) SPACE number=(INT | DOUBLE) ; +dateComparison: (NOT SPACE?)? op=(EQ | NEQ | LT | GT | LTE | GTE) SPACE DATE ; +dateTimeComparison: (NOT SPACE?)? op=(EQ | NEQ | LT | GT | LTE | GTE) SPACE DATETIME ; +booleanComparison: (NOT SPACE?)? op=(EQ | NEQ) SPACE (BOOLEAN | LOGGED_USER_ANONYMOUS) ; +nullComparison: (NOT SPACE?)? op=(EQ | NEQ) SPACE NULL ; + +// in list/in range comparisons +inListStringComparison: (NOT SPACE?)? op=IN SPACE? stringList ; +inListNumberComparison: (NOT SPACE?)? op=IN SPACE? (intList | doubleList) ; +inListDateComparison: (NOT SPACE?)? op=IN SPACE? (dateList | dateTimeList) ; +inListVersionComparison: (NOT SPACE?)? op=IN SPACE? versionList ; +inRangeStringComparison: (NOT SPACE?)? op=IN SPACE? stringRange ; +inRangeNumberComparison: (NOT SPACE?)? op=IN SPACE? (intRange | doubleRange) ; +inRangeDateComparison: (NOT SPACE?)? op=IN SPACE? (dateRange | dateTimeRange) ; +inRangeVersionComparison: (NOT SPACE?)? op=IN SPACE? versionRange ; + +// special attribute rules +dataValue: DATA '.' fieldId=javaId '.' VALUE ; +dataOptions: DATA '.' fieldId=javaId '.' OPTIONS ; +places: PLACES '.' placeId=javaId '.' MARKING ; +tasksState: TASKS '.' taskId=javaId '.' STATE ; +tasksUserId: TASKS '.' taskId=javaId '.' USER_ID ; + +// identifier that also accepts reserved words as plain identifiers +javaId: JAVA_ID + | ID | TITLE | IDENTIFIER | VERSION | CREATION_DATE + | PROCESS_ID | PROCESS_IDENTIFIER | AUTHOR | PLACES + | TRANSITION_ID | STATE | USER_ID | CASE_ID + | LAST_ASSIGN | LAST_FINISH + | NAME | SURNAME | EMAIL + | DATA | VALUE | OPTIONS | MARKING + | ENABLED | DISABLED + | PAGE | SIZE | ASC | DESC + | CASE | CASES | TASK | TASKS + | USER | USERS | PROCESS | PROCESSES + ; + +// operators +AND: A N D | '&' ; +OR: O R | '|' ; +NOT: N O T | '!' ; +EQ: E Q | '==' ; +NEQ: N E Q | '!=' ; +LT: L T | '<' ; +GT: G T | '>' ; +LTE: L T E | '<=' ; +GTE: G T E | '>=' ; +CONTAINS: C O N T A I N S | '~' ; +IN: I N ; + +// resurces +CASE: C A S E ; +CASES: C A S E S ; +TASK: T A S K ; +TASKS: T A S K S ; +USER: U S E R ; +USERS: U S E R S ; +PROCESS: P R O C E S S ; +PROCESSES: P R O C E S S E S ; + +// attributes +ID: I D ; +TITLE: T I T L E ; +IDENTIFIER: I D E N T I F I E R ; +VERSION: V E R S I O N ; +CREATION_DATE: C R E A T I O N D A T E ; +PROCESS_ID: P R O C E S S I D ; +PROCESS_IDENTIFIER: P R O C E S S I D E N T I F I E R ; +AUTHOR: A U T H O R ; +PLACES: P L A C E S ; +TRANSITION_ID: T R A N S I T I O N I D ; +STATE: S T A T E ; +USER_ID: U S E R I D ; +CASE_ID: C A S E I D ; +LAST_ASSIGN: L A S T A S S I G N ; +LAST_FINISH: L A S T F I N I S H ; +NAME: N A M E ; +SURNAME: S U R N A M E ; +EMAIL: E M A I L ; + +DATA: D A T A ; +VALUE: V A L U E ; +OPTIONS: O P T I O N S ; +MARKING: M A R K I N G ; +ENABLED: E N A B L E D ; +DISABLED: D I S A B L E D ; + +// paging +PAGE: P A G E ; +SIZE: S I Z E ; + +// sorting +SORT_BY: S O R T SPACE B Y ; +ASC: A S C ; +DESC: D E S C ; + +// basic types +stringList: '(' SPACE? ((STRING | loggedUserStringAttribute) SPACE? (',' SPACE? (STRING | loggedUserStringAttribute) SPACE? )* )? SPACE? ')' ; +intList: '(' SPACE? (INT SPACE? (',' SPACE? INT SPACE? )* )? SPACE? ')' ; +doubleList: '(' SPACE? (DOUBLE SPACE? (',' SPACE? DOUBLE SPACE? )* )? SPACE? ')' ; +dateList: '(' SPACE? (DATE SPACE? (',' SPACE? DATE SPACE? )* )? SPACE? ')' ; +dateTimeList: '(' SPACE? (DATETIME SPACE? (',' SPACE? DATETIME SPACE? )* )? SPACE? ')' ; +versionList: '(' SPACE? (VERSION_NUMBER SPACE? (',' SPACE? VERSION_NUMBER SPACE? )* )? SPACE? ')' ; +stringRange: leftEndpoint=('(' | '[') SPACE? (STRING | loggedUserStringAttribute) SPACE? ':' SPACE? (STRING | loggedUserStringAttribute) SPACE? rightEndpoint=(')' | ']') ; +intRange: leftEndpoint=('(' | '[') SPACE? INT SPACE? ':' SPACE? INT SPACE? rightEndpoint=(')' | ']') ; +doubleRange: leftEndpoint=('(' | '[') SPACE? DOUBLE SPACE? ':' SPACE? DOUBLE SPACE? rightEndpoint=(')' | ']') ; +dateRange: leftEndpoint=('(' | '[') SPACE? DATE SPACE? ':' SPACE? DATE SPACE? rightEndpoint=(')' | ']') ; +dateTimeRange: leftEndpoint=('(' | '[') SPACE? DATETIME SPACE? ':' SPACE? DATETIME SPACE? rightEndpoint=(')' | ']') ; +versionRange: leftEndpoint=('(' | '[') SPACE? VERSION_NUMBER SPACE? ':' SPACE? VERSION_NUMBER SPACE? rightEndpoint=(')' | ']') ; +STRING: '\'' (~('\'' | '\r' | '\n'))* '\'' ; // todo NAE-1997: escape??? +INT: DIGIT+ ; +DOUBLE: DIGIT+ '.' DIGIT+ ; +DATETIME: DATE 'T' ([01] DIGIT | '2' [0-3]) ':' [0-5] DIGIT ':' [0-5] DIGIT ('.' DIGIT+)? ; // 2020-03-03T20:00:00.055 // todo NAE-1997: format +DATE: DIGIT DIGIT DIGIT DIGIT '-' ('0' [1-9] | '1' [0-2]) '-' ('0' [1-9] | [12] DIGIT | '3' [01]) ; // 2020-03-03 // todo NAE-1997: format +BOOLEAN: T R U E | F A L S E ; +VERSION_NUMBER: DIGIT+ '.' DIGIT+ '.' DIGIT+ ; +NULL: N U L L ; +LIKE: '*' ; +JAVA_ID: [a-zA-Z$_] [a-zA-Z0-9$_]* ; + +SPACE: [ ]+ ; +ANY: . ; + +// place holders +loggedUserStringAttribute: (LOGGED_USER_ID | LOGGED_USER_USERNAME | LOGGED_USER_FULLNAME); +LOGGED_USER_ID: L O G G E D U S E R '.' I D ; +LOGGED_USER_FULLNAME: L O G G E D U S E R '.' F U L L N A M E ; +LOGGED_USER_USERNAME: L O G G E D U S E R '.' U S E R N A M E ; +LOGGED_USER_ANONYMOUS: L O G G E D U S E R '.' A N O N Y M O U S ; + +// fragments +fragment A : [aA]; +fragment B : [bB]; +fragment C : [cC]; +fragment D : [dD]; +fragment E : [eE]; +fragment F : [fF]; +fragment G : [gG]; +fragment H : [hH]; +fragment I : [iI]; +fragment J : [jJ]; +fragment K : [kK]; +fragment L : [lL]; +fragment M : [mM]; +fragment N : [nN]; +fragment O : [oO]; +fragment P : [pP]; +fragment Q : [qQ]; +fragment R : [rR]; +fragment S : [sS]; +fragment T : [tT]; +fragment U : [uU]; +fragment V : [vV]; +fragment W : [wW]; +fragment X : [xX]; +fragment Y : [yY]; +fragment Z : [zZ]; +fragment DIGIT: [0-9]; diff --git a/projects/netgrif-components-core/src/lib/pfql/generated/QueryLang.interp b/projects/netgrif-components-core/src/lib/pfql/generated/QueryLang.interp new file mode 100644 index 0000000000..44ace4fa1e --- /dev/null +++ b/projects/netgrif-components-core/src/lib/pfql/generated/QueryLang.interp @@ -0,0 +1,256 @@ +token literal names: +null +'(' +')' +':' +',' +'.' +'[' +']' +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +'*' +null +null +null +null +null +null +null + +token symbolic names: +null +null +null +null +null +null +null +null +WHERE +AND +OR +NOT +EQ +NEQ +LT +GT +LTE +GTE +CONTAINS +IN +CASE +CASES +TASK +TASKS +USER +USERS +PROCESS +PROCESSES +ID +TITLE +IDENTIFIER +VERSION +CREATION_DATE +PROCESS_ID +PROCESS_IDENTIFIER +AUTHOR +PLACES +TRANSITION_ID +STATE +USER_ID +CASE_ID +LAST_ASSIGN +LAST_FINISH +NAME +SURNAME +EMAIL +DATA +VALUE +OPTIONS +MARKING +ENABLED +DISABLED +PAGE +SIZE +SORT_BY +ASC +DESC +STRING +INT +DOUBLE +DATETIME +DATE +BOOLEAN +VERSION_NUMBER +NULL +LIKE +JAVA_ID +SPACE +ANY +LOGGED_USER_ID +LOGGED_USER_FULLNAME +LOGGED_USER_USERNAME +LOGGED_USER_ANONYMOUS + +rule names: +query +processConditionsAndPaging +caseConditionsAndPaging +taskConditionsAndPaging +userConditionsAndPaging +processConditions +processOrExpression +processAndExpression +processConditionGroup +processCondition +caseConditions +caseOrExpression +caseAndExpression +caseConditionGroup +caseCondition +taskConditions +taskOrExpression +taskAndExpression +taskConditionGroup +taskCondition +userConditions +userOrExpression +userAndExpression +userConditionGroup +userCondition +delimeter +paging +processSorting +processAttributeOrdering +processAttribute +caseSorting +caseAttributeOrdering +caseAttribute +taskSorting +taskAttributeOrdering +taskAttribute +userSorting +userAttributeOrdering +userAttribute +processComparisons +caseComparisons +taskComparisons +userComparisons +idComparison +titleComparison +identifierComparison +versionComparison +creationDateComparison +processIdComparison +processIdObjIdComparison +processIdentifierComparison +authorComparison +transitionIdComparison +stateComparison +userIdComparison +caseIdComparison +lastAssignComparison +lastFinishComparison +nameComparison +surnameComparison +emailComparison +dataValueComparison +dataOptionsComparison +placesComparison +tasksStateComparison +tasksUserIdComparison +objectIdComparison +stringComparison +stringLikeComparison +numberComparison +dateComparison +dateTimeComparison +booleanComparison +nullComparison +inListStringComparison +inListNumberComparison +inListDateComparison +inListVersionComparison +inRangeStringComparison +inRangeNumberComparison +inRangeDateComparison +inRangeVersionComparison +dataValue +dataOptions +places +tasksState +tasksUserId +javaId +stringList +intList +doubleList +dateList +dateTimeList +versionList +stringRange +intRange +doubleRange +dateRange +dateTimeRange +versionRange +loggedUserStringAttribute + + +atn: +[4, 1, 72, 1478, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, 2, 92, 7, 92, 2, 93, 7, 93, 2, 94, 7, 94, 2, 95, 7, 95, 2, 96, 7, 96, 2, 97, 7, 97, 2, 98, 7, 98, 2, 99, 7, 99, 2, 100, 7, 100, 1, 0, 1, 0, 3, 0, 205, 8, 0, 1, 0, 1, 0, 1, 0, 3, 0, 210, 8, 0, 1, 0, 1, 0, 1, 0, 3, 0, 215, 8, 0, 1, 0, 1, 0, 1, 0, 3, 0, 220, 8, 0, 1, 0, 3, 0, 223, 8, 0, 1, 1, 1, 1, 3, 1, 227, 8, 1, 1, 1, 3, 1, 230, 8, 1, 1, 1, 3, 1, 233, 8, 1, 1, 2, 1, 2, 3, 2, 237, 8, 2, 1, 2, 3, 2, 240, 8, 2, 1, 2, 3, 2, 243, 8, 2, 1, 3, 1, 3, 3, 3, 247, 8, 3, 1, 3, 3, 3, 250, 8, 3, 1, 3, 3, 3, 253, 8, 3, 1, 4, 1, 4, 3, 4, 257, 8, 4, 1, 4, 3, 4, 260, 8, 4, 1, 4, 3, 4, 263, 8, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 5, 6, 272, 8, 6, 10, 6, 12, 6, 275, 9, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 5, 7, 282, 8, 7, 10, 7, 12, 7, 285, 9, 7, 1, 8, 1, 8, 1, 8, 3, 8, 290, 8, 8, 3, 8, 292, 8, 8, 1, 8, 1, 8, 3, 8, 296, 8, 8, 1, 8, 1, 8, 3, 8, 300, 8, 8, 1, 8, 1, 8, 3, 8, 304, 8, 8, 3, 8, 306, 8, 8, 1, 9, 1, 9, 3, 9, 310, 8, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 5, 11, 319, 8, 11, 10, 11, 12, 11, 322, 9, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 5, 12, 329, 8, 12, 10, 12, 12, 12, 332, 9, 12, 1, 13, 1, 13, 1, 13, 3, 13, 337, 8, 13, 3, 13, 339, 8, 13, 1, 13, 1, 13, 3, 13, 343, 8, 13, 1, 13, 1, 13, 3, 13, 347, 8, 13, 1, 13, 1, 13, 3, 13, 351, 8, 13, 3, 13, 353, 8, 13, 1, 14, 1, 14, 3, 14, 357, 8, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 5, 16, 366, 8, 16, 10, 16, 12, 16, 369, 9, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 5, 17, 376, 8, 17, 10, 17, 12, 17, 379, 9, 17, 1, 18, 1, 18, 1, 18, 3, 18, 384, 8, 18, 3, 18, 386, 8, 18, 1, 18, 1, 18, 3, 18, 390, 8, 18, 1, 18, 1, 18, 3, 18, 394, 8, 18, 1, 18, 1, 18, 3, 18, 398, 8, 18, 3, 18, 400, 8, 18, 1, 19, 1, 19, 3, 19, 404, 8, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 5, 21, 413, 8, 21, 10, 21, 12, 21, 416, 9, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 5, 22, 423, 8, 22, 10, 22, 12, 22, 426, 9, 22, 1, 23, 1, 23, 1, 23, 3, 23, 431, 8, 23, 3, 23, 433, 8, 23, 1, 23, 1, 23, 3, 23, 437, 8, 23, 1, 23, 1, 23, 3, 23, 441, 8, 23, 1, 23, 1, 23, 3, 23, 445, 8, 23, 3, 23, 447, 8, 23, 1, 24, 1, 24, 3, 24, 451, 8, 24, 1, 25, 1, 25, 1, 25, 1, 25, 3, 25, 457, 8, 25, 1, 25, 1, 25, 3, 25, 461, 8, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 3, 26, 470, 8, 26, 1, 26, 3, 26, 473, 8, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 3, 27, 480, 8, 27, 1, 27, 5, 27, 483, 8, 27, 10, 27, 12, 27, 486, 9, 27, 1, 27, 3, 27, 489, 8, 27, 1, 28, 1, 28, 1, 28, 3, 28, 494, 8, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 3, 30, 503, 8, 30, 1, 30, 5, 30, 506, 8, 30, 10, 30, 12, 30, 509, 9, 30, 1, 30, 3, 30, 512, 8, 30, 1, 31, 1, 31, 1, 31, 3, 31, 517, 8, 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 3, 32, 530, 8, 32, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 3, 33, 537, 8, 33, 1, 33, 5, 33, 540, 8, 33, 10, 33, 12, 33, 543, 9, 33, 1, 33, 3, 33, 546, 8, 33, 1, 34, 1, 34, 1, 34, 3, 34, 551, 8, 34, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 3, 36, 560, 8, 36, 1, 36, 5, 36, 563, 8, 36, 10, 36, 12, 36, 566, 9, 36, 1, 36, 3, 36, 569, 8, 36, 1, 37, 1, 37, 1, 37, 3, 37, 574, 8, 37, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 3, 39, 583, 8, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 3, 40, 596, 8, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 3, 41, 607, 8, 41, 1, 42, 1, 42, 1, 42, 1, 42, 3, 42, 613, 8, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 3, 43, 624, 8, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 3, 44, 641, 8, 44, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 3, 45, 655, 8, 45, 1, 46, 1, 46, 1, 46, 1, 46, 3, 46, 661, 8, 46, 3, 46, 663, 8, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 3, 46, 677, 8, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 3, 47, 694, 8, 47, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 3, 48, 705, 8, 48, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 3, 49, 716, 8, 49, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 3, 50, 730, 8, 50, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 3, 51, 741, 8, 51, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 3, 52, 755, 8, 52, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 3, 54, 772, 8, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 3, 55, 783, 8, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 3, 56, 800, 8, 56, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 3, 57, 817, 8, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 3, 58, 831, 8, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 3, 59, 845, 8, 59, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 3, 60, 859, 8, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 3, 61, 913, 8, 61, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 3, 62, 931, 8, 62, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 3, 63, 949, 8, 63, 1, 64, 1, 64, 1, 64, 1, 64, 3, 64, 955, 8, 64, 3, 64, 957, 8, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 3, 65, 975, 8, 65, 1, 66, 1, 66, 3, 66, 979, 8, 66, 3, 66, 981, 8, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 67, 1, 67, 3, 67, 989, 8, 67, 3, 67, 991, 8, 67, 1, 67, 1, 67, 1, 67, 1, 67, 3, 67, 997, 8, 67, 1, 68, 1, 68, 1, 68, 1, 69, 1, 69, 3, 69, 1004, 8, 69, 3, 69, 1006, 8, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 70, 1, 70, 3, 70, 1014, 8, 70, 3, 70, 1016, 8, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 3, 71, 1024, 8, 71, 3, 71, 1026, 8, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 72, 1, 72, 3, 72, 1034, 8, 72, 3, 72, 1036, 8, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 3, 73, 1044, 8, 73, 3, 73, 1046, 8, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 74, 1, 74, 3, 74, 1054, 8, 74, 3, 74, 1056, 8, 74, 1, 74, 1, 74, 3, 74, 1060, 8, 74, 1, 74, 1, 74, 1, 75, 1, 75, 3, 75, 1066, 8, 75, 3, 75, 1068, 8, 75, 1, 75, 1, 75, 3, 75, 1072, 8, 75, 1, 75, 1, 75, 3, 75, 1076, 8, 75, 1, 76, 1, 76, 3, 76, 1080, 8, 76, 3, 76, 1082, 8, 76, 1, 76, 1, 76, 3, 76, 1086, 8, 76, 1, 76, 1, 76, 3, 76, 1090, 8, 76, 1, 77, 1, 77, 3, 77, 1094, 8, 77, 3, 77, 1096, 8, 77, 1, 77, 1, 77, 3, 77, 1100, 8, 77, 1, 77, 1, 77, 1, 78, 1, 78, 3, 78, 1106, 8, 78, 3, 78, 1108, 8, 78, 1, 78, 1, 78, 3, 78, 1112, 8, 78, 1, 78, 1, 78, 1, 79, 1, 79, 3, 79, 1118, 8, 79, 3, 79, 1120, 8, 79, 1, 79, 1, 79, 3, 79, 1124, 8, 79, 1, 79, 1, 79, 3, 79, 1128, 8, 79, 1, 80, 1, 80, 3, 80, 1132, 8, 80, 3, 80, 1134, 8, 80, 1, 80, 1, 80, 3, 80, 1138, 8, 80, 1, 80, 1, 80, 3, 80, 1142, 8, 80, 1, 81, 1, 81, 3, 81, 1146, 8, 81, 3, 81, 1148, 8, 81, 1, 81, 1, 81, 3, 81, 1152, 8, 81, 1, 81, 1, 81, 1, 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 84, 1, 84, 1, 84, 1, 84, 1, 84, 1, 84, 1, 85, 1, 85, 1, 85, 1, 85, 1, 85, 1, 85, 1, 86, 1, 86, 1, 86, 1, 86, 1, 86, 1, 86, 1, 87, 1, 87, 1, 88, 1, 88, 3, 88, 1190, 8, 88, 1, 88, 1, 88, 3, 88, 1194, 8, 88, 1, 88, 3, 88, 1197, 8, 88, 1, 88, 1, 88, 3, 88, 1201, 8, 88, 1, 88, 1, 88, 3, 88, 1205, 8, 88, 1, 88, 3, 88, 1208, 8, 88, 5, 88, 1210, 8, 88, 10, 88, 12, 88, 1213, 9, 88, 3, 88, 1215, 8, 88, 1, 88, 3, 88, 1218, 8, 88, 1, 88, 1, 88, 1, 89, 1, 89, 3, 89, 1224, 8, 89, 1, 89, 1, 89, 3, 89, 1228, 8, 89, 1, 89, 1, 89, 3, 89, 1232, 8, 89, 1, 89, 1, 89, 3, 89, 1236, 8, 89, 5, 89, 1238, 8, 89, 10, 89, 12, 89, 1241, 9, 89, 3, 89, 1243, 8, 89, 1, 89, 3, 89, 1246, 8, 89, 1, 89, 1, 89, 1, 90, 1, 90, 3, 90, 1252, 8, 90, 1, 90, 1, 90, 3, 90, 1256, 8, 90, 1, 90, 1, 90, 3, 90, 1260, 8, 90, 1, 90, 1, 90, 3, 90, 1264, 8, 90, 5, 90, 1266, 8, 90, 10, 90, 12, 90, 1269, 9, 90, 3, 90, 1271, 8, 90, 1, 90, 3, 90, 1274, 8, 90, 1, 90, 1, 90, 1, 91, 1, 91, 3, 91, 1280, 8, 91, 1, 91, 1, 91, 3, 91, 1284, 8, 91, 1, 91, 1, 91, 3, 91, 1288, 8, 91, 1, 91, 1, 91, 3, 91, 1292, 8, 91, 5, 91, 1294, 8, 91, 10, 91, 12, 91, 1297, 9, 91, 3, 91, 1299, 8, 91, 1, 91, 3, 91, 1302, 8, 91, 1, 91, 1, 91, 1, 92, 1, 92, 3, 92, 1308, 8, 92, 1, 92, 1, 92, 3, 92, 1312, 8, 92, 1, 92, 1, 92, 3, 92, 1316, 8, 92, 1, 92, 1, 92, 3, 92, 1320, 8, 92, 5, 92, 1322, 8, 92, 10, 92, 12, 92, 1325, 9, 92, 3, 92, 1327, 8, 92, 1, 92, 3, 92, 1330, 8, 92, 1, 92, 1, 92, 1, 93, 1, 93, 3, 93, 1336, 8, 93, 1, 93, 1, 93, 3, 93, 1340, 8, 93, 1, 93, 1, 93, 3, 93, 1344, 8, 93, 1, 93, 1, 93, 3, 93, 1348, 8, 93, 5, 93, 1350, 8, 93, 10, 93, 12, 93, 1353, 9, 93, 3, 93, 1355, 8, 93, 1, 93, 3, 93, 1358, 8, 93, 1, 93, 1, 93, 1, 94, 1, 94, 3, 94, 1364, 8, 94, 1, 94, 1, 94, 3, 94, 1368, 8, 94, 1, 94, 3, 94, 1371, 8, 94, 1, 94, 1, 94, 3, 94, 1375, 8, 94, 1, 94, 1, 94, 3, 94, 1379, 8, 94, 1, 94, 3, 94, 1382, 8, 94, 1, 94, 1, 94, 1, 95, 1, 95, 3, 95, 1388, 8, 95, 1, 95, 1, 95, 3, 95, 1392, 8, 95, 1, 95, 1, 95, 3, 95, 1396, 8, 95, 1, 95, 1, 95, 3, 95, 1400, 8, 95, 1, 95, 1, 95, 1, 96, 1, 96, 3, 96, 1406, 8, 96, 1, 96, 1, 96, 3, 96, 1410, 8, 96, 1, 96, 1, 96, 3, 96, 1414, 8, 96, 1, 96, 1, 96, 3, 96, 1418, 8, 96, 1, 96, 1, 96, 1, 97, 1, 97, 3, 97, 1424, 8, 97, 1, 97, 1, 97, 3, 97, 1428, 8, 97, 1, 97, 1, 97, 3, 97, 1432, 8, 97, 1, 97, 1, 97, 3, 97, 1436, 8, 97, 1, 97, 1, 97, 1, 98, 1, 98, 3, 98, 1442, 8, 98, 1, 98, 1, 98, 3, 98, 1446, 8, 98, 1, 98, 1, 98, 3, 98, 1450, 8, 98, 1, 98, 1, 98, 3, 98, 1454, 8, 98, 1, 98, 1, 98, 1, 99, 1, 99, 3, 99, 1460, 8, 99, 1, 99, 1, 99, 3, 99, 1464, 8, 99, 1, 99, 1, 99, 3, 99, 1468, 8, 99, 1, 99, 1, 99, 3, 99, 1472, 8, 99, 1, 99, 1, 99, 1, 100, 1, 100, 1, 100, 0, 0, 101, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 0, 20, 1, 0, 26, 27, 1, 0, 20, 21, 1, 0, 22, 23, 1, 0, 24, 25, 1, 0, 55, 56, 1, 0, 28, 32, 3, 0, 28, 29, 33, 33, 37, 42, 2, 0, 28, 28, 43, 45, 2, 0, 12, 12, 14, 17, 1, 0, 50, 51, 1, 0, 12, 13, 2, 0, 57, 57, 69, 69, 1, 0, 12, 18, 1, 0, 12, 17, 1, 0, 58, 59, 2, 0, 62, 62, 72, 72, 3, 0, 20, 53, 55, 56, 66, 66, 2, 0, 1, 1, 6, 6, 2, 0, 2, 2, 7, 7, 1, 0, 69, 71, 1672, 0, 222, 1, 0, 0, 0, 2, 224, 1, 0, 0, 0, 4, 234, 1, 0, 0, 0, 6, 244, 1, 0, 0, 0, 8, 254, 1, 0, 0, 0, 10, 264, 1, 0, 0, 0, 12, 266, 1, 0, 0, 0, 14, 276, 1, 0, 0, 0, 16, 305, 1, 0, 0, 0, 18, 307, 1, 0, 0, 0, 20, 311, 1, 0, 0, 0, 22, 313, 1, 0, 0, 0, 24, 323, 1, 0, 0, 0, 26, 352, 1, 0, 0, 0, 28, 354, 1, 0, 0, 0, 30, 358, 1, 0, 0, 0, 32, 360, 1, 0, 0, 0, 34, 370, 1, 0, 0, 0, 36, 399, 1, 0, 0, 0, 38, 401, 1, 0, 0, 0, 40, 405, 1, 0, 0, 0, 42, 407, 1, 0, 0, 0, 44, 417, 1, 0, 0, 0, 46, 446, 1, 0, 0, 0, 48, 448, 1, 0, 0, 0, 50, 460, 1, 0, 0, 0, 52, 462, 1, 0, 0, 0, 54, 474, 1, 0, 0, 0, 56, 490, 1, 0, 0, 0, 58, 495, 1, 0, 0, 0, 60, 497, 1, 0, 0, 0, 62, 513, 1, 0, 0, 0, 64, 529, 1, 0, 0, 0, 66, 531, 1, 0, 0, 0, 68, 547, 1, 0, 0, 0, 70, 552, 1, 0, 0, 0, 72, 554, 1, 0, 0, 0, 74, 570, 1, 0, 0, 0, 76, 575, 1, 0, 0, 0, 78, 582, 1, 0, 0, 0, 80, 595, 1, 0, 0, 0, 82, 606, 1, 0, 0, 0, 84, 612, 1, 0, 0, 0, 86, 623, 1, 0, 0, 0, 88, 640, 1, 0, 0, 0, 90, 654, 1, 0, 0, 0, 92, 676, 1, 0, 0, 0, 94, 693, 1, 0, 0, 0, 96, 704, 1, 0, 0, 0, 98, 715, 1, 0, 0, 0, 100, 729, 1, 0, 0, 0, 102, 740, 1, 0, 0, 0, 104, 754, 1, 0, 0, 0, 106, 756, 1, 0, 0, 0, 108, 771, 1, 0, 0, 0, 110, 782, 1, 0, 0, 0, 112, 799, 1, 0, 0, 0, 114, 816, 1, 0, 0, 0, 116, 830, 1, 0, 0, 0, 118, 844, 1, 0, 0, 0, 120, 858, 1, 0, 0, 0, 122, 912, 1, 0, 0, 0, 124, 930, 1, 0, 0, 0, 126, 948, 1, 0, 0, 0, 128, 950, 1, 0, 0, 0, 130, 974, 1, 0, 0, 0, 132, 980, 1, 0, 0, 0, 134, 990, 1, 0, 0, 0, 136, 998, 1, 0, 0, 0, 138, 1005, 1, 0, 0, 0, 140, 1015, 1, 0, 0, 0, 142, 1025, 1, 0, 0, 0, 144, 1035, 1, 0, 0, 0, 146, 1045, 1, 0, 0, 0, 148, 1055, 1, 0, 0, 0, 150, 1067, 1, 0, 0, 0, 152, 1081, 1, 0, 0, 0, 154, 1095, 1, 0, 0, 0, 156, 1107, 1, 0, 0, 0, 158, 1119, 1, 0, 0, 0, 160, 1133, 1, 0, 0, 0, 162, 1147, 1, 0, 0, 0, 164, 1155, 1, 0, 0, 0, 166, 1161, 1, 0, 0, 0, 168, 1167, 1, 0, 0, 0, 170, 1173, 1, 0, 0, 0, 172, 1179, 1, 0, 0, 0, 174, 1185, 1, 0, 0, 0, 176, 1187, 1, 0, 0, 0, 178, 1221, 1, 0, 0, 0, 180, 1249, 1, 0, 0, 0, 182, 1277, 1, 0, 0, 0, 184, 1305, 1, 0, 0, 0, 186, 1333, 1, 0, 0, 0, 188, 1361, 1, 0, 0, 0, 190, 1385, 1, 0, 0, 0, 192, 1403, 1, 0, 0, 0, 194, 1421, 1, 0, 0, 0, 196, 1439, 1, 0, 0, 0, 198, 1457, 1, 0, 0, 0, 200, 1475, 1, 0, 0, 0, 202, 204, 7, 0, 0, 0, 203, 205, 3, 2, 1, 0, 204, 203, 1, 0, 0, 0, 204, 205, 1, 0, 0, 0, 205, 206, 1, 0, 0, 0, 206, 223, 5, 0, 0, 1, 207, 209, 7, 1, 0, 0, 208, 210, 3, 4, 2, 0, 209, 208, 1, 0, 0, 0, 209, 210, 1, 0, 0, 0, 210, 211, 1, 0, 0, 0, 211, 223, 5, 0, 0, 1, 212, 214, 7, 2, 0, 0, 213, 215, 3, 6, 3, 0, 214, 213, 1, 0, 0, 0, 214, 215, 1, 0, 0, 0, 215, 216, 1, 0, 0, 0, 216, 223, 5, 0, 0, 1, 217, 219, 7, 3, 0, 0, 218, 220, 3, 8, 4, 0, 219, 218, 1, 0, 0, 0, 219, 220, 1, 0, 0, 0, 220, 221, 1, 0, 0, 0, 221, 223, 5, 0, 0, 1, 222, 202, 1, 0, 0, 0, 222, 207, 1, 0, 0, 0, 222, 212, 1, 0, 0, 0, 222, 217, 1, 0, 0, 0, 223, 1, 1, 0, 0, 0, 224, 226, 3, 50, 25, 0, 225, 227, 3, 10, 5, 0, 226, 225, 1, 0, 0, 0, 226, 227, 1, 0, 0, 0, 227, 229, 1, 0, 0, 0, 228, 230, 3, 52, 26, 0, 229, 228, 1, 0, 0, 0, 229, 230, 1, 0, 0, 0, 230, 232, 1, 0, 0, 0, 231, 233, 3, 54, 27, 0, 232, 231, 1, 0, 0, 0, 232, 233, 1, 0, 0, 0, 233, 3, 1, 0, 0, 0, 234, 236, 3, 50, 25, 0, 235, 237, 3, 20, 10, 0, 236, 235, 1, 0, 0, 0, 236, 237, 1, 0, 0, 0, 237, 239, 1, 0, 0, 0, 238, 240, 3, 52, 26, 0, 239, 238, 1, 0, 0, 0, 239, 240, 1, 0, 0, 0, 240, 242, 1, 0, 0, 0, 241, 243, 3, 60, 30, 0, 242, 241, 1, 0, 0, 0, 242, 243, 1, 0, 0, 0, 243, 5, 1, 0, 0, 0, 244, 246, 3, 50, 25, 0, 245, 247, 3, 30, 15, 0, 246, 245, 1, 0, 0, 0, 246, 247, 1, 0, 0, 0, 247, 249, 1, 0, 0, 0, 248, 250, 3, 52, 26, 0, 249, 248, 1, 0, 0, 0, 249, 250, 1, 0, 0, 0, 250, 252, 1, 0, 0, 0, 251, 253, 3, 66, 33, 0, 252, 251, 1, 0, 0, 0, 252, 253, 1, 0, 0, 0, 253, 7, 1, 0, 0, 0, 254, 256, 3, 50, 25, 0, 255, 257, 3, 40, 20, 0, 256, 255, 1, 0, 0, 0, 256, 257, 1, 0, 0, 0, 257, 259, 1, 0, 0, 0, 258, 260, 3, 52, 26, 0, 259, 258, 1, 0, 0, 0, 259, 260, 1, 0, 0, 0, 260, 262, 1, 0, 0, 0, 261, 263, 3, 72, 36, 0, 262, 261, 1, 0, 0, 0, 262, 263, 1, 0, 0, 0, 263, 9, 1, 0, 0, 0, 264, 265, 3, 12, 6, 0, 265, 11, 1, 0, 0, 0, 266, 273, 3, 14, 7, 0, 267, 268, 5, 67, 0, 0, 268, 269, 5, 10, 0, 0, 269, 270, 5, 67, 0, 0, 270, 272, 3, 14, 7, 0, 271, 267, 1, 0, 0, 0, 272, 275, 1, 0, 0, 0, 273, 271, 1, 0, 0, 0, 273, 274, 1, 0, 0, 0, 274, 13, 1, 0, 0, 0, 275, 273, 1, 0, 0, 0, 276, 283, 3, 16, 8, 0, 277, 278, 5, 67, 0, 0, 278, 279, 5, 9, 0, 0, 279, 280, 5, 67, 0, 0, 280, 282, 3, 16, 8, 0, 281, 277, 1, 0, 0, 0, 282, 285, 1, 0, 0, 0, 283, 281, 1, 0, 0, 0, 283, 284, 1, 0, 0, 0, 284, 15, 1, 0, 0, 0, 285, 283, 1, 0, 0, 0, 286, 306, 3, 18, 9, 0, 287, 289, 5, 11, 0, 0, 288, 290, 5, 67, 0, 0, 289, 288, 1, 0, 0, 0, 289, 290, 1, 0, 0, 0, 290, 292, 1, 0, 0, 0, 291, 287, 1, 0, 0, 0, 291, 292, 1, 0, 0, 0, 292, 293, 1, 0, 0, 0, 293, 295, 5, 1, 0, 0, 294, 296, 5, 67, 0, 0, 295, 294, 1, 0, 0, 0, 295, 296, 1, 0, 0, 0, 296, 297, 1, 0, 0, 0, 297, 299, 3, 10, 5, 0, 298, 300, 5, 67, 0, 0, 299, 298, 1, 0, 0, 0, 299, 300, 1, 0, 0, 0, 300, 301, 1, 0, 0, 0, 301, 303, 5, 2, 0, 0, 302, 304, 5, 67, 0, 0, 303, 302, 1, 0, 0, 0, 303, 304, 1, 0, 0, 0, 304, 306, 1, 0, 0, 0, 305, 286, 1, 0, 0, 0, 305, 291, 1, 0, 0, 0, 306, 17, 1, 0, 0, 0, 307, 309, 3, 78, 39, 0, 308, 310, 5, 67, 0, 0, 309, 308, 1, 0, 0, 0, 309, 310, 1, 0, 0, 0, 310, 19, 1, 0, 0, 0, 311, 312, 3, 22, 11, 0, 312, 21, 1, 0, 0, 0, 313, 320, 3, 24, 12, 0, 314, 315, 5, 67, 0, 0, 315, 316, 5, 10, 0, 0, 316, 317, 5, 67, 0, 0, 317, 319, 3, 24, 12, 0, 318, 314, 1, 0, 0, 0, 319, 322, 1, 0, 0, 0, 320, 318, 1, 0, 0, 0, 320, 321, 1, 0, 0, 0, 321, 23, 1, 0, 0, 0, 322, 320, 1, 0, 0, 0, 323, 330, 3, 26, 13, 0, 324, 325, 5, 67, 0, 0, 325, 326, 5, 9, 0, 0, 326, 327, 5, 67, 0, 0, 327, 329, 3, 26, 13, 0, 328, 324, 1, 0, 0, 0, 329, 332, 1, 0, 0, 0, 330, 328, 1, 0, 0, 0, 330, 331, 1, 0, 0, 0, 331, 25, 1, 0, 0, 0, 332, 330, 1, 0, 0, 0, 333, 353, 3, 28, 14, 0, 334, 336, 5, 11, 0, 0, 335, 337, 5, 67, 0, 0, 336, 335, 1, 0, 0, 0, 336, 337, 1, 0, 0, 0, 337, 339, 1, 0, 0, 0, 338, 334, 1, 0, 0, 0, 338, 339, 1, 0, 0, 0, 339, 340, 1, 0, 0, 0, 340, 342, 5, 1, 0, 0, 341, 343, 5, 67, 0, 0, 342, 341, 1, 0, 0, 0, 342, 343, 1, 0, 0, 0, 343, 344, 1, 0, 0, 0, 344, 346, 3, 20, 10, 0, 345, 347, 5, 67, 0, 0, 346, 345, 1, 0, 0, 0, 346, 347, 1, 0, 0, 0, 347, 348, 1, 0, 0, 0, 348, 350, 5, 2, 0, 0, 349, 351, 5, 67, 0, 0, 350, 349, 1, 0, 0, 0, 350, 351, 1, 0, 0, 0, 351, 353, 1, 0, 0, 0, 352, 333, 1, 0, 0, 0, 352, 338, 1, 0, 0, 0, 353, 27, 1, 0, 0, 0, 354, 356, 3, 80, 40, 0, 355, 357, 5, 67, 0, 0, 356, 355, 1, 0, 0, 0, 356, 357, 1, 0, 0, 0, 357, 29, 1, 0, 0, 0, 358, 359, 3, 32, 16, 0, 359, 31, 1, 0, 0, 0, 360, 367, 3, 34, 17, 0, 361, 362, 5, 67, 0, 0, 362, 363, 5, 10, 0, 0, 363, 364, 5, 67, 0, 0, 364, 366, 3, 34, 17, 0, 365, 361, 1, 0, 0, 0, 366, 369, 1, 0, 0, 0, 367, 365, 1, 0, 0, 0, 367, 368, 1, 0, 0, 0, 368, 33, 1, 0, 0, 0, 369, 367, 1, 0, 0, 0, 370, 377, 3, 36, 18, 0, 371, 372, 5, 67, 0, 0, 372, 373, 5, 9, 0, 0, 373, 374, 5, 67, 0, 0, 374, 376, 3, 36, 18, 0, 375, 371, 1, 0, 0, 0, 376, 379, 1, 0, 0, 0, 377, 375, 1, 0, 0, 0, 377, 378, 1, 0, 0, 0, 378, 35, 1, 0, 0, 0, 379, 377, 1, 0, 0, 0, 380, 400, 3, 38, 19, 0, 381, 383, 5, 11, 0, 0, 382, 384, 5, 67, 0, 0, 383, 382, 1, 0, 0, 0, 383, 384, 1, 0, 0, 0, 384, 386, 1, 0, 0, 0, 385, 381, 1, 0, 0, 0, 385, 386, 1, 0, 0, 0, 386, 387, 1, 0, 0, 0, 387, 389, 5, 1, 0, 0, 388, 390, 5, 67, 0, 0, 389, 388, 1, 0, 0, 0, 389, 390, 1, 0, 0, 0, 390, 391, 1, 0, 0, 0, 391, 393, 3, 30, 15, 0, 392, 394, 5, 67, 0, 0, 393, 392, 1, 0, 0, 0, 393, 394, 1, 0, 0, 0, 394, 395, 1, 0, 0, 0, 395, 397, 5, 2, 0, 0, 396, 398, 5, 67, 0, 0, 397, 396, 1, 0, 0, 0, 397, 398, 1, 0, 0, 0, 398, 400, 1, 0, 0, 0, 399, 380, 1, 0, 0, 0, 399, 385, 1, 0, 0, 0, 400, 37, 1, 0, 0, 0, 401, 403, 3, 82, 41, 0, 402, 404, 5, 67, 0, 0, 403, 402, 1, 0, 0, 0, 403, 404, 1, 0, 0, 0, 404, 39, 1, 0, 0, 0, 405, 406, 3, 42, 21, 0, 406, 41, 1, 0, 0, 0, 407, 414, 3, 44, 22, 0, 408, 409, 5, 67, 0, 0, 409, 410, 5, 10, 0, 0, 410, 411, 5, 67, 0, 0, 411, 413, 3, 44, 22, 0, 412, 408, 1, 0, 0, 0, 413, 416, 1, 0, 0, 0, 414, 412, 1, 0, 0, 0, 414, 415, 1, 0, 0, 0, 415, 43, 1, 0, 0, 0, 416, 414, 1, 0, 0, 0, 417, 424, 3, 46, 23, 0, 418, 419, 5, 67, 0, 0, 419, 420, 5, 9, 0, 0, 420, 421, 5, 67, 0, 0, 421, 423, 3, 46, 23, 0, 422, 418, 1, 0, 0, 0, 423, 426, 1, 0, 0, 0, 424, 422, 1, 0, 0, 0, 424, 425, 1, 0, 0, 0, 425, 45, 1, 0, 0, 0, 426, 424, 1, 0, 0, 0, 427, 447, 3, 48, 24, 0, 428, 430, 5, 11, 0, 0, 429, 431, 5, 67, 0, 0, 430, 429, 1, 0, 0, 0, 430, 431, 1, 0, 0, 0, 431, 433, 1, 0, 0, 0, 432, 428, 1, 0, 0, 0, 432, 433, 1, 0, 0, 0, 433, 434, 1, 0, 0, 0, 434, 436, 5, 1, 0, 0, 435, 437, 5, 67, 0, 0, 436, 435, 1, 0, 0, 0, 436, 437, 1, 0, 0, 0, 437, 438, 1, 0, 0, 0, 438, 440, 3, 40, 20, 0, 439, 441, 5, 67, 0, 0, 440, 439, 1, 0, 0, 0, 440, 441, 1, 0, 0, 0, 441, 442, 1, 0, 0, 0, 442, 444, 5, 2, 0, 0, 443, 445, 5, 67, 0, 0, 444, 443, 1, 0, 0, 0, 444, 445, 1, 0, 0, 0, 445, 447, 1, 0, 0, 0, 446, 427, 1, 0, 0, 0, 446, 432, 1, 0, 0, 0, 447, 47, 1, 0, 0, 0, 448, 450, 3, 84, 42, 0, 449, 451, 5, 67, 0, 0, 450, 449, 1, 0, 0, 0, 450, 451, 1, 0, 0, 0, 451, 49, 1, 0, 0, 0, 452, 453, 5, 67, 0, 0, 453, 454, 5, 8, 0, 0, 454, 461, 5, 67, 0, 0, 455, 457, 5, 67, 0, 0, 456, 455, 1, 0, 0, 0, 456, 457, 1, 0, 0, 0, 457, 458, 1, 0, 0, 0, 458, 459, 5, 3, 0, 0, 459, 461, 5, 67, 0, 0, 460, 452, 1, 0, 0, 0, 460, 456, 1, 0, 0, 0, 461, 51, 1, 0, 0, 0, 462, 463, 5, 52, 0, 0, 463, 464, 5, 67, 0, 0, 464, 469, 5, 58, 0, 0, 465, 466, 5, 67, 0, 0, 466, 467, 5, 53, 0, 0, 467, 468, 5, 67, 0, 0, 468, 470, 5, 58, 0, 0, 469, 465, 1, 0, 0, 0, 469, 470, 1, 0, 0, 0, 470, 472, 1, 0, 0, 0, 471, 473, 5, 67, 0, 0, 472, 471, 1, 0, 0, 0, 472, 473, 1, 0, 0, 0, 473, 53, 1, 0, 0, 0, 474, 475, 5, 54, 0, 0, 475, 476, 5, 67, 0, 0, 476, 484, 3, 56, 28, 0, 477, 479, 5, 4, 0, 0, 478, 480, 5, 67, 0, 0, 479, 478, 1, 0, 0, 0, 479, 480, 1, 0, 0, 0, 480, 481, 1, 0, 0, 0, 481, 483, 3, 56, 28, 0, 482, 477, 1, 0, 0, 0, 483, 486, 1, 0, 0, 0, 484, 482, 1, 0, 0, 0, 484, 485, 1, 0, 0, 0, 485, 488, 1, 0, 0, 0, 486, 484, 1, 0, 0, 0, 487, 489, 5, 67, 0, 0, 488, 487, 1, 0, 0, 0, 488, 489, 1, 0, 0, 0, 489, 55, 1, 0, 0, 0, 490, 493, 3, 58, 29, 0, 491, 492, 5, 67, 0, 0, 492, 494, 7, 4, 0, 0, 493, 491, 1, 0, 0, 0, 493, 494, 1, 0, 0, 0, 494, 57, 1, 0, 0, 0, 495, 496, 7, 5, 0, 0, 496, 59, 1, 0, 0, 0, 497, 498, 5, 54, 0, 0, 498, 499, 5, 67, 0, 0, 499, 507, 3, 62, 31, 0, 500, 502, 5, 4, 0, 0, 501, 503, 5, 67, 0, 0, 502, 501, 1, 0, 0, 0, 502, 503, 1, 0, 0, 0, 503, 504, 1, 0, 0, 0, 504, 506, 3, 62, 31, 0, 505, 500, 1, 0, 0, 0, 506, 509, 1, 0, 0, 0, 507, 505, 1, 0, 0, 0, 507, 508, 1, 0, 0, 0, 508, 511, 1, 0, 0, 0, 509, 507, 1, 0, 0, 0, 510, 512, 5, 67, 0, 0, 511, 510, 1, 0, 0, 0, 511, 512, 1, 0, 0, 0, 512, 61, 1, 0, 0, 0, 513, 516, 3, 64, 32, 0, 514, 515, 5, 67, 0, 0, 515, 517, 7, 4, 0, 0, 516, 514, 1, 0, 0, 0, 516, 517, 1, 0, 0, 0, 517, 63, 1, 0, 0, 0, 518, 530, 5, 28, 0, 0, 519, 530, 5, 33, 0, 0, 520, 530, 5, 34, 0, 0, 521, 530, 5, 29, 0, 0, 522, 530, 5, 32, 0, 0, 523, 530, 5, 35, 0, 0, 524, 530, 3, 168, 84, 0, 525, 530, 3, 172, 86, 0, 526, 530, 3, 170, 85, 0, 527, 530, 3, 164, 82, 0, 528, 530, 3, 166, 83, 0, 529, 518, 1, 0, 0, 0, 529, 519, 1, 0, 0, 0, 529, 520, 1, 0, 0, 0, 529, 521, 1, 0, 0, 0, 529, 522, 1, 0, 0, 0, 529, 523, 1, 0, 0, 0, 529, 524, 1, 0, 0, 0, 529, 525, 1, 0, 0, 0, 529, 526, 1, 0, 0, 0, 529, 527, 1, 0, 0, 0, 529, 528, 1, 0, 0, 0, 530, 65, 1, 0, 0, 0, 531, 532, 5, 54, 0, 0, 532, 533, 5, 67, 0, 0, 533, 541, 3, 68, 34, 0, 534, 536, 5, 4, 0, 0, 535, 537, 5, 67, 0, 0, 536, 535, 1, 0, 0, 0, 536, 537, 1, 0, 0, 0, 537, 538, 1, 0, 0, 0, 538, 540, 3, 68, 34, 0, 539, 534, 1, 0, 0, 0, 540, 543, 1, 0, 0, 0, 541, 539, 1, 0, 0, 0, 541, 542, 1, 0, 0, 0, 542, 545, 1, 0, 0, 0, 543, 541, 1, 0, 0, 0, 544, 546, 5, 67, 0, 0, 545, 544, 1, 0, 0, 0, 545, 546, 1, 0, 0, 0, 546, 67, 1, 0, 0, 0, 547, 550, 3, 70, 35, 0, 548, 549, 5, 67, 0, 0, 549, 551, 7, 4, 0, 0, 550, 548, 1, 0, 0, 0, 550, 551, 1, 0, 0, 0, 551, 69, 1, 0, 0, 0, 552, 553, 7, 6, 0, 0, 553, 71, 1, 0, 0, 0, 554, 555, 5, 54, 0, 0, 555, 556, 5, 67, 0, 0, 556, 564, 3, 74, 37, 0, 557, 559, 5, 4, 0, 0, 558, 560, 5, 67, 0, 0, 559, 558, 1, 0, 0, 0, 559, 560, 1, 0, 0, 0, 560, 561, 1, 0, 0, 0, 561, 563, 3, 74, 37, 0, 562, 557, 1, 0, 0, 0, 563, 566, 1, 0, 0, 0, 564, 562, 1, 0, 0, 0, 564, 565, 1, 0, 0, 0, 565, 568, 1, 0, 0, 0, 566, 564, 1, 0, 0, 0, 567, 569, 5, 67, 0, 0, 568, 567, 1, 0, 0, 0, 568, 569, 1, 0, 0, 0, 569, 73, 1, 0, 0, 0, 570, 573, 3, 76, 38, 0, 571, 572, 5, 67, 0, 0, 572, 574, 7, 4, 0, 0, 573, 571, 1, 0, 0, 0, 573, 574, 1, 0, 0, 0, 574, 75, 1, 0, 0, 0, 575, 576, 7, 7, 0, 0, 576, 77, 1, 0, 0, 0, 577, 583, 3, 86, 43, 0, 578, 583, 3, 90, 45, 0, 579, 583, 3, 92, 46, 0, 580, 583, 3, 88, 44, 0, 581, 583, 3, 94, 47, 0, 582, 577, 1, 0, 0, 0, 582, 578, 1, 0, 0, 0, 582, 579, 1, 0, 0, 0, 582, 580, 1, 0, 0, 0, 582, 581, 1, 0, 0, 0, 583, 79, 1, 0, 0, 0, 584, 596, 3, 86, 43, 0, 585, 596, 3, 98, 49, 0, 586, 596, 3, 100, 50, 0, 587, 596, 3, 88, 44, 0, 588, 596, 3, 94, 47, 0, 589, 596, 3, 102, 51, 0, 590, 596, 3, 126, 63, 0, 591, 596, 3, 128, 64, 0, 592, 596, 3, 130, 65, 0, 593, 596, 3, 122, 61, 0, 594, 596, 3, 124, 62, 0, 595, 584, 1, 0, 0, 0, 595, 585, 1, 0, 0, 0, 595, 586, 1, 0, 0, 0, 595, 587, 1, 0, 0, 0, 595, 588, 1, 0, 0, 0, 595, 589, 1, 0, 0, 0, 595, 590, 1, 0, 0, 0, 595, 591, 1, 0, 0, 0, 595, 592, 1, 0, 0, 0, 595, 593, 1, 0, 0, 0, 595, 594, 1, 0, 0, 0, 596, 81, 1, 0, 0, 0, 597, 607, 3, 86, 43, 0, 598, 607, 3, 104, 52, 0, 599, 607, 3, 88, 44, 0, 600, 607, 3, 106, 53, 0, 601, 607, 3, 108, 54, 0, 602, 607, 3, 110, 55, 0, 603, 607, 3, 96, 48, 0, 604, 607, 3, 112, 56, 0, 605, 607, 3, 114, 57, 0, 606, 597, 1, 0, 0, 0, 606, 598, 1, 0, 0, 0, 606, 599, 1, 0, 0, 0, 606, 600, 1, 0, 0, 0, 606, 601, 1, 0, 0, 0, 606, 602, 1, 0, 0, 0, 606, 603, 1, 0, 0, 0, 606, 604, 1, 0, 0, 0, 606, 605, 1, 0, 0, 0, 607, 83, 1, 0, 0, 0, 608, 613, 3, 86, 43, 0, 609, 613, 3, 116, 58, 0, 610, 613, 3, 118, 59, 0, 611, 613, 3, 120, 60, 0, 612, 608, 1, 0, 0, 0, 612, 609, 1, 0, 0, 0, 612, 610, 1, 0, 0, 0, 612, 611, 1, 0, 0, 0, 613, 85, 1, 0, 0, 0, 614, 615, 5, 28, 0, 0, 615, 616, 5, 67, 0, 0, 616, 624, 3, 132, 66, 0, 617, 618, 5, 28, 0, 0, 618, 619, 5, 67, 0, 0, 619, 624, 3, 148, 74, 0, 620, 621, 5, 28, 0, 0, 621, 622, 5, 67, 0, 0, 622, 624, 3, 146, 73, 0, 623, 614, 1, 0, 0, 0, 623, 617, 1, 0, 0, 0, 623, 620, 1, 0, 0, 0, 624, 87, 1, 0, 0, 0, 625, 626, 5, 29, 0, 0, 626, 627, 5, 67, 0, 0, 627, 641, 3, 134, 67, 0, 628, 629, 5, 29, 0, 0, 629, 630, 5, 67, 0, 0, 630, 641, 3, 136, 68, 0, 631, 632, 5, 29, 0, 0, 632, 633, 5, 67, 0, 0, 633, 641, 3, 148, 74, 0, 634, 635, 5, 29, 0, 0, 635, 636, 5, 67, 0, 0, 636, 641, 3, 156, 78, 0, 637, 638, 5, 29, 0, 0, 638, 639, 5, 67, 0, 0, 639, 641, 3, 146, 73, 0, 640, 625, 1, 0, 0, 0, 640, 628, 1, 0, 0, 0, 640, 631, 1, 0, 0, 0, 640, 634, 1, 0, 0, 0, 640, 637, 1, 0, 0, 0, 641, 89, 1, 0, 0, 0, 642, 643, 5, 30, 0, 0, 643, 644, 5, 67, 0, 0, 644, 655, 3, 134, 67, 0, 645, 646, 5, 30, 0, 0, 646, 647, 5, 67, 0, 0, 647, 655, 3, 148, 74, 0, 648, 649, 5, 30, 0, 0, 649, 650, 5, 67, 0, 0, 650, 655, 3, 156, 78, 0, 651, 652, 5, 30, 0, 0, 652, 653, 5, 67, 0, 0, 653, 655, 3, 146, 73, 0, 654, 642, 1, 0, 0, 0, 654, 645, 1, 0, 0, 0, 654, 648, 1, 0, 0, 0, 654, 651, 1, 0, 0, 0, 655, 91, 1, 0, 0, 0, 656, 657, 5, 31, 0, 0, 657, 662, 5, 67, 0, 0, 658, 660, 5, 11, 0, 0, 659, 661, 5, 67, 0, 0, 660, 659, 1, 0, 0, 0, 660, 661, 1, 0, 0, 0, 661, 663, 1, 0, 0, 0, 662, 658, 1, 0, 0, 0, 662, 663, 1, 0, 0, 0, 663, 664, 1, 0, 0, 0, 664, 665, 7, 8, 0, 0, 665, 666, 5, 67, 0, 0, 666, 677, 5, 63, 0, 0, 667, 668, 5, 31, 0, 0, 668, 669, 5, 67, 0, 0, 669, 677, 3, 154, 77, 0, 670, 671, 5, 31, 0, 0, 671, 672, 5, 67, 0, 0, 672, 677, 3, 162, 81, 0, 673, 674, 5, 31, 0, 0, 674, 675, 5, 67, 0, 0, 675, 677, 3, 146, 73, 0, 676, 656, 1, 0, 0, 0, 676, 667, 1, 0, 0, 0, 676, 670, 1, 0, 0, 0, 676, 673, 1, 0, 0, 0, 677, 93, 1, 0, 0, 0, 678, 679, 5, 32, 0, 0, 679, 680, 5, 67, 0, 0, 680, 694, 3, 140, 70, 0, 681, 682, 5, 32, 0, 0, 682, 683, 5, 67, 0, 0, 683, 694, 3, 142, 71, 0, 684, 685, 5, 32, 0, 0, 685, 686, 5, 67, 0, 0, 686, 694, 3, 152, 76, 0, 687, 688, 5, 32, 0, 0, 688, 689, 5, 67, 0, 0, 689, 694, 3, 160, 80, 0, 690, 691, 5, 32, 0, 0, 691, 692, 5, 67, 0, 0, 692, 694, 3, 146, 73, 0, 693, 678, 1, 0, 0, 0, 693, 681, 1, 0, 0, 0, 693, 684, 1, 0, 0, 0, 693, 687, 1, 0, 0, 0, 693, 690, 1, 0, 0, 0, 694, 95, 1, 0, 0, 0, 695, 696, 5, 33, 0, 0, 696, 697, 5, 67, 0, 0, 697, 705, 3, 134, 67, 0, 698, 699, 5, 33, 0, 0, 699, 700, 5, 67, 0, 0, 700, 705, 3, 148, 74, 0, 701, 702, 5, 33, 0, 0, 702, 703, 5, 67, 0, 0, 703, 705, 3, 146, 73, 0, 704, 695, 1, 0, 0, 0, 704, 698, 1, 0, 0, 0, 704, 701, 1, 0, 0, 0, 705, 97, 1, 0, 0, 0, 706, 707, 5, 33, 0, 0, 707, 708, 5, 67, 0, 0, 708, 716, 3, 132, 66, 0, 709, 710, 5, 33, 0, 0, 710, 711, 5, 67, 0, 0, 711, 716, 3, 148, 74, 0, 712, 713, 5, 33, 0, 0, 713, 714, 5, 67, 0, 0, 714, 716, 3, 146, 73, 0, 715, 706, 1, 0, 0, 0, 715, 709, 1, 0, 0, 0, 715, 712, 1, 0, 0, 0, 716, 99, 1, 0, 0, 0, 717, 718, 5, 34, 0, 0, 718, 719, 5, 67, 0, 0, 719, 730, 3, 134, 67, 0, 720, 721, 5, 34, 0, 0, 721, 722, 5, 67, 0, 0, 722, 730, 3, 148, 74, 0, 723, 724, 5, 34, 0, 0, 724, 725, 5, 67, 0, 0, 725, 730, 3, 156, 78, 0, 726, 727, 5, 34, 0, 0, 727, 728, 5, 67, 0, 0, 728, 730, 3, 146, 73, 0, 729, 717, 1, 0, 0, 0, 729, 720, 1, 0, 0, 0, 729, 723, 1, 0, 0, 0, 729, 726, 1, 0, 0, 0, 730, 101, 1, 0, 0, 0, 731, 732, 5, 35, 0, 0, 732, 733, 5, 67, 0, 0, 733, 741, 3, 134, 67, 0, 734, 735, 5, 35, 0, 0, 735, 736, 5, 67, 0, 0, 736, 741, 3, 148, 74, 0, 737, 738, 5, 35, 0, 0, 738, 739, 5, 67, 0, 0, 739, 741, 3, 146, 73, 0, 740, 731, 1, 0, 0, 0, 740, 734, 1, 0, 0, 0, 740, 737, 1, 0, 0, 0, 741, 103, 1, 0, 0, 0, 742, 743, 5, 37, 0, 0, 743, 744, 5, 67, 0, 0, 744, 755, 3, 134, 67, 0, 745, 746, 5, 37, 0, 0, 746, 747, 5, 67, 0, 0, 747, 755, 3, 148, 74, 0, 748, 749, 5, 37, 0, 0, 749, 750, 5, 67, 0, 0, 750, 755, 3, 156, 78, 0, 751, 752, 5, 37, 0, 0, 752, 753, 5, 67, 0, 0, 753, 755, 3, 146, 73, 0, 754, 742, 1, 0, 0, 0, 754, 745, 1, 0, 0, 0, 754, 748, 1, 0, 0, 0, 754, 751, 1, 0, 0, 0, 755, 105, 1, 0, 0, 0, 756, 757, 5, 38, 0, 0, 757, 758, 5, 67, 0, 0, 758, 759, 5, 12, 0, 0, 759, 760, 5, 67, 0, 0, 760, 761, 7, 9, 0, 0, 761, 107, 1, 0, 0, 0, 762, 763, 5, 39, 0, 0, 763, 764, 5, 67, 0, 0, 764, 772, 3, 134, 67, 0, 765, 766, 5, 39, 0, 0, 766, 767, 5, 67, 0, 0, 767, 772, 3, 148, 74, 0, 768, 769, 5, 39, 0, 0, 769, 770, 5, 67, 0, 0, 770, 772, 3, 146, 73, 0, 771, 762, 1, 0, 0, 0, 771, 765, 1, 0, 0, 0, 771, 768, 1, 0, 0, 0, 772, 109, 1, 0, 0, 0, 773, 774, 5, 40, 0, 0, 774, 775, 5, 67, 0, 0, 775, 783, 3, 134, 67, 0, 776, 777, 5, 40, 0, 0, 777, 778, 5, 67, 0, 0, 778, 783, 3, 148, 74, 0, 779, 780, 5, 40, 0, 0, 780, 781, 5, 67, 0, 0, 781, 783, 3, 146, 73, 0, 782, 773, 1, 0, 0, 0, 782, 776, 1, 0, 0, 0, 782, 779, 1, 0, 0, 0, 783, 111, 1, 0, 0, 0, 784, 785, 5, 41, 0, 0, 785, 786, 5, 67, 0, 0, 786, 800, 3, 140, 70, 0, 787, 788, 5, 41, 0, 0, 788, 789, 5, 67, 0, 0, 789, 800, 3, 142, 71, 0, 790, 791, 5, 41, 0, 0, 791, 792, 5, 67, 0, 0, 792, 800, 3, 152, 76, 0, 793, 794, 5, 41, 0, 0, 794, 795, 5, 67, 0, 0, 795, 800, 3, 160, 80, 0, 796, 797, 5, 41, 0, 0, 797, 798, 5, 67, 0, 0, 798, 800, 3, 146, 73, 0, 799, 784, 1, 0, 0, 0, 799, 787, 1, 0, 0, 0, 799, 790, 1, 0, 0, 0, 799, 793, 1, 0, 0, 0, 799, 796, 1, 0, 0, 0, 800, 113, 1, 0, 0, 0, 801, 802, 5, 42, 0, 0, 802, 803, 5, 67, 0, 0, 803, 817, 3, 140, 70, 0, 804, 805, 5, 42, 0, 0, 805, 806, 5, 67, 0, 0, 806, 817, 3, 142, 71, 0, 807, 808, 5, 42, 0, 0, 808, 809, 5, 67, 0, 0, 809, 817, 3, 152, 76, 0, 810, 811, 5, 42, 0, 0, 811, 812, 5, 67, 0, 0, 812, 817, 3, 160, 80, 0, 813, 814, 5, 42, 0, 0, 814, 815, 5, 67, 0, 0, 815, 817, 3, 146, 73, 0, 816, 801, 1, 0, 0, 0, 816, 804, 1, 0, 0, 0, 816, 807, 1, 0, 0, 0, 816, 810, 1, 0, 0, 0, 816, 813, 1, 0, 0, 0, 817, 115, 1, 0, 0, 0, 818, 819, 5, 43, 0, 0, 819, 820, 5, 67, 0, 0, 820, 831, 3, 134, 67, 0, 821, 822, 5, 43, 0, 0, 822, 823, 5, 67, 0, 0, 823, 831, 3, 148, 74, 0, 824, 825, 5, 43, 0, 0, 825, 826, 5, 67, 0, 0, 826, 831, 3, 156, 78, 0, 827, 828, 5, 43, 0, 0, 828, 829, 5, 67, 0, 0, 829, 831, 3, 146, 73, 0, 830, 818, 1, 0, 0, 0, 830, 821, 1, 0, 0, 0, 830, 824, 1, 0, 0, 0, 830, 827, 1, 0, 0, 0, 831, 117, 1, 0, 0, 0, 832, 833, 5, 44, 0, 0, 833, 834, 5, 67, 0, 0, 834, 845, 3, 134, 67, 0, 835, 836, 5, 44, 0, 0, 836, 837, 5, 67, 0, 0, 837, 845, 3, 148, 74, 0, 838, 839, 5, 44, 0, 0, 839, 840, 5, 67, 0, 0, 840, 845, 3, 156, 78, 0, 841, 842, 5, 44, 0, 0, 842, 843, 5, 67, 0, 0, 843, 845, 3, 146, 73, 0, 844, 832, 1, 0, 0, 0, 844, 835, 1, 0, 0, 0, 844, 838, 1, 0, 0, 0, 844, 841, 1, 0, 0, 0, 845, 119, 1, 0, 0, 0, 846, 847, 5, 45, 0, 0, 847, 848, 5, 67, 0, 0, 848, 859, 3, 134, 67, 0, 849, 850, 5, 45, 0, 0, 850, 851, 5, 67, 0, 0, 851, 859, 3, 148, 74, 0, 852, 853, 5, 45, 0, 0, 853, 854, 5, 67, 0, 0, 854, 859, 3, 156, 78, 0, 855, 856, 5, 45, 0, 0, 856, 857, 5, 67, 0, 0, 857, 859, 3, 146, 73, 0, 858, 846, 1, 0, 0, 0, 858, 849, 1, 0, 0, 0, 858, 852, 1, 0, 0, 0, 858, 855, 1, 0, 0, 0, 859, 121, 1, 0, 0, 0, 860, 861, 3, 164, 82, 0, 861, 862, 5, 67, 0, 0, 862, 863, 3, 134, 67, 0, 863, 913, 1, 0, 0, 0, 864, 865, 3, 164, 82, 0, 865, 866, 5, 67, 0, 0, 866, 867, 3, 136, 68, 0, 867, 913, 1, 0, 0, 0, 868, 869, 3, 164, 82, 0, 869, 870, 5, 67, 0, 0, 870, 871, 3, 138, 69, 0, 871, 913, 1, 0, 0, 0, 872, 873, 3, 164, 82, 0, 873, 874, 5, 67, 0, 0, 874, 875, 3, 140, 70, 0, 875, 913, 1, 0, 0, 0, 876, 877, 3, 164, 82, 0, 877, 878, 5, 67, 0, 0, 878, 879, 3, 142, 71, 0, 879, 913, 1, 0, 0, 0, 880, 881, 3, 164, 82, 0, 881, 882, 5, 67, 0, 0, 882, 883, 3, 144, 72, 0, 883, 913, 1, 0, 0, 0, 884, 885, 3, 164, 82, 0, 885, 886, 5, 67, 0, 0, 886, 887, 3, 148, 74, 0, 887, 913, 1, 0, 0, 0, 888, 889, 3, 164, 82, 0, 889, 890, 5, 67, 0, 0, 890, 891, 3, 150, 75, 0, 891, 913, 1, 0, 0, 0, 892, 893, 3, 164, 82, 0, 893, 894, 5, 67, 0, 0, 894, 895, 3, 152, 76, 0, 895, 913, 1, 0, 0, 0, 896, 897, 3, 164, 82, 0, 897, 898, 5, 67, 0, 0, 898, 899, 3, 156, 78, 0, 899, 913, 1, 0, 0, 0, 900, 901, 3, 164, 82, 0, 901, 902, 5, 67, 0, 0, 902, 903, 3, 158, 79, 0, 903, 913, 1, 0, 0, 0, 904, 905, 3, 164, 82, 0, 905, 906, 5, 67, 0, 0, 906, 907, 3, 160, 80, 0, 907, 913, 1, 0, 0, 0, 908, 909, 3, 164, 82, 0, 909, 910, 5, 67, 0, 0, 910, 911, 3, 146, 73, 0, 911, 913, 1, 0, 0, 0, 912, 860, 1, 0, 0, 0, 912, 864, 1, 0, 0, 0, 912, 868, 1, 0, 0, 0, 912, 872, 1, 0, 0, 0, 912, 876, 1, 0, 0, 0, 912, 880, 1, 0, 0, 0, 912, 884, 1, 0, 0, 0, 912, 888, 1, 0, 0, 0, 912, 892, 1, 0, 0, 0, 912, 896, 1, 0, 0, 0, 912, 900, 1, 0, 0, 0, 912, 904, 1, 0, 0, 0, 912, 908, 1, 0, 0, 0, 913, 123, 1, 0, 0, 0, 914, 915, 3, 166, 83, 0, 915, 916, 5, 67, 0, 0, 916, 917, 3, 134, 67, 0, 917, 931, 1, 0, 0, 0, 918, 919, 3, 166, 83, 0, 919, 920, 5, 67, 0, 0, 920, 921, 3, 148, 74, 0, 921, 931, 1, 0, 0, 0, 922, 923, 3, 166, 83, 0, 923, 924, 5, 67, 0, 0, 924, 925, 3, 156, 78, 0, 925, 931, 1, 0, 0, 0, 926, 927, 3, 166, 83, 0, 927, 928, 5, 67, 0, 0, 928, 929, 3, 146, 73, 0, 929, 931, 1, 0, 0, 0, 930, 914, 1, 0, 0, 0, 930, 918, 1, 0, 0, 0, 930, 922, 1, 0, 0, 0, 930, 926, 1, 0, 0, 0, 931, 125, 1, 0, 0, 0, 932, 933, 3, 168, 84, 0, 933, 934, 5, 67, 0, 0, 934, 935, 3, 138, 69, 0, 935, 949, 1, 0, 0, 0, 936, 937, 3, 168, 84, 0, 937, 938, 5, 67, 0, 0, 938, 939, 3, 150, 75, 0, 939, 949, 1, 0, 0, 0, 940, 941, 3, 168, 84, 0, 941, 942, 5, 67, 0, 0, 942, 943, 3, 158, 79, 0, 943, 949, 1, 0, 0, 0, 944, 945, 3, 168, 84, 0, 945, 946, 5, 67, 0, 0, 946, 947, 3, 146, 73, 0, 947, 949, 1, 0, 0, 0, 948, 932, 1, 0, 0, 0, 948, 936, 1, 0, 0, 0, 948, 940, 1, 0, 0, 0, 948, 944, 1, 0, 0, 0, 949, 127, 1, 0, 0, 0, 950, 951, 3, 170, 85, 0, 951, 956, 5, 67, 0, 0, 952, 954, 5, 11, 0, 0, 953, 955, 5, 67, 0, 0, 954, 953, 1, 0, 0, 0, 954, 955, 1, 0, 0, 0, 955, 957, 1, 0, 0, 0, 956, 952, 1, 0, 0, 0, 956, 957, 1, 0, 0, 0, 957, 958, 1, 0, 0, 0, 958, 959, 5, 12, 0, 0, 959, 960, 5, 67, 0, 0, 960, 961, 7, 9, 0, 0, 961, 129, 1, 0, 0, 0, 962, 963, 3, 172, 86, 0, 963, 964, 5, 67, 0, 0, 964, 965, 3, 134, 67, 0, 965, 975, 1, 0, 0, 0, 966, 967, 3, 172, 86, 0, 967, 968, 5, 67, 0, 0, 968, 969, 3, 148, 74, 0, 969, 975, 1, 0, 0, 0, 970, 971, 3, 172, 86, 0, 971, 972, 5, 67, 0, 0, 972, 973, 3, 146, 73, 0, 973, 975, 1, 0, 0, 0, 974, 962, 1, 0, 0, 0, 974, 966, 1, 0, 0, 0, 974, 970, 1, 0, 0, 0, 975, 131, 1, 0, 0, 0, 976, 978, 5, 11, 0, 0, 977, 979, 5, 67, 0, 0, 978, 977, 1, 0, 0, 0, 978, 979, 1, 0, 0, 0, 979, 981, 1, 0, 0, 0, 980, 976, 1, 0, 0, 0, 980, 981, 1, 0, 0, 0, 981, 982, 1, 0, 0, 0, 982, 983, 7, 10, 0, 0, 983, 984, 5, 67, 0, 0, 984, 985, 7, 11, 0, 0, 985, 133, 1, 0, 0, 0, 986, 988, 5, 11, 0, 0, 987, 989, 5, 67, 0, 0, 988, 987, 1, 0, 0, 0, 988, 989, 1, 0, 0, 0, 989, 991, 1, 0, 0, 0, 990, 986, 1, 0, 0, 0, 990, 991, 1, 0, 0, 0, 991, 992, 1, 0, 0, 0, 992, 993, 7, 12, 0, 0, 993, 996, 5, 67, 0, 0, 994, 997, 5, 57, 0, 0, 995, 997, 3, 200, 100, 0, 996, 994, 1, 0, 0, 0, 996, 995, 1, 0, 0, 0, 997, 135, 1, 0, 0, 0, 998, 999, 3, 134, 67, 0, 999, 1000, 5, 65, 0, 0, 1000, 137, 1, 0, 0, 0, 1001, 1003, 5, 11, 0, 0, 1002, 1004, 5, 67, 0, 0, 1003, 1002, 1, 0, 0, 0, 1003, 1004, 1, 0, 0, 0, 1004, 1006, 1, 0, 0, 0, 1005, 1001, 1, 0, 0, 0, 1005, 1006, 1, 0, 0, 0, 1006, 1007, 1, 0, 0, 0, 1007, 1008, 7, 13, 0, 0, 1008, 1009, 5, 67, 0, 0, 1009, 1010, 7, 14, 0, 0, 1010, 139, 1, 0, 0, 0, 1011, 1013, 5, 11, 0, 0, 1012, 1014, 5, 67, 0, 0, 1013, 1012, 1, 0, 0, 0, 1013, 1014, 1, 0, 0, 0, 1014, 1016, 1, 0, 0, 0, 1015, 1011, 1, 0, 0, 0, 1015, 1016, 1, 0, 0, 0, 1016, 1017, 1, 0, 0, 0, 1017, 1018, 7, 13, 0, 0, 1018, 1019, 5, 67, 0, 0, 1019, 1020, 5, 61, 0, 0, 1020, 141, 1, 0, 0, 0, 1021, 1023, 5, 11, 0, 0, 1022, 1024, 5, 67, 0, 0, 1023, 1022, 1, 0, 0, 0, 1023, 1024, 1, 0, 0, 0, 1024, 1026, 1, 0, 0, 0, 1025, 1021, 1, 0, 0, 0, 1025, 1026, 1, 0, 0, 0, 1026, 1027, 1, 0, 0, 0, 1027, 1028, 7, 13, 0, 0, 1028, 1029, 5, 67, 0, 0, 1029, 1030, 5, 60, 0, 0, 1030, 143, 1, 0, 0, 0, 1031, 1033, 5, 11, 0, 0, 1032, 1034, 5, 67, 0, 0, 1033, 1032, 1, 0, 0, 0, 1033, 1034, 1, 0, 0, 0, 1034, 1036, 1, 0, 0, 0, 1035, 1031, 1, 0, 0, 0, 1035, 1036, 1, 0, 0, 0, 1036, 1037, 1, 0, 0, 0, 1037, 1038, 7, 10, 0, 0, 1038, 1039, 5, 67, 0, 0, 1039, 1040, 7, 15, 0, 0, 1040, 145, 1, 0, 0, 0, 1041, 1043, 5, 11, 0, 0, 1042, 1044, 5, 67, 0, 0, 1043, 1042, 1, 0, 0, 0, 1043, 1044, 1, 0, 0, 0, 1044, 1046, 1, 0, 0, 0, 1045, 1041, 1, 0, 0, 0, 1045, 1046, 1, 0, 0, 0, 1046, 1047, 1, 0, 0, 0, 1047, 1048, 7, 10, 0, 0, 1048, 1049, 5, 67, 0, 0, 1049, 1050, 5, 64, 0, 0, 1050, 147, 1, 0, 0, 0, 1051, 1053, 5, 11, 0, 0, 1052, 1054, 5, 67, 0, 0, 1053, 1052, 1, 0, 0, 0, 1053, 1054, 1, 0, 0, 0, 1054, 1056, 1, 0, 0, 0, 1055, 1051, 1, 0, 0, 0, 1055, 1056, 1, 0, 0, 0, 1056, 1057, 1, 0, 0, 0, 1057, 1059, 5, 19, 0, 0, 1058, 1060, 5, 67, 0, 0, 1059, 1058, 1, 0, 0, 0, 1059, 1060, 1, 0, 0, 0, 1060, 1061, 1, 0, 0, 0, 1061, 1062, 3, 176, 88, 0, 1062, 149, 1, 0, 0, 0, 1063, 1065, 5, 11, 0, 0, 1064, 1066, 5, 67, 0, 0, 1065, 1064, 1, 0, 0, 0, 1065, 1066, 1, 0, 0, 0, 1066, 1068, 1, 0, 0, 0, 1067, 1063, 1, 0, 0, 0, 1067, 1068, 1, 0, 0, 0, 1068, 1069, 1, 0, 0, 0, 1069, 1071, 5, 19, 0, 0, 1070, 1072, 5, 67, 0, 0, 1071, 1070, 1, 0, 0, 0, 1071, 1072, 1, 0, 0, 0, 1072, 1075, 1, 0, 0, 0, 1073, 1076, 3, 178, 89, 0, 1074, 1076, 3, 180, 90, 0, 1075, 1073, 1, 0, 0, 0, 1075, 1074, 1, 0, 0, 0, 1076, 151, 1, 0, 0, 0, 1077, 1079, 5, 11, 0, 0, 1078, 1080, 5, 67, 0, 0, 1079, 1078, 1, 0, 0, 0, 1079, 1080, 1, 0, 0, 0, 1080, 1082, 1, 0, 0, 0, 1081, 1077, 1, 0, 0, 0, 1081, 1082, 1, 0, 0, 0, 1082, 1083, 1, 0, 0, 0, 1083, 1085, 5, 19, 0, 0, 1084, 1086, 5, 67, 0, 0, 1085, 1084, 1, 0, 0, 0, 1085, 1086, 1, 0, 0, 0, 1086, 1089, 1, 0, 0, 0, 1087, 1090, 3, 182, 91, 0, 1088, 1090, 3, 184, 92, 0, 1089, 1087, 1, 0, 0, 0, 1089, 1088, 1, 0, 0, 0, 1090, 153, 1, 0, 0, 0, 1091, 1093, 5, 11, 0, 0, 1092, 1094, 5, 67, 0, 0, 1093, 1092, 1, 0, 0, 0, 1093, 1094, 1, 0, 0, 0, 1094, 1096, 1, 0, 0, 0, 1095, 1091, 1, 0, 0, 0, 1095, 1096, 1, 0, 0, 0, 1096, 1097, 1, 0, 0, 0, 1097, 1099, 5, 19, 0, 0, 1098, 1100, 5, 67, 0, 0, 1099, 1098, 1, 0, 0, 0, 1099, 1100, 1, 0, 0, 0, 1100, 1101, 1, 0, 0, 0, 1101, 1102, 3, 186, 93, 0, 1102, 155, 1, 0, 0, 0, 1103, 1105, 5, 11, 0, 0, 1104, 1106, 5, 67, 0, 0, 1105, 1104, 1, 0, 0, 0, 1105, 1106, 1, 0, 0, 0, 1106, 1108, 1, 0, 0, 0, 1107, 1103, 1, 0, 0, 0, 1107, 1108, 1, 0, 0, 0, 1108, 1109, 1, 0, 0, 0, 1109, 1111, 5, 19, 0, 0, 1110, 1112, 5, 67, 0, 0, 1111, 1110, 1, 0, 0, 0, 1111, 1112, 1, 0, 0, 0, 1112, 1113, 1, 0, 0, 0, 1113, 1114, 3, 188, 94, 0, 1114, 157, 1, 0, 0, 0, 1115, 1117, 5, 11, 0, 0, 1116, 1118, 5, 67, 0, 0, 1117, 1116, 1, 0, 0, 0, 1117, 1118, 1, 0, 0, 0, 1118, 1120, 1, 0, 0, 0, 1119, 1115, 1, 0, 0, 0, 1119, 1120, 1, 0, 0, 0, 1120, 1121, 1, 0, 0, 0, 1121, 1123, 5, 19, 0, 0, 1122, 1124, 5, 67, 0, 0, 1123, 1122, 1, 0, 0, 0, 1123, 1124, 1, 0, 0, 0, 1124, 1127, 1, 0, 0, 0, 1125, 1128, 3, 190, 95, 0, 1126, 1128, 3, 192, 96, 0, 1127, 1125, 1, 0, 0, 0, 1127, 1126, 1, 0, 0, 0, 1128, 159, 1, 0, 0, 0, 1129, 1131, 5, 11, 0, 0, 1130, 1132, 5, 67, 0, 0, 1131, 1130, 1, 0, 0, 0, 1131, 1132, 1, 0, 0, 0, 1132, 1134, 1, 0, 0, 0, 1133, 1129, 1, 0, 0, 0, 1133, 1134, 1, 0, 0, 0, 1134, 1135, 1, 0, 0, 0, 1135, 1137, 5, 19, 0, 0, 1136, 1138, 5, 67, 0, 0, 1137, 1136, 1, 0, 0, 0, 1137, 1138, 1, 0, 0, 0, 1138, 1141, 1, 0, 0, 0, 1139, 1142, 3, 194, 97, 0, 1140, 1142, 3, 196, 98, 0, 1141, 1139, 1, 0, 0, 0, 1141, 1140, 1, 0, 0, 0, 1142, 161, 1, 0, 0, 0, 1143, 1145, 5, 11, 0, 0, 1144, 1146, 5, 67, 0, 0, 1145, 1144, 1, 0, 0, 0, 1145, 1146, 1, 0, 0, 0, 1146, 1148, 1, 0, 0, 0, 1147, 1143, 1, 0, 0, 0, 1147, 1148, 1, 0, 0, 0, 1148, 1149, 1, 0, 0, 0, 1149, 1151, 5, 19, 0, 0, 1150, 1152, 5, 67, 0, 0, 1151, 1150, 1, 0, 0, 0, 1151, 1152, 1, 0, 0, 0, 1152, 1153, 1, 0, 0, 0, 1153, 1154, 3, 198, 99, 0, 1154, 163, 1, 0, 0, 0, 1155, 1156, 5, 46, 0, 0, 1156, 1157, 5, 5, 0, 0, 1157, 1158, 3, 174, 87, 0, 1158, 1159, 5, 5, 0, 0, 1159, 1160, 5, 47, 0, 0, 1160, 165, 1, 0, 0, 0, 1161, 1162, 5, 46, 0, 0, 1162, 1163, 5, 5, 0, 0, 1163, 1164, 3, 174, 87, 0, 1164, 1165, 5, 5, 0, 0, 1165, 1166, 5, 48, 0, 0, 1166, 167, 1, 0, 0, 0, 1167, 1168, 5, 36, 0, 0, 1168, 1169, 5, 5, 0, 0, 1169, 1170, 3, 174, 87, 0, 1170, 1171, 5, 5, 0, 0, 1171, 1172, 5, 49, 0, 0, 1172, 169, 1, 0, 0, 0, 1173, 1174, 5, 23, 0, 0, 1174, 1175, 5, 5, 0, 0, 1175, 1176, 3, 174, 87, 0, 1176, 1177, 5, 5, 0, 0, 1177, 1178, 5, 38, 0, 0, 1178, 171, 1, 0, 0, 0, 1179, 1180, 5, 23, 0, 0, 1180, 1181, 5, 5, 0, 0, 1181, 1182, 3, 174, 87, 0, 1182, 1183, 5, 5, 0, 0, 1183, 1184, 5, 39, 0, 0, 1184, 173, 1, 0, 0, 0, 1185, 1186, 7, 16, 0, 0, 1186, 175, 1, 0, 0, 0, 1187, 1189, 5, 1, 0, 0, 1188, 1190, 5, 67, 0, 0, 1189, 1188, 1, 0, 0, 0, 1189, 1190, 1, 0, 0, 0, 1190, 1214, 1, 0, 0, 0, 1191, 1194, 5, 57, 0, 0, 1192, 1194, 3, 200, 100, 0, 1193, 1191, 1, 0, 0, 0, 1193, 1192, 1, 0, 0, 0, 1194, 1196, 1, 0, 0, 0, 1195, 1197, 5, 67, 0, 0, 1196, 1195, 1, 0, 0, 0, 1196, 1197, 1, 0, 0, 0, 1197, 1211, 1, 0, 0, 0, 1198, 1200, 5, 4, 0, 0, 1199, 1201, 5, 67, 0, 0, 1200, 1199, 1, 0, 0, 0, 1200, 1201, 1, 0, 0, 0, 1201, 1204, 1, 0, 0, 0, 1202, 1205, 5, 57, 0, 0, 1203, 1205, 3, 200, 100, 0, 1204, 1202, 1, 0, 0, 0, 1204, 1203, 1, 0, 0, 0, 1205, 1207, 1, 0, 0, 0, 1206, 1208, 5, 67, 0, 0, 1207, 1206, 1, 0, 0, 0, 1207, 1208, 1, 0, 0, 0, 1208, 1210, 1, 0, 0, 0, 1209, 1198, 1, 0, 0, 0, 1210, 1213, 1, 0, 0, 0, 1211, 1209, 1, 0, 0, 0, 1211, 1212, 1, 0, 0, 0, 1212, 1215, 1, 0, 0, 0, 1213, 1211, 1, 0, 0, 0, 1214, 1193, 1, 0, 0, 0, 1214, 1215, 1, 0, 0, 0, 1215, 1217, 1, 0, 0, 0, 1216, 1218, 5, 67, 0, 0, 1217, 1216, 1, 0, 0, 0, 1217, 1218, 1, 0, 0, 0, 1218, 1219, 1, 0, 0, 0, 1219, 1220, 5, 2, 0, 0, 1220, 177, 1, 0, 0, 0, 1221, 1223, 5, 1, 0, 0, 1222, 1224, 5, 67, 0, 0, 1223, 1222, 1, 0, 0, 0, 1223, 1224, 1, 0, 0, 0, 1224, 1242, 1, 0, 0, 0, 1225, 1227, 5, 58, 0, 0, 1226, 1228, 5, 67, 0, 0, 1227, 1226, 1, 0, 0, 0, 1227, 1228, 1, 0, 0, 0, 1228, 1239, 1, 0, 0, 0, 1229, 1231, 5, 4, 0, 0, 1230, 1232, 5, 67, 0, 0, 1231, 1230, 1, 0, 0, 0, 1231, 1232, 1, 0, 0, 0, 1232, 1233, 1, 0, 0, 0, 1233, 1235, 5, 58, 0, 0, 1234, 1236, 5, 67, 0, 0, 1235, 1234, 1, 0, 0, 0, 1235, 1236, 1, 0, 0, 0, 1236, 1238, 1, 0, 0, 0, 1237, 1229, 1, 0, 0, 0, 1238, 1241, 1, 0, 0, 0, 1239, 1237, 1, 0, 0, 0, 1239, 1240, 1, 0, 0, 0, 1240, 1243, 1, 0, 0, 0, 1241, 1239, 1, 0, 0, 0, 1242, 1225, 1, 0, 0, 0, 1242, 1243, 1, 0, 0, 0, 1243, 1245, 1, 0, 0, 0, 1244, 1246, 5, 67, 0, 0, 1245, 1244, 1, 0, 0, 0, 1245, 1246, 1, 0, 0, 0, 1246, 1247, 1, 0, 0, 0, 1247, 1248, 5, 2, 0, 0, 1248, 179, 1, 0, 0, 0, 1249, 1251, 5, 1, 0, 0, 1250, 1252, 5, 67, 0, 0, 1251, 1250, 1, 0, 0, 0, 1251, 1252, 1, 0, 0, 0, 1252, 1270, 1, 0, 0, 0, 1253, 1255, 5, 59, 0, 0, 1254, 1256, 5, 67, 0, 0, 1255, 1254, 1, 0, 0, 0, 1255, 1256, 1, 0, 0, 0, 1256, 1267, 1, 0, 0, 0, 1257, 1259, 5, 4, 0, 0, 1258, 1260, 5, 67, 0, 0, 1259, 1258, 1, 0, 0, 0, 1259, 1260, 1, 0, 0, 0, 1260, 1261, 1, 0, 0, 0, 1261, 1263, 5, 59, 0, 0, 1262, 1264, 5, 67, 0, 0, 1263, 1262, 1, 0, 0, 0, 1263, 1264, 1, 0, 0, 0, 1264, 1266, 1, 0, 0, 0, 1265, 1257, 1, 0, 0, 0, 1266, 1269, 1, 0, 0, 0, 1267, 1265, 1, 0, 0, 0, 1267, 1268, 1, 0, 0, 0, 1268, 1271, 1, 0, 0, 0, 1269, 1267, 1, 0, 0, 0, 1270, 1253, 1, 0, 0, 0, 1270, 1271, 1, 0, 0, 0, 1271, 1273, 1, 0, 0, 0, 1272, 1274, 5, 67, 0, 0, 1273, 1272, 1, 0, 0, 0, 1273, 1274, 1, 0, 0, 0, 1274, 1275, 1, 0, 0, 0, 1275, 1276, 5, 2, 0, 0, 1276, 181, 1, 0, 0, 0, 1277, 1279, 5, 1, 0, 0, 1278, 1280, 5, 67, 0, 0, 1279, 1278, 1, 0, 0, 0, 1279, 1280, 1, 0, 0, 0, 1280, 1298, 1, 0, 0, 0, 1281, 1283, 5, 61, 0, 0, 1282, 1284, 5, 67, 0, 0, 1283, 1282, 1, 0, 0, 0, 1283, 1284, 1, 0, 0, 0, 1284, 1295, 1, 0, 0, 0, 1285, 1287, 5, 4, 0, 0, 1286, 1288, 5, 67, 0, 0, 1287, 1286, 1, 0, 0, 0, 1287, 1288, 1, 0, 0, 0, 1288, 1289, 1, 0, 0, 0, 1289, 1291, 5, 61, 0, 0, 1290, 1292, 5, 67, 0, 0, 1291, 1290, 1, 0, 0, 0, 1291, 1292, 1, 0, 0, 0, 1292, 1294, 1, 0, 0, 0, 1293, 1285, 1, 0, 0, 0, 1294, 1297, 1, 0, 0, 0, 1295, 1293, 1, 0, 0, 0, 1295, 1296, 1, 0, 0, 0, 1296, 1299, 1, 0, 0, 0, 1297, 1295, 1, 0, 0, 0, 1298, 1281, 1, 0, 0, 0, 1298, 1299, 1, 0, 0, 0, 1299, 1301, 1, 0, 0, 0, 1300, 1302, 5, 67, 0, 0, 1301, 1300, 1, 0, 0, 0, 1301, 1302, 1, 0, 0, 0, 1302, 1303, 1, 0, 0, 0, 1303, 1304, 5, 2, 0, 0, 1304, 183, 1, 0, 0, 0, 1305, 1307, 5, 1, 0, 0, 1306, 1308, 5, 67, 0, 0, 1307, 1306, 1, 0, 0, 0, 1307, 1308, 1, 0, 0, 0, 1308, 1326, 1, 0, 0, 0, 1309, 1311, 5, 60, 0, 0, 1310, 1312, 5, 67, 0, 0, 1311, 1310, 1, 0, 0, 0, 1311, 1312, 1, 0, 0, 0, 1312, 1323, 1, 0, 0, 0, 1313, 1315, 5, 4, 0, 0, 1314, 1316, 5, 67, 0, 0, 1315, 1314, 1, 0, 0, 0, 1315, 1316, 1, 0, 0, 0, 1316, 1317, 1, 0, 0, 0, 1317, 1319, 5, 60, 0, 0, 1318, 1320, 5, 67, 0, 0, 1319, 1318, 1, 0, 0, 0, 1319, 1320, 1, 0, 0, 0, 1320, 1322, 1, 0, 0, 0, 1321, 1313, 1, 0, 0, 0, 1322, 1325, 1, 0, 0, 0, 1323, 1321, 1, 0, 0, 0, 1323, 1324, 1, 0, 0, 0, 1324, 1327, 1, 0, 0, 0, 1325, 1323, 1, 0, 0, 0, 1326, 1309, 1, 0, 0, 0, 1326, 1327, 1, 0, 0, 0, 1327, 1329, 1, 0, 0, 0, 1328, 1330, 5, 67, 0, 0, 1329, 1328, 1, 0, 0, 0, 1329, 1330, 1, 0, 0, 0, 1330, 1331, 1, 0, 0, 0, 1331, 1332, 5, 2, 0, 0, 1332, 185, 1, 0, 0, 0, 1333, 1335, 5, 1, 0, 0, 1334, 1336, 5, 67, 0, 0, 1335, 1334, 1, 0, 0, 0, 1335, 1336, 1, 0, 0, 0, 1336, 1354, 1, 0, 0, 0, 1337, 1339, 5, 63, 0, 0, 1338, 1340, 5, 67, 0, 0, 1339, 1338, 1, 0, 0, 0, 1339, 1340, 1, 0, 0, 0, 1340, 1351, 1, 0, 0, 0, 1341, 1343, 5, 4, 0, 0, 1342, 1344, 5, 67, 0, 0, 1343, 1342, 1, 0, 0, 0, 1343, 1344, 1, 0, 0, 0, 1344, 1345, 1, 0, 0, 0, 1345, 1347, 5, 63, 0, 0, 1346, 1348, 5, 67, 0, 0, 1347, 1346, 1, 0, 0, 0, 1347, 1348, 1, 0, 0, 0, 1348, 1350, 1, 0, 0, 0, 1349, 1341, 1, 0, 0, 0, 1350, 1353, 1, 0, 0, 0, 1351, 1349, 1, 0, 0, 0, 1351, 1352, 1, 0, 0, 0, 1352, 1355, 1, 0, 0, 0, 1353, 1351, 1, 0, 0, 0, 1354, 1337, 1, 0, 0, 0, 1354, 1355, 1, 0, 0, 0, 1355, 1357, 1, 0, 0, 0, 1356, 1358, 5, 67, 0, 0, 1357, 1356, 1, 0, 0, 0, 1357, 1358, 1, 0, 0, 0, 1358, 1359, 1, 0, 0, 0, 1359, 1360, 5, 2, 0, 0, 1360, 187, 1, 0, 0, 0, 1361, 1363, 7, 17, 0, 0, 1362, 1364, 5, 67, 0, 0, 1363, 1362, 1, 0, 0, 0, 1363, 1364, 1, 0, 0, 0, 1364, 1367, 1, 0, 0, 0, 1365, 1368, 5, 57, 0, 0, 1366, 1368, 3, 200, 100, 0, 1367, 1365, 1, 0, 0, 0, 1367, 1366, 1, 0, 0, 0, 1368, 1370, 1, 0, 0, 0, 1369, 1371, 5, 67, 0, 0, 1370, 1369, 1, 0, 0, 0, 1370, 1371, 1, 0, 0, 0, 1371, 1372, 1, 0, 0, 0, 1372, 1374, 5, 3, 0, 0, 1373, 1375, 5, 67, 0, 0, 1374, 1373, 1, 0, 0, 0, 1374, 1375, 1, 0, 0, 0, 1375, 1378, 1, 0, 0, 0, 1376, 1379, 5, 57, 0, 0, 1377, 1379, 3, 200, 100, 0, 1378, 1376, 1, 0, 0, 0, 1378, 1377, 1, 0, 0, 0, 1379, 1381, 1, 0, 0, 0, 1380, 1382, 5, 67, 0, 0, 1381, 1380, 1, 0, 0, 0, 1381, 1382, 1, 0, 0, 0, 1382, 1383, 1, 0, 0, 0, 1383, 1384, 7, 18, 0, 0, 1384, 189, 1, 0, 0, 0, 1385, 1387, 7, 17, 0, 0, 1386, 1388, 5, 67, 0, 0, 1387, 1386, 1, 0, 0, 0, 1387, 1388, 1, 0, 0, 0, 1388, 1389, 1, 0, 0, 0, 1389, 1391, 5, 58, 0, 0, 1390, 1392, 5, 67, 0, 0, 1391, 1390, 1, 0, 0, 0, 1391, 1392, 1, 0, 0, 0, 1392, 1393, 1, 0, 0, 0, 1393, 1395, 5, 3, 0, 0, 1394, 1396, 5, 67, 0, 0, 1395, 1394, 1, 0, 0, 0, 1395, 1396, 1, 0, 0, 0, 1396, 1397, 1, 0, 0, 0, 1397, 1399, 5, 58, 0, 0, 1398, 1400, 5, 67, 0, 0, 1399, 1398, 1, 0, 0, 0, 1399, 1400, 1, 0, 0, 0, 1400, 1401, 1, 0, 0, 0, 1401, 1402, 7, 18, 0, 0, 1402, 191, 1, 0, 0, 0, 1403, 1405, 7, 17, 0, 0, 1404, 1406, 5, 67, 0, 0, 1405, 1404, 1, 0, 0, 0, 1405, 1406, 1, 0, 0, 0, 1406, 1407, 1, 0, 0, 0, 1407, 1409, 5, 59, 0, 0, 1408, 1410, 5, 67, 0, 0, 1409, 1408, 1, 0, 0, 0, 1409, 1410, 1, 0, 0, 0, 1410, 1411, 1, 0, 0, 0, 1411, 1413, 5, 3, 0, 0, 1412, 1414, 5, 67, 0, 0, 1413, 1412, 1, 0, 0, 0, 1413, 1414, 1, 0, 0, 0, 1414, 1415, 1, 0, 0, 0, 1415, 1417, 5, 59, 0, 0, 1416, 1418, 5, 67, 0, 0, 1417, 1416, 1, 0, 0, 0, 1417, 1418, 1, 0, 0, 0, 1418, 1419, 1, 0, 0, 0, 1419, 1420, 7, 18, 0, 0, 1420, 193, 1, 0, 0, 0, 1421, 1423, 7, 17, 0, 0, 1422, 1424, 5, 67, 0, 0, 1423, 1422, 1, 0, 0, 0, 1423, 1424, 1, 0, 0, 0, 1424, 1425, 1, 0, 0, 0, 1425, 1427, 5, 61, 0, 0, 1426, 1428, 5, 67, 0, 0, 1427, 1426, 1, 0, 0, 0, 1427, 1428, 1, 0, 0, 0, 1428, 1429, 1, 0, 0, 0, 1429, 1431, 5, 3, 0, 0, 1430, 1432, 5, 67, 0, 0, 1431, 1430, 1, 0, 0, 0, 1431, 1432, 1, 0, 0, 0, 1432, 1433, 1, 0, 0, 0, 1433, 1435, 5, 61, 0, 0, 1434, 1436, 5, 67, 0, 0, 1435, 1434, 1, 0, 0, 0, 1435, 1436, 1, 0, 0, 0, 1436, 1437, 1, 0, 0, 0, 1437, 1438, 7, 18, 0, 0, 1438, 195, 1, 0, 0, 0, 1439, 1441, 7, 17, 0, 0, 1440, 1442, 5, 67, 0, 0, 1441, 1440, 1, 0, 0, 0, 1441, 1442, 1, 0, 0, 0, 1442, 1443, 1, 0, 0, 0, 1443, 1445, 5, 60, 0, 0, 1444, 1446, 5, 67, 0, 0, 1445, 1444, 1, 0, 0, 0, 1445, 1446, 1, 0, 0, 0, 1446, 1447, 1, 0, 0, 0, 1447, 1449, 5, 3, 0, 0, 1448, 1450, 5, 67, 0, 0, 1449, 1448, 1, 0, 0, 0, 1449, 1450, 1, 0, 0, 0, 1450, 1451, 1, 0, 0, 0, 1451, 1453, 5, 60, 0, 0, 1452, 1454, 5, 67, 0, 0, 1453, 1452, 1, 0, 0, 0, 1453, 1454, 1, 0, 0, 0, 1454, 1455, 1, 0, 0, 0, 1455, 1456, 7, 18, 0, 0, 1456, 197, 1, 0, 0, 0, 1457, 1459, 7, 17, 0, 0, 1458, 1460, 5, 67, 0, 0, 1459, 1458, 1, 0, 0, 0, 1459, 1460, 1, 0, 0, 0, 1460, 1461, 1, 0, 0, 0, 1461, 1463, 5, 63, 0, 0, 1462, 1464, 5, 67, 0, 0, 1463, 1462, 1, 0, 0, 0, 1463, 1464, 1, 0, 0, 0, 1464, 1465, 1, 0, 0, 0, 1465, 1467, 5, 3, 0, 0, 1466, 1468, 5, 67, 0, 0, 1467, 1466, 1, 0, 0, 0, 1467, 1468, 1, 0, 0, 0, 1468, 1469, 1, 0, 0, 0, 1469, 1471, 5, 63, 0, 0, 1470, 1472, 5, 67, 0, 0, 1471, 1470, 1, 0, 0, 0, 1471, 1472, 1, 0, 0, 0, 1472, 1473, 1, 0, 0, 0, 1473, 1474, 7, 18, 0, 0, 1474, 199, 1, 0, 0, 0, 1475, 1476, 7, 19, 0, 0, 1476, 201, 1, 0, 0, 0, 216, 204, 209, 214, 219, 222, 226, 229, 232, 236, 239, 242, 246, 249, 252, 256, 259, 262, 273, 283, 289, 291, 295, 299, 303, 305, 309, 320, 330, 336, 338, 342, 346, 350, 352, 356, 367, 377, 383, 385, 389, 393, 397, 399, 403, 414, 424, 430, 432, 436, 440, 444, 446, 450, 456, 460, 469, 472, 479, 484, 488, 493, 502, 507, 511, 516, 529, 536, 541, 545, 550, 559, 564, 568, 573, 582, 595, 606, 612, 623, 640, 654, 660, 662, 676, 693, 704, 715, 729, 740, 754, 771, 782, 799, 816, 830, 844, 858, 912, 930, 948, 954, 956, 974, 978, 980, 988, 990, 996, 1003, 1005, 1013, 1015, 1023, 1025, 1033, 1035, 1043, 1045, 1053, 1055, 1059, 1065, 1067, 1071, 1075, 1079, 1081, 1085, 1089, 1093, 1095, 1099, 1105, 1107, 1111, 1117, 1119, 1123, 1127, 1131, 1133, 1137, 1141, 1145, 1147, 1151, 1189, 1193, 1196, 1200, 1204, 1207, 1211, 1214, 1217, 1223, 1227, 1231, 1235, 1239, 1242, 1245, 1251, 1255, 1259, 1263, 1267, 1270, 1273, 1279, 1283, 1287, 1291, 1295, 1298, 1301, 1307, 1311, 1315, 1319, 1323, 1326, 1329, 1335, 1339, 1343, 1347, 1351, 1354, 1357, 1363, 1367, 1370, 1374, 1378, 1381, 1387, 1391, 1395, 1399, 1405, 1409, 1413, 1417, 1423, 1427, 1431, 1435, 1441, 1445, 1449, 1453, 1459, 1463, 1467, 1471] \ No newline at end of file diff --git a/projects/netgrif-components-core/src/lib/pfql/generated/QueryLang.tokens b/projects/netgrif-components-core/src/lib/pfql/generated/QueryLang.tokens new file mode 100644 index 0000000000..3ea0f1ea33 --- /dev/null +++ b/projects/netgrif-components-core/src/lib/pfql/generated/QueryLang.tokens @@ -0,0 +1,80 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +T__6=7 +WHERE=8 +AND=9 +OR=10 +NOT=11 +EQ=12 +NEQ=13 +LT=14 +GT=15 +LTE=16 +GTE=17 +CONTAINS=18 +IN=19 +CASE=20 +CASES=21 +TASK=22 +TASKS=23 +USER=24 +USERS=25 +PROCESS=26 +PROCESSES=27 +ID=28 +TITLE=29 +IDENTIFIER=30 +VERSION=31 +CREATION_DATE=32 +PROCESS_ID=33 +PROCESS_IDENTIFIER=34 +AUTHOR=35 +PLACES=36 +TRANSITION_ID=37 +STATE=38 +USER_ID=39 +CASE_ID=40 +LAST_ASSIGN=41 +LAST_FINISH=42 +NAME=43 +SURNAME=44 +EMAIL=45 +DATA=46 +VALUE=47 +OPTIONS=48 +MARKING=49 +ENABLED=50 +DISABLED=51 +PAGE=52 +SIZE=53 +SORT_BY=54 +ASC=55 +DESC=56 +STRING=57 +INT=58 +DOUBLE=59 +DATETIME=60 +DATE=61 +BOOLEAN=62 +VERSION_NUMBER=63 +NULL=64 +LIKE=65 +JAVA_ID=66 +SPACE=67 +ANY=68 +LOGGED_USER_ID=69 +LOGGED_USER_FULLNAME=70 +LOGGED_USER_USERNAME=71 +LOGGED_USER_ANONYMOUS=72 +'('=1 +')'=2 +':'=3 +','=4 +'.'=5 +'['=6 +']'=7 +'*'=65 diff --git a/projects/netgrif-components-core/src/lib/pfql/generated/QueryLangLexer.interp b/projects/netgrif-components-core/src/lib/pfql/generated/QueryLangLexer.interp new file mode 100644 index 0000000000..beed49f8fd --- /dev/null +++ b/projects/netgrif-components-core/src/lib/pfql/generated/QueryLangLexer.interp @@ -0,0 +1,260 @@ +token literal names: +null +'(' +')' +':' +',' +'.' +'[' +']' +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +'*' +null +null +null +null +null +null +null + +token symbolic names: +null +null +null +null +null +null +null +null +WHERE +AND +OR +NOT +EQ +NEQ +LT +GT +LTE +GTE +CONTAINS +IN +CASE +CASES +TASK +TASKS +USER +USERS +PROCESS +PROCESSES +ID +TITLE +IDENTIFIER +VERSION +CREATION_DATE +PROCESS_ID +PROCESS_IDENTIFIER +AUTHOR +PLACES +TRANSITION_ID +STATE +USER_ID +CASE_ID +LAST_ASSIGN +LAST_FINISH +NAME +SURNAME +EMAIL +DATA +VALUE +OPTIONS +MARKING +ENABLED +DISABLED +PAGE +SIZE +SORT_BY +ASC +DESC +STRING +INT +DOUBLE +DATETIME +DATE +BOOLEAN +VERSION_NUMBER +NULL +LIKE +JAVA_ID +SPACE +ANY +LOGGED_USER_ID +LOGGED_USER_FULLNAME +LOGGED_USER_USERNAME +LOGGED_USER_ANONYMOUS + +rule names: +T__0 +T__1 +T__2 +T__3 +T__4 +T__5 +T__6 +WHERE +AND +OR +NOT +EQ +NEQ +LT +GT +LTE +GTE +CONTAINS +IN +CASE +CASES +TASK +TASKS +USER +USERS +PROCESS +PROCESSES +ID +TITLE +IDENTIFIER +VERSION +CREATION_DATE +PROCESS_ID +PROCESS_IDENTIFIER +AUTHOR +PLACES +TRANSITION_ID +STATE +USER_ID +CASE_ID +LAST_ASSIGN +LAST_FINISH +NAME +SURNAME +EMAIL +DATA +VALUE +OPTIONS +MARKING +ENABLED +DISABLED +PAGE +SIZE +SORT_BY +ASC +DESC +STRING +INT +DOUBLE +DATETIME +DATE +BOOLEAN +VERSION_NUMBER +NULL +LIKE +JAVA_ID +SPACE +ANY +LOGGED_USER_ID +LOGGED_USER_FULLNAME +LOGGED_USER_USERNAME +LOGGED_USER_ANONYMOUS +A +B +C +D +E +F +G +H +I +J +K +L +M +N +O +P +Q +R +S +T +U +V +W +X +Y +Z +DIGIT + +channel names: +DEFAULT_TOKEN_CHANNEL +HIDDEN + +mode names: +DEFAULT_MODE + +atn: +[4, 0, 72, 823, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, 2, 92, 7, 92, 2, 93, 7, 93, 2, 94, 7, 94, 2, 95, 7, 95, 2, 96, 7, 96, 2, 97, 7, 97, 2, 98, 7, 98, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 225, 8, 8, 1, 9, 1, 9, 1, 9, 1, 9, 3, 9, 231, 8, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 3, 10, 238, 8, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 3, 11, 245, 8, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 3, 12, 253, 8, 12, 1, 13, 1, 13, 1, 13, 1, 13, 3, 13, 259, 8, 13, 1, 14, 1, 14, 1, 14, 1, 14, 3, 14, 265, 8, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 3, 15, 273, 8, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 3, 16, 281, 8, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 3, 17, 293, 8, 17, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 5, 56, 579, 8, 56, 10, 56, 12, 56, 582, 9, 56, 1, 56, 1, 56, 1, 57, 4, 57, 587, 8, 57, 11, 57, 12, 57, 588, 1, 58, 4, 58, 592, 8, 58, 11, 58, 12, 58, 593, 1, 58, 1, 58, 4, 58, 598, 8, 58, 11, 58, 12, 58, 599, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 3, 59, 608, 8, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 4, 59, 618, 8, 59, 11, 59, 12, 59, 619, 3, 59, 622, 8, 59, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 3, 60, 633, 8, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 3, 60, 642, 8, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 3, 61, 655, 8, 61, 1, 62, 4, 62, 658, 8, 62, 11, 62, 12, 62, 659, 1, 62, 1, 62, 4, 62, 664, 8, 62, 11, 62, 12, 62, 665, 1, 62, 1, 62, 4, 62, 670, 8, 62, 11, 62, 12, 62, 671, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 65, 1, 65, 5, 65, 683, 8, 65, 10, 65, 12, 65, 686, 9, 65, 1, 66, 4, 66, 689, 8, 66, 11, 66, 12, 66, 690, 1, 67, 1, 67, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 72, 1, 72, 1, 73, 1, 73, 1, 74, 1, 74, 1, 75, 1, 75, 1, 76, 1, 76, 1, 77, 1, 77, 1, 78, 1, 78, 1, 79, 1, 79, 1, 80, 1, 80, 1, 81, 1, 81, 1, 82, 1, 82, 1, 83, 1, 83, 1, 84, 1, 84, 1, 85, 1, 85, 1, 86, 1, 86, 1, 87, 1, 87, 1, 88, 1, 88, 1, 89, 1, 89, 1, 90, 1, 90, 1, 91, 1, 91, 1, 92, 1, 92, 1, 93, 1, 93, 1, 94, 1, 94, 1, 95, 1, 95, 1, 96, 1, 96, 1, 97, 1, 97, 1, 98, 1, 98, 0, 0, 99, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65, 33, 67, 34, 69, 35, 71, 36, 73, 37, 75, 38, 77, 39, 79, 40, 81, 41, 83, 42, 85, 43, 87, 44, 89, 45, 91, 46, 93, 47, 95, 48, 97, 49, 99, 50, 101, 51, 103, 52, 105, 53, 107, 54, 109, 55, 111, 56, 113, 57, 115, 58, 117, 59, 119, 60, 121, 61, 123, 62, 125, 63, 127, 64, 129, 65, 131, 66, 133, 67, 135, 68, 137, 69, 139, 70, 141, 71, 143, 72, 145, 0, 147, 0, 149, 0, 151, 0, 153, 0, 155, 0, 157, 0, 159, 0, 161, 0, 163, 0, 165, 0, 167, 0, 169, 0, 171, 0, 173, 0, 175, 0, 177, 0, 179, 0, 181, 0, 183, 0, 185, 0, 187, 0, 189, 0, 191, 0, 193, 0, 195, 0, 197, 0, 1, 0, 37, 3, 0, 10, 10, 13, 13, 39, 39, 1, 0, 48, 49, 1, 0, 48, 51, 1, 0, 48, 53, 1, 0, 49, 57, 1, 0, 48, 50, 1, 0, 49, 50, 4, 0, 36, 36, 65, 90, 95, 95, 97, 122, 5, 0, 36, 36, 48, 57, 65, 90, 95, 95, 97, 122, 1, 0, 32, 32, 2, 0, 65, 65, 97, 97, 2, 0, 66, 66, 98, 98, 2, 0, 67, 67, 99, 99, 2, 0, 68, 68, 100, 100, 2, 0, 69, 69, 101, 101, 2, 0, 70, 70, 102, 102, 2, 0, 71, 71, 103, 103, 2, 0, 72, 72, 104, 104, 2, 0, 73, 73, 105, 105, 2, 0, 74, 74, 106, 106, 2, 0, 75, 75, 107, 107, 2, 0, 76, 76, 108, 108, 2, 0, 77, 77, 109, 109, 2, 0, 78, 78, 110, 110, 2, 0, 79, 79, 111, 111, 2, 0, 80, 80, 112, 112, 2, 0, 81, 81, 113, 113, 2, 0, 82, 82, 114, 114, 2, 0, 83, 83, 115, 115, 2, 0, 84, 84, 116, 116, 2, 0, 85, 85, 117, 117, 2, 0, 86, 86, 118, 118, 2, 0, 87, 87, 119, 119, 2, 0, 88, 88, 120, 120, 2, 0, 89, 89, 121, 121, 2, 0, 90, 90, 122, 122, 1, 0, 48, 57, 821, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, 0, 0, 91, 1, 0, 0, 0, 0, 93, 1, 0, 0, 0, 0, 95, 1, 0, 0, 0, 0, 97, 1, 0, 0, 0, 0, 99, 1, 0, 0, 0, 0, 101, 1, 0, 0, 0, 0, 103, 1, 0, 0, 0, 0, 105, 1, 0, 0, 0, 0, 107, 1, 0, 0, 0, 0, 109, 1, 0, 0, 0, 0, 111, 1, 0, 0, 0, 0, 113, 1, 0, 0, 0, 0, 115, 1, 0, 0, 0, 0, 117, 1, 0, 0, 0, 0, 119, 1, 0, 0, 0, 0, 121, 1, 0, 0, 0, 0, 123, 1, 0, 0, 0, 0, 125, 1, 0, 0, 0, 0, 127, 1, 0, 0, 0, 0, 129, 1, 0, 0, 0, 0, 131, 1, 0, 0, 0, 0, 133, 1, 0, 0, 0, 0, 135, 1, 0, 0, 0, 0, 137, 1, 0, 0, 0, 0, 139, 1, 0, 0, 0, 0, 141, 1, 0, 0, 0, 0, 143, 1, 0, 0, 0, 1, 199, 1, 0, 0, 0, 3, 201, 1, 0, 0, 0, 5, 203, 1, 0, 0, 0, 7, 205, 1, 0, 0, 0, 9, 207, 1, 0, 0, 0, 11, 209, 1, 0, 0, 0, 13, 211, 1, 0, 0, 0, 15, 213, 1, 0, 0, 0, 17, 224, 1, 0, 0, 0, 19, 230, 1, 0, 0, 0, 21, 237, 1, 0, 0, 0, 23, 244, 1, 0, 0, 0, 25, 252, 1, 0, 0, 0, 27, 258, 1, 0, 0, 0, 29, 264, 1, 0, 0, 0, 31, 272, 1, 0, 0, 0, 33, 280, 1, 0, 0, 0, 35, 292, 1, 0, 0, 0, 37, 294, 1, 0, 0, 0, 39, 297, 1, 0, 0, 0, 41, 302, 1, 0, 0, 0, 43, 308, 1, 0, 0, 0, 45, 313, 1, 0, 0, 0, 47, 319, 1, 0, 0, 0, 49, 324, 1, 0, 0, 0, 51, 330, 1, 0, 0, 0, 53, 338, 1, 0, 0, 0, 55, 348, 1, 0, 0, 0, 57, 351, 1, 0, 0, 0, 59, 357, 1, 0, 0, 0, 61, 368, 1, 0, 0, 0, 63, 376, 1, 0, 0, 0, 65, 389, 1, 0, 0, 0, 67, 399, 1, 0, 0, 0, 69, 417, 1, 0, 0, 0, 71, 424, 1, 0, 0, 0, 73, 431, 1, 0, 0, 0, 75, 444, 1, 0, 0, 0, 77, 450, 1, 0, 0, 0, 79, 457, 1, 0, 0, 0, 81, 464, 1, 0, 0, 0, 83, 475, 1, 0, 0, 0, 85, 486, 1, 0, 0, 0, 87, 491, 1, 0, 0, 0, 89, 499, 1, 0, 0, 0, 91, 505, 1, 0, 0, 0, 93, 510, 1, 0, 0, 0, 95, 516, 1, 0, 0, 0, 97, 524, 1, 0, 0, 0, 99, 532, 1, 0, 0, 0, 101, 540, 1, 0, 0, 0, 103, 549, 1, 0, 0, 0, 105, 554, 1, 0, 0, 0, 107, 559, 1, 0, 0, 0, 109, 567, 1, 0, 0, 0, 111, 571, 1, 0, 0, 0, 113, 576, 1, 0, 0, 0, 115, 586, 1, 0, 0, 0, 117, 591, 1, 0, 0, 0, 119, 601, 1, 0, 0, 0, 121, 623, 1, 0, 0, 0, 123, 654, 1, 0, 0, 0, 125, 657, 1, 0, 0, 0, 127, 673, 1, 0, 0, 0, 129, 678, 1, 0, 0, 0, 131, 680, 1, 0, 0, 0, 133, 688, 1, 0, 0, 0, 135, 692, 1, 0, 0, 0, 137, 694, 1, 0, 0, 0, 139, 708, 1, 0, 0, 0, 141, 728, 1, 0, 0, 0, 143, 748, 1, 0, 0, 0, 145, 769, 1, 0, 0, 0, 147, 771, 1, 0, 0, 0, 149, 773, 1, 0, 0, 0, 151, 775, 1, 0, 0, 0, 153, 777, 1, 0, 0, 0, 155, 779, 1, 0, 0, 0, 157, 781, 1, 0, 0, 0, 159, 783, 1, 0, 0, 0, 161, 785, 1, 0, 0, 0, 163, 787, 1, 0, 0, 0, 165, 789, 1, 0, 0, 0, 167, 791, 1, 0, 0, 0, 169, 793, 1, 0, 0, 0, 171, 795, 1, 0, 0, 0, 173, 797, 1, 0, 0, 0, 175, 799, 1, 0, 0, 0, 177, 801, 1, 0, 0, 0, 179, 803, 1, 0, 0, 0, 181, 805, 1, 0, 0, 0, 183, 807, 1, 0, 0, 0, 185, 809, 1, 0, 0, 0, 187, 811, 1, 0, 0, 0, 189, 813, 1, 0, 0, 0, 191, 815, 1, 0, 0, 0, 193, 817, 1, 0, 0, 0, 195, 819, 1, 0, 0, 0, 197, 821, 1, 0, 0, 0, 199, 200, 5, 40, 0, 0, 200, 2, 1, 0, 0, 0, 201, 202, 5, 41, 0, 0, 202, 4, 1, 0, 0, 0, 203, 204, 5, 58, 0, 0, 204, 6, 1, 0, 0, 0, 205, 206, 5, 44, 0, 0, 206, 8, 1, 0, 0, 0, 207, 208, 5, 46, 0, 0, 208, 10, 1, 0, 0, 0, 209, 210, 5, 91, 0, 0, 210, 12, 1, 0, 0, 0, 211, 212, 5, 93, 0, 0, 212, 14, 1, 0, 0, 0, 213, 214, 3, 189, 94, 0, 214, 215, 3, 159, 79, 0, 215, 216, 3, 153, 76, 0, 216, 217, 3, 179, 89, 0, 217, 218, 3, 153, 76, 0, 218, 16, 1, 0, 0, 0, 219, 220, 3, 145, 72, 0, 220, 221, 3, 171, 85, 0, 221, 222, 3, 151, 75, 0, 222, 225, 1, 0, 0, 0, 223, 225, 5, 38, 0, 0, 224, 219, 1, 0, 0, 0, 224, 223, 1, 0, 0, 0, 225, 18, 1, 0, 0, 0, 226, 227, 3, 173, 86, 0, 227, 228, 3, 179, 89, 0, 228, 231, 1, 0, 0, 0, 229, 231, 5, 124, 0, 0, 230, 226, 1, 0, 0, 0, 230, 229, 1, 0, 0, 0, 231, 20, 1, 0, 0, 0, 232, 233, 3, 171, 85, 0, 233, 234, 3, 173, 86, 0, 234, 235, 3, 183, 91, 0, 235, 238, 1, 0, 0, 0, 236, 238, 5, 33, 0, 0, 237, 232, 1, 0, 0, 0, 237, 236, 1, 0, 0, 0, 238, 22, 1, 0, 0, 0, 239, 240, 3, 153, 76, 0, 240, 241, 3, 177, 88, 0, 241, 245, 1, 0, 0, 0, 242, 243, 5, 61, 0, 0, 243, 245, 5, 61, 0, 0, 244, 239, 1, 0, 0, 0, 244, 242, 1, 0, 0, 0, 245, 24, 1, 0, 0, 0, 246, 247, 3, 171, 85, 0, 247, 248, 3, 153, 76, 0, 248, 249, 3, 177, 88, 0, 249, 253, 1, 0, 0, 0, 250, 251, 5, 33, 0, 0, 251, 253, 5, 61, 0, 0, 252, 246, 1, 0, 0, 0, 252, 250, 1, 0, 0, 0, 253, 26, 1, 0, 0, 0, 254, 255, 3, 167, 83, 0, 255, 256, 3, 183, 91, 0, 256, 259, 1, 0, 0, 0, 257, 259, 5, 60, 0, 0, 258, 254, 1, 0, 0, 0, 258, 257, 1, 0, 0, 0, 259, 28, 1, 0, 0, 0, 260, 261, 3, 157, 78, 0, 261, 262, 3, 183, 91, 0, 262, 265, 1, 0, 0, 0, 263, 265, 5, 62, 0, 0, 264, 260, 1, 0, 0, 0, 264, 263, 1, 0, 0, 0, 265, 30, 1, 0, 0, 0, 266, 267, 3, 167, 83, 0, 267, 268, 3, 183, 91, 0, 268, 269, 3, 153, 76, 0, 269, 273, 1, 0, 0, 0, 270, 271, 5, 60, 0, 0, 271, 273, 5, 61, 0, 0, 272, 266, 1, 0, 0, 0, 272, 270, 1, 0, 0, 0, 273, 32, 1, 0, 0, 0, 274, 275, 3, 157, 78, 0, 275, 276, 3, 183, 91, 0, 276, 277, 3, 153, 76, 0, 277, 281, 1, 0, 0, 0, 278, 279, 5, 62, 0, 0, 279, 281, 5, 61, 0, 0, 280, 274, 1, 0, 0, 0, 280, 278, 1, 0, 0, 0, 281, 34, 1, 0, 0, 0, 282, 283, 3, 149, 74, 0, 283, 284, 3, 173, 86, 0, 284, 285, 3, 171, 85, 0, 285, 286, 3, 183, 91, 0, 286, 287, 3, 145, 72, 0, 287, 288, 3, 161, 80, 0, 288, 289, 3, 171, 85, 0, 289, 290, 3, 181, 90, 0, 290, 293, 1, 0, 0, 0, 291, 293, 5, 126, 0, 0, 292, 282, 1, 0, 0, 0, 292, 291, 1, 0, 0, 0, 293, 36, 1, 0, 0, 0, 294, 295, 3, 161, 80, 0, 295, 296, 3, 171, 85, 0, 296, 38, 1, 0, 0, 0, 297, 298, 3, 149, 74, 0, 298, 299, 3, 145, 72, 0, 299, 300, 3, 181, 90, 0, 300, 301, 3, 153, 76, 0, 301, 40, 1, 0, 0, 0, 302, 303, 3, 149, 74, 0, 303, 304, 3, 145, 72, 0, 304, 305, 3, 181, 90, 0, 305, 306, 3, 153, 76, 0, 306, 307, 3, 181, 90, 0, 307, 42, 1, 0, 0, 0, 308, 309, 3, 183, 91, 0, 309, 310, 3, 145, 72, 0, 310, 311, 3, 181, 90, 0, 311, 312, 3, 165, 82, 0, 312, 44, 1, 0, 0, 0, 313, 314, 3, 183, 91, 0, 314, 315, 3, 145, 72, 0, 315, 316, 3, 181, 90, 0, 316, 317, 3, 165, 82, 0, 317, 318, 3, 181, 90, 0, 318, 46, 1, 0, 0, 0, 319, 320, 3, 185, 92, 0, 320, 321, 3, 181, 90, 0, 321, 322, 3, 153, 76, 0, 322, 323, 3, 179, 89, 0, 323, 48, 1, 0, 0, 0, 324, 325, 3, 185, 92, 0, 325, 326, 3, 181, 90, 0, 326, 327, 3, 153, 76, 0, 327, 328, 3, 179, 89, 0, 328, 329, 3, 181, 90, 0, 329, 50, 1, 0, 0, 0, 330, 331, 3, 175, 87, 0, 331, 332, 3, 179, 89, 0, 332, 333, 3, 173, 86, 0, 333, 334, 3, 149, 74, 0, 334, 335, 3, 153, 76, 0, 335, 336, 3, 181, 90, 0, 336, 337, 3, 181, 90, 0, 337, 52, 1, 0, 0, 0, 338, 339, 3, 175, 87, 0, 339, 340, 3, 179, 89, 0, 340, 341, 3, 173, 86, 0, 341, 342, 3, 149, 74, 0, 342, 343, 3, 153, 76, 0, 343, 344, 3, 181, 90, 0, 344, 345, 3, 181, 90, 0, 345, 346, 3, 153, 76, 0, 346, 347, 3, 181, 90, 0, 347, 54, 1, 0, 0, 0, 348, 349, 3, 161, 80, 0, 349, 350, 3, 151, 75, 0, 350, 56, 1, 0, 0, 0, 351, 352, 3, 183, 91, 0, 352, 353, 3, 161, 80, 0, 353, 354, 3, 183, 91, 0, 354, 355, 3, 167, 83, 0, 355, 356, 3, 153, 76, 0, 356, 58, 1, 0, 0, 0, 357, 358, 3, 161, 80, 0, 358, 359, 3, 151, 75, 0, 359, 360, 3, 153, 76, 0, 360, 361, 3, 171, 85, 0, 361, 362, 3, 183, 91, 0, 362, 363, 3, 161, 80, 0, 363, 364, 3, 155, 77, 0, 364, 365, 3, 161, 80, 0, 365, 366, 3, 153, 76, 0, 366, 367, 3, 179, 89, 0, 367, 60, 1, 0, 0, 0, 368, 369, 3, 187, 93, 0, 369, 370, 3, 153, 76, 0, 370, 371, 3, 179, 89, 0, 371, 372, 3, 181, 90, 0, 372, 373, 3, 161, 80, 0, 373, 374, 3, 173, 86, 0, 374, 375, 3, 171, 85, 0, 375, 62, 1, 0, 0, 0, 376, 377, 3, 149, 74, 0, 377, 378, 3, 179, 89, 0, 378, 379, 3, 153, 76, 0, 379, 380, 3, 145, 72, 0, 380, 381, 3, 183, 91, 0, 381, 382, 3, 161, 80, 0, 382, 383, 3, 173, 86, 0, 383, 384, 3, 171, 85, 0, 384, 385, 3, 151, 75, 0, 385, 386, 3, 145, 72, 0, 386, 387, 3, 183, 91, 0, 387, 388, 3, 153, 76, 0, 388, 64, 1, 0, 0, 0, 389, 390, 3, 175, 87, 0, 390, 391, 3, 179, 89, 0, 391, 392, 3, 173, 86, 0, 392, 393, 3, 149, 74, 0, 393, 394, 3, 153, 76, 0, 394, 395, 3, 181, 90, 0, 395, 396, 3, 181, 90, 0, 396, 397, 3, 161, 80, 0, 397, 398, 3, 151, 75, 0, 398, 66, 1, 0, 0, 0, 399, 400, 3, 175, 87, 0, 400, 401, 3, 179, 89, 0, 401, 402, 3, 173, 86, 0, 402, 403, 3, 149, 74, 0, 403, 404, 3, 153, 76, 0, 404, 405, 3, 181, 90, 0, 405, 406, 3, 181, 90, 0, 406, 407, 3, 161, 80, 0, 407, 408, 3, 151, 75, 0, 408, 409, 3, 153, 76, 0, 409, 410, 3, 171, 85, 0, 410, 411, 3, 183, 91, 0, 411, 412, 3, 161, 80, 0, 412, 413, 3, 155, 77, 0, 413, 414, 3, 161, 80, 0, 414, 415, 3, 153, 76, 0, 415, 416, 3, 179, 89, 0, 416, 68, 1, 0, 0, 0, 417, 418, 3, 145, 72, 0, 418, 419, 3, 185, 92, 0, 419, 420, 3, 183, 91, 0, 420, 421, 3, 159, 79, 0, 421, 422, 3, 173, 86, 0, 422, 423, 3, 179, 89, 0, 423, 70, 1, 0, 0, 0, 424, 425, 3, 175, 87, 0, 425, 426, 3, 167, 83, 0, 426, 427, 3, 145, 72, 0, 427, 428, 3, 149, 74, 0, 428, 429, 3, 153, 76, 0, 429, 430, 3, 181, 90, 0, 430, 72, 1, 0, 0, 0, 431, 432, 3, 183, 91, 0, 432, 433, 3, 179, 89, 0, 433, 434, 3, 145, 72, 0, 434, 435, 3, 171, 85, 0, 435, 436, 3, 181, 90, 0, 436, 437, 3, 161, 80, 0, 437, 438, 3, 183, 91, 0, 438, 439, 3, 161, 80, 0, 439, 440, 3, 173, 86, 0, 440, 441, 3, 171, 85, 0, 441, 442, 3, 161, 80, 0, 442, 443, 3, 151, 75, 0, 443, 74, 1, 0, 0, 0, 444, 445, 3, 181, 90, 0, 445, 446, 3, 183, 91, 0, 446, 447, 3, 145, 72, 0, 447, 448, 3, 183, 91, 0, 448, 449, 3, 153, 76, 0, 449, 76, 1, 0, 0, 0, 450, 451, 3, 185, 92, 0, 451, 452, 3, 181, 90, 0, 452, 453, 3, 153, 76, 0, 453, 454, 3, 179, 89, 0, 454, 455, 3, 161, 80, 0, 455, 456, 3, 151, 75, 0, 456, 78, 1, 0, 0, 0, 457, 458, 3, 149, 74, 0, 458, 459, 3, 145, 72, 0, 459, 460, 3, 181, 90, 0, 460, 461, 3, 153, 76, 0, 461, 462, 3, 161, 80, 0, 462, 463, 3, 151, 75, 0, 463, 80, 1, 0, 0, 0, 464, 465, 3, 167, 83, 0, 465, 466, 3, 145, 72, 0, 466, 467, 3, 181, 90, 0, 467, 468, 3, 183, 91, 0, 468, 469, 3, 145, 72, 0, 469, 470, 3, 181, 90, 0, 470, 471, 3, 181, 90, 0, 471, 472, 3, 161, 80, 0, 472, 473, 3, 157, 78, 0, 473, 474, 3, 171, 85, 0, 474, 82, 1, 0, 0, 0, 475, 476, 3, 167, 83, 0, 476, 477, 3, 145, 72, 0, 477, 478, 3, 181, 90, 0, 478, 479, 3, 183, 91, 0, 479, 480, 3, 155, 77, 0, 480, 481, 3, 161, 80, 0, 481, 482, 3, 171, 85, 0, 482, 483, 3, 161, 80, 0, 483, 484, 3, 181, 90, 0, 484, 485, 3, 159, 79, 0, 485, 84, 1, 0, 0, 0, 486, 487, 3, 171, 85, 0, 487, 488, 3, 145, 72, 0, 488, 489, 3, 169, 84, 0, 489, 490, 3, 153, 76, 0, 490, 86, 1, 0, 0, 0, 491, 492, 3, 181, 90, 0, 492, 493, 3, 185, 92, 0, 493, 494, 3, 179, 89, 0, 494, 495, 3, 171, 85, 0, 495, 496, 3, 145, 72, 0, 496, 497, 3, 169, 84, 0, 497, 498, 3, 153, 76, 0, 498, 88, 1, 0, 0, 0, 499, 500, 3, 153, 76, 0, 500, 501, 3, 169, 84, 0, 501, 502, 3, 145, 72, 0, 502, 503, 3, 161, 80, 0, 503, 504, 3, 167, 83, 0, 504, 90, 1, 0, 0, 0, 505, 506, 3, 151, 75, 0, 506, 507, 3, 145, 72, 0, 507, 508, 3, 183, 91, 0, 508, 509, 3, 145, 72, 0, 509, 92, 1, 0, 0, 0, 510, 511, 3, 187, 93, 0, 511, 512, 3, 145, 72, 0, 512, 513, 3, 167, 83, 0, 513, 514, 3, 185, 92, 0, 514, 515, 3, 153, 76, 0, 515, 94, 1, 0, 0, 0, 516, 517, 3, 173, 86, 0, 517, 518, 3, 175, 87, 0, 518, 519, 3, 183, 91, 0, 519, 520, 3, 161, 80, 0, 520, 521, 3, 173, 86, 0, 521, 522, 3, 171, 85, 0, 522, 523, 3, 181, 90, 0, 523, 96, 1, 0, 0, 0, 524, 525, 3, 169, 84, 0, 525, 526, 3, 145, 72, 0, 526, 527, 3, 179, 89, 0, 527, 528, 3, 165, 82, 0, 528, 529, 3, 161, 80, 0, 529, 530, 3, 171, 85, 0, 530, 531, 3, 157, 78, 0, 531, 98, 1, 0, 0, 0, 532, 533, 3, 153, 76, 0, 533, 534, 3, 171, 85, 0, 534, 535, 3, 145, 72, 0, 535, 536, 3, 147, 73, 0, 536, 537, 3, 167, 83, 0, 537, 538, 3, 153, 76, 0, 538, 539, 3, 151, 75, 0, 539, 100, 1, 0, 0, 0, 540, 541, 3, 151, 75, 0, 541, 542, 3, 161, 80, 0, 542, 543, 3, 181, 90, 0, 543, 544, 3, 145, 72, 0, 544, 545, 3, 147, 73, 0, 545, 546, 3, 167, 83, 0, 546, 547, 3, 153, 76, 0, 547, 548, 3, 151, 75, 0, 548, 102, 1, 0, 0, 0, 549, 550, 3, 175, 87, 0, 550, 551, 3, 145, 72, 0, 551, 552, 3, 157, 78, 0, 552, 553, 3, 153, 76, 0, 553, 104, 1, 0, 0, 0, 554, 555, 3, 181, 90, 0, 555, 556, 3, 161, 80, 0, 556, 557, 3, 195, 97, 0, 557, 558, 3, 153, 76, 0, 558, 106, 1, 0, 0, 0, 559, 560, 3, 181, 90, 0, 560, 561, 3, 173, 86, 0, 561, 562, 3, 179, 89, 0, 562, 563, 3, 183, 91, 0, 563, 564, 3, 133, 66, 0, 564, 565, 3, 147, 73, 0, 565, 566, 3, 193, 96, 0, 566, 108, 1, 0, 0, 0, 567, 568, 3, 145, 72, 0, 568, 569, 3, 181, 90, 0, 569, 570, 3, 149, 74, 0, 570, 110, 1, 0, 0, 0, 571, 572, 3, 151, 75, 0, 572, 573, 3, 153, 76, 0, 573, 574, 3, 181, 90, 0, 574, 575, 3, 149, 74, 0, 575, 112, 1, 0, 0, 0, 576, 580, 5, 39, 0, 0, 577, 579, 8, 0, 0, 0, 578, 577, 1, 0, 0, 0, 579, 582, 1, 0, 0, 0, 580, 578, 1, 0, 0, 0, 580, 581, 1, 0, 0, 0, 581, 583, 1, 0, 0, 0, 582, 580, 1, 0, 0, 0, 583, 584, 5, 39, 0, 0, 584, 114, 1, 0, 0, 0, 585, 587, 3, 197, 98, 0, 586, 585, 1, 0, 0, 0, 587, 588, 1, 0, 0, 0, 588, 586, 1, 0, 0, 0, 588, 589, 1, 0, 0, 0, 589, 116, 1, 0, 0, 0, 590, 592, 3, 197, 98, 0, 591, 590, 1, 0, 0, 0, 592, 593, 1, 0, 0, 0, 593, 591, 1, 0, 0, 0, 593, 594, 1, 0, 0, 0, 594, 595, 1, 0, 0, 0, 595, 597, 5, 46, 0, 0, 596, 598, 3, 197, 98, 0, 597, 596, 1, 0, 0, 0, 598, 599, 1, 0, 0, 0, 599, 597, 1, 0, 0, 0, 599, 600, 1, 0, 0, 0, 600, 118, 1, 0, 0, 0, 601, 602, 3, 121, 60, 0, 602, 607, 5, 84, 0, 0, 603, 604, 7, 1, 0, 0, 604, 608, 3, 197, 98, 0, 605, 606, 5, 50, 0, 0, 606, 608, 7, 2, 0, 0, 607, 603, 1, 0, 0, 0, 607, 605, 1, 0, 0, 0, 608, 609, 1, 0, 0, 0, 609, 610, 5, 58, 0, 0, 610, 611, 7, 3, 0, 0, 611, 612, 3, 197, 98, 0, 612, 613, 5, 58, 0, 0, 613, 614, 7, 3, 0, 0, 614, 621, 3, 197, 98, 0, 615, 617, 5, 46, 0, 0, 616, 618, 3, 197, 98, 0, 617, 616, 1, 0, 0, 0, 618, 619, 1, 0, 0, 0, 619, 617, 1, 0, 0, 0, 619, 620, 1, 0, 0, 0, 620, 622, 1, 0, 0, 0, 621, 615, 1, 0, 0, 0, 621, 622, 1, 0, 0, 0, 622, 120, 1, 0, 0, 0, 623, 624, 3, 197, 98, 0, 624, 625, 3, 197, 98, 0, 625, 626, 3, 197, 98, 0, 626, 627, 3, 197, 98, 0, 627, 632, 5, 45, 0, 0, 628, 629, 5, 48, 0, 0, 629, 633, 7, 4, 0, 0, 630, 631, 5, 49, 0, 0, 631, 633, 7, 5, 0, 0, 632, 628, 1, 0, 0, 0, 632, 630, 1, 0, 0, 0, 633, 634, 1, 0, 0, 0, 634, 641, 5, 45, 0, 0, 635, 636, 5, 48, 0, 0, 636, 642, 7, 4, 0, 0, 637, 638, 7, 6, 0, 0, 638, 642, 3, 197, 98, 0, 639, 640, 5, 51, 0, 0, 640, 642, 7, 1, 0, 0, 641, 635, 1, 0, 0, 0, 641, 637, 1, 0, 0, 0, 641, 639, 1, 0, 0, 0, 642, 122, 1, 0, 0, 0, 643, 644, 3, 183, 91, 0, 644, 645, 3, 179, 89, 0, 645, 646, 3, 185, 92, 0, 646, 647, 3, 153, 76, 0, 647, 655, 1, 0, 0, 0, 648, 649, 3, 155, 77, 0, 649, 650, 3, 145, 72, 0, 650, 651, 3, 167, 83, 0, 651, 652, 3, 181, 90, 0, 652, 653, 3, 153, 76, 0, 653, 655, 1, 0, 0, 0, 654, 643, 1, 0, 0, 0, 654, 648, 1, 0, 0, 0, 655, 124, 1, 0, 0, 0, 656, 658, 3, 197, 98, 0, 657, 656, 1, 0, 0, 0, 658, 659, 1, 0, 0, 0, 659, 657, 1, 0, 0, 0, 659, 660, 1, 0, 0, 0, 660, 661, 1, 0, 0, 0, 661, 663, 5, 46, 0, 0, 662, 664, 3, 197, 98, 0, 663, 662, 1, 0, 0, 0, 664, 665, 1, 0, 0, 0, 665, 663, 1, 0, 0, 0, 665, 666, 1, 0, 0, 0, 666, 667, 1, 0, 0, 0, 667, 669, 5, 46, 0, 0, 668, 670, 3, 197, 98, 0, 669, 668, 1, 0, 0, 0, 670, 671, 1, 0, 0, 0, 671, 669, 1, 0, 0, 0, 671, 672, 1, 0, 0, 0, 672, 126, 1, 0, 0, 0, 673, 674, 3, 171, 85, 0, 674, 675, 3, 185, 92, 0, 675, 676, 3, 167, 83, 0, 676, 677, 3, 167, 83, 0, 677, 128, 1, 0, 0, 0, 678, 679, 5, 42, 0, 0, 679, 130, 1, 0, 0, 0, 680, 684, 7, 7, 0, 0, 681, 683, 7, 8, 0, 0, 682, 681, 1, 0, 0, 0, 683, 686, 1, 0, 0, 0, 684, 682, 1, 0, 0, 0, 684, 685, 1, 0, 0, 0, 685, 132, 1, 0, 0, 0, 686, 684, 1, 0, 0, 0, 687, 689, 7, 9, 0, 0, 688, 687, 1, 0, 0, 0, 689, 690, 1, 0, 0, 0, 690, 688, 1, 0, 0, 0, 690, 691, 1, 0, 0, 0, 691, 134, 1, 0, 0, 0, 692, 693, 9, 0, 0, 0, 693, 136, 1, 0, 0, 0, 694, 695, 3, 167, 83, 0, 695, 696, 3, 173, 86, 0, 696, 697, 3, 157, 78, 0, 697, 698, 3, 157, 78, 0, 698, 699, 3, 153, 76, 0, 699, 700, 3, 151, 75, 0, 700, 701, 3, 185, 92, 0, 701, 702, 3, 181, 90, 0, 702, 703, 3, 153, 76, 0, 703, 704, 3, 179, 89, 0, 704, 705, 5, 46, 0, 0, 705, 706, 3, 161, 80, 0, 706, 707, 3, 151, 75, 0, 707, 138, 1, 0, 0, 0, 708, 709, 3, 167, 83, 0, 709, 710, 3, 173, 86, 0, 710, 711, 3, 157, 78, 0, 711, 712, 3, 157, 78, 0, 712, 713, 3, 153, 76, 0, 713, 714, 3, 151, 75, 0, 714, 715, 3, 185, 92, 0, 715, 716, 3, 181, 90, 0, 716, 717, 3, 153, 76, 0, 717, 718, 3, 179, 89, 0, 718, 719, 5, 46, 0, 0, 719, 720, 3, 155, 77, 0, 720, 721, 3, 185, 92, 0, 721, 722, 3, 167, 83, 0, 722, 723, 3, 167, 83, 0, 723, 724, 3, 171, 85, 0, 724, 725, 3, 145, 72, 0, 725, 726, 3, 169, 84, 0, 726, 727, 3, 153, 76, 0, 727, 140, 1, 0, 0, 0, 728, 729, 3, 167, 83, 0, 729, 730, 3, 173, 86, 0, 730, 731, 3, 157, 78, 0, 731, 732, 3, 157, 78, 0, 732, 733, 3, 153, 76, 0, 733, 734, 3, 151, 75, 0, 734, 735, 3, 185, 92, 0, 735, 736, 3, 181, 90, 0, 736, 737, 3, 153, 76, 0, 737, 738, 3, 179, 89, 0, 738, 739, 5, 46, 0, 0, 739, 740, 3, 185, 92, 0, 740, 741, 3, 181, 90, 0, 741, 742, 3, 153, 76, 0, 742, 743, 3, 179, 89, 0, 743, 744, 3, 171, 85, 0, 744, 745, 3, 145, 72, 0, 745, 746, 3, 169, 84, 0, 746, 747, 3, 153, 76, 0, 747, 142, 1, 0, 0, 0, 748, 749, 3, 167, 83, 0, 749, 750, 3, 173, 86, 0, 750, 751, 3, 157, 78, 0, 751, 752, 3, 157, 78, 0, 752, 753, 3, 153, 76, 0, 753, 754, 3, 151, 75, 0, 754, 755, 3, 185, 92, 0, 755, 756, 3, 181, 90, 0, 756, 757, 3, 153, 76, 0, 757, 758, 3, 179, 89, 0, 758, 759, 5, 46, 0, 0, 759, 760, 3, 145, 72, 0, 760, 761, 3, 171, 85, 0, 761, 762, 3, 173, 86, 0, 762, 763, 3, 171, 85, 0, 763, 764, 3, 193, 96, 0, 764, 765, 3, 169, 84, 0, 765, 766, 3, 173, 86, 0, 766, 767, 3, 185, 92, 0, 767, 768, 3, 181, 90, 0, 768, 144, 1, 0, 0, 0, 769, 770, 7, 10, 0, 0, 770, 146, 1, 0, 0, 0, 771, 772, 7, 11, 0, 0, 772, 148, 1, 0, 0, 0, 773, 774, 7, 12, 0, 0, 774, 150, 1, 0, 0, 0, 775, 776, 7, 13, 0, 0, 776, 152, 1, 0, 0, 0, 777, 778, 7, 14, 0, 0, 778, 154, 1, 0, 0, 0, 779, 780, 7, 15, 0, 0, 780, 156, 1, 0, 0, 0, 781, 782, 7, 16, 0, 0, 782, 158, 1, 0, 0, 0, 783, 784, 7, 17, 0, 0, 784, 160, 1, 0, 0, 0, 785, 786, 7, 18, 0, 0, 786, 162, 1, 0, 0, 0, 787, 788, 7, 19, 0, 0, 788, 164, 1, 0, 0, 0, 789, 790, 7, 20, 0, 0, 790, 166, 1, 0, 0, 0, 791, 792, 7, 21, 0, 0, 792, 168, 1, 0, 0, 0, 793, 794, 7, 22, 0, 0, 794, 170, 1, 0, 0, 0, 795, 796, 7, 23, 0, 0, 796, 172, 1, 0, 0, 0, 797, 798, 7, 24, 0, 0, 798, 174, 1, 0, 0, 0, 799, 800, 7, 25, 0, 0, 800, 176, 1, 0, 0, 0, 801, 802, 7, 26, 0, 0, 802, 178, 1, 0, 0, 0, 803, 804, 7, 27, 0, 0, 804, 180, 1, 0, 0, 0, 805, 806, 7, 28, 0, 0, 806, 182, 1, 0, 0, 0, 807, 808, 7, 29, 0, 0, 808, 184, 1, 0, 0, 0, 809, 810, 7, 30, 0, 0, 810, 186, 1, 0, 0, 0, 811, 812, 7, 31, 0, 0, 812, 188, 1, 0, 0, 0, 813, 814, 7, 32, 0, 0, 814, 190, 1, 0, 0, 0, 815, 816, 7, 33, 0, 0, 816, 192, 1, 0, 0, 0, 817, 818, 7, 34, 0, 0, 818, 194, 1, 0, 0, 0, 819, 820, 7, 35, 0, 0, 820, 196, 1, 0, 0, 0, 821, 822, 7, 36, 0, 0, 822, 198, 1, 0, 0, 0, 26, 0, 224, 230, 237, 244, 252, 258, 264, 272, 280, 292, 580, 588, 593, 599, 607, 619, 621, 632, 641, 654, 659, 665, 671, 684, 690, 0] \ No newline at end of file diff --git a/projects/netgrif-components-core/src/lib/pfql/generated/QueryLangLexer.tokens b/projects/netgrif-components-core/src/lib/pfql/generated/QueryLangLexer.tokens new file mode 100644 index 0000000000..3ea0f1ea33 --- /dev/null +++ b/projects/netgrif-components-core/src/lib/pfql/generated/QueryLangLexer.tokens @@ -0,0 +1,80 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +T__6=7 +WHERE=8 +AND=9 +OR=10 +NOT=11 +EQ=12 +NEQ=13 +LT=14 +GT=15 +LTE=16 +GTE=17 +CONTAINS=18 +IN=19 +CASE=20 +CASES=21 +TASK=22 +TASKS=23 +USER=24 +USERS=25 +PROCESS=26 +PROCESSES=27 +ID=28 +TITLE=29 +IDENTIFIER=30 +VERSION=31 +CREATION_DATE=32 +PROCESS_ID=33 +PROCESS_IDENTIFIER=34 +AUTHOR=35 +PLACES=36 +TRANSITION_ID=37 +STATE=38 +USER_ID=39 +CASE_ID=40 +LAST_ASSIGN=41 +LAST_FINISH=42 +NAME=43 +SURNAME=44 +EMAIL=45 +DATA=46 +VALUE=47 +OPTIONS=48 +MARKING=49 +ENABLED=50 +DISABLED=51 +PAGE=52 +SIZE=53 +SORT_BY=54 +ASC=55 +DESC=56 +STRING=57 +INT=58 +DOUBLE=59 +DATETIME=60 +DATE=61 +BOOLEAN=62 +VERSION_NUMBER=63 +NULL=64 +LIKE=65 +JAVA_ID=66 +SPACE=67 +ANY=68 +LOGGED_USER_ID=69 +LOGGED_USER_FULLNAME=70 +LOGGED_USER_USERNAME=71 +LOGGED_USER_ANONYMOUS=72 +'('=1 +')'=2 +':'=3 +','=4 +'.'=5 +'['=6 +']'=7 +'*'=65 diff --git a/projects/netgrif-components-core/src/lib/pfql/generated/QueryLangLexer.ts b/projects/netgrif-components-core/src/lib/pfql/generated/QueryLangLexer.ts new file mode 100644 index 0000000000..85df87786a --- /dev/null +++ b/projects/netgrif-components-core/src/lib/pfql/generated/QueryLangLexer.ts @@ -0,0 +1,468 @@ + +import * as antlr from "antlr4ng"; +import { Token } from "antlr4ng"; + + +export class QueryLangLexer extends antlr.Lexer { + public static readonly T__0 = 1; + public static readonly T__1 = 2; + public static readonly T__2 = 3; + public static readonly T__3 = 4; + public static readonly T__4 = 5; + public static readonly T__5 = 6; + public static readonly T__6 = 7; + public static readonly WHERE = 8; + public static readonly AND = 9; + public static readonly OR = 10; + public static readonly NOT = 11; + public static readonly EQ = 12; + public static readonly NEQ = 13; + public static readonly LT = 14; + public static readonly GT = 15; + public static readonly LTE = 16; + public static readonly GTE = 17; + public static readonly CONTAINS = 18; + public static readonly IN = 19; + public static readonly CASE = 20; + public static readonly CASES = 21; + public static readonly TASK = 22; + public static readonly TASKS = 23; + public static readonly USER = 24; + public static readonly USERS = 25; + public static readonly PROCESS = 26; + public static readonly PROCESSES = 27; + public static readonly ID = 28; + public static readonly TITLE = 29; + public static readonly IDENTIFIER = 30; + public static readonly VERSION = 31; + public static readonly CREATION_DATE = 32; + public static readonly PROCESS_ID = 33; + public static readonly PROCESS_IDENTIFIER = 34; + public static readonly AUTHOR = 35; + public static readonly PLACES = 36; + public static readonly TRANSITION_ID = 37; + public static readonly STATE = 38; + public static readonly USER_ID = 39; + public static readonly CASE_ID = 40; + public static readonly LAST_ASSIGN = 41; + public static readonly LAST_FINISH = 42; + public static readonly NAME = 43; + public static readonly SURNAME = 44; + public static readonly EMAIL = 45; + public static readonly DATA = 46; + public static readonly VALUE = 47; + public static readonly OPTIONS = 48; + public static readonly MARKING = 49; + public static readonly ENABLED = 50; + public static readonly DISABLED = 51; + public static readonly PAGE = 52; + public static readonly SIZE = 53; + public static readonly SORT_BY = 54; + public static readonly ASC = 55; + public static readonly DESC = 56; + public static readonly STRING = 57; + public static readonly INT = 58; + public static readonly DOUBLE = 59; + public static readonly DATETIME = 60; + public static readonly DATE = 61; + public static readonly BOOLEAN = 62; + public static readonly VERSION_NUMBER = 63; + public static readonly NULL = 64; + public static readonly LIKE = 65; + public static readonly JAVA_ID = 66; + public static readonly SPACE = 67; + public static readonly ANY = 68; + public static readonly LOGGED_USER_ID = 69; + public static readonly LOGGED_USER_FULLNAME = 70; + public static readonly LOGGED_USER_USERNAME = 71; + public static readonly LOGGED_USER_ANONYMOUS = 72; + + public static readonly channelNames = [ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN" + ]; + + public static readonly literalNames = [ + null, "'('", "')'", "':'", "','", "'.'", "'['", "']'", null, null, + null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, + "'*'" + ]; + + public static readonly symbolicNames = [ + null, null, null, null, null, null, null, null, "WHERE", "AND", + "OR", "NOT", "EQ", "NEQ", "LT", "GT", "LTE", "GTE", "CONTAINS", + "IN", "CASE", "CASES", "TASK", "TASKS", "USER", "USERS", "PROCESS", + "PROCESSES", "ID", "TITLE", "IDENTIFIER", "VERSION", "CREATION_DATE", + "PROCESS_ID", "PROCESS_IDENTIFIER", "AUTHOR", "PLACES", "TRANSITION_ID", + "STATE", "USER_ID", "CASE_ID", "LAST_ASSIGN", "LAST_FINISH", "NAME", + "SURNAME", "EMAIL", "DATA", "VALUE", "OPTIONS", "MARKING", "ENABLED", + "DISABLED", "PAGE", "SIZE", "SORT_BY", "ASC", "DESC", "STRING", + "INT", "DOUBLE", "DATETIME", "DATE", "BOOLEAN", "VERSION_NUMBER", + "NULL", "LIKE", "JAVA_ID", "SPACE", "ANY", "LOGGED_USER_ID", "LOGGED_USER_FULLNAME", + "LOGGED_USER_USERNAME", "LOGGED_USER_ANONYMOUS" + ]; + + public static readonly modeNames = [ + "DEFAULT_MODE", + ]; + + public static readonly ruleNames = [ + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "WHERE", + "AND", "OR", "NOT", "EQ", "NEQ", "LT", "GT", "LTE", "GTE", "CONTAINS", + "IN", "CASE", "CASES", "TASK", "TASKS", "USER", "USERS", "PROCESS", + "PROCESSES", "ID", "TITLE", "IDENTIFIER", "VERSION", "CREATION_DATE", + "PROCESS_ID", "PROCESS_IDENTIFIER", "AUTHOR", "PLACES", "TRANSITION_ID", + "STATE", "USER_ID", "CASE_ID", "LAST_ASSIGN", "LAST_FINISH", "NAME", + "SURNAME", "EMAIL", "DATA", "VALUE", "OPTIONS", "MARKING", "ENABLED", + "DISABLED", "PAGE", "SIZE", "SORT_BY", "ASC", "DESC", "STRING", + "INT", "DOUBLE", "DATETIME", "DATE", "BOOLEAN", "VERSION_NUMBER", + "NULL", "LIKE", "JAVA_ID", "SPACE", "ANY", "LOGGED_USER_ID", "LOGGED_USER_FULLNAME", + "LOGGED_USER_USERNAME", "LOGGED_USER_ANONYMOUS", "A", "B", "C", + "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", + "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "DIGIT", + ]; + + + public constructor(input: antlr.CharStream) { + super(input); + this.interpreter = new antlr.LexerATNSimulator(this, QueryLangLexer._ATN, QueryLangLexer.decisionsToDFA, new antlr.PredictionContextCache()); + } + + public get grammarFileName(): string { return "QueryLang.g4"; } + + public get literalNames(): (string | null)[] { return QueryLangLexer.literalNames; } + public get symbolicNames(): (string | null)[] { return QueryLangLexer.symbolicNames; } + public get ruleNames(): string[] { return QueryLangLexer.ruleNames; } + + public get serializedATN(): number[] { return QueryLangLexer._serializedATN; } + + public get channelNames(): string[] { return QueryLangLexer.channelNames; } + + public get modeNames(): string[] { return QueryLangLexer.modeNames; } + + public static readonly _serializedATN: number[] = [ + 4,0,72,823,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5, + 2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2, + 13,7,13,2,14,7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7, + 19,2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2, + 26,7,26,2,27,7,27,2,28,7,28,2,29,7,29,2,30,7,30,2,31,7,31,2,32,7, + 32,2,33,7,33,2,34,7,34,2,35,7,35,2,36,7,36,2,37,7,37,2,38,7,38,2, + 39,7,39,2,40,7,40,2,41,7,41,2,42,7,42,2,43,7,43,2,44,7,44,2,45,7, + 45,2,46,7,46,2,47,7,47,2,48,7,48,2,49,7,49,2,50,7,50,2,51,7,51,2, + 52,7,52,2,53,7,53,2,54,7,54,2,55,7,55,2,56,7,56,2,57,7,57,2,58,7, + 58,2,59,7,59,2,60,7,60,2,61,7,61,2,62,7,62,2,63,7,63,2,64,7,64,2, + 65,7,65,2,66,7,66,2,67,7,67,2,68,7,68,2,69,7,69,2,70,7,70,2,71,7, + 71,2,72,7,72,2,73,7,73,2,74,7,74,2,75,7,75,2,76,7,76,2,77,7,77,2, + 78,7,78,2,79,7,79,2,80,7,80,2,81,7,81,2,82,7,82,2,83,7,83,2,84,7, + 84,2,85,7,85,2,86,7,86,2,87,7,87,2,88,7,88,2,89,7,89,2,90,7,90,2, + 91,7,91,2,92,7,92,2,93,7,93,2,94,7,94,2,95,7,95,2,96,7,96,2,97,7, + 97,2,98,7,98,1,0,1,0,1,1,1,1,1,2,1,2,1,3,1,3,1,4,1,4,1,5,1,5,1,6, + 1,6,1,7,1,7,1,7,1,7,1,7,1,7,1,8,1,8,1,8,1,8,1,8,3,8,225,8,8,1,9, + 1,9,1,9,1,9,3,9,231,8,9,1,10,1,10,1,10,1,10,1,10,3,10,238,8,10,1, + 11,1,11,1,11,1,11,1,11,3,11,245,8,11,1,12,1,12,1,12,1,12,1,12,1, + 12,3,12,253,8,12,1,13,1,13,1,13,1,13,3,13,259,8,13,1,14,1,14,1,14, + 1,14,3,14,265,8,14,1,15,1,15,1,15,1,15,1,15,1,15,3,15,273,8,15,1, + 16,1,16,1,16,1,16,1,16,1,16,3,16,281,8,16,1,17,1,17,1,17,1,17,1, + 17,1,17,1,17,1,17,1,17,1,17,3,17,293,8,17,1,18,1,18,1,18,1,19,1, + 19,1,19,1,19,1,19,1,20,1,20,1,20,1,20,1,20,1,20,1,21,1,21,1,21,1, + 21,1,21,1,22,1,22,1,22,1,22,1,22,1,22,1,23,1,23,1,23,1,23,1,23,1, + 24,1,24,1,24,1,24,1,24,1,24,1,25,1,25,1,25,1,25,1,25,1,25,1,25,1, + 25,1,26,1,26,1,26,1,26,1,26,1,26,1,26,1,26,1,26,1,26,1,27,1,27,1, + 27,1,28,1,28,1,28,1,28,1,28,1,28,1,29,1,29,1,29,1,29,1,29,1,29,1, + 29,1,29,1,29,1,29,1,29,1,30,1,30,1,30,1,30,1,30,1,30,1,30,1,30,1, + 31,1,31,1,31,1,31,1,31,1,31,1,31,1,31,1,31,1,31,1,31,1,31,1,31,1, + 32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,33,1,33,1,33,1, + 33,1,33,1,33,1,33,1,33,1,33,1,33,1,33,1,33,1,33,1,33,1,33,1,33,1, + 33,1,33,1,34,1,34,1,34,1,34,1,34,1,34,1,34,1,35,1,35,1,35,1,35,1, + 35,1,35,1,35,1,36,1,36,1,36,1,36,1,36,1,36,1,36,1,36,1,36,1,36,1, + 36,1,36,1,36,1,37,1,37,1,37,1,37,1,37,1,37,1,38,1,38,1,38,1,38,1, + 38,1,38,1,38,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,40,1,40,1,40,1, + 40,1,40,1,40,1,40,1,40,1,40,1,40,1,40,1,41,1,41,1,41,1,41,1,41,1, + 41,1,41,1,41,1,41,1,41,1,41,1,42,1,42,1,42,1,42,1,42,1,43,1,43,1, + 43,1,43,1,43,1,43,1,43,1,43,1,44,1,44,1,44,1,44,1,44,1,44,1,45,1, + 45,1,45,1,45,1,45,1,46,1,46,1,46,1,46,1,46,1,46,1,47,1,47,1,47,1, + 47,1,47,1,47,1,47,1,47,1,48,1,48,1,48,1,48,1,48,1,48,1,48,1,48,1, + 49,1,49,1,49,1,49,1,49,1,49,1,49,1,49,1,50,1,50,1,50,1,50,1,50,1, + 50,1,50,1,50,1,50,1,51,1,51,1,51,1,51,1,51,1,52,1,52,1,52,1,52,1, + 52,1,53,1,53,1,53,1,53,1,53,1,53,1,53,1,53,1,54,1,54,1,54,1,54,1, + 55,1,55,1,55,1,55,1,55,1,56,1,56,5,56,579,8,56,10,56,12,56,582,9, + 56,1,56,1,56,1,57,4,57,587,8,57,11,57,12,57,588,1,58,4,58,592,8, + 58,11,58,12,58,593,1,58,1,58,4,58,598,8,58,11,58,12,58,599,1,59, + 1,59,1,59,1,59,1,59,1,59,3,59,608,8,59,1,59,1,59,1,59,1,59,1,59, + 1,59,1,59,1,59,4,59,618,8,59,11,59,12,59,619,3,59,622,8,59,1,60, + 1,60,1,60,1,60,1,60,1,60,1,60,1,60,1,60,3,60,633,8,60,1,60,1,60, + 1,60,1,60,1,60,1,60,1,60,3,60,642,8,60,1,61,1,61,1,61,1,61,1,61, + 1,61,1,61,1,61,1,61,1,61,1,61,3,61,655,8,61,1,62,4,62,658,8,62,11, + 62,12,62,659,1,62,1,62,4,62,664,8,62,11,62,12,62,665,1,62,1,62,4, + 62,670,8,62,11,62,12,62,671,1,63,1,63,1,63,1,63,1,63,1,64,1,64,1, + 65,1,65,5,65,683,8,65,10,65,12,65,686,9,65,1,66,4,66,689,8,66,11, + 66,12,66,690,1,67,1,67,1,68,1,68,1,68,1,68,1,68,1,68,1,68,1,68,1, + 68,1,68,1,68,1,68,1,68,1,68,1,69,1,69,1,69,1,69,1,69,1,69,1,69,1, + 69,1,69,1,69,1,69,1,69,1,69,1,69,1,69,1,69,1,69,1,69,1,69,1,69,1, + 70,1,70,1,70,1,70,1,70,1,70,1,70,1,70,1,70,1,70,1,70,1,70,1,70,1, + 70,1,70,1,70,1,70,1,70,1,70,1,70,1,71,1,71,1,71,1,71,1,71,1,71,1, + 71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1, + 71,1,71,1,72,1,72,1,73,1,73,1,74,1,74,1,75,1,75,1,76,1,76,1,77,1, + 77,1,78,1,78,1,79,1,79,1,80,1,80,1,81,1,81,1,82,1,82,1,83,1,83,1, + 84,1,84,1,85,1,85,1,86,1,86,1,87,1,87,1,88,1,88,1,89,1,89,1,90,1, + 90,1,91,1,91,1,92,1,92,1,93,1,93,1,94,1,94,1,95,1,95,1,96,1,96,1, + 97,1,97,1,98,1,98,0,0,99,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,17,9, + 19,10,21,11,23,12,25,13,27,14,29,15,31,16,33,17,35,18,37,19,39,20, + 41,21,43,22,45,23,47,24,49,25,51,26,53,27,55,28,57,29,59,30,61,31, + 63,32,65,33,67,34,69,35,71,36,73,37,75,38,77,39,79,40,81,41,83,42, + 85,43,87,44,89,45,91,46,93,47,95,48,97,49,99,50,101,51,103,52,105, + 53,107,54,109,55,111,56,113,57,115,58,117,59,119,60,121,61,123,62, + 125,63,127,64,129,65,131,66,133,67,135,68,137,69,139,70,141,71,143, + 72,145,0,147,0,149,0,151,0,153,0,155,0,157,0,159,0,161,0,163,0,165, + 0,167,0,169,0,171,0,173,0,175,0,177,0,179,0,181,0,183,0,185,0,187, + 0,189,0,191,0,193,0,195,0,197,0,1,0,37,3,0,10,10,13,13,39,39,1,0, + 48,49,1,0,48,51,1,0,48,53,1,0,49,57,1,0,48,50,1,0,49,50,4,0,36,36, + 65,90,95,95,97,122,5,0,36,36,48,57,65,90,95,95,97,122,1,0,32,32, + 2,0,65,65,97,97,2,0,66,66,98,98,2,0,67,67,99,99,2,0,68,68,100,100, + 2,0,69,69,101,101,2,0,70,70,102,102,2,0,71,71,103,103,2,0,72,72, + 104,104,2,0,73,73,105,105,2,0,74,74,106,106,2,0,75,75,107,107,2, + 0,76,76,108,108,2,0,77,77,109,109,2,0,78,78,110,110,2,0,79,79,111, + 111,2,0,80,80,112,112,2,0,81,81,113,113,2,0,82,82,114,114,2,0,83, + 83,115,115,2,0,84,84,116,116,2,0,85,85,117,117,2,0,86,86,118,118, + 2,0,87,87,119,119,2,0,88,88,120,120,2,0,89,89,121,121,2,0,90,90, + 122,122,1,0,48,57,821,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1, + 0,0,0,0,9,1,0,0,0,0,11,1,0,0,0,0,13,1,0,0,0,0,15,1,0,0,0,0,17,1, + 0,0,0,0,19,1,0,0,0,0,21,1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0,0,27,1, + 0,0,0,0,29,1,0,0,0,0,31,1,0,0,0,0,33,1,0,0,0,0,35,1,0,0,0,0,37,1, + 0,0,0,0,39,1,0,0,0,0,41,1,0,0,0,0,43,1,0,0,0,0,45,1,0,0,0,0,47,1, + 0,0,0,0,49,1,0,0,0,0,51,1,0,0,0,0,53,1,0,0,0,0,55,1,0,0,0,0,57,1, + 0,0,0,0,59,1,0,0,0,0,61,1,0,0,0,0,63,1,0,0,0,0,65,1,0,0,0,0,67,1, + 0,0,0,0,69,1,0,0,0,0,71,1,0,0,0,0,73,1,0,0,0,0,75,1,0,0,0,0,77,1, + 0,0,0,0,79,1,0,0,0,0,81,1,0,0,0,0,83,1,0,0,0,0,85,1,0,0,0,0,87,1, + 0,0,0,0,89,1,0,0,0,0,91,1,0,0,0,0,93,1,0,0,0,0,95,1,0,0,0,0,97,1, + 0,0,0,0,99,1,0,0,0,0,101,1,0,0,0,0,103,1,0,0,0,0,105,1,0,0,0,0,107, + 1,0,0,0,0,109,1,0,0,0,0,111,1,0,0,0,0,113,1,0,0,0,0,115,1,0,0,0, + 0,117,1,0,0,0,0,119,1,0,0,0,0,121,1,0,0,0,0,123,1,0,0,0,0,125,1, + 0,0,0,0,127,1,0,0,0,0,129,1,0,0,0,0,131,1,0,0,0,0,133,1,0,0,0,0, + 135,1,0,0,0,0,137,1,0,0,0,0,139,1,0,0,0,0,141,1,0,0,0,0,143,1,0, + 0,0,1,199,1,0,0,0,3,201,1,0,0,0,5,203,1,0,0,0,7,205,1,0,0,0,9,207, + 1,0,0,0,11,209,1,0,0,0,13,211,1,0,0,0,15,213,1,0,0,0,17,224,1,0, + 0,0,19,230,1,0,0,0,21,237,1,0,0,0,23,244,1,0,0,0,25,252,1,0,0,0, + 27,258,1,0,0,0,29,264,1,0,0,0,31,272,1,0,0,0,33,280,1,0,0,0,35,292, + 1,0,0,0,37,294,1,0,0,0,39,297,1,0,0,0,41,302,1,0,0,0,43,308,1,0, + 0,0,45,313,1,0,0,0,47,319,1,0,0,0,49,324,1,0,0,0,51,330,1,0,0,0, + 53,338,1,0,0,0,55,348,1,0,0,0,57,351,1,0,0,0,59,357,1,0,0,0,61,368, + 1,0,0,0,63,376,1,0,0,0,65,389,1,0,0,0,67,399,1,0,0,0,69,417,1,0, + 0,0,71,424,1,0,0,0,73,431,1,0,0,0,75,444,1,0,0,0,77,450,1,0,0,0, + 79,457,1,0,0,0,81,464,1,0,0,0,83,475,1,0,0,0,85,486,1,0,0,0,87,491, + 1,0,0,0,89,499,1,0,0,0,91,505,1,0,0,0,93,510,1,0,0,0,95,516,1,0, + 0,0,97,524,1,0,0,0,99,532,1,0,0,0,101,540,1,0,0,0,103,549,1,0,0, + 0,105,554,1,0,0,0,107,559,1,0,0,0,109,567,1,0,0,0,111,571,1,0,0, + 0,113,576,1,0,0,0,115,586,1,0,0,0,117,591,1,0,0,0,119,601,1,0,0, + 0,121,623,1,0,0,0,123,654,1,0,0,0,125,657,1,0,0,0,127,673,1,0,0, + 0,129,678,1,0,0,0,131,680,1,0,0,0,133,688,1,0,0,0,135,692,1,0,0, + 0,137,694,1,0,0,0,139,708,1,0,0,0,141,728,1,0,0,0,143,748,1,0,0, + 0,145,769,1,0,0,0,147,771,1,0,0,0,149,773,1,0,0,0,151,775,1,0,0, + 0,153,777,1,0,0,0,155,779,1,0,0,0,157,781,1,0,0,0,159,783,1,0,0, + 0,161,785,1,0,0,0,163,787,1,0,0,0,165,789,1,0,0,0,167,791,1,0,0, + 0,169,793,1,0,0,0,171,795,1,0,0,0,173,797,1,0,0,0,175,799,1,0,0, + 0,177,801,1,0,0,0,179,803,1,0,0,0,181,805,1,0,0,0,183,807,1,0,0, + 0,185,809,1,0,0,0,187,811,1,0,0,0,189,813,1,0,0,0,191,815,1,0,0, + 0,193,817,1,0,0,0,195,819,1,0,0,0,197,821,1,0,0,0,199,200,5,40,0, + 0,200,2,1,0,0,0,201,202,5,41,0,0,202,4,1,0,0,0,203,204,5,58,0,0, + 204,6,1,0,0,0,205,206,5,44,0,0,206,8,1,0,0,0,207,208,5,46,0,0,208, + 10,1,0,0,0,209,210,5,91,0,0,210,12,1,0,0,0,211,212,5,93,0,0,212, + 14,1,0,0,0,213,214,3,189,94,0,214,215,3,159,79,0,215,216,3,153,76, + 0,216,217,3,179,89,0,217,218,3,153,76,0,218,16,1,0,0,0,219,220,3, + 145,72,0,220,221,3,171,85,0,221,222,3,151,75,0,222,225,1,0,0,0,223, + 225,5,38,0,0,224,219,1,0,0,0,224,223,1,0,0,0,225,18,1,0,0,0,226, + 227,3,173,86,0,227,228,3,179,89,0,228,231,1,0,0,0,229,231,5,124, + 0,0,230,226,1,0,0,0,230,229,1,0,0,0,231,20,1,0,0,0,232,233,3,171, + 85,0,233,234,3,173,86,0,234,235,3,183,91,0,235,238,1,0,0,0,236,238, + 5,33,0,0,237,232,1,0,0,0,237,236,1,0,0,0,238,22,1,0,0,0,239,240, + 3,153,76,0,240,241,3,177,88,0,241,245,1,0,0,0,242,243,5,61,0,0,243, + 245,5,61,0,0,244,239,1,0,0,0,244,242,1,0,0,0,245,24,1,0,0,0,246, + 247,3,171,85,0,247,248,3,153,76,0,248,249,3,177,88,0,249,253,1,0, + 0,0,250,251,5,33,0,0,251,253,5,61,0,0,252,246,1,0,0,0,252,250,1, + 0,0,0,253,26,1,0,0,0,254,255,3,167,83,0,255,256,3,183,91,0,256,259, + 1,0,0,0,257,259,5,60,0,0,258,254,1,0,0,0,258,257,1,0,0,0,259,28, + 1,0,0,0,260,261,3,157,78,0,261,262,3,183,91,0,262,265,1,0,0,0,263, + 265,5,62,0,0,264,260,1,0,0,0,264,263,1,0,0,0,265,30,1,0,0,0,266, + 267,3,167,83,0,267,268,3,183,91,0,268,269,3,153,76,0,269,273,1,0, + 0,0,270,271,5,60,0,0,271,273,5,61,0,0,272,266,1,0,0,0,272,270,1, + 0,0,0,273,32,1,0,0,0,274,275,3,157,78,0,275,276,3,183,91,0,276,277, + 3,153,76,0,277,281,1,0,0,0,278,279,5,62,0,0,279,281,5,61,0,0,280, + 274,1,0,0,0,280,278,1,0,0,0,281,34,1,0,0,0,282,283,3,149,74,0,283, + 284,3,173,86,0,284,285,3,171,85,0,285,286,3,183,91,0,286,287,3,145, + 72,0,287,288,3,161,80,0,288,289,3,171,85,0,289,290,3,181,90,0,290, + 293,1,0,0,0,291,293,5,126,0,0,292,282,1,0,0,0,292,291,1,0,0,0,293, + 36,1,0,0,0,294,295,3,161,80,0,295,296,3,171,85,0,296,38,1,0,0,0, + 297,298,3,149,74,0,298,299,3,145,72,0,299,300,3,181,90,0,300,301, + 3,153,76,0,301,40,1,0,0,0,302,303,3,149,74,0,303,304,3,145,72,0, + 304,305,3,181,90,0,305,306,3,153,76,0,306,307,3,181,90,0,307,42, + 1,0,0,0,308,309,3,183,91,0,309,310,3,145,72,0,310,311,3,181,90,0, + 311,312,3,165,82,0,312,44,1,0,0,0,313,314,3,183,91,0,314,315,3,145, + 72,0,315,316,3,181,90,0,316,317,3,165,82,0,317,318,3,181,90,0,318, + 46,1,0,0,0,319,320,3,185,92,0,320,321,3,181,90,0,321,322,3,153,76, + 0,322,323,3,179,89,0,323,48,1,0,0,0,324,325,3,185,92,0,325,326,3, + 181,90,0,326,327,3,153,76,0,327,328,3,179,89,0,328,329,3,181,90, + 0,329,50,1,0,0,0,330,331,3,175,87,0,331,332,3,179,89,0,332,333,3, + 173,86,0,333,334,3,149,74,0,334,335,3,153,76,0,335,336,3,181,90, + 0,336,337,3,181,90,0,337,52,1,0,0,0,338,339,3,175,87,0,339,340,3, + 179,89,0,340,341,3,173,86,0,341,342,3,149,74,0,342,343,3,153,76, + 0,343,344,3,181,90,0,344,345,3,181,90,0,345,346,3,153,76,0,346,347, + 3,181,90,0,347,54,1,0,0,0,348,349,3,161,80,0,349,350,3,151,75,0, + 350,56,1,0,0,0,351,352,3,183,91,0,352,353,3,161,80,0,353,354,3,183, + 91,0,354,355,3,167,83,0,355,356,3,153,76,0,356,58,1,0,0,0,357,358, + 3,161,80,0,358,359,3,151,75,0,359,360,3,153,76,0,360,361,3,171,85, + 0,361,362,3,183,91,0,362,363,3,161,80,0,363,364,3,155,77,0,364,365, + 3,161,80,0,365,366,3,153,76,0,366,367,3,179,89,0,367,60,1,0,0,0, + 368,369,3,187,93,0,369,370,3,153,76,0,370,371,3,179,89,0,371,372, + 3,181,90,0,372,373,3,161,80,0,373,374,3,173,86,0,374,375,3,171,85, + 0,375,62,1,0,0,0,376,377,3,149,74,0,377,378,3,179,89,0,378,379,3, + 153,76,0,379,380,3,145,72,0,380,381,3,183,91,0,381,382,3,161,80, + 0,382,383,3,173,86,0,383,384,3,171,85,0,384,385,3,151,75,0,385,386, + 3,145,72,0,386,387,3,183,91,0,387,388,3,153,76,0,388,64,1,0,0,0, + 389,390,3,175,87,0,390,391,3,179,89,0,391,392,3,173,86,0,392,393, + 3,149,74,0,393,394,3,153,76,0,394,395,3,181,90,0,395,396,3,181,90, + 0,396,397,3,161,80,0,397,398,3,151,75,0,398,66,1,0,0,0,399,400,3, + 175,87,0,400,401,3,179,89,0,401,402,3,173,86,0,402,403,3,149,74, + 0,403,404,3,153,76,0,404,405,3,181,90,0,405,406,3,181,90,0,406,407, + 3,161,80,0,407,408,3,151,75,0,408,409,3,153,76,0,409,410,3,171,85, + 0,410,411,3,183,91,0,411,412,3,161,80,0,412,413,3,155,77,0,413,414, + 3,161,80,0,414,415,3,153,76,0,415,416,3,179,89,0,416,68,1,0,0,0, + 417,418,3,145,72,0,418,419,3,185,92,0,419,420,3,183,91,0,420,421, + 3,159,79,0,421,422,3,173,86,0,422,423,3,179,89,0,423,70,1,0,0,0, + 424,425,3,175,87,0,425,426,3,167,83,0,426,427,3,145,72,0,427,428, + 3,149,74,0,428,429,3,153,76,0,429,430,3,181,90,0,430,72,1,0,0,0, + 431,432,3,183,91,0,432,433,3,179,89,0,433,434,3,145,72,0,434,435, + 3,171,85,0,435,436,3,181,90,0,436,437,3,161,80,0,437,438,3,183,91, + 0,438,439,3,161,80,0,439,440,3,173,86,0,440,441,3,171,85,0,441,442, + 3,161,80,0,442,443,3,151,75,0,443,74,1,0,0,0,444,445,3,181,90,0, + 445,446,3,183,91,0,446,447,3,145,72,0,447,448,3,183,91,0,448,449, + 3,153,76,0,449,76,1,0,0,0,450,451,3,185,92,0,451,452,3,181,90,0, + 452,453,3,153,76,0,453,454,3,179,89,0,454,455,3,161,80,0,455,456, + 3,151,75,0,456,78,1,0,0,0,457,458,3,149,74,0,458,459,3,145,72,0, + 459,460,3,181,90,0,460,461,3,153,76,0,461,462,3,161,80,0,462,463, + 3,151,75,0,463,80,1,0,0,0,464,465,3,167,83,0,465,466,3,145,72,0, + 466,467,3,181,90,0,467,468,3,183,91,0,468,469,3,145,72,0,469,470, + 3,181,90,0,470,471,3,181,90,0,471,472,3,161,80,0,472,473,3,157,78, + 0,473,474,3,171,85,0,474,82,1,0,0,0,475,476,3,167,83,0,476,477,3, + 145,72,0,477,478,3,181,90,0,478,479,3,183,91,0,479,480,3,155,77, + 0,480,481,3,161,80,0,481,482,3,171,85,0,482,483,3,161,80,0,483,484, + 3,181,90,0,484,485,3,159,79,0,485,84,1,0,0,0,486,487,3,171,85,0, + 487,488,3,145,72,0,488,489,3,169,84,0,489,490,3,153,76,0,490,86, + 1,0,0,0,491,492,3,181,90,0,492,493,3,185,92,0,493,494,3,179,89,0, + 494,495,3,171,85,0,495,496,3,145,72,0,496,497,3,169,84,0,497,498, + 3,153,76,0,498,88,1,0,0,0,499,500,3,153,76,0,500,501,3,169,84,0, + 501,502,3,145,72,0,502,503,3,161,80,0,503,504,3,167,83,0,504,90, + 1,0,0,0,505,506,3,151,75,0,506,507,3,145,72,0,507,508,3,183,91,0, + 508,509,3,145,72,0,509,92,1,0,0,0,510,511,3,187,93,0,511,512,3,145, + 72,0,512,513,3,167,83,0,513,514,3,185,92,0,514,515,3,153,76,0,515, + 94,1,0,0,0,516,517,3,173,86,0,517,518,3,175,87,0,518,519,3,183,91, + 0,519,520,3,161,80,0,520,521,3,173,86,0,521,522,3,171,85,0,522,523, + 3,181,90,0,523,96,1,0,0,0,524,525,3,169,84,0,525,526,3,145,72,0, + 526,527,3,179,89,0,527,528,3,165,82,0,528,529,3,161,80,0,529,530, + 3,171,85,0,530,531,3,157,78,0,531,98,1,0,0,0,532,533,3,153,76,0, + 533,534,3,171,85,0,534,535,3,145,72,0,535,536,3,147,73,0,536,537, + 3,167,83,0,537,538,3,153,76,0,538,539,3,151,75,0,539,100,1,0,0,0, + 540,541,3,151,75,0,541,542,3,161,80,0,542,543,3,181,90,0,543,544, + 3,145,72,0,544,545,3,147,73,0,545,546,3,167,83,0,546,547,3,153,76, + 0,547,548,3,151,75,0,548,102,1,0,0,0,549,550,3,175,87,0,550,551, + 3,145,72,0,551,552,3,157,78,0,552,553,3,153,76,0,553,104,1,0,0,0, + 554,555,3,181,90,0,555,556,3,161,80,0,556,557,3,195,97,0,557,558, + 3,153,76,0,558,106,1,0,0,0,559,560,3,181,90,0,560,561,3,173,86,0, + 561,562,3,179,89,0,562,563,3,183,91,0,563,564,3,133,66,0,564,565, + 3,147,73,0,565,566,3,193,96,0,566,108,1,0,0,0,567,568,3,145,72,0, + 568,569,3,181,90,0,569,570,3,149,74,0,570,110,1,0,0,0,571,572,3, + 151,75,0,572,573,3,153,76,0,573,574,3,181,90,0,574,575,3,149,74, + 0,575,112,1,0,0,0,576,580,5,39,0,0,577,579,8,0,0,0,578,577,1,0,0, + 0,579,582,1,0,0,0,580,578,1,0,0,0,580,581,1,0,0,0,581,583,1,0,0, + 0,582,580,1,0,0,0,583,584,5,39,0,0,584,114,1,0,0,0,585,587,3,197, + 98,0,586,585,1,0,0,0,587,588,1,0,0,0,588,586,1,0,0,0,588,589,1,0, + 0,0,589,116,1,0,0,0,590,592,3,197,98,0,591,590,1,0,0,0,592,593,1, + 0,0,0,593,591,1,0,0,0,593,594,1,0,0,0,594,595,1,0,0,0,595,597,5, + 46,0,0,596,598,3,197,98,0,597,596,1,0,0,0,598,599,1,0,0,0,599,597, + 1,0,0,0,599,600,1,0,0,0,600,118,1,0,0,0,601,602,3,121,60,0,602,607, + 5,84,0,0,603,604,7,1,0,0,604,608,3,197,98,0,605,606,5,50,0,0,606, + 608,7,2,0,0,607,603,1,0,0,0,607,605,1,0,0,0,608,609,1,0,0,0,609, + 610,5,58,0,0,610,611,7,3,0,0,611,612,3,197,98,0,612,613,5,58,0,0, + 613,614,7,3,0,0,614,621,3,197,98,0,615,617,5,46,0,0,616,618,3,197, + 98,0,617,616,1,0,0,0,618,619,1,0,0,0,619,617,1,0,0,0,619,620,1,0, + 0,0,620,622,1,0,0,0,621,615,1,0,0,0,621,622,1,0,0,0,622,120,1,0, + 0,0,623,624,3,197,98,0,624,625,3,197,98,0,625,626,3,197,98,0,626, + 627,3,197,98,0,627,632,5,45,0,0,628,629,5,48,0,0,629,633,7,4,0,0, + 630,631,5,49,0,0,631,633,7,5,0,0,632,628,1,0,0,0,632,630,1,0,0,0, + 633,634,1,0,0,0,634,641,5,45,0,0,635,636,5,48,0,0,636,642,7,4,0, + 0,637,638,7,6,0,0,638,642,3,197,98,0,639,640,5,51,0,0,640,642,7, + 1,0,0,641,635,1,0,0,0,641,637,1,0,0,0,641,639,1,0,0,0,642,122,1, + 0,0,0,643,644,3,183,91,0,644,645,3,179,89,0,645,646,3,185,92,0,646, + 647,3,153,76,0,647,655,1,0,0,0,648,649,3,155,77,0,649,650,3,145, + 72,0,650,651,3,167,83,0,651,652,3,181,90,0,652,653,3,153,76,0,653, + 655,1,0,0,0,654,643,1,0,0,0,654,648,1,0,0,0,655,124,1,0,0,0,656, + 658,3,197,98,0,657,656,1,0,0,0,658,659,1,0,0,0,659,657,1,0,0,0,659, + 660,1,0,0,0,660,661,1,0,0,0,661,663,5,46,0,0,662,664,3,197,98,0, + 663,662,1,0,0,0,664,665,1,0,0,0,665,663,1,0,0,0,665,666,1,0,0,0, + 666,667,1,0,0,0,667,669,5,46,0,0,668,670,3,197,98,0,669,668,1,0, + 0,0,670,671,1,0,0,0,671,669,1,0,0,0,671,672,1,0,0,0,672,126,1,0, + 0,0,673,674,3,171,85,0,674,675,3,185,92,0,675,676,3,167,83,0,676, + 677,3,167,83,0,677,128,1,0,0,0,678,679,5,42,0,0,679,130,1,0,0,0, + 680,684,7,7,0,0,681,683,7,8,0,0,682,681,1,0,0,0,683,686,1,0,0,0, + 684,682,1,0,0,0,684,685,1,0,0,0,685,132,1,0,0,0,686,684,1,0,0,0, + 687,689,7,9,0,0,688,687,1,0,0,0,689,690,1,0,0,0,690,688,1,0,0,0, + 690,691,1,0,0,0,691,134,1,0,0,0,692,693,9,0,0,0,693,136,1,0,0,0, + 694,695,3,167,83,0,695,696,3,173,86,0,696,697,3,157,78,0,697,698, + 3,157,78,0,698,699,3,153,76,0,699,700,3,151,75,0,700,701,3,185,92, + 0,701,702,3,181,90,0,702,703,3,153,76,0,703,704,3,179,89,0,704,705, + 5,46,0,0,705,706,3,161,80,0,706,707,3,151,75,0,707,138,1,0,0,0,708, + 709,3,167,83,0,709,710,3,173,86,0,710,711,3,157,78,0,711,712,3,157, + 78,0,712,713,3,153,76,0,713,714,3,151,75,0,714,715,3,185,92,0,715, + 716,3,181,90,0,716,717,3,153,76,0,717,718,3,179,89,0,718,719,5,46, + 0,0,719,720,3,155,77,0,720,721,3,185,92,0,721,722,3,167,83,0,722, + 723,3,167,83,0,723,724,3,171,85,0,724,725,3,145,72,0,725,726,3,169, + 84,0,726,727,3,153,76,0,727,140,1,0,0,0,728,729,3,167,83,0,729,730, + 3,173,86,0,730,731,3,157,78,0,731,732,3,157,78,0,732,733,3,153,76, + 0,733,734,3,151,75,0,734,735,3,185,92,0,735,736,3,181,90,0,736,737, + 3,153,76,0,737,738,3,179,89,0,738,739,5,46,0,0,739,740,3,185,92, + 0,740,741,3,181,90,0,741,742,3,153,76,0,742,743,3,179,89,0,743,744, + 3,171,85,0,744,745,3,145,72,0,745,746,3,169,84,0,746,747,3,153,76, + 0,747,142,1,0,0,0,748,749,3,167,83,0,749,750,3,173,86,0,750,751, + 3,157,78,0,751,752,3,157,78,0,752,753,3,153,76,0,753,754,3,151,75, + 0,754,755,3,185,92,0,755,756,3,181,90,0,756,757,3,153,76,0,757,758, + 3,179,89,0,758,759,5,46,0,0,759,760,3,145,72,0,760,761,3,171,85, + 0,761,762,3,173,86,0,762,763,3,171,85,0,763,764,3,193,96,0,764,765, + 3,169,84,0,765,766,3,173,86,0,766,767,3,185,92,0,767,768,3,181,90, + 0,768,144,1,0,0,0,769,770,7,10,0,0,770,146,1,0,0,0,771,772,7,11, + 0,0,772,148,1,0,0,0,773,774,7,12,0,0,774,150,1,0,0,0,775,776,7,13, + 0,0,776,152,1,0,0,0,777,778,7,14,0,0,778,154,1,0,0,0,779,780,7,15, + 0,0,780,156,1,0,0,0,781,782,7,16,0,0,782,158,1,0,0,0,783,784,7,17, + 0,0,784,160,1,0,0,0,785,786,7,18,0,0,786,162,1,0,0,0,787,788,7,19, + 0,0,788,164,1,0,0,0,789,790,7,20,0,0,790,166,1,0,0,0,791,792,7,21, + 0,0,792,168,1,0,0,0,793,794,7,22,0,0,794,170,1,0,0,0,795,796,7,23, + 0,0,796,172,1,0,0,0,797,798,7,24,0,0,798,174,1,0,0,0,799,800,7,25, + 0,0,800,176,1,0,0,0,801,802,7,26,0,0,802,178,1,0,0,0,803,804,7,27, + 0,0,804,180,1,0,0,0,805,806,7,28,0,0,806,182,1,0,0,0,807,808,7,29, + 0,0,808,184,1,0,0,0,809,810,7,30,0,0,810,186,1,0,0,0,811,812,7,31, + 0,0,812,188,1,0,0,0,813,814,7,32,0,0,814,190,1,0,0,0,815,816,7,33, + 0,0,816,192,1,0,0,0,817,818,7,34,0,0,818,194,1,0,0,0,819,820,7,35, + 0,0,820,196,1,0,0,0,821,822,7,36,0,0,822,198,1,0,0,0,26,0,224,230, + 237,244,252,258,264,272,280,292,580,588,593,599,607,619,621,632, + 641,654,659,665,671,684,690,0 + ]; + + private static __ATN: antlr.ATN; + public static get _ATN(): antlr.ATN { + if (!QueryLangLexer.__ATN) { + QueryLangLexer.__ATN = new antlr.ATNDeserializer().deserialize(QueryLangLexer._serializedATN); + } + + return QueryLangLexer.__ATN; + } + + + private static readonly vocabulary = new antlr.Vocabulary(QueryLangLexer.literalNames, QueryLangLexer.symbolicNames, []); + + public override get vocabulary(): antlr.Vocabulary { + return QueryLangLexer.vocabulary; + } + + private static readonly decisionsToDFA = QueryLangLexer._ATN.decisionToState.map( (ds: antlr.DecisionState, index: number) => new antlr.DFA(ds, index) ); +} \ No newline at end of file diff --git a/projects/netgrif-components-core/src/lib/pfql/generated/QueryLangParser.ts b/projects/netgrif-components-core/src/lib/pfql/generated/QueryLangParser.ts new file mode 100644 index 0000000000..777d4bf765 --- /dev/null +++ b/projects/netgrif-components-core/src/lib/pfql/generated/QueryLangParser.ts @@ -0,0 +1,12718 @@ + +import * as antlr from "antlr4ng"; +import { Token } from "antlr4ng"; + +import { QueryLangVisitor } from "./QueryLangVisitor.js"; + +// for running tests with parameters, TODO: discuss strategy for typed parameters in CI +// eslint-disable-next-line no-unused-vars +type int = number; + + +export class QueryLangParser extends antlr.Parser { + public static readonly T__0 = 1; + public static readonly T__1 = 2; + public static readonly T__2 = 3; + public static readonly T__3 = 4; + public static readonly T__4 = 5; + public static readonly T__5 = 6; + public static readonly T__6 = 7; + public static readonly WHERE = 8; + public static readonly AND = 9; + public static readonly OR = 10; + public static readonly NOT = 11; + public static readonly EQ = 12; + public static readonly NEQ = 13; + public static readonly LT = 14; + public static readonly GT = 15; + public static readonly LTE = 16; + public static readonly GTE = 17; + public static readonly CONTAINS = 18; + public static readonly IN = 19; + public static readonly CASE = 20; + public static readonly CASES = 21; + public static readonly TASK = 22; + public static readonly TASKS = 23; + public static readonly USER = 24; + public static readonly USERS = 25; + public static readonly PROCESS = 26; + public static readonly PROCESSES = 27; + public static readonly ID = 28; + public static readonly TITLE = 29; + public static readonly IDENTIFIER = 30; + public static readonly VERSION = 31; + public static readonly CREATION_DATE = 32; + public static readonly PROCESS_ID = 33; + public static readonly PROCESS_IDENTIFIER = 34; + public static readonly AUTHOR = 35; + public static readonly PLACES = 36; + public static readonly TRANSITION_ID = 37; + public static readonly STATE = 38; + public static readonly USER_ID = 39; + public static readonly CASE_ID = 40; + public static readonly LAST_ASSIGN = 41; + public static readonly LAST_FINISH = 42; + public static readonly NAME = 43; + public static readonly SURNAME = 44; + public static readonly EMAIL = 45; + public static readonly DATA = 46; + public static readonly VALUE = 47; + public static readonly OPTIONS = 48; + public static readonly MARKING = 49; + public static readonly ENABLED = 50; + public static readonly DISABLED = 51; + public static readonly PAGE = 52; + public static readonly SIZE = 53; + public static readonly SORT_BY = 54; + public static readonly ASC = 55; + public static readonly DESC = 56; + public static readonly STRING = 57; + public static readonly INT = 58; + public static readonly DOUBLE = 59; + public static readonly DATETIME = 60; + public static readonly DATE = 61; + public static readonly BOOLEAN = 62; + public static readonly VERSION_NUMBER = 63; + public static readonly NULL = 64; + public static readonly LIKE = 65; + public static readonly JAVA_ID = 66; + public static readonly SPACE = 67; + public static readonly ANY = 68; + public static readonly LOGGED_USER_ID = 69; + public static readonly LOGGED_USER_FULLNAME = 70; + public static readonly LOGGED_USER_USERNAME = 71; + public static readonly LOGGED_USER_ANONYMOUS = 72; + public static readonly RULE_query = 0; + public static readonly RULE_processConditionsAndPaging = 1; + public static readonly RULE_caseConditionsAndPaging = 2; + public static readonly RULE_taskConditionsAndPaging = 3; + public static readonly RULE_userConditionsAndPaging = 4; + public static readonly RULE_processConditions = 5; + public static readonly RULE_processOrExpression = 6; + public static readonly RULE_processAndExpression = 7; + public static readonly RULE_processConditionGroup = 8; + public static readonly RULE_processCondition = 9; + public static readonly RULE_caseConditions = 10; + public static readonly RULE_caseOrExpression = 11; + public static readonly RULE_caseAndExpression = 12; + public static readonly RULE_caseConditionGroup = 13; + public static readonly RULE_caseCondition = 14; + public static readonly RULE_taskConditions = 15; + public static readonly RULE_taskOrExpression = 16; + public static readonly RULE_taskAndExpression = 17; + public static readonly RULE_taskConditionGroup = 18; + public static readonly RULE_taskCondition = 19; + public static readonly RULE_userConditions = 20; + public static readonly RULE_userOrExpression = 21; + public static readonly RULE_userAndExpression = 22; + public static readonly RULE_userConditionGroup = 23; + public static readonly RULE_userCondition = 24; + public static readonly RULE_delimeter = 25; + public static readonly RULE_paging = 26; + public static readonly RULE_processSorting = 27; + public static readonly RULE_processAttributeOrdering = 28; + public static readonly RULE_processAttribute = 29; + public static readonly RULE_caseSorting = 30; + public static readonly RULE_caseAttributeOrdering = 31; + public static readonly RULE_caseAttribute = 32; + public static readonly RULE_taskSorting = 33; + public static readonly RULE_taskAttributeOrdering = 34; + public static readonly RULE_taskAttribute = 35; + public static readonly RULE_userSorting = 36; + public static readonly RULE_userAttributeOrdering = 37; + public static readonly RULE_userAttribute = 38; + public static readonly RULE_processComparisons = 39; + public static readonly RULE_caseComparisons = 40; + public static readonly RULE_taskComparisons = 41; + public static readonly RULE_userComparisons = 42; + public static readonly RULE_idComparison = 43; + public static readonly RULE_titleComparison = 44; + public static readonly RULE_identifierComparison = 45; + public static readonly RULE_versionComparison = 46; + public static readonly RULE_creationDateComparison = 47; + public static readonly RULE_processIdComparison = 48; + public static readonly RULE_processIdObjIdComparison = 49; + public static readonly RULE_processIdentifierComparison = 50; + public static readonly RULE_authorComparison = 51; + public static readonly RULE_transitionIdComparison = 52; + public static readonly RULE_stateComparison = 53; + public static readonly RULE_userIdComparison = 54; + public static readonly RULE_caseIdComparison = 55; + public static readonly RULE_lastAssignComparison = 56; + public static readonly RULE_lastFinishComparison = 57; + public static readonly RULE_nameComparison = 58; + public static readonly RULE_surnameComparison = 59; + public static readonly RULE_emailComparison = 60; + public static readonly RULE_dataValueComparison = 61; + public static readonly RULE_dataOptionsComparison = 62; + public static readonly RULE_placesComparison = 63; + public static readonly RULE_tasksStateComparison = 64; + public static readonly RULE_tasksUserIdComparison = 65; + public static readonly RULE_objectIdComparison = 66; + public static readonly RULE_stringComparison = 67; + public static readonly RULE_stringLikeComparison = 68; + public static readonly RULE_numberComparison = 69; + public static readonly RULE_dateComparison = 70; + public static readonly RULE_dateTimeComparison = 71; + public static readonly RULE_booleanComparison = 72; + public static readonly RULE_nullComparison = 73; + public static readonly RULE_inListStringComparison = 74; + public static readonly RULE_inListNumberComparison = 75; + public static readonly RULE_inListDateComparison = 76; + public static readonly RULE_inListVersionComparison = 77; + public static readonly RULE_inRangeStringComparison = 78; + public static readonly RULE_inRangeNumberComparison = 79; + public static readonly RULE_inRangeDateComparison = 80; + public static readonly RULE_inRangeVersionComparison = 81; + public static readonly RULE_dataValue = 82; + public static readonly RULE_dataOptions = 83; + public static readonly RULE_places = 84; + public static readonly RULE_tasksState = 85; + public static readonly RULE_tasksUserId = 86; + public static readonly RULE_javaId = 87; + public static readonly RULE_stringList = 88; + public static readonly RULE_intList = 89; + public static readonly RULE_doubleList = 90; + public static readonly RULE_dateList = 91; + public static readonly RULE_dateTimeList = 92; + public static readonly RULE_versionList = 93; + public static readonly RULE_stringRange = 94; + public static readonly RULE_intRange = 95; + public static readonly RULE_doubleRange = 96; + public static readonly RULE_dateRange = 97; + public static readonly RULE_dateTimeRange = 98; + public static readonly RULE_versionRange = 99; + public static readonly RULE_loggedUserStringAttribute = 100; + + public static readonly literalNames = [ + null, "'('", "')'", "':'", "','", "'.'", "'['", "']'", null, null, + null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, + "'*'" + ]; + + public static readonly symbolicNames = [ + null, null, null, null, null, null, null, null, "WHERE", "AND", + "OR", "NOT", "EQ", "NEQ", "LT", "GT", "LTE", "GTE", "CONTAINS", + "IN", "CASE", "CASES", "TASK", "TASKS", "USER", "USERS", "PROCESS", + "PROCESSES", "ID", "TITLE", "IDENTIFIER", "VERSION", "CREATION_DATE", + "PROCESS_ID", "PROCESS_IDENTIFIER", "AUTHOR", "PLACES", "TRANSITION_ID", + "STATE", "USER_ID", "CASE_ID", "LAST_ASSIGN", "LAST_FINISH", "NAME", + "SURNAME", "EMAIL", "DATA", "VALUE", "OPTIONS", "MARKING", "ENABLED", + "DISABLED", "PAGE", "SIZE", "SORT_BY", "ASC", "DESC", "STRING", + "INT", "DOUBLE", "DATETIME", "DATE", "BOOLEAN", "VERSION_NUMBER", + "NULL", "LIKE", "JAVA_ID", "SPACE", "ANY", "LOGGED_USER_ID", "LOGGED_USER_FULLNAME", + "LOGGED_USER_USERNAME", "LOGGED_USER_ANONYMOUS" + ]; + public static readonly ruleNames = [ + "query", "processConditionsAndPaging", "caseConditionsAndPaging", + "taskConditionsAndPaging", "userConditionsAndPaging", "processConditions", + "processOrExpression", "processAndExpression", "processConditionGroup", + "processCondition", "caseConditions", "caseOrExpression", "caseAndExpression", + "caseConditionGroup", "caseCondition", "taskConditions", "taskOrExpression", + "taskAndExpression", "taskConditionGroup", "taskCondition", "userConditions", + "userOrExpression", "userAndExpression", "userConditionGroup", "userCondition", + "delimeter", "paging", "processSorting", "processAttributeOrdering", + "processAttribute", "caseSorting", "caseAttributeOrdering", "caseAttribute", + "taskSorting", "taskAttributeOrdering", "taskAttribute", "userSorting", + "userAttributeOrdering", "userAttribute", "processComparisons", + "caseComparisons", "taskComparisons", "userComparisons", "idComparison", + "titleComparison", "identifierComparison", "versionComparison", + "creationDateComparison", "processIdComparison", "processIdObjIdComparison", + "processIdentifierComparison", "authorComparison", "transitionIdComparison", + "stateComparison", "userIdComparison", "caseIdComparison", "lastAssignComparison", + "lastFinishComparison", "nameComparison", "surnameComparison", "emailComparison", + "dataValueComparison", "dataOptionsComparison", "placesComparison", + "tasksStateComparison", "tasksUserIdComparison", "objectIdComparison", + "stringComparison", "stringLikeComparison", "numberComparison", + "dateComparison", "dateTimeComparison", "booleanComparison", "nullComparison", + "inListStringComparison", "inListNumberComparison", "inListDateComparison", + "inListVersionComparison", "inRangeStringComparison", "inRangeNumberComparison", + "inRangeDateComparison", "inRangeVersionComparison", "dataValue", + "dataOptions", "places", "tasksState", "tasksUserId", "javaId", + "stringList", "intList", "doubleList", "dateList", "dateTimeList", + "versionList", "stringRange", "intRange", "doubleRange", "dateRange", + "dateTimeRange", "versionRange", "loggedUserStringAttribute", + ]; + + public get grammarFileName(): string { return "QueryLang.g4"; } + public get literalNames(): (string | null)[] { return QueryLangParser.literalNames; } + public get symbolicNames(): (string | null)[] { return QueryLangParser.symbolicNames; } + public get ruleNames(): string[] { return QueryLangParser.ruleNames; } + public get serializedATN(): number[] { return QueryLangParser._serializedATN; } + + protected createFailedPredicateException(predicate?: string, message?: string): antlr.FailedPredicateException { + return new antlr.FailedPredicateException(this, predicate, message); + } + + public constructor(input: antlr.TokenStream) { + super(input); + this.interpreter = new antlr.ParserATNSimulator(this, QueryLangParser._ATN, QueryLangParser.decisionsToDFA, new antlr.PredictionContextCache()); + } + public query(): QueryContext { + let localContext = new QueryContext(this.context, this.state); + this.enterRule(localContext, 0, QueryLangParser.RULE_query); + let _la: number; + try { + this.state = 222; + this.errorHandler.sync(this); + switch (this.tokenStream.LA(1)) { + case QueryLangParser.PROCESS: + case QueryLangParser.PROCESSES: + localContext = new ProcessQueryContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 202; + (localContext as ProcessQueryContext)._resource = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 26 || _la === 27)) { + (localContext as ProcessQueryContext)._resource = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + this.state = 204; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 3 || _la === 67) { + { + this.state = 203; + this.processConditionsAndPaging(); + } + } + + this.state = 206; + this.match(QueryLangParser.EOF); + } + break; + case QueryLangParser.CASE: + case QueryLangParser.CASES: + localContext = new CaseQueryContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 207; + (localContext as CaseQueryContext)._resource = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 20 || _la === 21)) { + (localContext as CaseQueryContext)._resource = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + this.state = 209; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 3 || _la === 67) { + { + this.state = 208; + this.caseConditionsAndPaging(); + } + } + + this.state = 211; + this.match(QueryLangParser.EOF); + } + break; + case QueryLangParser.TASK: + case QueryLangParser.TASKS: + localContext = new TaskQueryContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 212; + (localContext as TaskQueryContext)._resource = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 22 || _la === 23)) { + (localContext as TaskQueryContext)._resource = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + this.state = 214; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 3 || _la === 67) { + { + this.state = 213; + this.taskConditionsAndPaging(); + } + } + + this.state = 216; + this.match(QueryLangParser.EOF); + } + break; + case QueryLangParser.USER: + case QueryLangParser.USERS: + localContext = new UserQueryContext(localContext); + this.enterOuterAlt(localContext, 4); + { + this.state = 217; + (localContext as UserQueryContext)._resource = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 24 || _la === 25)) { + (localContext as UserQueryContext)._resource = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + this.state = 219; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 3 || _la === 67) { + { + this.state = 218; + this.userConditionsAndPaging(); + } + } + + this.state = 221; + this.match(QueryLangParser.EOF); + } + break; + default: + throw new antlr.NoViableAltException(this); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public processConditionsAndPaging(): ProcessConditionsAndPagingContext { + let localContext = new ProcessConditionsAndPagingContext(this.context, this.state); + this.enterRule(localContext, 2, QueryLangParser.RULE_processConditionsAndPaging); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 224; + this.delimeter(); + this.state = 226; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (((((_la - 1)) & ~0x1F) === 0 && ((1 << (_la - 1)) & 4160750593) !== 0)) { + { + this.state = 225; + this.processConditions(); + } + } + + this.state = 229; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 52) { + { + this.state = 228; + this.paging(); + } + } + + this.state = 232; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 54) { + { + this.state = 231; + this.processSorting(); + } + } + + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public caseConditionsAndPaging(): CaseConditionsAndPagingContext { + let localContext = new CaseConditionsAndPagingContext(this.context, this.state); + this.enterRule(localContext, 4, QueryLangParser.RULE_caseConditionsAndPaging); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 234; + this.delimeter(); + this.state = 236; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 813697026) !== 0) || ((((_la - 32)) & ~0x1F) === 0 && ((1 << (_la - 32)) & 16415) !== 0)) { + { + this.state = 235; + this.caseConditions(); + } + } + + this.state = 239; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 52) { + { + this.state = 238; + this.paging(); + } + } + + this.state = 242; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 54) { + { + this.state = 241; + this.caseSorting(); + } + } + + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public taskConditionsAndPaging(): TaskConditionsAndPagingContext { + let localContext = new TaskConditionsAndPagingContext(this.context, this.state); + this.enterRule(localContext, 6, QueryLangParser.RULE_taskConditionsAndPaging); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 244; + this.delimeter(); + this.state = 246; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 805308418) !== 0) || ((((_la - 33)) & ~0x1F) === 0 && ((1 << (_la - 33)) & 1009) !== 0)) { + { + this.state = 245; + this.taskConditions(); + } + } + + this.state = 249; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 52) { + { + this.state = 248; + this.paging(); + } + } + + this.state = 252; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 54) { + { + this.state = 251; + this.taskSorting(); + } + } + + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public userConditionsAndPaging(): UserConditionsAndPagingContext { + let localContext = new UserConditionsAndPagingContext(this.context, this.state); + this.enterRule(localContext, 8, QueryLangParser.RULE_userConditionsAndPaging); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 254; + this.delimeter(); + this.state = 256; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 268437506) !== 0) || ((((_la - 43)) & ~0x1F) === 0 && ((1 << (_la - 43)) & 7) !== 0)) { + { + this.state = 255; + this.userConditions(); + } + } + + this.state = 259; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 52) { + { + this.state = 258; + this.paging(); + } + } + + this.state = 262; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 54) { + { + this.state = 261; + this.userSorting(); + } + } + + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public processConditions(): ProcessConditionsContext { + let localContext = new ProcessConditionsContext(this.context, this.state); + this.enterRule(localContext, 10, QueryLangParser.RULE_processConditions); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 264; + this.processOrExpression(); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public processOrExpression(): ProcessOrExpressionContext { + let localContext = new ProcessOrExpressionContext(this.context, this.state); + this.enterRule(localContext, 12, QueryLangParser.RULE_processOrExpression); + try { + let alternative: number; + this.enterOuterAlt(localContext, 1); + { + this.state = 266; + this.processAndExpression(); + this.state = 273; + this.errorHandler.sync(this); + alternative = this.interpreter.adaptivePredict(this.tokenStream, 17, this.context); + while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) { + if (alternative === 1) { + { + { + this.state = 267; + this.match(QueryLangParser.SPACE); + this.state = 268; + this.match(QueryLangParser.OR); + this.state = 269; + this.match(QueryLangParser.SPACE); + this.state = 270; + this.processAndExpression(); + } + } + } + this.state = 275; + this.errorHandler.sync(this); + alternative = this.interpreter.adaptivePredict(this.tokenStream, 17, this.context); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public processAndExpression(): ProcessAndExpressionContext { + let localContext = new ProcessAndExpressionContext(this.context, this.state); + this.enterRule(localContext, 14, QueryLangParser.RULE_processAndExpression); + try { + let alternative: number; + this.enterOuterAlt(localContext, 1); + { + this.state = 276; + this.processConditionGroup(); + this.state = 283; + this.errorHandler.sync(this); + alternative = this.interpreter.adaptivePredict(this.tokenStream, 18, this.context); + while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) { + if (alternative === 1) { + { + { + this.state = 277; + this.match(QueryLangParser.SPACE); + this.state = 278; + this.match(QueryLangParser.AND); + this.state = 279; + this.match(QueryLangParser.SPACE); + this.state = 280; + this.processConditionGroup(); + } + } + } + this.state = 285; + this.errorHandler.sync(this); + alternative = this.interpreter.adaptivePredict(this.tokenStream, 18, this.context); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public processConditionGroup(): ProcessConditionGroupContext { + let localContext = new ProcessConditionGroupContext(this.context, this.state); + this.enterRule(localContext, 16, QueryLangParser.RULE_processConditionGroup); + let _la: number; + try { + this.state = 305; + this.errorHandler.sync(this); + switch (this.tokenStream.LA(1)) { + case QueryLangParser.ID: + case QueryLangParser.TITLE: + case QueryLangParser.IDENTIFIER: + case QueryLangParser.VERSION: + case QueryLangParser.CREATION_DATE: + localContext = new ProcessConditionGroupBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 286; + this.processCondition(); + } + break; + case QueryLangParser.T__0: + case QueryLangParser.NOT: + localContext = new ProcessConditionGroupParenthesisContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 291; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 11) { + { + this.state = 287; + this.match(QueryLangParser.NOT); + this.state = 289; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 288; + this.match(QueryLangParser.SPACE); + } + } + + } + } + + this.state = 293; + this.match(QueryLangParser.T__0); + this.state = 295; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 294; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 297; + this.processConditions(); + this.state = 299; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 298; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 301; + this.match(QueryLangParser.T__1); + this.state = 303; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 23, this.context) ) { + case 1: + { + this.state = 302; + this.match(QueryLangParser.SPACE); + } + break; + } + } + break; + default: + throw new antlr.NoViableAltException(this); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public processCondition(): ProcessConditionContext { + let localContext = new ProcessConditionContext(this.context, this.state); + this.enterRule(localContext, 18, QueryLangParser.RULE_processCondition); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 307; + this.processComparisons(); + this.state = 309; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 25, this.context) ) { + case 1: + { + this.state = 308; + this.match(QueryLangParser.SPACE); + } + break; + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public caseConditions(): CaseConditionsContext { + let localContext = new CaseConditionsContext(this.context, this.state); + this.enterRule(localContext, 20, QueryLangParser.RULE_caseConditions); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 311; + this.caseOrExpression(); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public caseOrExpression(): CaseOrExpressionContext { + let localContext = new CaseOrExpressionContext(this.context, this.state); + this.enterRule(localContext, 22, QueryLangParser.RULE_caseOrExpression); + try { + let alternative: number; + this.enterOuterAlt(localContext, 1); + { + this.state = 313; + this.caseAndExpression(); + this.state = 320; + this.errorHandler.sync(this); + alternative = this.interpreter.adaptivePredict(this.tokenStream, 26, this.context); + while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) { + if (alternative === 1) { + { + { + this.state = 314; + this.match(QueryLangParser.SPACE); + this.state = 315; + this.match(QueryLangParser.OR); + this.state = 316; + this.match(QueryLangParser.SPACE); + this.state = 317; + this.caseAndExpression(); + } + } + } + this.state = 322; + this.errorHandler.sync(this); + alternative = this.interpreter.adaptivePredict(this.tokenStream, 26, this.context); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public caseAndExpression(): CaseAndExpressionContext { + let localContext = new CaseAndExpressionContext(this.context, this.state); + this.enterRule(localContext, 24, QueryLangParser.RULE_caseAndExpression); + try { + let alternative: number; + this.enterOuterAlt(localContext, 1); + { + this.state = 323; + this.caseConditionGroup(); + this.state = 330; + this.errorHandler.sync(this); + alternative = this.interpreter.adaptivePredict(this.tokenStream, 27, this.context); + while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) { + if (alternative === 1) { + { + { + this.state = 324; + this.match(QueryLangParser.SPACE); + this.state = 325; + this.match(QueryLangParser.AND); + this.state = 326; + this.match(QueryLangParser.SPACE); + this.state = 327; + this.caseConditionGroup(); + } + } + } + this.state = 332; + this.errorHandler.sync(this); + alternative = this.interpreter.adaptivePredict(this.tokenStream, 27, this.context); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public caseConditionGroup(): CaseConditionGroupContext { + let localContext = new CaseConditionGroupContext(this.context, this.state); + this.enterRule(localContext, 26, QueryLangParser.RULE_caseConditionGroup); + let _la: number; + try { + this.state = 352; + this.errorHandler.sync(this); + switch (this.tokenStream.LA(1)) { + case QueryLangParser.TASKS: + case QueryLangParser.ID: + case QueryLangParser.TITLE: + case QueryLangParser.CREATION_DATE: + case QueryLangParser.PROCESS_ID: + case QueryLangParser.PROCESS_IDENTIFIER: + case QueryLangParser.AUTHOR: + case QueryLangParser.PLACES: + case QueryLangParser.DATA: + localContext = new CaseConditionGroupBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 333; + this.caseCondition(); + } + break; + case QueryLangParser.T__0: + case QueryLangParser.NOT: + localContext = new CaseConditionGroupParenthesisContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 338; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 11) { + { + this.state = 334; + this.match(QueryLangParser.NOT); + this.state = 336; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 335; + this.match(QueryLangParser.SPACE); + } + } + + } + } + + this.state = 340; + this.match(QueryLangParser.T__0); + this.state = 342; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 341; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 344; + this.caseConditions(); + this.state = 346; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 345; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 348; + this.match(QueryLangParser.T__1); + this.state = 350; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 32, this.context) ) { + case 1: + { + this.state = 349; + this.match(QueryLangParser.SPACE); + } + break; + } + } + break; + default: + throw new antlr.NoViableAltException(this); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public caseCondition(): CaseConditionContext { + let localContext = new CaseConditionContext(this.context, this.state); + this.enterRule(localContext, 28, QueryLangParser.RULE_caseCondition); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 354; + this.caseComparisons(); + this.state = 356; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 34, this.context) ) { + case 1: + { + this.state = 355; + this.match(QueryLangParser.SPACE); + } + break; + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public taskConditions(): TaskConditionsContext { + let localContext = new TaskConditionsContext(this.context, this.state); + this.enterRule(localContext, 30, QueryLangParser.RULE_taskConditions); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 358; + this.taskOrExpression(); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public taskOrExpression(): TaskOrExpressionContext { + let localContext = new TaskOrExpressionContext(this.context, this.state); + this.enterRule(localContext, 32, QueryLangParser.RULE_taskOrExpression); + try { + let alternative: number; + this.enterOuterAlt(localContext, 1); + { + this.state = 360; + this.taskAndExpression(); + this.state = 367; + this.errorHandler.sync(this); + alternative = this.interpreter.adaptivePredict(this.tokenStream, 35, this.context); + while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) { + if (alternative === 1) { + { + { + this.state = 361; + this.match(QueryLangParser.SPACE); + this.state = 362; + this.match(QueryLangParser.OR); + this.state = 363; + this.match(QueryLangParser.SPACE); + this.state = 364; + this.taskAndExpression(); + } + } + } + this.state = 369; + this.errorHandler.sync(this); + alternative = this.interpreter.adaptivePredict(this.tokenStream, 35, this.context); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public taskAndExpression(): TaskAndExpressionContext { + let localContext = new TaskAndExpressionContext(this.context, this.state); + this.enterRule(localContext, 34, QueryLangParser.RULE_taskAndExpression); + try { + let alternative: number; + this.enterOuterAlt(localContext, 1); + { + this.state = 370; + this.taskConditionGroup(); + this.state = 377; + this.errorHandler.sync(this); + alternative = this.interpreter.adaptivePredict(this.tokenStream, 36, this.context); + while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) { + if (alternative === 1) { + { + { + this.state = 371; + this.match(QueryLangParser.SPACE); + this.state = 372; + this.match(QueryLangParser.AND); + this.state = 373; + this.match(QueryLangParser.SPACE); + this.state = 374; + this.taskConditionGroup(); + } + } + } + this.state = 379; + this.errorHandler.sync(this); + alternative = this.interpreter.adaptivePredict(this.tokenStream, 36, this.context); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public taskConditionGroup(): TaskConditionGroupContext { + let localContext = new TaskConditionGroupContext(this.context, this.state); + this.enterRule(localContext, 36, QueryLangParser.RULE_taskConditionGroup); + let _la: number; + try { + this.state = 399; + this.errorHandler.sync(this); + switch (this.tokenStream.LA(1)) { + case QueryLangParser.ID: + case QueryLangParser.TITLE: + case QueryLangParser.PROCESS_ID: + case QueryLangParser.TRANSITION_ID: + case QueryLangParser.STATE: + case QueryLangParser.USER_ID: + case QueryLangParser.CASE_ID: + case QueryLangParser.LAST_ASSIGN: + case QueryLangParser.LAST_FINISH: + localContext = new TaskConditionGroupBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 380; + this.taskCondition(); + } + break; + case QueryLangParser.T__0: + case QueryLangParser.NOT: + localContext = new TaskConditionGroupParenthesisContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 385; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 11) { + { + this.state = 381; + this.match(QueryLangParser.NOT); + this.state = 383; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 382; + this.match(QueryLangParser.SPACE); + } + } + + } + } + + this.state = 387; + this.match(QueryLangParser.T__0); + this.state = 389; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 388; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 391; + this.taskConditions(); + this.state = 393; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 392; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 395; + this.match(QueryLangParser.T__1); + this.state = 397; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 41, this.context) ) { + case 1: + { + this.state = 396; + this.match(QueryLangParser.SPACE); + } + break; + } + } + break; + default: + throw new antlr.NoViableAltException(this); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public taskCondition(): TaskConditionContext { + let localContext = new TaskConditionContext(this.context, this.state); + this.enterRule(localContext, 38, QueryLangParser.RULE_taskCondition); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 401; + this.taskComparisons(); + this.state = 403; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 43, this.context) ) { + case 1: + { + this.state = 402; + this.match(QueryLangParser.SPACE); + } + break; + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public userConditions(): UserConditionsContext { + let localContext = new UserConditionsContext(this.context, this.state); + this.enterRule(localContext, 40, QueryLangParser.RULE_userConditions); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 405; + this.userOrExpression(); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public userOrExpression(): UserOrExpressionContext { + let localContext = new UserOrExpressionContext(this.context, this.state); + this.enterRule(localContext, 42, QueryLangParser.RULE_userOrExpression); + try { + let alternative: number; + this.enterOuterAlt(localContext, 1); + { + this.state = 407; + this.userAndExpression(); + this.state = 414; + this.errorHandler.sync(this); + alternative = this.interpreter.adaptivePredict(this.tokenStream, 44, this.context); + while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) { + if (alternative === 1) { + { + { + this.state = 408; + this.match(QueryLangParser.SPACE); + this.state = 409; + this.match(QueryLangParser.OR); + this.state = 410; + this.match(QueryLangParser.SPACE); + this.state = 411; + this.userAndExpression(); + } + } + } + this.state = 416; + this.errorHandler.sync(this); + alternative = this.interpreter.adaptivePredict(this.tokenStream, 44, this.context); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public userAndExpression(): UserAndExpressionContext { + let localContext = new UserAndExpressionContext(this.context, this.state); + this.enterRule(localContext, 44, QueryLangParser.RULE_userAndExpression); + try { + let alternative: number; + this.enterOuterAlt(localContext, 1); + { + this.state = 417; + this.userConditionGroup(); + this.state = 424; + this.errorHandler.sync(this); + alternative = this.interpreter.adaptivePredict(this.tokenStream, 45, this.context); + while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) { + if (alternative === 1) { + { + { + this.state = 418; + this.match(QueryLangParser.SPACE); + this.state = 419; + this.match(QueryLangParser.AND); + this.state = 420; + this.match(QueryLangParser.SPACE); + this.state = 421; + this.userConditionGroup(); + } + } + } + this.state = 426; + this.errorHandler.sync(this); + alternative = this.interpreter.adaptivePredict(this.tokenStream, 45, this.context); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public userConditionGroup(): UserConditionGroupContext { + let localContext = new UserConditionGroupContext(this.context, this.state); + this.enterRule(localContext, 46, QueryLangParser.RULE_userConditionGroup); + let _la: number; + try { + this.state = 446; + this.errorHandler.sync(this); + switch (this.tokenStream.LA(1)) { + case QueryLangParser.ID: + case QueryLangParser.NAME: + case QueryLangParser.SURNAME: + case QueryLangParser.EMAIL: + localContext = new UserConditionGroupBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 427; + this.userCondition(); + } + break; + case QueryLangParser.T__0: + case QueryLangParser.NOT: + localContext = new UserConditionGroupParenthesisContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 432; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 11) { + { + this.state = 428; + this.match(QueryLangParser.NOT); + this.state = 430; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 429; + this.match(QueryLangParser.SPACE); + } + } + + } + } + + this.state = 434; + this.match(QueryLangParser.T__0); + this.state = 436; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 435; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 438; + this.userConditions(); + this.state = 440; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 439; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 442; + this.match(QueryLangParser.T__1); + this.state = 444; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 50, this.context) ) { + case 1: + { + this.state = 443; + this.match(QueryLangParser.SPACE); + } + break; + } + } + break; + default: + throw new antlr.NoViableAltException(this); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public userCondition(): UserConditionContext { + let localContext = new UserConditionContext(this.context, this.state); + this.enterRule(localContext, 48, QueryLangParser.RULE_userCondition); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 448; + this.userComparisons(); + this.state = 450; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 52, this.context) ) { + case 1: + { + this.state = 449; + this.match(QueryLangParser.SPACE); + } + break; + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public delimeter(): DelimeterContext { + let localContext = new DelimeterContext(this.context, this.state); + this.enterRule(localContext, 50, QueryLangParser.RULE_delimeter); + let _la: number; + try { + this.state = 460; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 54, this.context) ) { + case 1: + this.enterOuterAlt(localContext, 1); + { + this.state = 452; + this.match(QueryLangParser.SPACE); + this.state = 453; + this.match(QueryLangParser.WHERE); + this.state = 454; + this.match(QueryLangParser.SPACE); + } + break; + case 2: + this.enterOuterAlt(localContext, 2); + { + this.state = 456; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 455; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 458; + this.match(QueryLangParser.T__2); + this.state = 459; + this.match(QueryLangParser.SPACE); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public paging(): PagingContext { + let localContext = new PagingContext(this.context, this.state); + this.enterRule(localContext, 52, QueryLangParser.RULE_paging); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 462; + this.match(QueryLangParser.PAGE); + this.state = 463; + this.match(QueryLangParser.SPACE); + this.state = 464; + localContext._pageNum = this.match(QueryLangParser.INT); + this.state = 469; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 55, this.context) ) { + case 1: + { + this.state = 465; + this.match(QueryLangParser.SPACE); + this.state = 466; + this.match(QueryLangParser.SIZE); + this.state = 467; + this.match(QueryLangParser.SPACE); + this.state = 468; + localContext._pageSize = this.match(QueryLangParser.INT); + } + break; + } + this.state = 472; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 471; + this.match(QueryLangParser.SPACE); + } + } + + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public processSorting(): ProcessSortingContext { + let localContext = new ProcessSortingContext(this.context, this.state); + this.enterRule(localContext, 54, QueryLangParser.RULE_processSorting); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 474; + this.match(QueryLangParser.SORT_BY); + this.state = 475; + this.match(QueryLangParser.SPACE); + this.state = 476; + this.processAttributeOrdering(); + this.state = 484; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while (_la === 4) { + { + { + this.state = 477; + this.match(QueryLangParser.T__3); + this.state = 479; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 478; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 481; + this.processAttributeOrdering(); + } + } + this.state = 486; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + this.state = 488; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 487; + this.match(QueryLangParser.SPACE); + } + } + + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public processAttributeOrdering(): ProcessAttributeOrderingContext { + let localContext = new ProcessAttributeOrderingContext(this.context, this.state); + this.enterRule(localContext, 56, QueryLangParser.RULE_processAttributeOrdering); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 490; + this.processAttribute(); + this.state = 493; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 60, this.context) ) { + case 1: + { + this.state = 491; + this.match(QueryLangParser.SPACE); + this.state = 492; + localContext._ordering = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 55 || _la === 56)) { + localContext._ordering = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + break; + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public processAttribute(): ProcessAttributeContext { + let localContext = new ProcessAttributeContext(this.context, this.state); + this.enterRule(localContext, 58, QueryLangParser.RULE_processAttribute); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 495; + _la = this.tokenStream.LA(1); + if(!(((((_la - 28)) & ~0x1F) === 0 && ((1 << (_la - 28)) & 31) !== 0))) { + this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public caseSorting(): CaseSortingContext { + let localContext = new CaseSortingContext(this.context, this.state); + this.enterRule(localContext, 60, QueryLangParser.RULE_caseSorting); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 497; + this.match(QueryLangParser.SORT_BY); + this.state = 498; + this.match(QueryLangParser.SPACE); + this.state = 499; + this.caseAttributeOrdering(); + this.state = 507; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while (_la === 4) { + { + { + this.state = 500; + this.match(QueryLangParser.T__3); + this.state = 502; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 501; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 504; + this.caseAttributeOrdering(); + } + } + this.state = 509; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + this.state = 511; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 510; + this.match(QueryLangParser.SPACE); + } + } + + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public caseAttributeOrdering(): CaseAttributeOrderingContext { + let localContext = new CaseAttributeOrderingContext(this.context, this.state); + this.enterRule(localContext, 62, QueryLangParser.RULE_caseAttributeOrdering); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 513; + this.caseAttribute(); + this.state = 516; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 64, this.context) ) { + case 1: + { + this.state = 514; + this.match(QueryLangParser.SPACE); + this.state = 515; + localContext._ordering = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 55 || _la === 56)) { + localContext._ordering = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + break; + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public caseAttribute(): CaseAttributeContext { + let localContext = new CaseAttributeContext(this.context, this.state); + this.enterRule(localContext, 64, QueryLangParser.RULE_caseAttribute); + try { + this.state = 529; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 65, this.context) ) { + case 1: + this.enterOuterAlt(localContext, 1); + { + this.state = 518; + this.match(QueryLangParser.ID); + } + break; + case 2: + this.enterOuterAlt(localContext, 2); + { + this.state = 519; + this.match(QueryLangParser.PROCESS_ID); + } + break; + case 3: + this.enterOuterAlt(localContext, 3); + { + this.state = 520; + this.match(QueryLangParser.PROCESS_IDENTIFIER); + } + break; + case 4: + this.enterOuterAlt(localContext, 4); + { + this.state = 521; + this.match(QueryLangParser.TITLE); + } + break; + case 5: + this.enterOuterAlt(localContext, 5); + { + this.state = 522; + this.match(QueryLangParser.CREATION_DATE); + } + break; + case 6: + this.enterOuterAlt(localContext, 6); + { + this.state = 523; + this.match(QueryLangParser.AUTHOR); + } + break; + case 7: + this.enterOuterAlt(localContext, 7); + { + this.state = 524; + this.places(); + } + break; + case 8: + this.enterOuterAlt(localContext, 8); + { + this.state = 525; + this.tasksUserId(); + } + break; + case 9: + this.enterOuterAlt(localContext, 9); + { + this.state = 526; + this.tasksState(); + } + break; + case 10: + this.enterOuterAlt(localContext, 10); + { + this.state = 527; + this.dataValue(); + } + break; + case 11: + this.enterOuterAlt(localContext, 11); + { + this.state = 528; + this.dataOptions(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public taskSorting(): TaskSortingContext { + let localContext = new TaskSortingContext(this.context, this.state); + this.enterRule(localContext, 66, QueryLangParser.RULE_taskSorting); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 531; + this.match(QueryLangParser.SORT_BY); + this.state = 532; + this.match(QueryLangParser.SPACE); + this.state = 533; + this.taskAttributeOrdering(); + this.state = 541; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while (_la === 4) { + { + { + this.state = 534; + this.match(QueryLangParser.T__3); + this.state = 536; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 535; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 538; + this.taskAttributeOrdering(); + } + } + this.state = 543; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + this.state = 545; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 544; + this.match(QueryLangParser.SPACE); + } + } + + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public taskAttributeOrdering(): TaskAttributeOrderingContext { + let localContext = new TaskAttributeOrderingContext(this.context, this.state); + this.enterRule(localContext, 68, QueryLangParser.RULE_taskAttributeOrdering); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 547; + this.taskAttribute(); + this.state = 550; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 69, this.context) ) { + case 1: + { + this.state = 548; + this.match(QueryLangParser.SPACE); + this.state = 549; + localContext._ordering = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 55 || _la === 56)) { + localContext._ordering = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + break; + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public taskAttribute(): TaskAttributeContext { + let localContext = new TaskAttributeContext(this.context, this.state); + this.enterRule(localContext, 70, QueryLangParser.RULE_taskAttribute); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 552; + _la = this.tokenStream.LA(1); + if(!(((((_la - 28)) & ~0x1F) === 0 && ((1 << (_la - 28)) & 32291) !== 0))) { + this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public userSorting(): UserSortingContext { + let localContext = new UserSortingContext(this.context, this.state); + this.enterRule(localContext, 72, QueryLangParser.RULE_userSorting); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 554; + this.match(QueryLangParser.SORT_BY); + this.state = 555; + this.match(QueryLangParser.SPACE); + this.state = 556; + this.userAttributeOrdering(); + this.state = 564; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while (_la === 4) { + { + { + this.state = 557; + this.match(QueryLangParser.T__3); + this.state = 559; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 558; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 561; + this.userAttributeOrdering(); + } + } + this.state = 566; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + this.state = 568; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 567; + this.match(QueryLangParser.SPACE); + } + } + + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public userAttributeOrdering(): UserAttributeOrderingContext { + let localContext = new UserAttributeOrderingContext(this.context, this.state); + this.enterRule(localContext, 74, QueryLangParser.RULE_userAttributeOrdering); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 570; + this.userAttribute(); + this.state = 573; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 73, this.context) ) { + case 1: + { + this.state = 571; + this.match(QueryLangParser.SPACE); + this.state = 572; + localContext._ordering = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 55 || _la === 56)) { + localContext._ordering = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + break; + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public userAttribute(): UserAttributeContext { + let localContext = new UserAttributeContext(this.context, this.state); + this.enterRule(localContext, 76, QueryLangParser.RULE_userAttribute); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 575; + _la = this.tokenStream.LA(1); + if(!(((((_la - 28)) & ~0x1F) === 0 && ((1 << (_la - 28)) & 229377) !== 0))) { + this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public processComparisons(): ProcessComparisonsContext { + let localContext = new ProcessComparisonsContext(this.context, this.state); + this.enterRule(localContext, 78, QueryLangParser.RULE_processComparisons); + try { + this.state = 582; + this.errorHandler.sync(this); + switch (this.tokenStream.LA(1)) { + case QueryLangParser.ID: + this.enterOuterAlt(localContext, 1); + { + this.state = 577; + this.idComparison(); + } + break; + case QueryLangParser.IDENTIFIER: + this.enterOuterAlt(localContext, 2); + { + this.state = 578; + this.identifierComparison(); + } + break; + case QueryLangParser.VERSION: + this.enterOuterAlt(localContext, 3); + { + this.state = 579; + this.versionComparison(); + } + break; + case QueryLangParser.TITLE: + this.enterOuterAlt(localContext, 4); + { + this.state = 580; + this.titleComparison(); + } + break; + case QueryLangParser.CREATION_DATE: + this.enterOuterAlt(localContext, 5); + { + this.state = 581; + this.creationDateComparison(); + } + break; + default: + throw new antlr.NoViableAltException(this); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public caseComparisons(): CaseComparisonsContext { + let localContext = new CaseComparisonsContext(this.context, this.state); + this.enterRule(localContext, 80, QueryLangParser.RULE_caseComparisons); + try { + this.state = 595; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 75, this.context) ) { + case 1: + this.enterOuterAlt(localContext, 1); + { + this.state = 584; + this.idComparison(); + } + break; + case 2: + this.enterOuterAlt(localContext, 2); + { + this.state = 585; + this.processIdObjIdComparison(); + } + break; + case 3: + this.enterOuterAlt(localContext, 3); + { + this.state = 586; + this.processIdentifierComparison(); + } + break; + case 4: + this.enterOuterAlt(localContext, 4); + { + this.state = 587; + this.titleComparison(); + } + break; + case 5: + this.enterOuterAlt(localContext, 5); + { + this.state = 588; + this.creationDateComparison(); + } + break; + case 6: + this.enterOuterAlt(localContext, 6); + { + this.state = 589; + this.authorComparison(); + } + break; + case 7: + this.enterOuterAlt(localContext, 7); + { + this.state = 590; + this.placesComparison(); + } + break; + case 8: + this.enterOuterAlt(localContext, 8); + { + this.state = 591; + this.tasksStateComparison(); + } + break; + case 9: + this.enterOuterAlt(localContext, 9); + { + this.state = 592; + this.tasksUserIdComparison(); + } + break; + case 10: + this.enterOuterAlt(localContext, 10); + { + this.state = 593; + this.dataValueComparison(); + } + break; + case 11: + this.enterOuterAlt(localContext, 11); + { + this.state = 594; + this.dataOptionsComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public taskComparisons(): TaskComparisonsContext { + let localContext = new TaskComparisonsContext(this.context, this.state); + this.enterRule(localContext, 82, QueryLangParser.RULE_taskComparisons); + try { + this.state = 606; + this.errorHandler.sync(this); + switch (this.tokenStream.LA(1)) { + case QueryLangParser.ID: + this.enterOuterAlt(localContext, 1); + { + this.state = 597; + this.idComparison(); + } + break; + case QueryLangParser.TRANSITION_ID: + this.enterOuterAlt(localContext, 2); + { + this.state = 598; + this.transitionIdComparison(); + } + break; + case QueryLangParser.TITLE: + this.enterOuterAlt(localContext, 3); + { + this.state = 599; + this.titleComparison(); + } + break; + case QueryLangParser.STATE: + this.enterOuterAlt(localContext, 4); + { + this.state = 600; + this.stateComparison(); + } + break; + case QueryLangParser.USER_ID: + this.enterOuterAlt(localContext, 5); + { + this.state = 601; + this.userIdComparison(); + } + break; + case QueryLangParser.CASE_ID: + this.enterOuterAlt(localContext, 6); + { + this.state = 602; + this.caseIdComparison(); + } + break; + case QueryLangParser.PROCESS_ID: + this.enterOuterAlt(localContext, 7); + { + this.state = 603; + this.processIdComparison(); + } + break; + case QueryLangParser.LAST_ASSIGN: + this.enterOuterAlt(localContext, 8); + { + this.state = 604; + this.lastAssignComparison(); + } + break; + case QueryLangParser.LAST_FINISH: + this.enterOuterAlt(localContext, 9); + { + this.state = 605; + this.lastFinishComparison(); + } + break; + default: + throw new antlr.NoViableAltException(this); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public userComparisons(): UserComparisonsContext { + let localContext = new UserComparisonsContext(this.context, this.state); + this.enterRule(localContext, 84, QueryLangParser.RULE_userComparisons); + try { + this.state = 612; + this.errorHandler.sync(this); + switch (this.tokenStream.LA(1)) { + case QueryLangParser.ID: + this.enterOuterAlt(localContext, 1); + { + this.state = 608; + this.idComparison(); + } + break; + case QueryLangParser.NAME: + this.enterOuterAlt(localContext, 2); + { + this.state = 609; + this.nameComparison(); + } + break; + case QueryLangParser.SURNAME: + this.enterOuterAlt(localContext, 3); + { + this.state = 610; + this.surnameComparison(); + } + break; + case QueryLangParser.EMAIL: + this.enterOuterAlt(localContext, 4); + { + this.state = 611; + this.emailComparison(); + } + break; + default: + throw new antlr.NoViableAltException(this); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public idComparison(): IdComparisonContext { + let localContext = new IdComparisonContext(this.context, this.state); + this.enterRule(localContext, 86, QueryLangParser.RULE_idComparison); + try { + this.state = 623; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 78, this.context) ) { + case 1: + localContext = new IdBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 614; + this.match(QueryLangParser.ID); + this.state = 615; + this.match(QueryLangParser.SPACE); + this.state = 616; + this.objectIdComparison(); + } + break; + case 2: + localContext = new IdListContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 617; + this.match(QueryLangParser.ID); + this.state = 618; + this.match(QueryLangParser.SPACE); + this.state = 619; + this.inListStringComparison(); + } + break; + case 3: + localContext = new IdNullContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 620; + this.match(QueryLangParser.ID); + this.state = 621; + this.match(QueryLangParser.SPACE); + this.state = 622; + this.nullComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public titleComparison(): TitleComparisonContext { + let localContext = new TitleComparisonContext(this.context, this.state); + this.enterRule(localContext, 88, QueryLangParser.RULE_titleComparison); + try { + this.state = 640; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 79, this.context) ) { + case 1: + localContext = new TitleBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 625; + this.match(QueryLangParser.TITLE); + this.state = 626; + this.match(QueryLangParser.SPACE); + this.state = 627; + this.stringComparison(); + } + break; + case 2: + localContext = new TitleLikeContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 628; + this.match(QueryLangParser.TITLE); + this.state = 629; + this.match(QueryLangParser.SPACE); + this.state = 630; + this.stringLikeComparison(); + } + break; + case 3: + localContext = new TitleListContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 631; + this.match(QueryLangParser.TITLE); + this.state = 632; + this.match(QueryLangParser.SPACE); + this.state = 633; + this.inListStringComparison(); + } + break; + case 4: + localContext = new TitleRangeContext(localContext); + this.enterOuterAlt(localContext, 4); + { + this.state = 634; + this.match(QueryLangParser.TITLE); + this.state = 635; + this.match(QueryLangParser.SPACE); + this.state = 636; + this.inRangeStringComparison(); + } + break; + case 5: + localContext = new TitleNullContext(localContext); + this.enterOuterAlt(localContext, 5); + { + this.state = 637; + this.match(QueryLangParser.TITLE); + this.state = 638; + this.match(QueryLangParser.SPACE); + this.state = 639; + this.nullComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public identifierComparison(): IdentifierComparisonContext { + let localContext = new IdentifierComparisonContext(this.context, this.state); + this.enterRule(localContext, 90, QueryLangParser.RULE_identifierComparison); + try { + this.state = 654; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 80, this.context) ) { + case 1: + localContext = new IdentifierBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 642; + this.match(QueryLangParser.IDENTIFIER); + this.state = 643; + this.match(QueryLangParser.SPACE); + this.state = 644; + this.stringComparison(); + } + break; + case 2: + localContext = new IdentifierListContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 645; + this.match(QueryLangParser.IDENTIFIER); + this.state = 646; + this.match(QueryLangParser.SPACE); + this.state = 647; + this.inListStringComparison(); + } + break; + case 3: + localContext = new IdentifierRangeContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 648; + this.match(QueryLangParser.IDENTIFIER); + this.state = 649; + this.match(QueryLangParser.SPACE); + this.state = 650; + this.inRangeStringComparison(); + } + break; + case 4: + localContext = new IdentifierNullContext(localContext); + this.enterOuterAlt(localContext, 4); + { + this.state = 651; + this.match(QueryLangParser.IDENTIFIER); + this.state = 652; + this.match(QueryLangParser.SPACE); + this.state = 653; + this.nullComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public versionComparison(): VersionComparisonContext { + let localContext = new VersionComparisonContext(this.context, this.state); + this.enterRule(localContext, 92, QueryLangParser.RULE_versionComparison); + let _la: number; + try { + this.state = 676; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 83, this.context) ) { + case 1: + localContext = new VersionBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 656; + this.match(QueryLangParser.VERSION); + this.state = 657; + this.match(QueryLangParser.SPACE); + this.state = 662; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 11) { + { + this.state = 658; + this.match(QueryLangParser.NOT); + this.state = 660; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 659; + this.match(QueryLangParser.SPACE); + } + } + + } + } + + this.state = 664; + (localContext as VersionBasicContext)._op = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 249856) !== 0))) { + (localContext as VersionBasicContext)._op = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + this.state = 665; + this.match(QueryLangParser.SPACE); + this.state = 666; + this.match(QueryLangParser.VERSION_NUMBER); + } + break; + case 2: + localContext = new VersionListCmpContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 667; + this.match(QueryLangParser.VERSION); + this.state = 668; + this.match(QueryLangParser.SPACE); + this.state = 669; + this.inListVersionComparison(); + } + break; + case 3: + localContext = new VersionRangeCmpContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 670; + this.match(QueryLangParser.VERSION); + this.state = 671; + this.match(QueryLangParser.SPACE); + this.state = 672; + this.inRangeVersionComparison(); + } + break; + case 4: + localContext = new VersionNullContext(localContext); + this.enterOuterAlt(localContext, 4); + { + this.state = 673; + this.match(QueryLangParser.VERSION); + this.state = 674; + this.match(QueryLangParser.SPACE); + this.state = 675; + this.nullComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public creationDateComparison(): CreationDateComparisonContext { + let localContext = new CreationDateComparisonContext(this.context, this.state); + this.enterRule(localContext, 94, QueryLangParser.RULE_creationDateComparison); + try { + this.state = 693; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 84, this.context) ) { + case 1: + localContext = new CdDateBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 678; + this.match(QueryLangParser.CREATION_DATE); + this.state = 679; + this.match(QueryLangParser.SPACE); + this.state = 680; + this.dateComparison(); + } + break; + case 2: + localContext = new CdDateTimeBasicContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 681; + this.match(QueryLangParser.CREATION_DATE); + this.state = 682; + this.match(QueryLangParser.SPACE); + this.state = 683; + this.dateTimeComparison(); + } + break; + case 3: + localContext = new CdDateListContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 684; + this.match(QueryLangParser.CREATION_DATE); + this.state = 685; + this.match(QueryLangParser.SPACE); + this.state = 686; + this.inListDateComparison(); + } + break; + case 4: + localContext = new CdDateRangeContext(localContext); + this.enterOuterAlt(localContext, 4); + { + this.state = 687; + this.match(QueryLangParser.CREATION_DATE); + this.state = 688; + this.match(QueryLangParser.SPACE); + this.state = 689; + this.inRangeDateComparison(); + } + break; + case 5: + localContext = new CdNullContext(localContext); + this.enterOuterAlt(localContext, 5); + { + this.state = 690; + this.match(QueryLangParser.CREATION_DATE); + this.state = 691; + this.match(QueryLangParser.SPACE); + this.state = 692; + this.nullComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public processIdComparison(): ProcessIdComparisonContext { + let localContext = new ProcessIdComparisonContext(this.context, this.state); + this.enterRule(localContext, 96, QueryLangParser.RULE_processIdComparison); + try { + this.state = 704; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 85, this.context) ) { + case 1: + localContext = new ProcessIdBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 695; + this.match(QueryLangParser.PROCESS_ID); + this.state = 696; + this.match(QueryLangParser.SPACE); + this.state = 697; + this.stringComparison(); + } + break; + case 2: + localContext = new ProcessIdListContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 698; + this.match(QueryLangParser.PROCESS_ID); + this.state = 699; + this.match(QueryLangParser.SPACE); + this.state = 700; + this.inListStringComparison(); + } + break; + case 3: + localContext = new ProcessIdNullContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 701; + this.match(QueryLangParser.PROCESS_ID); + this.state = 702; + this.match(QueryLangParser.SPACE); + this.state = 703; + this.nullComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public processIdObjIdComparison(): ProcessIdObjIdComparisonContext { + let localContext = new ProcessIdObjIdComparisonContext(this.context, this.state); + this.enterRule(localContext, 98, QueryLangParser.RULE_processIdObjIdComparison); + try { + this.state = 715; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 86, this.context) ) { + case 1: + localContext = new ProcessIdObjIdBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 706; + this.match(QueryLangParser.PROCESS_ID); + this.state = 707; + this.match(QueryLangParser.SPACE); + this.state = 708; + this.objectIdComparison(); + } + break; + case 2: + localContext = new ProcessIdObjIdListContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 709; + this.match(QueryLangParser.PROCESS_ID); + this.state = 710; + this.match(QueryLangParser.SPACE); + this.state = 711; + this.inListStringComparison(); + } + break; + case 3: + localContext = new ProcessIdObjNullContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 712; + this.match(QueryLangParser.PROCESS_ID); + this.state = 713; + this.match(QueryLangParser.SPACE); + this.state = 714; + this.nullComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public processIdentifierComparison(): ProcessIdentifierComparisonContext { + let localContext = new ProcessIdentifierComparisonContext(this.context, this.state); + this.enterRule(localContext, 100, QueryLangParser.RULE_processIdentifierComparison); + try { + this.state = 729; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 87, this.context) ) { + case 1: + localContext = new ProcessIdentifierBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 717; + this.match(QueryLangParser.PROCESS_IDENTIFIER); + this.state = 718; + this.match(QueryLangParser.SPACE); + this.state = 719; + this.stringComparison(); + } + break; + case 2: + localContext = new ProcessIdentifierListContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 720; + this.match(QueryLangParser.PROCESS_IDENTIFIER); + this.state = 721; + this.match(QueryLangParser.SPACE); + this.state = 722; + this.inListStringComparison(); + } + break; + case 3: + localContext = new ProcessIdentifierRangeContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 723; + this.match(QueryLangParser.PROCESS_IDENTIFIER); + this.state = 724; + this.match(QueryLangParser.SPACE); + this.state = 725; + this.inRangeStringComparison(); + } + break; + case 4: + localContext = new ProcessIdentifierNullContext(localContext); + this.enterOuterAlt(localContext, 4); + { + this.state = 726; + this.match(QueryLangParser.PROCESS_IDENTIFIER); + this.state = 727; + this.match(QueryLangParser.SPACE); + this.state = 728; + this.nullComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public authorComparison(): AuthorComparisonContext { + let localContext = new AuthorComparisonContext(this.context, this.state); + this.enterRule(localContext, 102, QueryLangParser.RULE_authorComparison); + try { + this.state = 740; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 88, this.context) ) { + case 1: + localContext = new AuthorBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 731; + this.match(QueryLangParser.AUTHOR); + this.state = 732; + this.match(QueryLangParser.SPACE); + this.state = 733; + this.stringComparison(); + } + break; + case 2: + localContext = new AuthorListContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 734; + this.match(QueryLangParser.AUTHOR); + this.state = 735; + this.match(QueryLangParser.SPACE); + this.state = 736; + this.inListStringComparison(); + } + break; + case 3: + localContext = new AuthorNullContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 737; + this.match(QueryLangParser.AUTHOR); + this.state = 738; + this.match(QueryLangParser.SPACE); + this.state = 739; + this.nullComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public transitionIdComparison(): TransitionIdComparisonContext { + let localContext = new TransitionIdComparisonContext(this.context, this.state); + this.enterRule(localContext, 104, QueryLangParser.RULE_transitionIdComparison); + try { + this.state = 754; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 89, this.context) ) { + case 1: + localContext = new TransitionIdBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 742; + this.match(QueryLangParser.TRANSITION_ID); + this.state = 743; + this.match(QueryLangParser.SPACE); + this.state = 744; + this.stringComparison(); + } + break; + case 2: + localContext = new TransitionIdListContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 745; + this.match(QueryLangParser.TRANSITION_ID); + this.state = 746; + this.match(QueryLangParser.SPACE); + this.state = 747; + this.inListStringComparison(); + } + break; + case 3: + localContext = new TransitionIdRangeContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 748; + this.match(QueryLangParser.TRANSITION_ID); + this.state = 749; + this.match(QueryLangParser.SPACE); + this.state = 750; + this.inRangeStringComparison(); + } + break; + case 4: + localContext = new TransitionIdNullContext(localContext); + this.enterOuterAlt(localContext, 4); + { + this.state = 751; + this.match(QueryLangParser.TRANSITION_ID); + this.state = 752; + this.match(QueryLangParser.SPACE); + this.state = 753; + this.nullComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public stateComparison(): StateComparisonContext { + let localContext = new StateComparisonContext(this.context, this.state); + this.enterRule(localContext, 106, QueryLangParser.RULE_stateComparison); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 756; + this.match(QueryLangParser.STATE); + this.state = 757; + this.match(QueryLangParser.SPACE); + this.state = 758; + this.match(QueryLangParser.EQ); + this.state = 759; + this.match(QueryLangParser.SPACE); + this.state = 760; + localContext._state = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 50 || _la === 51)) { + localContext._state = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public userIdComparison(): UserIdComparisonContext { + let localContext = new UserIdComparisonContext(this.context, this.state); + this.enterRule(localContext, 108, QueryLangParser.RULE_userIdComparison); + try { + this.state = 771; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 90, this.context) ) { + case 1: + localContext = new UserIdBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 762; + this.match(QueryLangParser.USER_ID); + this.state = 763; + this.match(QueryLangParser.SPACE); + this.state = 764; + this.stringComparison(); + } + break; + case 2: + localContext = new UserIdListContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 765; + this.match(QueryLangParser.USER_ID); + this.state = 766; + this.match(QueryLangParser.SPACE); + this.state = 767; + this.inListStringComparison(); + } + break; + case 3: + localContext = new UserIdNullContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 768; + this.match(QueryLangParser.USER_ID); + this.state = 769; + this.match(QueryLangParser.SPACE); + this.state = 770; + this.nullComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public caseIdComparison(): CaseIdComparisonContext { + let localContext = new CaseIdComparisonContext(this.context, this.state); + this.enterRule(localContext, 110, QueryLangParser.RULE_caseIdComparison); + try { + this.state = 782; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 91, this.context) ) { + case 1: + localContext = new CaseIdBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 773; + this.match(QueryLangParser.CASE_ID); + this.state = 774; + this.match(QueryLangParser.SPACE); + this.state = 775; + this.stringComparison(); + } + break; + case 2: + localContext = new CaseIdListContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 776; + this.match(QueryLangParser.CASE_ID); + this.state = 777; + this.match(QueryLangParser.SPACE); + this.state = 778; + this.inListStringComparison(); + } + break; + case 3: + localContext = new CaseIdNullContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 779; + this.match(QueryLangParser.CASE_ID); + this.state = 780; + this.match(QueryLangParser.SPACE); + this.state = 781; + this.nullComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public lastAssignComparison(): LastAssignComparisonContext { + let localContext = new LastAssignComparisonContext(this.context, this.state); + this.enterRule(localContext, 112, QueryLangParser.RULE_lastAssignComparison); + try { + this.state = 799; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 92, this.context) ) { + case 1: + localContext = new LaDateBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 784; + this.match(QueryLangParser.LAST_ASSIGN); + this.state = 785; + this.match(QueryLangParser.SPACE); + this.state = 786; + this.dateComparison(); + } + break; + case 2: + localContext = new LaDateTimeBasicContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 787; + this.match(QueryLangParser.LAST_ASSIGN); + this.state = 788; + this.match(QueryLangParser.SPACE); + this.state = 789; + this.dateTimeComparison(); + } + break; + case 3: + localContext = new LaDateListContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 790; + this.match(QueryLangParser.LAST_ASSIGN); + this.state = 791; + this.match(QueryLangParser.SPACE); + this.state = 792; + this.inListDateComparison(); + } + break; + case 4: + localContext = new LaDateRangeContext(localContext); + this.enterOuterAlt(localContext, 4); + { + this.state = 793; + this.match(QueryLangParser.LAST_ASSIGN); + this.state = 794; + this.match(QueryLangParser.SPACE); + this.state = 795; + this.inRangeDateComparison(); + } + break; + case 5: + localContext = new LaNullContext(localContext); + this.enterOuterAlt(localContext, 5); + { + this.state = 796; + this.match(QueryLangParser.LAST_ASSIGN); + this.state = 797; + this.match(QueryLangParser.SPACE); + this.state = 798; + this.nullComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public lastFinishComparison(): LastFinishComparisonContext { + let localContext = new LastFinishComparisonContext(this.context, this.state); + this.enterRule(localContext, 114, QueryLangParser.RULE_lastFinishComparison); + try { + this.state = 816; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 93, this.context) ) { + case 1: + localContext = new LfDateBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 801; + this.match(QueryLangParser.LAST_FINISH); + this.state = 802; + this.match(QueryLangParser.SPACE); + this.state = 803; + this.dateComparison(); + } + break; + case 2: + localContext = new LfDateTimeBasicContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 804; + this.match(QueryLangParser.LAST_FINISH); + this.state = 805; + this.match(QueryLangParser.SPACE); + this.state = 806; + this.dateTimeComparison(); + } + break; + case 3: + localContext = new LfDateListContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 807; + this.match(QueryLangParser.LAST_FINISH); + this.state = 808; + this.match(QueryLangParser.SPACE); + this.state = 809; + this.inListDateComparison(); + } + break; + case 4: + localContext = new LfDateRangeContext(localContext); + this.enterOuterAlt(localContext, 4); + { + this.state = 810; + this.match(QueryLangParser.LAST_FINISH); + this.state = 811; + this.match(QueryLangParser.SPACE); + this.state = 812; + this.inRangeDateComparison(); + } + break; + case 5: + localContext = new LfNullContext(localContext); + this.enterOuterAlt(localContext, 5); + { + this.state = 813; + this.match(QueryLangParser.LAST_FINISH); + this.state = 814; + this.match(QueryLangParser.SPACE); + this.state = 815; + this.nullComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public nameComparison(): NameComparisonContext { + let localContext = new NameComparisonContext(this.context, this.state); + this.enterRule(localContext, 116, QueryLangParser.RULE_nameComparison); + try { + this.state = 830; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 94, this.context) ) { + case 1: + localContext = new NameBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 818; + this.match(QueryLangParser.NAME); + this.state = 819; + this.match(QueryLangParser.SPACE); + this.state = 820; + this.stringComparison(); + } + break; + case 2: + localContext = new NameListContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 821; + this.match(QueryLangParser.NAME); + this.state = 822; + this.match(QueryLangParser.SPACE); + this.state = 823; + this.inListStringComparison(); + } + break; + case 3: + localContext = new NameRangeContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 824; + this.match(QueryLangParser.NAME); + this.state = 825; + this.match(QueryLangParser.SPACE); + this.state = 826; + this.inRangeStringComparison(); + } + break; + case 4: + localContext = new NameNullContext(localContext); + this.enterOuterAlt(localContext, 4); + { + this.state = 827; + this.match(QueryLangParser.NAME); + this.state = 828; + this.match(QueryLangParser.SPACE); + this.state = 829; + this.nullComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public surnameComparison(): SurnameComparisonContext { + let localContext = new SurnameComparisonContext(this.context, this.state); + this.enterRule(localContext, 118, QueryLangParser.RULE_surnameComparison); + try { + this.state = 844; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 95, this.context) ) { + case 1: + localContext = new SurnameBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 832; + this.match(QueryLangParser.SURNAME); + this.state = 833; + this.match(QueryLangParser.SPACE); + this.state = 834; + this.stringComparison(); + } + break; + case 2: + localContext = new SurnameListContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 835; + this.match(QueryLangParser.SURNAME); + this.state = 836; + this.match(QueryLangParser.SPACE); + this.state = 837; + this.inListStringComparison(); + } + break; + case 3: + localContext = new SurnameRangeContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 838; + this.match(QueryLangParser.SURNAME); + this.state = 839; + this.match(QueryLangParser.SPACE); + this.state = 840; + this.inRangeStringComparison(); + } + break; + case 4: + localContext = new SurnameNullContext(localContext); + this.enterOuterAlt(localContext, 4); + { + this.state = 841; + this.match(QueryLangParser.SURNAME); + this.state = 842; + this.match(QueryLangParser.SPACE); + this.state = 843; + this.nullComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public emailComparison(): EmailComparisonContext { + let localContext = new EmailComparisonContext(this.context, this.state); + this.enterRule(localContext, 120, QueryLangParser.RULE_emailComparison); + try { + this.state = 858; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 96, this.context) ) { + case 1: + localContext = new EmailBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 846; + this.match(QueryLangParser.EMAIL); + this.state = 847; + this.match(QueryLangParser.SPACE); + this.state = 848; + this.stringComparison(); + } + break; + case 2: + localContext = new EmailListContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 849; + this.match(QueryLangParser.EMAIL); + this.state = 850; + this.match(QueryLangParser.SPACE); + this.state = 851; + this.inListStringComparison(); + } + break; + case 3: + localContext = new EmailRangeContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 852; + this.match(QueryLangParser.EMAIL); + this.state = 853; + this.match(QueryLangParser.SPACE); + this.state = 854; + this.inRangeStringComparison(); + } + break; + case 4: + localContext = new EmailNullContext(localContext); + this.enterOuterAlt(localContext, 4); + { + this.state = 855; + this.match(QueryLangParser.EMAIL); + this.state = 856; + this.match(QueryLangParser.SPACE); + this.state = 857; + this.nullComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public dataValueComparison(): DataValueComparisonContext { + let localContext = new DataValueComparisonContext(this.context, this.state); + this.enterRule(localContext, 122, QueryLangParser.RULE_dataValueComparison); + try { + this.state = 912; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 97, this.context) ) { + case 1: + localContext = new DataStringContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 860; + this.dataValue(); + this.state = 861; + this.match(QueryLangParser.SPACE); + this.state = 862; + this.stringComparison(); + } + break; + case 2: + localContext = new DataStringLikeContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 864; + this.dataValue(); + this.state = 865; + this.match(QueryLangParser.SPACE); + this.state = 866; + this.stringLikeComparison(); + } + break; + case 3: + localContext = new DataNumberContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 868; + this.dataValue(); + this.state = 869; + this.match(QueryLangParser.SPACE); + this.state = 870; + this.numberComparison(); + } + break; + case 4: + localContext = new DataDateContext(localContext); + this.enterOuterAlt(localContext, 4); + { + this.state = 872; + this.dataValue(); + this.state = 873; + this.match(QueryLangParser.SPACE); + this.state = 874; + this.dateComparison(); + } + break; + case 5: + localContext = new DataDatetimeContext(localContext); + this.enterOuterAlt(localContext, 5); + { + this.state = 876; + this.dataValue(); + this.state = 877; + this.match(QueryLangParser.SPACE); + this.state = 878; + this.dateTimeComparison(); + } + break; + case 6: + localContext = new DataBooleanContext(localContext); + this.enterOuterAlt(localContext, 6); + { + this.state = 880; + this.dataValue(); + this.state = 881; + this.match(QueryLangParser.SPACE); + this.state = 882; + this.booleanComparison(); + } + break; + case 7: + localContext = new DataStringListContext(localContext); + this.enterOuterAlt(localContext, 7); + { + this.state = 884; + this.dataValue(); + this.state = 885; + this.match(QueryLangParser.SPACE); + this.state = 886; + this.inListStringComparison(); + } + break; + case 8: + localContext = new DataNumberListContext(localContext); + this.enterOuterAlt(localContext, 8); + { + this.state = 888; + this.dataValue(); + this.state = 889; + this.match(QueryLangParser.SPACE); + this.state = 890; + this.inListNumberComparison(); + } + break; + case 9: + localContext = new DataDateListContext(localContext); + this.enterOuterAlt(localContext, 9); + { + this.state = 892; + this.dataValue(); + this.state = 893; + this.match(QueryLangParser.SPACE); + this.state = 894; + this.inListDateComparison(); + } + break; + case 10: + localContext = new DataStringRangeContext(localContext); + this.enterOuterAlt(localContext, 10); + { + this.state = 896; + this.dataValue(); + this.state = 897; + this.match(QueryLangParser.SPACE); + this.state = 898; + this.inRangeStringComparison(); + } + break; + case 11: + localContext = new DataNumberRangeContext(localContext); + this.enterOuterAlt(localContext, 11); + { + this.state = 900; + this.dataValue(); + this.state = 901; + this.match(QueryLangParser.SPACE); + this.state = 902; + this.inRangeNumberComparison(); + } + break; + case 12: + localContext = new DataDateRangeContext(localContext); + this.enterOuterAlt(localContext, 12); + { + this.state = 904; + this.dataValue(); + this.state = 905; + this.match(QueryLangParser.SPACE); + this.state = 906; + this.inRangeDateComparison(); + } + break; + case 13: + localContext = new DataNullContext(localContext); + this.enterOuterAlt(localContext, 13); + { + this.state = 908; + this.dataValue(); + this.state = 909; + this.match(QueryLangParser.SPACE); + this.state = 910; + this.nullComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public dataOptionsComparison(): DataOptionsComparisonContext { + let localContext = new DataOptionsComparisonContext(this.context, this.state); + this.enterRule(localContext, 124, QueryLangParser.RULE_dataOptionsComparison); + try { + this.state = 930; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 98, this.context) ) { + case 1: + localContext = new DataOptionsBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 914; + this.dataOptions(); + this.state = 915; + this.match(QueryLangParser.SPACE); + this.state = 916; + this.stringComparison(); + } + break; + case 2: + localContext = new DataOptionsListContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 918; + this.dataOptions(); + this.state = 919; + this.match(QueryLangParser.SPACE); + this.state = 920; + this.inListStringComparison(); + } + break; + case 3: + localContext = new DataOptionsRangeContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 922; + this.dataOptions(); + this.state = 923; + this.match(QueryLangParser.SPACE); + this.state = 924; + this.inRangeStringComparison(); + } + break; + case 4: + localContext = new DataOptionsNullContext(localContext); + this.enterOuterAlt(localContext, 4); + { + this.state = 926; + this.dataOptions(); + this.state = 927; + this.match(QueryLangParser.SPACE); + this.state = 928; + this.nullComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public placesComparison(): PlacesComparisonContext { + let localContext = new PlacesComparisonContext(this.context, this.state); + this.enterRule(localContext, 126, QueryLangParser.RULE_placesComparison); + try { + this.state = 948; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 99, this.context) ) { + case 1: + localContext = new PlacesBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 932; + this.places(); + this.state = 933; + this.match(QueryLangParser.SPACE); + this.state = 934; + this.numberComparison(); + } + break; + case 2: + localContext = new PlacesListContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 936; + this.places(); + this.state = 937; + this.match(QueryLangParser.SPACE); + this.state = 938; + this.inListNumberComparison(); + } + break; + case 3: + localContext = new PlacesRangeContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 940; + this.places(); + this.state = 941; + this.match(QueryLangParser.SPACE); + this.state = 942; + this.inRangeNumberComparison(); + } + break; + case 4: + localContext = new PlacesNullContext(localContext); + this.enterOuterAlt(localContext, 4); + { + this.state = 944; + this.places(); + this.state = 945; + this.match(QueryLangParser.SPACE); + this.state = 946; + this.nullComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public tasksStateComparison(): TasksStateComparisonContext { + let localContext = new TasksStateComparisonContext(this.context, this.state); + this.enterRule(localContext, 128, QueryLangParser.RULE_tasksStateComparison); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 950; + this.tasksState(); + this.state = 951; + this.match(QueryLangParser.SPACE); + this.state = 956; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 11) { + { + this.state = 952; + this.match(QueryLangParser.NOT); + this.state = 954; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 953; + this.match(QueryLangParser.SPACE); + } + } + + } + } + + this.state = 958; + localContext._op = this.match(QueryLangParser.EQ); + this.state = 959; + this.match(QueryLangParser.SPACE); + this.state = 960; + localContext._state = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 50 || _la === 51)) { + localContext._state = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public tasksUserIdComparison(): TasksUserIdComparisonContext { + let localContext = new TasksUserIdComparisonContext(this.context, this.state); + this.enterRule(localContext, 130, QueryLangParser.RULE_tasksUserIdComparison); + try { + this.state = 974; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 102, this.context) ) { + case 1: + localContext = new TasksUserIdBasicContext(localContext); + this.enterOuterAlt(localContext, 1); + { + this.state = 962; + this.tasksUserId(); + this.state = 963; + this.match(QueryLangParser.SPACE); + this.state = 964; + this.stringComparison(); + } + break; + case 2: + localContext = new TasksUserIdListContext(localContext); + this.enterOuterAlt(localContext, 2); + { + this.state = 966; + this.tasksUserId(); + this.state = 967; + this.match(QueryLangParser.SPACE); + this.state = 968; + this.inListStringComparison(); + } + break; + case 3: + localContext = new TasksUserIdNullContext(localContext); + this.enterOuterAlt(localContext, 3); + { + this.state = 970; + this.tasksUserId(); + this.state = 971; + this.match(QueryLangParser.SPACE); + this.state = 972; + this.nullComparison(); + } + break; + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public objectIdComparison(): ObjectIdComparisonContext { + let localContext = new ObjectIdComparisonContext(this.context, this.state); + this.enterRule(localContext, 132, QueryLangParser.RULE_objectIdComparison); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 980; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 11) { + { + this.state = 976; + this.match(QueryLangParser.NOT); + this.state = 978; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 977; + this.match(QueryLangParser.SPACE); + } + } + + } + } + + this.state = 982; + localContext._op = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 12 || _la === 13)) { + localContext._op = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + this.state = 983; + this.match(QueryLangParser.SPACE); + this.state = 984; + _la = this.tokenStream.LA(1); + if(!(_la === 57 || _la === 69)) { + this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public stringComparison(): StringComparisonContext { + let localContext = new StringComparisonContext(this.context, this.state); + this.enterRule(localContext, 134, QueryLangParser.RULE_stringComparison); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 990; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 11) { + { + this.state = 986; + this.match(QueryLangParser.NOT); + this.state = 988; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 987; + this.match(QueryLangParser.SPACE); + } + } + + } + } + + this.state = 992; + localContext._op = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 520192) !== 0))) { + localContext._op = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + this.state = 993; + this.match(QueryLangParser.SPACE); + this.state = 996; + this.errorHandler.sync(this); + switch (this.tokenStream.LA(1)) { + case QueryLangParser.STRING: + { + this.state = 994; + this.match(QueryLangParser.STRING); + } + break; + case QueryLangParser.LOGGED_USER_ID: + case QueryLangParser.LOGGED_USER_FULLNAME: + case QueryLangParser.LOGGED_USER_USERNAME: + { + this.state = 995; + this.loggedUserStringAttribute(); + } + break; + default: + throw new antlr.NoViableAltException(this); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public stringLikeComparison(): StringLikeComparisonContext { + let localContext = new StringLikeComparisonContext(this.context, this.state); + this.enterRule(localContext, 136, QueryLangParser.RULE_stringLikeComparison); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 998; + this.stringComparison(); + this.state = 999; + this.match(QueryLangParser.LIKE); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public numberComparison(): NumberComparisonContext { + let localContext = new NumberComparisonContext(this.context, this.state); + this.enterRule(localContext, 138, QueryLangParser.RULE_numberComparison); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1005; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 11) { + { + this.state = 1001; + this.match(QueryLangParser.NOT); + this.state = 1003; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1002; + this.match(QueryLangParser.SPACE); + } + } + + } + } + + this.state = 1007; + localContext._op = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 258048) !== 0))) { + localContext._op = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + this.state = 1008; + this.match(QueryLangParser.SPACE); + this.state = 1009; + localContext._number_ = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 58 || _la === 59)) { + localContext._number_ = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public dateComparison(): DateComparisonContext { + let localContext = new DateComparisonContext(this.context, this.state); + this.enterRule(localContext, 140, QueryLangParser.RULE_dateComparison); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1015; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 11) { + { + this.state = 1011; + this.match(QueryLangParser.NOT); + this.state = 1013; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1012; + this.match(QueryLangParser.SPACE); + } + } + + } + } + + this.state = 1017; + localContext._op = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 258048) !== 0))) { + localContext._op = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + this.state = 1018; + this.match(QueryLangParser.SPACE); + this.state = 1019; + this.match(QueryLangParser.DATE); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public dateTimeComparison(): DateTimeComparisonContext { + let localContext = new DateTimeComparisonContext(this.context, this.state); + this.enterRule(localContext, 142, QueryLangParser.RULE_dateTimeComparison); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1025; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 11) { + { + this.state = 1021; + this.match(QueryLangParser.NOT); + this.state = 1023; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1022; + this.match(QueryLangParser.SPACE); + } + } + + } + } + + this.state = 1027; + localContext._op = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 258048) !== 0))) { + localContext._op = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + this.state = 1028; + this.match(QueryLangParser.SPACE); + this.state = 1029; + this.match(QueryLangParser.DATETIME); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public booleanComparison(): BooleanComparisonContext { + let localContext = new BooleanComparisonContext(this.context, this.state); + this.enterRule(localContext, 144, QueryLangParser.RULE_booleanComparison); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1035; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 11) { + { + this.state = 1031; + this.match(QueryLangParser.NOT); + this.state = 1033; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1032; + this.match(QueryLangParser.SPACE); + } + } + + } + } + + this.state = 1037; + localContext._op = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 12 || _la === 13)) { + localContext._op = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + this.state = 1038; + this.match(QueryLangParser.SPACE); + this.state = 1039; + _la = this.tokenStream.LA(1); + if(!(_la === 62 || _la === 72)) { + this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public nullComparison(): NullComparisonContext { + let localContext = new NullComparisonContext(this.context, this.state); + this.enterRule(localContext, 146, QueryLangParser.RULE_nullComparison); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1045; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 11) { + { + this.state = 1041; + this.match(QueryLangParser.NOT); + this.state = 1043; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1042; + this.match(QueryLangParser.SPACE); + } + } + + } + } + + this.state = 1047; + localContext._op = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 12 || _la === 13)) { + localContext._op = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + this.state = 1048; + this.match(QueryLangParser.SPACE); + this.state = 1049; + this.match(QueryLangParser.NULL); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public inListStringComparison(): InListStringComparisonContext { + let localContext = new InListStringComparisonContext(this.context, this.state); + this.enterRule(localContext, 148, QueryLangParser.RULE_inListStringComparison); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1055; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 11) { + { + this.state = 1051; + this.match(QueryLangParser.NOT); + this.state = 1053; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1052; + this.match(QueryLangParser.SPACE); + } + } + + } + } + + this.state = 1057; + localContext._op = this.match(QueryLangParser.IN); + this.state = 1059; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1058; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1061; + this.stringList(); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public inListNumberComparison(): InListNumberComparisonContext { + let localContext = new InListNumberComparisonContext(this.context, this.state); + this.enterRule(localContext, 150, QueryLangParser.RULE_inListNumberComparison); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1067; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 11) { + { + this.state = 1063; + this.match(QueryLangParser.NOT); + this.state = 1065; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1064; + this.match(QueryLangParser.SPACE); + } + } + + } + } + + this.state = 1069; + localContext._op = this.match(QueryLangParser.IN); + this.state = 1071; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1070; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1075; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 124, this.context) ) { + case 1: + { + this.state = 1073; + this.intList(); + } + break; + case 2: + { + this.state = 1074; + this.doubleList(); + } + break; + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public inListDateComparison(): InListDateComparisonContext { + let localContext = new InListDateComparisonContext(this.context, this.state); + this.enterRule(localContext, 152, QueryLangParser.RULE_inListDateComparison); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1081; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 11) { + { + this.state = 1077; + this.match(QueryLangParser.NOT); + this.state = 1079; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1078; + this.match(QueryLangParser.SPACE); + } + } + + } + } + + this.state = 1083; + localContext._op = this.match(QueryLangParser.IN); + this.state = 1085; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1084; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1089; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 128, this.context) ) { + case 1: + { + this.state = 1087; + this.dateList(); + } + break; + case 2: + { + this.state = 1088; + this.dateTimeList(); + } + break; + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public inListVersionComparison(): InListVersionComparisonContext { + let localContext = new InListVersionComparisonContext(this.context, this.state); + this.enterRule(localContext, 154, QueryLangParser.RULE_inListVersionComparison); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1095; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 11) { + { + this.state = 1091; + this.match(QueryLangParser.NOT); + this.state = 1093; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1092; + this.match(QueryLangParser.SPACE); + } + } + + } + } + + this.state = 1097; + localContext._op = this.match(QueryLangParser.IN); + this.state = 1099; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1098; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1101; + this.versionList(); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public inRangeStringComparison(): InRangeStringComparisonContext { + let localContext = new InRangeStringComparisonContext(this.context, this.state); + this.enterRule(localContext, 156, QueryLangParser.RULE_inRangeStringComparison); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1107; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 11) { + { + this.state = 1103; + this.match(QueryLangParser.NOT); + this.state = 1105; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1104; + this.match(QueryLangParser.SPACE); + } + } + + } + } + + this.state = 1109; + localContext._op = this.match(QueryLangParser.IN); + this.state = 1111; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1110; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1113; + this.stringRange(); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public inRangeNumberComparison(): InRangeNumberComparisonContext { + let localContext = new InRangeNumberComparisonContext(this.context, this.state); + this.enterRule(localContext, 158, QueryLangParser.RULE_inRangeNumberComparison); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1119; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 11) { + { + this.state = 1115; + this.match(QueryLangParser.NOT); + this.state = 1117; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1116; + this.match(QueryLangParser.SPACE); + } + } + + } + } + + this.state = 1121; + localContext._op = this.match(QueryLangParser.IN); + this.state = 1123; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1122; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1127; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 138, this.context) ) { + case 1: + { + this.state = 1125; + this.intRange(); + } + break; + case 2: + { + this.state = 1126; + this.doubleRange(); + } + break; + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public inRangeDateComparison(): InRangeDateComparisonContext { + let localContext = new InRangeDateComparisonContext(this.context, this.state); + this.enterRule(localContext, 160, QueryLangParser.RULE_inRangeDateComparison); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1133; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 11) { + { + this.state = 1129; + this.match(QueryLangParser.NOT); + this.state = 1131; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1130; + this.match(QueryLangParser.SPACE); + } + } + + } + } + + this.state = 1135; + localContext._op = this.match(QueryLangParser.IN); + this.state = 1137; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1136; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1141; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 142, this.context) ) { + case 1: + { + this.state = 1139; + this.dateRange(); + } + break; + case 2: + { + this.state = 1140; + this.dateTimeRange(); + } + break; + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public inRangeVersionComparison(): InRangeVersionComparisonContext { + let localContext = new InRangeVersionComparisonContext(this.context, this.state); + this.enterRule(localContext, 162, QueryLangParser.RULE_inRangeVersionComparison); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1147; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 11) { + { + this.state = 1143; + this.match(QueryLangParser.NOT); + this.state = 1145; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1144; + this.match(QueryLangParser.SPACE); + } + } + + } + } + + this.state = 1149; + localContext._op = this.match(QueryLangParser.IN); + this.state = 1151; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1150; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1153; + this.versionRange(); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public dataValue(): DataValueContext { + let localContext = new DataValueContext(this.context, this.state); + this.enterRule(localContext, 164, QueryLangParser.RULE_dataValue); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1155; + this.match(QueryLangParser.DATA); + this.state = 1156; + this.match(QueryLangParser.T__4); + this.state = 1157; + localContext._fieldId = this.javaId(); + this.state = 1158; + this.match(QueryLangParser.T__4); + this.state = 1159; + this.match(QueryLangParser.VALUE); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public dataOptions(): DataOptionsContext { + let localContext = new DataOptionsContext(this.context, this.state); + this.enterRule(localContext, 166, QueryLangParser.RULE_dataOptions); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1161; + this.match(QueryLangParser.DATA); + this.state = 1162; + this.match(QueryLangParser.T__4); + this.state = 1163; + localContext._fieldId = this.javaId(); + this.state = 1164; + this.match(QueryLangParser.T__4); + this.state = 1165; + this.match(QueryLangParser.OPTIONS); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public places(): PlacesContext { + let localContext = new PlacesContext(this.context, this.state); + this.enterRule(localContext, 168, QueryLangParser.RULE_places); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1167; + this.match(QueryLangParser.PLACES); + this.state = 1168; + this.match(QueryLangParser.T__4); + this.state = 1169; + localContext._placeId = this.javaId(); + this.state = 1170; + this.match(QueryLangParser.T__4); + this.state = 1171; + this.match(QueryLangParser.MARKING); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public tasksState(): TasksStateContext { + let localContext = new TasksStateContext(this.context, this.state); + this.enterRule(localContext, 170, QueryLangParser.RULE_tasksState); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1173; + this.match(QueryLangParser.TASKS); + this.state = 1174; + this.match(QueryLangParser.T__4); + this.state = 1175; + localContext._taskId = this.javaId(); + this.state = 1176; + this.match(QueryLangParser.T__4); + this.state = 1177; + this.match(QueryLangParser.STATE); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public tasksUserId(): TasksUserIdContext { + let localContext = new TasksUserIdContext(this.context, this.state); + this.enterRule(localContext, 172, QueryLangParser.RULE_tasksUserId); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1179; + this.match(QueryLangParser.TASKS); + this.state = 1180; + this.match(QueryLangParser.T__4); + this.state = 1181; + localContext._taskId = this.javaId(); + this.state = 1182; + this.match(QueryLangParser.T__4); + this.state = 1183; + this.match(QueryLangParser.USER_ID); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public javaId(): JavaIdContext { + let localContext = new JavaIdContext(this.context, this.state); + this.enterRule(localContext, 174, QueryLangParser.RULE_javaId); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1185; + _la = this.tokenStream.LA(1); + if(!(((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & 4294967295) !== 0) || ((((_la - 52)) & ~0x1F) === 0 && ((1 << (_la - 52)) & 16411) !== 0))) { + this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public stringList(): StringListContext { + let localContext = new StringListContext(this.context, this.state); + this.enterRule(localContext, 176, QueryLangParser.RULE_stringList); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1187; + this.match(QueryLangParser.T__0); + this.state = 1189; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 146, this.context) ) { + case 1: + { + this.state = 1188; + this.match(QueryLangParser.SPACE); + } + break; + } + this.state = 1214; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (((((_la - 57)) & ~0x1F) === 0 && ((1 << (_la - 57)) & 28673) !== 0)) { + { + this.state = 1193; + this.errorHandler.sync(this); + switch (this.tokenStream.LA(1)) { + case QueryLangParser.STRING: + { + this.state = 1191; + this.match(QueryLangParser.STRING); + } + break; + case QueryLangParser.LOGGED_USER_ID: + case QueryLangParser.LOGGED_USER_FULLNAME: + case QueryLangParser.LOGGED_USER_USERNAME: + { + this.state = 1192; + this.loggedUserStringAttribute(); + } + break; + default: + throw new antlr.NoViableAltException(this); + } + this.state = 1196; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 148, this.context) ) { + case 1: + { + this.state = 1195; + this.match(QueryLangParser.SPACE); + } + break; + } + this.state = 1211; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while (_la === 4) { + { + { + this.state = 1198; + this.match(QueryLangParser.T__3); + this.state = 1200; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1199; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1204; + this.errorHandler.sync(this); + switch (this.tokenStream.LA(1)) { + case QueryLangParser.STRING: + { + this.state = 1202; + this.match(QueryLangParser.STRING); + } + break; + case QueryLangParser.LOGGED_USER_ID: + case QueryLangParser.LOGGED_USER_FULLNAME: + case QueryLangParser.LOGGED_USER_USERNAME: + { + this.state = 1203; + this.loggedUserStringAttribute(); + } + break; + default: + throw new antlr.NoViableAltException(this); + } + this.state = 1207; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 151, this.context) ) { + case 1: + { + this.state = 1206; + this.match(QueryLangParser.SPACE); + } + break; + } + } + } + this.state = 1213; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + } + } + + this.state = 1217; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1216; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1219; + this.match(QueryLangParser.T__1); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public intList(): IntListContext { + let localContext = new IntListContext(this.context, this.state); + this.enterRule(localContext, 178, QueryLangParser.RULE_intList); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1221; + this.match(QueryLangParser.T__0); + this.state = 1223; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 155, this.context) ) { + case 1: + { + this.state = 1222; + this.match(QueryLangParser.SPACE); + } + break; + } + this.state = 1242; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 58) { + { + this.state = 1225; + this.match(QueryLangParser.INT); + this.state = 1227; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 156, this.context) ) { + case 1: + { + this.state = 1226; + this.match(QueryLangParser.SPACE); + } + break; + } + this.state = 1239; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while (_la === 4) { + { + { + this.state = 1229; + this.match(QueryLangParser.T__3); + this.state = 1231; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1230; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1233; + this.match(QueryLangParser.INT); + this.state = 1235; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 158, this.context) ) { + case 1: + { + this.state = 1234; + this.match(QueryLangParser.SPACE); + } + break; + } + } + } + this.state = 1241; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + } + } + + this.state = 1245; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1244; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1247; + this.match(QueryLangParser.T__1); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public doubleList(): DoubleListContext { + let localContext = new DoubleListContext(this.context, this.state); + this.enterRule(localContext, 180, QueryLangParser.RULE_doubleList); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1249; + this.match(QueryLangParser.T__0); + this.state = 1251; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 162, this.context) ) { + case 1: + { + this.state = 1250; + this.match(QueryLangParser.SPACE); + } + break; + } + this.state = 1270; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 59) { + { + this.state = 1253; + this.match(QueryLangParser.DOUBLE); + this.state = 1255; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 163, this.context) ) { + case 1: + { + this.state = 1254; + this.match(QueryLangParser.SPACE); + } + break; + } + this.state = 1267; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while (_la === 4) { + { + { + this.state = 1257; + this.match(QueryLangParser.T__3); + this.state = 1259; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1258; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1261; + this.match(QueryLangParser.DOUBLE); + this.state = 1263; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 165, this.context) ) { + case 1: + { + this.state = 1262; + this.match(QueryLangParser.SPACE); + } + break; + } + } + } + this.state = 1269; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + } + } + + this.state = 1273; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1272; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1275; + this.match(QueryLangParser.T__1); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public dateList(): DateListContext { + let localContext = new DateListContext(this.context, this.state); + this.enterRule(localContext, 182, QueryLangParser.RULE_dateList); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1277; + this.match(QueryLangParser.T__0); + this.state = 1279; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 169, this.context) ) { + case 1: + { + this.state = 1278; + this.match(QueryLangParser.SPACE); + } + break; + } + this.state = 1298; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 61) { + { + this.state = 1281; + this.match(QueryLangParser.DATE); + this.state = 1283; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 170, this.context) ) { + case 1: + { + this.state = 1282; + this.match(QueryLangParser.SPACE); + } + break; + } + this.state = 1295; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while (_la === 4) { + { + { + this.state = 1285; + this.match(QueryLangParser.T__3); + this.state = 1287; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1286; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1289; + this.match(QueryLangParser.DATE); + this.state = 1291; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 172, this.context) ) { + case 1: + { + this.state = 1290; + this.match(QueryLangParser.SPACE); + } + break; + } + } + } + this.state = 1297; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + } + } + + this.state = 1301; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1300; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1303; + this.match(QueryLangParser.T__1); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public dateTimeList(): DateTimeListContext { + let localContext = new DateTimeListContext(this.context, this.state); + this.enterRule(localContext, 184, QueryLangParser.RULE_dateTimeList); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1305; + this.match(QueryLangParser.T__0); + this.state = 1307; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 176, this.context) ) { + case 1: + { + this.state = 1306; + this.match(QueryLangParser.SPACE); + } + break; + } + this.state = 1326; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 60) { + { + this.state = 1309; + this.match(QueryLangParser.DATETIME); + this.state = 1311; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 177, this.context) ) { + case 1: + { + this.state = 1310; + this.match(QueryLangParser.SPACE); + } + break; + } + this.state = 1323; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while (_la === 4) { + { + { + this.state = 1313; + this.match(QueryLangParser.T__3); + this.state = 1315; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1314; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1317; + this.match(QueryLangParser.DATETIME); + this.state = 1319; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 179, this.context) ) { + case 1: + { + this.state = 1318; + this.match(QueryLangParser.SPACE); + } + break; + } + } + } + this.state = 1325; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + } + } + + this.state = 1329; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1328; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1331; + this.match(QueryLangParser.T__1); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public versionList(): VersionListContext { + let localContext = new VersionListContext(this.context, this.state); + this.enterRule(localContext, 186, QueryLangParser.RULE_versionList); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1333; + this.match(QueryLangParser.T__0); + this.state = 1335; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 183, this.context) ) { + case 1: + { + this.state = 1334; + this.match(QueryLangParser.SPACE); + } + break; + } + this.state = 1354; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 63) { + { + this.state = 1337; + this.match(QueryLangParser.VERSION_NUMBER); + this.state = 1339; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 184, this.context) ) { + case 1: + { + this.state = 1338; + this.match(QueryLangParser.SPACE); + } + break; + } + this.state = 1351; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while (_la === 4) { + { + { + this.state = 1341; + this.match(QueryLangParser.T__3); + this.state = 1343; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1342; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1345; + this.match(QueryLangParser.VERSION_NUMBER); + this.state = 1347; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 186, this.context) ) { + case 1: + { + this.state = 1346; + this.match(QueryLangParser.SPACE); + } + break; + } + } + } + this.state = 1353; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + } + } + + this.state = 1357; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1356; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1359; + this.match(QueryLangParser.T__1); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public stringRange(): StringRangeContext { + let localContext = new StringRangeContext(this.context, this.state); + this.enterRule(localContext, 188, QueryLangParser.RULE_stringRange); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1361; + localContext._leftEndpoint = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 1 || _la === 6)) { + localContext._leftEndpoint = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + this.state = 1363; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1362; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1367; + this.errorHandler.sync(this); + switch (this.tokenStream.LA(1)) { + case QueryLangParser.STRING: + { + this.state = 1365; + this.match(QueryLangParser.STRING); + } + break; + case QueryLangParser.LOGGED_USER_ID: + case QueryLangParser.LOGGED_USER_FULLNAME: + case QueryLangParser.LOGGED_USER_USERNAME: + { + this.state = 1366; + this.loggedUserStringAttribute(); + } + break; + default: + throw new antlr.NoViableAltException(this); + } + this.state = 1370; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1369; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1372; + this.match(QueryLangParser.T__2); + this.state = 1374; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1373; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1378; + this.errorHandler.sync(this); + switch (this.tokenStream.LA(1)) { + case QueryLangParser.STRING: + { + this.state = 1376; + this.match(QueryLangParser.STRING); + } + break; + case QueryLangParser.LOGGED_USER_ID: + case QueryLangParser.LOGGED_USER_FULLNAME: + case QueryLangParser.LOGGED_USER_USERNAME: + { + this.state = 1377; + this.loggedUserStringAttribute(); + } + break; + default: + throw new antlr.NoViableAltException(this); + } + this.state = 1381; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1380; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1383; + localContext._rightEndpoint = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 2 || _la === 7)) { + localContext._rightEndpoint = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public intRange(): IntRangeContext { + let localContext = new IntRangeContext(this.context, this.state); + this.enterRule(localContext, 190, QueryLangParser.RULE_intRange); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1385; + localContext._leftEndpoint = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 1 || _la === 6)) { + localContext._leftEndpoint = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + this.state = 1387; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1386; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1389; + this.match(QueryLangParser.INT); + this.state = 1391; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1390; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1393; + this.match(QueryLangParser.T__2); + this.state = 1395; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1394; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1397; + this.match(QueryLangParser.INT); + this.state = 1399; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1398; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1401; + localContext._rightEndpoint = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 2 || _la === 7)) { + localContext._rightEndpoint = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public doubleRange(): DoubleRangeContext { + let localContext = new DoubleRangeContext(this.context, this.state); + this.enterRule(localContext, 192, QueryLangParser.RULE_doubleRange); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1403; + localContext._leftEndpoint = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 1 || _la === 6)) { + localContext._leftEndpoint = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + this.state = 1405; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1404; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1407; + this.match(QueryLangParser.DOUBLE); + this.state = 1409; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1408; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1411; + this.match(QueryLangParser.T__2); + this.state = 1413; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1412; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1415; + this.match(QueryLangParser.DOUBLE); + this.state = 1417; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1416; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1419; + localContext._rightEndpoint = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 2 || _la === 7)) { + localContext._rightEndpoint = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public dateRange(): DateRangeContext { + let localContext = new DateRangeContext(this.context, this.state); + this.enterRule(localContext, 194, QueryLangParser.RULE_dateRange); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1421; + localContext._leftEndpoint = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 1 || _la === 6)) { + localContext._leftEndpoint = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + this.state = 1423; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1422; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1425; + this.match(QueryLangParser.DATE); + this.state = 1427; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1426; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1429; + this.match(QueryLangParser.T__2); + this.state = 1431; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1430; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1433; + this.match(QueryLangParser.DATE); + this.state = 1435; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1434; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1437; + localContext._rightEndpoint = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 2 || _la === 7)) { + localContext._rightEndpoint = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public dateTimeRange(): DateTimeRangeContext { + let localContext = new DateTimeRangeContext(this.context, this.state); + this.enterRule(localContext, 196, QueryLangParser.RULE_dateTimeRange); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1439; + localContext._leftEndpoint = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 1 || _la === 6)) { + localContext._leftEndpoint = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + this.state = 1441; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1440; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1443; + this.match(QueryLangParser.DATETIME); + this.state = 1445; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1444; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1447; + this.match(QueryLangParser.T__2); + this.state = 1449; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1448; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1451; + this.match(QueryLangParser.DATETIME); + this.state = 1453; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1452; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1455; + localContext._rightEndpoint = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 2 || _la === 7)) { + localContext._rightEndpoint = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public versionRange(): VersionRangeContext { + let localContext = new VersionRangeContext(this.context, this.state); + this.enterRule(localContext, 198, QueryLangParser.RULE_versionRange); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1457; + localContext._leftEndpoint = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 1 || _la === 6)) { + localContext._leftEndpoint = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + this.state = 1459; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1458; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1461; + this.match(QueryLangParser.VERSION_NUMBER); + this.state = 1463; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1462; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1465; + this.match(QueryLangParser.T__2); + this.state = 1467; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1466; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1469; + this.match(QueryLangParser.VERSION_NUMBER); + this.state = 1471; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 67) { + { + this.state = 1470; + this.match(QueryLangParser.SPACE); + } + } + + this.state = 1473; + localContext._rightEndpoint = this.tokenStream.LT(1); + _la = this.tokenStream.LA(1); + if(!(_la === 2 || _la === 7)) { + localContext._rightEndpoint = this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public loggedUserStringAttribute(): LoggedUserStringAttributeContext { + let localContext = new LoggedUserStringAttributeContext(this.context, this.state); + this.enterRule(localContext, 200, QueryLangParser.RULE_loggedUserStringAttribute); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 1475; + _la = this.tokenStream.LA(1); + if(!(((((_la - 69)) & ~0x1F) === 0 && ((1 << (_la - 69)) & 7) !== 0))) { + this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + + public static readonly _serializedATN: number[] = [ + 4,1,72,1478,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6, + 7,6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7, + 13,2,14,7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7,19,2, + 20,7,20,2,21,7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2,26,7, + 26,2,27,7,27,2,28,7,28,2,29,7,29,2,30,7,30,2,31,7,31,2,32,7,32,2, + 33,7,33,2,34,7,34,2,35,7,35,2,36,7,36,2,37,7,37,2,38,7,38,2,39,7, + 39,2,40,7,40,2,41,7,41,2,42,7,42,2,43,7,43,2,44,7,44,2,45,7,45,2, + 46,7,46,2,47,7,47,2,48,7,48,2,49,7,49,2,50,7,50,2,51,7,51,2,52,7, + 52,2,53,7,53,2,54,7,54,2,55,7,55,2,56,7,56,2,57,7,57,2,58,7,58,2, + 59,7,59,2,60,7,60,2,61,7,61,2,62,7,62,2,63,7,63,2,64,7,64,2,65,7, + 65,2,66,7,66,2,67,7,67,2,68,7,68,2,69,7,69,2,70,7,70,2,71,7,71,2, + 72,7,72,2,73,7,73,2,74,7,74,2,75,7,75,2,76,7,76,2,77,7,77,2,78,7, + 78,2,79,7,79,2,80,7,80,2,81,7,81,2,82,7,82,2,83,7,83,2,84,7,84,2, + 85,7,85,2,86,7,86,2,87,7,87,2,88,7,88,2,89,7,89,2,90,7,90,2,91,7, + 91,2,92,7,92,2,93,7,93,2,94,7,94,2,95,7,95,2,96,7,96,2,97,7,97,2, + 98,7,98,2,99,7,99,2,100,7,100,1,0,1,0,3,0,205,8,0,1,0,1,0,1,0,3, + 0,210,8,0,1,0,1,0,1,0,3,0,215,8,0,1,0,1,0,1,0,3,0,220,8,0,1,0,3, + 0,223,8,0,1,1,1,1,3,1,227,8,1,1,1,3,1,230,8,1,1,1,3,1,233,8,1,1, + 2,1,2,3,2,237,8,2,1,2,3,2,240,8,2,1,2,3,2,243,8,2,1,3,1,3,3,3,247, + 8,3,1,3,3,3,250,8,3,1,3,3,3,253,8,3,1,4,1,4,3,4,257,8,4,1,4,3,4, + 260,8,4,1,4,3,4,263,8,4,1,5,1,5,1,6,1,6,1,6,1,6,1,6,5,6,272,8,6, + 10,6,12,6,275,9,6,1,7,1,7,1,7,1,7,1,7,5,7,282,8,7,10,7,12,7,285, + 9,7,1,8,1,8,1,8,3,8,290,8,8,3,8,292,8,8,1,8,1,8,3,8,296,8,8,1,8, + 1,8,3,8,300,8,8,1,8,1,8,3,8,304,8,8,3,8,306,8,8,1,9,1,9,3,9,310, + 8,9,1,10,1,10,1,11,1,11,1,11,1,11,1,11,5,11,319,8,11,10,11,12,11, + 322,9,11,1,12,1,12,1,12,1,12,1,12,5,12,329,8,12,10,12,12,12,332, + 9,12,1,13,1,13,1,13,3,13,337,8,13,3,13,339,8,13,1,13,1,13,3,13,343, + 8,13,1,13,1,13,3,13,347,8,13,1,13,1,13,3,13,351,8,13,3,13,353,8, + 13,1,14,1,14,3,14,357,8,14,1,15,1,15,1,16,1,16,1,16,1,16,1,16,5, + 16,366,8,16,10,16,12,16,369,9,16,1,17,1,17,1,17,1,17,1,17,5,17,376, + 8,17,10,17,12,17,379,9,17,1,18,1,18,1,18,3,18,384,8,18,3,18,386, + 8,18,1,18,1,18,3,18,390,8,18,1,18,1,18,3,18,394,8,18,1,18,1,18,3, + 18,398,8,18,3,18,400,8,18,1,19,1,19,3,19,404,8,19,1,20,1,20,1,21, + 1,21,1,21,1,21,1,21,5,21,413,8,21,10,21,12,21,416,9,21,1,22,1,22, + 1,22,1,22,1,22,5,22,423,8,22,10,22,12,22,426,9,22,1,23,1,23,1,23, + 3,23,431,8,23,3,23,433,8,23,1,23,1,23,3,23,437,8,23,1,23,1,23,3, + 23,441,8,23,1,23,1,23,3,23,445,8,23,3,23,447,8,23,1,24,1,24,3,24, + 451,8,24,1,25,1,25,1,25,1,25,3,25,457,8,25,1,25,1,25,3,25,461,8, + 25,1,26,1,26,1,26,1,26,1,26,1,26,1,26,3,26,470,8,26,1,26,3,26,473, + 8,26,1,27,1,27,1,27,1,27,1,27,3,27,480,8,27,1,27,5,27,483,8,27,10, + 27,12,27,486,9,27,1,27,3,27,489,8,27,1,28,1,28,1,28,3,28,494,8,28, + 1,29,1,29,1,30,1,30,1,30,1,30,1,30,3,30,503,8,30,1,30,5,30,506,8, + 30,10,30,12,30,509,9,30,1,30,3,30,512,8,30,1,31,1,31,1,31,3,31,517, + 8,31,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,3,32, + 530,8,32,1,33,1,33,1,33,1,33,1,33,3,33,537,8,33,1,33,5,33,540,8, + 33,10,33,12,33,543,9,33,1,33,3,33,546,8,33,1,34,1,34,1,34,3,34,551, + 8,34,1,35,1,35,1,36,1,36,1,36,1,36,1,36,3,36,560,8,36,1,36,5,36, + 563,8,36,10,36,12,36,566,9,36,1,36,3,36,569,8,36,1,37,1,37,1,37, + 3,37,574,8,37,1,38,1,38,1,39,1,39,1,39,1,39,1,39,3,39,583,8,39,1, + 40,1,40,1,40,1,40,1,40,1,40,1,40,1,40,1,40,1,40,1,40,3,40,596,8, + 40,1,41,1,41,1,41,1,41,1,41,1,41,1,41,1,41,1,41,3,41,607,8,41,1, + 42,1,42,1,42,1,42,3,42,613,8,42,1,43,1,43,1,43,1,43,1,43,1,43,1, + 43,1,43,1,43,3,43,624,8,43,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1, + 44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,3,44,641,8,44,1,45,1,45,1, + 45,1,45,1,45,1,45,1,45,1,45,1,45,1,45,1,45,1,45,3,45,655,8,45,1, + 46,1,46,1,46,1,46,3,46,661,8,46,3,46,663,8,46,1,46,1,46,1,46,1,46, + 1,46,1,46,1,46,1,46,1,46,1,46,1,46,1,46,3,46,677,8,46,1,47,1,47, + 1,47,1,47,1,47,1,47,1,47,1,47,1,47,1,47,1,47,1,47,1,47,1,47,1,47, + 3,47,694,8,47,1,48,1,48,1,48,1,48,1,48,1,48,1,48,1,48,1,48,3,48, + 705,8,48,1,49,1,49,1,49,1,49,1,49,1,49,1,49,1,49,1,49,3,49,716,8, + 49,1,50,1,50,1,50,1,50,1,50,1,50,1,50,1,50,1,50,1,50,1,50,1,50,3, + 50,730,8,50,1,51,1,51,1,51,1,51,1,51,1,51,1,51,1,51,1,51,3,51,741, + 8,51,1,52,1,52,1,52,1,52,1,52,1,52,1,52,1,52,1,52,1,52,1,52,1,52, + 3,52,755,8,52,1,53,1,53,1,53,1,53,1,53,1,53,1,54,1,54,1,54,1,54, + 1,54,1,54,1,54,1,54,1,54,3,54,772,8,54,1,55,1,55,1,55,1,55,1,55, + 1,55,1,55,1,55,1,55,3,55,783,8,55,1,56,1,56,1,56,1,56,1,56,1,56, + 1,56,1,56,1,56,1,56,1,56,1,56,1,56,1,56,1,56,3,56,800,8,56,1,57, + 1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,57, + 1,57,3,57,817,8,57,1,58,1,58,1,58,1,58,1,58,1,58,1,58,1,58,1,58, + 1,58,1,58,1,58,3,58,831,8,58,1,59,1,59,1,59,1,59,1,59,1,59,1,59, + 1,59,1,59,1,59,1,59,1,59,3,59,845,8,59,1,60,1,60,1,60,1,60,1,60, + 1,60,1,60,1,60,1,60,1,60,1,60,1,60,3,60,859,8,60,1,61,1,61,1,61, + 1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61, + 1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61, + 1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61, + 1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61,1,61,3,61,913,8,61, + 1,62,1,62,1,62,1,62,1,62,1,62,1,62,1,62,1,62,1,62,1,62,1,62,1,62, + 1,62,1,62,1,62,3,62,931,8,62,1,63,1,63,1,63,1,63,1,63,1,63,1,63, + 1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,3,63,949,8,63,1,64, + 1,64,1,64,1,64,3,64,955,8,64,3,64,957,8,64,1,64,1,64,1,64,1,64,1, + 65,1,65,1,65,1,65,1,65,1,65,1,65,1,65,1,65,1,65,1,65,1,65,3,65,975, + 8,65,1,66,1,66,3,66,979,8,66,3,66,981,8,66,1,66,1,66,1,66,1,66,1, + 67,1,67,3,67,989,8,67,3,67,991,8,67,1,67,1,67,1,67,1,67,3,67,997, + 8,67,1,68,1,68,1,68,1,69,1,69,3,69,1004,8,69,3,69,1006,8,69,1,69, + 1,69,1,69,1,69,1,70,1,70,3,70,1014,8,70,3,70,1016,8,70,1,70,1,70, + 1,70,1,70,1,71,1,71,3,71,1024,8,71,3,71,1026,8,71,1,71,1,71,1,71, + 1,71,1,72,1,72,3,72,1034,8,72,3,72,1036,8,72,1,72,1,72,1,72,1,72, + 1,73,1,73,3,73,1044,8,73,3,73,1046,8,73,1,73,1,73,1,73,1,73,1,74, + 1,74,3,74,1054,8,74,3,74,1056,8,74,1,74,1,74,3,74,1060,8,74,1,74, + 1,74,1,75,1,75,3,75,1066,8,75,3,75,1068,8,75,1,75,1,75,3,75,1072, + 8,75,1,75,1,75,3,75,1076,8,75,1,76,1,76,3,76,1080,8,76,3,76,1082, + 8,76,1,76,1,76,3,76,1086,8,76,1,76,1,76,3,76,1090,8,76,1,77,1,77, + 3,77,1094,8,77,3,77,1096,8,77,1,77,1,77,3,77,1100,8,77,1,77,1,77, + 1,78,1,78,3,78,1106,8,78,3,78,1108,8,78,1,78,1,78,3,78,1112,8,78, + 1,78,1,78,1,79,1,79,3,79,1118,8,79,3,79,1120,8,79,1,79,1,79,3,79, + 1124,8,79,1,79,1,79,3,79,1128,8,79,1,80,1,80,3,80,1132,8,80,3,80, + 1134,8,80,1,80,1,80,3,80,1138,8,80,1,80,1,80,3,80,1142,8,80,1,81, + 1,81,3,81,1146,8,81,3,81,1148,8,81,1,81,1,81,3,81,1152,8,81,1,81, + 1,81,1,82,1,82,1,82,1,82,1,82,1,82,1,83,1,83,1,83,1,83,1,83,1,83, + 1,84,1,84,1,84,1,84,1,84,1,84,1,85,1,85,1,85,1,85,1,85,1,85,1,86, + 1,86,1,86,1,86,1,86,1,86,1,87,1,87,1,88,1,88,3,88,1190,8,88,1,88, + 1,88,3,88,1194,8,88,1,88,3,88,1197,8,88,1,88,1,88,3,88,1201,8,88, + 1,88,1,88,3,88,1205,8,88,1,88,3,88,1208,8,88,5,88,1210,8,88,10,88, + 12,88,1213,9,88,3,88,1215,8,88,1,88,3,88,1218,8,88,1,88,1,88,1,89, + 1,89,3,89,1224,8,89,1,89,1,89,3,89,1228,8,89,1,89,1,89,3,89,1232, + 8,89,1,89,1,89,3,89,1236,8,89,5,89,1238,8,89,10,89,12,89,1241,9, + 89,3,89,1243,8,89,1,89,3,89,1246,8,89,1,89,1,89,1,90,1,90,3,90,1252, + 8,90,1,90,1,90,3,90,1256,8,90,1,90,1,90,3,90,1260,8,90,1,90,1,90, + 3,90,1264,8,90,5,90,1266,8,90,10,90,12,90,1269,9,90,3,90,1271,8, + 90,1,90,3,90,1274,8,90,1,90,1,90,1,91,1,91,3,91,1280,8,91,1,91,1, + 91,3,91,1284,8,91,1,91,1,91,3,91,1288,8,91,1,91,1,91,3,91,1292,8, + 91,5,91,1294,8,91,10,91,12,91,1297,9,91,3,91,1299,8,91,1,91,3,91, + 1302,8,91,1,91,1,91,1,92,1,92,3,92,1308,8,92,1,92,1,92,3,92,1312, + 8,92,1,92,1,92,3,92,1316,8,92,1,92,1,92,3,92,1320,8,92,5,92,1322, + 8,92,10,92,12,92,1325,9,92,3,92,1327,8,92,1,92,3,92,1330,8,92,1, + 92,1,92,1,93,1,93,3,93,1336,8,93,1,93,1,93,3,93,1340,8,93,1,93,1, + 93,3,93,1344,8,93,1,93,1,93,3,93,1348,8,93,5,93,1350,8,93,10,93, + 12,93,1353,9,93,3,93,1355,8,93,1,93,3,93,1358,8,93,1,93,1,93,1,94, + 1,94,3,94,1364,8,94,1,94,1,94,3,94,1368,8,94,1,94,3,94,1371,8,94, + 1,94,1,94,3,94,1375,8,94,1,94,1,94,3,94,1379,8,94,1,94,3,94,1382, + 8,94,1,94,1,94,1,95,1,95,3,95,1388,8,95,1,95,1,95,3,95,1392,8,95, + 1,95,1,95,3,95,1396,8,95,1,95,1,95,3,95,1400,8,95,1,95,1,95,1,96, + 1,96,3,96,1406,8,96,1,96,1,96,3,96,1410,8,96,1,96,1,96,3,96,1414, + 8,96,1,96,1,96,3,96,1418,8,96,1,96,1,96,1,97,1,97,3,97,1424,8,97, + 1,97,1,97,3,97,1428,8,97,1,97,1,97,3,97,1432,8,97,1,97,1,97,3,97, + 1436,8,97,1,97,1,97,1,98,1,98,3,98,1442,8,98,1,98,1,98,3,98,1446, + 8,98,1,98,1,98,3,98,1450,8,98,1,98,1,98,3,98,1454,8,98,1,98,1,98, + 1,99,1,99,3,99,1460,8,99,1,99,1,99,3,99,1464,8,99,1,99,1,99,3,99, + 1468,8,99,1,99,1,99,3,99,1472,8,99,1,99,1,99,1,100,1,100,1,100,0, + 0,101,0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40, + 42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84, + 86,88,90,92,94,96,98,100,102,104,106,108,110,112,114,116,118,120, + 122,124,126,128,130,132,134,136,138,140,142,144,146,148,150,152, + 154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184, + 186,188,190,192,194,196,198,200,0,20,1,0,26,27,1,0,20,21,1,0,22, + 23,1,0,24,25,1,0,55,56,1,0,28,32,3,0,28,29,33,33,37,42,2,0,28,28, + 43,45,2,0,12,12,14,17,1,0,50,51,1,0,12,13,2,0,57,57,69,69,1,0,12, + 18,1,0,12,17,1,0,58,59,2,0,62,62,72,72,3,0,20,53,55,56,66,66,2,0, + 1,1,6,6,2,0,2,2,7,7,1,0,69,71,1672,0,222,1,0,0,0,2,224,1,0,0,0,4, + 234,1,0,0,0,6,244,1,0,0,0,8,254,1,0,0,0,10,264,1,0,0,0,12,266,1, + 0,0,0,14,276,1,0,0,0,16,305,1,0,0,0,18,307,1,0,0,0,20,311,1,0,0, + 0,22,313,1,0,0,0,24,323,1,0,0,0,26,352,1,0,0,0,28,354,1,0,0,0,30, + 358,1,0,0,0,32,360,1,0,0,0,34,370,1,0,0,0,36,399,1,0,0,0,38,401, + 1,0,0,0,40,405,1,0,0,0,42,407,1,0,0,0,44,417,1,0,0,0,46,446,1,0, + 0,0,48,448,1,0,0,0,50,460,1,0,0,0,52,462,1,0,0,0,54,474,1,0,0,0, + 56,490,1,0,0,0,58,495,1,0,0,0,60,497,1,0,0,0,62,513,1,0,0,0,64,529, + 1,0,0,0,66,531,1,0,0,0,68,547,1,0,0,0,70,552,1,0,0,0,72,554,1,0, + 0,0,74,570,1,0,0,0,76,575,1,0,0,0,78,582,1,0,0,0,80,595,1,0,0,0, + 82,606,1,0,0,0,84,612,1,0,0,0,86,623,1,0,0,0,88,640,1,0,0,0,90,654, + 1,0,0,0,92,676,1,0,0,0,94,693,1,0,0,0,96,704,1,0,0,0,98,715,1,0, + 0,0,100,729,1,0,0,0,102,740,1,0,0,0,104,754,1,0,0,0,106,756,1,0, + 0,0,108,771,1,0,0,0,110,782,1,0,0,0,112,799,1,0,0,0,114,816,1,0, + 0,0,116,830,1,0,0,0,118,844,1,0,0,0,120,858,1,0,0,0,122,912,1,0, + 0,0,124,930,1,0,0,0,126,948,1,0,0,0,128,950,1,0,0,0,130,974,1,0, + 0,0,132,980,1,0,0,0,134,990,1,0,0,0,136,998,1,0,0,0,138,1005,1,0, + 0,0,140,1015,1,0,0,0,142,1025,1,0,0,0,144,1035,1,0,0,0,146,1045, + 1,0,0,0,148,1055,1,0,0,0,150,1067,1,0,0,0,152,1081,1,0,0,0,154,1095, + 1,0,0,0,156,1107,1,0,0,0,158,1119,1,0,0,0,160,1133,1,0,0,0,162,1147, + 1,0,0,0,164,1155,1,0,0,0,166,1161,1,0,0,0,168,1167,1,0,0,0,170,1173, + 1,0,0,0,172,1179,1,0,0,0,174,1185,1,0,0,0,176,1187,1,0,0,0,178,1221, + 1,0,0,0,180,1249,1,0,0,0,182,1277,1,0,0,0,184,1305,1,0,0,0,186,1333, + 1,0,0,0,188,1361,1,0,0,0,190,1385,1,0,0,0,192,1403,1,0,0,0,194,1421, + 1,0,0,0,196,1439,1,0,0,0,198,1457,1,0,0,0,200,1475,1,0,0,0,202,204, + 7,0,0,0,203,205,3,2,1,0,204,203,1,0,0,0,204,205,1,0,0,0,205,206, + 1,0,0,0,206,223,5,0,0,1,207,209,7,1,0,0,208,210,3,4,2,0,209,208, + 1,0,0,0,209,210,1,0,0,0,210,211,1,0,0,0,211,223,5,0,0,1,212,214, + 7,2,0,0,213,215,3,6,3,0,214,213,1,0,0,0,214,215,1,0,0,0,215,216, + 1,0,0,0,216,223,5,0,0,1,217,219,7,3,0,0,218,220,3,8,4,0,219,218, + 1,0,0,0,219,220,1,0,0,0,220,221,1,0,0,0,221,223,5,0,0,1,222,202, + 1,0,0,0,222,207,1,0,0,0,222,212,1,0,0,0,222,217,1,0,0,0,223,1,1, + 0,0,0,224,226,3,50,25,0,225,227,3,10,5,0,226,225,1,0,0,0,226,227, + 1,0,0,0,227,229,1,0,0,0,228,230,3,52,26,0,229,228,1,0,0,0,229,230, + 1,0,0,0,230,232,1,0,0,0,231,233,3,54,27,0,232,231,1,0,0,0,232,233, + 1,0,0,0,233,3,1,0,0,0,234,236,3,50,25,0,235,237,3,20,10,0,236,235, + 1,0,0,0,236,237,1,0,0,0,237,239,1,0,0,0,238,240,3,52,26,0,239,238, + 1,0,0,0,239,240,1,0,0,0,240,242,1,0,0,0,241,243,3,60,30,0,242,241, + 1,0,0,0,242,243,1,0,0,0,243,5,1,0,0,0,244,246,3,50,25,0,245,247, + 3,30,15,0,246,245,1,0,0,0,246,247,1,0,0,0,247,249,1,0,0,0,248,250, + 3,52,26,0,249,248,1,0,0,0,249,250,1,0,0,0,250,252,1,0,0,0,251,253, + 3,66,33,0,252,251,1,0,0,0,252,253,1,0,0,0,253,7,1,0,0,0,254,256, + 3,50,25,0,255,257,3,40,20,0,256,255,1,0,0,0,256,257,1,0,0,0,257, + 259,1,0,0,0,258,260,3,52,26,0,259,258,1,0,0,0,259,260,1,0,0,0,260, + 262,1,0,0,0,261,263,3,72,36,0,262,261,1,0,0,0,262,263,1,0,0,0,263, + 9,1,0,0,0,264,265,3,12,6,0,265,11,1,0,0,0,266,273,3,14,7,0,267,268, + 5,67,0,0,268,269,5,10,0,0,269,270,5,67,0,0,270,272,3,14,7,0,271, + 267,1,0,0,0,272,275,1,0,0,0,273,271,1,0,0,0,273,274,1,0,0,0,274, + 13,1,0,0,0,275,273,1,0,0,0,276,283,3,16,8,0,277,278,5,67,0,0,278, + 279,5,9,0,0,279,280,5,67,0,0,280,282,3,16,8,0,281,277,1,0,0,0,282, + 285,1,0,0,0,283,281,1,0,0,0,283,284,1,0,0,0,284,15,1,0,0,0,285,283, + 1,0,0,0,286,306,3,18,9,0,287,289,5,11,0,0,288,290,5,67,0,0,289,288, + 1,0,0,0,289,290,1,0,0,0,290,292,1,0,0,0,291,287,1,0,0,0,291,292, + 1,0,0,0,292,293,1,0,0,0,293,295,5,1,0,0,294,296,5,67,0,0,295,294, + 1,0,0,0,295,296,1,0,0,0,296,297,1,0,0,0,297,299,3,10,5,0,298,300, + 5,67,0,0,299,298,1,0,0,0,299,300,1,0,0,0,300,301,1,0,0,0,301,303, + 5,2,0,0,302,304,5,67,0,0,303,302,1,0,0,0,303,304,1,0,0,0,304,306, + 1,0,0,0,305,286,1,0,0,0,305,291,1,0,0,0,306,17,1,0,0,0,307,309,3, + 78,39,0,308,310,5,67,0,0,309,308,1,0,0,0,309,310,1,0,0,0,310,19, + 1,0,0,0,311,312,3,22,11,0,312,21,1,0,0,0,313,320,3,24,12,0,314,315, + 5,67,0,0,315,316,5,10,0,0,316,317,5,67,0,0,317,319,3,24,12,0,318, + 314,1,0,0,0,319,322,1,0,0,0,320,318,1,0,0,0,320,321,1,0,0,0,321, + 23,1,0,0,0,322,320,1,0,0,0,323,330,3,26,13,0,324,325,5,67,0,0,325, + 326,5,9,0,0,326,327,5,67,0,0,327,329,3,26,13,0,328,324,1,0,0,0,329, + 332,1,0,0,0,330,328,1,0,0,0,330,331,1,0,0,0,331,25,1,0,0,0,332,330, + 1,0,0,0,333,353,3,28,14,0,334,336,5,11,0,0,335,337,5,67,0,0,336, + 335,1,0,0,0,336,337,1,0,0,0,337,339,1,0,0,0,338,334,1,0,0,0,338, + 339,1,0,0,0,339,340,1,0,0,0,340,342,5,1,0,0,341,343,5,67,0,0,342, + 341,1,0,0,0,342,343,1,0,0,0,343,344,1,0,0,0,344,346,3,20,10,0,345, + 347,5,67,0,0,346,345,1,0,0,0,346,347,1,0,0,0,347,348,1,0,0,0,348, + 350,5,2,0,0,349,351,5,67,0,0,350,349,1,0,0,0,350,351,1,0,0,0,351, + 353,1,0,0,0,352,333,1,0,0,0,352,338,1,0,0,0,353,27,1,0,0,0,354,356, + 3,80,40,0,355,357,5,67,0,0,356,355,1,0,0,0,356,357,1,0,0,0,357,29, + 1,0,0,0,358,359,3,32,16,0,359,31,1,0,0,0,360,367,3,34,17,0,361,362, + 5,67,0,0,362,363,5,10,0,0,363,364,5,67,0,0,364,366,3,34,17,0,365, + 361,1,0,0,0,366,369,1,0,0,0,367,365,1,0,0,0,367,368,1,0,0,0,368, + 33,1,0,0,0,369,367,1,0,0,0,370,377,3,36,18,0,371,372,5,67,0,0,372, + 373,5,9,0,0,373,374,5,67,0,0,374,376,3,36,18,0,375,371,1,0,0,0,376, + 379,1,0,0,0,377,375,1,0,0,0,377,378,1,0,0,0,378,35,1,0,0,0,379,377, + 1,0,0,0,380,400,3,38,19,0,381,383,5,11,0,0,382,384,5,67,0,0,383, + 382,1,0,0,0,383,384,1,0,0,0,384,386,1,0,0,0,385,381,1,0,0,0,385, + 386,1,0,0,0,386,387,1,0,0,0,387,389,5,1,0,0,388,390,5,67,0,0,389, + 388,1,0,0,0,389,390,1,0,0,0,390,391,1,0,0,0,391,393,3,30,15,0,392, + 394,5,67,0,0,393,392,1,0,0,0,393,394,1,0,0,0,394,395,1,0,0,0,395, + 397,5,2,0,0,396,398,5,67,0,0,397,396,1,0,0,0,397,398,1,0,0,0,398, + 400,1,0,0,0,399,380,1,0,0,0,399,385,1,0,0,0,400,37,1,0,0,0,401,403, + 3,82,41,0,402,404,5,67,0,0,403,402,1,0,0,0,403,404,1,0,0,0,404,39, + 1,0,0,0,405,406,3,42,21,0,406,41,1,0,0,0,407,414,3,44,22,0,408,409, + 5,67,0,0,409,410,5,10,0,0,410,411,5,67,0,0,411,413,3,44,22,0,412, + 408,1,0,0,0,413,416,1,0,0,0,414,412,1,0,0,0,414,415,1,0,0,0,415, + 43,1,0,0,0,416,414,1,0,0,0,417,424,3,46,23,0,418,419,5,67,0,0,419, + 420,5,9,0,0,420,421,5,67,0,0,421,423,3,46,23,0,422,418,1,0,0,0,423, + 426,1,0,0,0,424,422,1,0,0,0,424,425,1,0,0,0,425,45,1,0,0,0,426,424, + 1,0,0,0,427,447,3,48,24,0,428,430,5,11,0,0,429,431,5,67,0,0,430, + 429,1,0,0,0,430,431,1,0,0,0,431,433,1,0,0,0,432,428,1,0,0,0,432, + 433,1,0,0,0,433,434,1,0,0,0,434,436,5,1,0,0,435,437,5,67,0,0,436, + 435,1,0,0,0,436,437,1,0,0,0,437,438,1,0,0,0,438,440,3,40,20,0,439, + 441,5,67,0,0,440,439,1,0,0,0,440,441,1,0,0,0,441,442,1,0,0,0,442, + 444,5,2,0,0,443,445,5,67,0,0,444,443,1,0,0,0,444,445,1,0,0,0,445, + 447,1,0,0,0,446,427,1,0,0,0,446,432,1,0,0,0,447,47,1,0,0,0,448,450, + 3,84,42,0,449,451,5,67,0,0,450,449,1,0,0,0,450,451,1,0,0,0,451,49, + 1,0,0,0,452,453,5,67,0,0,453,454,5,8,0,0,454,461,5,67,0,0,455,457, + 5,67,0,0,456,455,1,0,0,0,456,457,1,0,0,0,457,458,1,0,0,0,458,459, + 5,3,0,0,459,461,5,67,0,0,460,452,1,0,0,0,460,456,1,0,0,0,461,51, + 1,0,0,0,462,463,5,52,0,0,463,464,5,67,0,0,464,469,5,58,0,0,465,466, + 5,67,0,0,466,467,5,53,0,0,467,468,5,67,0,0,468,470,5,58,0,0,469, + 465,1,0,0,0,469,470,1,0,0,0,470,472,1,0,0,0,471,473,5,67,0,0,472, + 471,1,0,0,0,472,473,1,0,0,0,473,53,1,0,0,0,474,475,5,54,0,0,475, + 476,5,67,0,0,476,484,3,56,28,0,477,479,5,4,0,0,478,480,5,67,0,0, + 479,478,1,0,0,0,479,480,1,0,0,0,480,481,1,0,0,0,481,483,3,56,28, + 0,482,477,1,0,0,0,483,486,1,0,0,0,484,482,1,0,0,0,484,485,1,0,0, + 0,485,488,1,0,0,0,486,484,1,0,0,0,487,489,5,67,0,0,488,487,1,0,0, + 0,488,489,1,0,0,0,489,55,1,0,0,0,490,493,3,58,29,0,491,492,5,67, + 0,0,492,494,7,4,0,0,493,491,1,0,0,0,493,494,1,0,0,0,494,57,1,0,0, + 0,495,496,7,5,0,0,496,59,1,0,0,0,497,498,5,54,0,0,498,499,5,67,0, + 0,499,507,3,62,31,0,500,502,5,4,0,0,501,503,5,67,0,0,502,501,1,0, + 0,0,502,503,1,0,0,0,503,504,1,0,0,0,504,506,3,62,31,0,505,500,1, + 0,0,0,506,509,1,0,0,0,507,505,1,0,0,0,507,508,1,0,0,0,508,511,1, + 0,0,0,509,507,1,0,0,0,510,512,5,67,0,0,511,510,1,0,0,0,511,512,1, + 0,0,0,512,61,1,0,0,0,513,516,3,64,32,0,514,515,5,67,0,0,515,517, + 7,4,0,0,516,514,1,0,0,0,516,517,1,0,0,0,517,63,1,0,0,0,518,530,5, + 28,0,0,519,530,5,33,0,0,520,530,5,34,0,0,521,530,5,29,0,0,522,530, + 5,32,0,0,523,530,5,35,0,0,524,530,3,168,84,0,525,530,3,172,86,0, + 526,530,3,170,85,0,527,530,3,164,82,0,528,530,3,166,83,0,529,518, + 1,0,0,0,529,519,1,0,0,0,529,520,1,0,0,0,529,521,1,0,0,0,529,522, + 1,0,0,0,529,523,1,0,0,0,529,524,1,0,0,0,529,525,1,0,0,0,529,526, + 1,0,0,0,529,527,1,0,0,0,529,528,1,0,0,0,530,65,1,0,0,0,531,532,5, + 54,0,0,532,533,5,67,0,0,533,541,3,68,34,0,534,536,5,4,0,0,535,537, + 5,67,0,0,536,535,1,0,0,0,536,537,1,0,0,0,537,538,1,0,0,0,538,540, + 3,68,34,0,539,534,1,0,0,0,540,543,1,0,0,0,541,539,1,0,0,0,541,542, + 1,0,0,0,542,545,1,0,0,0,543,541,1,0,0,0,544,546,5,67,0,0,545,544, + 1,0,0,0,545,546,1,0,0,0,546,67,1,0,0,0,547,550,3,70,35,0,548,549, + 5,67,0,0,549,551,7,4,0,0,550,548,1,0,0,0,550,551,1,0,0,0,551,69, + 1,0,0,0,552,553,7,6,0,0,553,71,1,0,0,0,554,555,5,54,0,0,555,556, + 5,67,0,0,556,564,3,74,37,0,557,559,5,4,0,0,558,560,5,67,0,0,559, + 558,1,0,0,0,559,560,1,0,0,0,560,561,1,0,0,0,561,563,3,74,37,0,562, + 557,1,0,0,0,563,566,1,0,0,0,564,562,1,0,0,0,564,565,1,0,0,0,565, + 568,1,0,0,0,566,564,1,0,0,0,567,569,5,67,0,0,568,567,1,0,0,0,568, + 569,1,0,0,0,569,73,1,0,0,0,570,573,3,76,38,0,571,572,5,67,0,0,572, + 574,7,4,0,0,573,571,1,0,0,0,573,574,1,0,0,0,574,75,1,0,0,0,575,576, + 7,7,0,0,576,77,1,0,0,0,577,583,3,86,43,0,578,583,3,90,45,0,579,583, + 3,92,46,0,580,583,3,88,44,0,581,583,3,94,47,0,582,577,1,0,0,0,582, + 578,1,0,0,0,582,579,1,0,0,0,582,580,1,0,0,0,582,581,1,0,0,0,583, + 79,1,0,0,0,584,596,3,86,43,0,585,596,3,98,49,0,586,596,3,100,50, + 0,587,596,3,88,44,0,588,596,3,94,47,0,589,596,3,102,51,0,590,596, + 3,126,63,0,591,596,3,128,64,0,592,596,3,130,65,0,593,596,3,122,61, + 0,594,596,3,124,62,0,595,584,1,0,0,0,595,585,1,0,0,0,595,586,1,0, + 0,0,595,587,1,0,0,0,595,588,1,0,0,0,595,589,1,0,0,0,595,590,1,0, + 0,0,595,591,1,0,0,0,595,592,1,0,0,0,595,593,1,0,0,0,595,594,1,0, + 0,0,596,81,1,0,0,0,597,607,3,86,43,0,598,607,3,104,52,0,599,607, + 3,88,44,0,600,607,3,106,53,0,601,607,3,108,54,0,602,607,3,110,55, + 0,603,607,3,96,48,0,604,607,3,112,56,0,605,607,3,114,57,0,606,597, + 1,0,0,0,606,598,1,0,0,0,606,599,1,0,0,0,606,600,1,0,0,0,606,601, + 1,0,0,0,606,602,1,0,0,0,606,603,1,0,0,0,606,604,1,0,0,0,606,605, + 1,0,0,0,607,83,1,0,0,0,608,613,3,86,43,0,609,613,3,116,58,0,610, + 613,3,118,59,0,611,613,3,120,60,0,612,608,1,0,0,0,612,609,1,0,0, + 0,612,610,1,0,0,0,612,611,1,0,0,0,613,85,1,0,0,0,614,615,5,28,0, + 0,615,616,5,67,0,0,616,624,3,132,66,0,617,618,5,28,0,0,618,619,5, + 67,0,0,619,624,3,148,74,0,620,621,5,28,0,0,621,622,5,67,0,0,622, + 624,3,146,73,0,623,614,1,0,0,0,623,617,1,0,0,0,623,620,1,0,0,0,624, + 87,1,0,0,0,625,626,5,29,0,0,626,627,5,67,0,0,627,641,3,134,67,0, + 628,629,5,29,0,0,629,630,5,67,0,0,630,641,3,136,68,0,631,632,5,29, + 0,0,632,633,5,67,0,0,633,641,3,148,74,0,634,635,5,29,0,0,635,636, + 5,67,0,0,636,641,3,156,78,0,637,638,5,29,0,0,638,639,5,67,0,0,639, + 641,3,146,73,0,640,625,1,0,0,0,640,628,1,0,0,0,640,631,1,0,0,0,640, + 634,1,0,0,0,640,637,1,0,0,0,641,89,1,0,0,0,642,643,5,30,0,0,643, + 644,5,67,0,0,644,655,3,134,67,0,645,646,5,30,0,0,646,647,5,67,0, + 0,647,655,3,148,74,0,648,649,5,30,0,0,649,650,5,67,0,0,650,655,3, + 156,78,0,651,652,5,30,0,0,652,653,5,67,0,0,653,655,3,146,73,0,654, + 642,1,0,0,0,654,645,1,0,0,0,654,648,1,0,0,0,654,651,1,0,0,0,655, + 91,1,0,0,0,656,657,5,31,0,0,657,662,5,67,0,0,658,660,5,11,0,0,659, + 661,5,67,0,0,660,659,1,0,0,0,660,661,1,0,0,0,661,663,1,0,0,0,662, + 658,1,0,0,0,662,663,1,0,0,0,663,664,1,0,0,0,664,665,7,8,0,0,665, + 666,5,67,0,0,666,677,5,63,0,0,667,668,5,31,0,0,668,669,5,67,0,0, + 669,677,3,154,77,0,670,671,5,31,0,0,671,672,5,67,0,0,672,677,3,162, + 81,0,673,674,5,31,0,0,674,675,5,67,0,0,675,677,3,146,73,0,676,656, + 1,0,0,0,676,667,1,0,0,0,676,670,1,0,0,0,676,673,1,0,0,0,677,93,1, + 0,0,0,678,679,5,32,0,0,679,680,5,67,0,0,680,694,3,140,70,0,681,682, + 5,32,0,0,682,683,5,67,0,0,683,694,3,142,71,0,684,685,5,32,0,0,685, + 686,5,67,0,0,686,694,3,152,76,0,687,688,5,32,0,0,688,689,5,67,0, + 0,689,694,3,160,80,0,690,691,5,32,0,0,691,692,5,67,0,0,692,694,3, + 146,73,0,693,678,1,0,0,0,693,681,1,0,0,0,693,684,1,0,0,0,693,687, + 1,0,0,0,693,690,1,0,0,0,694,95,1,0,0,0,695,696,5,33,0,0,696,697, + 5,67,0,0,697,705,3,134,67,0,698,699,5,33,0,0,699,700,5,67,0,0,700, + 705,3,148,74,0,701,702,5,33,0,0,702,703,5,67,0,0,703,705,3,146,73, + 0,704,695,1,0,0,0,704,698,1,0,0,0,704,701,1,0,0,0,705,97,1,0,0,0, + 706,707,5,33,0,0,707,708,5,67,0,0,708,716,3,132,66,0,709,710,5,33, + 0,0,710,711,5,67,0,0,711,716,3,148,74,0,712,713,5,33,0,0,713,714, + 5,67,0,0,714,716,3,146,73,0,715,706,1,0,0,0,715,709,1,0,0,0,715, + 712,1,0,0,0,716,99,1,0,0,0,717,718,5,34,0,0,718,719,5,67,0,0,719, + 730,3,134,67,0,720,721,5,34,0,0,721,722,5,67,0,0,722,730,3,148,74, + 0,723,724,5,34,0,0,724,725,5,67,0,0,725,730,3,156,78,0,726,727,5, + 34,0,0,727,728,5,67,0,0,728,730,3,146,73,0,729,717,1,0,0,0,729,720, + 1,0,0,0,729,723,1,0,0,0,729,726,1,0,0,0,730,101,1,0,0,0,731,732, + 5,35,0,0,732,733,5,67,0,0,733,741,3,134,67,0,734,735,5,35,0,0,735, + 736,5,67,0,0,736,741,3,148,74,0,737,738,5,35,0,0,738,739,5,67,0, + 0,739,741,3,146,73,0,740,731,1,0,0,0,740,734,1,0,0,0,740,737,1,0, + 0,0,741,103,1,0,0,0,742,743,5,37,0,0,743,744,5,67,0,0,744,755,3, + 134,67,0,745,746,5,37,0,0,746,747,5,67,0,0,747,755,3,148,74,0,748, + 749,5,37,0,0,749,750,5,67,0,0,750,755,3,156,78,0,751,752,5,37,0, + 0,752,753,5,67,0,0,753,755,3,146,73,0,754,742,1,0,0,0,754,745,1, + 0,0,0,754,748,1,0,0,0,754,751,1,0,0,0,755,105,1,0,0,0,756,757,5, + 38,0,0,757,758,5,67,0,0,758,759,5,12,0,0,759,760,5,67,0,0,760,761, + 7,9,0,0,761,107,1,0,0,0,762,763,5,39,0,0,763,764,5,67,0,0,764,772, + 3,134,67,0,765,766,5,39,0,0,766,767,5,67,0,0,767,772,3,148,74,0, + 768,769,5,39,0,0,769,770,5,67,0,0,770,772,3,146,73,0,771,762,1,0, + 0,0,771,765,1,0,0,0,771,768,1,0,0,0,772,109,1,0,0,0,773,774,5,40, + 0,0,774,775,5,67,0,0,775,783,3,134,67,0,776,777,5,40,0,0,777,778, + 5,67,0,0,778,783,3,148,74,0,779,780,5,40,0,0,780,781,5,67,0,0,781, + 783,3,146,73,0,782,773,1,0,0,0,782,776,1,0,0,0,782,779,1,0,0,0,783, + 111,1,0,0,0,784,785,5,41,0,0,785,786,5,67,0,0,786,800,3,140,70,0, + 787,788,5,41,0,0,788,789,5,67,0,0,789,800,3,142,71,0,790,791,5,41, + 0,0,791,792,5,67,0,0,792,800,3,152,76,0,793,794,5,41,0,0,794,795, + 5,67,0,0,795,800,3,160,80,0,796,797,5,41,0,0,797,798,5,67,0,0,798, + 800,3,146,73,0,799,784,1,0,0,0,799,787,1,0,0,0,799,790,1,0,0,0,799, + 793,1,0,0,0,799,796,1,0,0,0,800,113,1,0,0,0,801,802,5,42,0,0,802, + 803,5,67,0,0,803,817,3,140,70,0,804,805,5,42,0,0,805,806,5,67,0, + 0,806,817,3,142,71,0,807,808,5,42,0,0,808,809,5,67,0,0,809,817,3, + 152,76,0,810,811,5,42,0,0,811,812,5,67,0,0,812,817,3,160,80,0,813, + 814,5,42,0,0,814,815,5,67,0,0,815,817,3,146,73,0,816,801,1,0,0,0, + 816,804,1,0,0,0,816,807,1,0,0,0,816,810,1,0,0,0,816,813,1,0,0,0, + 817,115,1,0,0,0,818,819,5,43,0,0,819,820,5,67,0,0,820,831,3,134, + 67,0,821,822,5,43,0,0,822,823,5,67,0,0,823,831,3,148,74,0,824,825, + 5,43,0,0,825,826,5,67,0,0,826,831,3,156,78,0,827,828,5,43,0,0,828, + 829,5,67,0,0,829,831,3,146,73,0,830,818,1,0,0,0,830,821,1,0,0,0, + 830,824,1,0,0,0,830,827,1,0,0,0,831,117,1,0,0,0,832,833,5,44,0,0, + 833,834,5,67,0,0,834,845,3,134,67,0,835,836,5,44,0,0,836,837,5,67, + 0,0,837,845,3,148,74,0,838,839,5,44,0,0,839,840,5,67,0,0,840,845, + 3,156,78,0,841,842,5,44,0,0,842,843,5,67,0,0,843,845,3,146,73,0, + 844,832,1,0,0,0,844,835,1,0,0,0,844,838,1,0,0,0,844,841,1,0,0,0, + 845,119,1,0,0,0,846,847,5,45,0,0,847,848,5,67,0,0,848,859,3,134, + 67,0,849,850,5,45,0,0,850,851,5,67,0,0,851,859,3,148,74,0,852,853, + 5,45,0,0,853,854,5,67,0,0,854,859,3,156,78,0,855,856,5,45,0,0,856, + 857,5,67,0,0,857,859,3,146,73,0,858,846,1,0,0,0,858,849,1,0,0,0, + 858,852,1,0,0,0,858,855,1,0,0,0,859,121,1,0,0,0,860,861,3,164,82, + 0,861,862,5,67,0,0,862,863,3,134,67,0,863,913,1,0,0,0,864,865,3, + 164,82,0,865,866,5,67,0,0,866,867,3,136,68,0,867,913,1,0,0,0,868, + 869,3,164,82,0,869,870,5,67,0,0,870,871,3,138,69,0,871,913,1,0,0, + 0,872,873,3,164,82,0,873,874,5,67,0,0,874,875,3,140,70,0,875,913, + 1,0,0,0,876,877,3,164,82,0,877,878,5,67,0,0,878,879,3,142,71,0,879, + 913,1,0,0,0,880,881,3,164,82,0,881,882,5,67,0,0,882,883,3,144,72, + 0,883,913,1,0,0,0,884,885,3,164,82,0,885,886,5,67,0,0,886,887,3, + 148,74,0,887,913,1,0,0,0,888,889,3,164,82,0,889,890,5,67,0,0,890, + 891,3,150,75,0,891,913,1,0,0,0,892,893,3,164,82,0,893,894,5,67,0, + 0,894,895,3,152,76,0,895,913,1,0,0,0,896,897,3,164,82,0,897,898, + 5,67,0,0,898,899,3,156,78,0,899,913,1,0,0,0,900,901,3,164,82,0,901, + 902,5,67,0,0,902,903,3,158,79,0,903,913,1,0,0,0,904,905,3,164,82, + 0,905,906,5,67,0,0,906,907,3,160,80,0,907,913,1,0,0,0,908,909,3, + 164,82,0,909,910,5,67,0,0,910,911,3,146,73,0,911,913,1,0,0,0,912, + 860,1,0,0,0,912,864,1,0,0,0,912,868,1,0,0,0,912,872,1,0,0,0,912, + 876,1,0,0,0,912,880,1,0,0,0,912,884,1,0,0,0,912,888,1,0,0,0,912, + 892,1,0,0,0,912,896,1,0,0,0,912,900,1,0,0,0,912,904,1,0,0,0,912, + 908,1,0,0,0,913,123,1,0,0,0,914,915,3,166,83,0,915,916,5,67,0,0, + 916,917,3,134,67,0,917,931,1,0,0,0,918,919,3,166,83,0,919,920,5, + 67,0,0,920,921,3,148,74,0,921,931,1,0,0,0,922,923,3,166,83,0,923, + 924,5,67,0,0,924,925,3,156,78,0,925,931,1,0,0,0,926,927,3,166,83, + 0,927,928,5,67,0,0,928,929,3,146,73,0,929,931,1,0,0,0,930,914,1, + 0,0,0,930,918,1,0,0,0,930,922,1,0,0,0,930,926,1,0,0,0,931,125,1, + 0,0,0,932,933,3,168,84,0,933,934,5,67,0,0,934,935,3,138,69,0,935, + 949,1,0,0,0,936,937,3,168,84,0,937,938,5,67,0,0,938,939,3,150,75, + 0,939,949,1,0,0,0,940,941,3,168,84,0,941,942,5,67,0,0,942,943,3, + 158,79,0,943,949,1,0,0,0,944,945,3,168,84,0,945,946,5,67,0,0,946, + 947,3,146,73,0,947,949,1,0,0,0,948,932,1,0,0,0,948,936,1,0,0,0,948, + 940,1,0,0,0,948,944,1,0,0,0,949,127,1,0,0,0,950,951,3,170,85,0,951, + 956,5,67,0,0,952,954,5,11,0,0,953,955,5,67,0,0,954,953,1,0,0,0,954, + 955,1,0,0,0,955,957,1,0,0,0,956,952,1,0,0,0,956,957,1,0,0,0,957, + 958,1,0,0,0,958,959,5,12,0,0,959,960,5,67,0,0,960,961,7,9,0,0,961, + 129,1,0,0,0,962,963,3,172,86,0,963,964,5,67,0,0,964,965,3,134,67, + 0,965,975,1,0,0,0,966,967,3,172,86,0,967,968,5,67,0,0,968,969,3, + 148,74,0,969,975,1,0,0,0,970,971,3,172,86,0,971,972,5,67,0,0,972, + 973,3,146,73,0,973,975,1,0,0,0,974,962,1,0,0,0,974,966,1,0,0,0,974, + 970,1,0,0,0,975,131,1,0,0,0,976,978,5,11,0,0,977,979,5,67,0,0,978, + 977,1,0,0,0,978,979,1,0,0,0,979,981,1,0,0,0,980,976,1,0,0,0,980, + 981,1,0,0,0,981,982,1,0,0,0,982,983,7,10,0,0,983,984,5,67,0,0,984, + 985,7,11,0,0,985,133,1,0,0,0,986,988,5,11,0,0,987,989,5,67,0,0,988, + 987,1,0,0,0,988,989,1,0,0,0,989,991,1,0,0,0,990,986,1,0,0,0,990, + 991,1,0,0,0,991,992,1,0,0,0,992,993,7,12,0,0,993,996,5,67,0,0,994, + 997,5,57,0,0,995,997,3,200,100,0,996,994,1,0,0,0,996,995,1,0,0,0, + 997,135,1,0,0,0,998,999,3,134,67,0,999,1000,5,65,0,0,1000,137,1, + 0,0,0,1001,1003,5,11,0,0,1002,1004,5,67,0,0,1003,1002,1,0,0,0,1003, + 1004,1,0,0,0,1004,1006,1,0,0,0,1005,1001,1,0,0,0,1005,1006,1,0,0, + 0,1006,1007,1,0,0,0,1007,1008,7,13,0,0,1008,1009,5,67,0,0,1009,1010, + 7,14,0,0,1010,139,1,0,0,0,1011,1013,5,11,0,0,1012,1014,5,67,0,0, + 1013,1012,1,0,0,0,1013,1014,1,0,0,0,1014,1016,1,0,0,0,1015,1011, + 1,0,0,0,1015,1016,1,0,0,0,1016,1017,1,0,0,0,1017,1018,7,13,0,0,1018, + 1019,5,67,0,0,1019,1020,5,61,0,0,1020,141,1,0,0,0,1021,1023,5,11, + 0,0,1022,1024,5,67,0,0,1023,1022,1,0,0,0,1023,1024,1,0,0,0,1024, + 1026,1,0,0,0,1025,1021,1,0,0,0,1025,1026,1,0,0,0,1026,1027,1,0,0, + 0,1027,1028,7,13,0,0,1028,1029,5,67,0,0,1029,1030,5,60,0,0,1030, + 143,1,0,0,0,1031,1033,5,11,0,0,1032,1034,5,67,0,0,1033,1032,1,0, + 0,0,1033,1034,1,0,0,0,1034,1036,1,0,0,0,1035,1031,1,0,0,0,1035,1036, + 1,0,0,0,1036,1037,1,0,0,0,1037,1038,7,10,0,0,1038,1039,5,67,0,0, + 1039,1040,7,15,0,0,1040,145,1,0,0,0,1041,1043,5,11,0,0,1042,1044, + 5,67,0,0,1043,1042,1,0,0,0,1043,1044,1,0,0,0,1044,1046,1,0,0,0,1045, + 1041,1,0,0,0,1045,1046,1,0,0,0,1046,1047,1,0,0,0,1047,1048,7,10, + 0,0,1048,1049,5,67,0,0,1049,1050,5,64,0,0,1050,147,1,0,0,0,1051, + 1053,5,11,0,0,1052,1054,5,67,0,0,1053,1052,1,0,0,0,1053,1054,1,0, + 0,0,1054,1056,1,0,0,0,1055,1051,1,0,0,0,1055,1056,1,0,0,0,1056,1057, + 1,0,0,0,1057,1059,5,19,0,0,1058,1060,5,67,0,0,1059,1058,1,0,0,0, + 1059,1060,1,0,0,0,1060,1061,1,0,0,0,1061,1062,3,176,88,0,1062,149, + 1,0,0,0,1063,1065,5,11,0,0,1064,1066,5,67,0,0,1065,1064,1,0,0,0, + 1065,1066,1,0,0,0,1066,1068,1,0,0,0,1067,1063,1,0,0,0,1067,1068, + 1,0,0,0,1068,1069,1,0,0,0,1069,1071,5,19,0,0,1070,1072,5,67,0,0, + 1071,1070,1,0,0,0,1071,1072,1,0,0,0,1072,1075,1,0,0,0,1073,1076, + 3,178,89,0,1074,1076,3,180,90,0,1075,1073,1,0,0,0,1075,1074,1,0, + 0,0,1076,151,1,0,0,0,1077,1079,5,11,0,0,1078,1080,5,67,0,0,1079, + 1078,1,0,0,0,1079,1080,1,0,0,0,1080,1082,1,0,0,0,1081,1077,1,0,0, + 0,1081,1082,1,0,0,0,1082,1083,1,0,0,0,1083,1085,5,19,0,0,1084,1086, + 5,67,0,0,1085,1084,1,0,0,0,1085,1086,1,0,0,0,1086,1089,1,0,0,0,1087, + 1090,3,182,91,0,1088,1090,3,184,92,0,1089,1087,1,0,0,0,1089,1088, + 1,0,0,0,1090,153,1,0,0,0,1091,1093,5,11,0,0,1092,1094,5,67,0,0,1093, + 1092,1,0,0,0,1093,1094,1,0,0,0,1094,1096,1,0,0,0,1095,1091,1,0,0, + 0,1095,1096,1,0,0,0,1096,1097,1,0,0,0,1097,1099,5,19,0,0,1098,1100, + 5,67,0,0,1099,1098,1,0,0,0,1099,1100,1,0,0,0,1100,1101,1,0,0,0,1101, + 1102,3,186,93,0,1102,155,1,0,0,0,1103,1105,5,11,0,0,1104,1106,5, + 67,0,0,1105,1104,1,0,0,0,1105,1106,1,0,0,0,1106,1108,1,0,0,0,1107, + 1103,1,0,0,0,1107,1108,1,0,0,0,1108,1109,1,0,0,0,1109,1111,5,19, + 0,0,1110,1112,5,67,0,0,1111,1110,1,0,0,0,1111,1112,1,0,0,0,1112, + 1113,1,0,0,0,1113,1114,3,188,94,0,1114,157,1,0,0,0,1115,1117,5,11, + 0,0,1116,1118,5,67,0,0,1117,1116,1,0,0,0,1117,1118,1,0,0,0,1118, + 1120,1,0,0,0,1119,1115,1,0,0,0,1119,1120,1,0,0,0,1120,1121,1,0,0, + 0,1121,1123,5,19,0,0,1122,1124,5,67,0,0,1123,1122,1,0,0,0,1123,1124, + 1,0,0,0,1124,1127,1,0,0,0,1125,1128,3,190,95,0,1126,1128,3,192,96, + 0,1127,1125,1,0,0,0,1127,1126,1,0,0,0,1128,159,1,0,0,0,1129,1131, + 5,11,0,0,1130,1132,5,67,0,0,1131,1130,1,0,0,0,1131,1132,1,0,0,0, + 1132,1134,1,0,0,0,1133,1129,1,0,0,0,1133,1134,1,0,0,0,1134,1135, + 1,0,0,0,1135,1137,5,19,0,0,1136,1138,5,67,0,0,1137,1136,1,0,0,0, + 1137,1138,1,0,0,0,1138,1141,1,0,0,0,1139,1142,3,194,97,0,1140,1142, + 3,196,98,0,1141,1139,1,0,0,0,1141,1140,1,0,0,0,1142,161,1,0,0,0, + 1143,1145,5,11,0,0,1144,1146,5,67,0,0,1145,1144,1,0,0,0,1145,1146, + 1,0,0,0,1146,1148,1,0,0,0,1147,1143,1,0,0,0,1147,1148,1,0,0,0,1148, + 1149,1,0,0,0,1149,1151,5,19,0,0,1150,1152,5,67,0,0,1151,1150,1,0, + 0,0,1151,1152,1,0,0,0,1152,1153,1,0,0,0,1153,1154,3,198,99,0,1154, + 163,1,0,0,0,1155,1156,5,46,0,0,1156,1157,5,5,0,0,1157,1158,3,174, + 87,0,1158,1159,5,5,0,0,1159,1160,5,47,0,0,1160,165,1,0,0,0,1161, + 1162,5,46,0,0,1162,1163,5,5,0,0,1163,1164,3,174,87,0,1164,1165,5, + 5,0,0,1165,1166,5,48,0,0,1166,167,1,0,0,0,1167,1168,5,36,0,0,1168, + 1169,5,5,0,0,1169,1170,3,174,87,0,1170,1171,5,5,0,0,1171,1172,5, + 49,0,0,1172,169,1,0,0,0,1173,1174,5,23,0,0,1174,1175,5,5,0,0,1175, + 1176,3,174,87,0,1176,1177,5,5,0,0,1177,1178,5,38,0,0,1178,171,1, + 0,0,0,1179,1180,5,23,0,0,1180,1181,5,5,0,0,1181,1182,3,174,87,0, + 1182,1183,5,5,0,0,1183,1184,5,39,0,0,1184,173,1,0,0,0,1185,1186, + 7,16,0,0,1186,175,1,0,0,0,1187,1189,5,1,0,0,1188,1190,5,67,0,0,1189, + 1188,1,0,0,0,1189,1190,1,0,0,0,1190,1214,1,0,0,0,1191,1194,5,57, + 0,0,1192,1194,3,200,100,0,1193,1191,1,0,0,0,1193,1192,1,0,0,0,1194, + 1196,1,0,0,0,1195,1197,5,67,0,0,1196,1195,1,0,0,0,1196,1197,1,0, + 0,0,1197,1211,1,0,0,0,1198,1200,5,4,0,0,1199,1201,5,67,0,0,1200, + 1199,1,0,0,0,1200,1201,1,0,0,0,1201,1204,1,0,0,0,1202,1205,5,57, + 0,0,1203,1205,3,200,100,0,1204,1202,1,0,0,0,1204,1203,1,0,0,0,1205, + 1207,1,0,0,0,1206,1208,5,67,0,0,1207,1206,1,0,0,0,1207,1208,1,0, + 0,0,1208,1210,1,0,0,0,1209,1198,1,0,0,0,1210,1213,1,0,0,0,1211,1209, + 1,0,0,0,1211,1212,1,0,0,0,1212,1215,1,0,0,0,1213,1211,1,0,0,0,1214, + 1193,1,0,0,0,1214,1215,1,0,0,0,1215,1217,1,0,0,0,1216,1218,5,67, + 0,0,1217,1216,1,0,0,0,1217,1218,1,0,0,0,1218,1219,1,0,0,0,1219,1220, + 5,2,0,0,1220,177,1,0,0,0,1221,1223,5,1,0,0,1222,1224,5,67,0,0,1223, + 1222,1,0,0,0,1223,1224,1,0,0,0,1224,1242,1,0,0,0,1225,1227,5,58, + 0,0,1226,1228,5,67,0,0,1227,1226,1,0,0,0,1227,1228,1,0,0,0,1228, + 1239,1,0,0,0,1229,1231,5,4,0,0,1230,1232,5,67,0,0,1231,1230,1,0, + 0,0,1231,1232,1,0,0,0,1232,1233,1,0,0,0,1233,1235,5,58,0,0,1234, + 1236,5,67,0,0,1235,1234,1,0,0,0,1235,1236,1,0,0,0,1236,1238,1,0, + 0,0,1237,1229,1,0,0,0,1238,1241,1,0,0,0,1239,1237,1,0,0,0,1239,1240, + 1,0,0,0,1240,1243,1,0,0,0,1241,1239,1,0,0,0,1242,1225,1,0,0,0,1242, + 1243,1,0,0,0,1243,1245,1,0,0,0,1244,1246,5,67,0,0,1245,1244,1,0, + 0,0,1245,1246,1,0,0,0,1246,1247,1,0,0,0,1247,1248,5,2,0,0,1248,179, + 1,0,0,0,1249,1251,5,1,0,0,1250,1252,5,67,0,0,1251,1250,1,0,0,0,1251, + 1252,1,0,0,0,1252,1270,1,0,0,0,1253,1255,5,59,0,0,1254,1256,5,67, + 0,0,1255,1254,1,0,0,0,1255,1256,1,0,0,0,1256,1267,1,0,0,0,1257,1259, + 5,4,0,0,1258,1260,5,67,0,0,1259,1258,1,0,0,0,1259,1260,1,0,0,0,1260, + 1261,1,0,0,0,1261,1263,5,59,0,0,1262,1264,5,67,0,0,1263,1262,1,0, + 0,0,1263,1264,1,0,0,0,1264,1266,1,0,0,0,1265,1257,1,0,0,0,1266,1269, + 1,0,0,0,1267,1265,1,0,0,0,1267,1268,1,0,0,0,1268,1271,1,0,0,0,1269, + 1267,1,0,0,0,1270,1253,1,0,0,0,1270,1271,1,0,0,0,1271,1273,1,0,0, + 0,1272,1274,5,67,0,0,1273,1272,1,0,0,0,1273,1274,1,0,0,0,1274,1275, + 1,0,0,0,1275,1276,5,2,0,0,1276,181,1,0,0,0,1277,1279,5,1,0,0,1278, + 1280,5,67,0,0,1279,1278,1,0,0,0,1279,1280,1,0,0,0,1280,1298,1,0, + 0,0,1281,1283,5,61,0,0,1282,1284,5,67,0,0,1283,1282,1,0,0,0,1283, + 1284,1,0,0,0,1284,1295,1,0,0,0,1285,1287,5,4,0,0,1286,1288,5,67, + 0,0,1287,1286,1,0,0,0,1287,1288,1,0,0,0,1288,1289,1,0,0,0,1289,1291, + 5,61,0,0,1290,1292,5,67,0,0,1291,1290,1,0,0,0,1291,1292,1,0,0,0, + 1292,1294,1,0,0,0,1293,1285,1,0,0,0,1294,1297,1,0,0,0,1295,1293, + 1,0,0,0,1295,1296,1,0,0,0,1296,1299,1,0,0,0,1297,1295,1,0,0,0,1298, + 1281,1,0,0,0,1298,1299,1,0,0,0,1299,1301,1,0,0,0,1300,1302,5,67, + 0,0,1301,1300,1,0,0,0,1301,1302,1,0,0,0,1302,1303,1,0,0,0,1303,1304, + 5,2,0,0,1304,183,1,0,0,0,1305,1307,5,1,0,0,1306,1308,5,67,0,0,1307, + 1306,1,0,0,0,1307,1308,1,0,0,0,1308,1326,1,0,0,0,1309,1311,5,60, + 0,0,1310,1312,5,67,0,0,1311,1310,1,0,0,0,1311,1312,1,0,0,0,1312, + 1323,1,0,0,0,1313,1315,5,4,0,0,1314,1316,5,67,0,0,1315,1314,1,0, + 0,0,1315,1316,1,0,0,0,1316,1317,1,0,0,0,1317,1319,5,60,0,0,1318, + 1320,5,67,0,0,1319,1318,1,0,0,0,1319,1320,1,0,0,0,1320,1322,1,0, + 0,0,1321,1313,1,0,0,0,1322,1325,1,0,0,0,1323,1321,1,0,0,0,1323,1324, + 1,0,0,0,1324,1327,1,0,0,0,1325,1323,1,0,0,0,1326,1309,1,0,0,0,1326, + 1327,1,0,0,0,1327,1329,1,0,0,0,1328,1330,5,67,0,0,1329,1328,1,0, + 0,0,1329,1330,1,0,0,0,1330,1331,1,0,0,0,1331,1332,5,2,0,0,1332,185, + 1,0,0,0,1333,1335,5,1,0,0,1334,1336,5,67,0,0,1335,1334,1,0,0,0,1335, + 1336,1,0,0,0,1336,1354,1,0,0,0,1337,1339,5,63,0,0,1338,1340,5,67, + 0,0,1339,1338,1,0,0,0,1339,1340,1,0,0,0,1340,1351,1,0,0,0,1341,1343, + 5,4,0,0,1342,1344,5,67,0,0,1343,1342,1,0,0,0,1343,1344,1,0,0,0,1344, + 1345,1,0,0,0,1345,1347,5,63,0,0,1346,1348,5,67,0,0,1347,1346,1,0, + 0,0,1347,1348,1,0,0,0,1348,1350,1,0,0,0,1349,1341,1,0,0,0,1350,1353, + 1,0,0,0,1351,1349,1,0,0,0,1351,1352,1,0,0,0,1352,1355,1,0,0,0,1353, + 1351,1,0,0,0,1354,1337,1,0,0,0,1354,1355,1,0,0,0,1355,1357,1,0,0, + 0,1356,1358,5,67,0,0,1357,1356,1,0,0,0,1357,1358,1,0,0,0,1358,1359, + 1,0,0,0,1359,1360,5,2,0,0,1360,187,1,0,0,0,1361,1363,7,17,0,0,1362, + 1364,5,67,0,0,1363,1362,1,0,0,0,1363,1364,1,0,0,0,1364,1367,1,0, + 0,0,1365,1368,5,57,0,0,1366,1368,3,200,100,0,1367,1365,1,0,0,0,1367, + 1366,1,0,0,0,1368,1370,1,0,0,0,1369,1371,5,67,0,0,1370,1369,1,0, + 0,0,1370,1371,1,0,0,0,1371,1372,1,0,0,0,1372,1374,5,3,0,0,1373,1375, + 5,67,0,0,1374,1373,1,0,0,0,1374,1375,1,0,0,0,1375,1378,1,0,0,0,1376, + 1379,5,57,0,0,1377,1379,3,200,100,0,1378,1376,1,0,0,0,1378,1377, + 1,0,0,0,1379,1381,1,0,0,0,1380,1382,5,67,0,0,1381,1380,1,0,0,0,1381, + 1382,1,0,0,0,1382,1383,1,0,0,0,1383,1384,7,18,0,0,1384,189,1,0,0, + 0,1385,1387,7,17,0,0,1386,1388,5,67,0,0,1387,1386,1,0,0,0,1387,1388, + 1,0,0,0,1388,1389,1,0,0,0,1389,1391,5,58,0,0,1390,1392,5,67,0,0, + 1391,1390,1,0,0,0,1391,1392,1,0,0,0,1392,1393,1,0,0,0,1393,1395, + 5,3,0,0,1394,1396,5,67,0,0,1395,1394,1,0,0,0,1395,1396,1,0,0,0,1396, + 1397,1,0,0,0,1397,1399,5,58,0,0,1398,1400,5,67,0,0,1399,1398,1,0, + 0,0,1399,1400,1,0,0,0,1400,1401,1,0,0,0,1401,1402,7,18,0,0,1402, + 191,1,0,0,0,1403,1405,7,17,0,0,1404,1406,5,67,0,0,1405,1404,1,0, + 0,0,1405,1406,1,0,0,0,1406,1407,1,0,0,0,1407,1409,5,59,0,0,1408, + 1410,5,67,0,0,1409,1408,1,0,0,0,1409,1410,1,0,0,0,1410,1411,1,0, + 0,0,1411,1413,5,3,0,0,1412,1414,5,67,0,0,1413,1412,1,0,0,0,1413, + 1414,1,0,0,0,1414,1415,1,0,0,0,1415,1417,5,59,0,0,1416,1418,5,67, + 0,0,1417,1416,1,0,0,0,1417,1418,1,0,0,0,1418,1419,1,0,0,0,1419,1420, + 7,18,0,0,1420,193,1,0,0,0,1421,1423,7,17,0,0,1422,1424,5,67,0,0, + 1423,1422,1,0,0,0,1423,1424,1,0,0,0,1424,1425,1,0,0,0,1425,1427, + 5,61,0,0,1426,1428,5,67,0,0,1427,1426,1,0,0,0,1427,1428,1,0,0,0, + 1428,1429,1,0,0,0,1429,1431,5,3,0,0,1430,1432,5,67,0,0,1431,1430, + 1,0,0,0,1431,1432,1,0,0,0,1432,1433,1,0,0,0,1433,1435,5,61,0,0,1434, + 1436,5,67,0,0,1435,1434,1,0,0,0,1435,1436,1,0,0,0,1436,1437,1,0, + 0,0,1437,1438,7,18,0,0,1438,195,1,0,0,0,1439,1441,7,17,0,0,1440, + 1442,5,67,0,0,1441,1440,1,0,0,0,1441,1442,1,0,0,0,1442,1443,1,0, + 0,0,1443,1445,5,60,0,0,1444,1446,5,67,0,0,1445,1444,1,0,0,0,1445, + 1446,1,0,0,0,1446,1447,1,0,0,0,1447,1449,5,3,0,0,1448,1450,5,67, + 0,0,1449,1448,1,0,0,0,1449,1450,1,0,0,0,1450,1451,1,0,0,0,1451,1453, + 5,60,0,0,1452,1454,5,67,0,0,1453,1452,1,0,0,0,1453,1454,1,0,0,0, + 1454,1455,1,0,0,0,1455,1456,7,18,0,0,1456,197,1,0,0,0,1457,1459, + 7,17,0,0,1458,1460,5,67,0,0,1459,1458,1,0,0,0,1459,1460,1,0,0,0, + 1460,1461,1,0,0,0,1461,1463,5,63,0,0,1462,1464,5,67,0,0,1463,1462, + 1,0,0,0,1463,1464,1,0,0,0,1464,1465,1,0,0,0,1465,1467,5,3,0,0,1466, + 1468,5,67,0,0,1467,1466,1,0,0,0,1467,1468,1,0,0,0,1468,1469,1,0, + 0,0,1469,1471,5,63,0,0,1470,1472,5,67,0,0,1471,1470,1,0,0,0,1471, + 1472,1,0,0,0,1472,1473,1,0,0,0,1473,1474,7,18,0,0,1474,199,1,0,0, + 0,1475,1476,7,19,0,0,1476,201,1,0,0,0,216,204,209,214,219,222,226, + 229,232,236,239,242,246,249,252,256,259,262,273,283,289,291,295, + 299,303,305,309,320,330,336,338,342,346,350,352,356,367,377,383, + 385,389,393,397,399,403,414,424,430,432,436,440,444,446,450,456, + 460,469,472,479,484,488,493,502,507,511,516,529,536,541,545,550, + 559,564,568,573,582,595,606,612,623,640,654,660,662,676,693,704, + 715,729,740,754,771,782,799,816,830,844,858,912,930,948,954,956, + 974,978,980,988,990,996,1003,1005,1013,1015,1023,1025,1033,1035, + 1043,1045,1053,1055,1059,1065,1067,1071,1075,1079,1081,1085,1089, + 1093,1095,1099,1105,1107,1111,1117,1119,1123,1127,1131,1133,1137, + 1141,1145,1147,1151,1189,1193,1196,1200,1204,1207,1211,1214,1217, + 1223,1227,1231,1235,1239,1242,1245,1251,1255,1259,1263,1267,1270, + 1273,1279,1283,1287,1291,1295,1298,1301,1307,1311,1315,1319,1323, + 1326,1329,1335,1339,1343,1347,1351,1354,1357,1363,1367,1370,1374, + 1378,1381,1387,1391,1395,1399,1405,1409,1413,1417,1423,1427,1431, + 1435,1441,1445,1449,1453,1459,1463,1467,1471 + ]; + + private static __ATN: antlr.ATN; + public static get _ATN(): antlr.ATN { + if (!QueryLangParser.__ATN) { + QueryLangParser.__ATN = new antlr.ATNDeserializer().deserialize(QueryLangParser._serializedATN); + } + + return QueryLangParser.__ATN; + } + + + private static readonly vocabulary = new antlr.Vocabulary(QueryLangParser.literalNames, QueryLangParser.symbolicNames, []); + + public override get vocabulary(): antlr.Vocabulary { + return QueryLangParser.vocabulary; + } + + private static readonly decisionsToDFA = QueryLangParser._ATN.decisionToState.map( (ds: antlr.DecisionState, index: number) => new antlr.DFA(ds, index) ); +} + +export class QueryContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_query; + } + public override copyFrom(ctx: QueryContext): void { + super.copyFrom(ctx); + } +} +export class ProcessQueryContext extends QueryContext { + public _resource?: Token | null; + public constructor(ctx: QueryContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public EOF(): antlr.TerminalNode { + return this.getToken(QueryLangParser.EOF, 0)!; + } + public PROCESS(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.PROCESS, 0); + } + public PROCESSES(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.PROCESSES, 0); + } + public processConditionsAndPaging(): ProcessConditionsAndPagingContext | null { + return this.getRuleContext(0, ProcessConditionsAndPagingContext); + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessQuery) { + return visitor.visitProcessQuery(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class CaseQueryContext extends QueryContext { + public _resource?: Token | null; + public constructor(ctx: QueryContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public EOF(): antlr.TerminalNode { + return this.getToken(QueryLangParser.EOF, 0)!; + } + public CASE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.CASE, 0); + } + public CASES(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.CASES, 0); + } + public caseConditionsAndPaging(): CaseConditionsAndPagingContext | null { + return this.getRuleContext(0, CaseConditionsAndPagingContext); + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitCaseQuery) { + return visitor.visitCaseQuery(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class TaskQueryContext extends QueryContext { + public _resource?: Token | null; + public constructor(ctx: QueryContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public EOF(): antlr.TerminalNode { + return this.getToken(QueryLangParser.EOF, 0)!; + } + public TASK(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.TASK, 0); + } + public TASKS(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.TASKS, 0); + } + public taskConditionsAndPaging(): TaskConditionsAndPagingContext | null { + return this.getRuleContext(0, TaskConditionsAndPagingContext); + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTaskQuery) { + return visitor.visitTaskQuery(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class UserQueryContext extends QueryContext { + public _resource?: Token | null; + public constructor(ctx: QueryContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public EOF(): antlr.TerminalNode { + return this.getToken(QueryLangParser.EOF, 0)!; + } + public USER(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.USER, 0); + } + public USERS(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.USERS, 0); + } + public userConditionsAndPaging(): UserConditionsAndPagingContext | null { + return this.getRuleContext(0, UserConditionsAndPagingContext); + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitUserQuery) { + return visitor.visitUserQuery(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ProcessConditionsAndPagingContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public delimeter(): DelimeterContext { + return this.getRuleContext(0, DelimeterContext)!; + } + public processConditions(): ProcessConditionsContext | null { + return this.getRuleContext(0, ProcessConditionsContext); + } + public paging(): PagingContext | null { + return this.getRuleContext(0, PagingContext); + } + public processSorting(): ProcessSortingContext | null { + return this.getRuleContext(0, ProcessSortingContext); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_processConditionsAndPaging; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessConditionsAndPaging) { + return visitor.visitProcessConditionsAndPaging(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class CaseConditionsAndPagingContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public delimeter(): DelimeterContext { + return this.getRuleContext(0, DelimeterContext)!; + } + public caseConditions(): CaseConditionsContext | null { + return this.getRuleContext(0, CaseConditionsContext); + } + public paging(): PagingContext | null { + return this.getRuleContext(0, PagingContext); + } + public caseSorting(): CaseSortingContext | null { + return this.getRuleContext(0, CaseSortingContext); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_caseConditionsAndPaging; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitCaseConditionsAndPaging) { + return visitor.visitCaseConditionsAndPaging(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class TaskConditionsAndPagingContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public delimeter(): DelimeterContext { + return this.getRuleContext(0, DelimeterContext)!; + } + public taskConditions(): TaskConditionsContext | null { + return this.getRuleContext(0, TaskConditionsContext); + } + public paging(): PagingContext | null { + return this.getRuleContext(0, PagingContext); + } + public taskSorting(): TaskSortingContext | null { + return this.getRuleContext(0, TaskSortingContext); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_taskConditionsAndPaging; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTaskConditionsAndPaging) { + return visitor.visitTaskConditionsAndPaging(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class UserConditionsAndPagingContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public delimeter(): DelimeterContext { + return this.getRuleContext(0, DelimeterContext)!; + } + public userConditions(): UserConditionsContext | null { + return this.getRuleContext(0, UserConditionsContext); + } + public paging(): PagingContext | null { + return this.getRuleContext(0, PagingContext); + } + public userSorting(): UserSortingContext | null { + return this.getRuleContext(0, UserSortingContext); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_userConditionsAndPaging; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitUserConditionsAndPaging) { + return visitor.visitUserConditionsAndPaging(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ProcessConditionsContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public processOrExpression(): ProcessOrExpressionContext { + return this.getRuleContext(0, ProcessOrExpressionContext)!; + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_processConditions; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessConditions) { + return visitor.visitProcessConditions(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ProcessOrExpressionContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public processAndExpression(): ProcessAndExpressionContext[]; + public processAndExpression(i: number): ProcessAndExpressionContext | null; + public processAndExpression(i?: number): ProcessAndExpressionContext[] | ProcessAndExpressionContext | null { + if (i === undefined) { + return this.getRuleContexts(ProcessAndExpressionContext); + } + + return this.getRuleContext(i, ProcessAndExpressionContext); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public OR(): antlr.TerminalNode[]; + public OR(i: number): antlr.TerminalNode | null; + public OR(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.OR); + } else { + return this.getToken(QueryLangParser.OR, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_processOrExpression; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessOrExpression) { + return visitor.visitProcessOrExpression(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ProcessAndExpressionContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public processConditionGroup(): ProcessConditionGroupContext[]; + public processConditionGroup(i: number): ProcessConditionGroupContext | null; + public processConditionGroup(i?: number): ProcessConditionGroupContext[] | ProcessConditionGroupContext | null { + if (i === undefined) { + return this.getRuleContexts(ProcessConditionGroupContext); + } + + return this.getRuleContext(i, ProcessConditionGroupContext); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public AND(): antlr.TerminalNode[]; + public AND(i: number): antlr.TerminalNode | null; + public AND(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.AND); + } else { + return this.getToken(QueryLangParser.AND, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_processAndExpression; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessAndExpression) { + return visitor.visitProcessAndExpression(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ProcessConditionGroupContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_processConditionGroup; + } + public override copyFrom(ctx: ProcessConditionGroupContext): void { + super.copyFrom(ctx); + } +} +export class ProcessConditionGroupBasicContext extends ProcessConditionGroupContext { + public constructor(ctx: ProcessConditionGroupContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public processCondition(): ProcessConditionContext { + return this.getRuleContext(0, ProcessConditionContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessConditionGroupBasic) { + return visitor.visitProcessConditionGroupBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class ProcessConditionGroupParenthesisContext extends ProcessConditionGroupContext { + public constructor(ctx: ProcessConditionGroupContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public processConditions(): ProcessConditionsContext { + return this.getRuleContext(0, ProcessConditionsContext)!; + } + public NOT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NOT, 0); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessConditionGroupParenthesis) { + return visitor.visitProcessConditionGroupParenthesis(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ProcessConditionContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public processComparisons(): ProcessComparisonsContext { + return this.getRuleContext(0, ProcessComparisonsContext)!; + } + public SPACE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.SPACE, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_processCondition; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessCondition) { + return visitor.visitProcessCondition(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class CaseConditionsContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public caseOrExpression(): CaseOrExpressionContext { + return this.getRuleContext(0, CaseOrExpressionContext)!; + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_caseConditions; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitCaseConditions) { + return visitor.visitCaseConditions(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class CaseOrExpressionContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public caseAndExpression(): CaseAndExpressionContext[]; + public caseAndExpression(i: number): CaseAndExpressionContext | null; + public caseAndExpression(i?: number): CaseAndExpressionContext[] | CaseAndExpressionContext | null { + if (i === undefined) { + return this.getRuleContexts(CaseAndExpressionContext); + } + + return this.getRuleContext(i, CaseAndExpressionContext); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public OR(): antlr.TerminalNode[]; + public OR(i: number): antlr.TerminalNode | null; + public OR(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.OR); + } else { + return this.getToken(QueryLangParser.OR, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_caseOrExpression; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitCaseOrExpression) { + return visitor.visitCaseOrExpression(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class CaseAndExpressionContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public caseConditionGroup(): CaseConditionGroupContext[]; + public caseConditionGroup(i: number): CaseConditionGroupContext | null; + public caseConditionGroup(i?: number): CaseConditionGroupContext[] | CaseConditionGroupContext | null { + if (i === undefined) { + return this.getRuleContexts(CaseConditionGroupContext); + } + + return this.getRuleContext(i, CaseConditionGroupContext); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public AND(): antlr.TerminalNode[]; + public AND(i: number): antlr.TerminalNode | null; + public AND(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.AND); + } else { + return this.getToken(QueryLangParser.AND, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_caseAndExpression; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitCaseAndExpression) { + return visitor.visitCaseAndExpression(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class CaseConditionGroupContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_caseConditionGroup; + } + public override copyFrom(ctx: CaseConditionGroupContext): void { + super.copyFrom(ctx); + } +} +export class CaseConditionGroupBasicContext extends CaseConditionGroupContext { + public constructor(ctx: CaseConditionGroupContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public caseCondition(): CaseConditionContext { + return this.getRuleContext(0, CaseConditionContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitCaseConditionGroupBasic) { + return visitor.visitCaseConditionGroupBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class CaseConditionGroupParenthesisContext extends CaseConditionGroupContext { + public constructor(ctx: CaseConditionGroupContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public caseConditions(): CaseConditionsContext { + return this.getRuleContext(0, CaseConditionsContext)!; + } + public NOT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NOT, 0); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitCaseConditionGroupParenthesis) { + return visitor.visitCaseConditionGroupParenthesis(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class CaseConditionContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public caseComparisons(): CaseComparisonsContext { + return this.getRuleContext(0, CaseComparisonsContext)!; + } + public SPACE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.SPACE, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_caseCondition; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitCaseCondition) { + return visitor.visitCaseCondition(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class TaskConditionsContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public taskOrExpression(): TaskOrExpressionContext { + return this.getRuleContext(0, TaskOrExpressionContext)!; + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_taskConditions; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTaskConditions) { + return visitor.visitTaskConditions(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class TaskOrExpressionContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public taskAndExpression(): TaskAndExpressionContext[]; + public taskAndExpression(i: number): TaskAndExpressionContext | null; + public taskAndExpression(i?: number): TaskAndExpressionContext[] | TaskAndExpressionContext | null { + if (i === undefined) { + return this.getRuleContexts(TaskAndExpressionContext); + } + + return this.getRuleContext(i, TaskAndExpressionContext); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public OR(): antlr.TerminalNode[]; + public OR(i: number): antlr.TerminalNode | null; + public OR(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.OR); + } else { + return this.getToken(QueryLangParser.OR, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_taskOrExpression; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTaskOrExpression) { + return visitor.visitTaskOrExpression(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class TaskAndExpressionContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public taskConditionGroup(): TaskConditionGroupContext[]; + public taskConditionGroup(i: number): TaskConditionGroupContext | null; + public taskConditionGroup(i?: number): TaskConditionGroupContext[] | TaskConditionGroupContext | null { + if (i === undefined) { + return this.getRuleContexts(TaskConditionGroupContext); + } + + return this.getRuleContext(i, TaskConditionGroupContext); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public AND(): antlr.TerminalNode[]; + public AND(i: number): antlr.TerminalNode | null; + public AND(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.AND); + } else { + return this.getToken(QueryLangParser.AND, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_taskAndExpression; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTaskAndExpression) { + return visitor.visitTaskAndExpression(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class TaskConditionGroupContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_taskConditionGroup; + } + public override copyFrom(ctx: TaskConditionGroupContext): void { + super.copyFrom(ctx); + } +} +export class TaskConditionGroupBasicContext extends TaskConditionGroupContext { + public constructor(ctx: TaskConditionGroupContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public taskCondition(): TaskConditionContext { + return this.getRuleContext(0, TaskConditionContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTaskConditionGroupBasic) { + return visitor.visitTaskConditionGroupBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class TaskConditionGroupParenthesisContext extends TaskConditionGroupContext { + public constructor(ctx: TaskConditionGroupContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public taskConditions(): TaskConditionsContext { + return this.getRuleContext(0, TaskConditionsContext)!; + } + public NOT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NOT, 0); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTaskConditionGroupParenthesis) { + return visitor.visitTaskConditionGroupParenthesis(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class TaskConditionContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public taskComparisons(): TaskComparisonsContext { + return this.getRuleContext(0, TaskComparisonsContext)!; + } + public SPACE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.SPACE, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_taskCondition; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTaskCondition) { + return visitor.visitTaskCondition(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class UserConditionsContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public userOrExpression(): UserOrExpressionContext { + return this.getRuleContext(0, UserOrExpressionContext)!; + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_userConditions; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitUserConditions) { + return visitor.visitUserConditions(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class UserOrExpressionContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public userAndExpression(): UserAndExpressionContext[]; + public userAndExpression(i: number): UserAndExpressionContext | null; + public userAndExpression(i?: number): UserAndExpressionContext[] | UserAndExpressionContext | null { + if (i === undefined) { + return this.getRuleContexts(UserAndExpressionContext); + } + + return this.getRuleContext(i, UserAndExpressionContext); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public OR(): antlr.TerminalNode[]; + public OR(i: number): antlr.TerminalNode | null; + public OR(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.OR); + } else { + return this.getToken(QueryLangParser.OR, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_userOrExpression; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitUserOrExpression) { + return visitor.visitUserOrExpression(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class UserAndExpressionContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public userConditionGroup(): UserConditionGroupContext[]; + public userConditionGroup(i: number): UserConditionGroupContext | null; + public userConditionGroup(i?: number): UserConditionGroupContext[] | UserConditionGroupContext | null { + if (i === undefined) { + return this.getRuleContexts(UserConditionGroupContext); + } + + return this.getRuleContext(i, UserConditionGroupContext); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public AND(): antlr.TerminalNode[]; + public AND(i: number): antlr.TerminalNode | null; + public AND(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.AND); + } else { + return this.getToken(QueryLangParser.AND, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_userAndExpression; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitUserAndExpression) { + return visitor.visitUserAndExpression(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class UserConditionGroupContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_userConditionGroup; + } + public override copyFrom(ctx: UserConditionGroupContext): void { + super.copyFrom(ctx); + } +} +export class UserConditionGroupBasicContext extends UserConditionGroupContext { + public constructor(ctx: UserConditionGroupContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public userCondition(): UserConditionContext { + return this.getRuleContext(0, UserConditionContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitUserConditionGroupBasic) { + return visitor.visitUserConditionGroupBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class UserConditionGroupParenthesisContext extends UserConditionGroupContext { + public constructor(ctx: UserConditionGroupContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public userConditions(): UserConditionsContext { + return this.getRuleContext(0, UserConditionsContext)!; + } + public NOT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NOT, 0); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitUserConditionGroupParenthesis) { + return visitor.visitUserConditionGroupParenthesis(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class UserConditionContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public userComparisons(): UserComparisonsContext { + return this.getRuleContext(0, UserComparisonsContext)!; + } + public SPACE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.SPACE, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_userCondition; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitUserCondition) { + return visitor.visitUserCondition(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class DelimeterContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public WHERE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.WHERE, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_delimeter; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDelimeter) { + return visitor.visitDelimeter(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class PagingContext extends antlr.ParserRuleContext { + public _pageNum?: Token | null; + public _pageSize?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public PAGE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.PAGE, 0)!; + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public INT(): antlr.TerminalNode[]; + public INT(i: number): antlr.TerminalNode | null; + public INT(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.INT); + } else { + return this.getToken(QueryLangParser.INT, i); + } + } + public SIZE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.SIZE, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_paging; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitPaging) { + return visitor.visitPaging(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ProcessSortingContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public SORT_BY(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SORT_BY, 0)!; + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public processAttributeOrdering(): ProcessAttributeOrderingContext[]; + public processAttributeOrdering(i: number): ProcessAttributeOrderingContext | null; + public processAttributeOrdering(i?: number): ProcessAttributeOrderingContext[] | ProcessAttributeOrderingContext | null { + if (i === undefined) { + return this.getRuleContexts(ProcessAttributeOrderingContext); + } + + return this.getRuleContext(i, ProcessAttributeOrderingContext); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_processSorting; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessSorting) { + return visitor.visitProcessSorting(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ProcessAttributeOrderingContext extends antlr.ParserRuleContext { + public _ordering?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public processAttribute(): ProcessAttributeContext { + return this.getRuleContext(0, ProcessAttributeContext)!; + } + public SPACE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.SPACE, 0); + } + public ASC(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.ASC, 0); + } + public DESC(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.DESC, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_processAttributeOrdering; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessAttributeOrdering) { + return visitor.visitProcessAttributeOrdering(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ProcessAttributeContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public ID(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.ID, 0); + } + public IDENTIFIER(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.IDENTIFIER, 0); + } + public VERSION(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.VERSION, 0); + } + public TITLE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.TITLE, 0); + } + public CREATION_DATE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.CREATION_DATE, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_processAttribute; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessAttribute) { + return visitor.visitProcessAttribute(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class CaseSortingContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public SORT_BY(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SORT_BY, 0)!; + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public caseAttributeOrdering(): CaseAttributeOrderingContext[]; + public caseAttributeOrdering(i: number): CaseAttributeOrderingContext | null; + public caseAttributeOrdering(i?: number): CaseAttributeOrderingContext[] | CaseAttributeOrderingContext | null { + if (i === undefined) { + return this.getRuleContexts(CaseAttributeOrderingContext); + } + + return this.getRuleContext(i, CaseAttributeOrderingContext); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_caseSorting; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitCaseSorting) { + return visitor.visitCaseSorting(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class CaseAttributeOrderingContext extends antlr.ParserRuleContext { + public _ordering?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public caseAttribute(): CaseAttributeContext { + return this.getRuleContext(0, CaseAttributeContext)!; + } + public SPACE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.SPACE, 0); + } + public ASC(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.ASC, 0); + } + public DESC(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.DESC, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_caseAttributeOrdering; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitCaseAttributeOrdering) { + return visitor.visitCaseAttributeOrdering(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class CaseAttributeContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public ID(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.ID, 0); + } + public PROCESS_ID(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.PROCESS_ID, 0); + } + public PROCESS_IDENTIFIER(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.PROCESS_IDENTIFIER, 0); + } + public TITLE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.TITLE, 0); + } + public CREATION_DATE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.CREATION_DATE, 0); + } + public AUTHOR(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.AUTHOR, 0); + } + public places(): PlacesContext | null { + return this.getRuleContext(0, PlacesContext); + } + public tasksUserId(): TasksUserIdContext | null { + return this.getRuleContext(0, TasksUserIdContext); + } + public tasksState(): TasksStateContext | null { + return this.getRuleContext(0, TasksStateContext); + } + public dataValue(): DataValueContext | null { + return this.getRuleContext(0, DataValueContext); + } + public dataOptions(): DataOptionsContext | null { + return this.getRuleContext(0, DataOptionsContext); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_caseAttribute; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitCaseAttribute) { + return visitor.visitCaseAttribute(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class TaskSortingContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public SORT_BY(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SORT_BY, 0)!; + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public taskAttributeOrdering(): TaskAttributeOrderingContext[]; + public taskAttributeOrdering(i: number): TaskAttributeOrderingContext | null; + public taskAttributeOrdering(i?: number): TaskAttributeOrderingContext[] | TaskAttributeOrderingContext | null { + if (i === undefined) { + return this.getRuleContexts(TaskAttributeOrderingContext); + } + + return this.getRuleContext(i, TaskAttributeOrderingContext); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_taskSorting; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTaskSorting) { + return visitor.visitTaskSorting(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class TaskAttributeOrderingContext extends antlr.ParserRuleContext { + public _ordering?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public taskAttribute(): TaskAttributeContext { + return this.getRuleContext(0, TaskAttributeContext)!; + } + public SPACE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.SPACE, 0); + } + public ASC(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.ASC, 0); + } + public DESC(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.DESC, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_taskAttributeOrdering; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTaskAttributeOrdering) { + return visitor.visitTaskAttributeOrdering(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class TaskAttributeContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public ID(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.ID, 0); + } + public TRANSITION_ID(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.TRANSITION_ID, 0); + } + public TITLE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.TITLE, 0); + } + public STATE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.STATE, 0); + } + public USER_ID(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.USER_ID, 0); + } + public CASE_ID(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.CASE_ID, 0); + } + public PROCESS_ID(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.PROCESS_ID, 0); + } + public LAST_ASSIGN(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.LAST_ASSIGN, 0); + } + public LAST_FINISH(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.LAST_FINISH, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_taskAttribute; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTaskAttribute) { + return visitor.visitTaskAttribute(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class UserSortingContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public SORT_BY(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SORT_BY, 0)!; + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public userAttributeOrdering(): UserAttributeOrderingContext[]; + public userAttributeOrdering(i: number): UserAttributeOrderingContext | null; + public userAttributeOrdering(i?: number): UserAttributeOrderingContext[] | UserAttributeOrderingContext | null { + if (i === undefined) { + return this.getRuleContexts(UserAttributeOrderingContext); + } + + return this.getRuleContext(i, UserAttributeOrderingContext); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_userSorting; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitUserSorting) { + return visitor.visitUserSorting(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class UserAttributeOrderingContext extends antlr.ParserRuleContext { + public _ordering?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public userAttribute(): UserAttributeContext { + return this.getRuleContext(0, UserAttributeContext)!; + } + public SPACE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.SPACE, 0); + } + public ASC(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.ASC, 0); + } + public DESC(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.DESC, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_userAttributeOrdering; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitUserAttributeOrdering) { + return visitor.visitUserAttributeOrdering(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class UserAttributeContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public ID(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.ID, 0); + } + public NAME(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NAME, 0); + } + public SURNAME(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.SURNAME, 0); + } + public EMAIL(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.EMAIL, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_userAttribute; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitUserAttribute) { + return visitor.visitUserAttribute(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ProcessComparisonsContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public idComparison(): IdComparisonContext | null { + return this.getRuleContext(0, IdComparisonContext); + } + public identifierComparison(): IdentifierComparisonContext | null { + return this.getRuleContext(0, IdentifierComparisonContext); + } + public versionComparison(): VersionComparisonContext | null { + return this.getRuleContext(0, VersionComparisonContext); + } + public titleComparison(): TitleComparisonContext | null { + return this.getRuleContext(0, TitleComparisonContext); + } + public creationDateComparison(): CreationDateComparisonContext | null { + return this.getRuleContext(0, CreationDateComparisonContext); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_processComparisons; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessComparisons) { + return visitor.visitProcessComparisons(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class CaseComparisonsContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public idComparison(): IdComparisonContext | null { + return this.getRuleContext(0, IdComparisonContext); + } + public processIdObjIdComparison(): ProcessIdObjIdComparisonContext | null { + return this.getRuleContext(0, ProcessIdObjIdComparisonContext); + } + public processIdentifierComparison(): ProcessIdentifierComparisonContext | null { + return this.getRuleContext(0, ProcessIdentifierComparisonContext); + } + public titleComparison(): TitleComparisonContext | null { + return this.getRuleContext(0, TitleComparisonContext); + } + public creationDateComparison(): CreationDateComparisonContext | null { + return this.getRuleContext(0, CreationDateComparisonContext); + } + public authorComparison(): AuthorComparisonContext | null { + return this.getRuleContext(0, AuthorComparisonContext); + } + public placesComparison(): PlacesComparisonContext | null { + return this.getRuleContext(0, PlacesComparisonContext); + } + public tasksStateComparison(): TasksStateComparisonContext | null { + return this.getRuleContext(0, TasksStateComparisonContext); + } + public tasksUserIdComparison(): TasksUserIdComparisonContext | null { + return this.getRuleContext(0, TasksUserIdComparisonContext); + } + public dataValueComparison(): DataValueComparisonContext | null { + return this.getRuleContext(0, DataValueComparisonContext); + } + public dataOptionsComparison(): DataOptionsComparisonContext | null { + return this.getRuleContext(0, DataOptionsComparisonContext); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_caseComparisons; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitCaseComparisons) { + return visitor.visitCaseComparisons(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class TaskComparisonsContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public idComparison(): IdComparisonContext | null { + return this.getRuleContext(0, IdComparisonContext); + } + public transitionIdComparison(): TransitionIdComparisonContext | null { + return this.getRuleContext(0, TransitionIdComparisonContext); + } + public titleComparison(): TitleComparisonContext | null { + return this.getRuleContext(0, TitleComparisonContext); + } + public stateComparison(): StateComparisonContext | null { + return this.getRuleContext(0, StateComparisonContext); + } + public userIdComparison(): UserIdComparisonContext | null { + return this.getRuleContext(0, UserIdComparisonContext); + } + public caseIdComparison(): CaseIdComparisonContext | null { + return this.getRuleContext(0, CaseIdComparisonContext); + } + public processIdComparison(): ProcessIdComparisonContext | null { + return this.getRuleContext(0, ProcessIdComparisonContext); + } + public lastAssignComparison(): LastAssignComparisonContext | null { + return this.getRuleContext(0, LastAssignComparisonContext); + } + public lastFinishComparison(): LastFinishComparisonContext | null { + return this.getRuleContext(0, LastFinishComparisonContext); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_taskComparisons; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTaskComparisons) { + return visitor.visitTaskComparisons(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class UserComparisonsContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public idComparison(): IdComparisonContext | null { + return this.getRuleContext(0, IdComparisonContext); + } + public nameComparison(): NameComparisonContext | null { + return this.getRuleContext(0, NameComparisonContext); + } + public surnameComparison(): SurnameComparisonContext | null { + return this.getRuleContext(0, SurnameComparisonContext); + } + public emailComparison(): EmailComparisonContext | null { + return this.getRuleContext(0, EmailComparisonContext); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_userComparisons; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitUserComparisons) { + return visitor.visitUserComparisons(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class IdComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_idComparison; + } + public override copyFrom(ctx: IdComparisonContext): void { + super.copyFrom(ctx); + } +} +export class IdBasicContext extends IdComparisonContext { + public constructor(ctx: IdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public ID(): antlr.TerminalNode { + return this.getToken(QueryLangParser.ID, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public objectIdComparison(): ObjectIdComparisonContext { + return this.getRuleContext(0, ObjectIdComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitIdBasic) { + return visitor.visitIdBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class IdListContext extends IdComparisonContext { + public constructor(ctx: IdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public ID(): antlr.TerminalNode { + return this.getToken(QueryLangParser.ID, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListStringComparison(): InListStringComparisonContext { + return this.getRuleContext(0, InListStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitIdList) { + return visitor.visitIdList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class IdNullContext extends IdComparisonContext { + public constructor(ctx: IdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public ID(): antlr.TerminalNode { + return this.getToken(QueryLangParser.ID, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public nullComparison(): NullComparisonContext { + return this.getRuleContext(0, NullComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitIdNull) { + return visitor.visitIdNull(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class TitleComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_titleComparison; + } + public override copyFrom(ctx: TitleComparisonContext): void { + super.copyFrom(ctx); + } +} +export class TitleBasicContext extends TitleComparisonContext { + public constructor(ctx: TitleComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public TITLE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.TITLE, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public stringComparison(): StringComparisonContext { + return this.getRuleContext(0, StringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTitleBasic) { + return visitor.visitTitleBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class TitleLikeContext extends TitleComparisonContext { + public constructor(ctx: TitleComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public TITLE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.TITLE, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public stringLikeComparison(): StringLikeComparisonContext { + return this.getRuleContext(0, StringLikeComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTitleLike) { + return visitor.visitTitleLike(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class TitleListContext extends TitleComparisonContext { + public constructor(ctx: TitleComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public TITLE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.TITLE, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListStringComparison(): InListStringComparisonContext { + return this.getRuleContext(0, InListStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTitleList) { + return visitor.visitTitleList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class TitleRangeContext extends TitleComparisonContext { + public constructor(ctx: TitleComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public TITLE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.TITLE, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inRangeStringComparison(): InRangeStringComparisonContext { + return this.getRuleContext(0, InRangeStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTitleRange) { + return visitor.visitTitleRange(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class TitleNullContext extends TitleComparisonContext { + public constructor(ctx: TitleComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public TITLE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.TITLE, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public nullComparison(): NullComparisonContext { + return this.getRuleContext(0, NullComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTitleNull) { + return visitor.visitTitleNull(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class IdentifierComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_identifierComparison; + } + public override copyFrom(ctx: IdentifierComparisonContext): void { + super.copyFrom(ctx); + } +} +export class IdentifierBasicContext extends IdentifierComparisonContext { + public constructor(ctx: IdentifierComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public IDENTIFIER(): antlr.TerminalNode { + return this.getToken(QueryLangParser.IDENTIFIER, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public stringComparison(): StringComparisonContext { + return this.getRuleContext(0, StringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitIdentifierBasic) { + return visitor.visitIdentifierBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class IdentifierListContext extends IdentifierComparisonContext { + public constructor(ctx: IdentifierComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public IDENTIFIER(): antlr.TerminalNode { + return this.getToken(QueryLangParser.IDENTIFIER, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListStringComparison(): InListStringComparisonContext { + return this.getRuleContext(0, InListStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitIdentifierList) { + return visitor.visitIdentifierList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class IdentifierRangeContext extends IdentifierComparisonContext { + public constructor(ctx: IdentifierComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public IDENTIFIER(): antlr.TerminalNode { + return this.getToken(QueryLangParser.IDENTIFIER, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inRangeStringComparison(): InRangeStringComparisonContext { + return this.getRuleContext(0, InRangeStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitIdentifierRange) { + return visitor.visitIdentifierRange(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class IdentifierNullContext extends IdentifierComparisonContext { + public constructor(ctx: IdentifierComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public IDENTIFIER(): antlr.TerminalNode { + return this.getToken(QueryLangParser.IDENTIFIER, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public nullComparison(): NullComparisonContext { + return this.getRuleContext(0, NullComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitIdentifierNull) { + return visitor.visitIdentifierNull(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class VersionComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_versionComparison; + } + public override copyFrom(ctx: VersionComparisonContext): void { + super.copyFrom(ctx); + } +} +export class VersionBasicContext extends VersionComparisonContext { + public _op?: Token | null; + public constructor(ctx: VersionComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public VERSION(): antlr.TerminalNode { + return this.getToken(QueryLangParser.VERSION, 0)!; + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public VERSION_NUMBER(): antlr.TerminalNode { + return this.getToken(QueryLangParser.VERSION_NUMBER, 0)!; + } + public EQ(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.EQ, 0); + } + public LT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.LT, 0); + } + public GT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.GT, 0); + } + public LTE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.LTE, 0); + } + public GTE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.GTE, 0); + } + public NOT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NOT, 0); + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitVersionBasic) { + return visitor.visitVersionBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class VersionListCmpContext extends VersionComparisonContext { + public constructor(ctx: VersionComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public VERSION(): antlr.TerminalNode { + return this.getToken(QueryLangParser.VERSION, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListVersionComparison(): InListVersionComparisonContext { + return this.getRuleContext(0, InListVersionComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitVersionListCmp) { + return visitor.visitVersionListCmp(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class VersionRangeCmpContext extends VersionComparisonContext { + public constructor(ctx: VersionComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public VERSION(): antlr.TerminalNode { + return this.getToken(QueryLangParser.VERSION, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inRangeVersionComparison(): InRangeVersionComparisonContext { + return this.getRuleContext(0, InRangeVersionComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitVersionRangeCmp) { + return visitor.visitVersionRangeCmp(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class VersionNullContext extends VersionComparisonContext { + public constructor(ctx: VersionComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public VERSION(): antlr.TerminalNode { + return this.getToken(QueryLangParser.VERSION, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public nullComparison(): NullComparisonContext { + return this.getRuleContext(0, NullComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitVersionNull) { + return visitor.visitVersionNull(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class CreationDateComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_creationDateComparison; + } + public override copyFrom(ctx: CreationDateComparisonContext): void { + super.copyFrom(ctx); + } +} +export class CdDateBasicContext extends CreationDateComparisonContext { + public constructor(ctx: CreationDateComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public CREATION_DATE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.CREATION_DATE, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public dateComparison(): DateComparisonContext { + return this.getRuleContext(0, DateComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitCdDateBasic) { + return visitor.visitCdDateBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class CdDateTimeBasicContext extends CreationDateComparisonContext { + public constructor(ctx: CreationDateComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public CREATION_DATE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.CREATION_DATE, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public dateTimeComparison(): DateTimeComparisonContext { + return this.getRuleContext(0, DateTimeComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitCdDateTimeBasic) { + return visitor.visitCdDateTimeBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class CdDateListContext extends CreationDateComparisonContext { + public constructor(ctx: CreationDateComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public CREATION_DATE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.CREATION_DATE, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListDateComparison(): InListDateComparisonContext { + return this.getRuleContext(0, InListDateComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitCdDateList) { + return visitor.visitCdDateList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class CdDateRangeContext extends CreationDateComparisonContext { + public constructor(ctx: CreationDateComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public CREATION_DATE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.CREATION_DATE, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inRangeDateComparison(): InRangeDateComparisonContext { + return this.getRuleContext(0, InRangeDateComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitCdDateRange) { + return visitor.visitCdDateRange(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class CdNullContext extends CreationDateComparisonContext { + public constructor(ctx: CreationDateComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public CREATION_DATE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.CREATION_DATE, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public nullComparison(): NullComparisonContext { + return this.getRuleContext(0, NullComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitCdNull) { + return visitor.visitCdNull(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ProcessIdComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_processIdComparison; + } + public override copyFrom(ctx: ProcessIdComparisonContext): void { + super.copyFrom(ctx); + } +} +export class ProcessIdBasicContext extends ProcessIdComparisonContext { + public constructor(ctx: ProcessIdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public PROCESS_ID(): antlr.TerminalNode { + return this.getToken(QueryLangParser.PROCESS_ID, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public stringComparison(): StringComparisonContext { + return this.getRuleContext(0, StringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessIdBasic) { + return visitor.visitProcessIdBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class ProcessIdListContext extends ProcessIdComparisonContext { + public constructor(ctx: ProcessIdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public PROCESS_ID(): antlr.TerminalNode { + return this.getToken(QueryLangParser.PROCESS_ID, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListStringComparison(): InListStringComparisonContext { + return this.getRuleContext(0, InListStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessIdList) { + return visitor.visitProcessIdList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class ProcessIdNullContext extends ProcessIdComparisonContext { + public constructor(ctx: ProcessIdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public PROCESS_ID(): antlr.TerminalNode { + return this.getToken(QueryLangParser.PROCESS_ID, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public nullComparison(): NullComparisonContext { + return this.getRuleContext(0, NullComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessIdNull) { + return visitor.visitProcessIdNull(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ProcessIdObjIdComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_processIdObjIdComparison; + } + public override copyFrom(ctx: ProcessIdObjIdComparisonContext): void { + super.copyFrom(ctx); + } +} +export class ProcessIdObjIdBasicContext extends ProcessIdObjIdComparisonContext { + public constructor(ctx: ProcessIdObjIdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public PROCESS_ID(): antlr.TerminalNode { + return this.getToken(QueryLangParser.PROCESS_ID, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public objectIdComparison(): ObjectIdComparisonContext { + return this.getRuleContext(0, ObjectIdComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessIdObjIdBasic) { + return visitor.visitProcessIdObjIdBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class ProcessIdObjIdListContext extends ProcessIdObjIdComparisonContext { + public constructor(ctx: ProcessIdObjIdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public PROCESS_ID(): antlr.TerminalNode { + return this.getToken(QueryLangParser.PROCESS_ID, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListStringComparison(): InListStringComparisonContext { + return this.getRuleContext(0, InListStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessIdObjIdList) { + return visitor.visitProcessIdObjIdList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class ProcessIdObjNullContext extends ProcessIdObjIdComparisonContext { + public constructor(ctx: ProcessIdObjIdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public PROCESS_ID(): antlr.TerminalNode { + return this.getToken(QueryLangParser.PROCESS_ID, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public nullComparison(): NullComparisonContext { + return this.getRuleContext(0, NullComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessIdObjNull) { + return visitor.visitProcessIdObjNull(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ProcessIdentifierComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_processIdentifierComparison; + } + public override copyFrom(ctx: ProcessIdentifierComparisonContext): void { + super.copyFrom(ctx); + } +} +export class ProcessIdentifierBasicContext extends ProcessIdentifierComparisonContext { + public constructor(ctx: ProcessIdentifierComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public PROCESS_IDENTIFIER(): antlr.TerminalNode { + return this.getToken(QueryLangParser.PROCESS_IDENTIFIER, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public stringComparison(): StringComparisonContext { + return this.getRuleContext(0, StringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessIdentifierBasic) { + return visitor.visitProcessIdentifierBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class ProcessIdentifierListContext extends ProcessIdentifierComparisonContext { + public constructor(ctx: ProcessIdentifierComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public PROCESS_IDENTIFIER(): antlr.TerminalNode { + return this.getToken(QueryLangParser.PROCESS_IDENTIFIER, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListStringComparison(): InListStringComparisonContext { + return this.getRuleContext(0, InListStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessIdentifierList) { + return visitor.visitProcessIdentifierList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class ProcessIdentifierRangeContext extends ProcessIdentifierComparisonContext { + public constructor(ctx: ProcessIdentifierComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public PROCESS_IDENTIFIER(): antlr.TerminalNode { + return this.getToken(QueryLangParser.PROCESS_IDENTIFIER, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inRangeStringComparison(): InRangeStringComparisonContext { + return this.getRuleContext(0, InRangeStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessIdentifierRange) { + return visitor.visitProcessIdentifierRange(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class ProcessIdentifierNullContext extends ProcessIdentifierComparisonContext { + public constructor(ctx: ProcessIdentifierComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public PROCESS_IDENTIFIER(): antlr.TerminalNode { + return this.getToken(QueryLangParser.PROCESS_IDENTIFIER, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public nullComparison(): NullComparisonContext { + return this.getRuleContext(0, NullComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitProcessIdentifierNull) { + return visitor.visitProcessIdentifierNull(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class AuthorComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_authorComparison; + } + public override copyFrom(ctx: AuthorComparisonContext): void { + super.copyFrom(ctx); + } +} +export class AuthorBasicContext extends AuthorComparisonContext { + public constructor(ctx: AuthorComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public AUTHOR(): antlr.TerminalNode { + return this.getToken(QueryLangParser.AUTHOR, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public stringComparison(): StringComparisonContext { + return this.getRuleContext(0, StringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitAuthorBasic) { + return visitor.visitAuthorBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class AuthorListContext extends AuthorComparisonContext { + public constructor(ctx: AuthorComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public AUTHOR(): antlr.TerminalNode { + return this.getToken(QueryLangParser.AUTHOR, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListStringComparison(): InListStringComparisonContext { + return this.getRuleContext(0, InListStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitAuthorList) { + return visitor.visitAuthorList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class AuthorNullContext extends AuthorComparisonContext { + public constructor(ctx: AuthorComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public AUTHOR(): antlr.TerminalNode { + return this.getToken(QueryLangParser.AUTHOR, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public nullComparison(): NullComparisonContext { + return this.getRuleContext(0, NullComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitAuthorNull) { + return visitor.visitAuthorNull(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class TransitionIdComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_transitionIdComparison; + } + public override copyFrom(ctx: TransitionIdComparisonContext): void { + super.copyFrom(ctx); + } +} +export class TransitionIdBasicContext extends TransitionIdComparisonContext { + public constructor(ctx: TransitionIdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public TRANSITION_ID(): antlr.TerminalNode { + return this.getToken(QueryLangParser.TRANSITION_ID, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public stringComparison(): StringComparisonContext { + return this.getRuleContext(0, StringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTransitionIdBasic) { + return visitor.visitTransitionIdBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class TransitionIdListContext extends TransitionIdComparisonContext { + public constructor(ctx: TransitionIdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public TRANSITION_ID(): antlr.TerminalNode { + return this.getToken(QueryLangParser.TRANSITION_ID, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListStringComparison(): InListStringComparisonContext { + return this.getRuleContext(0, InListStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTransitionIdList) { + return visitor.visitTransitionIdList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class TransitionIdRangeContext extends TransitionIdComparisonContext { + public constructor(ctx: TransitionIdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public TRANSITION_ID(): antlr.TerminalNode { + return this.getToken(QueryLangParser.TRANSITION_ID, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inRangeStringComparison(): InRangeStringComparisonContext { + return this.getRuleContext(0, InRangeStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTransitionIdRange) { + return visitor.visitTransitionIdRange(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class TransitionIdNullContext extends TransitionIdComparisonContext { + public constructor(ctx: TransitionIdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public TRANSITION_ID(): antlr.TerminalNode { + return this.getToken(QueryLangParser.TRANSITION_ID, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public nullComparison(): NullComparisonContext { + return this.getRuleContext(0, NullComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTransitionIdNull) { + return visitor.visitTransitionIdNull(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class StateComparisonContext extends antlr.ParserRuleContext { + public _state?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public STATE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.STATE, 0)!; + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public EQ(): antlr.TerminalNode { + return this.getToken(QueryLangParser.EQ, 0)!; + } + public ENABLED(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.ENABLED, 0); + } + public DISABLED(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.DISABLED, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_stateComparison; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitStateComparison) { + return visitor.visitStateComparison(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class UserIdComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_userIdComparison; + } + public override copyFrom(ctx: UserIdComparisonContext): void { + super.copyFrom(ctx); + } +} +export class UserIdBasicContext extends UserIdComparisonContext { + public constructor(ctx: UserIdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public USER_ID(): antlr.TerminalNode { + return this.getToken(QueryLangParser.USER_ID, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public stringComparison(): StringComparisonContext { + return this.getRuleContext(0, StringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitUserIdBasic) { + return visitor.visitUserIdBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class UserIdListContext extends UserIdComparisonContext { + public constructor(ctx: UserIdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public USER_ID(): antlr.TerminalNode { + return this.getToken(QueryLangParser.USER_ID, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListStringComparison(): InListStringComparisonContext { + return this.getRuleContext(0, InListStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitUserIdList) { + return visitor.visitUserIdList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class UserIdNullContext extends UserIdComparisonContext { + public constructor(ctx: UserIdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public USER_ID(): antlr.TerminalNode { + return this.getToken(QueryLangParser.USER_ID, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public nullComparison(): NullComparisonContext { + return this.getRuleContext(0, NullComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitUserIdNull) { + return visitor.visitUserIdNull(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class CaseIdComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_caseIdComparison; + } + public override copyFrom(ctx: CaseIdComparisonContext): void { + super.copyFrom(ctx); + } +} +export class CaseIdBasicContext extends CaseIdComparisonContext { + public constructor(ctx: CaseIdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public CASE_ID(): antlr.TerminalNode { + return this.getToken(QueryLangParser.CASE_ID, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public stringComparison(): StringComparisonContext { + return this.getRuleContext(0, StringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitCaseIdBasic) { + return visitor.visitCaseIdBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class CaseIdListContext extends CaseIdComparisonContext { + public constructor(ctx: CaseIdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public CASE_ID(): antlr.TerminalNode { + return this.getToken(QueryLangParser.CASE_ID, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListStringComparison(): InListStringComparisonContext { + return this.getRuleContext(0, InListStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitCaseIdList) { + return visitor.visitCaseIdList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class CaseIdNullContext extends CaseIdComparisonContext { + public constructor(ctx: CaseIdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public CASE_ID(): antlr.TerminalNode { + return this.getToken(QueryLangParser.CASE_ID, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public nullComparison(): NullComparisonContext { + return this.getRuleContext(0, NullComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitCaseIdNull) { + return visitor.visitCaseIdNull(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class LastAssignComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_lastAssignComparison; + } + public override copyFrom(ctx: LastAssignComparisonContext): void { + super.copyFrom(ctx); + } +} +export class LaDateBasicContext extends LastAssignComparisonContext { + public constructor(ctx: LastAssignComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public LAST_ASSIGN(): antlr.TerminalNode { + return this.getToken(QueryLangParser.LAST_ASSIGN, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public dateComparison(): DateComparisonContext { + return this.getRuleContext(0, DateComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitLaDateBasic) { + return visitor.visitLaDateBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class LaDateTimeBasicContext extends LastAssignComparisonContext { + public constructor(ctx: LastAssignComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public LAST_ASSIGN(): antlr.TerminalNode { + return this.getToken(QueryLangParser.LAST_ASSIGN, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public dateTimeComparison(): DateTimeComparisonContext { + return this.getRuleContext(0, DateTimeComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitLaDateTimeBasic) { + return visitor.visitLaDateTimeBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class LaDateListContext extends LastAssignComparisonContext { + public constructor(ctx: LastAssignComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public LAST_ASSIGN(): antlr.TerminalNode { + return this.getToken(QueryLangParser.LAST_ASSIGN, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListDateComparison(): InListDateComparisonContext { + return this.getRuleContext(0, InListDateComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitLaDateList) { + return visitor.visitLaDateList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class LaDateRangeContext extends LastAssignComparisonContext { + public constructor(ctx: LastAssignComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public LAST_ASSIGN(): antlr.TerminalNode { + return this.getToken(QueryLangParser.LAST_ASSIGN, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inRangeDateComparison(): InRangeDateComparisonContext { + return this.getRuleContext(0, InRangeDateComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitLaDateRange) { + return visitor.visitLaDateRange(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class LaNullContext extends LastAssignComparisonContext { + public constructor(ctx: LastAssignComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public LAST_ASSIGN(): antlr.TerminalNode { + return this.getToken(QueryLangParser.LAST_ASSIGN, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public nullComparison(): NullComparisonContext { + return this.getRuleContext(0, NullComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitLaNull) { + return visitor.visitLaNull(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class LastFinishComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_lastFinishComparison; + } + public override copyFrom(ctx: LastFinishComparisonContext): void { + super.copyFrom(ctx); + } +} +export class LfDateBasicContext extends LastFinishComparisonContext { + public constructor(ctx: LastFinishComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public LAST_FINISH(): antlr.TerminalNode { + return this.getToken(QueryLangParser.LAST_FINISH, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public dateComparison(): DateComparisonContext { + return this.getRuleContext(0, DateComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitLfDateBasic) { + return visitor.visitLfDateBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class LfDateTimeBasicContext extends LastFinishComparisonContext { + public constructor(ctx: LastFinishComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public LAST_FINISH(): antlr.TerminalNode { + return this.getToken(QueryLangParser.LAST_FINISH, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public dateTimeComparison(): DateTimeComparisonContext { + return this.getRuleContext(0, DateTimeComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitLfDateTimeBasic) { + return visitor.visitLfDateTimeBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class LfDateListContext extends LastFinishComparisonContext { + public constructor(ctx: LastFinishComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public LAST_FINISH(): antlr.TerminalNode { + return this.getToken(QueryLangParser.LAST_FINISH, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListDateComparison(): InListDateComparisonContext { + return this.getRuleContext(0, InListDateComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitLfDateList) { + return visitor.visitLfDateList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class LfDateRangeContext extends LastFinishComparisonContext { + public constructor(ctx: LastFinishComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public LAST_FINISH(): antlr.TerminalNode { + return this.getToken(QueryLangParser.LAST_FINISH, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inRangeDateComparison(): InRangeDateComparisonContext { + return this.getRuleContext(0, InRangeDateComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitLfDateRange) { + return visitor.visitLfDateRange(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class LfNullContext extends LastFinishComparisonContext { + public constructor(ctx: LastFinishComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public LAST_FINISH(): antlr.TerminalNode { + return this.getToken(QueryLangParser.LAST_FINISH, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public nullComparison(): NullComparisonContext { + return this.getRuleContext(0, NullComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitLfNull) { + return visitor.visitLfNull(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class NameComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_nameComparison; + } + public override copyFrom(ctx: NameComparisonContext): void { + super.copyFrom(ctx); + } +} +export class NameBasicContext extends NameComparisonContext { + public constructor(ctx: NameComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public NAME(): antlr.TerminalNode { + return this.getToken(QueryLangParser.NAME, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public stringComparison(): StringComparisonContext { + return this.getRuleContext(0, StringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitNameBasic) { + return visitor.visitNameBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class NameListContext extends NameComparisonContext { + public constructor(ctx: NameComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public NAME(): antlr.TerminalNode { + return this.getToken(QueryLangParser.NAME, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListStringComparison(): InListStringComparisonContext { + return this.getRuleContext(0, InListStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitNameList) { + return visitor.visitNameList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class NameRangeContext extends NameComparisonContext { + public constructor(ctx: NameComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public NAME(): antlr.TerminalNode { + return this.getToken(QueryLangParser.NAME, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inRangeStringComparison(): InRangeStringComparisonContext { + return this.getRuleContext(0, InRangeStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitNameRange) { + return visitor.visitNameRange(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class NameNullContext extends NameComparisonContext { + public constructor(ctx: NameComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public NAME(): antlr.TerminalNode { + return this.getToken(QueryLangParser.NAME, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public nullComparison(): NullComparisonContext { + return this.getRuleContext(0, NullComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitNameNull) { + return visitor.visitNameNull(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class SurnameComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_surnameComparison; + } + public override copyFrom(ctx: SurnameComparisonContext): void { + super.copyFrom(ctx); + } +} +export class SurnameBasicContext extends SurnameComparisonContext { + public constructor(ctx: SurnameComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public SURNAME(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SURNAME, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public stringComparison(): StringComparisonContext { + return this.getRuleContext(0, StringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitSurnameBasic) { + return visitor.visitSurnameBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class SurnameListContext extends SurnameComparisonContext { + public constructor(ctx: SurnameComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public SURNAME(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SURNAME, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListStringComparison(): InListStringComparisonContext { + return this.getRuleContext(0, InListStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitSurnameList) { + return visitor.visitSurnameList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class SurnameRangeContext extends SurnameComparisonContext { + public constructor(ctx: SurnameComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public SURNAME(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SURNAME, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inRangeStringComparison(): InRangeStringComparisonContext { + return this.getRuleContext(0, InRangeStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitSurnameRange) { + return visitor.visitSurnameRange(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class SurnameNullContext extends SurnameComparisonContext { + public constructor(ctx: SurnameComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public SURNAME(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SURNAME, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public nullComparison(): NullComparisonContext { + return this.getRuleContext(0, NullComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitSurnameNull) { + return visitor.visitSurnameNull(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class EmailComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_emailComparison; + } + public override copyFrom(ctx: EmailComparisonContext): void { + super.copyFrom(ctx); + } +} +export class EmailBasicContext extends EmailComparisonContext { + public constructor(ctx: EmailComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public EMAIL(): antlr.TerminalNode { + return this.getToken(QueryLangParser.EMAIL, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public stringComparison(): StringComparisonContext { + return this.getRuleContext(0, StringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitEmailBasic) { + return visitor.visitEmailBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class EmailListContext extends EmailComparisonContext { + public constructor(ctx: EmailComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public EMAIL(): antlr.TerminalNode { + return this.getToken(QueryLangParser.EMAIL, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListStringComparison(): InListStringComparisonContext { + return this.getRuleContext(0, InListStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitEmailList) { + return visitor.visitEmailList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class EmailRangeContext extends EmailComparisonContext { + public constructor(ctx: EmailComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public EMAIL(): antlr.TerminalNode { + return this.getToken(QueryLangParser.EMAIL, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inRangeStringComparison(): InRangeStringComparisonContext { + return this.getRuleContext(0, InRangeStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitEmailRange) { + return visitor.visitEmailRange(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class EmailNullContext extends EmailComparisonContext { + public constructor(ctx: EmailComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public EMAIL(): antlr.TerminalNode { + return this.getToken(QueryLangParser.EMAIL, 0)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public nullComparison(): NullComparisonContext { + return this.getRuleContext(0, NullComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitEmailNull) { + return visitor.visitEmailNull(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class DataValueComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_dataValueComparison; + } + public override copyFrom(ctx: DataValueComparisonContext): void { + super.copyFrom(ctx); + } +} +export class DataStringContext extends DataValueComparisonContext { + public constructor(ctx: DataValueComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public dataValue(): DataValueContext { + return this.getRuleContext(0, DataValueContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public stringComparison(): StringComparisonContext { + return this.getRuleContext(0, StringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDataString) { + return visitor.visitDataString(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class DataStringLikeContext extends DataValueComparisonContext { + public constructor(ctx: DataValueComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public dataValue(): DataValueContext { + return this.getRuleContext(0, DataValueContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public stringLikeComparison(): StringLikeComparisonContext { + return this.getRuleContext(0, StringLikeComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDataStringLike) { + return visitor.visitDataStringLike(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class DataNumberContext extends DataValueComparisonContext { + public constructor(ctx: DataValueComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public dataValue(): DataValueContext { + return this.getRuleContext(0, DataValueContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public numberComparison(): NumberComparisonContext { + return this.getRuleContext(0, NumberComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDataNumber) { + return visitor.visitDataNumber(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class DataDateContext extends DataValueComparisonContext { + public constructor(ctx: DataValueComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public dataValue(): DataValueContext { + return this.getRuleContext(0, DataValueContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public dateComparison(): DateComparisonContext { + return this.getRuleContext(0, DateComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDataDate) { + return visitor.visitDataDate(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class DataDatetimeContext extends DataValueComparisonContext { + public constructor(ctx: DataValueComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public dataValue(): DataValueContext { + return this.getRuleContext(0, DataValueContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public dateTimeComparison(): DateTimeComparisonContext { + return this.getRuleContext(0, DateTimeComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDataDatetime) { + return visitor.visitDataDatetime(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class DataBooleanContext extends DataValueComparisonContext { + public constructor(ctx: DataValueComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public dataValue(): DataValueContext { + return this.getRuleContext(0, DataValueContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public booleanComparison(): BooleanComparisonContext { + return this.getRuleContext(0, BooleanComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDataBoolean) { + return visitor.visitDataBoolean(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class DataStringListContext extends DataValueComparisonContext { + public constructor(ctx: DataValueComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public dataValue(): DataValueContext { + return this.getRuleContext(0, DataValueContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListStringComparison(): InListStringComparisonContext { + return this.getRuleContext(0, InListStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDataStringList) { + return visitor.visitDataStringList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class DataNumberListContext extends DataValueComparisonContext { + public constructor(ctx: DataValueComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public dataValue(): DataValueContext { + return this.getRuleContext(0, DataValueContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListNumberComparison(): InListNumberComparisonContext { + return this.getRuleContext(0, InListNumberComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDataNumberList) { + return visitor.visitDataNumberList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class DataDateListContext extends DataValueComparisonContext { + public constructor(ctx: DataValueComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public dataValue(): DataValueContext { + return this.getRuleContext(0, DataValueContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListDateComparison(): InListDateComparisonContext { + return this.getRuleContext(0, InListDateComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDataDateList) { + return visitor.visitDataDateList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class DataStringRangeContext extends DataValueComparisonContext { + public constructor(ctx: DataValueComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public dataValue(): DataValueContext { + return this.getRuleContext(0, DataValueContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inRangeStringComparison(): InRangeStringComparisonContext { + return this.getRuleContext(0, InRangeStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDataStringRange) { + return visitor.visitDataStringRange(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class DataNumberRangeContext extends DataValueComparisonContext { + public constructor(ctx: DataValueComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public dataValue(): DataValueContext { + return this.getRuleContext(0, DataValueContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inRangeNumberComparison(): InRangeNumberComparisonContext { + return this.getRuleContext(0, InRangeNumberComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDataNumberRange) { + return visitor.visitDataNumberRange(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class DataDateRangeContext extends DataValueComparisonContext { + public constructor(ctx: DataValueComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public dataValue(): DataValueContext { + return this.getRuleContext(0, DataValueContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inRangeDateComparison(): InRangeDateComparisonContext { + return this.getRuleContext(0, InRangeDateComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDataDateRange) { + return visitor.visitDataDateRange(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class DataNullContext extends DataValueComparisonContext { + public constructor(ctx: DataValueComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public dataValue(): DataValueContext { + return this.getRuleContext(0, DataValueContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public nullComparison(): NullComparisonContext { + return this.getRuleContext(0, NullComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDataNull) { + return visitor.visitDataNull(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class DataOptionsComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_dataOptionsComparison; + } + public override copyFrom(ctx: DataOptionsComparisonContext): void { + super.copyFrom(ctx); + } +} +export class DataOptionsBasicContext extends DataOptionsComparisonContext { + public constructor(ctx: DataOptionsComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public dataOptions(): DataOptionsContext { + return this.getRuleContext(0, DataOptionsContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public stringComparison(): StringComparisonContext { + return this.getRuleContext(0, StringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDataOptionsBasic) { + return visitor.visitDataOptionsBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class DataOptionsListContext extends DataOptionsComparisonContext { + public constructor(ctx: DataOptionsComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public dataOptions(): DataOptionsContext { + return this.getRuleContext(0, DataOptionsContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListStringComparison(): InListStringComparisonContext { + return this.getRuleContext(0, InListStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDataOptionsList) { + return visitor.visitDataOptionsList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class DataOptionsRangeContext extends DataOptionsComparisonContext { + public constructor(ctx: DataOptionsComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public dataOptions(): DataOptionsContext { + return this.getRuleContext(0, DataOptionsContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inRangeStringComparison(): InRangeStringComparisonContext { + return this.getRuleContext(0, InRangeStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDataOptionsRange) { + return visitor.visitDataOptionsRange(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class DataOptionsNullContext extends DataOptionsComparisonContext { + public constructor(ctx: DataOptionsComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public dataOptions(): DataOptionsContext { + return this.getRuleContext(0, DataOptionsContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public nullComparison(): NullComparisonContext { + return this.getRuleContext(0, NullComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDataOptionsNull) { + return visitor.visitDataOptionsNull(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class PlacesComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_placesComparison; + } + public override copyFrom(ctx: PlacesComparisonContext): void { + super.copyFrom(ctx); + } +} +export class PlacesBasicContext extends PlacesComparisonContext { + public constructor(ctx: PlacesComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public places(): PlacesContext { + return this.getRuleContext(0, PlacesContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public numberComparison(): NumberComparisonContext { + return this.getRuleContext(0, NumberComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitPlacesBasic) { + return visitor.visitPlacesBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class PlacesListContext extends PlacesComparisonContext { + public constructor(ctx: PlacesComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public places(): PlacesContext { + return this.getRuleContext(0, PlacesContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListNumberComparison(): InListNumberComparisonContext { + return this.getRuleContext(0, InListNumberComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitPlacesList) { + return visitor.visitPlacesList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class PlacesRangeContext extends PlacesComparisonContext { + public constructor(ctx: PlacesComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public places(): PlacesContext { + return this.getRuleContext(0, PlacesContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inRangeNumberComparison(): InRangeNumberComparisonContext { + return this.getRuleContext(0, InRangeNumberComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitPlacesRange) { + return visitor.visitPlacesRange(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class PlacesNullContext extends PlacesComparisonContext { + public constructor(ctx: PlacesComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public places(): PlacesContext { + return this.getRuleContext(0, PlacesContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public nullComparison(): NullComparisonContext { + return this.getRuleContext(0, NullComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitPlacesNull) { + return visitor.visitPlacesNull(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class TasksStateComparisonContext extends antlr.ParserRuleContext { + public _op?: Token | null; + public _state?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public tasksState(): TasksStateContext { + return this.getRuleContext(0, TasksStateContext)!; + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public EQ(): antlr.TerminalNode { + return this.getToken(QueryLangParser.EQ, 0)!; + } + public ENABLED(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.ENABLED, 0); + } + public DISABLED(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.DISABLED, 0); + } + public NOT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NOT, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_tasksStateComparison; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTasksStateComparison) { + return visitor.visitTasksStateComparison(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class TasksUserIdComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_tasksUserIdComparison; + } + public override copyFrom(ctx: TasksUserIdComparisonContext): void { + super.copyFrom(ctx); + } +} +export class TasksUserIdBasicContext extends TasksUserIdComparisonContext { + public constructor(ctx: TasksUserIdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public tasksUserId(): TasksUserIdContext { + return this.getRuleContext(0, TasksUserIdContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public stringComparison(): StringComparisonContext { + return this.getRuleContext(0, StringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTasksUserIdBasic) { + return visitor.visitTasksUserIdBasic(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class TasksUserIdListContext extends TasksUserIdComparisonContext { + public constructor(ctx: TasksUserIdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public tasksUserId(): TasksUserIdContext { + return this.getRuleContext(0, TasksUserIdContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public inListStringComparison(): InListStringComparisonContext { + return this.getRuleContext(0, InListStringComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTasksUserIdList) { + return visitor.visitTasksUserIdList(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class TasksUserIdNullContext extends TasksUserIdComparisonContext { + public constructor(ctx: TasksUserIdComparisonContext) { + super(ctx.parent, ctx.invokingState); + super.copyFrom(ctx); + } + public tasksUserId(): TasksUserIdContext { + return this.getRuleContext(0, TasksUserIdContext)!; + } + public SPACE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.SPACE, 0)!; + } + public nullComparison(): NullComparisonContext { + return this.getRuleContext(0, NullComparisonContext)!; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTasksUserIdNull) { + return visitor.visitTasksUserIdNull(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ObjectIdComparisonContext extends antlr.ParserRuleContext { + public _op?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public STRING(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.STRING, 0); + } + public LOGGED_USER_ID(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.LOGGED_USER_ID, 0); + } + public EQ(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.EQ, 0); + } + public NEQ(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NEQ, 0); + } + public NOT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NOT, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_objectIdComparison; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitObjectIdComparison) { + return visitor.visitObjectIdComparison(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class StringComparisonContext extends antlr.ParserRuleContext { + public _op?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public EQ(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.EQ, 0); + } + public NEQ(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NEQ, 0); + } + public CONTAINS(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.CONTAINS, 0); + } + public LT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.LT, 0); + } + public GT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.GT, 0); + } + public LTE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.LTE, 0); + } + public GTE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.GTE, 0); + } + public STRING(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.STRING, 0); + } + public loggedUserStringAttribute(): LoggedUserStringAttributeContext | null { + return this.getRuleContext(0, LoggedUserStringAttributeContext); + } + public NOT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NOT, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_stringComparison; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitStringComparison) { + return visitor.visitStringComparison(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class StringLikeComparisonContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public stringComparison(): StringComparisonContext { + return this.getRuleContext(0, StringComparisonContext)!; + } + public LIKE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.LIKE, 0)!; + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_stringLikeComparison; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitStringLikeComparison) { + return visitor.visitStringLikeComparison(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class NumberComparisonContext extends antlr.ParserRuleContext { + public _op?: Token | null; + public _number_?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public EQ(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.EQ, 0); + } + public NEQ(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NEQ, 0); + } + public LT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.LT, 0); + } + public GT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.GT, 0); + } + public LTE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.LTE, 0); + } + public GTE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.GTE, 0); + } + public INT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.INT, 0); + } + public DOUBLE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.DOUBLE, 0); + } + public NOT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NOT, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_numberComparison; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitNumberComparison) { + return visitor.visitNumberComparison(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class DateComparisonContext extends antlr.ParserRuleContext { + public _op?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public DATE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.DATE, 0)!; + } + public EQ(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.EQ, 0); + } + public NEQ(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NEQ, 0); + } + public LT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.LT, 0); + } + public GT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.GT, 0); + } + public LTE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.LTE, 0); + } + public GTE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.GTE, 0); + } + public NOT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NOT, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_dateComparison; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDateComparison) { + return visitor.visitDateComparison(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class DateTimeComparisonContext extends antlr.ParserRuleContext { + public _op?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public DATETIME(): antlr.TerminalNode { + return this.getToken(QueryLangParser.DATETIME, 0)!; + } + public EQ(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.EQ, 0); + } + public NEQ(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NEQ, 0); + } + public LT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.LT, 0); + } + public GT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.GT, 0); + } + public LTE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.LTE, 0); + } + public GTE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.GTE, 0); + } + public NOT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NOT, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_dateTimeComparison; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDateTimeComparison) { + return visitor.visitDateTimeComparison(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class BooleanComparisonContext extends antlr.ParserRuleContext { + public _op?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public BOOLEAN(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.BOOLEAN, 0); + } + public LOGGED_USER_ANONYMOUS(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.LOGGED_USER_ANONYMOUS, 0); + } + public EQ(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.EQ, 0); + } + public NEQ(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NEQ, 0); + } + public NOT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NOT, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_booleanComparison; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitBooleanComparison) { + return visitor.visitBooleanComparison(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class NullComparisonContext extends antlr.ParserRuleContext { + public _op?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public NULL(): antlr.TerminalNode { + return this.getToken(QueryLangParser.NULL, 0)!; + } + public EQ(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.EQ, 0); + } + public NEQ(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NEQ, 0); + } + public NOT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NOT, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_nullComparison; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitNullComparison) { + return visitor.visitNullComparison(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class InListStringComparisonContext extends antlr.ParserRuleContext { + public _op?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public stringList(): StringListContext { + return this.getRuleContext(0, StringListContext)!; + } + public IN(): antlr.TerminalNode { + return this.getToken(QueryLangParser.IN, 0)!; + } + public NOT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NOT, 0); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_inListStringComparison; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitInListStringComparison) { + return visitor.visitInListStringComparison(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class InListNumberComparisonContext extends antlr.ParserRuleContext { + public _op?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public IN(): antlr.TerminalNode { + return this.getToken(QueryLangParser.IN, 0)!; + } + public intList(): IntListContext | null { + return this.getRuleContext(0, IntListContext); + } + public doubleList(): DoubleListContext | null { + return this.getRuleContext(0, DoubleListContext); + } + public NOT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NOT, 0); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_inListNumberComparison; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitInListNumberComparison) { + return visitor.visitInListNumberComparison(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class InListDateComparisonContext extends antlr.ParserRuleContext { + public _op?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public IN(): antlr.TerminalNode { + return this.getToken(QueryLangParser.IN, 0)!; + } + public dateList(): DateListContext | null { + return this.getRuleContext(0, DateListContext); + } + public dateTimeList(): DateTimeListContext | null { + return this.getRuleContext(0, DateTimeListContext); + } + public NOT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NOT, 0); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_inListDateComparison; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitInListDateComparison) { + return visitor.visitInListDateComparison(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class InListVersionComparisonContext extends antlr.ParserRuleContext { + public _op?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public versionList(): VersionListContext { + return this.getRuleContext(0, VersionListContext)!; + } + public IN(): antlr.TerminalNode { + return this.getToken(QueryLangParser.IN, 0)!; + } + public NOT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NOT, 0); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_inListVersionComparison; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitInListVersionComparison) { + return visitor.visitInListVersionComparison(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class InRangeStringComparisonContext extends antlr.ParserRuleContext { + public _op?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public stringRange(): StringRangeContext { + return this.getRuleContext(0, StringRangeContext)!; + } + public IN(): antlr.TerminalNode { + return this.getToken(QueryLangParser.IN, 0)!; + } + public NOT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NOT, 0); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_inRangeStringComparison; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitInRangeStringComparison) { + return visitor.visitInRangeStringComparison(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class InRangeNumberComparisonContext extends antlr.ParserRuleContext { + public _op?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public IN(): antlr.TerminalNode { + return this.getToken(QueryLangParser.IN, 0)!; + } + public intRange(): IntRangeContext | null { + return this.getRuleContext(0, IntRangeContext); + } + public doubleRange(): DoubleRangeContext | null { + return this.getRuleContext(0, DoubleRangeContext); + } + public NOT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NOT, 0); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_inRangeNumberComparison; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitInRangeNumberComparison) { + return visitor.visitInRangeNumberComparison(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class InRangeDateComparisonContext extends antlr.ParserRuleContext { + public _op?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public IN(): antlr.TerminalNode { + return this.getToken(QueryLangParser.IN, 0)!; + } + public dateRange(): DateRangeContext | null { + return this.getRuleContext(0, DateRangeContext); + } + public dateTimeRange(): DateTimeRangeContext | null { + return this.getRuleContext(0, DateTimeRangeContext); + } + public NOT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NOT, 0); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_inRangeDateComparison; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitInRangeDateComparison) { + return visitor.visitInRangeDateComparison(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class InRangeVersionComparisonContext extends antlr.ParserRuleContext { + public _op?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public versionRange(): VersionRangeContext { + return this.getRuleContext(0, VersionRangeContext)!; + } + public IN(): antlr.TerminalNode { + return this.getToken(QueryLangParser.IN, 0)!; + } + public NOT(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NOT, 0); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_inRangeVersionComparison; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitInRangeVersionComparison) { + return visitor.visitInRangeVersionComparison(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class DataValueContext extends antlr.ParserRuleContext { + public _fieldId?: JavaIdContext; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public DATA(): antlr.TerminalNode { + return this.getToken(QueryLangParser.DATA, 0)!; + } + public VALUE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.VALUE, 0)!; + } + public javaId(): JavaIdContext { + return this.getRuleContext(0, JavaIdContext)!; + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_dataValue; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDataValue) { + return visitor.visitDataValue(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class DataOptionsContext extends antlr.ParserRuleContext { + public _fieldId?: JavaIdContext; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public DATA(): antlr.TerminalNode { + return this.getToken(QueryLangParser.DATA, 0)!; + } + public OPTIONS(): antlr.TerminalNode { + return this.getToken(QueryLangParser.OPTIONS, 0)!; + } + public javaId(): JavaIdContext { + return this.getRuleContext(0, JavaIdContext)!; + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_dataOptions; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDataOptions) { + return visitor.visitDataOptions(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class PlacesContext extends antlr.ParserRuleContext { + public _placeId?: JavaIdContext; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public PLACES(): antlr.TerminalNode { + return this.getToken(QueryLangParser.PLACES, 0)!; + } + public MARKING(): antlr.TerminalNode { + return this.getToken(QueryLangParser.MARKING, 0)!; + } + public javaId(): JavaIdContext { + return this.getRuleContext(0, JavaIdContext)!; + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_places; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitPlaces) { + return visitor.visitPlaces(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class TasksStateContext extends antlr.ParserRuleContext { + public _taskId?: JavaIdContext; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public TASKS(): antlr.TerminalNode { + return this.getToken(QueryLangParser.TASKS, 0)!; + } + public STATE(): antlr.TerminalNode { + return this.getToken(QueryLangParser.STATE, 0)!; + } + public javaId(): JavaIdContext { + return this.getRuleContext(0, JavaIdContext)!; + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_tasksState; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTasksState) { + return visitor.visitTasksState(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class TasksUserIdContext extends antlr.ParserRuleContext { + public _taskId?: JavaIdContext; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public TASKS(): antlr.TerminalNode { + return this.getToken(QueryLangParser.TASKS, 0)!; + } + public USER_ID(): antlr.TerminalNode { + return this.getToken(QueryLangParser.USER_ID, 0)!; + } + public javaId(): JavaIdContext { + return this.getRuleContext(0, JavaIdContext)!; + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_tasksUserId; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitTasksUserId) { + return visitor.visitTasksUserId(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class JavaIdContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public JAVA_ID(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.JAVA_ID, 0); + } + public ID(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.ID, 0); + } + public TITLE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.TITLE, 0); + } + public IDENTIFIER(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.IDENTIFIER, 0); + } + public VERSION(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.VERSION, 0); + } + public CREATION_DATE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.CREATION_DATE, 0); + } + public PROCESS_ID(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.PROCESS_ID, 0); + } + public PROCESS_IDENTIFIER(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.PROCESS_IDENTIFIER, 0); + } + public AUTHOR(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.AUTHOR, 0); + } + public PLACES(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.PLACES, 0); + } + public TRANSITION_ID(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.TRANSITION_ID, 0); + } + public STATE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.STATE, 0); + } + public USER_ID(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.USER_ID, 0); + } + public CASE_ID(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.CASE_ID, 0); + } + public LAST_ASSIGN(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.LAST_ASSIGN, 0); + } + public LAST_FINISH(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.LAST_FINISH, 0); + } + public NAME(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.NAME, 0); + } + public SURNAME(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.SURNAME, 0); + } + public EMAIL(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.EMAIL, 0); + } + public DATA(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.DATA, 0); + } + public VALUE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.VALUE, 0); + } + public OPTIONS(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.OPTIONS, 0); + } + public MARKING(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.MARKING, 0); + } + public ENABLED(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.ENABLED, 0); + } + public DISABLED(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.DISABLED, 0); + } + public PAGE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.PAGE, 0); + } + public SIZE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.SIZE, 0); + } + public ASC(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.ASC, 0); + } + public DESC(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.DESC, 0); + } + public CASE(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.CASE, 0); + } + public CASES(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.CASES, 0); + } + public TASK(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.TASK, 0); + } + public TASKS(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.TASKS, 0); + } + public USER(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.USER, 0); + } + public USERS(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.USERS, 0); + } + public PROCESS(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.PROCESS, 0); + } + public PROCESSES(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.PROCESSES, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_javaId; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitJavaId) { + return visitor.visitJavaId(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class StringListContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public STRING(): antlr.TerminalNode[]; + public STRING(i: number): antlr.TerminalNode | null; + public STRING(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.STRING); + } else { + return this.getToken(QueryLangParser.STRING, i); + } + } + public loggedUserStringAttribute(): LoggedUserStringAttributeContext[]; + public loggedUserStringAttribute(i: number): LoggedUserStringAttributeContext | null; + public loggedUserStringAttribute(i?: number): LoggedUserStringAttributeContext[] | LoggedUserStringAttributeContext | null { + if (i === undefined) { + return this.getRuleContexts(LoggedUserStringAttributeContext); + } + + return this.getRuleContext(i, LoggedUserStringAttributeContext); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_stringList; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitStringList) { + return visitor.visitStringList(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class IntListContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public INT(): antlr.TerminalNode[]; + public INT(i: number): antlr.TerminalNode | null; + public INT(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.INT); + } else { + return this.getToken(QueryLangParser.INT, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_intList; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitIntList) { + return visitor.visitIntList(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class DoubleListContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public DOUBLE(): antlr.TerminalNode[]; + public DOUBLE(i: number): antlr.TerminalNode | null; + public DOUBLE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.DOUBLE); + } else { + return this.getToken(QueryLangParser.DOUBLE, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_doubleList; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDoubleList) { + return visitor.visitDoubleList(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class DateListContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public DATE(): antlr.TerminalNode[]; + public DATE(i: number): antlr.TerminalNode | null; + public DATE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.DATE); + } else { + return this.getToken(QueryLangParser.DATE, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_dateList; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDateList) { + return visitor.visitDateList(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class DateTimeListContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public DATETIME(): antlr.TerminalNode[]; + public DATETIME(i: number): antlr.TerminalNode | null; + public DATETIME(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.DATETIME); + } else { + return this.getToken(QueryLangParser.DATETIME, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_dateTimeList; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDateTimeList) { + return visitor.visitDateTimeList(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class VersionListContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public VERSION_NUMBER(): antlr.TerminalNode[]; + public VERSION_NUMBER(i: number): antlr.TerminalNode | null; + public VERSION_NUMBER(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.VERSION_NUMBER); + } else { + return this.getToken(QueryLangParser.VERSION_NUMBER, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_versionList; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitVersionList) { + return visitor.visitVersionList(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class StringRangeContext extends antlr.ParserRuleContext { + public _leftEndpoint?: Token | null; + public _rightEndpoint?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public STRING(): antlr.TerminalNode[]; + public STRING(i: number): antlr.TerminalNode | null; + public STRING(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.STRING); + } else { + return this.getToken(QueryLangParser.STRING, i); + } + } + public loggedUserStringAttribute(): LoggedUserStringAttributeContext[]; + public loggedUserStringAttribute(i: number): LoggedUserStringAttributeContext | null; + public loggedUserStringAttribute(i?: number): LoggedUserStringAttributeContext[] | LoggedUserStringAttributeContext | null { + if (i === undefined) { + return this.getRuleContexts(LoggedUserStringAttributeContext); + } + + return this.getRuleContext(i, LoggedUserStringAttributeContext); + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_stringRange; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitStringRange) { + return visitor.visitStringRange(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class IntRangeContext extends antlr.ParserRuleContext { + public _leftEndpoint?: Token | null; + public _rightEndpoint?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public INT(): antlr.TerminalNode[]; + public INT(i: number): antlr.TerminalNode | null; + public INT(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.INT); + } else { + return this.getToken(QueryLangParser.INT, i); + } + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_intRange; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitIntRange) { + return visitor.visitIntRange(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class DoubleRangeContext extends antlr.ParserRuleContext { + public _leftEndpoint?: Token | null; + public _rightEndpoint?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public DOUBLE(): antlr.TerminalNode[]; + public DOUBLE(i: number): antlr.TerminalNode | null; + public DOUBLE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.DOUBLE); + } else { + return this.getToken(QueryLangParser.DOUBLE, i); + } + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_doubleRange; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDoubleRange) { + return visitor.visitDoubleRange(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class DateRangeContext extends antlr.ParserRuleContext { + public _leftEndpoint?: Token | null; + public _rightEndpoint?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public DATE(): antlr.TerminalNode[]; + public DATE(i: number): antlr.TerminalNode | null; + public DATE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.DATE); + } else { + return this.getToken(QueryLangParser.DATE, i); + } + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_dateRange; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDateRange) { + return visitor.visitDateRange(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class DateTimeRangeContext extends antlr.ParserRuleContext { + public _leftEndpoint?: Token | null; + public _rightEndpoint?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public DATETIME(): antlr.TerminalNode[]; + public DATETIME(i: number): antlr.TerminalNode | null; + public DATETIME(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.DATETIME); + } else { + return this.getToken(QueryLangParser.DATETIME, i); + } + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_dateTimeRange; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitDateTimeRange) { + return visitor.visitDateTimeRange(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class VersionRangeContext extends antlr.ParserRuleContext { + public _leftEndpoint?: Token | null; + public _rightEndpoint?: Token | null; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public VERSION_NUMBER(): antlr.TerminalNode[]; + public VERSION_NUMBER(i: number): antlr.TerminalNode | null; + public VERSION_NUMBER(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.VERSION_NUMBER); + } else { + return this.getToken(QueryLangParser.VERSION_NUMBER, i); + } + } + public SPACE(): antlr.TerminalNode[]; + public SPACE(i: number): antlr.TerminalNode | null; + public SPACE(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(QueryLangParser.SPACE); + } else { + return this.getToken(QueryLangParser.SPACE, i); + } + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_versionRange; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitVersionRange) { + return visitor.visitVersionRange(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class LoggedUserStringAttributeContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public LOGGED_USER_ID(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.LOGGED_USER_ID, 0); + } + public LOGGED_USER_USERNAME(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.LOGGED_USER_USERNAME, 0); + } + public LOGGED_USER_FULLNAME(): antlr.TerminalNode | null { + return this.getToken(QueryLangParser.LOGGED_USER_FULLNAME, 0); + } + public override get ruleIndex(): number { + return QueryLangParser.RULE_loggedUserStringAttribute; + } + public override accept(visitor: QueryLangVisitor): Result | null { + if (visitor.visitLoggedUserStringAttribute) { + return visitor.visitLoggedUserStringAttribute(this); + } else { + return visitor.visitChildren(this); + } + } +} diff --git a/projects/netgrif-components-core/src/lib/pfql/generated/QueryLangVisitor.ts b/projects/netgrif-components-core/src/lib/pfql/generated/QueryLangVisitor.ts new file mode 100644 index 0000000000..b7f1dba548 --- /dev/null +++ b/projects/netgrif-components-core/src/lib/pfql/generated/QueryLangVisitor.ts @@ -0,0 +1,1357 @@ + +import { AbstractParseTreeVisitor } from "antlr4ng"; + + +import { ProcessQueryContext } from "./QueryLangParser.js"; +import { CaseQueryContext } from "./QueryLangParser.js"; +import { TaskQueryContext } from "./QueryLangParser.js"; +import { UserQueryContext } from "./QueryLangParser.js"; +import { ProcessConditionsAndPagingContext } from "./QueryLangParser.js"; +import { CaseConditionsAndPagingContext } from "./QueryLangParser.js"; +import { TaskConditionsAndPagingContext } from "./QueryLangParser.js"; +import { UserConditionsAndPagingContext } from "./QueryLangParser.js"; +import { ProcessConditionsContext } from "./QueryLangParser.js"; +import { ProcessOrExpressionContext } from "./QueryLangParser.js"; +import { ProcessAndExpressionContext } from "./QueryLangParser.js"; +import { ProcessConditionGroupBasicContext } from "./QueryLangParser.js"; +import { ProcessConditionGroupParenthesisContext } from "./QueryLangParser.js"; +import { ProcessConditionContext } from "./QueryLangParser.js"; +import { CaseConditionsContext } from "./QueryLangParser.js"; +import { CaseOrExpressionContext } from "./QueryLangParser.js"; +import { CaseAndExpressionContext } from "./QueryLangParser.js"; +import { CaseConditionGroupBasicContext } from "./QueryLangParser.js"; +import { CaseConditionGroupParenthesisContext } from "./QueryLangParser.js"; +import { CaseConditionContext } from "./QueryLangParser.js"; +import { TaskConditionsContext } from "./QueryLangParser.js"; +import { TaskOrExpressionContext } from "./QueryLangParser.js"; +import { TaskAndExpressionContext } from "./QueryLangParser.js"; +import { TaskConditionGroupBasicContext } from "./QueryLangParser.js"; +import { TaskConditionGroupParenthesisContext } from "./QueryLangParser.js"; +import { TaskConditionContext } from "./QueryLangParser.js"; +import { UserConditionsContext } from "./QueryLangParser.js"; +import { UserOrExpressionContext } from "./QueryLangParser.js"; +import { UserAndExpressionContext } from "./QueryLangParser.js"; +import { UserConditionGroupBasicContext } from "./QueryLangParser.js"; +import { UserConditionGroupParenthesisContext } from "./QueryLangParser.js"; +import { UserConditionContext } from "./QueryLangParser.js"; +import { DelimeterContext } from "./QueryLangParser.js"; +import { PagingContext } from "./QueryLangParser.js"; +import { ProcessSortingContext } from "./QueryLangParser.js"; +import { ProcessAttributeOrderingContext } from "./QueryLangParser.js"; +import { ProcessAttributeContext } from "./QueryLangParser.js"; +import { CaseSortingContext } from "./QueryLangParser.js"; +import { CaseAttributeOrderingContext } from "./QueryLangParser.js"; +import { CaseAttributeContext } from "./QueryLangParser.js"; +import { TaskSortingContext } from "./QueryLangParser.js"; +import { TaskAttributeOrderingContext } from "./QueryLangParser.js"; +import { TaskAttributeContext } from "./QueryLangParser.js"; +import { UserSortingContext } from "./QueryLangParser.js"; +import { UserAttributeOrderingContext } from "./QueryLangParser.js"; +import { UserAttributeContext } from "./QueryLangParser.js"; +import { ProcessComparisonsContext } from "./QueryLangParser.js"; +import { CaseComparisonsContext } from "./QueryLangParser.js"; +import { TaskComparisonsContext } from "./QueryLangParser.js"; +import { UserComparisonsContext } from "./QueryLangParser.js"; +import { IdBasicContext } from "./QueryLangParser.js"; +import { IdListContext } from "./QueryLangParser.js"; +import { IdNullContext } from "./QueryLangParser.js"; +import { TitleBasicContext } from "./QueryLangParser.js"; +import { TitleLikeContext } from "./QueryLangParser.js"; +import { TitleListContext } from "./QueryLangParser.js"; +import { TitleRangeContext } from "./QueryLangParser.js"; +import { TitleNullContext } from "./QueryLangParser.js"; +import { IdentifierBasicContext } from "./QueryLangParser.js"; +import { IdentifierListContext } from "./QueryLangParser.js"; +import { IdentifierRangeContext } from "./QueryLangParser.js"; +import { IdentifierNullContext } from "./QueryLangParser.js"; +import { VersionBasicContext } from "./QueryLangParser.js"; +import { VersionListCmpContext } from "./QueryLangParser.js"; +import { VersionRangeCmpContext } from "./QueryLangParser.js"; +import { VersionNullContext } from "./QueryLangParser.js"; +import { CdDateBasicContext } from "./QueryLangParser.js"; +import { CdDateTimeBasicContext } from "./QueryLangParser.js"; +import { CdDateListContext } from "./QueryLangParser.js"; +import { CdDateRangeContext } from "./QueryLangParser.js"; +import { CdNullContext } from "./QueryLangParser.js"; +import { ProcessIdBasicContext } from "./QueryLangParser.js"; +import { ProcessIdListContext } from "./QueryLangParser.js"; +import { ProcessIdNullContext } from "./QueryLangParser.js"; +import { ProcessIdObjIdBasicContext } from "./QueryLangParser.js"; +import { ProcessIdObjIdListContext } from "./QueryLangParser.js"; +import { ProcessIdObjNullContext } from "./QueryLangParser.js"; +import { ProcessIdentifierBasicContext } from "./QueryLangParser.js"; +import { ProcessIdentifierListContext } from "./QueryLangParser.js"; +import { ProcessIdentifierRangeContext } from "./QueryLangParser.js"; +import { ProcessIdentifierNullContext } from "./QueryLangParser.js"; +import { AuthorBasicContext } from "./QueryLangParser.js"; +import { AuthorListContext } from "./QueryLangParser.js"; +import { AuthorNullContext } from "./QueryLangParser.js"; +import { TransitionIdBasicContext } from "./QueryLangParser.js"; +import { TransitionIdListContext } from "./QueryLangParser.js"; +import { TransitionIdRangeContext } from "./QueryLangParser.js"; +import { TransitionIdNullContext } from "./QueryLangParser.js"; +import { StateComparisonContext } from "./QueryLangParser.js"; +import { UserIdBasicContext } from "./QueryLangParser.js"; +import { UserIdListContext } from "./QueryLangParser.js"; +import { UserIdNullContext } from "./QueryLangParser.js"; +import { CaseIdBasicContext } from "./QueryLangParser.js"; +import { CaseIdListContext } from "./QueryLangParser.js"; +import { CaseIdNullContext } from "./QueryLangParser.js"; +import { LaDateBasicContext } from "./QueryLangParser.js"; +import { LaDateTimeBasicContext } from "./QueryLangParser.js"; +import { LaDateListContext } from "./QueryLangParser.js"; +import { LaDateRangeContext } from "./QueryLangParser.js"; +import { LaNullContext } from "./QueryLangParser.js"; +import { LfDateBasicContext } from "./QueryLangParser.js"; +import { LfDateTimeBasicContext } from "./QueryLangParser.js"; +import { LfDateListContext } from "./QueryLangParser.js"; +import { LfDateRangeContext } from "./QueryLangParser.js"; +import { LfNullContext } from "./QueryLangParser.js"; +import { NameBasicContext } from "./QueryLangParser.js"; +import { NameListContext } from "./QueryLangParser.js"; +import { NameRangeContext } from "./QueryLangParser.js"; +import { NameNullContext } from "./QueryLangParser.js"; +import { SurnameBasicContext } from "./QueryLangParser.js"; +import { SurnameListContext } from "./QueryLangParser.js"; +import { SurnameRangeContext } from "./QueryLangParser.js"; +import { SurnameNullContext } from "./QueryLangParser.js"; +import { EmailBasicContext } from "./QueryLangParser.js"; +import { EmailListContext } from "./QueryLangParser.js"; +import { EmailRangeContext } from "./QueryLangParser.js"; +import { EmailNullContext } from "./QueryLangParser.js"; +import { DataStringContext } from "./QueryLangParser.js"; +import { DataStringLikeContext } from "./QueryLangParser.js"; +import { DataNumberContext } from "./QueryLangParser.js"; +import { DataDateContext } from "./QueryLangParser.js"; +import { DataDatetimeContext } from "./QueryLangParser.js"; +import { DataBooleanContext } from "./QueryLangParser.js"; +import { DataStringListContext } from "./QueryLangParser.js"; +import { DataNumberListContext } from "./QueryLangParser.js"; +import { DataDateListContext } from "./QueryLangParser.js"; +import { DataStringRangeContext } from "./QueryLangParser.js"; +import { DataNumberRangeContext } from "./QueryLangParser.js"; +import { DataDateRangeContext } from "./QueryLangParser.js"; +import { DataNullContext } from "./QueryLangParser.js"; +import { DataOptionsBasicContext } from "./QueryLangParser.js"; +import { DataOptionsListContext } from "./QueryLangParser.js"; +import { DataOptionsRangeContext } from "./QueryLangParser.js"; +import { DataOptionsNullContext } from "./QueryLangParser.js"; +import { PlacesBasicContext } from "./QueryLangParser.js"; +import { PlacesListContext } from "./QueryLangParser.js"; +import { PlacesRangeContext } from "./QueryLangParser.js"; +import { PlacesNullContext } from "./QueryLangParser.js"; +import { TasksStateComparisonContext } from "./QueryLangParser.js"; +import { TasksUserIdBasicContext } from "./QueryLangParser.js"; +import { TasksUserIdListContext } from "./QueryLangParser.js"; +import { TasksUserIdNullContext } from "./QueryLangParser.js"; +import { ObjectIdComparisonContext } from "./QueryLangParser.js"; +import { StringComparisonContext } from "./QueryLangParser.js"; +import { StringLikeComparisonContext } from "./QueryLangParser.js"; +import { NumberComparisonContext } from "./QueryLangParser.js"; +import { DateComparisonContext } from "./QueryLangParser.js"; +import { DateTimeComparisonContext } from "./QueryLangParser.js"; +import { BooleanComparisonContext } from "./QueryLangParser.js"; +import { NullComparisonContext } from "./QueryLangParser.js"; +import { InListStringComparisonContext } from "./QueryLangParser.js"; +import { InListNumberComparisonContext } from "./QueryLangParser.js"; +import { InListDateComparisonContext } from "./QueryLangParser.js"; +import { InListVersionComparisonContext } from "./QueryLangParser.js"; +import { InRangeStringComparisonContext } from "./QueryLangParser.js"; +import { InRangeNumberComparisonContext } from "./QueryLangParser.js"; +import { InRangeDateComparisonContext } from "./QueryLangParser.js"; +import { InRangeVersionComparisonContext } from "./QueryLangParser.js"; +import { DataValueContext } from "./QueryLangParser.js"; +import { DataOptionsContext } from "./QueryLangParser.js"; +import { PlacesContext } from "./QueryLangParser.js"; +import { TasksStateContext } from "./QueryLangParser.js"; +import { TasksUserIdContext } from "./QueryLangParser.js"; +import { JavaIdContext } from "./QueryLangParser.js"; +import { StringListContext } from "./QueryLangParser.js"; +import { IntListContext } from "./QueryLangParser.js"; +import { DoubleListContext } from "./QueryLangParser.js"; +import { DateListContext } from "./QueryLangParser.js"; +import { DateTimeListContext } from "./QueryLangParser.js"; +import { VersionListContext } from "./QueryLangParser.js"; +import { StringRangeContext } from "./QueryLangParser.js"; +import { IntRangeContext } from "./QueryLangParser.js"; +import { DoubleRangeContext } from "./QueryLangParser.js"; +import { DateRangeContext } from "./QueryLangParser.js"; +import { DateTimeRangeContext } from "./QueryLangParser.js"; +import { VersionRangeContext } from "./QueryLangParser.js"; +import { LoggedUserStringAttributeContext } from "./QueryLangParser.js"; + + +/** + * This interface defines a complete generic visitor for a parse tree produced + * by `QueryLangParser`. + * + * @param The return type of the visit operation. Use `void` for + * operations with no return type. + */ +export class QueryLangVisitor extends AbstractParseTreeVisitor { + /** + * Visit a parse tree produced by the `processQuery` + * labeled alternative in `QueryLangParser.query`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessQuery?: (ctx: ProcessQueryContext) => Result; + /** + * Visit a parse tree produced by the `caseQuery` + * labeled alternative in `QueryLangParser.query`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCaseQuery?: (ctx: CaseQueryContext) => Result; + /** + * Visit a parse tree produced by the `taskQuery` + * labeled alternative in `QueryLangParser.query`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTaskQuery?: (ctx: TaskQueryContext) => Result; + /** + * Visit a parse tree produced by the `userQuery` + * labeled alternative in `QueryLangParser.query`. + * @param ctx the parse tree + * @return the visitor result + */ + visitUserQuery?: (ctx: UserQueryContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.processConditionsAndPaging`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessConditionsAndPaging?: (ctx: ProcessConditionsAndPagingContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.caseConditionsAndPaging`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCaseConditionsAndPaging?: (ctx: CaseConditionsAndPagingContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.taskConditionsAndPaging`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTaskConditionsAndPaging?: (ctx: TaskConditionsAndPagingContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.userConditionsAndPaging`. + * @param ctx the parse tree + * @return the visitor result + */ + visitUserConditionsAndPaging?: (ctx: UserConditionsAndPagingContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.processConditions`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessConditions?: (ctx: ProcessConditionsContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.processOrExpression`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessOrExpression?: (ctx: ProcessOrExpressionContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.processAndExpression`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessAndExpression?: (ctx: ProcessAndExpressionContext) => Result; + /** + * Visit a parse tree produced by the `processConditionGroupBasic` + * labeled alternative in `QueryLangParser.processConditionGroup`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessConditionGroupBasic?: (ctx: ProcessConditionGroupBasicContext) => Result; + /** + * Visit a parse tree produced by the `processConditionGroupParenthesis` + * labeled alternative in `QueryLangParser.processConditionGroup`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessConditionGroupParenthesis?: (ctx: ProcessConditionGroupParenthesisContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.processCondition`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessCondition?: (ctx: ProcessConditionContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.caseConditions`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCaseConditions?: (ctx: CaseConditionsContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.caseOrExpression`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCaseOrExpression?: (ctx: CaseOrExpressionContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.caseAndExpression`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCaseAndExpression?: (ctx: CaseAndExpressionContext) => Result; + /** + * Visit a parse tree produced by the `caseConditionGroupBasic` + * labeled alternative in `QueryLangParser.caseConditionGroup`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCaseConditionGroupBasic?: (ctx: CaseConditionGroupBasicContext) => Result; + /** + * Visit a parse tree produced by the `caseConditionGroupParenthesis` + * labeled alternative in `QueryLangParser.caseConditionGroup`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCaseConditionGroupParenthesis?: (ctx: CaseConditionGroupParenthesisContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.caseCondition`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCaseCondition?: (ctx: CaseConditionContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.taskConditions`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTaskConditions?: (ctx: TaskConditionsContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.taskOrExpression`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTaskOrExpression?: (ctx: TaskOrExpressionContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.taskAndExpression`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTaskAndExpression?: (ctx: TaskAndExpressionContext) => Result; + /** + * Visit a parse tree produced by the `taskConditionGroupBasic` + * labeled alternative in `QueryLangParser.taskConditionGroup`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTaskConditionGroupBasic?: (ctx: TaskConditionGroupBasicContext) => Result; + /** + * Visit a parse tree produced by the `taskConditionGroupParenthesis` + * labeled alternative in `QueryLangParser.taskConditionGroup`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTaskConditionGroupParenthesis?: (ctx: TaskConditionGroupParenthesisContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.taskCondition`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTaskCondition?: (ctx: TaskConditionContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.userConditions`. + * @param ctx the parse tree + * @return the visitor result + */ + visitUserConditions?: (ctx: UserConditionsContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.userOrExpression`. + * @param ctx the parse tree + * @return the visitor result + */ + visitUserOrExpression?: (ctx: UserOrExpressionContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.userAndExpression`. + * @param ctx the parse tree + * @return the visitor result + */ + visitUserAndExpression?: (ctx: UserAndExpressionContext) => Result; + /** + * Visit a parse tree produced by the `userConditionGroupBasic` + * labeled alternative in `QueryLangParser.userConditionGroup`. + * @param ctx the parse tree + * @return the visitor result + */ + visitUserConditionGroupBasic?: (ctx: UserConditionGroupBasicContext) => Result; + /** + * Visit a parse tree produced by the `userConditionGroupParenthesis` + * labeled alternative in `QueryLangParser.userConditionGroup`. + * @param ctx the parse tree + * @return the visitor result + */ + visitUserConditionGroupParenthesis?: (ctx: UserConditionGroupParenthesisContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.userCondition`. + * @param ctx the parse tree + * @return the visitor result + */ + visitUserCondition?: (ctx: UserConditionContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.delimeter`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDelimeter?: (ctx: DelimeterContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.paging`. + * @param ctx the parse tree + * @return the visitor result + */ + visitPaging?: (ctx: PagingContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.processSorting`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessSorting?: (ctx: ProcessSortingContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.processAttributeOrdering`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessAttributeOrdering?: (ctx: ProcessAttributeOrderingContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.processAttribute`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessAttribute?: (ctx: ProcessAttributeContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.caseSorting`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCaseSorting?: (ctx: CaseSortingContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.caseAttributeOrdering`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCaseAttributeOrdering?: (ctx: CaseAttributeOrderingContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.caseAttribute`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCaseAttribute?: (ctx: CaseAttributeContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.taskSorting`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTaskSorting?: (ctx: TaskSortingContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.taskAttributeOrdering`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTaskAttributeOrdering?: (ctx: TaskAttributeOrderingContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.taskAttribute`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTaskAttribute?: (ctx: TaskAttributeContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.userSorting`. + * @param ctx the parse tree + * @return the visitor result + */ + visitUserSorting?: (ctx: UserSortingContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.userAttributeOrdering`. + * @param ctx the parse tree + * @return the visitor result + */ + visitUserAttributeOrdering?: (ctx: UserAttributeOrderingContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.userAttribute`. + * @param ctx the parse tree + * @return the visitor result + */ + visitUserAttribute?: (ctx: UserAttributeContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.processComparisons`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessComparisons?: (ctx: ProcessComparisonsContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.caseComparisons`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCaseComparisons?: (ctx: CaseComparisonsContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.taskComparisons`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTaskComparisons?: (ctx: TaskComparisonsContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.userComparisons`. + * @param ctx the parse tree + * @return the visitor result + */ + visitUserComparisons?: (ctx: UserComparisonsContext) => Result; + /** + * Visit a parse tree produced by the `idBasic` + * labeled alternative in `QueryLangParser.idComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitIdBasic?: (ctx: IdBasicContext) => Result; + /** + * Visit a parse tree produced by the `idList` + * labeled alternative in `QueryLangParser.idComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitIdList?: (ctx: IdListContext) => Result; + /** + * Visit a parse tree produced by the `idNull` + * labeled alternative in `QueryLangParser.idComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitIdNull?: (ctx: IdNullContext) => Result; + /** + * Visit a parse tree produced by the `titleBasic` + * labeled alternative in `QueryLangParser.titleComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTitleBasic?: (ctx: TitleBasicContext) => Result; + /** + * Visit a parse tree produced by the `titleLike` + * labeled alternative in `QueryLangParser.titleComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTitleLike?: (ctx: TitleLikeContext) => Result; + /** + * Visit a parse tree produced by the `titleList` + * labeled alternative in `QueryLangParser.titleComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTitleList?: (ctx: TitleListContext) => Result; + /** + * Visit a parse tree produced by the `titleRange` + * labeled alternative in `QueryLangParser.titleComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTitleRange?: (ctx: TitleRangeContext) => Result; + /** + * Visit a parse tree produced by the `titleNull` + * labeled alternative in `QueryLangParser.titleComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTitleNull?: (ctx: TitleNullContext) => Result; + /** + * Visit a parse tree produced by the `identifierBasic` + * labeled alternative in `QueryLangParser.identifierComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitIdentifierBasic?: (ctx: IdentifierBasicContext) => Result; + /** + * Visit a parse tree produced by the `identifierList` + * labeled alternative in `QueryLangParser.identifierComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitIdentifierList?: (ctx: IdentifierListContext) => Result; + /** + * Visit a parse tree produced by the `identifierRange` + * labeled alternative in `QueryLangParser.identifierComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitIdentifierRange?: (ctx: IdentifierRangeContext) => Result; + /** + * Visit a parse tree produced by the `identifierNull` + * labeled alternative in `QueryLangParser.identifierComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitIdentifierNull?: (ctx: IdentifierNullContext) => Result; + /** + * Visit a parse tree produced by the `versionBasic` + * labeled alternative in `QueryLangParser.versionComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitVersionBasic?: (ctx: VersionBasicContext) => Result; + /** + * Visit a parse tree produced by the `versionListCmp` + * labeled alternative in `QueryLangParser.versionComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitVersionListCmp?: (ctx: VersionListCmpContext) => Result; + /** + * Visit a parse tree produced by the `versionRangeCmp` + * labeled alternative in `QueryLangParser.versionComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitVersionRangeCmp?: (ctx: VersionRangeCmpContext) => Result; + /** + * Visit a parse tree produced by the `versionNull` + * labeled alternative in `QueryLangParser.versionComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitVersionNull?: (ctx: VersionNullContext) => Result; + /** + * Visit a parse tree produced by the `cdDateBasic` + * labeled alternative in `QueryLangParser.creationDateComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCdDateBasic?: (ctx: CdDateBasicContext) => Result; + /** + * Visit a parse tree produced by the `cdDateTimeBasic` + * labeled alternative in `QueryLangParser.creationDateComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCdDateTimeBasic?: (ctx: CdDateTimeBasicContext) => Result; + /** + * Visit a parse tree produced by the `cdDateList` + * labeled alternative in `QueryLangParser.creationDateComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCdDateList?: (ctx: CdDateListContext) => Result; + /** + * Visit a parse tree produced by the `cdDateRange` + * labeled alternative in `QueryLangParser.creationDateComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCdDateRange?: (ctx: CdDateRangeContext) => Result; + /** + * Visit a parse tree produced by the `cdNull` + * labeled alternative in `QueryLangParser.creationDateComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCdNull?: (ctx: CdNullContext) => Result; + /** + * Visit a parse tree produced by the `processIdBasic` + * labeled alternative in `QueryLangParser.processIdComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessIdBasic?: (ctx: ProcessIdBasicContext) => Result; + /** + * Visit a parse tree produced by the `processIdList` + * labeled alternative in `QueryLangParser.processIdComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessIdList?: (ctx: ProcessIdListContext) => Result; + /** + * Visit a parse tree produced by the `processIdNull` + * labeled alternative in `QueryLangParser.processIdComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessIdNull?: (ctx: ProcessIdNullContext) => Result; + /** + * Visit a parse tree produced by the `processIdObjIdBasic` + * labeled alternative in `QueryLangParser.processIdObjIdComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessIdObjIdBasic?: (ctx: ProcessIdObjIdBasicContext) => Result; + /** + * Visit a parse tree produced by the `processIdObjIdList` + * labeled alternative in `QueryLangParser.processIdObjIdComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessIdObjIdList?: (ctx: ProcessIdObjIdListContext) => Result; + /** + * Visit a parse tree produced by the `processIdObjNull` + * labeled alternative in `QueryLangParser.processIdObjIdComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessIdObjNull?: (ctx: ProcessIdObjNullContext) => Result; + /** + * Visit a parse tree produced by the `processIdentifierBasic` + * labeled alternative in `QueryLangParser.processIdentifierComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessIdentifierBasic?: (ctx: ProcessIdentifierBasicContext) => Result; + /** + * Visit a parse tree produced by the `processIdentifierList` + * labeled alternative in `QueryLangParser.processIdentifierComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessIdentifierList?: (ctx: ProcessIdentifierListContext) => Result; + /** + * Visit a parse tree produced by the `processIdentifierRange` + * labeled alternative in `QueryLangParser.processIdentifierComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessIdentifierRange?: (ctx: ProcessIdentifierRangeContext) => Result; + /** + * Visit a parse tree produced by the `processIdentifierNull` + * labeled alternative in `QueryLangParser.processIdentifierComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProcessIdentifierNull?: (ctx: ProcessIdentifierNullContext) => Result; + /** + * Visit a parse tree produced by the `authorBasic` + * labeled alternative in `QueryLangParser.authorComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitAuthorBasic?: (ctx: AuthorBasicContext) => Result; + /** + * Visit a parse tree produced by the `authorList` + * labeled alternative in `QueryLangParser.authorComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitAuthorList?: (ctx: AuthorListContext) => Result; + /** + * Visit a parse tree produced by the `authorNull` + * labeled alternative in `QueryLangParser.authorComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitAuthorNull?: (ctx: AuthorNullContext) => Result; + /** + * Visit a parse tree produced by the `transitionIdBasic` + * labeled alternative in `QueryLangParser.transitionIdComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTransitionIdBasic?: (ctx: TransitionIdBasicContext) => Result; + /** + * Visit a parse tree produced by the `transitionIdList` + * labeled alternative in `QueryLangParser.transitionIdComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTransitionIdList?: (ctx: TransitionIdListContext) => Result; + /** + * Visit a parse tree produced by the `transitionIdRange` + * labeled alternative in `QueryLangParser.transitionIdComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTransitionIdRange?: (ctx: TransitionIdRangeContext) => Result; + /** + * Visit a parse tree produced by the `transitionIdNull` + * labeled alternative in `QueryLangParser.transitionIdComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTransitionIdNull?: (ctx: TransitionIdNullContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.stateComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitStateComparison?: (ctx: StateComparisonContext) => Result; + /** + * Visit a parse tree produced by the `userIdBasic` + * labeled alternative in `QueryLangParser.userIdComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitUserIdBasic?: (ctx: UserIdBasicContext) => Result; + /** + * Visit a parse tree produced by the `userIdList` + * labeled alternative in `QueryLangParser.userIdComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitUserIdList?: (ctx: UserIdListContext) => Result; + /** + * Visit a parse tree produced by the `userIdNull` + * labeled alternative in `QueryLangParser.userIdComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitUserIdNull?: (ctx: UserIdNullContext) => Result; + /** + * Visit a parse tree produced by the `caseIdBasic` + * labeled alternative in `QueryLangParser.caseIdComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCaseIdBasic?: (ctx: CaseIdBasicContext) => Result; + /** + * Visit a parse tree produced by the `caseIdList` + * labeled alternative in `QueryLangParser.caseIdComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCaseIdList?: (ctx: CaseIdListContext) => Result; + /** + * Visit a parse tree produced by the `caseIdNull` + * labeled alternative in `QueryLangParser.caseIdComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitCaseIdNull?: (ctx: CaseIdNullContext) => Result; + /** + * Visit a parse tree produced by the `laDateBasic` + * labeled alternative in `QueryLangParser.lastAssignComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitLaDateBasic?: (ctx: LaDateBasicContext) => Result; + /** + * Visit a parse tree produced by the `laDateTimeBasic` + * labeled alternative in `QueryLangParser.lastAssignComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitLaDateTimeBasic?: (ctx: LaDateTimeBasicContext) => Result; + /** + * Visit a parse tree produced by the `laDateList` + * labeled alternative in `QueryLangParser.lastAssignComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitLaDateList?: (ctx: LaDateListContext) => Result; + /** + * Visit a parse tree produced by the `laDateRange` + * labeled alternative in `QueryLangParser.lastAssignComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitLaDateRange?: (ctx: LaDateRangeContext) => Result; + /** + * Visit a parse tree produced by the `laNull` + * labeled alternative in `QueryLangParser.lastAssignComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitLaNull?: (ctx: LaNullContext) => Result; + /** + * Visit a parse tree produced by the `lfDateBasic` + * labeled alternative in `QueryLangParser.lastFinishComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitLfDateBasic?: (ctx: LfDateBasicContext) => Result; + /** + * Visit a parse tree produced by the `lfDateTimeBasic` + * labeled alternative in `QueryLangParser.lastFinishComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitLfDateTimeBasic?: (ctx: LfDateTimeBasicContext) => Result; + /** + * Visit a parse tree produced by the `lfDateList` + * labeled alternative in `QueryLangParser.lastFinishComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitLfDateList?: (ctx: LfDateListContext) => Result; + /** + * Visit a parse tree produced by the `lfDateRange` + * labeled alternative in `QueryLangParser.lastFinishComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitLfDateRange?: (ctx: LfDateRangeContext) => Result; + /** + * Visit a parse tree produced by the `lfNull` + * labeled alternative in `QueryLangParser.lastFinishComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitLfNull?: (ctx: LfNullContext) => Result; + /** + * Visit a parse tree produced by the `nameBasic` + * labeled alternative in `QueryLangParser.nameComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitNameBasic?: (ctx: NameBasicContext) => Result; + /** + * Visit a parse tree produced by the `nameList` + * labeled alternative in `QueryLangParser.nameComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitNameList?: (ctx: NameListContext) => Result; + /** + * Visit a parse tree produced by the `nameRange` + * labeled alternative in `QueryLangParser.nameComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitNameRange?: (ctx: NameRangeContext) => Result; + /** + * Visit a parse tree produced by the `nameNull` + * labeled alternative in `QueryLangParser.nameComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitNameNull?: (ctx: NameNullContext) => Result; + /** + * Visit a parse tree produced by the `surnameBasic` + * labeled alternative in `QueryLangParser.surnameComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitSurnameBasic?: (ctx: SurnameBasicContext) => Result; + /** + * Visit a parse tree produced by the `surnameList` + * labeled alternative in `QueryLangParser.surnameComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitSurnameList?: (ctx: SurnameListContext) => Result; + /** + * Visit a parse tree produced by the `surnameRange` + * labeled alternative in `QueryLangParser.surnameComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitSurnameRange?: (ctx: SurnameRangeContext) => Result; + /** + * Visit a parse tree produced by the `surnameNull` + * labeled alternative in `QueryLangParser.surnameComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitSurnameNull?: (ctx: SurnameNullContext) => Result; + /** + * Visit a parse tree produced by the `emailBasic` + * labeled alternative in `QueryLangParser.emailComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitEmailBasic?: (ctx: EmailBasicContext) => Result; + /** + * Visit a parse tree produced by the `emailList` + * labeled alternative in `QueryLangParser.emailComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitEmailList?: (ctx: EmailListContext) => Result; + /** + * Visit a parse tree produced by the `emailRange` + * labeled alternative in `QueryLangParser.emailComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitEmailRange?: (ctx: EmailRangeContext) => Result; + /** + * Visit a parse tree produced by the `emailNull` + * labeled alternative in `QueryLangParser.emailComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitEmailNull?: (ctx: EmailNullContext) => Result; + /** + * Visit a parse tree produced by the `dataString` + * labeled alternative in `QueryLangParser.dataValueComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDataString?: (ctx: DataStringContext) => Result; + /** + * Visit a parse tree produced by the `dataStringLike` + * labeled alternative in `QueryLangParser.dataValueComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDataStringLike?: (ctx: DataStringLikeContext) => Result; + /** + * Visit a parse tree produced by the `dataNumber` + * labeled alternative in `QueryLangParser.dataValueComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDataNumber?: (ctx: DataNumberContext) => Result; + /** + * Visit a parse tree produced by the `dataDate` + * labeled alternative in `QueryLangParser.dataValueComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDataDate?: (ctx: DataDateContext) => Result; + /** + * Visit a parse tree produced by the `dataDatetime` + * labeled alternative in `QueryLangParser.dataValueComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDataDatetime?: (ctx: DataDatetimeContext) => Result; + /** + * Visit a parse tree produced by the `dataBoolean` + * labeled alternative in `QueryLangParser.dataValueComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDataBoolean?: (ctx: DataBooleanContext) => Result; + /** + * Visit a parse tree produced by the `dataStringList` + * labeled alternative in `QueryLangParser.dataValueComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDataStringList?: (ctx: DataStringListContext) => Result; + /** + * Visit a parse tree produced by the `dataNumberList` + * labeled alternative in `QueryLangParser.dataValueComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDataNumberList?: (ctx: DataNumberListContext) => Result; + /** + * Visit a parse tree produced by the `dataDateList` + * labeled alternative in `QueryLangParser.dataValueComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDataDateList?: (ctx: DataDateListContext) => Result; + /** + * Visit a parse tree produced by the `dataStringRange` + * labeled alternative in `QueryLangParser.dataValueComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDataStringRange?: (ctx: DataStringRangeContext) => Result; + /** + * Visit a parse tree produced by the `dataNumberRange` + * labeled alternative in `QueryLangParser.dataValueComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDataNumberRange?: (ctx: DataNumberRangeContext) => Result; + /** + * Visit a parse tree produced by the `dataDateRange` + * labeled alternative in `QueryLangParser.dataValueComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDataDateRange?: (ctx: DataDateRangeContext) => Result; + /** + * Visit a parse tree produced by the `dataNull` + * labeled alternative in `QueryLangParser.dataValueComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDataNull?: (ctx: DataNullContext) => Result; + /** + * Visit a parse tree produced by the `dataOptionsBasic` + * labeled alternative in `QueryLangParser.dataOptionsComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDataOptionsBasic?: (ctx: DataOptionsBasicContext) => Result; + /** + * Visit a parse tree produced by the `dataOptionsList` + * labeled alternative in `QueryLangParser.dataOptionsComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDataOptionsList?: (ctx: DataOptionsListContext) => Result; + /** + * Visit a parse tree produced by the `dataOptionsRange` + * labeled alternative in `QueryLangParser.dataOptionsComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDataOptionsRange?: (ctx: DataOptionsRangeContext) => Result; + /** + * Visit a parse tree produced by the `dataOptionsNull` + * labeled alternative in `QueryLangParser.dataOptionsComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDataOptionsNull?: (ctx: DataOptionsNullContext) => Result; + /** + * Visit a parse tree produced by the `placesBasic` + * labeled alternative in `QueryLangParser.placesComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitPlacesBasic?: (ctx: PlacesBasicContext) => Result; + /** + * Visit a parse tree produced by the `placesList` + * labeled alternative in `QueryLangParser.placesComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitPlacesList?: (ctx: PlacesListContext) => Result; + /** + * Visit a parse tree produced by the `placesRange` + * labeled alternative in `QueryLangParser.placesComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitPlacesRange?: (ctx: PlacesRangeContext) => Result; + /** + * Visit a parse tree produced by the `placesNull` + * labeled alternative in `QueryLangParser.placesComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitPlacesNull?: (ctx: PlacesNullContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.tasksStateComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTasksStateComparison?: (ctx: TasksStateComparisonContext) => Result; + /** + * Visit a parse tree produced by the `tasksUserIdBasic` + * labeled alternative in `QueryLangParser.tasksUserIdComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTasksUserIdBasic?: (ctx: TasksUserIdBasicContext) => Result; + /** + * Visit a parse tree produced by the `tasksUserIdList` + * labeled alternative in `QueryLangParser.tasksUserIdComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTasksUserIdList?: (ctx: TasksUserIdListContext) => Result; + /** + * Visit a parse tree produced by the `tasksUserIdNull` + * labeled alternative in `QueryLangParser.tasksUserIdComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTasksUserIdNull?: (ctx: TasksUserIdNullContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.objectIdComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitObjectIdComparison?: (ctx: ObjectIdComparisonContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.stringComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitStringComparison?: (ctx: StringComparisonContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.stringLikeComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitStringLikeComparison?: (ctx: StringLikeComparisonContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.numberComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitNumberComparison?: (ctx: NumberComparisonContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.dateComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDateComparison?: (ctx: DateComparisonContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.dateTimeComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDateTimeComparison?: (ctx: DateTimeComparisonContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.booleanComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitBooleanComparison?: (ctx: BooleanComparisonContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.nullComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitNullComparison?: (ctx: NullComparisonContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.inListStringComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitInListStringComparison?: (ctx: InListStringComparisonContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.inListNumberComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitInListNumberComparison?: (ctx: InListNumberComparisonContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.inListDateComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitInListDateComparison?: (ctx: InListDateComparisonContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.inListVersionComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitInListVersionComparison?: (ctx: InListVersionComparisonContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.inRangeStringComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitInRangeStringComparison?: (ctx: InRangeStringComparisonContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.inRangeNumberComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitInRangeNumberComparison?: (ctx: InRangeNumberComparisonContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.inRangeDateComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitInRangeDateComparison?: (ctx: InRangeDateComparisonContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.inRangeVersionComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + visitInRangeVersionComparison?: (ctx: InRangeVersionComparisonContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.dataValue`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDataValue?: (ctx: DataValueContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.dataOptions`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDataOptions?: (ctx: DataOptionsContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.places`. + * @param ctx the parse tree + * @return the visitor result + */ + visitPlaces?: (ctx: PlacesContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.tasksState`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTasksState?: (ctx: TasksStateContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.tasksUserId`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTasksUserId?: (ctx: TasksUserIdContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.javaId`. + * @param ctx the parse tree + * @return the visitor result + */ + visitJavaId?: (ctx: JavaIdContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.stringList`. + * @param ctx the parse tree + * @return the visitor result + */ + visitStringList?: (ctx: StringListContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.intList`. + * @param ctx the parse tree + * @return the visitor result + */ + visitIntList?: (ctx: IntListContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.doubleList`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDoubleList?: (ctx: DoubleListContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.dateList`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDateList?: (ctx: DateListContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.dateTimeList`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDateTimeList?: (ctx: DateTimeListContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.versionList`. + * @param ctx the parse tree + * @return the visitor result + */ + visitVersionList?: (ctx: VersionListContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.stringRange`. + * @param ctx the parse tree + * @return the visitor result + */ + visitStringRange?: (ctx: StringRangeContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.intRange`. + * @param ctx the parse tree + * @return the visitor result + */ + visitIntRange?: (ctx: IntRangeContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.doubleRange`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDoubleRange?: (ctx: DoubleRangeContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.dateRange`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDateRange?: (ctx: DateRangeContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.dateTimeRange`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDateTimeRange?: (ctx: DateTimeRangeContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.versionRange`. + * @param ctx the parse tree + * @return the visitor result + */ + visitVersionRange?: (ctx: VersionRangeContext) => Result; + /** + * Visit a parse tree produced by `QueryLangParser.loggedUserStringAttribute`. + * @param ctx the parse tree + * @return the visitor result + */ + visitLoggedUserStringAttribute?: (ctx: LoggedUserStringAttributeContext) => Result; +} + From df2b364ffe30c5a2df2f85fd6eff6809044acd2b Mon Sep 17 00:00:00 2001 From: chvostek Date: Fri, 24 Jul 2026 11:19:09 +0200 Subject: [PATCH 10/55] [NAE-2466] Advanced search for PFQL - add parser models --- .../src/lib/pfql/model/complex-expression.ts | 42 +++++++++++++++++++ .../src/lib/pfql/model/logical-operator.ts | 24 +++++++++++ .../lib/pfql/model/query-item-interface.ts | 5 +++ .../src/lib/pfql/model/query-item-type.ts | 12 ++++++ .../src/lib/pfql/model/simple-expression.ts | 40 ++++++++++++++++++ 5 files changed, 123 insertions(+) create mode 100644 projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts create mode 100644 projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts create mode 100644 projects/netgrif-components-core/src/lib/pfql/model/query-item-interface.ts create mode 100644 projects/netgrif-components-core/src/lib/pfql/model/query-item-type.ts create mode 100644 projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts diff --git a/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts b/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts new file mode 100644 index 0000000000..7be128584b --- /dev/null +++ b/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts @@ -0,0 +1,42 @@ +import {LogicalOperator} from "./logical-operator"; +import {QueryItemInterface} from "./query-item-interface"; +import {QueryItem, QueryItemType} from "./query-item-type"; + +// todo 2466 +export class ComplexExpression implements QueryItemInterface { + protected _negated: boolean; + protected _items: QueryItem[]; + protected _logicalOperator: LogicalOperator; + + public constructor(negated: boolean, items: QueryItem[], logicalOperator: LogicalOperator) { + this._negated = negated; + this._items = !items ? [] : items; + this._logicalOperator = logicalOperator; + } + + public type(): QueryItemType { + return QueryItemType.COMPLEX_EXPRESSION; + } + + public pushItems(items: QueryItem[]) { + this._items.push(...items); + } + + public get items(): QueryItem[] { + return this._items; + } + + public get isNegated(): boolean { + return this._negated; + } + + public get logicalOperator(): LogicalOperator { + return this._logicalOperator; + } + + // todo 2466 + public pushDownNegation(): void { + // negate inner expressions + // set _negated to false + } +} diff --git a/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts b/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts new file mode 100644 index 0000000000..a5620c80ea --- /dev/null +++ b/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts @@ -0,0 +1,24 @@ +import {QueryItemType} from "./query-item-type"; +import {QueryItemInterface} from "./query-item-interface"; + +export enum LogicalOperatorEnum { + AND, + OR +} + +// todo 2466 +export class LogicalOperator implements QueryItemInterface { + protected _value: LogicalOperatorEnum + + public constructor(value: LogicalOperatorEnum) { + this._value = value; + } + + public type(): QueryItemType { + return QueryItemType.LOGICAL_OPERATOR; + } + + public get value(): LogicalOperatorEnum { + return this._value; + } +} diff --git a/projects/netgrif-components-core/src/lib/pfql/model/query-item-interface.ts b/projects/netgrif-components-core/src/lib/pfql/model/query-item-interface.ts new file mode 100644 index 0000000000..d3670b7e03 --- /dev/null +++ b/projects/netgrif-components-core/src/lib/pfql/model/query-item-interface.ts @@ -0,0 +1,5 @@ +import {QueryItemType} from "./query-item-type"; + +export interface QueryItemInterface { + type(): QueryItemType; +} diff --git a/projects/netgrif-components-core/src/lib/pfql/model/query-item-type.ts b/projects/netgrif-components-core/src/lib/pfql/model/query-item-type.ts new file mode 100644 index 0000000000..2033034c76 --- /dev/null +++ b/projects/netgrif-components-core/src/lib/pfql/model/query-item-type.ts @@ -0,0 +1,12 @@ +import {SimpleExpression} from "./simple-expression"; +import {ComplexExpression} from "./complex-expression"; +import { LogicalOperator } from "./logical-operator"; + +export enum QueryItemType { + SIMPLE_EXPRESSION, + COMPLEX_EXPRESSION, + LOGICAL_OPERATOR +} + +export type QueryItem = SimpleExpression | ComplexExpression | LogicalOperator; + diff --git a/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts b/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts new file mode 100644 index 0000000000..b70fbbffac --- /dev/null +++ b/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts @@ -0,0 +1,40 @@ +import {Category} from "../../search/models/category/category"; +import {Operator} from "../../search/models/operator/operator"; +import {QueryItemInterface} from "./query-item-interface"; +import { QueryItemType } from "./query-item-type"; + +// todo 2466 +export class SimpleExpression implements QueryItemInterface { + protected _category: Category + protected _operator: Operator + protected _operandValue: any; + + public constructor(category: Category, operator: Operator, operandValue: any) { + this._category = category; + this._operator = operator; + this._operandValue = operandValue; + } + + public type(): QueryItemType { + return QueryItemType.SIMPLE_EXPRESSION; + } + + public get category(): Category { + return this._category; + } + + public get operator(): Operator { + return this._operator; + } + + public get operandValue(): any { + return this._operandValue; + } + + // todo 2466 + public negate(): void { + // possible only if operator is: EQ, NEQ, GT, GTE, LT, LTE + // throw if operator is: Substring, IN RANGE + // throw if calculated operator is: NEQ null + } +} From b1bfb5499abacf8695ba059c62a140e5ae3ff2ff Mon Sep 17 00:00:00 2001 From: chvostek Date: Tue, 28 Jul 2026 16:24:13 +0200 Subject: [PATCH 11/55] [NAE-2466] Advanced search for PFQL - implement mechanism to parse string PFQL query into advanced search - add todos --- .../src/lib/pfql/model/complex-expression.ts | 13 +- .../src/lib/pfql/model/logical-operator.ts | 12 +- .../src/lib/pfql/model/simple-expression.ts | 19 +- .../src/lib/pfql/pfql-utils.ts | 76 +++++++ .../src/lib/pfql/pfql-visitor.ts | 187 ++++++++++++++++++ .../src/lib/pfql/public-api.ts | 10 + .../models/operator/equals-date-time.ts | 2 +- .../lib/search/models/operator/equals-date.ts | 2 +- .../src/lib/search/models/operator/equals.ts | 2 +- .../models/operator/in-range-date-time.ts | 2 +- .../search/models/operator/in-range-date.ts | 2 +- .../lib/search/models/operator/in-range.ts | 2 +- .../src/lib/search/models/operator/is-null.ts | 2 +- .../models/operator/less-than-date-time.ts | 2 +- .../search/models/operator/less-than-date.ts | 2 +- .../operator/less-than-equal-date-time.ts | 2 +- .../models/operator/less-than-equal-date.ts | 2 +- .../search/models/operator/less-than-equal.ts | 2 +- .../lib/search/models/operator/less-than.ts | 2 +- .../src/lib/search/models/operator/like.ts | 2 +- .../models/operator/more-than-date-time.ts | 2 +- .../search/models/operator/more-than-date.ts | 2 +- .../operator/more-than-equal-date-time.ts | 2 +- .../models/operator/more-than-equal-date.ts | 2 +- .../search/models/operator/more-than-equal.ts | 2 +- .../lib/search/models/operator/more-than.ts | 2 +- .../models/operator/not-equals-date-time.ts | 2 +- .../search/models/operator/not-equals-date.ts | 2 +- .../lib/search/models/operator/not-equals.ts | 2 +- .../lib/search/models/operator/operator.ts | 13 +- .../lib/search/models/operator/substring.ts | 2 +- .../search/search-service/search.service.ts | 73 ++++++- .../netgrif-components-core/src/public-api.ts | 3 +- 33 files changed, 407 insertions(+), 47 deletions(-) create mode 100644 projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts create mode 100644 projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts create mode 100644 projects/netgrif-components-core/src/lib/pfql/public-api.ts diff --git a/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts b/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts index 7be128584b..34e9f5285d 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts @@ -1,4 +1,3 @@ -import {LogicalOperator} from "./logical-operator"; import {QueryItemInterface} from "./query-item-interface"; import {QueryItem, QueryItemType} from "./query-item-type"; @@ -6,12 +5,10 @@ import {QueryItem, QueryItemType} from "./query-item-type"; export class ComplexExpression implements QueryItemInterface { protected _negated: boolean; protected _items: QueryItem[]; - protected _logicalOperator: LogicalOperator; - public constructor(negated: boolean, items: QueryItem[], logicalOperator: LogicalOperator) { + public constructor(negated: boolean, items: QueryItem[]) { this._negated = negated; this._items = !items ? [] : items; - this._logicalOperator = logicalOperator; } public type(): QueryItemType { @@ -26,12 +23,12 @@ export class ComplexExpression implements QueryItemInterface { return this._items; } - public get isNegated(): boolean { - return this._negated; + public set items(items: QueryItem[]) { + this._items = items; } - public get logicalOperator(): LogicalOperator { - return this._logicalOperator; + public get isNegated(): boolean { + return this._negated; } // todo 2466 diff --git a/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts b/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts index a5620c80ea..438c8076ca 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts @@ -1,16 +1,12 @@ import {QueryItemType} from "./query-item-type"; import {QueryItemInterface} from "./query-item-interface"; - -export enum LogicalOperatorEnum { - AND, - OR -} +import {BooleanOperator} from "../../search/models/boolean-operator"; // todo 2466 export class LogicalOperator implements QueryItemInterface { - protected _value: LogicalOperatorEnum + protected _value: BooleanOperator - public constructor(value: LogicalOperatorEnum) { + public constructor(value: BooleanOperator) { this._value = value; } @@ -18,7 +14,7 @@ export class LogicalOperator implements QueryItemInterface { return QueryItemType.LOGICAL_OPERATOR; } - public get value(): LogicalOperatorEnum { + public get value(): BooleanOperator { return this._value; } } diff --git a/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts b/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts index b70fbbffac..f047fbad65 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts @@ -8,11 +8,13 @@ export class SimpleExpression implements QueryItemInterface { protected _category: Category protected _operator: Operator protected _operandValue: any; + protected _negated: boolean; - public constructor(category: Category, operator: Operator, operandValue: any) { - this._category = category; + public constructor(operator: Operator, operandValue: any, negated: boolean, category?: Category) { this._operator = operator; this._operandValue = operandValue; + this._negated = negated; + this._category = category; } public type(): QueryItemType { @@ -23,6 +25,10 @@ export class SimpleExpression implements QueryItemInterface { return this._category; } + public set category(cat: Category) { + this._category = cat; + } + public get operator(): Operator { return this._operator; } @@ -31,8 +37,17 @@ export class SimpleExpression implements QueryItemInterface { return this._operandValue; } + public get negated(): boolean { + return this._negated; + } + // todo 2466 public negate(): void { + if (!!this._negated) { + this._negated = false; + return; + } + // todo 2466 // possible only if operator is: EQ, NEQ, GT, GTE, LT, LTE // throw if operator is: Substring, IN RANGE // throw if calculated operator is: NEQ null diff --git a/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts b/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts new file mode 100644 index 0000000000..2e186687f0 --- /dev/null +++ b/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts @@ -0,0 +1,76 @@ +import {CharStream, CommonTokenStream, Token} from "antlr4ng"; +import { QueryLangLexer } from "./generated/QueryLangLexer"; +import {QueryLangParser} from "./generated/QueryLangParser"; +import {PfqlVisitor} from "./pfql-visitor"; +import {Injector} from "@angular/core"; +import {QueryItem, QueryItemType} from "./model/query-item-type"; +import {Operator} from "../search/models/operator/operator"; +import {Equals} from "../search/models/operator/equals"; +import {Substring} from "../search/models/operator/substring"; +import {LessThan} from "../search/models/operator/less-than"; +import {LessThanEqual} from "../search/models/operator/less-than-equal"; +import {MoreThan} from "../search/models/operator/more-than"; +import {MoreThanEqual} from "../search/models/operator/more-than-equal"; +import {NotEquals} from "../search/models/operator/not-equals"; +import {ComplexExpression} from "./model/complex-expression"; + +// todo 2466 +export function parseQuery(query: string, injector: Injector): Array { + // todo 2466 injector as parameter? + // todo 2466 logging (also catch error) + const inputStream = CharStream.fromString(query); + const lexer = new QueryLangLexer(inputStream); + const tokenStream = new CommonTokenStream(lexer); + const parser = new QueryLangParser(tokenStream); + const tree = parser.query(); + const visitor = new PfqlVisitor(injector); + let items: Array = visitor.visit(tree); + // todo 2466 push down negations (also in sub-expressions) + return reduceComplexToSimpleExpressions(items); +} + +// todo 2466 +export function getOperatorFromToken(operatorToken: Token | null): Operator | undefined { + if (operatorToken === null) { + return undefined; + } + switch (operatorToken.type) { + case QueryLangParser.EQ: + return new Equals(); + case QueryLangParser.NEQ: + return new NotEquals(); + case QueryLangParser.CONTAINS: + return new Substring(); + case QueryLangParser.LT: + return new LessThan(); + case QueryLangParser.LTE: + return new LessThanEqual(); + case QueryLangParser.GT: + return new MoreThan(); + case QueryLangParser.GTE: + return new MoreThanEqual(); + default: + return undefined; + } +} + +function reduceComplexToSimpleExpressions(items: Array): Array { + return items?.map(queryItem => { + if (queryItem.type() === QueryItemType.COMPLEX_EXPRESSION) { + const complexExpr: ComplexExpression = queryItem as ComplexExpression; + if (canBeReducedToSimpleExpr(complexExpr)) { + return complexExpr.items[0]; + } + complexExpr.items = reduceComplexToSimpleExpressions(complexExpr.items); + } + return queryItem; + }); +} + +function canBeReducedToSimpleExpr(complexExpr: ComplexExpression): boolean { + return !!complexExpr.items && complexExpr.items.length === 1 && complexExpr.items[0]?.type() === QueryItemType.SIMPLE_EXPRESSION; +} + +// todo 2466 date operators + +// todo 2466 date-time operators diff --git a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts new file mode 100644 index 0000000000..871dcb50ac --- /dev/null +++ b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts @@ -0,0 +1,187 @@ +import {QueryLangVisitor} from "./generated/QueryLangVisitor"; +import { + CaseAndExpressionContext, + CaseComparisonsContext, + CaseConditionGroupParenthesisContext, CaseConditionsAndPagingContext, + CaseOrExpressionContext, CaseQueryContext, + StringComparisonContext, + StringLikeComparisonContext, TaskConditionsAndPagingContext, TaskQueryContext, + TitleBasicContext, + TitleLikeContext, + TitleListContext, + TitleNullContext, + TitleRangeContext +} from "./generated/QueryLangParser"; +import {LoggerService} from "../logger/services/logger.service"; +import {CaseTitle} from "../search/models/category/case/case-title"; +import {Injector} from "@angular/core"; +import {OperatorService} from "../search/operator-service/operator.service"; +import {QueryItem} from "./model/query-item-type"; +import {LogicalOperator} from "./model/logical-operator"; +import {ComplexExpression} from "./model/complex-expression"; +import {SimpleExpression} from "./model/simple-expression"; +import {getOperatorFromToken} from "./pfql-utils"; +import {Like} from "../search/models/operator/like"; +import {Operator} from "../search/models/operator/operator"; +import {BooleanOperator} from "../search/models/boolean-operator"; + + +// todo 2466 doc +export class PfqlVisitor extends QueryLangVisitor> { + protected _logger: LoggerService; + protected _operatorService: OperatorService + + public constructor(injector: Injector) { + super(); + this._logger = injector.get(LoggerService); + this._operatorService = injector.get(OperatorService); + } + + // todo 2466 doc + override visitCaseQuery = (ctx: CaseQueryContext): Array => { + const conditionsAndPaging = ctx.caseConditionsAndPaging(); + if (!conditionsAndPaging) { + return []; + } + return this.visit(conditionsAndPaging); + }; + + // todo 2466 doc + override visitCaseConditionsAndPaging = (ctx: CaseConditionsAndPagingContext): Array => { + const conditions = ctx.caseConditions(); + if (!conditions) { + return []; + } + return this.visit(conditions); + }; + + // todo 2466 doc + override visitTaskQuery = (ctx: TaskQueryContext): Array => { + const conditionsAndPaging = ctx.taskConditionsAndPaging(); + if (!conditionsAndPaging) { + return []; + } + return this.visit(conditionsAndPaging); + }; + + // todo 2466 doc + override visitTaskConditionsAndPaging = (ctx: TaskConditionsAndPagingContext): Array => { + const conditions = ctx.taskConditions(); + if (!conditions) { + return []; + } + return this.visit(conditions); + }; + + // todo 2466 doc + override visitCaseOrExpression = (ctx: CaseOrExpressionContext): Array => { + const andExpressionContexts = ctx.caseAndExpression(); + const items: Array = [...this.visit(andExpressionContexts[0])]; + for (let i = 1; i < andExpressionContexts.length; i++) { + items.push(new LogicalOperator(BooleanOperator.OR)); + items.push(...this.visit(andExpressionContexts[i])); + } + return items; + }; + + // todo 2466 doc + override visitCaseAndExpression = (ctx: CaseAndExpressionContext): Array => { + const conditionGroupContexts = ctx.caseConditionGroup(); + const items: Array = [...this.visit(conditionGroupContexts[0])]; + for (let i = 1; i < conditionGroupContexts.length; i++) { + items.push(new LogicalOperator(BooleanOperator.AND)); + items.push(...this.visit(conditionGroupContexts[i])); + } + return items; + }; + + // todo 2466 doc + override visitCaseConditionGroupParenthesis = (ctx: CaseConditionGroupParenthesisContext): Array => { + const innerItems: Array = [...this.visit(ctx.caseConditions())]; + const isNegated: boolean = !!ctx.NOT(); + return [new ComplexExpression(isNegated, innerItems)]; + }; + + /** + * Visit a parse tree produced by the `titleBasic` + * labeled alternative in `QueryLangParser.titleComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + override visitTitleBasic = (ctx: TitleBasicContext): Array => { + if (ctx.parent instanceof CaseComparisonsContext) { + const expr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); + expr.category = new CaseTitle(this._operatorService, this._logger); + return [expr]; + } else { + this._logger.warn("There is no dedicated category when visiting title while parsing PFQL query"); + return [] + } + }; + + /** + * Visit a parse tree produced by the `titleLike` + * labeled alternative in `QueryLangParser.titleComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + override visitTitleLike = (ctx: TitleLikeContext): Array => { + if (ctx.parent instanceof CaseComparisonsContext) { + const expr: SimpleExpression = this.handleStringLikeComparisonContext(ctx.stringLikeComparison()); + expr.category = new CaseTitle(this._operatorService, this._logger); + return [expr]; + } else { + this._logger.warn("There is no dedicated category when visiting title while parsing PFQL query"); + return []; + } + }; + + /** + * Visit a parse tree produced by the `titleList` + * labeled alternative in `QueryLangParser.titleComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + override visitTitleList = (ctx: TitleListContext): Array => { + this._logger.warn("There is no in list operator for title"); + return []; + }; + + /** + * Visit a parse tree produced by the `titleRange` + * labeled alternative in `QueryLangParser.titleComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + override visitTitleRange = (ctx: TitleRangeContext): Array => { + this._logger.warn("There is no in range operator for title"); + return []; + }; + + /** + * Visit a parse tree produced by the `titleNull` + * labeled alternative in `QueryLangParser.titleComparison`. + * @param ctx the parse tree + * @return the visitor result + */ + override visitTitleNull = (ctx: TitleNullContext): Array => { + this._logger.warn("There is no null/empty operator for title"); + return []; + }; + + // todo 2466 more visit methods + + protected handleStringComparisonContext(ctx: StringComparisonContext): SimpleExpression { + const operator: Operator = getOperatorFromToken(ctx._op); + const value: string = ctx.STRING()?.getText(); + return new SimpleExpression(operator, value, !!ctx.NOT()); + } + + protected handleStringLikeComparisonContext(ctx: StringLikeComparisonContext): SimpleExpression { + const operator: Operator = new Like(); + const value: string = ctx.stringComparison().STRING().getText(); + return new SimpleExpression(operator, value, !!ctx.stringComparison().NOT()); + } + + // todo 2466 more handle methods +} diff --git a/projects/netgrif-components-core/src/lib/pfql/public-api.ts b/projects/netgrif-components-core/src/lib/pfql/public-api.ts new file mode 100644 index 0000000000..a372963aeb --- /dev/null +++ b/projects/netgrif-components-core/src/lib/pfql/public-api.ts @@ -0,0 +1,10 @@ +export * from './generated/QueryLangVisitor'; +export * from './generated/QueryLangParser'; +export * from './generated/QueryLangLexer'; +export * from './model/complex-expression'; +export * from './model/logical-operator'; +export * from './model/simple-expression'; +export * from './model/query-item-type'; +export * from './model/query-item-interface'; +export * from './pfql-visitor'; +export * from './pfql-utils'; diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/equals-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/equals-date-time.ts index 7160273bed..a94432d7de 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/equals-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/equals-date-time.ts @@ -16,7 +16,7 @@ export class EqualsDateTime extends Operator { protected dateTimeRange: InRangeDateTime; constructor(operators: OperatorService) { - super(1); + super(1, Operators.EQUALS_DATE_TIME); this.dateTimeRange = operators.getOperator(InRangeDateTime) as InRangeDateTime; } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/equals-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/equals-date.ts index bd28764e37..f3a3c7ffa1 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/equals-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/equals-date.ts @@ -16,7 +16,7 @@ export class EqualsDate extends Operator { protected dateRange: InRangeDate; constructor(operators: OperatorService) { - super(1); + super(1, Operators.EQUALS_DATE); this.dateRange = operators.getOperator(InRangeDate) as InRangeDate; } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/equals.ts b/projects/netgrif-components-core/src/lib/search/models/operator/equals.ts index a1b646a58a..5c969ad0af 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/equals.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/equals.ts @@ -10,7 +10,7 @@ import {Operators} from './operators'; export class Equals extends Operator { constructor() { // query string queries don't use a special symbol for strict equality - super(1, 'eq'); + super(1, Operators.EQUALS, 'eq'); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date-time.ts index 2f689442b8..17ba88c6fc 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date-time.ts @@ -11,7 +11,7 @@ import {Operators} from './operators'; */ export class InRangeDateTime extends Operator { constructor() { - super(2); + super(2, Operators.IN_RANGE_DATE_TIME); } /** diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date.ts index d635cef42b..ac5b6e0d88 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date.ts @@ -12,7 +12,7 @@ import {Operators} from './operators'; */ export class InRangeDate extends Operator { constructor() { - super(2); + super(2, Operators.IN_RANGE_DATE); } /** diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/in-range.ts b/projects/netgrif-components-core/src/lib/search/models/operator/in-range.ts index 746acc475c..182f015508 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/in-range.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/in-range.ts @@ -7,7 +7,7 @@ import {Operators} from './operators'; */ export class InRange extends Operator { constructor() { - super(2); + super(2, Operators.IN_RANGE); } createQuery(pfqlKeywords: Array, args: Array): Query { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/is-null.ts b/projects/netgrif-components-core/src/lib/search/models/operator/is-null.ts index e3ebb07a9b..741fa706f9 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/is-null.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/is-null.ts @@ -12,7 +12,7 @@ import {BooleanOperator} from "../boolean-operator"; export class IsNull extends Operator { constructor() { - super(0); + super(0, Operators.IS_NULL); } /** diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date-time.ts index e31f4f0b2e..e9c7841aa4 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date-time.ts @@ -13,7 +13,7 @@ export class LessThanDateTime extends Operator { protected lessThan: LessThan; constructor(operators: OperatorService) { - super(1); + super(1, Operators.LESS_THAN_DATE_TIME); this.lessThan = operators.getOperator(LessThan) as LessThan; } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date.ts index 51b067c286..b646133b7c 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date.ts @@ -13,7 +13,7 @@ export class LessThanDate extends Operator { protected lessThan: LessThan; constructor(operators: OperatorService) { - super(1); + super(1, Operators.LESS_THAN_DATE); this.lessThan = operators.getOperator(LessThan) as LessThan; } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date-time.ts index 0e87b98c67..51bbf51c0a 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date-time.ts @@ -13,7 +13,7 @@ export class LessThanEqualDateTime extends Operator { protected lessThanEqual: LessThanEqual; constructor(operators: OperatorService) { - super(1); + super(1, Operators.LESS_THAN_EQUAL_DATE_TIME); this.lessThanEqual = operators.getOperator(LessThanEqual) as LessThanEqual; } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date.ts index d9d1f7f122..6b4a4fa4aa 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date.ts @@ -13,7 +13,7 @@ export class LessThanEqualDate extends Operator { protected lessThan: LessThanDate; constructor(operators: OperatorService) { - super(1); + super(1, Operators.LESS_THAN_EQUAL_DATE); this.lessThan = operators.getOperator(LessThanDate) as LessThanDate; } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal.ts index da9d13246f..eb22166f23 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal.ts @@ -7,7 +7,7 @@ import {Operators} from './operators'; export class LessThanEqual extends Operator { constructor() { - super(1, 'lte'); + super(1, Operators.LESS_THAN_EQUAL, 'lte'); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than.ts index 6f9fef774d..3c07dfaeec 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than.ts @@ -6,7 +6,7 @@ import {Operators} from './operators'; */ export class LessThan extends Operator { constructor() { - super(1, 'lt'); + super(1, Operators.LESS_THAN, 'lt'); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/like.ts b/projects/netgrif-components-core/src/lib/search/models/operator/like.ts index 1f1eab7cec..c848d00b3c 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/like.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/like.ts @@ -11,7 +11,7 @@ import {Operators} from './operators'; */ export class Like extends Operator { constructor() { - super(1); + super(1, Operators.LIKE); } createQuery(pfqlKeywords: Array, args: Array): Query { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date-time.ts index 38f60939fb..4e1870c7bb 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date-time.ts @@ -13,7 +13,7 @@ export class MoreThanDateTime extends Operator { protected moreThan: MoreThan; constructor(operators: OperatorService) { - super(1); + super(1, Operators.MORE_THAN_DATE_TIME); this.moreThan = operators.getOperator(MoreThan) as MoreThan; } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date.ts index 929c89517d..bb7c47b5f3 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date.ts @@ -13,7 +13,7 @@ export class MoreThanDate extends Operator { protected moreThan: MoreThan; constructor(operators: OperatorService) { - super(1); + super(1, Operators.MORE_THAN_DATE); this.moreThan = operators.getOperator(MoreThan) as MoreThan; } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date-time.ts index 5800c861a7..f7ad79b54a 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date-time.ts @@ -13,7 +13,7 @@ export class MoreThanEqualDateTime extends Operator { protected moreThanEqual: MoreThanEqual; constructor(operators: OperatorService) { - super(1); + super(1, Operators.MORE_THAN_EQUAL_DATE_TIME); this.moreThanEqual = operators.getOperator(MoreThanEqual) as MoreThanEqual; } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date.ts index 57d4743447..71a73ec0fc 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date.ts @@ -13,7 +13,7 @@ export class MoreThanEqualDate extends Operator { protected moreThanEqual: MoreThanEqual; constructor(operators: OperatorService) { - super(1); + super(1, Operators.MORE_THAN_EQUAL_DATE); this.moreThanEqual = operators.getOperator(MoreThanEqual) as MoreThanEqual; } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal.ts index dd00a26530..d2503e1f0a 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal.ts @@ -7,7 +7,7 @@ import {Operators} from './operators'; export class MoreThanEqual extends Operator { constructor() { - super(1, 'gte'); + super(1, Operators.MORE_THAN_EQUAL, 'gte'); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than.ts index a8a99ec469..34de7437aa 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than.ts @@ -6,7 +6,7 @@ import {Operators} from './operators'; */ export class MoreThan extends Operator { constructor() { - super(1, 'gt'); + super(1, Operators.MORE_THAN, 'gt'); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date-time.ts index 8b99698289..bd88a1658f 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date-time.ts @@ -10,7 +10,7 @@ export class NotEqualsDateTime extends Operator { protected equals: EqualsDateTime; constructor(operators: OperatorService) { - super(1); + super(1, Operators.NOT_EQUALS_DATE_TIME); this.equals = operators.getOperator(EqualsDateTime) as EqualsDateTime; } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date.ts index 2325158492..bcde5e8bec 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date.ts @@ -13,7 +13,7 @@ export class NotEqualsDate extends Operator { protected equals: EqualsDate; constructor(operators: OperatorService) { - super(1); + super(1, Operators.NOT_EQUALS_DATE); this.equals = operators.getOperator(EqualsDate) as EqualsDate; } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals.ts b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals.ts index 6fa3813b7b..100b41f5a7 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals.ts @@ -9,7 +9,7 @@ import {Operators} from './operators'; */ export class NotEquals extends Operator { constructor() { - super(1, 'neq'); + super(1, Operators.NOT_EQUALS, 'neq'); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts b/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts index 64d5934c98..30a196e67a 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts @@ -42,11 +42,19 @@ export abstract class Operator { */ private readonly _operatorSymbols: string; - protected constructor(numberOfOperands: number, operatorSymbols = '') { + // todo 2466 + private readonly _type: Operators; + + protected constructor(numberOfOperands: number, type: Operators, operatorSymbols = '') { this._numberOfOperands = numberOfOperands; + this._type = type; this._operatorSymbols = operatorSymbols; } + public get type(): Operators { + return this._type; + } + /** * Escapes all escapable Elasticsearch symbols. Removes all unescapable Elasticsearch symbols. * @@ -104,7 +112,8 @@ export abstract class Operator { * @param canWrap is set to true if the wrapping is allowed */ public static wrapInputWithQuotes(input: string, canWrap: boolean = true): WrapResult { - if (typeof input === 'string' && canWrap && input !== UserAutocomplete.USER_ME_TEMPLATE) + if (typeof input === 'string' && canWrap && input !== UserAutocomplete.USER_ME_TEMPLATE + && !(input.startsWith(`'`) && input.endsWith(`'`))) return {value: `'${input}'`, wasWrapped: true}; else return {value: input, wasWrapped: false}; diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/substring.ts b/projects/netgrif-components-core/src/lib/search/models/operator/substring.ts index 3c7425865e..b30d22a8fa 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/substring.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/substring.ts @@ -7,7 +7,7 @@ import {Operators} from './operators'; */ export class Substring extends Operator { constructor() { - super(1, 'contains'); + super(1, Operators.SUBSTRING, 'contains'); } getOperatorNameTemplate(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts index 8ad37061cb..51c8e9757f 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts @@ -1,4 +1,4 @@ -import {Inject, Injectable, OnDestroy, Optional} from '@angular/core'; +import {Inject, Injectable, Injector, OnDestroy, Optional} from '@angular/core'; import {BooleanOperator} from '../models/boolean-operator'; import {Filter} from '../../filter/models/filter'; import {BehaviorSubject, forkJoin, Observable, Subject, Subscription} from 'rxjs'; @@ -19,6 +19,11 @@ import {FilterType} from '../../filter/models/filter-type'; import {LoadingEmitter} from '../../utility/loading-emitter'; import {FilterMetadata} from '../models/persistance/filter-metadata'; import {FilterTextSegment} from '../models/persistance/filter-text-segment'; +import {QueryItem, QueryItemType} from "../../pfql/model/query-item-type"; +import {parseQuery} from "../../pfql/pfql-utils"; +import {LogicalOperator} from "../../pfql/model/logical-operator"; +import {SimpleExpression} from "../../pfql/model/simple-expression"; +import {ComplexExpression} from "../../pfql/model/complex-expression"; /** * Holds information about the filter that is currently applied to the view component, that provides this services. @@ -60,10 +65,12 @@ export class SearchService implements OnDestroy { * It is required if we want to load predicate filter from saved metadata * @param baseFilter Filter that should be applied to the view when no searching is being performed. * Injected trough the {@link NAE_BASE_FILTER} injection token. + * @param _injector injector from angular core */ constructor(protected _log: LoggerService, @Optional() protected _categoryFactory: CategoryFactory, - @Inject(NAE_BASE_FILTER) baseFilter: BaseFilter) { + @Inject(NAE_BASE_FILTER) baseFilter: BaseFilter, + protected _injector: Injector) { if (baseFilter.filter instanceof Filter) { this._baseFilter = baseFilter.filter.clone(); } else if (baseFilter.filter instanceof Observable) { @@ -370,10 +377,72 @@ export class SearchService implements OnDestroy { }); } + // todo 2466 + public loadFromPfql(query: string) { + // todo 2466 validate query prefix with filter type + + this.clearPredicates(true); + const queryItems: Array = parseQuery(query, this._injector); + if (!queryItems) { + this._log.warn(`Could not parse query '${query}. Clearing the search...`) + return; + } + + // todo 2466 na jednej urovni moze byt len jeden typ operatora + + this.loadExpressionsIntoPredicate(this._rootPredicate, BooleanOperator.AND, queryItems); + this.updateActiveFilter(); + } + /** * @returns an Array of filter text segments that correspond to the currently displayed completed predicates */ public createFilterTextSegments(): Array { return this._rootPredicate.createFilterTextSegments(); } + + protected loadExpressionsIntoPredicate(predicate: EditableClausePredicateWithGenerators, operatorOfPredicate: BooleanOperator, + items: Array) { + const expressions: Array = items.filter(item => item.type() !== QueryItemType.LOGICAL_OPERATOR); + for (const expression of expressions) { + if (expression.type() === QueryItemType.SIMPLE_EXPRESSION) { + if (operatorOfPredicate.valueOf() === BooleanOperator.AND.valueOf()) { + const branchId = predicate.addNewClausePredicate(BooleanOperator.OR); + const localPredicate = predicate.getPredicateMap().get(branchId).getWrappedPredicate() as unknown as EditableClausePredicateWithGenerators; + this.loadSimpleExpressionIntoPredicate(localPredicate, expression as SimpleExpression); + } else { + this.loadSimpleExpressionIntoPredicate(predicate, expression as SimpleExpression); + } + } else if (expression.type() === QueryItemType.COMPLEX_EXPRESSION) { + this.loadFromQueryItemsIntoNewPredicate(predicate, (expression as ComplexExpression).items); + } else { + // todo 2466 warn ignoring + } + } + } + + protected loadFromQueryItemsIntoNewPredicate(parentPredicate: EditableClausePredicateWithGenerators, items: Array) { + const booleanOperator: BooleanOperator = this.determineBooleanOperator(items); + const branchId = parentPredicate.addNewClausePredicate(booleanOperator); + const branchPredicate = parentPredicate.getPredicateMap().get(branchId).getWrappedPredicate() as unknown as EditableClausePredicateWithGenerators + this.loadExpressionsIntoPredicate(branchPredicate, booleanOperator, items); + } + + protected determineBooleanOperator(items: Array): BooleanOperator { + const booleanOperators = items.filter(item => item.type() === QueryItemType.LOGICAL_OPERATOR); + return booleanOperators.length === 0 ? BooleanOperator.AND : (booleanOperators[0] as LogicalOperator).value; + } + + protected loadSimpleExpressionIntoPredicate(predicate: EditableClausePredicateWithGenerators, simpleExpr: SimpleExpression) { + const category: Category = simpleExpr.category; + const operatorIdx: number = category.allowedOperators.findIndex(op => op.type === simpleExpr.operator.type); + if (operatorIdx === -1) { + // todo 2466 handle error + this._log.error(`Operator '${simpleExpr.operator.type}' is unavailable for this category`); + return; + } + category.selectOperator(operatorIdx); + category.setOperands([simpleExpr.operandValue]); + predicate.addNewPredicateFromGenerator(category); + } } diff --git a/projects/netgrif-components-core/src/public-api.ts b/projects/netgrif-components-core/src/public-api.ts index a817bbb5a3..5b29bd9d0a 100644 --- a/projects/netgrif-components-core/src/public-api.ts +++ b/projects/netgrif-components-core/src/public-api.ts @@ -48,4 +48,5 @@ export * from './lib/impersonation/public-api'; export * from './lib/registry/public-api'; export * from './lib/actions/public-api'; export * from './lib/providers/public-api'; -export * from './lib/export/public-api' +export * from './lib/export/public-api'; +export * from './lib/pfql/public-api'; From 7cf142e3465e0cbfe445a1eb3336729859e21f04 Mon Sep 17 00:00:00 2001 From: chvostek Date: Thu, 30 Jul 2026 10:14:55 +0200 Subject: [PATCH 12/55] [NAE-2466] Advanced search for PFQL - update parser: implement handling for more case categories --- .../src/lib/pfql/pfql-utils.ts | 59 +++++ .../src/lib/pfql/pfql-visitor.ts | 238 ++++++++++++++---- .../models/category/case/case-process.ts | 25 +- .../lib/search/models/category/category.ts | 28 ++- .../net-attribute-autocomplete-category.ts | 8 +- ...onfiguration-user-autocomplete-category.ts | 27 +- .../models/category/task/task-process.ts | 8 +- .../models/category/user-autocomplete.ts | 7 + .../search/search-service/search.service.ts | 35 +-- 9 files changed, 367 insertions(+), 68 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts b/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts index 2e186687f0..fdce657fec 100644 --- a/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts +++ b/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts @@ -13,6 +13,19 @@ import {MoreThan} from "../search/models/operator/more-than"; import {MoreThanEqual} from "../search/models/operator/more-than-equal"; import {NotEquals} from "../search/models/operator/not-equals"; import {ComplexExpression} from "./model/complex-expression"; +import {EqualsDate} from "../search/models/operator/equals-date"; +import {NotEqualsDate} from "../search/models/operator/not-equals-date"; +import {LessThanDate} from "../search/models/operator/less-than-date"; +import {LessThanEqualDate} from "../search/models/operator/less-than-equal-date"; +import {MoreThanEqualDate} from "../search/models/operator/more-than-equal-date"; +import {MoreThanDate} from "../search/models/operator/more-than-date"; +import {OperatorService} from "../search/operator-service/operator.service"; +import {EqualsDateTime} from "../search/models/operator/equals-date-time"; +import {NotEqualsDateTime} from "../search/models/operator/not-equals-date-time"; +import {MoreThanDateTime} from "../search/models/operator/more-than-date-time"; +import {MoreThanEqualDateTime} from "../search/models/operator/more-than-equal-date-time"; +import {LessThanDateTime} from "../search/models/operator/less-than-date-time"; +import {LessThanEqualDateTime} from "../search/models/operator/less-than-equal-date-time"; // todo 2466 export function parseQuery(query: string, injector: Injector): Array { @@ -54,6 +67,52 @@ export function getOperatorFromToken(operatorToken: Token | null): Operator } } +// todo 2466 +export function getDateOperatorFromToken(operatorToken: Token | null, operatorService: OperatorService): Operator | undefined { + if (operatorToken === null) { + return undefined; + } + switch (operatorToken.type) { + case QueryLangParser.EQ: + return new EqualsDate(operatorService); + case QueryLangParser.NEQ: + return new NotEqualsDate(operatorService); + case QueryLangParser.LT: + return new LessThanDate(operatorService); + case QueryLangParser.LTE: + return new LessThanEqualDate(operatorService); + case QueryLangParser.GT: + return new MoreThanDate(operatorService); + case QueryLangParser.GTE: + return new MoreThanEqualDate(operatorService); + default: + return undefined; + } +} + +// todo 2466 +export function getDateTimeOperatorFromToken(operatorToken: Token | null, operatorService: OperatorService): Operator | undefined { + if (operatorToken === null) { + return undefined; + } + switch (operatorToken.type) { + case QueryLangParser.EQ: + return new EqualsDateTime(operatorService); + case QueryLangParser.NEQ: + return new NotEqualsDateTime(operatorService); + case QueryLangParser.LT: + return new LessThanDateTime(operatorService); + case QueryLangParser.LTE: + return new LessThanEqualDateTime(operatorService); + case QueryLangParser.GT: + return new MoreThanDateTime(operatorService); + case QueryLangParser.GTE: + return new MoreThanEqualDateTime(operatorService); + default: + return undefined; + } +} + function reduceComplexToSimpleExpressions(items: Array): Array { return items?.map(queryItem => { if (queryItem.type() === QueryItemType.COMPLEX_EXPRESSION) { diff --git a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts index 871dcb50ac..cfb3557f8e 100644 --- a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts +++ b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts @@ -1,16 +1,37 @@ import {QueryLangVisitor} from "./generated/QueryLangVisitor"; import { + AuthorBasicContext, CaseAndExpressionContext, CaseComparisonsContext, - CaseConditionGroupParenthesisContext, CaseConditionsAndPagingContext, - CaseOrExpressionContext, CaseQueryContext, + CaseConditionGroupParenthesisContext, + CaseConditionsAndPagingContext, + CaseOrExpressionContext, + CaseQueryContext, + CdDateBasicContext, + CdDateRangeContext, + CdDateTimeBasicContext, + DataBooleanContext, + DataDateContext, + DataDateRangeContext, + DataDatetimeContext, + DataNullContext, + DataNumberContext, + DataNumberRangeContext, + DataStringContext, + DataStringLikeContext, + DateComparisonContext, + DateRangeContext, + DateTimeComparisonContext, + DateTimeRangeContext, + IdBasicContext, + ObjectIdComparisonContext, + ProcessIdentifierBasicContext, StringComparisonContext, - StringLikeComparisonContext, TaskConditionsAndPagingContext, TaskQueryContext, + StringLikeComparisonContext, + TaskConditionsAndPagingContext, + TaskQueryContext, TitleBasicContext, TitleLikeContext, - TitleListContext, - TitleNullContext, - TitleRangeContext } from "./generated/QueryLangParser"; import {LoggerService} from "../logger/services/logger.service"; import {CaseTitle} from "../search/models/category/case/case-title"; @@ -20,21 +41,47 @@ import {QueryItem} from "./model/query-item-type"; import {LogicalOperator} from "./model/logical-operator"; import {ComplexExpression} from "./model/complex-expression"; import {SimpleExpression} from "./model/simple-expression"; -import {getOperatorFromToken} from "./pfql-utils"; +import {getDateOperatorFromToken, getDateTimeOperatorFromToken, getOperatorFromToken} from "./pfql-utils"; import {Like} from "../search/models/operator/like"; import {Operator} from "../search/models/operator/operator"; import {BooleanOperator} from "../search/models/boolean-operator"; +import {CaseStringId} from "../search/models/category/case/case-string-id"; +import {CaseAuthor} from "../search/models/category/case/case-author"; +import {UserResourceService} from "../resources/engine-endpoint/user-resource.service"; +import {CaseCreationDate} from "../search/models/category/case/case-creation-date"; +import {CaseCreationDateTime} from "../search/models/category/case/case-creation-date-time"; +import {InRangeDate} from "../search/models/operator/in-range-date"; +import {InRangeDateTime} from "../search/models/operator/in-range-date-time"; +import {CaseDataset} from "../search/models/category/case/case-dataset"; +import {CategoryFactory} from "../search/category-factory/category-factory"; +import {AllowedNetsService} from "../allowed-nets/services/allowed-nets.service"; +import {OptionalDependencies} from "../search/category-factory/optional-dependencies"; +import {CaseProcess} from "../search/models/category/case/case-process"; // todo 2466 doc export class PfqlVisitor extends QueryLangVisitor> { protected _logger: LoggerService; protected _operatorService: OperatorService + protected _userResourceService: UserResourceService; + protected _categoryFactory: CategoryFactory; + protected _allowedNetsService: AllowedNetsService; + + protected _categoryOptionalDependencies: OptionalDependencies; public constructor(injector: Injector) { super(); this._logger = injector.get(LoggerService); this._operatorService = injector.get(OperatorService); + this._userResourceService = injector.get(UserResourceService); + this._categoryFactory = injector.get(CategoryFactory); + this._allowedNetsService = injector.get(AllowedNetsService); + this._categoryOptionalDependencies = { + categoryFactory: this._categoryFactory, + searchIndexResolver: undefined, + allowedNetsService: this._allowedNetsService, + userResourceService: this._userResourceService + }; } // todo 2466 doc @@ -102,12 +149,8 @@ export class PfqlVisitor extends QueryLangVisitor> { return [new ComplexExpression(isNegated, innerItems)]; }; - /** - * Visit a parse tree produced by the `titleBasic` - * labeled alternative in `QueryLangParser.titleComparison`. - * @param ctx the parse tree - * @return the visitor result - */ + // todo 2466 more task alternatives + override visitTitleBasic = (ctx: TitleBasicContext): Array => { if (ctx.parent instanceof CaseComparisonsContext) { const expr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); @@ -119,12 +162,6 @@ export class PfqlVisitor extends QueryLangVisitor> { } }; - /** - * Visit a parse tree produced by the `titleLike` - * labeled alternative in `QueryLangParser.titleComparison`. - * @param ctx the parse tree - * @return the visitor result - */ override visitTitleLike = (ctx: TitleLikeContext): Array => { if (ctx.parent instanceof CaseComparisonsContext) { const expr: SimpleExpression = this.handleStringLikeComparisonContext(ctx.stringLikeComparison()); @@ -136,51 +173,158 @@ export class PfqlVisitor extends QueryLangVisitor> { } }; - /** - * Visit a parse tree produced by the `titleList` - * labeled alternative in `QueryLangParser.titleComparison`. - * @param ctx the parse tree - * @return the visitor result - */ - override visitTitleList = (ctx: TitleListContext): Array => { - this._logger.warn("There is no in list operator for title"); + override visitIdBasic = (ctx: IdBasicContext): Array => { + if (ctx.parent instanceof CaseComparisonsContext) { + const expr: SimpleExpression = this.handleObjectIdComparisonContext(ctx.objectIdComparison()); + expr.category = new CaseStringId(this._operatorService, this._logger); + return [expr]; + } else { + this._logger.warn("There is no dedicated category when visiting title while parsing PFQL query"); + return []; + } + }; + + override visitAuthorBasic = (ctx: AuthorBasicContext): Array => { + const expr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); + expr.category = new CaseAuthor(this._operatorService, this._logger, this._categoryOptionalDependencies); + return [expr]; + }; + + override visitCdDateBasic = (ctx: CdDateBasicContext): Array => { + const expr: SimpleExpression = this.handleDateComparisonContext(ctx.dateComparison()); + expr.category = new CaseCreationDate(this._operatorService, this._logger); + return [expr]; + }; + + override visitCdDateTimeBasic = (ctx: CdDateTimeBasicContext): Array => { + const expr: SimpleExpression = this.handleDateTimeComparisonContext(ctx.dateTimeComparison()); + expr.category = new CaseCreationDateTime(this._operatorService, this._logger); + return [expr]; + }; + + override visitCdDateRange = (ctx: CdDateRangeContext): Array => { + const inRangeCtx = ctx.inRangeDateComparison(); + if (!!inRangeCtx.dateRange()) { + const expr: SimpleExpression = this.handleDateRangeContext(inRangeCtx.dateRange(), !!inRangeCtx.NOT()); + expr.category = new CaseCreationDate(this._operatorService, this._logger); + return [expr]; + } else if (!!inRangeCtx.dateTimeRange()) { + const expr: SimpleExpression = this.handleDateTimeRangeContext(inRangeCtx.dateTimeRange(), !!inRangeCtx.NOT()); + expr.category = new CaseCreationDateTime(this._operatorService, this._logger); + return [expr]; + } else { + this._logger.error("No range values provided for creationDate range comparison"); + return []; + } + }; + + override visitDataString = (ctx: DataStringContext): Array => { + const expr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); + expr.category = new CaseDataset(this._operatorService, this._logger, this._categoryOptionalDependencies); + return [expr]; + }; + + override visitDataStringLike = (ctx: DataStringLikeContext): Array => { + // dataStringLike + return []; + }; + + override visitDataNumber = (ctx: DataNumberContext): Array => { + // dataNumber + return []; + }; + + override visitDataNumberRange = (ctx: DataNumberRangeContext): Array => { + // dataNumberRange return []; }; - /** - * Visit a parse tree produced by the `titleRange` - * labeled alternative in `QueryLangParser.titleComparison`. - * @param ctx the parse tree - * @return the visitor result - */ - override visitTitleRange = (ctx: TitleRangeContext): Array => { - this._logger.warn("There is no in range operator for title"); + override visitDataDate = (ctx: DataDateContext): Array => { + // dataDate return []; }; - /** - * Visit a parse tree produced by the `titleNull` - * labeled alternative in `QueryLangParser.titleComparison`. - * @param ctx the parse tree - * @return the visitor result - */ - override visitTitleNull = (ctx: TitleNullContext): Array => { - this._logger.warn("There is no null/empty operator for title"); + override visitDataDateRange = (ctx: DataDateRangeContext): Array => { + // dataDateRange + // handles also date time return []; }; - // todo 2466 more visit methods + override visitDataDatetime = (ctx: DataDatetimeContext): Array => { + // dataDatetime + return []; + }; + + override visitDataBoolean = (ctx: DataBooleanContext): Array => { + // dataBoolean + return []; + }; + + override visitDataNull = (ctx: DataNullContext): Array => { + // dataNull + return []; + }; + + // todo 2466 user field comparison ? ... ak je v string comparison mongo id, tak je to mozno user id? + + override visitProcessIdentifierBasic = (ctx: ProcessIdentifierBasicContext): Array => { + const expr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); + expr.category = new CaseProcess(this._operatorService, this._logger, this._categoryOptionalDependencies); + return [expr]; + }; + + // todo 2466 more visit methods (task comparisons) protected handleStringComparisonContext(ctx: StringComparisonContext): SimpleExpression { const operator: Operator = getOperatorFromToken(ctx._op); - const value: string = ctx.STRING()?.getText(); + const value: string = this.removeSingleQuotesFromString(ctx.STRING()?.getText()); + // todo 2466 handle logged user placeholder return new SimpleExpression(operator, value, !!ctx.NOT()); - } + }; protected handleStringLikeComparisonContext(ctx: StringLikeComparisonContext): SimpleExpression { const operator: Operator = new Like(); - const value: string = ctx.stringComparison().STRING().getText(); + const value: string = this.removeSingleQuotesFromString(ctx.stringComparison().STRING()?.getText()); + // todo 2466 handle logged user placeholder return new SimpleExpression(operator, value, !!ctx.stringComparison().NOT()); + }; + + protected removeSingleQuotesFromString(value: string): string { + if (value && value.length >= 2 && value.startsWith("'") && value.endsWith("'")) { + return value.substring(1, value.length - 1); + } + return value; + } + + protected handleObjectIdComparisonContext(ctx: ObjectIdComparisonContext): SimpleExpression { + const operator: Operator = getOperatorFromToken(ctx._op); + const value: string = this.removeSingleQuotesFromString(ctx.STRING()?.getText()) + // todo 2466 handle logged user id placeholder + return new SimpleExpression(operator, value, !!ctx.NOT()); + } + + protected handleDateComparisonContext(ctx: DateComparisonContext): SimpleExpression { + const operator: Operator = getDateOperatorFromToken(ctx._op, this._operatorService); + const value: string = ctx.DATE()?.getText(); + return new SimpleExpression(operator, value, !!ctx.NOT()); + } + + protected handleDateTimeComparisonContext(ctx: DateTimeComparisonContext): SimpleExpression { + const operator: Operator = getDateTimeOperatorFromToken(ctx._op, this._operatorService); + const value: string = ctx.DATETIME()?.getText(); + return new SimpleExpression(operator, value, !!ctx.NOT()); + } + + protected handleDateRangeContext(ctx: DateRangeContext, isNegated: boolean): SimpleExpression { + const operator: Operator = new InRangeDate(); + const value: string[] = ctx.DATE()?.map(terminalNode => terminalNode.getText()); + return new SimpleExpression(operator, value, isNegated); + } + + protected handleDateTimeRangeContext(ctx: DateTimeRangeContext, isNegated: boolean): SimpleExpression { + const operator: Operator = new InRangeDateTime(); + const value: string[] = ctx.DATETIME()?.map(terminalNode => terminalNode.getText()); + return new SimpleExpression(operator, value, isNegated); } // todo 2466 more handle methods diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts index 48922f7d9a..40e7114139 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts @@ -7,9 +7,11 @@ import {OptionalDependencies} from '../../../category-factory/optional-dependenc import {NoConfigurationAutocompleteCategory} from '../no-configuration-autocomplete-category'; import {NotEquals} from '../../operator/not-equals'; import {Categories} from '../categories'; -import {Subscription} from 'rxjs'; +import {Observable, Subject, Subscription} from 'rxjs'; import {CaseSearch} from './case-search.enum'; import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; +import {take, filter} from "rxjs/operators"; +import {SimpleExpression} from "../../../../pfql/model/simple-expression"; export class CaseProcess extends NoConfigurationAutocompleteCategory { @@ -53,6 +55,27 @@ export class CaseProcess extends NoConfigurationAutocompleteCategory { }); } + public override loadFromPfqlExpression(expression: SimpleExpression): Observable { + const isDone$ = new Subject(); + if (!this.selectOperatorFromPfqlExpression(expression)) { + isDone$.next(); + isDone$.complete(); + return isDone$.asObservable(); + } + this._options$.pipe( + filter(options => options.length > 0), + take(1) + ).subscribe(options => { + const found = options.find(option => option.value.includes(expression.operandValue)); + if (found) { + this.setOperands([found] as any); + } + isDone$.next(); + isDone$.complete(); + }); + return isDone$.asObservable(); + } + /** * Checks whether the provided option is unique and updates the list of unique options with it. * @param key autocomplete option key diff --git a/projects/netgrif-components-core/src/lib/search/models/category/category.ts b/projects/netgrif-components-core/src/lib/search/models/category/category.ts index 9f6935e2d7..1c28f38b14 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/category.ts @@ -4,7 +4,7 @@ import {Query} from '../query/query'; import {ElementaryPredicate} from '../predicate/elementary-predicate'; import {SearchInputType} from './search-input-type'; import {FormControl} from '@angular/forms'; -import {BehaviorSubject, forkJoin, Observable, of, ReplaySubject} from 'rxjs'; +import {BehaviorSubject, forkJoin, Observable, of, ReplaySubject, Subject} from 'rxjs'; import {debounceTime, defaultIfEmpty, map} from 'rxjs/operators'; import {OperatorTemplatePart} from '../operator-template-part'; import {IncrementingCounter} from '../../../utility/incrementing-counter'; @@ -18,6 +18,7 @@ import {FilterTextSegment} from '../persistance/filter-text-segment'; import {DATE_FORMAT_STRING, DATE_TIME_FORMAT_STRING} from '../../../moment/time-formats'; import {Type} from '@angular/core'; import {ResourceTypeQueryPrefix} from "./resource-type-query-prefix"; +import {SimpleExpression} from "../../../pfql/model/simple-expression"; /** * The top level of abstraction in search query generation. Represents a set of indexed fields that can be searched. @@ -423,6 +424,31 @@ export abstract class Category { return result$.asObservable(); } + // todo 2466 + public loadFromPfqlExpression(expression: SimpleExpression): Observable { + const isDone$ = new Subject(); + if (!this.selectOperatorFromPfqlExpression(expression)) { + isDone$.next(); + isDone$.complete(); + return isDone$.asObservable(); + } + this.setOperands(Array.isArray(expression.operandValue) ? expression.operandValue : [expression.operandValue]); + isDone$.next(); + isDone$.complete(); + return isDone$.asObservable(); + } + + protected selectOperatorFromPfqlExpression(expression: SimpleExpression): boolean { + const operatorIdx: number = this.allowedOperators.findIndex(op => op.type === expression.operator.type); + if (operatorIdx === -1) { + // todo 2466 log also category + this._log.error(`Operator '${expression.operator.type}' is unavailable for this category`); + return false; + } + this.selectOperator(operatorIdx); + return true; + } + /** * This method is calle in the constructor. Apart from calling this method, the constructor only creates instances to fill the protected * fields of this class. diff --git a/projects/netgrif-components-core/src/lib/search/models/category/net-attribute-autocomplete-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/net-attribute-autocomplete-category.ts index 8eef9e749b..d1c76ca010 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/net-attribute-autocomplete-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/net-attribute-autocomplete-category.ts @@ -7,10 +7,11 @@ import {NameIdPair} from './name-id-pair'; import {Query} from '../query/query'; import {BooleanOperator} from '../boolean-operator'; import {Category} from './category'; -import {Subscription} from 'rxjs'; +import {Observable, Subscription} from 'rxjs'; import {OperatorService} from '../../operator-service/operator.service'; import {OptionalDependencies} from '../../category-factory/optional-dependencies'; import {ResourceTypeQueryPrefix} from "./resource-type-query-prefix"; +import {SimpleExpression} from "../../../pfql/model/simple-expression"; /** * A utility class for autocomplete search categories that are net specific, such as searching by roles, or tasks. @@ -61,6 +62,11 @@ export abstract class NetAttributeAutocompleteCategory extends NoConfigurationAu }); } + public override loadFromPfqlExpression(expression: SimpleExpression): Observable { + // todo 2466 + return undefined; + } + /** * This method should extract the relevant attribute display names and ids. * They will be automatically paired with the net id for further use by this search category. diff --git a/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts index 3acbfa819e..0b9ae5fe08 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts @@ -4,11 +4,13 @@ import {Operator} from '../operator/operator'; import {LoggerService} from '../../../logger/services/logger.service'; import {OperatorService} from '../../operator-service/operator.service'; import {OptionalDependencies} from '../../category-factory/optional-dependencies'; -import {Observable} from 'rxjs'; +import {Observable, Subject} from 'rxjs'; import {SearchAutocompleteOption} from './search-autocomplete-option'; import {Query} from '../query/query'; import {FormControl} from '@angular/forms'; import {ResourceTypeQueryPrefix} from "./resource-type-query-prefix"; +import {take} from "rxjs/operators"; +import {SimpleExpression} from "../../../pfql/model/simple-expression"; export abstract class NoConfigurationUserAutocompleteCategory extends NoConfigurationAutocompleteCategory { @@ -47,4 +49,27 @@ export abstract class NoConfigurationUserAutocompleteCategory extends NoConfigur Observable>> { return this._userAutocomplete.deserializeOperandValue(savedOption); } + + public override loadFromPfqlExpression(expression: SimpleExpression): Observable { + // todo 2466 check if expressionValue is valid object id hex string + const isDone$ = new Subject(); + if (!this.selectOperatorFromPfqlExpression(expression)) { + isDone$.next(); + isDone$.complete(); + return isDone$.asObservable(); + } + const optionToBeSelected$ = this._userAutocomplete.getOptionFromExpressionValue$(expression.operandValue); + optionToBeSelected$.pipe(take(1)).subscribe({ + next: optionToBeSelected => { + this.setOperands([optionToBeSelected] as any); + isDone$.next(); + isDone$.complete(); + }, + error: error => { + isDone$.next(); + isDone$.complete(); + } + }); + return isDone$.asObservable(); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts index c64eae2253..8177a6c70f 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts @@ -7,8 +7,9 @@ import {BooleanOperator} from '../../boolean-operator'; import {NoConfigurationAutocompleteCategory} from '../no-configuration-autocomplete-category'; import {NotEquals} from '../../operator/not-equals'; import {Categories} from '../categories'; -import {Subscription} from 'rxjs'; +import {Observable, Subscription} from 'rxjs'; import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; +import {SimpleExpression} from "../../../../pfql/model/simple-expression"; export class TaskProcess extends NoConfigurationAutocompleteCategory { @@ -48,6 +49,11 @@ export class TaskProcess extends NoConfigurationAutocompleteCategory { }); } + public override loadFromPfqlExpression(expression: SimpleExpression): Observable { + // todo 2466 + return undefined; + } + protected generateQuery(userInput: Array>): Query { if (this.selectedOperator.numberOfOperands !== 1) { throw new Error('Only unary operators are currently supported by the TaskProcess implementation'); diff --git a/projects/netgrif-components-core/src/lib/search/models/category/user-autocomplete.ts b/projects/netgrif-components-core/src/lib/search/models/category/user-autocomplete.ts index d1ee8458de..c45eb5b9cf 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/user-autocomplete.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/user-autocomplete.ts @@ -78,6 +78,13 @@ export class UserAutocomplete implements AutocompleteOptions { return of({...savedOption, icon: this.isUserMeTemplate(savedOption) ? UserAutocomplete.USER_ME_ICON : UserAutocomplete.USER_ICON}); } + public getOptionFromExpressionValue$(expressionValue: string): Observable>> { + return this._userResourceService.getUser(expressionValue).pipe( + map(user => { + return {text: user.fullName, value: [user.id], icon: UserAutocomplete.USER_ICON}; + })); + } + private isUserMeTemplate(option: SearchAutocompleteOption>): boolean { return !!option?.value && Array.isArray(option.value) diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts index 51c8e9757f..d75173c1d7 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts @@ -382,6 +382,7 @@ export class SearchService implements OnDestroy { // todo 2466 validate query prefix with filter type this.clearPredicates(true); + this._loadingFromMetadata$.on(); const queryItems: Array = parseQuery(query, this._injector); if (!queryItems) { this._log.warn(`Could not parse query '${query}. Clearing the search...`) @@ -390,8 +391,11 @@ export class SearchService implements OnDestroy { // todo 2466 na jednej urovni moze byt len jeden typ operatora - this.loadExpressionsIntoPredicate(this._rootPredicate, BooleanOperator.AND, queryItems); - this.updateActiveFilter(); + const categoryLoadings$ = this.loadExpressionsIntoPredicate(this._rootPredicate, BooleanOperator.AND, queryItems); + forkJoin(categoryLoadings$).subscribe(() => { + this._loadingFromMetadata$.off(); + this.updateActiveFilter(); + }); } /** @@ -402,30 +406,35 @@ export class SearchService implements OnDestroy { } protected loadExpressionsIntoPredicate(predicate: EditableClausePredicateWithGenerators, operatorOfPredicate: BooleanOperator, - items: Array) { + items: Array): Array> { const expressions: Array = items.filter(item => item.type() !== QueryItemType.LOGICAL_OPERATOR); + const categoryLoadings$: Array> = []; for (const expression of expressions) { if (expression.type() === QueryItemType.SIMPLE_EXPRESSION) { + let categoryLoading$: Observable; if (operatorOfPredicate.valueOf() === BooleanOperator.AND.valueOf()) { const branchId = predicate.addNewClausePredicate(BooleanOperator.OR); const localPredicate = predicate.getPredicateMap().get(branchId).getWrappedPredicate() as unknown as EditableClausePredicateWithGenerators; - this.loadSimpleExpressionIntoPredicate(localPredicate, expression as SimpleExpression); + categoryLoading$ = this.loadSimpleExpressionIntoPredicate(localPredicate, expression as SimpleExpression); } else { - this.loadSimpleExpressionIntoPredicate(predicate, expression as SimpleExpression); + categoryLoading$ = this.loadSimpleExpressionIntoPredicate(predicate, expression as SimpleExpression); } + categoryLoadings$.push(categoryLoading$); } else if (expression.type() === QueryItemType.COMPLEX_EXPRESSION) { this.loadFromQueryItemsIntoNewPredicate(predicate, (expression as ComplexExpression).items); } else { // todo 2466 warn ignoring } } + return categoryLoadings$; } - protected loadFromQueryItemsIntoNewPredicate(parentPredicate: EditableClausePredicateWithGenerators, items: Array) { + protected loadFromQueryItemsIntoNewPredicate(parentPredicate: EditableClausePredicateWithGenerators, + items: Array): Array> { const booleanOperator: BooleanOperator = this.determineBooleanOperator(items); const branchId = parentPredicate.addNewClausePredicate(booleanOperator); const branchPredicate = parentPredicate.getPredicateMap().get(branchId).getWrappedPredicate() as unknown as EditableClausePredicateWithGenerators - this.loadExpressionsIntoPredicate(branchPredicate, booleanOperator, items); + return this.loadExpressionsIntoPredicate(branchPredicate, booleanOperator, items); } protected determineBooleanOperator(items: Array): BooleanOperator { @@ -433,16 +442,10 @@ export class SearchService implements OnDestroy { return booleanOperators.length === 0 ? BooleanOperator.AND : (booleanOperators[0] as LogicalOperator).value; } - protected loadSimpleExpressionIntoPredicate(predicate: EditableClausePredicateWithGenerators, simpleExpr: SimpleExpression) { + protected loadSimpleExpressionIntoPredicate(predicate: EditableClausePredicateWithGenerators, simpleExpr: SimpleExpression): Observable { const category: Category = simpleExpr.category; - const operatorIdx: number = category.allowedOperators.findIndex(op => op.type === simpleExpr.operator.type); - if (operatorIdx === -1) { - // todo 2466 handle error - this._log.error(`Operator '${simpleExpr.operator.type}' is unavailable for this category`); - return; - } - category.selectOperator(operatorIdx); - category.setOperands([simpleExpr.operandValue]); + const categoryLoading$: Observable = category.loadFromPfqlExpression(simpleExpr); predicate.addNewPredicateFromGenerator(category); + return categoryLoading$; } } From dd5834c9f9dd31b8d127e725a8bb6507def589ca Mon Sep 17 00:00:00 2001 From: chvostek Date: Thu, 30 Jul 2026 11:38:16 +0200 Subject: [PATCH 13/55] [NAE-2466] Advanced search for PFQL - implement handling for CaseDataSet category --- .../lib/pfql/model/data-simple-expression.ts | 19 +++++++++ .../src/lib/pfql/pfql-visitor.ts | 9 +++-- .../models/category/case/case-dataset.ts | 40 ++++++++++++++++++- 3 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 projects/netgrif-components-core/src/lib/pfql/model/data-simple-expression.ts diff --git a/projects/netgrif-components-core/src/lib/pfql/model/data-simple-expression.ts b/projects/netgrif-components-core/src/lib/pfql/model/data-simple-expression.ts new file mode 100644 index 0000000000..b0a4effa57 --- /dev/null +++ b/projects/netgrif-components-core/src/lib/pfql/model/data-simple-expression.ts @@ -0,0 +1,19 @@ +import {SimpleExpression} from "./simple-expression"; +import {Operator} from "../../search/models/operator/operator"; +import {Category} from "../../search/models/category/category"; + +// todo 2466 +export class DataSimpleExpression extends SimpleExpression { + protected _dataFieldId: string; + + public constructor(dataFieldPath: string, operator: Operator, operandValue: any, negated: boolean, category?: Category) { + super(operator, operandValue, negated, category); + + const parts = dataFieldPath.split('.'); + this._dataFieldId = parts.length >= 3 && parts[0] === 'data' ? parts[1] : dataFieldPath; + } + + public get dataFieldId(): string { + return this._dataFieldId; + } +} diff --git a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts index cfb3557f8e..6dadfc09a5 100644 --- a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts +++ b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts @@ -57,6 +57,7 @@ import {CategoryFactory} from "../search/category-factory/category-factory"; import {AllowedNetsService} from "../allowed-nets/services/allowed-nets.service"; import {OptionalDependencies} from "../search/category-factory/optional-dependencies"; import {CaseProcess} from "../search/models/category/case/case-process"; +import {DataSimpleExpression} from "./model/data-simple-expression"; // todo 2466 doc @@ -219,9 +220,11 @@ export class PfqlVisitor extends QueryLangVisitor> { }; override visitDataString = (ctx: DataStringContext): Array => { - const expr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); - expr.category = new CaseDataset(this._operatorService, this._logger, this._categoryOptionalDependencies); - return [expr]; + const simpleExpr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); + const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, + simpleExpr.operandValue, simpleExpr.negated) + dataExpr.category = new CaseDataset(this._operatorService, this._logger, this._categoryOptionalDependencies); + return [dataExpr]; }; override visitDataStringLike = (ctx: DataStringLikeContext): Array => { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts index aaf949b963..1aed30a39b 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts @@ -12,7 +12,7 @@ import { EqualsDate } from '../../operator/equals-date'; import { Substring } from '../../operator/substring'; import { EqualsDateTime } from '../../operator/equals-date-time'; import { Equals } from '../../operator/equals'; -import { BehaviorSubject, Observable, of, ReplaySubject, Subscription } from 'rxjs'; +import {BehaviorSubject, Observable, of, ReplaySubject, Subject, Subscription} from 'rxjs'; import { Category } from '../category'; import { NotEquals } from '../../operator/not-equals'; import { IsNull } from '../../operator/is-null'; @@ -43,6 +43,9 @@ import { FilterTextSegment } from '../../persistance/filter-text-segment'; import { UserAutocomplete } from '../user-autocomplete'; import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; import {FieldTypeResource} from "../../../../task-content/model/field-type-resource"; +import {SimpleExpression} from "../../../../pfql/model/simple-expression"; +import {DataSimpleExpression} from "../../../../pfql/model/data-simple-expression"; +import {take} from "rxjs/operators"; interface Datafield { netIdentifier: string; @@ -349,6 +352,21 @@ export class CaseDataset extends Category implements AutocompleteOpti } } + public selectDataFieldsByPfqlExpression(expression: DataSimpleExpression): void { + let dataFieldMapKey: string | undefined; + for (const [key, dataFields] of this._datafieldOptions.entries()) { + if (dataFields.some(dataField => dataField.fieldId === expression.dataFieldId)) { + dataFieldMapKey = key; + break; + } + } + if (dataFieldMapKey === undefined) { + this._log.warn(`No data field option found for dataFieldId '${expression.dataFieldId}'`); + return; + } + this._DATAFIELD_INPUT.formControl.setValue(DatafieldMapKey.parse(dataFieldMapKey)); + } + /** * Adds a new entry or pushes value into an existing entry. * When a new entry is created, it is created as an Array of one element. @@ -440,6 +458,26 @@ export class CaseDataset extends Category implements AutocompleteOpti return result$.asObservable(); } + public override loadFromPfqlExpression(expression: SimpleExpression): Observable { + const isDone$ = new Subject(); + if (!(expression instanceof DataSimpleExpression)) { + this._log.error("Cannot load category CaseDataSet from wrong PFQL expression") + isDone$.next(); + isDone$.complete(); + return isDone$.asObservable(); + } + + this._datafieldOptionsInitialized$.pipe(take(1)).subscribe(() => { + this.selectDataFieldsByPfqlExpression(expression); + this.selectOperatorFromPfqlExpression(expression); + this.setOperands([expression.operandValue] as any); + isDone$.next(); + isDone$.complete(); + }); + + return isDone$.asObservable(); + } + protected deserializeOperandValue(value: unknown): Observable { switch (this.inputType) { case SearchInputType.AUTOCOMPLETE: From e558d532a1f795c6d8520be3baddbda4c7aa256a Mon Sep 17 00:00:00 2001 From: chvostek Date: Thu, 30 Jul 2026 16:25:19 +0200 Subject: [PATCH 14/55] [NAE-2466] Advanced search for PFQL - implement handling for CaseDataSet category --- .../src/lib/pfql/pfql-visitor.ts | 112 +++++++++++++++--- .../models/category/case/case-dataset.ts | 14 ++- 2 files changed, 103 insertions(+), 23 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts index 6dadfc09a5..8dcadcb620 100644 --- a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts +++ b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts @@ -1,6 +1,7 @@ import {QueryLangVisitor} from "./generated/QueryLangVisitor"; import { AuthorBasicContext, + BooleanComparisonContext, CaseAndExpressionContext, CaseComparisonsContext, CaseConditionGroupParenthesisContext, @@ -24,6 +25,9 @@ import { DateTimeComparisonContext, DateTimeRangeContext, IdBasicContext, + InRangeNumberComparisonContext, + NullComparisonContext, + NumberComparisonContext, ObjectIdComparisonContext, ProcessIdentifierBasicContext, StringComparisonContext, @@ -58,6 +62,8 @@ import {AllowedNetsService} from "../allowed-nets/services/allowed-nets.service" import {OptionalDependencies} from "../search/category-factory/optional-dependencies"; import {CaseProcess} from "../search/models/category/case/case-process"; import {DataSimpleExpression} from "./model/data-simple-expression"; +import {InRange} from "../search/models/operator/in-range"; +import {IsNull} from "../search/models/operator/is-null"; // todo 2466 doc @@ -222,50 +228,83 @@ export class PfqlVisitor extends QueryLangVisitor> { override visitDataString = (ctx: DataStringContext): Array => { const simpleExpr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, - simpleExpr.operandValue, simpleExpr.negated) + simpleExpr.operandValue, simpleExpr.negated); dataExpr.category = new CaseDataset(this._operatorService, this._logger, this._categoryOptionalDependencies); return [dataExpr]; }; override visitDataStringLike = (ctx: DataStringLikeContext): Array => { - // dataStringLike - return []; + const simpleExpr: SimpleExpression = this.handleStringLikeComparisonContext(ctx.stringLikeComparison()); + const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, + simpleExpr.operandValue, simpleExpr.negated); + dataExpr.category = new CaseDataset(this._operatorService, this._logger, this._categoryOptionalDependencies); + return [dataExpr]; }; override visitDataNumber = (ctx: DataNumberContext): Array => { - // dataNumber - return []; + const simpleExpr: SimpleExpression = this.handleNumberComparisonContext(ctx.numberComparison()); + const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, + simpleExpr.operandValue, simpleExpr.negated); + dataExpr.category = new CaseDataset(this._operatorService, this._logger, this._categoryOptionalDependencies); + return [dataExpr]; }; override visitDataNumberRange = (ctx: DataNumberRangeContext): Array => { - // dataNumberRange - return []; + const simpleExpr: SimpleExpression = this.handleInRangeNumberComparisonContext(ctx.inRangeNumberComparison()); + const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, + simpleExpr.operandValue, simpleExpr.negated); + dataExpr.category = new CaseDataset(this._operatorService, this._logger, this._categoryOptionalDependencies); + return [dataExpr]; }; override visitDataDate = (ctx: DataDateContext): Array => { - // dataDate - return []; + const simpleExpr: SimpleExpression = this.handleDateComparisonContext(ctx.dateComparison()); + const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, + simpleExpr.operandValue, simpleExpr.negated); + dataExpr.category = new CaseDataset(this._operatorService, this._logger, this._categoryOptionalDependencies); + return [dataExpr]; }; override visitDataDateRange = (ctx: DataDateRangeContext): Array => { - // dataDateRange - // handles also date time - return []; + const inRangeCtx = ctx.inRangeDateComparison(); + let simpleExpr: SimpleExpression; + if (!!inRangeCtx.dateRange()) { + simpleExpr = this.handleDateRangeContext(inRangeCtx.dateRange(), !!inRangeCtx.NOT()); + } else if (!!inRangeCtx.dateTimeRange()) { + simpleExpr = this.handleDateTimeRangeContext(inRangeCtx.dateTimeRange(), !!inRangeCtx.NOT()); + } else { + this._logger.error("No range values provided for creationDate range comparison"); + return []; + } + + const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, + simpleExpr.operandValue, simpleExpr.negated); + dataExpr.category = new CaseDataset(this._operatorService, this._logger, this._categoryOptionalDependencies); + return [dataExpr]; }; override visitDataDatetime = (ctx: DataDatetimeContext): Array => { - // dataDatetime - return []; + const simpleExpr: SimpleExpression = this.handleDateTimeComparisonContext(ctx.dateTimeComparison()); + const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, + simpleExpr.operandValue, simpleExpr.negated); + dataExpr.category = new CaseDataset(this._operatorService, this._logger, this._categoryOptionalDependencies); + return [dataExpr]; }; override visitDataBoolean = (ctx: DataBooleanContext): Array => { - // dataBoolean - return []; + const simpleExpr: SimpleExpression = this.handleBooleanComparisonContext(ctx.booleanComparison()); + const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, + simpleExpr.operandValue, simpleExpr.negated); + dataExpr.category = new CaseDataset(this._operatorService, this._logger, this._categoryOptionalDependencies); + return [dataExpr]; }; override visitDataNull = (ctx: DataNullContext): Array => { - // dataNull - return []; + const simpleExpr: SimpleExpression = this.handleNullComparisonContext(ctx.nullComparison()); + const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, + simpleExpr.operandValue, simpleExpr.negated); + dataExpr.category = new CaseDataset(this._operatorService, this._logger, this._categoryOptionalDependencies); + return [dataExpr]; }; // todo 2466 user field comparison ? ... ak je v string comparison mongo id, tak je to mozno user id? @@ -278,6 +317,8 @@ export class PfqlVisitor extends QueryLangVisitor> { // todo 2466 more visit methods (task comparisons) + // todo 2466 implement handler dispatcher? + protected handleStringComparisonContext(ctx: StringComparisonContext): SimpleExpression { const operator: Operator = getOperatorFromToken(ctx._op); const value: string = this.removeSingleQuotesFromString(ctx.STRING()?.getText()); @@ -330,5 +371,40 @@ export class PfqlVisitor extends QueryLangVisitor> { return new SimpleExpression(operator, value, isNegated); } + protected handleNumberComparisonContext(ctx: NumberComparisonContext): SimpleExpression { + const operator: Operator = getOperatorFromToken(ctx._op); + let value: number; + if (!!ctx.INT()) { + value = parseInt(ctx.INT().getText(), 10); + } else if (!!ctx.DOUBLE()) { + value = parseFloat(ctx.DOUBLE().getText()); + } + return new SimpleExpression(operator, value, !!ctx.NOT()); + } + + protected handleInRangeNumberComparisonContext(ctx: InRangeNumberComparisonContext): SimpleExpression { + const operator: Operator = new InRange(); + let fromValue: number, toValue: number; + if (!!ctx.intRange()) { + fromValue = parseInt(ctx.intRange().INT()[0].getText(), 10); + toValue = parseInt(ctx.intRange().INT()[1].getText(), 10); + } else if (!!ctx.doubleRange()) { + fromValue = parseFloat(ctx.doubleRange().DOUBLE()[0].getText()); + toValue = parseFloat(ctx.doubleRange().DOUBLE()[1].getText()); + } + return new SimpleExpression(operator, [fromValue, toValue], !!ctx.NOT()); + } + + protected handleBooleanComparisonContext(ctx: BooleanComparisonContext): SimpleExpression { + const operator: Operator = getOperatorFromToken(ctx._op); + const value: boolean = ctx.BOOLEAN().getText().toLowerCase() === 'true'; + return new SimpleExpression(operator, value, !!ctx.NOT()); + } + + protected handleNullComparisonContext(ctx: NullComparisonContext): SimpleExpression { + const operator: Operator = new IsNull(); + return new SimpleExpression(operator, undefined, !!ctx.NOT()); + } + // todo 2466 more handle methods } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts index 1aed30a39b..b236b35a9f 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts @@ -70,9 +70,11 @@ export class CaseDataset extends Category implements AutocompleteOpti protected _datafieldOptions: Map>; - private _datafieldOptionsInitialized$: ReplaySubject; - private _allowedNetsSub: Subscription; - private _userAutocomplete: UserAutocomplete; + protected _datafieldOptionsInitialized$: ReplaySubject; + protected _allowedNetsSub: Subscription; + protected _userAutocomplete: UserAutocomplete; + + protected _isLoadedFromPfql: boolean = false; public static FieldTypeToInputType(fieldType: string): SearchInputType { switch (fieldType) { @@ -294,7 +296,8 @@ export class CaseDataset extends Category implements AutocompleteOpti } protected generateNetConstraint(datafield: Datafield): Query { - return this._processCategory.generatePredicate([[datafield.netIdentifier]]).query; + return this._isLoadedFromPfql ? new Query(undefined, ResourceTypeQueryPrefix.CASES, true) + : this._processCategory.generatePredicate([[datafield.netIdentifier]]).query; } protected createDatafieldOptions(): void { @@ -468,9 +471,10 @@ export class CaseDataset extends Category implements AutocompleteOpti } this._datafieldOptionsInitialized$.pipe(take(1)).subscribe(() => { + this._isLoadedFromPfql = true; this.selectDataFieldsByPfqlExpression(expression); this.selectOperatorFromPfqlExpression(expression); - this.setOperands([expression.operandValue] as any); + this.setOperands(Array.isArray(expression.operandValue) ? expression.operandValue : [expression.operandValue]); isDone$.next(); isDone$.complete(); }); From 574ba77da3cb015aa7b82178ec76705977fc0ee6 Mon Sep 17 00:00:00 2001 From: chvostek Date: Mon, 3 Aug 2026 16:45:17 +0200 Subject: [PATCH 15/55] [NAE-2466] Advanced search for PFQL - implement handling for task categories --- .../src/lib/pfql/pfql-visitor.ts | 63 ++++++++++++++++++- .../models/category/case/case-dataset.ts | 12 ++-- .../models/category/case/case-process.ts | 8 +-- .../lib/search/models/category/category.ts | 9 +-- .../net-attribute-autocomplete-category.ts | 8 +-- ...onfiguration-user-autocomplete-category.ts | 26 +++++--- .../models/category/task/task-process.ts | 29 ++++++++- .../search/models/category/task/task-task.ts | 32 ++++++++++ .../search/search-service/search.service.ts | 5 ++ 9 files changed, 154 insertions(+), 38 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts index 8dcadcb620..48d40e615d 100644 --- a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts +++ b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts @@ -29,13 +29,20 @@ import { NullComparisonContext, NumberComparisonContext, ObjectIdComparisonContext, + ProcessIdBasicContext, ProcessIdentifierBasicContext, StringComparisonContext, StringLikeComparisonContext, + TaskAndExpressionContext, + TaskConditionGroupParenthesisContext, TaskConditionsAndPagingContext, + TaskOrExpressionContext, TaskQueryContext, TitleBasicContext, TitleLikeContext, + TransitionIdBasicContext, + UserIdBasicContext, + UserIdNullContext, } from "./generated/QueryLangParser"; import {LoggerService} from "../logger/services/logger.service"; import {CaseTitle} from "../search/models/category/case/case-title"; @@ -64,6 +71,9 @@ import {CaseProcess} from "../search/models/category/case/case-process"; import {DataSimpleExpression} from "./model/data-simple-expression"; import {InRange} from "../search/models/operator/in-range"; import {IsNull} from "../search/models/operator/is-null"; +import {TaskTask} from "../search/models/category/task/task-task"; +import {TaskAssignee} from "../search/models/category/task/task-assignee"; +import {TaskProcess} from "../search/models/category/task/task-process"; // todo 2466 doc @@ -156,7 +166,34 @@ export class PfqlVisitor extends QueryLangVisitor> { return [new ComplexExpression(isNegated, innerItems)]; }; - // todo 2466 more task alternatives + // todo 2466 doc + override visitTaskOrExpression = (ctx: TaskOrExpressionContext): Array => { + const andExpressionContexts = ctx.taskAndExpression(); + const items: Array = [...this.visit(andExpressionContexts[0])]; + for (let i = 1; i < andExpressionContexts.length; i++) { + items.push(new LogicalOperator(BooleanOperator.OR)); + items.push(...this.visit(andExpressionContexts[i])); + } + return items; + }; + + // todo 2466 doc + override visitTaskAndExpression = (ctx: TaskAndExpressionContext): Array => { + const conditionGroupContexts = ctx.taskConditionGroup(); + const items: Array = [...this.visit(conditionGroupContexts[0])]; + for (let i = 1; i < conditionGroupContexts.length; i++) { + items.push(new LogicalOperator(BooleanOperator.AND)); + items.push(...this.visit(conditionGroupContexts[i])); + } + return items; + }; + + // todo 2466 doc + override visitTaskConditionGroupParenthesis = (ctx: TaskConditionGroupParenthesisContext): Array => { + const innerItems: Array = [...this.visit(ctx.taskConditions())]; + const isNegated: boolean = !!ctx.NOT(); + return [new ComplexExpression(isNegated, innerItems)]; + }; override visitTitleBasic = (ctx: TitleBasicContext): Array => { if (ctx.parent instanceof CaseComparisonsContext) { @@ -315,7 +352,29 @@ export class PfqlVisitor extends QueryLangVisitor> { return [expr]; }; - // todo 2466 more visit methods (task comparisons) + override visitTransitionIdBasic = (ctx: TransitionIdBasicContext): Array => { + const expr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); + expr.category = new TaskTask(this._operatorService, this._logger, this._categoryOptionalDependencies); + return [expr]; + } + + override visitUserIdBasic = (ctx: UserIdBasicContext): Array => { + const expr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); + expr.category = new TaskAssignee(this._operatorService, this._logger, this._categoryOptionalDependencies); + return [expr]; + }; + + override visitUserIdNull = (ctx: UserIdNullContext): Array => { + const expr: SimpleExpression = this.handleNullComparisonContext(ctx.nullComparison()); + expr.category = new TaskAssignee(this._operatorService, this._logger, this._categoryOptionalDependencies); + return [expr]; + }; + + override visitProcessIdBasic = (ctx: ProcessIdBasicContext): Array => { + const expr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); + expr.category = new TaskProcess(this._operatorService, this._logger, this._categoryOptionalDependencies); + return [expr]; + }; // todo 2466 implement handler dispatcher? diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts index b236b35a9f..1b614fd00f 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts @@ -462,18 +462,20 @@ export class CaseDataset extends Category implements AutocompleteOpti } public override loadFromPfqlExpression(expression: SimpleExpression): Observable { - const isDone$ = new Subject(); if (!(expression instanceof DataSimpleExpression)) { this._log.error("Cannot load category CaseDataSet from wrong PFQL expression") - isDone$.next(); - isDone$.complete(); - return isDone$.asObservable(); + return of(undefined); } + const isDone$ = new Subject(); this._datafieldOptionsInitialized$.pipe(take(1)).subscribe(() => { this._isLoadedFromPfql = true; this.selectDataFieldsByPfqlExpression(expression); - this.selectOperatorFromPfqlExpression(expression); + if (!this.selectOperatorFromPfqlExpression(expression)) { + isDone$.next(); + isDone$.complete(); + return; + } this.setOperands(Array.isArray(expression.operandValue) ? expression.operandValue : [expression.operandValue]); isDone$.next(); isDone$.complete(); diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts index 40e7114139..ccaae23459 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts @@ -7,7 +7,7 @@ import {OptionalDependencies} from '../../../category-factory/optional-dependenc import {NoConfigurationAutocompleteCategory} from '../no-configuration-autocomplete-category'; import {NotEquals} from '../../operator/not-equals'; import {Categories} from '../categories'; -import {Observable, Subject, Subscription} from 'rxjs'; +import {Observable, of, Subject, Subscription} from 'rxjs'; import {CaseSearch} from './case-search.enum'; import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; import {take, filter} from "rxjs/operators"; @@ -56,12 +56,10 @@ export class CaseProcess extends NoConfigurationAutocompleteCategory { } public override loadFromPfqlExpression(expression: SimpleExpression): Observable { - const isDone$ = new Subject(); if (!this.selectOperatorFromPfqlExpression(expression)) { - isDone$.next(); - isDone$.complete(); - return isDone$.asObservable(); + return of(undefined); } + const isDone$ = new Subject(); this._options$.pipe( filter(options => options.length > 0), take(1) diff --git a/projects/netgrif-components-core/src/lib/search/models/category/category.ts b/projects/netgrif-components-core/src/lib/search/models/category/category.ts index 1c28f38b14..aade1ad6bb 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/category.ts @@ -426,16 +426,11 @@ export abstract class Category { // todo 2466 public loadFromPfqlExpression(expression: SimpleExpression): Observable { - const isDone$ = new Subject(); if (!this.selectOperatorFromPfqlExpression(expression)) { - isDone$.next(); - isDone$.complete(); - return isDone$.asObservable(); + return of(undefined); } this.setOperands(Array.isArray(expression.operandValue) ? expression.operandValue : [expression.operandValue]); - isDone$.next(); - isDone$.complete(); - return isDone$.asObservable(); + return of(undefined); } protected selectOperatorFromPfqlExpression(expression: SimpleExpression): boolean { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/net-attribute-autocomplete-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/net-attribute-autocomplete-category.ts index d1c76ca010..8eef9e749b 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/net-attribute-autocomplete-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/net-attribute-autocomplete-category.ts @@ -7,11 +7,10 @@ import {NameIdPair} from './name-id-pair'; import {Query} from '../query/query'; import {BooleanOperator} from '../boolean-operator'; import {Category} from './category'; -import {Observable, Subscription} from 'rxjs'; +import {Subscription} from 'rxjs'; import {OperatorService} from '../../operator-service/operator.service'; import {OptionalDependencies} from '../../category-factory/optional-dependencies'; import {ResourceTypeQueryPrefix} from "./resource-type-query-prefix"; -import {SimpleExpression} from "../../../pfql/model/simple-expression"; /** * A utility class for autocomplete search categories that are net specific, such as searching by roles, or tasks. @@ -62,11 +61,6 @@ export abstract class NetAttributeAutocompleteCategory extends NoConfigurationAu }); } - public override loadFromPfqlExpression(expression: SimpleExpression): Observable { - // todo 2466 - return undefined; - } - /** * This method should extract the relevant attribute display names and ids. * They will be automatically paired with the net id for further use by this search category. diff --git a/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts index 0b9ae5fe08..d58b188ddd 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts @@ -4,13 +4,14 @@ import {Operator} from '../operator/operator'; import {LoggerService} from '../../../logger/services/logger.service'; import {OperatorService} from '../../operator-service/operator.service'; import {OptionalDependencies} from '../../category-factory/optional-dependencies'; -import {Observable, Subject} from 'rxjs'; +import {Observable, of, Subject} from 'rxjs'; import {SearchAutocompleteOption} from './search-autocomplete-option'; import {Query} from '../query/query'; import {FormControl} from '@angular/forms'; import {ResourceTypeQueryPrefix} from "./resource-type-query-prefix"; import {take} from "rxjs/operators"; import {SimpleExpression} from "../../../pfql/model/simple-expression"; +import {IsNull} from "../operator/is-null"; export abstract class NoConfigurationUserAutocompleteCategory extends NoConfigurationAutocompleteCategory { @@ -34,11 +35,16 @@ export abstract class NoConfigurationUserAutocompleteCategory extends NoConfigur } protected generateQuery(userInput: Array>): Query { - if (this.selectedOperator.numberOfOperands !== 1) { - throw new Error(`Only unary operators are currently supported by the ${this._className} implementation`); + if (this.selectedOperator.numberOfOperands > 1) { + throw new Error(`Only unary or none operators are currently supported by the ${this._className} implementation`); + } + if (this.isSelectedOperator(IsNull)) { + return (this.selectedOperator as IsNull).createQuery(this.pfqlKeywords) + .addPrefixAndGet(this._resourceTypePrefix); + } else { + return this.selectedOperator.createQuery(this.pfqlKeywords, Array.isArray(userInput[0]) ? userInput[0] : userInput, false) + .addPrefixAndGet(this._resourceTypePrefix); } - return this.selectedOperator.createQuery(this.pfqlKeywords, Array.isArray(userInput[0]) ? userInput[0] : userInput, false) - .addPrefixAndGet(this._resourceTypePrefix); } protected serializeOperandValue(valueFormControl: FormControl): any { @@ -52,12 +58,14 @@ export abstract class NoConfigurationUserAutocompleteCategory extends NoConfigur public override loadFromPfqlExpression(expression: SimpleExpression): Observable { // todo 2466 check if expressionValue is valid object id hex string - const isDone$ = new Subject(); if (!this.selectOperatorFromPfqlExpression(expression)) { - isDone$.next(); - isDone$.complete(); - return isDone$.asObservable(); + return of(undefined); } + if (!expression.operandValue) { + this._generatedPredicate$.next(this.generatePredicate([])) + return of(undefined); + } + const isDone$ = new Subject(); const optionToBeSelected$ = this._userAutocomplete.getOptionFromExpressionValue$(expression.operandValue); optionToBeSelected$.pipe(take(1)).subscribe({ next: optionToBeSelected => { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts index 8177a6c70f..f2356ecb57 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts @@ -7,9 +7,11 @@ import {BooleanOperator} from '../../boolean-operator'; import {NoConfigurationAutocompleteCategory} from '../no-configuration-autocomplete-category'; import {NotEquals} from '../../operator/not-equals'; import {Categories} from '../categories'; -import {Observable, Subscription} from 'rxjs'; +import {Observable, of, Subject, Subscription} from 'rxjs'; import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; import {SimpleExpression} from "../../../../pfql/model/simple-expression"; +import {filter, take} from "rxjs/operators"; +import {SearchAutocompleteOption} from "../search-autocomplete-option"; export class TaskProcess extends NoConfigurationAutocompleteCategory { @@ -50,8 +52,29 @@ export class TaskProcess extends NoConfigurationAutocompleteCategory { } public override loadFromPfqlExpression(expression: SimpleExpression): Observable { - // todo 2466 - return undefined; + if (!this.selectOperatorFromPfqlExpression(expression)) { + return of(undefined); + } + const isDone$ = new Subject(); + this._options$.pipe( + filter(options => options.length > 0), + take(1) + ).subscribe(options => { + let selectedOption: SearchAutocompleteOption | undefined; + for (const option of options) { + if (option.value.some(netId => netId === expression.operandValue)) { + selectedOption = option; + break; + } + } + if (!!selectedOption) { + this.setOperands([selectedOption] as any); + } + isDone$.next(); + isDone$.complete(); + }) + + return isDone$.asObservable(); } protected generateQuery(userInput: Array>): Query { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts index 7a504e77a5..085c351937 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts @@ -8,6 +8,11 @@ import {Net} from '../../../../process/net'; import {NameIdPair} from '../name-id-pair'; import {Categories} from '../categories'; import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; +import {SimpleExpression} from "../../../../pfql/model/simple-expression"; +import {Observable, of, Subject} from "rxjs"; +import {filter, take} from "rxjs/operators"; +import {NetAttributePair} from "../net-attribute-pair"; +import {SearchAutocompleteOption} from "../search-autocomplete-option"; export class TaskTask extends TaskNetAttributeAutocompleteCategory { @@ -28,6 +33,33 @@ export class TaskTask extends TaskNetAttributeAutocompleteCategory { return petriNet.transitions.map(t => ({id: t.stringId, name: t.title})); } + public override loadFromPfqlExpression(expression: SimpleExpression): Observable { + if (!this.selectOperatorFromPfqlExpression(expression)) { + return of(undefined); + } + + const isDone$ = new Subject(); + this._options$.pipe( + filter(options => options.length > 0), + take(1) + ).subscribe(options => { + let selectedOption: SearchAutocompleteOption | undefined; + for (const option of options) { + if (option.value.some(pair => pair.attributeId === expression.operandValue)) { + selectedOption = option; + break; + } + } + if (!!selectedOption) { + this.setOperands([selectedOption] as any); + } + isDone$.next(); + isDone$.complete(); + }) + + return isDone$.asObservable(); + } + get inputPlaceholder(): string { return `${TaskTask._i18n}.placeholder`; } diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts index d75173c1d7..54f4453d82 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts @@ -392,6 +392,11 @@ export class SearchService implements OnDestroy { // todo 2466 na jednej urovni moze byt len jeden typ operatora const categoryLoadings$ = this.loadExpressionsIntoPredicate(this._rootPredicate, BooleanOperator.AND, queryItems); + if (categoryLoadings$.length === 0) { + this._loadingFromMetadata$.off(); + this.updateActiveFilter(); + return; + } forkJoin(categoryLoadings$).subscribe(() => { this._loadingFromMetadata$.off(); this.updateActiveFilter(); From f3041437ce4a32e0f8039429e73eace1e52e152f Mon Sep 17 00:00:00 2001 From: chvostek Date: Mon, 3 Aug 2026 18:22:21 +0200 Subject: [PATCH 16/55] [NAE-2466] Advanced search for PFQL - add documentation - resolve some todos - handle logged user placeholders --- .../src/lib/pfql/model/complex-expression.ts | 11 +- .../lib/pfql/model/data-simple-expression.ts | 8 +- .../src/lib/pfql/model/logical-operator.ts | 12 +- .../src/lib/pfql/model/simple-expression.ts | 6 +- .../src/lib/pfql/pfql-utils.ts | 63 +++- .../src/lib/pfql/pfql-visitor.ts | 328 ++++++++++++++++-- .../lib/search/models/category/category.ts | 20 +- ...onfiguration-user-autocomplete-category.ts | 1 - .../category/resource-type-query-prefix.ts | 6 +- .../lib/search/models/operator/operator.ts | 4 +- .../search/search-service/search.service.ts | 76 +++- 11 files changed, 481 insertions(+), 54 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts b/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts index 34e9f5285d..b0dde5193f 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts @@ -1,7 +1,16 @@ import {QueryItemInterface} from "./query-item-interface"; import {QueryItem, QueryItemType} from "./query-item-type"; -// todo 2466 +/** + * Represents a complex expression in a PFQL (Process Filter Query Language) query. + * + * A complex expression is a composite query item that contains multiple child query items + * (either simple expressions or other complex expressions) and can be negated. + * It is used to build hierarchical query structures with logical operations. + * + * The class supports negation push-down operations to optimize query execution by + * distributing negations to inner expressions. + */ export class ComplexExpression implements QueryItemInterface { protected _negated: boolean; protected _items: QueryItem[]; diff --git a/projects/netgrif-components-core/src/lib/pfql/model/data-simple-expression.ts b/projects/netgrif-components-core/src/lib/pfql/model/data-simple-expression.ts index b0a4effa57..89cc4504a8 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/data-simple-expression.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/data-simple-expression.ts @@ -2,7 +2,13 @@ import {SimpleExpression} from "./simple-expression"; import {Operator} from "../../search/models/operator/operator"; import {Category} from "../../search/models/category/category"; -// todo 2466 +/** + * Represents a simple expression that operates on data fields in PFQL queries. + * Extends SimpleExpression to provide data field-specific functionality. + * + * This class extracts and stores the data field identifier from a data field path, + * allowing for easy access to the field ID when constructing PFQL queries. + */ export class DataSimpleExpression extends SimpleExpression { protected _dataFieldId: string; diff --git a/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts b/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts index 438c8076ca..e94f365bae 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts @@ -2,7 +2,17 @@ import {QueryItemType} from "./query-item-type"; import {QueryItemInterface} from "./query-item-interface"; import {BooleanOperator} from "../../search/models/boolean-operator"; -// todo 2466 +/** + * Represents a logical operator (AND, OR, NOT) used in PFQL query construction. + * + * This class implements the {@link QueryItemInterface} and serves as a wrapper for {@link BooleanOperator} values, + * allowing them to be used as part of a query structure. Logical operators are used to combine multiple + * query conditions or predicates in a boolean expression. + * + * @see BooleanOperator for available operator types + * @see QueryItemInterface for the common interface of query items + * @see Query.combineQueries for usage example of combining queries with boolean operators + */ export class LogicalOperator implements QueryItemInterface { protected _value: BooleanOperator diff --git a/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts b/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts index f047fbad65..07f7bc9788 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts @@ -3,7 +3,11 @@ import {Operator} from "../../search/models/operator/operator"; import {QueryItemInterface} from "./query-item-interface"; import { QueryItemType } from "./query-item-type"; -// todo 2466 +/** + * Represents a simple PFQL expression consisting of a category, operator, operand value, and negation flag. + * A simple expression is a basic building block of PFQL queries that combines a search category with an operator + * and a value to create a single query condition. The expression can also be negated to invert its meaning. + */ export class SimpleExpression implements QueryItemInterface { protected _category: Category protected _operator: Operator diff --git a/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts b/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts index fdce657fec..ec1b69417d 100644 --- a/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts +++ b/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts @@ -26,23 +26,40 @@ import {MoreThanDateTime} from "../search/models/operator/more-than-date-time"; import {MoreThanEqualDateTime} from "../search/models/operator/more-than-equal-date-time"; import {LessThanDateTime} from "../search/models/operator/less-than-date-time"; import {LessThanEqualDateTime} from "../search/models/operator/less-than-equal-date-time"; +import {LoggerService} from "../logger/services/logger.service"; -// todo 2466 +/** + * Parses a PFQL query string into an array of query items. + * + * @param query - The PFQL query string to parse + * @param injector - Angular injector used for dependency injection during parsing + * @returns An array of QueryItem objects representing the parsed query structure + */ export function parseQuery(query: string, injector: Injector): Array { // todo 2466 injector as parameter? - // todo 2466 logging (also catch error) - const inputStream = CharStream.fromString(query); - const lexer = new QueryLangLexer(inputStream); - const tokenStream = new CommonTokenStream(lexer); - const parser = new QueryLangParser(tokenStream); - const tree = parser.query(); - const visitor = new PfqlVisitor(injector); - let items: Array = visitor.visit(tree); - // todo 2466 push down negations (also in sub-expressions) - return reduceComplexToSimpleExpressions(items); + const logger = injector.get(LoggerService); + try { + const inputStream = CharStream.fromString(query); + const lexer = new QueryLangLexer(inputStream); + const tokenStream = new CommonTokenStream(lexer); + const parser = new QueryLangParser(tokenStream); + const tree = parser.query(); + const visitor = new PfqlVisitor(injector); + let items: Array = visitor.visit(tree); + // todo 2466 push down negations (also in sub-expressions) + return reduceComplexToSimpleExpressions(items); + } catch (error) { + logger.error(`Could not parse PFQL query: ${error}`); + } } -// todo 2466 +/** + * Converts a lexer token into the corresponding operator instance for basic comparisons. + * Supports equality, inequality, substring, and relational operators. + * + * @param operatorToken - The token representing the operator, or null + * @returns The corresponding Operator instance, or undefined if the token is null or unrecognized + */ export function getOperatorFromToken(operatorToken: Token | null): Operator | undefined { if (operatorToken === null) { return undefined; @@ -67,7 +84,14 @@ export function getOperatorFromToken(operatorToken: Token | null): Operator } } -// todo 2466 +/** + * Converts a lexer token into the corresponding date-specific operator instance. + * Supports date equality, inequality, and relational operators. + * + * @param operatorToken - The token representing the operator, or null + * @param operatorService - Service providing operator-related functionality + * @returns The corresponding date Operator instance, or undefined if the token is null or unrecognized + */ export function getDateOperatorFromToken(operatorToken: Token | null, operatorService: OperatorService): Operator | undefined { if (operatorToken === null) { return undefined; @@ -90,7 +114,14 @@ export function getDateOperatorFromToken(operatorToken: Token | null, operatorSe } } -// todo 2466 +/** + * Converts a lexer token into the corresponding datetime-specific operator instance. + * Supports datetime equality, inequality, and relational operators. + * + * @param operatorToken - The token representing the operator, or null + * @param operatorService - Service providing operator-related functionality + * @returns The corresponding datetime Operator instance, or undefined if the token is null or unrecognized + */ export function getDateTimeOperatorFromToken(operatorToken: Token | null, operatorService: OperatorService): Operator | undefined { if (operatorToken === null) { return undefined; @@ -129,7 +160,3 @@ function reduceComplexToSimpleExpressions(items: Array): Array> { protected _logger: LoggerService; protected _operatorService: OperatorService protected _userResourceService: UserResourceService; + protected _userService: UserService; protected _categoryFactory: CategoryFactory; protected _allowedNetsService: AllowedNetsService; @@ -91,6 +103,7 @@ export class PfqlVisitor extends QueryLangVisitor> { this._logger = injector.get(LoggerService); this._operatorService = injector.get(OperatorService); this._userResourceService = injector.get(UserResourceService); + this._userService = injector.get(UserService); this._categoryFactory = injector.get(CategoryFactory); this._allowedNetsService = injector.get(AllowedNetsService); this._categoryOptionalDependencies = { @@ -101,7 +114,12 @@ export class PfqlVisitor extends QueryLangVisitor> { }; } - // todo 2466 doc + /** + * Visits the root case query context and extracts query items from case conditions. + * + * @param ctx - The case query parse tree context + * @returns An array of query items representing the case search criteria, or an empty array if no conditions are present + */ override visitCaseQuery = (ctx: CaseQueryContext): Array => { const conditionsAndPaging = ctx.caseConditionsAndPaging(); if (!conditionsAndPaging) { @@ -110,7 +128,12 @@ export class PfqlVisitor extends QueryLangVisitor> { return this.visit(conditionsAndPaging); }; - // todo 2466 doc + /** + * Visits the case conditions and paging context and extracts the case conditions. + * + * @param ctx - The case conditions and paging parse tree context + * @returns An array of query items representing the case conditions, or an empty array if no conditions are present + */ override visitCaseConditionsAndPaging = (ctx: CaseConditionsAndPagingContext): Array => { const conditions = ctx.caseConditions(); if (!conditions) { @@ -119,7 +142,12 @@ export class PfqlVisitor extends QueryLangVisitor> { return this.visit(conditions); }; - // todo 2466 doc + /** + * Visits the root task query context and extracts query items from task conditions. + * + * @param ctx - The task query parse tree context + * @returns An array of query items representing the task search criteria, or an empty array if no conditions are present + */ override visitTaskQuery = (ctx: TaskQueryContext): Array => { const conditionsAndPaging = ctx.taskConditionsAndPaging(); if (!conditionsAndPaging) { @@ -128,7 +156,12 @@ export class PfqlVisitor extends QueryLangVisitor> { return this.visit(conditionsAndPaging); }; - // todo 2466 doc + /** + * Visits the task conditions and paging context and extracts the task conditions. + * + * @param ctx - The task conditions and paging parse tree context + * @returns An array of query items representing the task conditions, or an empty array if no conditions are present + */ override visitTaskConditionsAndPaging = (ctx: TaskConditionsAndPagingContext): Array => { const conditions = ctx.taskConditions(); if (!conditions) { @@ -137,7 +170,12 @@ export class PfqlVisitor extends QueryLangVisitor> { return this.visit(conditions); }; - // todo 2466 doc + /** + * Visits a case OR expression and combines multiple AND expressions with OR logical operators. + * + * @param ctx - The case OR expression parse tree context + * @returns An array of query items with AND expressions joined by OR operators + */ override visitCaseOrExpression = (ctx: CaseOrExpressionContext): Array => { const andExpressionContexts = ctx.caseAndExpression(); const items: Array = [...this.visit(andExpressionContexts[0])]; @@ -148,7 +186,12 @@ export class PfqlVisitor extends QueryLangVisitor> { return items; }; - // todo 2466 doc + /** + * Visits a case AND expression and combines multiple condition groups with AND logical operators. + * + * @param ctx - The case AND expression parse tree context + * @returns An array of query items with condition groups joined by AND operators + */ override visitCaseAndExpression = (ctx: CaseAndExpressionContext): Array => { const conditionGroupContexts = ctx.caseConditionGroup(); const items: Array = [...this.visit(conditionGroupContexts[0])]; @@ -159,14 +202,25 @@ export class PfqlVisitor extends QueryLangVisitor> { return items; }; - // todo 2466 doc + /** + * Visits a parenthesized case condition group and wraps the inner conditions in a complex expression. + * Supports negation with the NOT keyword. + * + * @param ctx - The case condition group parenthesis parse tree context + * @returns An array containing a single complex expression with the inner conditions and negation flag + */ override visitCaseConditionGroupParenthesis = (ctx: CaseConditionGroupParenthesisContext): Array => { const innerItems: Array = [...this.visit(ctx.caseConditions())]; const isNegated: boolean = !!ctx.NOT(); return [new ComplexExpression(isNegated, innerItems)]; }; - // todo 2466 doc + /** + * Visits a task OR expression and combines multiple AND expressions with OR logical operators. + * + * @param ctx - The task OR expression parse tree context + * @returns An array of query items with AND expressions joined by OR operators + */ override visitTaskOrExpression = (ctx: TaskOrExpressionContext): Array => { const andExpressionContexts = ctx.taskAndExpression(); const items: Array = [...this.visit(andExpressionContexts[0])]; @@ -177,7 +231,12 @@ export class PfqlVisitor extends QueryLangVisitor> { return items; }; - // todo 2466 doc + /** + * Visits a task AND expression and combines multiple condition groups with AND logical operators. + * + * @param ctx - The task AND expression parse tree context + * @returns An array of query items with condition groups joined by AND operators + */ override visitTaskAndExpression = (ctx: TaskAndExpressionContext): Array => { const conditionGroupContexts = ctx.taskConditionGroup(); const items: Array = [...this.visit(conditionGroupContexts[0])]; @@ -188,13 +247,25 @@ export class PfqlVisitor extends QueryLangVisitor> { return items; }; - // todo 2466 doc + /** + * Visits a parenthesized task condition group and wraps the inner conditions in a complex expression. + * Supports negation with the NOT keyword. + * + * @param ctx - The task condition group parenthesis parse tree context + * @returns An array containing a single complex expression with the inner conditions and negation flag + */ override visitTaskConditionGroupParenthesis = (ctx: TaskConditionGroupParenthesisContext): Array => { const innerItems: Array = [...this.visit(ctx.taskConditions())]; const isNegated: boolean = !!ctx.NOT(); return [new ComplexExpression(isNegated, innerItems)]; }; + /** + * Visits a basic title comparison and creates a case title search expression. + * + * @param ctx - The title basic parse tree context + * @returns An array containing a single simple expression with case title category, or an empty array if no case comparison context exists + */ override visitTitleBasic = (ctx: TitleBasicContext): Array => { if (ctx.parent instanceof CaseComparisonsContext) { const expr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); @@ -206,6 +277,12 @@ export class PfqlVisitor extends QueryLangVisitor> { } }; + /** + * Visits a LIKE title comparison and creates a case title search expression with pattern matching. + * + * @param ctx - The title LIKE parse tree context + * @returns An array containing a single simple expression with case title category and LIKE operator, or an empty array if no case comparison context exists + */ override visitTitleLike = (ctx: TitleLikeContext): Array => { if (ctx.parent instanceof CaseComparisonsContext) { const expr: SimpleExpression = this.handleStringLikeComparisonContext(ctx.stringLikeComparison()); @@ -217,6 +294,12 @@ export class PfqlVisitor extends QueryLangVisitor> { } }; + /** + * Visits a basic ID comparison and creates a case string ID search expression. + * + * @param ctx - The ID basic parse tree context + * @returns An array containing a single simple expression with case string ID category, or an empty array if no case comparison context exists + */ override visitIdBasic = (ctx: IdBasicContext): Array => { if (ctx.parent instanceof CaseComparisonsContext) { const expr: SimpleExpression = this.handleObjectIdComparisonContext(ctx.objectIdComparison()); @@ -228,24 +311,48 @@ export class PfqlVisitor extends QueryLangVisitor> { } }; + /** + * Visits a basic author comparison and creates a case author search expression. + * + * @param ctx - The author basic parse tree context + * @returns An array containing a single simple expression with case author category + */ override visitAuthorBasic = (ctx: AuthorBasicContext): Array => { const expr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); expr.category = new CaseAuthor(this._operatorService, this._logger, this._categoryOptionalDependencies); return [expr]; }; + /** + * Visits a basic creation date comparison and creates a case creation date search expression. + * + * @param ctx - The creation date basic parse tree context + * @returns An array containing a single simple expression with case creation date category + */ override visitCdDateBasic = (ctx: CdDateBasicContext): Array => { const expr: SimpleExpression = this.handleDateComparisonContext(ctx.dateComparison()); expr.category = new CaseCreationDate(this._operatorService, this._logger); return [expr]; }; + /** + * Visits a basic creation datetime comparison and creates a case creation datetime search expression. + * + * @param ctx - The creation datetime basic parse tree context + * @returns An array containing a single simple expression with case creation datetime category + */ override visitCdDateTimeBasic = (ctx: CdDateTimeBasicContext): Array => { const expr: SimpleExpression = this.handleDateTimeComparisonContext(ctx.dateTimeComparison()); expr.category = new CaseCreationDateTime(this._operatorService, this._logger); return [expr]; }; + /** + * Visits a creation date range comparison and creates either a date or datetime range search expression. + * + * @param ctx - The creation date range parse tree context + * @returns An array containing a single simple expression with either case creation date or datetime category, or an empty array if no range values are provided + */ override visitCdDateRange = (ctx: CdDateRangeContext): Array => { const inRangeCtx = ctx.inRangeDateComparison(); if (!!inRangeCtx.dateRange()) { @@ -262,6 +369,12 @@ export class PfqlVisitor extends QueryLangVisitor> { } }; + /** + * Visits a data string comparison and creates a data field search expression for string values. + * + * @param ctx - The data string parse tree context + * @returns An array containing a single data simple expression with case dataset category + */ override visitDataString = (ctx: DataStringContext): Array => { const simpleExpr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, @@ -270,6 +383,12 @@ export class PfqlVisitor extends QueryLangVisitor> { return [dataExpr]; }; + /** + * Visits a data string LIKE comparison and creates a data field search expression with pattern matching for string values. + * + * @param ctx - The data string LIKE parse tree context + * @returns An array containing a single data simple expression with case dataset category and LIKE operator + */ override visitDataStringLike = (ctx: DataStringLikeContext): Array => { const simpleExpr: SimpleExpression = this.handleStringLikeComparisonContext(ctx.stringLikeComparison()); const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, @@ -278,6 +397,12 @@ export class PfqlVisitor extends QueryLangVisitor> { return [dataExpr]; }; + /** + * Visits a data number comparison and creates a data field search expression for numeric values. + * + * @param ctx - The data number parse tree context + * @returns An array containing a single data simple expression with case dataset category + */ override visitDataNumber = (ctx: DataNumberContext): Array => { const simpleExpr: SimpleExpression = this.handleNumberComparisonContext(ctx.numberComparison()); const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, @@ -286,6 +411,12 @@ export class PfqlVisitor extends QueryLangVisitor> { return [dataExpr]; }; + /** + * Visits a data number range comparison and creates a data field search expression for numeric range values. + * + * @param ctx - The data number range parse tree context + * @returns An array containing a single data simple expression with case dataset category and range operator + */ override visitDataNumberRange = (ctx: DataNumberRangeContext): Array => { const simpleExpr: SimpleExpression = this.handleInRangeNumberComparisonContext(ctx.inRangeNumberComparison()); const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, @@ -294,6 +425,12 @@ export class PfqlVisitor extends QueryLangVisitor> { return [dataExpr]; }; + /** + * Visits a data date comparison and creates a data field search expression for date values. + * + * @param ctx - The data date parse tree context + * @returns An array containing a single data simple expression with case dataset category + */ override visitDataDate = (ctx: DataDateContext): Array => { const simpleExpr: SimpleExpression = this.handleDateComparisonContext(ctx.dateComparison()); const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, @@ -302,6 +439,12 @@ export class PfqlVisitor extends QueryLangVisitor> { return [dataExpr]; }; + /** + * Visits a data date range comparison and creates a data field search expression for date or datetime range values. + * + * @param ctx - The data date range parse tree context + * @returns An array containing a single data simple expression with case dataset category and range operator, or an empty array if no range values are provided + */ override visitDataDateRange = (ctx: DataDateRangeContext): Array => { const inRangeCtx = ctx.inRangeDateComparison(); let simpleExpr: SimpleExpression; @@ -320,6 +463,12 @@ export class PfqlVisitor extends QueryLangVisitor> { return [dataExpr]; }; + /** + * Visits a data datetime comparison and creates a data field search expression for datetime values. + * + * @param ctx - The data datetime parse tree context + * @returns An array containing a single data simple expression with case dataset category + */ override visitDataDatetime = (ctx: DataDatetimeContext): Array => { const simpleExpr: SimpleExpression = this.handleDateTimeComparisonContext(ctx.dateTimeComparison()); const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, @@ -328,6 +477,12 @@ export class PfqlVisitor extends QueryLangVisitor> { return [dataExpr]; }; + /** + * Visits a data boolean comparison and creates a data field search expression for boolean values. + * + * @param ctx - The data boolean parse tree context + * @returns An array containing a single data simple expression with case dataset category + */ override visitDataBoolean = (ctx: DataBooleanContext): Array => { const simpleExpr: SimpleExpression = this.handleBooleanComparisonContext(ctx.booleanComparison()); const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, @@ -336,6 +491,12 @@ export class PfqlVisitor extends QueryLangVisitor> { return [dataExpr]; }; + /** + * Visits a data null comparison and creates a data field search expression for null checks. + * + * @param ctx - The data null parse tree context + * @returns An array containing a single data simple expression with case dataset category and null operator + */ override visitDataNull = (ctx: DataNullContext): Array => { const simpleExpr: SimpleExpression = this.handleNullComparisonContext(ctx.nullComparison()); const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, @@ -346,30 +507,60 @@ export class PfqlVisitor extends QueryLangVisitor> { // todo 2466 user field comparison ? ... ak je v string comparison mongo id, tak je to mozno user id? + /** + * Visits a basic process identifier comparison and creates a case process search expression. + * + * @param ctx - The process identifier basic parse tree context + * @returns An array containing a single simple expression with case process category + */ override visitProcessIdentifierBasic = (ctx: ProcessIdentifierBasicContext): Array => { const expr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); expr.category = new CaseProcess(this._operatorService, this._logger, this._categoryOptionalDependencies); return [expr]; }; + /** + * Visits a basic transition ID comparison and creates a task task search expression. + * + * @param ctx - The transition ID basic parse tree context + * @returns An array containing a single simple expression with task task category + */ override visitTransitionIdBasic = (ctx: TransitionIdBasicContext): Array => { const expr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); expr.category = new TaskTask(this._operatorService, this._logger, this._categoryOptionalDependencies); return [expr]; } + /** + * Visits a basic user ID comparison and creates a task assignee search expression. + * + * @param ctx - The user ID basic parse tree context + * @returns An array containing a single simple expression with task assignee category + */ override visitUserIdBasic = (ctx: UserIdBasicContext): Array => { const expr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); expr.category = new TaskAssignee(this._operatorService, this._logger, this._categoryOptionalDependencies); return [expr]; }; + /** + * Visits a user ID null comparison and creates a task assignee search expression for null checks. + * + * @param ctx - The user ID null parse tree context + * @returns An array containing a single simple expression with task assignee category and null operator + */ override visitUserIdNull = (ctx: UserIdNullContext): Array => { const expr: SimpleExpression = this.handleNullComparisonContext(ctx.nullComparison()); expr.category = new TaskAssignee(this._operatorService, this._logger, this._categoryOptionalDependencies); return [expr]; }; + /** + * Visits a basic process ID comparison for tasks and creates a task process search expression. + * + * @param ctx - The process ID basic parse tree context + * @returns An array containing a single simple expression with task process category + */ override visitProcessIdBasic = (ctx: ProcessIdBasicContext): Array => { const expr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); expr.category = new TaskProcess(this._operatorService, this._logger, this._categoryOptionalDependencies); @@ -378,20 +569,61 @@ export class PfqlVisitor extends QueryLangVisitor> { // todo 2466 implement handler dispatcher? + /** + * Handles a string comparison context and creates a simple expression with the appropriate operator and value. + * + * @param ctx - The string comparison parse tree context + * @returns A simple expression with the extracted operator, string value, and negation flag + */ protected handleStringComparisonContext(ctx: StringComparisonContext): SimpleExpression { const operator: Operator = getOperatorFromToken(ctx._op); - const value: string = this.removeSingleQuotesFromString(ctx.STRING()?.getText()); - // todo 2466 handle logged user placeholder + const value: string = this.extractStringValueFromStringComparisonContext(ctx); return new SimpleExpression(operator, value, !!ctx.NOT()); }; + /** + * Handles a string LIKE comparison context and creates a simple expression with the LIKE operator. + * + * @param ctx - The string LIKE comparison parse tree context + * @returns A simple expression with the LIKE operator, extracted string value, and negation flag + */ protected handleStringLikeComparisonContext(ctx: StringLikeComparisonContext): SimpleExpression { const operator: Operator = new Like(); - const value: string = this.removeSingleQuotesFromString(ctx.stringComparison().STRING()?.getText()); - // todo 2466 handle logged user placeholder + const value: string = this.extractStringValueFromStringComparisonContext(ctx.stringComparison()); return new SimpleExpression(operator, value, !!ctx.stringComparison().NOT()); }; + /** + * Extracts the string value from a string comparison context, handling both logged user attributes and literal strings. + * + * @param ctx - The string comparison parse tree context + * @returns The extracted string value, either from logged user attributes or from a quoted string literal + */ + protected extractStringValueFromStringComparisonContext(ctx: StringComparisonContext): string { + let value: string; + if (!!ctx.loggedUserStringAttribute()) { + const loggedUserCtx = ctx.loggedUserStringAttribute(); + const user = this._userService.user; + if (!!loggedUserCtx.LOGGED_USER_ID()) { + value = user?.id; + } else if (!!loggedUserCtx.LOGGED_USER_FULLNAME()) { + value = user?.fullName; + } else if (!!loggedUserCtx.LOGGED_USER_USERNAME()) { + value = user?.email; + } + } + if (!value) { + value = this.removeSingleQuotesFromString(ctx.STRING()?.getText()); + } + return value; + } + + /** + * Removes single quotes from the beginning and end of a string if they are present. + * + * @param value - The string value that may be enclosed in single quotes + * @returns The string with single quotes removed, or the original string if not enclosed in quotes + */ protected removeSingleQuotesFromString(value: string): string { if (value && value.length >= 2 && value.startsWith("'") && value.endsWith("'")) { return value.substring(1, value.length - 1); @@ -399,37 +631,75 @@ export class PfqlVisitor extends QueryLangVisitor> { return value; } + /** + * Handles an object ID comparison context and creates a simple expression with the appropriate operator and ID value. + * + * @param ctx - The object ID comparison parse tree context + * @returns A simple expression with the extracted operator, object ID value (either logged user ID or string literal), and negation flag + */ protected handleObjectIdComparisonContext(ctx: ObjectIdComparisonContext): SimpleExpression { const operator: Operator = getOperatorFromToken(ctx._op); - const value: string = this.removeSingleQuotesFromString(ctx.STRING()?.getText()) - // todo 2466 handle logged user id placeholder + const value: string = !!ctx.LOGGED_USER_ID() ? this._userService.user?.id + : this.removeSingleQuotesFromString(ctx.STRING()?.getText()); return new SimpleExpression(operator, value, !!ctx.NOT()); } + /** + * Handles a date comparison context and creates a simple expression with the appropriate date operator and date value. + * + * @param ctx - The date comparison parse tree context + * @returns A simple expression with the date operator, extracted date value, and negation flag + */ protected handleDateComparisonContext(ctx: DateComparisonContext): SimpleExpression { const operator: Operator = getDateOperatorFromToken(ctx._op, this._operatorService); const value: string = ctx.DATE()?.getText(); return new SimpleExpression(operator, value, !!ctx.NOT()); } + /** + * Handles a datetime comparison context and creates a simple expression with the appropriate datetime operator and datetime value. + * + * @param ctx - The datetime comparison parse tree context + * @returns A simple expression with the datetime operator, extracted datetime value, and negation flag + */ protected handleDateTimeComparisonContext(ctx: DateTimeComparisonContext): SimpleExpression { const operator: Operator = getDateTimeOperatorFromToken(ctx._op, this._operatorService); const value: string = ctx.DATETIME()?.getText(); return new SimpleExpression(operator, value, !!ctx.NOT()); } + /** + * Handles a date range context and creates a simple expression with the InRangeDate operator and date range values. + * + * @param ctx - The date range parse tree context + * @param isNegated - Whether the range comparison is negated + * @returns A simple expression with the InRangeDate operator, array of date values, and negation flag + */ protected handleDateRangeContext(ctx: DateRangeContext, isNegated: boolean): SimpleExpression { const operator: Operator = new InRangeDate(); const value: string[] = ctx.DATE()?.map(terminalNode => terminalNode.getText()); return new SimpleExpression(operator, value, isNegated); } + /** + * Handles a datetime range context and creates a simple expression with the InRangeDateTime operator and datetime range values. + * + * @param ctx - The datetime range parse tree context + * @param isNegated - Whether the range comparison is negated + * @returns A simple expression with the InRangeDateTime operator, array of datetime values, and negation flag + */ protected handleDateTimeRangeContext(ctx: DateTimeRangeContext, isNegated: boolean): SimpleExpression { const operator: Operator = new InRangeDateTime(); const value: string[] = ctx.DATETIME()?.map(terminalNode => terminalNode.getText()); return new SimpleExpression(operator, value, isNegated); } + /** + * Handles a number comparison context and creates a simple expression with the appropriate operator and numeric value. + * + * @param ctx - The number comparison parse tree context + * @returns A simple expression with the extracted operator, numeric value (integer or double), and negation flag + */ protected handleNumberComparisonContext(ctx: NumberComparisonContext): SimpleExpression { const operator: Operator = getOperatorFromToken(ctx._op); let value: number; @@ -441,6 +711,12 @@ export class PfqlVisitor extends QueryLangVisitor> { return new SimpleExpression(operator, value, !!ctx.NOT()); } + /** + * Handles a number range comparison context and creates a simple expression with the InRange operator and numeric range values. + * + * @param ctx - The in-range number comparison parse tree context + * @returns A simple expression with the InRange operator, array of numeric values (integer or double range), and negation flag + */ protected handleInRangeNumberComparisonContext(ctx: InRangeNumberComparisonContext): SimpleExpression { const operator: Operator = new InRange(); let fromValue: number, toValue: number; @@ -454,16 +730,26 @@ export class PfqlVisitor extends QueryLangVisitor> { return new SimpleExpression(operator, [fromValue, toValue], !!ctx.NOT()); } + /** + * Handles a boolean comparison context and creates a simple expression with the appropriate operator and boolean value. + * + * @param ctx - The boolean comparison parse tree context + * @returns A simple expression with the extracted operator, boolean value, and negation flag + */ protected handleBooleanComparisonContext(ctx: BooleanComparisonContext): SimpleExpression { const operator: Operator = getOperatorFromToken(ctx._op); const value: boolean = ctx.BOOLEAN().getText().toLowerCase() === 'true'; return new SimpleExpression(operator, value, !!ctx.NOT()); } + /** + * Handles a null comparison context and creates a simple expression with the IsNull operator. + * + * @param ctx - The null comparison parse tree context + * @returns A simple expression with the IsNull operator, undefined value, and negation flag + */ protected handleNullComparisonContext(ctx: NullComparisonContext): SimpleExpression { const operator: Operator = new IsNull(); return new SimpleExpression(operator, undefined, !!ctx.NOT()); } - - // todo 2466 more handle methods } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/category.ts b/projects/netgrif-components-core/src/lib/search/models/category/category.ts index aade1ad6bb..18d1b7df6b 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/category.ts @@ -424,7 +424,15 @@ export abstract class Category { return result$.asObservable(); } - // todo 2466 + /** + * Loads the category state from a PFQL expression. + * + * This method attempts to select an operator based on the expression's operator type and then sets the operands + * from the expression's operand values. If the operator cannot be selected, the method returns immediately. + * + * @param expression the PFQL simple expression containing the operator and operand values + * @returns an Observable that emits void when the loading is complete + */ public loadFromPfqlExpression(expression: SimpleExpression): Observable { if (!this.selectOperatorFromPfqlExpression(expression)) { return of(undefined); @@ -433,10 +441,18 @@ export abstract class Category { return of(undefined); } + /** + * Selects an operator from the category's allowed operators based on the PFQL expression's operator type. + * + * This method searches for an operator in the allowed operators array that matches the type specified in the + * PFQL expression. If a matching operator is found, it is selected. If no match is found, an error is logged. + * + * @param expression the PFQL simple expression containing the operator type to select + * @returns `true` if a matching operator was found and selected, `false` otherwise + */ protected selectOperatorFromPfqlExpression(expression: SimpleExpression): boolean { const operatorIdx: number = this.allowedOperators.findIndex(op => op.type === expression.operator.type); if (operatorIdx === -1) { - // todo 2466 log also category this._log.error(`Operator '${expression.operator.type}' is unavailable for this category`); return false; } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts index d58b188ddd..4a84c2e2e2 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts @@ -57,7 +57,6 @@ export abstract class NoConfigurationUserAutocompleteCategory extends NoConfigur } public override loadFromPfqlExpression(expression: SimpleExpression): Observable { - // todo 2466 check if expressionValue is valid object id hex string if (!this.selectOperatorFromPfqlExpression(expression)) { return of(undefined); } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/resource-type-query-prefix.ts b/projects/netgrif-components-core/src/lib/search/models/category/resource-type-query-prefix.ts index 29a5f19fcf..7166867e68 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/resource-type-query-prefix.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/resource-type-query-prefix.ts @@ -3,7 +3,11 @@ */ export enum ResourceTypeQueryPrefix { CASES = 'cases', + CASE = 'case', TASKS = 'tasks', + TASK = 'task', PROCESSES = 'processes', - USERS = 'users' + PROCESS = 'process', + USERS = 'users', + USER = 'user' } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts b/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts index 30a196e67a..5b3822f4ac 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts @@ -42,7 +42,9 @@ export abstract class Operator { */ private readonly _operatorSymbols: string; - // todo 2466 + /** + * Type of the current operator + */ private readonly _type: Operators; protected constructor(numberOfOperands: number, type: Operators, operatorSymbols = '') { diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts index 54f4453d82..eed0e48397 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts @@ -24,6 +24,7 @@ import {parseQuery} from "../../pfql/pfql-utils"; import {LogicalOperator} from "../../pfql/model/logical-operator"; import {SimpleExpression} from "../../pfql/model/simple-expression"; import {ComplexExpression} from "../../pfql/model/complex-expression"; +import {ResourceTypeQueryPrefix} from "../models/category/resource-type-query-prefix"; /** * Holds information about the filter that is currently applied to the view component, that provides this services. @@ -377,9 +378,24 @@ export class SearchService implements OnDestroy { }); } - // todo 2466 + /** + * Loads a PFQL query string into the search service's predicate tree structure. + * + * Parses the provided PFQL query and reconstructs the predicate tree from it. + * The query resource type must match the filter type of this search service. + * All existing predicates (including hidden ones) are cleared before loading the new query. + * + * @param query the PFQL query string to parse and load into the predicate tree + */ public loadFromPfql(query: string) { - // todo 2466 validate query prefix with filter type + if (!query) { + this._log.warn("No query was provided. Cannot load the filter"); + return; + } + if (!this.validateQueryResourceType(query)) { + this._log.error("Query resource type is of wrong type"); + return; + } this.clearPredicates(true); this._loadingFromMetadata$.on(); @@ -389,8 +405,6 @@ export class SearchService implements OnDestroy { return; } - // todo 2466 na jednej urovni moze byt len jeden typ operatora - const categoryLoadings$ = this.loadExpressionsIntoPredicate(this._rootPredicate, BooleanOperator.AND, queryItems); if (categoryLoadings$.length === 0) { this._loadingFromMetadata$.off(); @@ -403,6 +417,18 @@ export class SearchService implements OnDestroy { }); } + /** + * Validates that the resource type prefix in the PFQL query matches the filter type of this search service. + * + * @param query the PFQL query string to validate + * @returns `true` if the query's resource type prefix matches the search service's filter type, `false` otherwise + */ + protected validateQueryResourceType(query: string): boolean { + const filterType = this.baseFilter.type; + return filterType === FilterType.CASE ? query.startsWith(ResourceTypeQueryPrefix.CASES) || query.startsWith(ResourceTypeQueryPrefix.CASE) + : query.startsWith(ResourceTypeQueryPrefix.TASKS) || query.startsWith(ResourceTypeQueryPrefix.TASK); + } + /** * @returns an Array of filter text segments that correspond to the currently displayed completed predicates */ @@ -410,6 +436,17 @@ export class SearchService implements OnDestroy { return this._rootPredicate.createFilterTextSegments(); } + /** + * Recursively loads query items (expressions and operators) into a predicate tree node. + * + * Processes simple expressions by loading them into predicates (creating branch predicates for AND operators), + * and recursively handles complex expressions by creating new nested predicates. + * + * @param predicate the predicate node into which the expressions should be loaded + * @param operatorOfPredicate the boolean operator used by the predicate node + * @param items the array of query items (expressions and operators) to process + * @returns an array of observables that emit when category data is loaded for each simple expression + */ protected loadExpressionsIntoPredicate(predicate: EditableClausePredicateWithGenerators, operatorOfPredicate: BooleanOperator, items: Array): Array> { const expressions: Array = items.filter(item => item.type() !== QueryItemType.LOGICAL_OPERATOR); @@ -427,13 +464,21 @@ export class SearchService implements OnDestroy { categoryLoadings$.push(categoryLoading$); } else if (expression.type() === QueryItemType.COMPLEX_EXPRESSION) { this.loadFromQueryItemsIntoNewPredicate(predicate, (expression as ComplexExpression).items); - } else { - // todo 2466 warn ignoring } } return categoryLoadings$; } + /** + * Creates a new branch predicate under the parent and loads query items into it. + * + * Determines the appropriate boolean operator from the query items, creates a new clause predicate + * with that operator, and recursively loads the expressions into the new predicate. + * + * @param parentPredicate the parent predicate under which to create the new branch + * @param items the array of query items to load into the new predicate branch + * @returns an array of observables that emit when category data is loaded for each simple expression + */ protected loadFromQueryItemsIntoNewPredicate(parentPredicate: EditableClausePredicateWithGenerators, items: Array): Array> { const booleanOperator: BooleanOperator = this.determineBooleanOperator(items); @@ -442,11 +487,30 @@ export class SearchService implements OnDestroy { return this.loadExpressionsIntoPredicate(branchPredicate, booleanOperator, items); } + /** + * Determines the boolean operator to use for combining query items. + * + * Extracts logical operators from the query items array. If no logical operators are found, + * defaults to AND. If logical operators are present, uses the first one found. + * + * @param items the array of query items to examine + * @returns the boolean operator (AND or OR) determined from the query items + */ protected determineBooleanOperator(items: Array): BooleanOperator { const booleanOperators = items.filter(item => item.type() === QueryItemType.LOGICAL_OPERATOR); return booleanOperators.length === 0 ? BooleanOperator.AND : (booleanOperators[0] as LogicalOperator).value; } + /** + * Loads a simple PFQL expression into a predicate node. + * + * Extracts the category from the simple expression, loads the expression data into the category, + * and adds the category as a new predicate generator to the given predicate node. + * + * @param predicate the predicate node into which the simple expression should be loaded + * @param simpleExpr the simple expression to load + * @returns an observable that emits when the category data has been loaded from the expression + */ protected loadSimpleExpressionIntoPredicate(predicate: EditableClausePredicateWithGenerators, simpleExpr: SimpleExpression): Observable { const category: Category = simpleExpr.category; const categoryLoading$: Observable = category.loadFromPfqlExpression(simpleExpr); From 1f1ad218a7938a87a3036e28dd2818383fa772dd Mon Sep 17 00:00:00 2001 From: chvostek Date: Mon, 3 Aug 2026 19:22:41 +0200 Subject: [PATCH 17/55] [NAE-2466] Advanced search for PFQL - implement negations for simple expressions --- .../src/lib/pfql/model/complex-expression.ts | 10 ++++-- .../src/lib/pfql/model/logical-operator.ts | 4 +++ .../src/lib/pfql/model/negatable.ts | 5 +++ .../lib/pfql/model/query-item-interface.ts | 2 ++ .../src/lib/pfql/model/simple-expression.ts | 36 +++++++++++++++---- .../src/lib/pfql/pfql-utils.ts | 9 ++++- .../models/operator/equals-date-time.ts | 9 +++-- .../lib/search/models/operator/equals-date.ts | 9 +++-- .../src/lib/search/models/operator/equals.ts | 6 ++++ .../models/operator/in-range-date-time.ts | 4 +++ .../search/models/operator/in-range-date.ts | 4 +++ .../lib/search/models/operator/in-range.ts | 4 +++ .../src/lib/search/models/operator/is-null.ts | 4 +++ .../models/operator/less-than-date-time.ts | 9 +++-- .../search/models/operator/less-than-date.ts | 9 +++-- .../operator/less-than-equal-date-time.ts | 9 +++-- .../models/operator/less-than-equal-date.ts | 8 +++-- .../search/models/operator/less-than-equal.ts | 5 ++- .../lib/search/models/operator/less-than.ts | 5 +++ .../src/lib/search/models/operator/like.ts | 4 +++ .../models/operator/more-than-date-time.ts | 9 +++-- .../search/models/operator/more-than-date.ts | 9 +++-- .../operator/more-than-equal-date-time.ts | 9 +++-- .../models/operator/more-than-equal-date.ts | 8 +++-- .../search/models/operator/more-than-equal.ts | 5 ++- .../lib/search/models/operator/more-than.ts | 5 +++ .../models/operator/not-equals-date-time.ts | 8 +++-- .../search/models/operator/not-equals-date.ts | 8 +++-- .../lib/search/models/operator/not-equals.ts | 5 +++ .../lib/search/models/operator/operator.ts | 3 ++ .../lib/search/models/operator/substring.ts | 4 +++ 31 files changed, 191 insertions(+), 37 deletions(-) create mode 100644 projects/netgrif-components-core/src/lib/pfql/model/negatable.ts diff --git a/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts b/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts index b0dde5193f..1d10f4b25a 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts @@ -1,5 +1,6 @@ import {QueryItemInterface} from "./query-item-interface"; import {QueryItem, QueryItemType} from "./query-item-type"; +import {Negatable} from "./negatable"; /** * Represents a complex expression in a PFQL (Process Filter Query Language) query. @@ -11,7 +12,7 @@ import {QueryItem, QueryItemType} from "./query-item-type"; * The class supports negation push-down operations to optimize query execution by * distributing negations to inner expressions. */ -export class ComplexExpression implements QueryItemInterface { +export class ComplexExpression implements QueryItemInterface, Negatable { protected _negated: boolean; protected _items: QueryItem[]; @@ -40,8 +41,13 @@ export class ComplexExpression implements QueryItemInterface { return this._negated; } - // todo 2466 + public isNegatable(): boolean { + return true; + } + + // todo 2466 doc public pushDownNegation(): void { + // todo 2466 // negate inner expressions // set _negated to false } diff --git a/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts b/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts index e94f365bae..263d94398a 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts @@ -27,4 +27,8 @@ export class LogicalOperator implements QueryItemInterface { public get value(): BooleanOperator { return this._value; } + + public isNegatable(): boolean { + return false; + } } diff --git a/projects/netgrif-components-core/src/lib/pfql/model/negatable.ts b/projects/netgrif-components-core/src/lib/pfql/model/negatable.ts new file mode 100644 index 0000000000..4f59cb5c32 --- /dev/null +++ b/projects/netgrif-components-core/src/lib/pfql/model/negatable.ts @@ -0,0 +1,5 @@ + +// todo 2466 doc +export interface Negatable { + pushDownNegation(): void; +} diff --git a/projects/netgrif-components-core/src/lib/pfql/model/query-item-interface.ts b/projects/netgrif-components-core/src/lib/pfql/model/query-item-interface.ts index d3670b7e03..727f12ddf3 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/query-item-interface.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/query-item-interface.ts @@ -1,5 +1,7 @@ import {QueryItemType} from "./query-item-type"; +// todo 2466 doc export interface QueryItemInterface { type(): QueryItemType; + isNegatable(): boolean; } diff --git a/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts b/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts index 07f7bc9788..8af117fa2f 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts @@ -2,13 +2,14 @@ import {Category} from "../../search/models/category/category"; import {Operator} from "../../search/models/operator/operator"; import {QueryItemInterface} from "./query-item-interface"; import { QueryItemType } from "./query-item-type"; +import {Negatable} from "./negatable"; /** * Represents a simple PFQL expression consisting of a category, operator, operand value, and negation flag. * A simple expression is a basic building block of PFQL queries that combines a search category with an operator * and a value to create a single query condition. The expression can also be negated to invert its meaning. */ -export class SimpleExpression implements QueryItemInterface { +export class SimpleExpression implements QueryItemInterface, Negatable { protected _category: Category protected _operator: Operator protected _operandValue: any; @@ -45,15 +46,38 @@ export class SimpleExpression implements QueryItemInterface { return this._negated; } - // todo 2466 + public isNegatable(): boolean { + return true; + } + + /** + * Pushes down the negation flag by converting it into an operator negation. + * If the expression is negated, this method clears the negation flag and inverts the operator instead. + * This normalization ensures that negation is represented consistently at the operator level rather than + * at the expression level. If the expression is not negated, this method does nothing. + */ + public pushDownNegation() { + if (!this.negated) { + return; + } + this._negated = false; + this.negate(); + } + + /** + * Toggles the negation of this expression. + * If the expression is currently negated (flag is true), clears the negation flag. + * Otherwise, inverts the operator to its negated form if an operator is present. + * @throws {Error} if the expression has no operator or cannot be negated + */ public negate(): void { if (!!this._negated) { this._negated = false; return; } - // todo 2466 - // possible only if operator is: EQ, NEQ, GT, GTE, LT, LTE - // throw if operator is: Substring, IN RANGE - // throw if calculated operator is: NEQ null + if (!this.operator) { + throw new Error("Expression cannot be negated. There is no operator"); + } + this._operator = this._operator.negated(); } } diff --git a/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts b/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts index ec1b69417d..1ede2e0fc8 100644 --- a/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts +++ b/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts @@ -27,6 +27,7 @@ import {MoreThanEqualDateTime} from "../search/models/operator/more-than-equal-d import {LessThanDateTime} from "../search/models/operator/less-than-date-time"; import {LessThanEqualDateTime} from "../search/models/operator/less-than-equal-date-time"; import {LoggerService} from "../logger/services/logger.service"; +import {Negatable} from "./model/negatable"; /** * Parses a PFQL query string into an array of query items. @@ -45,8 +46,9 @@ export function parseQuery(query: string, injector: Injector): Array const parser = new QueryLangParser(tokenStream); const tree = parser.query(); const visitor = new PfqlVisitor(injector); + let items: Array = visitor.visit(tree); - // todo 2466 push down negations (also in sub-expressions) + pushDownNegations(items); return reduceComplexToSimpleExpressions(items); } catch (error) { logger.error(`Could not parse PFQL query: ${error}`); @@ -160,3 +162,8 @@ function reduceComplexToSimpleExpressions(items: Array): Array): void { + items.filter(item => item.isNegatable()) + .forEach(item => (item as Negatable).pushDownNegation()); +} diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/equals-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/equals-date-time.ts index a94432d7de..c9f7de2f02 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/equals-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/equals-date-time.ts @@ -4,6 +4,7 @@ import {Moment} from 'moment'; import {Query} from '../query/query'; import {Operator} from './operator'; import {Operators} from './operators'; +import {NotEqualsDateTime} from "./not-equals-date-time"; /** * Equality operator for indexed fields that store a date time object in timestamp format. @@ -15,9 +16,9 @@ export class EqualsDateTime extends Operator { protected dateTimeRange: InRangeDateTime; - constructor(operators: OperatorService) { + constructor(protected _operators: OperatorService) { super(1, Operators.EQUALS_DATE_TIME); - this.dateTimeRange = operators.getOperator(InRangeDateTime) as InRangeDateTime; + this.dateTimeRange = this._operators.getOperator(InRangeDateTime) as InRangeDateTime; } createQuery(pfqlKeywords: Array, args: Array): Query { @@ -32,4 +33,8 @@ export class EqualsDateTime extends Operator { serialize(): Operators | string { return Operators.EQUALS_DATE_TIME; } + + override negated(): Operator { + return new NotEqualsDateTime(this._operators); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/equals-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/equals-date.ts index f3a3c7ffa1..953f8661a4 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/equals-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/equals-date.ts @@ -4,6 +4,7 @@ import {Query} from '../query/query'; import {OperatorService} from '../../operator-service/operator.service'; import {InRangeDate} from './in-range-date'; import {Operators} from './operators'; +import {NotEqualsDate} from "./not-equals-date"; /** * Equality operator for indexed fields that store a date in timestamp format. @@ -15,9 +16,9 @@ export class EqualsDate extends Operator { protected dateRange: InRangeDate; - constructor(operators: OperatorService) { + constructor(protected _operators: OperatorService) { super(1, Operators.EQUALS_DATE); - this.dateRange = operators.getOperator(InRangeDate) as InRangeDate; + this.dateRange = this._operators.getOperator(InRangeDate) as InRangeDate; } createQuery(pfqlKeywords: Array, args: Array): Query { @@ -32,4 +33,8 @@ export class EqualsDate extends Operator { serialize(): Operators | string { return Operators.EQUALS_DATE; } + + negated(): Operator { + return new NotEqualsDate(this._operators); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/equals.ts b/projects/netgrif-components-core/src/lib/search/models/operator/equals.ts index 5c969ad0af..23e1945e21 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/equals.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/equals.ts @@ -1,5 +1,6 @@ import {Operator} from './operator'; import {Operators} from './operators'; +import {NotEquals} from "./not-equals"; /** * Strict equality operator. Will match if the field has the exact same value as the input. @@ -20,4 +21,9 @@ export class Equals extends Operator { serialize(): Operators | string { return Operators.EQUALS; } + + negated(): Operator { + return new NotEquals(); + } + } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date-time.ts index 17ba88c6fc..9fdfcc24c4 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date-time.ts @@ -43,4 +43,8 @@ export class InRangeDateTime extends Operator { serialize(): Operators | string { return Operators.IN_RANGE_DATE_TIME; } + + negated(): Operator { + throw new Error("Operator InRangeDateTime cannot be negated"); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date.ts index ac5b6e0d88..dd5306a2dc 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date.ts @@ -40,4 +40,8 @@ export class InRangeDate extends Operator { serialize(): Operators | string { return Operators.IN_RANGE_DATE; } + + negated(): Operator { + throw new Error("Operator InRangeDate cannot be negated"); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/in-range.ts b/projects/netgrif-components-core/src/lib/search/models/operator/in-range.ts index 182f015508..f706d32ee5 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/in-range.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/in-range.ts @@ -22,4 +22,8 @@ export class InRange extends Operator { serialize(): Operators | string { return Operators.IN_RANGE; } + + negated(): Operator { + throw new Error("Operator InRange cannot be negated"); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/is-null.ts b/projects/netgrif-components-core/src/lib/search/models/operator/is-null.ts index 741fa706f9..e75dbae8c9 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/is-null.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/is-null.ts @@ -74,4 +74,8 @@ export class IsNull extends Operator { serialize(): Operators | string { return Operators.IS_NULL; } + + negated(): Operator { + throw new Error("Operator IsNull cannot be negated"); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date-time.ts index e9c7841aa4..86254459ec 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date-time.ts @@ -4,6 +4,7 @@ import {LessThan} from './less-than'; import {OperatorService} from '../../operator-service/operator.service'; import {Query} from '../query/query'; import {Operators} from './operators'; +import {MoreThanEqualDateTime} from "./more-than-equal-date-time"; /** * A strict less than operator for DateTime fields @@ -12,9 +13,9 @@ export class LessThanDateTime extends Operator { protected lessThan: LessThan; - constructor(operators: OperatorService) { + constructor(protected _operators: OperatorService) { super(1, Operators.LESS_THAN_DATE_TIME); - this.lessThan = operators.getOperator(LessThan) as LessThan; + this.lessThan = this._operators.getOperator(LessThan) as LessThan; } createQuery(pfqlKeywords: Array, args: Array): Query { @@ -32,4 +33,8 @@ export class LessThanDateTime extends Operator { serialize(): Operators | string { return Operators.LESS_THAN_DATE_TIME; } + + negated(): Operator { + return new MoreThanEqualDateTime(this._operators); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date.ts index b646133b7c..b2913a282b 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date.ts @@ -4,6 +4,7 @@ import {OperatorService} from '../../operator-service/operator.service'; import {Query} from '../query/query'; import {LessThan} from './less-than'; import {Operators} from './operators'; +import {MoreThanEqualDate} from "./more-than-equal-date"; /** * A strict less than operator for Date fields @@ -12,9 +13,9 @@ export class LessThanDate extends Operator { protected lessThan: LessThan; - constructor(operators: OperatorService) { + constructor(protected _operators: OperatorService) { super(1, Operators.LESS_THAN_DATE); - this.lessThan = operators.getOperator(LessThan) as LessThan; + this.lessThan = this._operators.getOperator(LessThan) as LessThan; } createQuery(pfqlKeywords: Array, args: Array): Query { @@ -30,4 +31,8 @@ export class LessThanDate extends Operator { serialize(): Operators | string { return Operators.LESS_THAN_DATE; } + + negated(): Operator { + return new MoreThanEqualDate(this._operators); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date-time.ts index 51bbf51c0a..fa42ed6d37 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date-time.ts @@ -4,6 +4,7 @@ import {LessThanEqual} from './less-than-equal'; import {OperatorService} from '../../operator-service/operator.service'; import {Operators} from './operators'; import {Query} from '../query/query'; +import {MoreThanDateTime} from "./more-than-date-time"; /** * Less or equal than operator for Datetime fields @@ -12,9 +13,9 @@ export class LessThanEqualDateTime extends Operator { protected lessThanEqual: LessThanEqual; - constructor(operators: OperatorService) { + constructor(protected _operators: OperatorService) { super(1, Operators.LESS_THAN_EQUAL_DATE_TIME); - this.lessThanEqual = operators.getOperator(LessThanEqual) as LessThanEqual; + this.lessThanEqual = this._operators.getOperator(LessThanEqual) as LessThanEqual; } createQuery(pfqlKeywords: Array, args: Array): Query { @@ -33,5 +34,7 @@ export class LessThanEqualDateTime extends Operator { return Operators.LESS_THAN_DATE_TIME; } - + negated(): Operator { + return new MoreThanDateTime(this._operators); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date.ts index 6b4a4fa4aa..96da873516 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date.ts @@ -4,6 +4,7 @@ import {OperatorService} from '../../operator-service/operator.service'; import {Query} from '../query/query'; import {Operators} from './operators'; import {LessThanDate} from './less-than-date'; +import {MoreThanDate} from "./more-than-date"; /** * Less or equal than operator for Date fields @@ -12,9 +13,9 @@ export class LessThanEqualDate extends Operator { protected lessThan: LessThanDate; - constructor(operators: OperatorService) { + constructor(protected _operators: OperatorService) { super(1, Operators.LESS_THAN_EQUAL_DATE); - this.lessThan = operators.getOperator(LessThanDate) as LessThanDate; + this.lessThan = this._operators.getOperator(LessThanDate) as LessThanDate; } createQuery(pfqlKeywords: Array, args: Array): Query { @@ -32,4 +33,7 @@ export class LessThanEqualDate extends Operator { return Operators.LESS_THAN_EQUAL_DATE; } + negated(): Operator { + return new MoreThanDate(this._operators); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal.ts index eb22166f23..201e1c3c83 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal.ts @@ -1,5 +1,6 @@ import {Operator} from './operator'; import {Operators} from './operators'; +import {MoreThan} from "./more-than"; /** * Less or equal than operator for numeric or string fields @@ -18,5 +19,7 @@ export class LessThanEqual extends Operator { return Operators.LESS_THAN_EQUAL; } - + negated(): Operator { + return new MoreThan(); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than.ts index 3c07dfaeec..dd8eead751 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than.ts @@ -1,5 +1,6 @@ import {Operator} from './operator'; import {Operators} from './operators'; +import {MoreThanEqual} from "./more-than-equal"; /** * A strict less than operator for numeric or string fields. @@ -16,4 +17,8 @@ export class LessThan extends Operator { serialize(): Operators | string { return Operators.LESS_THAN; } + + negated(): Operator { + return new MoreThanEqual(); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/like.ts b/projects/netgrif-components-core/src/lib/search/models/operator/like.ts index c848d00b3c..21a07be461 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/like.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/like.ts @@ -28,4 +28,8 @@ export class Like extends Operator { serialize(): Operators | string { return Operators.LIKE; } + + negated(): Operator { + throw new Error("Operator Like cannot be negated"); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date-time.ts index 4e1870c7bb..ab37944aa9 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date-time.ts @@ -4,6 +4,7 @@ import {MoreThan} from './more-than'; import {OperatorService} from '../../operator-service/operator.service'; import {Query} from '../query/query'; import {Operators} from './operators'; +import {LessThanEqualDateTime} from "./less-than-equal-date-time"; /** * A strict greater than operator for DateTime fields @@ -12,9 +13,9 @@ export class MoreThanDateTime extends Operator { protected moreThan: MoreThan; - constructor(operators: OperatorService) { + constructor(protected _operators: OperatorService) { super(1, Operators.MORE_THAN_DATE_TIME); - this.moreThan = operators.getOperator(MoreThan) as MoreThan; + this.moreThan = this._operators.getOperator(MoreThan) as MoreThan; } createQuery(pfqlKeywords: Array, args: Array): Query { @@ -34,4 +35,8 @@ export class MoreThanDateTime extends Operator { serialize(): Operators | string { return Operators.MORE_THAN_DATE_TIME; } + + negated(): Operator { + return new LessThanEqualDateTime(this._operators); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date.ts index bb7c47b5f3..fdef6a8fb0 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date.ts @@ -4,6 +4,7 @@ import {Query} from '../query/query'; import {MoreThan} from './more-than'; import moment, {Moment} from 'moment'; import {Operators} from './operators'; +import {LessThanEqualDate} from "./less-than-equal-date"; /** * A strict greater than operator for Date fields @@ -12,9 +13,9 @@ export class MoreThanDate extends Operator { protected moreThan: MoreThan; - constructor(operators: OperatorService) { + constructor(protected _operators: OperatorService) { super(1, Operators.MORE_THAN_DATE); - this.moreThan = operators.getOperator(MoreThan) as MoreThan; + this.moreThan = this._operators.getOperator(MoreThan) as MoreThan; } createQuery(pfqlKeywords: Array, args: Array): Query { @@ -32,4 +33,8 @@ export class MoreThanDate extends Operator { serialize(): Operators | string { return Operators.MORE_THAN_DATE; } + + negated(): Operator { + return new LessThanEqualDate(this._operators); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date-time.ts index f7ad79b54a..bf83f05a8e 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date-time.ts @@ -4,6 +4,7 @@ import {MoreThanEqual} from './more-than-equal'; import {OperatorService} from '../../operator-service/operator.service'; import {Operators} from './operators'; import {Query} from '../query/query'; +import {LessThanDateTime} from "./less-than-date-time"; /** * Greater or equal than operator for Datetime fields @@ -12,9 +13,9 @@ export class MoreThanEqualDateTime extends Operator { protected moreThanEqual: MoreThanEqual; - constructor(operators: OperatorService) { + constructor(protected _operators: OperatorService) { super(1, Operators.MORE_THAN_EQUAL_DATE_TIME); - this.moreThanEqual = operators.getOperator(MoreThanEqual) as MoreThanEqual; + this.moreThanEqual = this._operators.getOperator(MoreThanEqual) as MoreThanEqual; } createQuery(pfqlKeywords: Array, args: Array): Query { @@ -33,5 +34,7 @@ export class MoreThanEqualDateTime extends Operator { return Operators.MORE_THAN_EQUAL_DATE_TIME; } - + negated(): Operator { + return new LessThanDateTime(this._operators); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date.ts index 71a73ec0fc..c7c16e1cd0 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date.ts @@ -4,6 +4,7 @@ import {OperatorService} from '../../operator-service/operator.service'; import {MoreThanEqual} from './more-than-equal'; import {Operators} from './operators'; import {Query} from '../query/query'; +import {LessThanDate} from "./less-than-date"; /** * Greater or equal than operator for Date fields @@ -12,9 +13,9 @@ export class MoreThanEqualDate extends Operator { protected moreThanEqual: MoreThanEqual; - constructor(operators: OperatorService) { + constructor(protected _operators: OperatorService) { super(1, Operators.MORE_THAN_EQUAL_DATE); - this.moreThanEqual = operators.getOperator(MoreThanEqual) as MoreThanEqual; + this.moreThanEqual = this._operators.getOperator(MoreThanEqual) as MoreThanEqual; } createQuery(pfqlKeywords: Array, args: Array): Query { @@ -31,4 +32,7 @@ export class MoreThanEqualDate extends Operator { return Operators.MORE_THAN_EQUAL_DATE; } + negated(): Operator { + return new LessThanDate(this._operators); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal.ts index d2503e1f0a..6bcc08a594 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal.ts @@ -1,5 +1,6 @@ import {Operator} from './operator'; import {Operators} from './operators'; +import {LessThan} from "./less-than"; /** * Greater or equal than operator for numeric or string fields @@ -18,5 +19,7 @@ export class MoreThanEqual extends Operator { return Operators.LESS_THAN_EQUAL; } - + negated(): Operator { + return new LessThan(); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than.ts index 34de7437aa..b29ac052aa 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than.ts @@ -1,5 +1,6 @@ import {Operator} from './operator'; import {Operators} from './operators'; +import {LessThanEqual} from "./less-than-equal"; /** * A strict greater than operator for numeric or string fields. @@ -16,4 +17,8 @@ export class MoreThan extends Operator { serialize(): Operators | string { return Operators.MORE_THAN; } + + negated(): Operator { + return new LessThanEqual(); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date-time.ts index bd88a1658f..fd6cbd6eb8 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date-time.ts @@ -9,9 +9,9 @@ export class NotEqualsDateTime extends Operator { protected equals: EqualsDateTime; - constructor(operators: OperatorService) { + constructor(protected _operators: OperatorService) { super(1, Operators.NOT_EQUALS_DATE_TIME); - this.equals = operators.getOperator(EqualsDateTime) as EqualsDateTime; + this.equals = this._operators.getOperator(EqualsDateTime) as EqualsDateTime; } createQuery(pfqlKeywords: Array, args: Array): Query { @@ -29,4 +29,8 @@ export class NotEqualsDateTime extends Operator { serialize(): Operators | string { return Operators.NOT_EQUALS_DATE_TIME; } + + negated(): Operator { + return new EqualsDateTime(this._operators); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date.ts index bcde5e8bec..94dbdde641 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date.ts @@ -12,9 +12,9 @@ export class NotEqualsDate extends Operator { protected equals: EqualsDate; - constructor(operators: OperatorService) { + constructor(protected _operators: OperatorService) { super(1, Operators.NOT_EQUALS_DATE); - this.equals = operators.getOperator(EqualsDate) as EqualsDate; + this.equals = this._operators.getOperator(EqualsDate) as EqualsDate; } createQuery(pfqlKeywords: Array, args: Array): Query { @@ -32,4 +32,8 @@ export class NotEqualsDate extends Operator { serialize(): Operators | string { return Operators.NOT_EQUALS_DATE; } + + negated(): Operator { + return new EqualsDate(this._operators); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals.ts b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals.ts index 100b41f5a7..5ca75f93cc 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals.ts @@ -1,5 +1,6 @@ import {Operator} from './operator'; import {Operators} from './operators'; +import {Equals} from "./equals"; /** * Inequality operator. Will match if the field has a different value than the input. @@ -19,4 +20,8 @@ export class NotEquals extends Operator { serialize(): Operators | string { return Operators.NOT_EQUALS; } + + negated(): Operator { + return new Equals(); + } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts b/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts index 5b3822f4ac..71d4163bd2 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts @@ -57,6 +57,9 @@ export abstract class Operator { return this._type; } + // todo 2466 doc + public abstract negated(): Operator; + /** * Escapes all escapable Elasticsearch symbols. Removes all unescapable Elasticsearch symbols. * diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/substring.ts b/projects/netgrif-components-core/src/lib/search/models/operator/substring.ts index b30d22a8fa..ee403860a5 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/substring.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/substring.ts @@ -17,4 +17,8 @@ export class Substring extends Operator { serialize(): Operators | string { return Operators.SUBSTRING; } + + negated(): Operator { + throw new Error("Operator Substring cannot be negated"); + } } From 0978b8bd5109f76c6e781685561bb0a580ecb870 Mon Sep 17 00:00:00 2001 From: chvostek Date: Tue, 4 Aug 2026 10:04:30 +0200 Subject: [PATCH 18/55] [NAE-2466] Advanced search for PFQL - implement negations for complex expressions --- .../src/lib/pfql/model/complex-expression.ts | 43 ++++++++++++++++--- .../src/lib/pfql/model/logical-operator.ts | 5 +++ .../src/lib/pfql/model/negatable.ts | 1 + 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts b/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts index 1d10f4b25a..58933b0a7e 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts @@ -1,6 +1,7 @@ import {QueryItemInterface} from "./query-item-interface"; import {QueryItem, QueryItemType} from "./query-item-type"; import {Negatable} from "./negatable"; +import {LogicalOperator} from "./logical-operator"; /** * Represents a complex expression in a PFQL (Process Filter Query Language) query. @@ -25,10 +26,6 @@ export class ComplexExpression implements QueryItemInterface, Negatable { return QueryItemType.COMPLEX_EXPRESSION; } - public pushItems(items: QueryItem[]) { - this._items.push(...items); - } - public get items(): QueryItem[] { return this._items; } @@ -47,8 +44,40 @@ export class ComplexExpression implements QueryItemInterface, Negatable { // todo 2466 doc public pushDownNegation(): void { - // todo 2466 - // negate inner expressions - // set _negated to false + this.pushDownNegationForInnerItems(); + this._negated = false; // must be set after the push-down call + } + + // todo 2466 doc + public negate(): void { + if (this._negated) { + this._negated = false; // forces push-down for items + this.pushDownNegationForInnerItems(); + return; + } + this.negateInnerItems(); + } + + // todo 2466 doc + protected pushDownNegationForInnerItems(): void { + for (const item of this._items) { + if (!item.isNegatable()) { + continue + } + const expression: Negatable = item as Negatable; + this._negated ? expression.negate() : expression.pushDownNegation(); + } + } + + // todo 2466 doc + protected negateInnerItems(): void { + for (let item of this._items) { + if (item.type() === QueryItemType.LOGICAL_OPERATOR) { + item = (item as LogicalOperator).opposite(); // todo 2466 test: vymeni to referenciu v poli? + } else if (item.isNegatable()) { + const expression = item as Negatable; + expression.negate(); + } + } } } diff --git a/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts b/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts index 263d94398a..e6add4eda4 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts @@ -31,4 +31,9 @@ export class LogicalOperator implements QueryItemInterface { public isNegatable(): boolean { return false; } + + // todo 2466 doc + public opposite(): LogicalOperator { + return this.value === BooleanOperator.OR ? new LogicalOperator(BooleanOperator.AND) : new LogicalOperator(BooleanOperator.OR); + } } diff --git a/projects/netgrif-components-core/src/lib/pfql/model/negatable.ts b/projects/netgrif-components-core/src/lib/pfql/model/negatable.ts index 4f59cb5c32..af2dec4ee7 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/negatable.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/negatable.ts @@ -2,4 +2,5 @@ // todo 2466 doc export interface Negatable { pushDownNegation(): void; + negate(): void } From 17baf36e18be0ad69f6dfcda7eabd13c5a22d960 Mon Sep 17 00:00:00 2001 From: chvostek Date: Tue, 4 Aug 2026 17:19:35 +0200 Subject: [PATCH 19/55] [NAE-2466] Advanced search for PFQL - fix negations in complex-expression.ts - fix reducing complex expressions in pfql-utils.ts --- .../src/lib/pfql/model/complex-expression.ts | 17 ++++++++++------- .../src/lib/pfql/pfql-utils.ts | 7 +++++++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts b/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts index 58933b0a7e..ce05bc7706 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts @@ -60,20 +60,23 @@ export class ComplexExpression implements QueryItemInterface, Negatable { // todo 2466 doc protected pushDownNegationForInnerItems(): void { - for (const item of this._items) { - if (!item.isNegatable()) { - continue + for (let i = 0; i < this._items.length; i++) { + const item = this._items[i]; + if (this._negated && item.type() === QueryItemType.LOGICAL_OPERATOR) { + this._items[i] = (item as LogicalOperator).opposite(); + } else if (item.isNegatable()) { + const expression: Negatable = item as Negatable; + this._negated ? expression.negate() : expression.pushDownNegation(); } - const expression: Negatable = item as Negatable; - this._negated ? expression.negate() : expression.pushDownNegation(); } } // todo 2466 doc protected negateInnerItems(): void { - for (let item of this._items) { + for (let i = 0; i < this._items.length; i++) { + const item = this._items[i]; if (item.type() === QueryItemType.LOGICAL_OPERATOR) { - item = (item as LogicalOperator).opposite(); // todo 2466 test: vymeni to referenciu v poli? + this._items[i] = (item as LogicalOperator).opposite(); } else if (item.isNegatable()) { const expression = item as Negatable; expression.negate(); diff --git a/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts b/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts index 1ede2e0fc8..87e7369674 100644 --- a/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts +++ b/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts @@ -147,6 +147,9 @@ export function getDateTimeOperatorFromToken(operatorToken: Token | null, operat } function reduceComplexToSimpleExpressions(items: Array): Array { + if (isSingleComplexExpr(items)) { + items = (items[0] as ComplexExpression).items; + } return items?.map(queryItem => { if (queryItem.type() === QueryItemType.COMPLEX_EXPRESSION) { const complexExpr: ComplexExpression = queryItem as ComplexExpression; @@ -163,6 +166,10 @@ function canBeReducedToSimpleExpr(complexExpr: ComplexExpression): boolean { return !!complexExpr.items && complexExpr.items.length === 1 && complexExpr.items[0]?.type() === QueryItemType.SIMPLE_EXPRESSION; } +function isSingleComplexExpr(items: Array): boolean { + return !!items && items.length === 1 && items[0].type() === QueryItemType.COMPLEX_EXPRESSION; +} + function pushDownNegations(items: Array): void { items.filter(item => item.isNegatable()) .forEach(item => (item as Negatable).pushDownNegation()); From 066261949a4ef14bb6871dc0142102e09f61d4cf Mon Sep 17 00:00:00 2001 From: chvostek Date: Wed, 5 Aug 2026 14:54:35 +0200 Subject: [PATCH 20/55] [NAE-2466] Advanced search for PFQL - fix handling simple ORs - fix await for category loadings --- .../search/search-service/search.service.ts | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts index eed0e48397..72372060cf 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts @@ -405,7 +405,7 @@ export class SearchService implements OnDestroy { return; } - const categoryLoadings$ = this.loadExpressionsIntoPredicate(this._rootPredicate, BooleanOperator.AND, queryItems); + const categoryLoadings$ = this.loadFromQueryItemsIntoRootPredicate(queryItems); if (categoryLoadings$.length === 0) { this._loadingFromMetadata$.off(); this.updateActiveFilter(); @@ -463,7 +463,9 @@ export class SearchService implements OnDestroy { } categoryLoadings$.push(categoryLoading$); } else if (expression.type() === QueryItemType.COMPLEX_EXPRESSION) { - this.loadFromQueryItemsIntoNewPredicate(predicate, (expression as ComplexExpression).items); + const subCategoryLoadings$: Array> = this.loadFromQueryItemsIntoNewPredicate(predicate, + (expression as ComplexExpression).items); + categoryLoadings$.push(...subCategoryLoadings$); } } return categoryLoadings$; @@ -481,12 +483,33 @@ export class SearchService implements OnDestroy { */ protected loadFromQueryItemsIntoNewPredicate(parentPredicate: EditableClausePredicateWithGenerators, items: Array): Array> { + if (!this.areBooleanOperatorsOfSingleType(items)) { + throw new Error("Cannot load the PFQL query. There are different boolean operators in the same group of expressions") + } const booleanOperator: BooleanOperator = this.determineBooleanOperator(items); const branchId = parentPredicate.addNewClausePredicate(booleanOperator); const branchPredicate = parentPredicate.getPredicateMap().get(branchId).getWrappedPredicate() as unknown as EditableClausePredicateWithGenerators return this.loadExpressionsIntoPredicate(branchPredicate, booleanOperator, items); } + /** + * todo 2466 doc + */ + protected loadFromQueryItemsIntoRootPredicate(items: Array): Array> { + if (!this.areBooleanOperatorsOfSingleType(items)) { + throw new Error("Cannot load the PFQL query. There are different boolean operators in the same group of expressions") + } + const booleanOperator: BooleanOperator = this.determineBooleanOperator(items); + let targetPredicate = this.rootPredicate; + + if (booleanOperator === BooleanOperator.OR) { + const branchId = this.rootPredicate.addNewClausePredicate(booleanOperator); + targetPredicate = this.rootPredicate.getPredicateMap().get(branchId).getWrappedPredicate() as unknown as EditableClausePredicateWithGenerators + } + + return this.loadExpressionsIntoPredicate(targetPredicate, booleanOperator, items); + } + /** * Determines the boolean operator to use for combining query items. * @@ -517,4 +540,11 @@ export class SearchService implements OnDestroy { predicate.addNewPredicateFromGenerator(category); return categoryLoading$; } + + protected areBooleanOperatorsOfSingleType(items: Array): boolean { + const operators: Array = items.filter(item => item.type() === QueryItemType.LOGICAL_OPERATOR) + .map(operator => operator as LogicalOperator); + + return operators.length === 0 || operators.every(op => op.value === operators[0].value); + } } From 445e7222d941ccafac5518e446e2009e50306532 Mon Sep 17 00:00:00 2001 From: chvostek Date: Wed, 5 Aug 2026 15:39:57 +0200 Subject: [PATCH 21/55] [NAE-2466] Advanced search for PFQL - flat query items if the boolean operator is the same as parent predicate's boolean operator --- .../src/lib/search/search-service/search.service.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts index 72372060cf..6dd0057a5f 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts @@ -464,7 +464,7 @@ export class SearchService implements OnDestroy { categoryLoadings$.push(categoryLoading$); } else if (expression.type() === QueryItemType.COMPLEX_EXPRESSION) { const subCategoryLoadings$: Array> = this.loadFromQueryItemsIntoNewPredicate(predicate, - (expression as ComplexExpression).items); + operatorOfPredicate, (expression as ComplexExpression).items); categoryLoadings$.push(...subCategoryLoadings$); } } @@ -478,15 +478,20 @@ export class SearchService implements OnDestroy { * with that operator, and recursively loads the expressions into the new predicate. * * @param parentPredicate the parent predicate under which to create the new branch + * @param operatorOfParentPredicate boolean operator of the parentPredicate * @param items the array of query items to load into the new predicate branch * @returns an array of observables that emit when category data is loaded for each simple expression */ protected loadFromQueryItemsIntoNewPredicate(parentPredicate: EditableClausePredicateWithGenerators, + operatorOfParentPredicate: BooleanOperator, items: Array): Array> { if (!this.areBooleanOperatorsOfSingleType(items)) { throw new Error("Cannot load the PFQL query. There are different boolean operators in the same group of expressions") } const booleanOperator: BooleanOperator = this.determineBooleanOperator(items); + if (operatorOfParentPredicate === booleanOperator) { + return this.loadExpressionsIntoPredicate(parentPredicate, booleanOperator, items); + } const branchId = parentPredicate.addNewClausePredicate(booleanOperator); const branchPredicate = parentPredicate.getPredicateMap().get(branchId).getWrappedPredicate() as unknown as EditableClausePredicateWithGenerators return this.loadExpressionsIntoPredicate(branchPredicate, booleanOperator, items); From 3b9249c8db5089ae803dc396d5c6ea71cd64218b Mon Sep 17 00:00:00 2001 From: chvostek Date: Wed, 5 Aug 2026 15:48:13 +0200 Subject: [PATCH 22/55] [NAE-2466] Advanced search for PFQL - add docs --- .../src/lib/pfql/model/complex-expression.ts | 34 ++++++++++++++++--- .../src/lib/pfql/model/logical-operator.ts | 12 ++++++- .../src/lib/pfql/model/negatable.ts | 34 +++++++++++++++++-- .../lib/pfql/model/query-item-interface.ts | 25 +++++++++++++- .../lib/search/models/operator/operator.ts | 13 ++++++- .../search/search-service/search.service.ts | 10 +++++- 6 files changed, 118 insertions(+), 10 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts b/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts index ce05bc7706..a974769a10 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts @@ -42,13 +42,26 @@ export class ComplexExpression implements QueryItemInterface, Negatable { return true; } - // todo 2466 doc + /** + * Pushes down the negation flag to child items in the expression tree. + * If the expression is negated, this method propagates the negation to all child items + * by negating them and converting logical operators to their opposites (AND <-> OR). + * After propagation, the negation flag on this expression is cleared. + * This normalization ensures that negation is represented at the leaf level rather than + * at the complex expression level, which can optimize query execution. + */ public pushDownNegation(): void { this.pushDownNegationForInnerItems(); this._negated = false; // must be set after the push-down call } - // todo 2466 doc + /** + * Toggles the negation state of this complex expression. + * If the expression is currently negated, clears the negation flag and pushes down + * the negation to child items. If the expression is not negated, negates all child items + * and converts logical operators to their opposites without setting the negation flag. + * This method applies De Morgan's laws to maintain logical equivalence. + */ public negate(): void { if (this._negated) { this._negated = false; // forces push-down for items @@ -58,7 +71,14 @@ export class ComplexExpression implements QueryItemInterface, Negatable { this.negateInnerItems(); } - // todo 2466 doc + /** + * Propagates negation to all child items in this complex expression. + * For each child item: + * - If this expression is negated and the child is a logical operator, replaces it with its opposite (AND <-> OR) + * - If the child is negatable and this expression is negated, negates the child + * - If the child is negatable and this expression is not negated, recursively pushes down negation on the child + * This method is called internally to distribute negation throughout the expression tree. + */ protected pushDownNegationForInnerItems(): void { for (let i = 0; i < this._items.length; i++) { const item = this._items[i]; @@ -71,7 +91,13 @@ export class ComplexExpression implements QueryItemInterface, Negatable { } } - // todo 2466 doc + /** + * Negates all child items in this complex expression without setting the negation flag. + * For each child item: + * - If the child is a logical operator, replaces it with its opposite (AND <-> OR) + * - If the child is negatable (simple or complex expression), negates it + * This method is used to apply De Morgan's laws when negating the entire complex expression. + */ protected negateInnerItems(): void { for (let i = 0; i < this._items.length; i++) { const item = this._items[i]; diff --git a/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts b/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts index e6add4eda4..8b926a15dd 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts @@ -32,7 +32,17 @@ export class LogicalOperator implements QueryItemInterface { return false; } - // todo 2466 doc + /** + * Returns the logical opposite of the current operator. + * + * This method returns a new LogicalOperator instance with the opposite boolean operator: + * - If the current operator is OR, returns AND + * - If the current operator is AND, returns OR + * + * Note: This method does not handle the NOT operator as it operates only on binary operators (AND/OR). + * + * @returns a new LogicalOperator instance with the opposite operator value + */ public opposite(): LogicalOperator { return this.value === BooleanOperator.OR ? new LogicalOperator(BooleanOperator.AND) : new LogicalOperator(BooleanOperator.OR); } diff --git a/projects/netgrif-components-core/src/lib/pfql/model/negatable.ts b/projects/netgrif-components-core/src/lib/pfql/model/negatable.ts index af2dec4ee7..df6e37f48f 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/negatable.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/negatable.ts @@ -1,6 +1,36 @@ - -// todo 2466 doc +/** + * Interface for query items that support negation operations in PFQL queries. + * + * This interface provides two approaches to negation: + * - Direct negation via {@link negate}, which toggles the negation state + * - Negation push-down via {@link pushDownNegation}, which distributes negation to child items + * + * Push-down negation is an optimization technique that moves negation closer to leaf expressions, + * applying De Morgan's laws to flip logical operators (AND ↔ OR) when necessary. + * + * @see ComplexExpression for implementation example + * @see QueryItemInterface.isNegatable for checking if an item supports negation + */ export interface Negatable { + /** + * Pushes negation down to child query items and clears the negation flag on this item. + * + * This method distributes negation to inner expressions and flips logical operators + * according to De Morgan's laws (AND becomes OR, OR becomes AND). After execution, + * the negation state of this item is cleared. + * + * This is typically called during query optimization to simplify the query structure. + */ pushDownNegation(): void; + + /** + * Toggles or applies negation to this query item. + * + * The behavior depends on the current negation state: + * - If not negated: applies negation by flipping logical operators and negating child items + * - If already negated: clears negation and pushes it down to child items instead + * + * This method is used when constructing or modifying queries to express NOT conditions. + */ negate(): void } diff --git a/projects/netgrif-components-core/src/lib/pfql/model/query-item-interface.ts b/projects/netgrif-components-core/src/lib/pfql/model/query-item-interface.ts index 727f12ddf3..7a79fa6d00 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/query-item-interface.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/query-item-interface.ts @@ -1,7 +1,30 @@ import {QueryItemType} from "./query-item-type"; -// todo 2466 doc +/** + * Base interface for all items that can be part of a PFQL (Process Filter Query Language) query structure. + * + * This interface defines the common contract for query components, including simple expressions, + * complex expressions, and logical operators. Each query item has a type and may or may not + * support negation operations. + * + * @see QueryItemType for available query item types + * @see ComplexExpression for composite query items + * @see LogicalOperator for boolean operators in queries + */ export interface QueryItemInterface { + /** + * Returns the type of this query item. + * + * @returns The {@link QueryItemType} enum value indicating whether this is a simple expression, + * complex expression, or logical operator. + */ type(): QueryItemType; + + /** + * Indicates whether this query item supports negation operations. + * + * @returns `true` if this item implements {@link Negatable} and can be negated, `false` otherwise. + * Logical operators typically return `false`, while expressions return `true`. + */ isNegatable(): boolean; } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts b/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts index 71d4163bd2..f815f0603c 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts @@ -57,7 +57,18 @@ export abstract class Operator { return this._type; } - // todo 2466 doc + /** + * Returns a new operator instance that represents the logical negation of this operator. + * + * This method creates a negated version of the current operator, which can be used to + * construct inverse queries. For example, an "equals" operator would return a "not equals" + * operator, and vice versa. + * + * The returned operator should have the same arity as the original but produce logically + * opposite query results when applied to the same arguments. + * + * @returns a new Operator instance that represents the negation of this operator + */ public abstract negated(): Operator; /** diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts index 6dd0057a5f..c0299894f8 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts @@ -498,7 +498,15 @@ export class SearchService implements OnDestroy { } /** - * todo 2466 doc + * Loads query items into the root predicate of the search service. + * + * Validates that all boolean operators in the query items are of the same type (all AND or all OR). + * Determines the appropriate boolean operator from the items and loads expressions accordingly. + * If the operator is OR, creates a new branch predicate under the root; otherwise loads directly into root. + * + * @param items the array of query items (expressions and operators) to load into the root predicate + * @returns an array of observables that emit when category data is loaded for each simple expression + * @throws Error if the query items contain different boolean operator types in the same group */ protected loadFromQueryItemsIntoRootPredicate(items: Array): Array> { if (!this.areBooleanOperatorsOfSingleType(items)) { From a5814bcac6de5a4d133f0ea796e491df0b033646 Mon Sep 17 00:00:00 2001 From: chvostek Date: Thu, 6 Aug 2026 07:56:56 +0200 Subject: [PATCH 23/55] [NAE-2466] Advanced search for PFQL - fix redundant requests to BE when initializing advanced search --- .../search/search-service/search.service.ts | 43 +++++++++++++++---- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts index c0299894f8..599d718ca8 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts @@ -7,7 +7,7 @@ import {SimpleFilter} from '../../filter/models/simple-filter'; import {MergeOperator} from '../../filter/models/merge-operator'; import {PredicateRemovalEvent} from '../models/predicate-removal-event'; import {Query} from '../models/query/query'; -import {distinctUntilChanged, map, tap} from 'rxjs/operators'; +import {distinctUntilChanged, map, tap, filter} from 'rxjs/operators'; import {EditableClausePredicateWithGenerators} from '../models/predicate/editable-clause-predicate-with-generators'; import {Category} from '../models/category/category'; import {PredicateTreeMetadata} from '../models/persistance/generator-metadata'; @@ -53,11 +53,13 @@ export class SearchService implements OnDestroy { */ protected _predicateRemoved$: Subject; protected _loadingFromMetadata$: LoadingEmitter; + protected _loadingFromPfql$: LoadingEmitter; /** * The `rootPredicate` uses this stream to notify the search service about changes to the held query */ private readonly _predicateQueryChanged$: Subject; private readonly subFilter: Subscription; + private readonly subPredicateChanged: Subscription; /** * The {@link Predicate} tree root uses an [AND]{@link BooleanOperator#AND} operator to combine the Predicates. @@ -85,6 +87,7 @@ export class SearchService implements OnDestroy { this._activeFilter = new BehaviorSubject(this._baseFilter); this._predicateRemoved$ = new Subject(); this._loadingFromMetadata$ = new LoadingEmitter(); + this._loadingFromPfql$ = new LoadingEmitter(); if (baseFilter.filter instanceof Observable) { this.subFilter = baseFilter.filter.subscribe((filter) => { @@ -93,7 +96,7 @@ export class SearchService implements OnDestroy { }); } - this.predicateQueryChanged$.subscribe(() => { + this.subPredicateChanged = this.predicateQueryChanged$.pipe(filter(() => !this._loadingFromPfql$.value)).subscribe(() => { this.updateActiveFilter(); }); } @@ -105,7 +108,9 @@ export class SearchService implements OnDestroy { if (this.subFilter) { this.subFilter.unsubscribe(); } + this.subPredicateChanged?.unsubscribe(); this._loadingFromMetadata$.complete(); + this._loadingFromPfql$.complete(); this._rootPredicate.destroy(); } @@ -181,6 +186,15 @@ export class SearchService implements OnDestroy { return this._loadingFromMetadata$.value; } + /** + * @returns whether the search service is currently loading its state from PFQL query or not. + * + * See [loadFromPfql()]{@link SearchService#loadFromPfql} + */ + public get loadingFromPfql(): boolean { + return this._loadingFromPfql$.value; + } + /** * @returns an `Observable` that emits `true` if the search service is currently loading its state from metadata, * emits `false` otherwise. @@ -191,6 +205,16 @@ export class SearchService implements OnDestroy { return this._loadingFromMetadata$.asObservable(); } + /** + * @returns an `Observable` that emits `true` if the search service is currently loading its state from PFQL query, + * emits `false` otherwise. + * + See [loadFromPfql()]{@link SearchService#loadFromPfql} + */ + public get loadingFromPfql$(): Observable { + return this._loadingFromPfql$.asObservable(); + } + /** * @returns an Observable that emits whenever the root predicates query changes */ @@ -247,15 +271,18 @@ export class SearchService implements OnDestroy { * Removes all {@link Predicate} objects that contribute to the search. Updates the active Filter if it was affected. * * @param clearHidden whether the hidden predicates should be cleared as well + * @param updateActiveFilter whether the filter should be updated */ - public clearPredicates(clearHidden = false): void { + public clearPredicates(clearHidden = false, updateActiveFilter = true): void { if (this._rootPredicate.getPredicateMap().size > 0) { for (const [id, predicate] of this._rootPredicate.getPredicateMap().entries()) { if (clearHidden || predicate.isVisible) { this.removePredicate(id); } } - this.updateActiveFilter(); + if (updateActiveFilter) { + this.updateActiveFilter(); + } } } @@ -397,8 +424,8 @@ export class SearchService implements OnDestroy { return; } - this.clearPredicates(true); - this._loadingFromMetadata$.on(); + this._loadingFromPfql$.on(); + this.clearPredicates(true, false); const queryItems: Array = parseQuery(query, this._injector); if (!queryItems) { this._log.warn(`Could not parse query '${query}. Clearing the search...`) @@ -407,12 +434,12 @@ export class SearchService implements OnDestroy { const categoryLoadings$ = this.loadFromQueryItemsIntoRootPredicate(queryItems); if (categoryLoadings$.length === 0) { - this._loadingFromMetadata$.off(); + this._loadingFromPfql$.off(); this.updateActiveFilter(); return; } forkJoin(categoryLoadings$).subscribe(() => { - this._loadingFromMetadata$.off(); + this._loadingFromPfql$.off(); this.updateActiveFilter(); }); } From a3b4a28e56e8dfde049d17839af751baa22fa7a8 Mon Sep 17 00:00:00 2001 From: chvostek Date: Thu, 6 Aug 2026 08:44:36 +0200 Subject: [PATCH 24/55] [NAE-2466] Advanced search for PFQL - fix race condition when loading dataset category from pfql --- .../models/category/case/case-dataset.ts | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts index 1b614fd00f..2b282648e3 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts @@ -45,7 +45,7 @@ import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; import {FieldTypeResource} from "../../../../task-content/model/field-type-resource"; import {SimpleExpression} from "../../../../pfql/model/simple-expression"; import {DataSimpleExpression} from "../../../../pfql/model/data-simple-expression"; -import {take} from "rxjs/operators"; +import {take, map} from "rxjs/operators"; interface Datafield { netIdentifier: string; @@ -467,21 +467,17 @@ export class CaseDataset extends Category implements AutocompleteOpti return of(undefined); } - const isDone$ = new Subject(); - this._datafieldOptionsInitialized$.pipe(take(1)).subscribe(() => { - this._isLoadedFromPfql = true; - this.selectDataFieldsByPfqlExpression(expression); - if (!this.selectOperatorFromPfqlExpression(expression)) { - isDone$.next(); - isDone$.complete(); - return; - } - this.setOperands(Array.isArray(expression.operandValue) ? expression.operandValue : [expression.operandValue]); - isDone$.next(); - isDone$.complete(); - }); - - return isDone$.asObservable(); + return this._datafieldOptionsInitialized$.pipe( + take(1), + map(() => { + this._isLoadedFromPfql = true; + this.selectDataFieldsByPfqlExpression(expression); + if (!this.selectOperatorFromPfqlExpression(expression)) { + return; + } + this.setOperands(Array.isArray(expression.operandValue) ? expression.operandValue : [expression.operandValue]); + }) + ); } protected deserializeOperandValue(value: unknown): Observable { From af216674855312f35df331f600a64c19797b13f0 Mon Sep 17 00:00:00 2001 From: chvostek Date: Fri, 7 Aug 2026 13:37:37 +0200 Subject: [PATCH 25/55] [NAE-2466] Advanced search for PFQL - remove push down negation --- .../src/lib/pfql/model/complex-expression.ts | 76 +------------------ .../src/lib/pfql/model/logical-operator.ts | 19 ----- .../src/lib/pfql/model/negatable.ts | 36 --------- .../lib/pfql/model/query-item-interface.ts | 8 -- .../src/lib/pfql/model/simple-expression.ts | 38 +--------- .../src/lib/pfql/pfql-utils.ts | 7 -- 6 files changed, 2 insertions(+), 182 deletions(-) delete mode 100644 projects/netgrif-components-core/src/lib/pfql/model/negatable.ts diff --git a/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts b/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts index a974769a10..dde0d62096 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts @@ -1,7 +1,5 @@ import {QueryItemInterface} from "./query-item-interface"; import {QueryItem, QueryItemType} from "./query-item-type"; -import {Negatable} from "./negatable"; -import {LogicalOperator} from "./logical-operator"; /** * Represents a complex expression in a PFQL (Process Filter Query Language) query. @@ -13,7 +11,7 @@ import {LogicalOperator} from "./logical-operator"; * The class supports negation push-down operations to optimize query execution by * distributing negations to inner expressions. */ -export class ComplexExpression implements QueryItemInterface, Negatable { +export class ComplexExpression implements QueryItemInterface { protected _negated: boolean; protected _items: QueryItem[]; @@ -37,76 +35,4 @@ export class ComplexExpression implements QueryItemInterface, Negatable { public get isNegated(): boolean { return this._negated; } - - public isNegatable(): boolean { - return true; - } - - /** - * Pushes down the negation flag to child items in the expression tree. - * If the expression is negated, this method propagates the negation to all child items - * by negating them and converting logical operators to their opposites (AND <-> OR). - * After propagation, the negation flag on this expression is cleared. - * This normalization ensures that negation is represented at the leaf level rather than - * at the complex expression level, which can optimize query execution. - */ - public pushDownNegation(): void { - this.pushDownNegationForInnerItems(); - this._negated = false; // must be set after the push-down call - } - - /** - * Toggles the negation state of this complex expression. - * If the expression is currently negated, clears the negation flag and pushes down - * the negation to child items. If the expression is not negated, negates all child items - * and converts logical operators to their opposites without setting the negation flag. - * This method applies De Morgan's laws to maintain logical equivalence. - */ - public negate(): void { - if (this._negated) { - this._negated = false; // forces push-down for items - this.pushDownNegationForInnerItems(); - return; - } - this.negateInnerItems(); - } - - /** - * Propagates negation to all child items in this complex expression. - * For each child item: - * - If this expression is negated and the child is a logical operator, replaces it with its opposite (AND <-> OR) - * - If the child is negatable and this expression is negated, negates the child - * - If the child is negatable and this expression is not negated, recursively pushes down negation on the child - * This method is called internally to distribute negation throughout the expression tree. - */ - protected pushDownNegationForInnerItems(): void { - for (let i = 0; i < this._items.length; i++) { - const item = this._items[i]; - if (this._negated && item.type() === QueryItemType.LOGICAL_OPERATOR) { - this._items[i] = (item as LogicalOperator).opposite(); - } else if (item.isNegatable()) { - const expression: Negatable = item as Negatable; - this._negated ? expression.negate() : expression.pushDownNegation(); - } - } - } - - /** - * Negates all child items in this complex expression without setting the negation flag. - * For each child item: - * - If the child is a logical operator, replaces it with its opposite (AND <-> OR) - * - If the child is negatable (simple or complex expression), negates it - * This method is used to apply De Morgan's laws when negating the entire complex expression. - */ - protected negateInnerItems(): void { - for (let i = 0; i < this._items.length; i++) { - const item = this._items[i]; - if (item.type() === QueryItemType.LOGICAL_OPERATOR) { - this._items[i] = (item as LogicalOperator).opposite(); - } else if (item.isNegatable()) { - const expression = item as Negatable; - expression.negate(); - } - } - } } diff --git a/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts b/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts index 8b926a15dd..e94f365bae 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/logical-operator.ts @@ -27,23 +27,4 @@ export class LogicalOperator implements QueryItemInterface { public get value(): BooleanOperator { return this._value; } - - public isNegatable(): boolean { - return false; - } - - /** - * Returns the logical opposite of the current operator. - * - * This method returns a new LogicalOperator instance with the opposite boolean operator: - * - If the current operator is OR, returns AND - * - If the current operator is AND, returns OR - * - * Note: This method does not handle the NOT operator as it operates only on binary operators (AND/OR). - * - * @returns a new LogicalOperator instance with the opposite operator value - */ - public opposite(): LogicalOperator { - return this.value === BooleanOperator.OR ? new LogicalOperator(BooleanOperator.AND) : new LogicalOperator(BooleanOperator.OR); - } } diff --git a/projects/netgrif-components-core/src/lib/pfql/model/negatable.ts b/projects/netgrif-components-core/src/lib/pfql/model/negatable.ts deleted file mode 100644 index df6e37f48f..0000000000 --- a/projects/netgrif-components-core/src/lib/pfql/model/negatable.ts +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Interface for query items that support negation operations in PFQL queries. - * - * This interface provides two approaches to negation: - * - Direct negation via {@link negate}, which toggles the negation state - * - Negation push-down via {@link pushDownNegation}, which distributes negation to child items - * - * Push-down negation is an optimization technique that moves negation closer to leaf expressions, - * applying De Morgan's laws to flip logical operators (AND ↔ OR) when necessary. - * - * @see ComplexExpression for implementation example - * @see QueryItemInterface.isNegatable for checking if an item supports negation - */ -export interface Negatable { - /** - * Pushes negation down to child query items and clears the negation flag on this item. - * - * This method distributes negation to inner expressions and flips logical operators - * according to De Morgan's laws (AND becomes OR, OR becomes AND). After execution, - * the negation state of this item is cleared. - * - * This is typically called during query optimization to simplify the query structure. - */ - pushDownNegation(): void; - - /** - * Toggles or applies negation to this query item. - * - * The behavior depends on the current negation state: - * - If not negated: applies negation by flipping logical operators and negating child items - * - If already negated: clears negation and pushes it down to child items instead - * - * This method is used when constructing or modifying queries to express NOT conditions. - */ - negate(): void -} diff --git a/projects/netgrif-components-core/src/lib/pfql/model/query-item-interface.ts b/projects/netgrif-components-core/src/lib/pfql/model/query-item-interface.ts index 7a79fa6d00..7b598e0ef5 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/query-item-interface.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/query-item-interface.ts @@ -19,12 +19,4 @@ export interface QueryItemInterface { * complex expression, or logical operator. */ type(): QueryItemType; - - /** - * Indicates whether this query item supports negation operations. - * - * @returns `true` if this item implements {@link Negatable} and can be negated, `false` otherwise. - * Logical operators typically return `false`, while expressions return `true`. - */ - isNegatable(): boolean; } diff --git a/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts b/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts index 8af117fa2f..ca8fbe59ee 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts @@ -2,14 +2,13 @@ import {Category} from "../../search/models/category/category"; import {Operator} from "../../search/models/operator/operator"; import {QueryItemInterface} from "./query-item-interface"; import { QueryItemType } from "./query-item-type"; -import {Negatable} from "./negatable"; /** * Represents a simple PFQL expression consisting of a category, operator, operand value, and negation flag. * A simple expression is a basic building block of PFQL queries that combines a search category with an operator * and a value to create a single query condition. The expression can also be negated to invert its meaning. */ -export class SimpleExpression implements QueryItemInterface, Negatable { +export class SimpleExpression implements QueryItemInterface { protected _category: Category protected _operator: Operator protected _operandValue: any; @@ -45,39 +44,4 @@ export class SimpleExpression implements QueryItemInterface, Negatable { public get negated(): boolean { return this._negated; } - - public isNegatable(): boolean { - return true; - } - - /** - * Pushes down the negation flag by converting it into an operator negation. - * If the expression is negated, this method clears the negation flag and inverts the operator instead. - * This normalization ensures that negation is represented consistently at the operator level rather than - * at the expression level. If the expression is not negated, this method does nothing. - */ - public pushDownNegation() { - if (!this.negated) { - return; - } - this._negated = false; - this.negate(); - } - - /** - * Toggles the negation of this expression. - * If the expression is currently negated (flag is true), clears the negation flag. - * Otherwise, inverts the operator to its negated form if an operator is present. - * @throws {Error} if the expression has no operator or cannot be negated - */ - public negate(): void { - if (!!this._negated) { - this._negated = false; - return; - } - if (!this.operator) { - throw new Error("Expression cannot be negated. There is no operator"); - } - this._operator = this._operator.negated(); - } } diff --git a/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts b/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts index 87e7369674..a0d211e5c4 100644 --- a/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts +++ b/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts @@ -27,7 +27,6 @@ import {MoreThanEqualDateTime} from "../search/models/operator/more-than-equal-d import {LessThanDateTime} from "../search/models/operator/less-than-date-time"; import {LessThanEqualDateTime} from "../search/models/operator/less-than-equal-date-time"; import {LoggerService} from "../logger/services/logger.service"; -import {Negatable} from "./model/negatable"; /** * Parses a PFQL query string into an array of query items. @@ -48,7 +47,6 @@ export function parseQuery(query: string, injector: Injector): Array const visitor = new PfqlVisitor(injector); let items: Array = visitor.visit(tree); - pushDownNegations(items); return reduceComplexToSimpleExpressions(items); } catch (error) { logger.error(`Could not parse PFQL query: ${error}`); @@ -169,8 +167,3 @@ function canBeReducedToSimpleExpr(complexExpr: ComplexExpression): boolean { function isSingleComplexExpr(items: Array): boolean { return !!items && items.length === 1 && items[0].type() === QueryItemType.COMPLEX_EXPRESSION; } - -function pushDownNegations(items: Array): void { - items.filter(item => item.isNegatable()) - .forEach(item => (item as Negatable).pushDownNegation()); -} From de1470e217966aca2e9bfc96ec9d844a6acfec38 Mon Sep 17 00:00:00 2001 From: chvostek Date: Fri, 7 Aug 2026 13:55:23 +0200 Subject: [PATCH 26/55] [NAE-2466] Advanced search for PFQL - remove OR operator button --- .../search-clause-component/search-clause.component.html | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/projects/netgrif-components/src/lib/search/advanced-search/search-clause-component/search-clause.component.html b/projects/netgrif-components/src/lib/search/advanced-search/search-clause-component/search-clause.component.html index 32e6108bba..e3cda44548 100644 --- a/projects/netgrif-components/src/lib/search/advanced-search/search-clause-component/search-clause.component.html +++ b/projects/netgrif-components/src/lib/search/advanced-search/search-clause-component/search-clause.component.html @@ -1,10 +1,8 @@
-
-
{{'search.or' | translate | uppercase}}
-
From 9a04c774853509df3c508009715b5b33795ca58f Mon Sep 17 00:00:00 2001 From: chvostek Date: Mon, 10 Aug 2026 12:53:57 +0200 Subject: [PATCH 27/55] [NAE-2466] Advanced search for PFQL - introduce plain query category --- .../src/assets/i18n/de.json | 16 ++--- .../src/assets/i18n/en.json | 16 ++--- .../src/assets/i18n/sk.json | 18 ++--- .../category-resolver.service.ts | 8 +++ .../default-categories-factories.ts | 8 ++- .../default-search-categories.module.ts | 4 ++ .../models/category/case/case-plain-query.ts | 23 +++++++ .../lib/search/models/category/categories.ts | 2 + .../lib/search/models/category/category.ts | 7 ++ .../models/category/plain-query-category.ts | 68 +++++++++++++++++++ .../models/category/search-input-type.ts | 1 + .../models/category/task/task-plain-query.ts | 22 ++++++ .../lib/search/models/configuration-input.ts | 3 +- .../search-configuration-input.component.html | 9 +++ .../search-operand-input.component.html | 8 ++- 15 files changed, 171 insertions(+), 42 deletions(-) create mode 100644 projects/netgrif-components-core/src/lib/search/models/category/case/case-plain-query.ts create mode 100644 projects/netgrif-components-core/src/lib/search/models/category/plain-query-category.ts create mode 100644 projects/netgrif-components-core/src/lib/search/models/category/task/task-plain-query.ts diff --git a/projects/netgrif-components-core/src/assets/i18n/de.json b/projects/netgrif-components-core/src/assets/i18n/de.json index df8c571d62..b60c8b3673 100644 --- a/projects/netgrif-components-core/src/assets/i18n/de.json +++ b/projects/netgrif-components-core/src/assets/i18n/de.json @@ -127,10 +127,6 @@ "name": "Fallname", "placeholder": "Geben Sie den Fallnamen ein" }, - "visualId": { - "name": "Visuelle ID", - "placeholder": "Geben Sie die visuelle ID ein" - }, "stringId": { "name": "Fall ID", "placeholder": "Geben Sie die Fall ID ein" @@ -143,10 +139,6 @@ "name": "Prozess", "placeholder": "Wählen Sie den Prozess aus" }, - "role": { - "name": "Prozessrolle", - "placeholder": "Wählen Sie die Prozessrolle aus" - }, "task": { "name": "Fallaufgabe", "placeholder": "Wählen Sie die Fallaufgabe aus" @@ -176,15 +168,15 @@ "name": "Prozess", "placeholder": "Wählen Sie den Prozess aus" }, - "role": { - "name": "Aufgabenprocessrolle", - "placeholder": "Wählen Sie die Prozessrolle der Aufgabe aus" - }, "task": { "name": "Aufgabe", "placeholder": "Wählen Sie die Aufgabe aus" } }, + "plainText": { + "name": "Klartext", + "placeholder": "Schreiben Sie eine gültige PFQL-Abfrage auf." + }, "select": "Suchkategorie", "userMe": "ICH" }, diff --git a/projects/netgrif-components-core/src/assets/i18n/en.json b/projects/netgrif-components-core/src/assets/i18n/en.json index 05e7d0b758..74da0da840 100644 --- a/projects/netgrif-components-core/src/assets/i18n/en.json +++ b/projects/netgrif-components-core/src/assets/i18n/en.json @@ -127,10 +127,6 @@ "name": "Case title", "placeholder": "Enter case title" }, - "visualId": { - "name": "Case visual ID", - "placeholder": "Enter case visual ID" - }, "stringId": { "name": "Case ID", "placeholder": "Enter case ID" @@ -143,10 +139,6 @@ "name": "Case process", "placeholder": "Select case process" }, - "role": { - "name": "Process role", - "placeholder": "Select process role" - }, "task": { "name": "Case task", "placeholder": "Select case task" @@ -176,15 +168,15 @@ "name": "Task process", "placeholder": "Select task process" }, - "role": { - "name": "Task process role", - "placeholder": "Select task process role" - }, "task": { "name": "Task", "placeholder": "Select task" } }, + "plainText": { + "name": "Plain query", + "placeholder": "Write down valid PFQL query" + }, "select": "Search category", "userMe": "ME" }, diff --git a/projects/netgrif-components-core/src/assets/i18n/sk.json b/projects/netgrif-components-core/src/assets/i18n/sk.json index 27b8ecad2d..fa48b5dce2 100644 --- a/projects/netgrif-components-core/src/assets/i18n/sk.json +++ b/projects/netgrif-components-core/src/assets/i18n/sk.json @@ -127,10 +127,6 @@ "name": "Názov prípadu", "placeholder": "Zadajte názov prípadu" }, - "visualId": { - "name": "Vizuálne ID prípadu", - "placeholder": "Zadajte vizuálne ID prípadu" - }, "stringId": { "name": "ID prípadu", "placeholder": "Zadajte ID prípadu" @@ -143,10 +139,6 @@ "name": "Proces prípadu", "placeholder": "Vyberte proces prípadu" }, - "role": { - "name": "Procesná rola", - "placeholder": "Vyberte procesnú rolu" - }, "task": { "name": "Úloha prípadu", "placeholder": "Vyberte úlohu" @@ -176,15 +168,15 @@ "name": "Proces úlohy", "placeholder": "Vyberte proces úlohy" }, - "role": { - "name": "Procesná rola úlohy", - "placeholder": "Vyberte procesnú rolu" - }, "task": { "name": "Úloha", "placeholder": "Vyberte úlohu" } }, + "plainText": { + "name": "Obyčajný dopyt", + "placeholder": "Napíšte platný PFQL dopyt" + }, "select": "Kategória vyhľadávania", "userMe": "JA" }, @@ -213,7 +205,7 @@ }, "help": { "title": "Nápoveda pre rozšírené vyhľadávanie", - "text": "Rozšírené vyhľadávanie slúži na zostavenie komplikovanejších požiadaviek na vyhľadávanie. Na začiatku zvoľte kategóriu vyhľadávania. Kategória vyhľadávania učruje, podľa čoho má váš dopyt vyhľadávať. Niektoré kategórie, ako napríklad \"Dáta prípadu\" vyžadujú dodatočnú konfiguráciu. Po zvolení kategórie je nutné zvoliť operátor vyhľadávania. Operátor rozhoduje o tom, akým spôsobom sa hľadá zhoda s hľadaným výtazom a dátami. Operátorom je možné hľadať napríklad presnú zhodu, alebo hodnotu z rozsahu. Nakoniec je nutné zadať hľadanú hodnotu. Dopyty je možné kombinovať pomocou kľúčových slov A SÚČASNE a ALEBO. Dopyty kombinované slovom ALEBO nájdu výsledky, spĺňajúce aspoň jednu z podmienok. Dopyty kombinované slovom A SÚČASNE nájdu výsledky spĺňajúce všetky podmienky." + "text": "Rozšírené vyhľadávanie slúži na zostavenie komplikovanejších požiadaviek na vyhľadávanie. Na začiatku zvoľte kategóriu vyhľadávania. Kategória vyhľadávania určuje, podľa čoho má váš dopyt vyhľadávať. Niektoré kategórie, ako napríklad \"Dáta prípadu\" vyžadujú dodatočnú konfiguráciu. Po zvolení kategórie je nutné zvoliť operátor vyhľadávania. Operátor rozhoduje o tom, akým spôsobom sa hľadá zhoda s hľadaným výtazom a dátami. Operátorom je možné hľadať napríklad presnú zhodu, alebo hodnotu z rozsahu. Nakoniec je nutné zadať hľadanú hodnotu. Dopyty je možné kombinovať pomocou kľúčových slov A SÚČASNE a ALEBO. Dopyty kombinované slovom ALEBO nájdu výsledky, spĺňajúce aspoň jednu z podmienok. Dopyty kombinované slovom A SÚČASNE nájdu výsledky spĺňajúce všetky podmienky." }, "fullText": "Zadajte hľadaný text", "and": "a súčasne", diff --git a/projects/netgrif-components-core/src/lib/search/category-factory/category-resolver.service.ts b/projects/netgrif-components-core/src/lib/search/category-factory/category-resolver.service.ts index 47ded37f3a..1cea1de494 100644 --- a/projects/netgrif-components-core/src/lib/search/category-factory/category-resolver.service.ts +++ b/projects/netgrif-components-core/src/lib/search/category-factory/category-resolver.service.ts @@ -13,6 +13,8 @@ import {TaskProcess} from '../models/category/task/task-process'; import {TaskTask} from '../models/category/task/task-task'; import {CaseCreationDateTime} from '../models/category/case/case-creation-date-time'; import {CategorySerialisationPair} from './category-serialisation-pair'; +import {CasePlainQuery} from "../models/category/case/case-plain-query"; +import {TaskPlainQuery} from "../models/category/task/task-plain-query"; /** * A service that resolves {@link Categories} (or custom string) into a concrete {@link Category} implementation class and vice versa. @@ -61,6 +63,9 @@ export class CategoryResolverService { }, { classReference: CaseStringId, serialized: Categories.CASE_STRING_ID + }, { + classReference: CasePlainQuery, + serialized: Categories.CASE_PLAIN_QUERY }, // Task { @@ -72,6 +77,9 @@ export class CategoryResolverService { }, { classReference: TaskTask, serialized: Categories.TASK_TASK + }, { + classReference: TaskPlainQuery, + serialized: Categories.TASK_PLAIN_QUERY } ].forEach(pair => this.registerPair(pair)); } diff --git a/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.ts b/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.ts index 2a58ede08f..28eac2fc02 100644 --- a/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.ts +++ b/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.ts @@ -10,6 +10,8 @@ import {TaskAssignee} from '../models/category/task/task-assignee'; import {TaskProcess} from '../models/category/task/task-process'; import {TaskTask} from '../models/category/task/task-task'; import {CaseCreationDateTime} from '../models/category/case/case-creation-date-time'; +import {CasePlainQuery} from "../models/category/case/case-plain-query"; +import {TaskPlainQuery} from "../models/category/task/task-plain-query"; /** * Creates the default case search categories. @@ -21,7 +23,7 @@ import {CaseCreationDateTime} from '../models/category/case/case-creation-date-t * [duplicate()]{@link Category#duplicate} method. * * @returns an Array containing the default case search categories: {@link CaseDataset}, {@link CaseTitle}, {@link CaseCreationDate}, - * {@link CaseProcess}, {@link CaseAuthor}, and {@link CaseStringId} + * {@link CaseProcess}, {@link CaseAuthor}, {@link CaseStringId} and {@link CasePlainQuery} * * @deprecated in 5.6.0 - Use the {@link NAE_DEFAULT_CASE_SEARCH_CATEGORIES} injection token instead */ @@ -34,6 +36,7 @@ export function defaultCaseSearchCategoriesFactory(factory: CategoryFactory): Ar factory.get(CaseProcess), factory.get(CaseAuthor), factory.get(CaseStringId), + factory.get(CasePlainQuery), ]; cats.forEach(cat => cat.destroy()); return cats; @@ -48,7 +51,7 @@ export function defaultCaseSearchCategoriesFactory(factory: CategoryFactory): Ar * caused by uncompleted Subjects. They should only be used to create new Category instances with the help of the * [duplicate()]{@link Category#duplicate} method. * - * @returns an Array containing the default task search categories: {@link TaskAssignee}, {@link TaskTask} and {@link TaskProcess} + * @returns an Array containing the default task search categories: {@link TaskAssignee}, {@link TaskTask}, {@link TaskProcess} and {@link TaskPlainQuery} * * @deprecated in 5.6.0 - Use the {@link NAE_DEFAULT_TASK_SEARCH_CATEGORIES} injection token instead */ @@ -57,6 +60,7 @@ export function defaultTaskSearchCategoriesFactory(factory: CategoryFactory): Ar factory.get(TaskAssignee), factory.get(TaskTask), factory.get(TaskProcess), + factory.get(TaskPlainQuery), ]; cats.forEach(cat => cat.destroy()); return cats; diff --git a/projects/netgrif-components-core/src/lib/search/category-factory/default-search-categories.module.ts b/projects/netgrif-components-core/src/lib/search/category-factory/default-search-categories.module.ts index d27a5c0630..aa8cf95b12 100644 --- a/projects/netgrif-components-core/src/lib/search/category-factory/default-search-categories.module.ts +++ b/projects/netgrif-components-core/src/lib/search/category-factory/default-search-categories.module.ts @@ -10,6 +10,8 @@ import {TaskTask} from '../models/category/task/task-task'; import {TaskProcess} from '../models/category/task/task-process'; import {CaseCreationDateTime} from '../models/category/case/case-creation-date-time'; import {CaseStringId} from '../models/category/case/case-string-id'; +import {CasePlainQuery} from "../models/category/case/case-plain-query"; +import {TaskPlainQuery} from "../models/category/task/task-plain-query"; @NgModule({ @@ -26,6 +28,7 @@ import {CaseStringId} from '../models/category/case/case-string-id'; CaseProcess, CaseAuthor, CaseStringId, + CasePlainQuery, ] }, { provide: NAE_DEFAULT_TASK_SEARCH_CATEGORIES, @@ -33,6 +36,7 @@ import {CaseStringId} from '../models/category/case/case-string-id'; TaskAssignee, TaskTask, TaskProcess, + TaskPlainQuery, ] } ] diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-plain-query.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-plain-query.ts new file mode 100644 index 0000000000..e33d7578f5 --- /dev/null +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-plain-query.ts @@ -0,0 +1,23 @@ +import {Category} from "../category"; +import {OperatorService} from "../../../operator-service/operator.service"; +import {LoggerService} from "../../../../logger/services/logger.service"; +import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; +import {Categories} from "../categories"; +import {PlainQueryCategory} from "../plain-query-category"; + +// todo 2466 doc +export class CasePlainQuery extends PlainQueryCategory { + + constructor(operators: OperatorService, logger: LoggerService) { + super(operators, logger, ResourceTypeQueryPrefix.CASES); + } + + duplicate(): Category { + return new CasePlainQuery(this._operatorService, this._log); + } + + serializeClass(): string { + return Categories.CASE_PLAIN_QUERY; + } + +} diff --git a/projects/netgrif-components-core/src/lib/search/models/category/categories.ts b/projects/netgrif-components-core/src/lib/search/models/category/categories.ts index 350e21f6ba..f0fe9e62b8 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/categories.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/categories.ts @@ -11,9 +11,11 @@ export enum Categories { CASE_SIMPLE_DATASET = 'case_simple_dataset', CASE_TITLE = 'case_title', CASE_STRING_ID = 'case_string_id', + CASE_PLAIN_QUERY = 'case_plain_query', // Task categories TASK_ASSIGNEE = 'task_assignee', TASK_PROCESS = 'task_process', TASK_TASK = 'task_task', + TASK_PLAIN_QUERY = 'task_plain_query', } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/category.ts b/projects/netgrif-components-core/src/lib/search/models/category/category.ts index 18d1b7df6b..dd178cffec 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/category.ts @@ -224,6 +224,13 @@ export abstract class Category { return this._operandsFormControls$.asObservable(); } + /** + * todo 2466 doc + */ + public get operandsFormControls(): Array { + return this._operandsFormControls; + } + /** * A new value is emitted whenever the selected operator changes. `undefined` is emitted if no operator is selected. * diff --git a/projects/netgrif-components-core/src/lib/search/models/category/plain-query-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/plain-query-category.ts new file mode 100644 index 0000000000..3e06c1b705 --- /dev/null +++ b/projects/netgrif-components-core/src/lib/search/models/category/plain-query-category.ts @@ -0,0 +1,68 @@ +import {ConfigurationInput} from "../configuration-input"; +import {Query} from "../query/query"; +import {Category} from "./category"; +import {Observable, of} from "rxjs"; +import {debounceTime} from "rxjs/operators"; +import {FilterTextSegment} from "../persistance/filter-text-segment"; +import {OperatorService} from "../../operator-service/operator.service"; +import {LoggerService} from "../../../logger/services/logger.service"; +import {SearchInputType} from "./search-input-type"; +import {ResourceTypeQueryPrefix} from "./resource-type-query-prefix"; + +export abstract class PlainQueryCategory extends Category { + private static readonly _title = 'search.category.plainText'; // todo 2466 add translation + + protected _configurationInput: ConfigurationInput; + + protected constructor(operators: OperatorService, logger: LoggerService, resourceType: ResourceTypeQueryPrefix) { + super([], [], `${PlainQueryCategory._title}.name`, SearchInputType.PLAIN_QUERY, logger, operators, resourceType); + this._configurationInput = new ConfigurationInput( + SearchInputType.PLAIN_QUERY, + 'search.category.plainText.name', + false, + new Map>(), + () => { + throw new Error('ConfigurationInput of type PLAIN_QUERY is a placeholder!' + + ' Use operator related methods from the Category class instead.'); + } + ); + const fc = this._configurationInput.formControl; + fc.valueChanges.pipe(debounceTime(600)).subscribe(() => this.operandValueChanges(0)); + this._operandsFormControls.push(fc); + } + + protected override generateQuery(userInput: string[]): Query { + if (!userInput || userInput.length === 0) { + return new Query('', this._resourceTypePrefix); + } + const pfqlQueryString: string = userInput[0]; + return new Query(pfqlQueryString).addPrefixAndGet(this._resourceTypePrefix); + } + + protected override operandValueChanges(operandIndex: number) { + this._generatedPredicate$.next(this.generatePredicate(this._operandsFormControls + .filter(fc => !!fc) + .map(fc => this.transformCategoryValue(fc.value)))) + return; + } + + get configurationInputs$(): Observable { + return of([this._configurationInput]); + } + + protected createConfigurationFilterTextSegments(): FilterTextSegment[] { + return []; + } + + get displayBold(): boolean { + return true; + } + + protected isOperandValueSelected(newValue: any): boolean { + return !!newValue; + } + + get inputPlaceholder(): string { + return `${PlainQueryCategory._title}.placeholder`; + } +} diff --git a/projects/netgrif-components-core/src/lib/search/models/category/search-input-type.ts b/projects/netgrif-components-core/src/lib/search/models/category/search-input-type.ts index bad9d0dc91..0b188062d7 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/search-input-type.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/search-input-type.ts @@ -3,6 +3,7 @@ */ export enum SearchInputType { TEXT = 'text', + PLAIN_QUERY = 'plain_query', AUTOCOMPLETE = 'autocomplete', DATE = 'date', DATE_TIME = 'dateTime', diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-plain-query.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-plain-query.ts new file mode 100644 index 0000000000..803cc2037e --- /dev/null +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-plain-query.ts @@ -0,0 +1,22 @@ +import {Category} from "../category"; +import {OperatorService} from "../../../operator-service/operator.service"; +import {LoggerService} from "../../../../logger/services/logger.service"; +import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; +import {Categories} from "../categories"; +import {PlainQueryCategory} from "../plain-query-category"; + +// todo 2466 doc +export class TaskPlainQuery extends PlainQueryCategory { + + constructor(operators: OperatorService, logger: LoggerService) { + super(operators, logger, ResourceTypeQueryPrefix.TASKS); + } + + duplicate(): Category { + return new TaskPlainQuery(this._operatorService, this._log); + } + + serializeClass(): string { + return Categories.TASK_PLAIN_QUERY; + } +} diff --git a/projects/netgrif-components-core/src/lib/search/models/configuration-input.ts b/projects/netgrif-components-core/src/lib/search/models/configuration-input.ts index af3dd8cdbe..270d19efee 100644 --- a/projects/netgrif-components-core/src/lib/search/models/configuration-input.ts +++ b/projects/netgrif-components-core/src/lib/search/models/configuration-input.ts @@ -26,7 +26,7 @@ export class ConfigurationInput { * @param filterOptions a method that receives the keys of the available options and should return * the appropriately filtered autocomplete options */ - constructor(public type: SearchInputType.AUTOCOMPLETE | SearchInputType.OPERATOR, + constructor(public type: SearchInputType.AUTOCOMPLETE | SearchInputType.OPERATOR | SearchInputType.PLAIN_QUERY, public label: string, public displayBold: boolean, protected _autocompleteOptions: Map>, @@ -38,7 +38,6 @@ export class ConfigurationInput { filter(newValue => typeof newValue === 'string'), map(newValue => { return filterOptions(Array.from(this._autocompleteOptions.keys()), newValue); - }) ); } diff --git a/projects/netgrif-components/src/lib/search/advanced-search/search-configuration-input-component/search-configuration-input.component.html b/projects/netgrif-components/src/lib/search/advanced-search/search-configuration-input-component/search-configuration-input.component.html index 76cadf4585..3eadd49952 100644 --- a/projects/netgrif-components/src/lib/search/advanced-search/search-configuration-input-component/search-configuration-input.component.html +++ b/projects/netgrif-components/src/lib/search/advanced-search/search-configuration-input-component/search-configuration-input.component.html @@ -90,4 +90,13 @@
+ +
+ +
+
diff --git a/projects/netgrif-components/src/lib/search/advanced-search/search-operand-input-component/search-operand-input.component.html b/projects/netgrif-components/src/lib/search/advanced-search/search-operand-input-component/search-operand-input.component.html index e633056139..b4821be310 100644 --- a/projects/netgrif-components/src/lib/search/advanced-search/search-operand-input-component/search-operand-input.component.html +++ b/projects/netgrif-components/src/lib/search/advanced-search/search-operand-input-component/search-operand-input.component.html @@ -3,6 +3,12 @@
+ + + + + + -
+
{{inputFormControl.value.text | translate}}
From f3b5d483183e91d999009e909c456010a9740452 Mon Sep 17 00:00:00 2001 From: chvostek Date: Mon, 10 Aug 2026 15:58:44 +0200 Subject: [PATCH 28/55] [NAE-2466] Advanced search for PFQL - implement loading of plain query --- .../src/lib/pfql/model/complex-expression.ts | 13 +- .../lib/pfql/model/data-simple-expression.ts | 4 +- .../src/lib/pfql/model/query-item-type.ts | 6 +- .../src/lib/pfql/model/raw-expression.ts | 25 +++ .../src/lib/pfql/model/simple-expression.ts | 12 +- .../src/lib/pfql/pfql-visitor.ts | 185 ++++++++++++------ .../models/category/plain-query-category.ts | 6 + .../search/search-service/search.service.ts | 119 +++-------- 8 files changed, 188 insertions(+), 182 deletions(-) create mode 100644 projects/netgrif-components-core/src/lib/pfql/model/raw-expression.ts diff --git a/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts b/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts index dde0d62096..42b32dc596 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts @@ -5,18 +5,13 @@ import {QueryItem, QueryItemType} from "./query-item-type"; * Represents a complex expression in a PFQL (Process Filter Query Language) query. * * A complex expression is a composite query item that contains multiple child query items - * (either simple expressions or other complex expressions) and can be negated. + * (either simple expressions or other complex expressions). * It is used to build hierarchical query structures with logical operations. - * - * The class supports negation push-down operations to optimize query execution by - * distributing negations to inner expressions. */ export class ComplexExpression implements QueryItemInterface { - protected _negated: boolean; protected _items: QueryItem[]; - public constructor(negated: boolean, items: QueryItem[]) { - this._negated = negated; + public constructor(items: QueryItem[]) { this._items = !items ? [] : items; } @@ -31,8 +26,4 @@ export class ComplexExpression implements QueryItemInterface { public set items(items: QueryItem[]) { this._items = items; } - - public get isNegated(): boolean { - return this._negated; - } } diff --git a/projects/netgrif-components-core/src/lib/pfql/model/data-simple-expression.ts b/projects/netgrif-components-core/src/lib/pfql/model/data-simple-expression.ts index 89cc4504a8..483e6c9f8e 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/data-simple-expression.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/data-simple-expression.ts @@ -12,8 +12,8 @@ import {Category} from "../../search/models/category/category"; export class DataSimpleExpression extends SimpleExpression { protected _dataFieldId: string; - public constructor(dataFieldPath: string, operator: Operator, operandValue: any, negated: boolean, category?: Category) { - super(operator, operandValue, negated, category); + public constructor(dataFieldPath: string, operator: Operator, operandValue: any, category?: Category) { + super(operator, operandValue, category); const parts = dataFieldPath.split('.'); this._dataFieldId = parts.length >= 3 && parts[0] === 'data' ? parts[1] : dataFieldPath; diff --git a/projects/netgrif-components-core/src/lib/pfql/model/query-item-type.ts b/projects/netgrif-components-core/src/lib/pfql/model/query-item-type.ts index 2033034c76..4374557d27 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/query-item-type.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/query-item-type.ts @@ -1,12 +1,14 @@ import {SimpleExpression} from "./simple-expression"; import {ComplexExpression} from "./complex-expression"; import { LogicalOperator } from "./logical-operator"; +import {RawExpression} from "./raw-expression"; export enum QueryItemType { SIMPLE_EXPRESSION, COMPLEX_EXPRESSION, - LOGICAL_OPERATOR + LOGICAL_OPERATOR, + RAW_EXPRESSION, } -export type QueryItem = SimpleExpression | ComplexExpression | LogicalOperator; +export type QueryItem = SimpleExpression | ComplexExpression | RawExpression | LogicalOperator; diff --git a/projects/netgrif-components-core/src/lib/pfql/model/raw-expression.ts b/projects/netgrif-components-core/src/lib/pfql/model/raw-expression.ts new file mode 100644 index 0000000000..b2aacf196c --- /dev/null +++ b/projects/netgrif-components-core/src/lib/pfql/model/raw-expression.ts @@ -0,0 +1,25 @@ +import {QueryItemInterface} from "./query-item-interface"; +import {QueryItemType} from "./query-item-type"; +import {PlainQueryCategory} from "../../search/models/category/plain-query-category"; + +export class RawExpression implements QueryItemInterface { + protected _category: PlainQueryCategory; + protected _rawQuery: string; + + public constructor(category: PlainQueryCategory, rawQuery: string) { + this._category = category; + this._rawQuery = rawQuery; + } + + public type(): QueryItemType { + return QueryItemType.RAW_EXPRESSION; + } + + public get category(): PlainQueryCategory { + return this._category; + } + + public get rawQuery(): string { + return this._rawQuery; + } +} diff --git a/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts b/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts index ca8fbe59ee..43f6ab390b 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/simple-expression.ts @@ -4,20 +4,18 @@ import {QueryItemInterface} from "./query-item-interface"; import { QueryItemType } from "./query-item-type"; /** - * Represents a simple PFQL expression consisting of a category, operator, operand value, and negation flag. + * Represents a simple PFQL expression consisting of a category, operator, and operand value. * A simple expression is a basic building block of PFQL queries that combines a search category with an operator - * and a value to create a single query condition. The expression can also be negated to invert its meaning. + * and a value to create a single query condition. */ export class SimpleExpression implements QueryItemInterface { protected _category: Category protected _operator: Operator protected _operandValue: any; - protected _negated: boolean; - public constructor(operator: Operator, operandValue: any, negated: boolean, category?: Category) { + public constructor(operator: Operator, operandValue: any, category?: Category) { this._operator = operator; this._operandValue = operandValue; - this._negated = negated; this._category = category; } @@ -40,8 +38,4 @@ export class SimpleExpression implements QueryItemInterface { public get operandValue(): any { return this._operandValue; } - - public get negated(): boolean { - return this._negated; - } } diff --git a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts index 139b2b0e82..a25cdf464a 100644 --- a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts +++ b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts @@ -26,7 +26,6 @@ import { DateTimeRangeContext, IdBasicContext, InRangeNumberComparisonContext, - NullComparisonContext, NumberComparisonContext, ObjectIdComparisonContext, ProcessIdBasicContext, @@ -75,6 +74,9 @@ import {TaskTask} from "../search/models/category/task/task-task"; import {TaskAssignee} from "../search/models/category/task/task-assignee"; import {TaskProcess} from "../search/models/category/task/task-process"; import {UserService} from "../user/services/user.service"; +import {CasePlainQuery} from "../search/models/category/case/case-plain-query"; +import {RawExpression} from "./model/raw-expression"; +import {TaskPlainQuery} from "../search/models/category/task/task-plain-query"; /** @@ -171,19 +173,11 @@ export class PfqlVisitor extends QueryLangVisitor> { }; /** - * Visits a case OR expression and combines multiple AND expressions with OR logical operators. - * - * @param ctx - The case OR expression parse tree context - * @returns An array of query items with AND expressions joined by OR operators + * todo 2466 doc */ override visitCaseOrExpression = (ctx: CaseOrExpressionContext): Array => { const andExpressionContexts = ctx.caseAndExpression(); - const items: Array = [...this.visit(andExpressionContexts[0])]; - for (let i = 1; i < andExpressionContexts.length; i++) { - items.push(new LogicalOperator(BooleanOperator.OR)); - items.push(...this.visit(andExpressionContexts[i])); - } - return items; + return andExpressionContexts.length === 1 ? [...this.visit(andExpressionContexts[0])] : [this.handleCaseRawQuery(ctx.getText())] }; /** @@ -204,31 +198,24 @@ export class PfqlVisitor extends QueryLangVisitor> { /** * Visits a parenthesized case condition group and wraps the inner conditions in a complex expression. - * Supports negation with the NOT keyword. * * @param ctx - The case condition group parenthesis parse tree context - * @returns An array containing a single complex expression with the inner conditions and negation flag + * @returns An array containing a single complex expression with the inner conditions */ override visitCaseConditionGroupParenthesis = (ctx: CaseConditionGroupParenthesisContext): Array => { const innerItems: Array = [...this.visit(ctx.caseConditions())]; - const isNegated: boolean = !!ctx.NOT(); - return [new ComplexExpression(isNegated, innerItems)]; + if (!!ctx.NOT()) { + return [this.handleCaseRawQuery(ctx.getText())]; + } + return [new ComplexExpression(innerItems)]; }; /** - * Visits a task OR expression and combines multiple AND expressions with OR logical operators. - * - * @param ctx - The task OR expression parse tree context - * @returns An array of query items with AND expressions joined by OR operators + * todo 2466 doc */ override visitTaskOrExpression = (ctx: TaskOrExpressionContext): Array => { const andExpressionContexts = ctx.taskAndExpression(); - const items: Array = [...this.visit(andExpressionContexts[0])]; - for (let i = 1; i < andExpressionContexts.length; i++) { - items.push(new LogicalOperator(BooleanOperator.OR)); - items.push(...this.visit(andExpressionContexts[i])); - } - return items; + return andExpressionContexts.length === 1 ? [...this.visit(andExpressionContexts[0])] : [this.handleTaskRawQuery(ctx.getText())] }; /** @@ -256,8 +243,10 @@ export class PfqlVisitor extends QueryLangVisitor> { */ override visitTaskConditionGroupParenthesis = (ctx: TaskConditionGroupParenthesisContext): Array => { const innerItems: Array = [...this.visit(ctx.taskConditions())]; - const isNegated: boolean = !!ctx.NOT(); - return [new ComplexExpression(isNegated, innerItems)]; + if (!!ctx.NOT()) { + return [this.handleTaskRawQuery(ctx.getText())]; + } + return [new ComplexExpression(innerItems)]; }; /** @@ -268,6 +257,9 @@ export class PfqlVisitor extends QueryLangVisitor> { */ override visitTitleBasic = (ctx: TitleBasicContext): Array => { if (ctx.parent instanceof CaseComparisonsContext) { + if (!!ctx.stringComparison().NOT()) { + return [this.handleCaseRawQuery(ctx.getText())]; + } const expr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); expr.category = new CaseTitle(this._operatorService, this._logger); return [expr]; @@ -285,6 +277,9 @@ export class PfqlVisitor extends QueryLangVisitor> { */ override visitTitleLike = (ctx: TitleLikeContext): Array => { if (ctx.parent instanceof CaseComparisonsContext) { + if (!!ctx.stringLikeComparison().stringComparison().NOT()) { + return [this.handleCaseRawQuery(ctx.getText())]; + } const expr: SimpleExpression = this.handleStringLikeComparisonContext(ctx.stringLikeComparison()); expr.category = new CaseTitle(this._operatorService, this._logger); return [expr]; @@ -302,6 +297,9 @@ export class PfqlVisitor extends QueryLangVisitor> { */ override visitIdBasic = (ctx: IdBasicContext): Array => { if (ctx.parent instanceof CaseComparisonsContext) { + if (!!ctx.objectIdComparison().NOT()) { + return [this.handleCaseRawQuery(ctx.getText())]; + } const expr: SimpleExpression = this.handleObjectIdComparisonContext(ctx.objectIdComparison()); expr.category = new CaseStringId(this._operatorService, this._logger); return [expr]; @@ -318,6 +316,9 @@ export class PfqlVisitor extends QueryLangVisitor> { * @returns An array containing a single simple expression with case author category */ override visitAuthorBasic = (ctx: AuthorBasicContext): Array => { + if (!!ctx.stringComparison().NOT()) { + return [this.handleCaseRawQuery(ctx.getText())]; + } const expr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); expr.category = new CaseAuthor(this._operatorService, this._logger, this._categoryOptionalDependencies); return [expr]; @@ -330,6 +331,9 @@ export class PfqlVisitor extends QueryLangVisitor> { * @returns An array containing a single simple expression with case creation date category */ override visitCdDateBasic = (ctx: CdDateBasicContext): Array => { + if (!!ctx.dateComparison().NOT()) { + return [this.handleCaseRawQuery(ctx.getText())]; + } const expr: SimpleExpression = this.handleDateComparisonContext(ctx.dateComparison()); expr.category = new CaseCreationDate(this._operatorService, this._logger); return [expr]; @@ -342,6 +346,9 @@ export class PfqlVisitor extends QueryLangVisitor> { * @returns An array containing a single simple expression with case creation datetime category */ override visitCdDateTimeBasic = (ctx: CdDateTimeBasicContext): Array => { + if (!!ctx.dateTimeComparison().NOT()) { + return [this.handleCaseRawQuery(ctx.getText())]; + } const expr: SimpleExpression = this.handleDateTimeComparisonContext(ctx.dateTimeComparison()); expr.category = new CaseCreationDateTime(this._operatorService, this._logger); return [expr]; @@ -355,12 +362,15 @@ export class PfqlVisitor extends QueryLangVisitor> { */ override visitCdDateRange = (ctx: CdDateRangeContext): Array => { const inRangeCtx = ctx.inRangeDateComparison(); + if (!!inRangeCtx.NOT()) { + return [this.handleCaseRawQuery(ctx.getText())]; + } if (!!inRangeCtx.dateRange()) { - const expr: SimpleExpression = this.handleDateRangeContext(inRangeCtx.dateRange(), !!inRangeCtx.NOT()); + const expr: SimpleExpression = this.handleDateRangeContext(inRangeCtx.dateRange()); expr.category = new CaseCreationDate(this._operatorService, this._logger); return [expr]; } else if (!!inRangeCtx.dateTimeRange()) { - const expr: SimpleExpression = this.handleDateTimeRangeContext(inRangeCtx.dateTimeRange(), !!inRangeCtx.NOT()); + const expr: SimpleExpression = this.handleDateTimeRangeContext(inRangeCtx.dateTimeRange()); expr.category = new CaseCreationDateTime(this._operatorService, this._logger); return [expr]; } else { @@ -376,9 +386,12 @@ export class PfqlVisitor extends QueryLangVisitor> { * @returns An array containing a single data simple expression with case dataset category */ override visitDataString = (ctx: DataStringContext): Array => { + if (!!ctx.stringComparison().NOT()) { + return [this.handleCaseRawQuery(ctx.getText())]; + } const simpleExpr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, - simpleExpr.operandValue, simpleExpr.negated); + simpleExpr.operandValue); dataExpr.category = new CaseDataset(this._operatorService, this._logger, this._categoryOptionalDependencies); return [dataExpr]; }; @@ -390,9 +403,12 @@ export class PfqlVisitor extends QueryLangVisitor> { * @returns An array containing a single data simple expression with case dataset category and LIKE operator */ override visitDataStringLike = (ctx: DataStringLikeContext): Array => { + if (!!ctx.stringLikeComparison().stringComparison().NOT()) { + return [this.handleCaseRawQuery(ctx.getText())]; + } const simpleExpr: SimpleExpression = this.handleStringLikeComparisonContext(ctx.stringLikeComparison()); const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, - simpleExpr.operandValue, simpleExpr.negated); + simpleExpr.operandValue); dataExpr.category = new CaseDataset(this._operatorService, this._logger, this._categoryOptionalDependencies); return [dataExpr]; }; @@ -404,9 +420,12 @@ export class PfqlVisitor extends QueryLangVisitor> { * @returns An array containing a single data simple expression with case dataset category */ override visitDataNumber = (ctx: DataNumberContext): Array => { + if (!!ctx.numberComparison().NOT()) { + return [this.handleCaseRawQuery(ctx.getText())]; + } const simpleExpr: SimpleExpression = this.handleNumberComparisonContext(ctx.numberComparison()); const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, - simpleExpr.operandValue, simpleExpr.negated); + simpleExpr.operandValue); dataExpr.category = new CaseDataset(this._operatorService, this._logger, this._categoryOptionalDependencies); return [dataExpr]; }; @@ -418,9 +437,12 @@ export class PfqlVisitor extends QueryLangVisitor> { * @returns An array containing a single data simple expression with case dataset category and range operator */ override visitDataNumberRange = (ctx: DataNumberRangeContext): Array => { + if (!!ctx.inRangeNumberComparison().NOT()) { + return [this.handleCaseRawQuery(ctx.getText())]; + } const simpleExpr: SimpleExpression = this.handleInRangeNumberComparisonContext(ctx.inRangeNumberComparison()); const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, - simpleExpr.operandValue, simpleExpr.negated); + simpleExpr.operandValue); dataExpr.category = new CaseDataset(this._operatorService, this._logger, this._categoryOptionalDependencies); return [dataExpr]; }; @@ -432,9 +454,12 @@ export class PfqlVisitor extends QueryLangVisitor> { * @returns An array containing a single data simple expression with case dataset category */ override visitDataDate = (ctx: DataDateContext): Array => { + if (!!ctx.dateComparison().NOT()) { + return [this.handleCaseRawQuery(ctx.getText())]; + } const simpleExpr: SimpleExpression = this.handleDateComparisonContext(ctx.dateComparison()); const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, - simpleExpr.operandValue, simpleExpr.negated); + simpleExpr.operandValue); dataExpr.category = new CaseDataset(this._operatorService, this._logger, this._categoryOptionalDependencies); return [dataExpr]; }; @@ -447,18 +472,21 @@ export class PfqlVisitor extends QueryLangVisitor> { */ override visitDataDateRange = (ctx: DataDateRangeContext): Array => { const inRangeCtx = ctx.inRangeDateComparison(); + if (!!inRangeCtx.NOT()) { + return [this.handleCaseRawQuery(ctx.getText())]; + } let simpleExpr: SimpleExpression; if (!!inRangeCtx.dateRange()) { - simpleExpr = this.handleDateRangeContext(inRangeCtx.dateRange(), !!inRangeCtx.NOT()); + simpleExpr = this.handleDateRangeContext(inRangeCtx.dateRange()); } else if (!!inRangeCtx.dateTimeRange()) { - simpleExpr = this.handleDateTimeRangeContext(inRangeCtx.dateTimeRange(), !!inRangeCtx.NOT()); + simpleExpr = this.handleDateTimeRangeContext(inRangeCtx.dateTimeRange()); } else { this._logger.error("No range values provided for creationDate range comparison"); return []; } const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, - simpleExpr.operandValue, simpleExpr.negated); + simpleExpr.operandValue); dataExpr.category = new CaseDataset(this._operatorService, this._logger, this._categoryOptionalDependencies); return [dataExpr]; }; @@ -470,9 +498,12 @@ export class PfqlVisitor extends QueryLangVisitor> { * @returns An array containing a single data simple expression with case dataset category */ override visitDataDatetime = (ctx: DataDatetimeContext): Array => { + if (!!ctx.dateTimeComparison().NOT()) { + return [this.handleCaseRawQuery(ctx.getText())]; + } const simpleExpr: SimpleExpression = this.handleDateTimeComparisonContext(ctx.dateTimeComparison()); const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, - simpleExpr.operandValue, simpleExpr.negated); + simpleExpr.operandValue); dataExpr.category = new CaseDataset(this._operatorService, this._logger, this._categoryOptionalDependencies); return [dataExpr]; }; @@ -484,9 +515,12 @@ export class PfqlVisitor extends QueryLangVisitor> { * @returns An array containing a single data simple expression with case dataset category */ override visitDataBoolean = (ctx: DataBooleanContext): Array => { + if (!!ctx.booleanComparison().NOT()) { + return [this.handleCaseRawQuery(ctx.getText())]; + } const simpleExpr: SimpleExpression = this.handleBooleanComparisonContext(ctx.booleanComparison()); const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, - simpleExpr.operandValue, simpleExpr.negated); + simpleExpr.operandValue); dataExpr.category = new CaseDataset(this._operatorService, this._logger, this._categoryOptionalDependencies); return [dataExpr]; }; @@ -498,9 +532,12 @@ export class PfqlVisitor extends QueryLangVisitor> { * @returns An array containing a single data simple expression with case dataset category and null operator */ override visitDataNull = (ctx: DataNullContext): Array => { - const simpleExpr: SimpleExpression = this.handleNullComparisonContext(ctx.nullComparison()); + if (!!ctx.nullComparison().NOT()) { + return [this.handleCaseRawQuery(ctx.getText())]; + } + const simpleExpr: SimpleExpression = this.handleNullComparisonContext(); const dataExpr: DataSimpleExpression = new DataSimpleExpression(ctx.dataValue().getText(), simpleExpr.operator, - simpleExpr.operandValue, simpleExpr.negated); + simpleExpr.operandValue); dataExpr.category = new CaseDataset(this._operatorService, this._logger, this._categoryOptionalDependencies); return [dataExpr]; }; @@ -514,6 +551,9 @@ export class PfqlVisitor extends QueryLangVisitor> { * @returns An array containing a single simple expression with case process category */ override visitProcessIdentifierBasic = (ctx: ProcessIdentifierBasicContext): Array => { + if (!!ctx.stringComparison().NOT()) { + return [this.handleCaseRawQuery(ctx.getText())]; + } const expr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); expr.category = new CaseProcess(this._operatorService, this._logger, this._categoryOptionalDependencies); return [expr]; @@ -526,6 +566,9 @@ export class PfqlVisitor extends QueryLangVisitor> { * @returns An array containing a single simple expression with task task category */ override visitTransitionIdBasic = (ctx: TransitionIdBasicContext): Array => { + if (!!ctx.stringComparison().NOT()) { + return [this.handleTaskRawQuery(ctx.getText())]; + } const expr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); expr.category = new TaskTask(this._operatorService, this._logger, this._categoryOptionalDependencies); return [expr]; @@ -538,6 +581,9 @@ export class PfqlVisitor extends QueryLangVisitor> { * @returns An array containing a single simple expression with task assignee category */ override visitUserIdBasic = (ctx: UserIdBasicContext): Array => { + if (!!ctx.stringComparison().NOT()) { + return [this.handleTaskRawQuery(ctx.getText())]; + } const expr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); expr.category = new TaskAssignee(this._operatorService, this._logger, this._categoryOptionalDependencies); return [expr]; @@ -550,7 +596,10 @@ export class PfqlVisitor extends QueryLangVisitor> { * @returns An array containing a single simple expression with task assignee category and null operator */ override visitUserIdNull = (ctx: UserIdNullContext): Array => { - const expr: SimpleExpression = this.handleNullComparisonContext(ctx.nullComparison()); + if (!!ctx.nullComparison().NOT()) { + return [this.handleTaskRawQuery(ctx.getText())]; + } + const expr: SimpleExpression = this.handleNullComparisonContext(); expr.category = new TaskAssignee(this._operatorService, this._logger, this._categoryOptionalDependencies); return [expr]; }; @@ -562,6 +611,9 @@ export class PfqlVisitor extends QueryLangVisitor> { * @returns An array containing a single simple expression with task process category */ override visitProcessIdBasic = (ctx: ProcessIdBasicContext): Array => { + if (!!ctx.stringComparison().NOT()) { + return [this.handleTaskRawQuery(ctx.getText())]; + } const expr: SimpleExpression = this.handleStringComparisonContext(ctx.stringComparison()); expr.category = new TaskProcess(this._operatorService, this._logger, this._categoryOptionalDependencies); return [expr]; @@ -578,7 +630,7 @@ export class PfqlVisitor extends QueryLangVisitor> { protected handleStringComparisonContext(ctx: StringComparisonContext): SimpleExpression { const operator: Operator = getOperatorFromToken(ctx._op); const value: string = this.extractStringValueFromStringComparisonContext(ctx); - return new SimpleExpression(operator, value, !!ctx.NOT()); + return new SimpleExpression(operator, value); }; /** @@ -590,7 +642,7 @@ export class PfqlVisitor extends QueryLangVisitor> { protected handleStringLikeComparisonContext(ctx: StringLikeComparisonContext): SimpleExpression { const operator: Operator = new Like(); const value: string = this.extractStringValueFromStringComparisonContext(ctx.stringComparison()); - return new SimpleExpression(operator, value, !!ctx.stringComparison().NOT()); + return new SimpleExpression(operator, value); }; /** @@ -641,7 +693,7 @@ export class PfqlVisitor extends QueryLangVisitor> { const operator: Operator = getOperatorFromToken(ctx._op); const value: string = !!ctx.LOGGED_USER_ID() ? this._userService.user?.id : this.removeSingleQuotesFromString(ctx.STRING()?.getText()); - return new SimpleExpression(operator, value, !!ctx.NOT()); + return new SimpleExpression(operator, value); } /** @@ -653,7 +705,7 @@ export class PfqlVisitor extends QueryLangVisitor> { protected handleDateComparisonContext(ctx: DateComparisonContext): SimpleExpression { const operator: Operator = getDateOperatorFromToken(ctx._op, this._operatorService); const value: string = ctx.DATE()?.getText(); - return new SimpleExpression(operator, value, !!ctx.NOT()); + return new SimpleExpression(operator, value); } /** @@ -665,33 +717,31 @@ export class PfqlVisitor extends QueryLangVisitor> { protected handleDateTimeComparisonContext(ctx: DateTimeComparisonContext): SimpleExpression { const operator: Operator = getDateTimeOperatorFromToken(ctx._op, this._operatorService); const value: string = ctx.DATETIME()?.getText(); - return new SimpleExpression(operator, value, !!ctx.NOT()); + return new SimpleExpression(operator, value); } /** * Handles a date range context and creates a simple expression with the InRangeDate operator and date range values. * * @param ctx - The date range parse tree context - * @param isNegated - Whether the range comparison is negated - * @returns A simple expression with the InRangeDate operator, array of date values, and negation flag + * @returns A simple expression with the InRangeDate operator, and array of date values */ - protected handleDateRangeContext(ctx: DateRangeContext, isNegated: boolean): SimpleExpression { + protected handleDateRangeContext(ctx: DateRangeContext): SimpleExpression { const operator: Operator = new InRangeDate(); const value: string[] = ctx.DATE()?.map(terminalNode => terminalNode.getText()); - return new SimpleExpression(operator, value, isNegated); + return new SimpleExpression(operator, value); } /** * Handles a datetime range context and creates a simple expression with the InRangeDateTime operator and datetime range values. * * @param ctx - The datetime range parse tree context - * @param isNegated - Whether the range comparison is negated - * @returns A simple expression with the InRangeDateTime operator, array of datetime values, and negation flag + * @returns A simple expression with the InRangeDateTime operator, and array of datetime values */ - protected handleDateTimeRangeContext(ctx: DateTimeRangeContext, isNegated: boolean): SimpleExpression { + protected handleDateTimeRangeContext(ctx: DateTimeRangeContext): SimpleExpression { const operator: Operator = new InRangeDateTime(); const value: string[] = ctx.DATETIME()?.map(terminalNode => terminalNode.getText()); - return new SimpleExpression(operator, value, isNegated); + return new SimpleExpression(operator, value); } /** @@ -708,7 +758,7 @@ export class PfqlVisitor extends QueryLangVisitor> { } else if (!!ctx.DOUBLE()) { value = parseFloat(ctx.DOUBLE().getText()); } - return new SimpleExpression(operator, value, !!ctx.NOT()); + return new SimpleExpression(operator, value); } /** @@ -727,7 +777,7 @@ export class PfqlVisitor extends QueryLangVisitor> { fromValue = parseFloat(ctx.doubleRange().DOUBLE()[0].getText()); toValue = parseFloat(ctx.doubleRange().DOUBLE()[1].getText()); } - return new SimpleExpression(operator, [fromValue, toValue], !!ctx.NOT()); + return new SimpleExpression(operator, [fromValue, toValue]); } /** @@ -739,17 +789,28 @@ export class PfqlVisitor extends QueryLangVisitor> { protected handleBooleanComparisonContext(ctx: BooleanComparisonContext): SimpleExpression { const operator: Operator = getOperatorFromToken(ctx._op); const value: boolean = ctx.BOOLEAN().getText().toLowerCase() === 'true'; - return new SimpleExpression(operator, value, !!ctx.NOT()); + return new SimpleExpression(operator, value); } /** * Handles a null comparison context and creates a simple expression with the IsNull operator. * - * @param ctx - The null comparison parse tree context - * @returns A simple expression with the IsNull operator, undefined value, and negation flag + * @returns A simple expression with the IsNull operator */ - protected handleNullComparisonContext(ctx: NullComparisonContext): SimpleExpression { + protected handleNullComparisonContext(): SimpleExpression { const operator: Operator = new IsNull(); - return new SimpleExpression(operator, undefined, !!ctx.NOT()); + return new SimpleExpression(operator, undefined); + } + + // todo 2466 doc + protected handleCaseRawQuery(query: string): RawExpression { + const category: CasePlainQuery = new CasePlainQuery(this._operatorService, this._logger); + return new RawExpression(category, query); + } + + // todo 2466 doc + protected handleTaskRawQuery(query: string): RawExpression { + const category: TaskPlainQuery = new TaskPlainQuery(this._operatorService, this._logger); + return new RawExpression(category, query); } } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/plain-query-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/plain-query-category.ts index 3e06c1b705..b5138c1c9f 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/plain-query-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/plain-query-category.ts @@ -8,6 +8,7 @@ import {OperatorService} from "../../operator-service/operator.service"; import {LoggerService} from "../../../logger/services/logger.service"; import {SearchInputType} from "./search-input-type"; import {ResourceTypeQueryPrefix} from "./resource-type-query-prefix"; +import {RawExpression} from "../../../pfql/model/raw-expression"; export abstract class PlainQueryCategory extends Category { private static readonly _title = 'search.category.plainText'; // todo 2466 add translation @@ -46,6 +47,11 @@ export abstract class PlainQueryCategory extends Category { return; } + public loadFromPfqlRawExpression(expression: RawExpression): Observable { + this.setOperands([expression.rawQuery]); + return of(undefined); + } + get configurationInputs$(): Observable { return of([this._configurationInput]); } diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts index 599d718ca8..56e8591427 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts @@ -7,7 +7,7 @@ import {SimpleFilter} from '../../filter/models/simple-filter'; import {MergeOperator} from '../../filter/models/merge-operator'; import {PredicateRemovalEvent} from '../models/predicate-removal-event'; import {Query} from '../models/query/query'; -import {distinctUntilChanged, map, tap, filter} from 'rxjs/operators'; +import {distinctUntilChanged, filter, map, tap} from 'rxjs/operators'; import {EditableClausePredicateWithGenerators} from '../models/predicate/editable-clause-predicate-with-generators'; import {Category} from '../models/category/category'; import {PredicateTreeMetadata} from '../models/persistance/generator-metadata'; @@ -21,10 +21,11 @@ import {FilterMetadata} from '../models/persistance/filter-metadata'; import {FilterTextSegment} from '../models/persistance/filter-text-segment'; import {QueryItem, QueryItemType} from "../../pfql/model/query-item-type"; import {parseQuery} from "../../pfql/pfql-utils"; -import {LogicalOperator} from "../../pfql/model/logical-operator"; import {SimpleExpression} from "../../pfql/model/simple-expression"; import {ComplexExpression} from "../../pfql/model/complex-expression"; import {ResourceTypeQueryPrefix} from "../models/category/resource-type-query-prefix"; +import {RawExpression} from "../../pfql/model/raw-expression"; +import {PlainQueryCategory} from "../models/category/plain-query-category"; /** * Holds information about the filter that is currently applied to the view component, that provides this services. @@ -432,7 +433,7 @@ export class SearchService implements OnDestroy { return; } - const categoryLoadings$ = this.loadFromQueryItemsIntoRootPredicate(queryItems); + const categoryLoadings$ = this.loadExpressionsIntoPredicate(this.rootPredicate, queryItems); if (categoryLoadings$.length === 0) { this._loadingFromPfql$.off(); this.updateActiveFilter(); @@ -464,106 +465,27 @@ export class SearchService implements OnDestroy { } /** - * Recursively loads query items (expressions and operators) into a predicate tree node. - * - * Processes simple expressions by loading them into predicates (creating branch predicates for AND operators), - * and recursively handles complex expressions by creating new nested predicates. - * - * @param predicate the predicate node into which the expressions should be loaded - * @param operatorOfPredicate the boolean operator used by the predicate node - * @param items the array of query items (expressions and operators) to process - * @returns an array of observables that emit when category data is loaded for each simple expression + * todo 2466 */ - protected loadExpressionsIntoPredicate(predicate: EditableClausePredicateWithGenerators, operatorOfPredicate: BooleanOperator, - items: Array): Array> { + protected loadExpressionsIntoPredicate(predicate: EditableClausePredicateWithGenerators, items: Array): Array> { const expressions: Array = items.filter(item => item.type() !== QueryItemType.LOGICAL_OPERATOR); const categoryLoadings$: Array> = []; for (const expression of expressions) { if (expression.type() === QueryItemType.SIMPLE_EXPRESSION) { - let categoryLoading$: Observable; - if (operatorOfPredicate.valueOf() === BooleanOperator.AND.valueOf()) { - const branchId = predicate.addNewClausePredicate(BooleanOperator.OR); - const localPredicate = predicate.getPredicateMap().get(branchId).getWrappedPredicate() as unknown as EditableClausePredicateWithGenerators; - categoryLoading$ = this.loadSimpleExpressionIntoPredicate(localPredicate, expression as SimpleExpression); - } else { - categoryLoading$ = this.loadSimpleExpressionIntoPredicate(predicate, expression as SimpleExpression); - } + const categoryLoading$ = this.loadSimpleExpressionIntoPredicate(predicate, expression as SimpleExpression); categoryLoadings$.push(categoryLoading$); } else if (expression.type() === QueryItemType.COMPLEX_EXPRESSION) { - const subCategoryLoadings$: Array> = this.loadFromQueryItemsIntoNewPredicate(predicate, - operatorOfPredicate, (expression as ComplexExpression).items); + const complexExpression: ComplexExpression = expression as ComplexExpression; + const subCategoryLoadings$: Array> = this.loadExpressionsIntoPredicate(predicate, complexExpression.items) categoryLoadings$.push(...subCategoryLoadings$); + } else if (expression.type() === QueryItemType.RAW_EXPRESSION) { + const categoryLoading$ = this.loadPlainQueryIntoPredicate(predicate, expression as RawExpression); + categoryLoadings$.push(categoryLoading$); } } return categoryLoadings$; } - /** - * Creates a new branch predicate under the parent and loads query items into it. - * - * Determines the appropriate boolean operator from the query items, creates a new clause predicate - * with that operator, and recursively loads the expressions into the new predicate. - * - * @param parentPredicate the parent predicate under which to create the new branch - * @param operatorOfParentPredicate boolean operator of the parentPredicate - * @param items the array of query items to load into the new predicate branch - * @returns an array of observables that emit when category data is loaded for each simple expression - */ - protected loadFromQueryItemsIntoNewPredicate(parentPredicate: EditableClausePredicateWithGenerators, - operatorOfParentPredicate: BooleanOperator, - items: Array): Array> { - if (!this.areBooleanOperatorsOfSingleType(items)) { - throw new Error("Cannot load the PFQL query. There are different boolean operators in the same group of expressions") - } - const booleanOperator: BooleanOperator = this.determineBooleanOperator(items); - if (operatorOfParentPredicate === booleanOperator) { - return this.loadExpressionsIntoPredicate(parentPredicate, booleanOperator, items); - } - const branchId = parentPredicate.addNewClausePredicate(booleanOperator); - const branchPredicate = parentPredicate.getPredicateMap().get(branchId).getWrappedPredicate() as unknown as EditableClausePredicateWithGenerators - return this.loadExpressionsIntoPredicate(branchPredicate, booleanOperator, items); - } - - /** - * Loads query items into the root predicate of the search service. - * - * Validates that all boolean operators in the query items are of the same type (all AND or all OR). - * Determines the appropriate boolean operator from the items and loads expressions accordingly. - * If the operator is OR, creates a new branch predicate under the root; otherwise loads directly into root. - * - * @param items the array of query items (expressions and operators) to load into the root predicate - * @returns an array of observables that emit when category data is loaded for each simple expression - * @throws Error if the query items contain different boolean operator types in the same group - */ - protected loadFromQueryItemsIntoRootPredicate(items: Array): Array> { - if (!this.areBooleanOperatorsOfSingleType(items)) { - throw new Error("Cannot load the PFQL query. There are different boolean operators in the same group of expressions") - } - const booleanOperator: BooleanOperator = this.determineBooleanOperator(items); - let targetPredicate = this.rootPredicate; - - if (booleanOperator === BooleanOperator.OR) { - const branchId = this.rootPredicate.addNewClausePredicate(booleanOperator); - targetPredicate = this.rootPredicate.getPredicateMap().get(branchId).getWrappedPredicate() as unknown as EditableClausePredicateWithGenerators - } - - return this.loadExpressionsIntoPredicate(targetPredicate, booleanOperator, items); - } - - /** - * Determines the boolean operator to use for combining query items. - * - * Extracts logical operators from the query items array. If no logical operators are found, - * defaults to AND. If logical operators are present, uses the first one found. - * - * @param items the array of query items to examine - * @returns the boolean operator (AND or OR) determined from the query items - */ - protected determineBooleanOperator(items: Array): BooleanOperator { - const booleanOperators = items.filter(item => item.type() === QueryItemType.LOGICAL_OPERATOR); - return booleanOperators.length === 0 ? BooleanOperator.AND : (booleanOperators[0] as LogicalOperator).value; - } - /** * Loads a simple PFQL expression into a predicate node. * @@ -575,16 +497,21 @@ export class SearchService implements OnDestroy { * @returns an observable that emits when the category data has been loaded from the expression */ protected loadSimpleExpressionIntoPredicate(predicate: EditableClausePredicateWithGenerators, simpleExpr: SimpleExpression): Observable { + const branchId = predicate.addNewClausePredicate(BooleanOperator.OR); + const localPredicate = predicate.getPredicateMap().get(branchId).getWrappedPredicate() as unknown as EditableClausePredicateWithGenerators; const category: Category = simpleExpr.category; const categoryLoading$: Observable = category.loadFromPfqlExpression(simpleExpr); - predicate.addNewPredicateFromGenerator(category); + localPredicate.addNewPredicateFromGenerator(category); return categoryLoading$; } - protected areBooleanOperatorsOfSingleType(items: Array): boolean { - const operators: Array = items.filter(item => item.type() === QueryItemType.LOGICAL_OPERATOR) - .map(operator => operator as LogicalOperator); - - return operators.length === 0 || operators.every(op => op.value === operators[0].value); + // todo 2466 doc + protected loadPlainQueryIntoPredicate(predicate: EditableClausePredicateWithGenerators, expression: RawExpression): Observable{ + const branchId = predicate.addNewClausePredicate(BooleanOperator.OR); + const localPredicate = predicate.getPredicateMap().get(branchId).getWrappedPredicate() as unknown as EditableClausePredicateWithGenerators; + const category: PlainQueryCategory = expression.category; + const categoryLoading$: Observable = category.loadFromPfqlRawExpression(expression); + localPredicate.addNewPredicateFromGenerator(category); + return categoryLoading$; } } From 5e695e48b1723cec0440f86633b82b0eb23a615a Mon Sep 17 00:00:00 2001 From: chvostek Date: Wed, 12 Aug 2026 10:39:12 +0200 Subject: [PATCH 29/55] [NAE-2466] Advanced search for PFQL - implement possibility to show filter field as advanced search in form - change default component of filter to string-query --- ...abstract-filter-field-content.component.ts | 11 ++++-- ...abstract-filter-default-field.component.ts | 37 ++++++++++++++++-- .../filter-field/models/filter-field.ts | 10 ++++- .../search/search-service/search.service.ts | 2 +- .../services/field-converter.service.ts | 2 +- .../src/lib/data-fields/data-fields.module.ts | 3 +- .../filter-default-field.component.html | 2 +- .../filter-default-field.component.ts | 16 ++++++-- .../filter-field-content.component.ts | 39 +++++++++++++++---- 9 files changed, 97 insertions(+), 25 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-content.component.ts b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-content.component.ts index 9caf46d1b6..5eecb790f2 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-content.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-content.component.ts @@ -3,7 +3,8 @@ import {NAE_FILTER_FIELD} from './models/filter-field-injection-token'; import {FilterField} from './models/filter-field'; import {SearchService} from '../../search/search-service/search.service'; import {filter, take} from 'rxjs/operators'; -import {Subscription} from 'rxjs'; +import {Subscription, Observable} from 'rxjs'; +import {Query} from "../../search/models/query/query"; @Component({ selector: 'ncc-abstract-filtercontent-field', @@ -17,8 +18,8 @@ export abstract class AbstractFilterFieldContentComponent implements OnDestroy { protected constructor(@Inject(NAE_FILTER_FIELD) protected _filterField: FilterField, protected _fieldSearchService: SearchService) { - this._fieldSearchService.loadFromMetadata(this._filterField.filterMetadata); - this._searchServiceSub = this._fieldSearchService.loadingFromMetadata$.pipe(filter(loading => !loading), take(1)).subscribe(() => { + this._fieldSearchService.loadFromPfql(this._filterField.value); + this._searchServiceSub = this._fieldSearchService.loadingFromPfql$.pipe(filter(loading => !loading), take(1)).subscribe(() => { this.filterLoaded = true; }); } @@ -33,4 +34,8 @@ export abstract class AbstractFilterFieldContentComponent implements OnDestroy { } } + public predicateQueryChanged$(): Observable { + return this._fieldSearchService.predicateQueryChanged$; + } + } diff --git a/projects/netgrif-components-core/src/lib/data-fields/filter-field/filter-default-field/abstract-filter-default-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/filter-field/filter-default-field/abstract-filter-default-field.component.ts index d53abf75e2..ceb3cfe6a0 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/filter-field/filter-default-field/abstract-filter-default-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/filter-field/filter-default-field/abstract-filter-default-field.component.ts @@ -1,19 +1,26 @@ -import {Component, Inject, Injector, OnInit, Optional, StaticProvider} from "@angular/core"; +import {Component, ComponentRef, Inject, Injector, OnDestroy, OnInit, Optional, StaticProvider} from "@angular/core"; import {ComponentPortal, ComponentType} from "@angular/cdk/portal"; import {AbstractFilterFieldContentComponent} from "../abstract-filter-field-content.component"; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; import {FilterField} from "../models/filter-field"; import {NAE_FILTER_FIELD} from "../models/filter-field-injection-token"; import {AbstractBaseDataFieldComponent} from "../../base-component/abstract-base-data-field.component"; +import { + AbstractFilterStringQueryFieldComponent +} from "../filter-string-query-field/abstract-filter-string-query-field.component"; +import {Subscription} from "rxjs"; +import {skip} from "rxjs/operators"; @Component({ selector: 'ncc-abstract-filter-default-field', template: '' }) -export abstract class AbstractFilterDefaultFieldComponent extends AbstractBaseDataFieldComponent implements OnInit { +export abstract class AbstractFilterDefaultFieldComponent extends AbstractBaseDataFieldComponent implements OnInit, OnDestroy { public initialized: boolean; - public portal: ComponentPortal; + public portal: ComponentPortal; + + protected _contentQuerySub: Subscription; constructor(protected _parentInjector: Injector, @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { @@ -29,9 +36,31 @@ export abstract class AbstractFilterDefaultFieldComponent extends AbstractBaseDa this.initialized = true; } + ngOnDestroy(): void { + super.ngOnDestroy(); + if (this._contentQuerySub && !this._contentQuerySub.closed) { + this._contentQuerySub.unsubscribe(); + } + } + public get editable(): boolean { return !!this.dataField.behavior.editable; } - protected abstract getFilterContentComponent(): ComponentType; + protected abstract getFilterContentComponent(): ComponentType; + + public onContentAttached(ref: ComponentRef): void { + if (this._contentQuerySub && !this._contentQuerySub.closed) { + this._contentQuerySub.unsubscribe(); + } + + const instance = ref.instance; + if (instance instanceof AbstractFilterFieldContentComponent) { + this._contentQuerySub = instance.predicateQueryChanged$().pipe( + skip(1) // skip first emission from loadFromPfql + ).subscribe(query => { + this.formControlRef.setValue(query.value ? query.value : ''); + }); + } + } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/filter-field/models/filter-field.ts b/projects/netgrif-components-core/src/lib/data-fields/filter-field/models/filter-field.ts index 36ae44b240..e1668fb47f 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/filter-field/models/filter-field.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/filter-field/models/filter-field.ts @@ -4,6 +4,7 @@ import {Layout} from '../../models/layout'; import {Component, ComponentPrefixes} from '../../models/component'; import {FilterMetadata} from '../../../search/models/persistance/filter-metadata'; import {Validation} from '../../models/validation'; +import {FieldTypeResource} from "../../../task-content/model/field-type-resource"; export enum FilterFieldValidation { REQUIRED = 'required' @@ -12,14 +13,19 @@ export enum FilterFieldValidation { export class FilterField extends DataField { constructor(stringId: string, title: string, - initialValue: string, private _filterMetadata: FilterMetadata, private _allowedNets: Array, + initialValue: string, private _filterType: FieldTypeResource, private _allowedNets: Array, behavior: Behavior, placeholder: string, description: string, layout?: Layout, validations?: Array, component?: Component, parentTaskId?: string) { super(stringId, title, initialValue, behavior, placeholder, description, layout, validations, component, parentTaskId); } get filterMetadata(): FilterMetadata { - return this._filterMetadata; + // todo 2466 remove + return undefined; + } + + get filterType(): FieldTypeResource { + return this._filterType; } get allowedNets(): Array { diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts index 56e8591427..fdae4ee0d8 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts @@ -219,7 +219,7 @@ export class SearchService implements OnDestroy { /** * @returns an Observable that emits whenever the root predicates query changes */ - protected get predicateQueryChanged$(): Observable { + public get predicateQueryChanged$(): Observable { return this._predicateQueryChanged$.asObservable().pipe( map(() => this._rootPredicate.query), distinctUntilChanged((prev, curr) => prev && prev.equals(curr)) diff --git a/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.ts b/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.ts index 13eb0a56db..62c0efe9f8 100644 --- a/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.ts +++ b/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.ts @@ -111,7 +111,7 @@ export class FieldConverterService { case FieldTypeResource.CASE_FILTER: case FieldTypeResource.TASK_FILTER: case FieldTypeResource.PROCESS_FILTER: - return new FilterField(item.stringId, item.name, item.value ?? '', item.filterMetadata, item.allowedNets, + return new FilterField(item.stringId, item.name, item.value ?? '', item.type, item.allowedNets, item.behavior, item.placeholder, item.description, item.layout, item.validations, item.component, item.parentTaskId); case FieldTypeResource.I18N: return new I18nField(item.stringId, item.name, item.value ?? {defaultValue: ''}, item.behavior, item.placeholder, diff --git a/projects/netgrif-components/src/lib/data-fields/data-fields.module.ts b/projects/netgrif-components/src/lib/data-fields/data-fields.module.ts index 210300cfa9..322edc43c9 100644 --- a/projects/netgrif-components/src/lib/data-fields/data-fields.module.ts +++ b/projects/netgrif-components/src/lib/data-fields/data-fields.module.ts @@ -244,7 +244,8 @@ export class DataFieldsComponentModule { registry.register("file-list-default", (injector: Injector) => new ComponentPortal(FileListDefaultFieldComponent, null, injector)); registry.register("filter-default", (injector: Injector) => new ComponentPortal(FilterDefaultFieldComponent, null, injector)); registry.register("filter-filter-tab-view", (injector: Injector) => new ComponentPortal(FilterDefaultFieldComponent, null, injector)); - registry.register("filter-string_query", (injector: Injector) => new ComponentPortal(FilterStringQueryFieldComponent, null, injector)); + registry.register("filter-string-query", (injector: Injector) => new ComponentPortal(FilterStringQueryFieldComponent, null, injector)); + registry.register("filter-advanced-search-query", (injector: Injector) => new ComponentPortal(FilterDefaultFieldComponent, null, injector)); registry.register("i18n-divider", (injector: Injector) => new ComponentPortal(I18nDividerFieldComponent, null, injector)); registry.register("i18n-text", (injector: Injector) => new ComponentPortal(I18nTextFieldComponent, null, injector)); registry.register("i18n-default", (injector: Injector) => new ComponentPortal(I18nTextFieldComponent, null, injector)); diff --git a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-default-field/filter-default-field.component.html b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-default-field/filter-default-field.component.html index 4bd39088cb..bd2af17408 100644 --- a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-default-field/filter-default-field.component.html +++ b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-default-field/filter-default-field.component.html @@ -1,3 +1,3 @@ - + diff --git a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-default-field/filter-default-field.component.ts b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-default-field/filter-default-field.component.ts index 71401f7f3f..6aa867a466 100644 --- a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-default-field/filter-default-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-default-field/filter-default-field.component.ts @@ -7,8 +7,11 @@ import { DataFieldPortalData, FilterField, AbstractFilterFieldContentComponent, - Dashboard, AbstractFilterDefaultFieldComponent + Dashboard, + AbstractFilterDefaultFieldComponent, + AbstractFilterStringQueryFieldComponent } from '@netgrif/components-core'; +import {FilterStringQueryFieldComponent} from "../filter-string-query-field/filter-string-query-field.component"; @Component({ selector: 'nc-filter-default-field', @@ -22,11 +25,16 @@ export class FilterDefaultFieldComponent extends AbstractFilterDefaultFieldCompo super(parentInjector, dataFieldPortalData); } - protected getFilterContentComponent(): ComponentType { - if (this.dataField.component?.name === Dashboard.FILTER_TAB_VIEW_COMPONENT_ID) { + protected override getFilterContentComponent(): ComponentType { + const componentName: string = this.dataField.component?.name; + if (componentName === Dashboard.FILTER_TAB_VIEW_COMPONENT_ID) { return FilterFieldTabViewContentComponent; + } else if (componentName === 'string-query') { + return FilterStringQueryFieldComponent; + } else if (componentName === 'advanced-search-query') { + return FilterFieldContentComponent; } - return FilterFieldContentComponent; + return FilterStringQueryFieldComponent; } } diff --git a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.ts b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.ts index 94eaebf144..36ae7acfca 100644 --- a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.ts @@ -3,23 +3,45 @@ import { AbstractFilterFieldContentComponent, SearchService, AllowedNetsService, - AllowedNetsServiceFactory, FilterField, NAE_FILTER_FIELD, NAE_BASE_FILTER, BaseFilter, - SimpleFilter, CategoryResolverService, NAE_SEARCH_CATEGORIES, Category, CategoryFactory + AllowedNetsServiceFactory, + FilterField, + NAE_FILTER_FIELD, + NAE_BASE_FILTER, + BaseFilter, + SimpleFilter, + NAE_SEARCH_CATEGORIES, + Category, + CategoryFactory, + FilterType, + FieldTypeResource, + NAE_DEFAULT_CASE_SEARCH_CATEGORIES, + NAE_DEFAULT_TASK_SEARCH_CATEGORIES } from '@netgrif/components-core'; export function filterFieldBaseFilterFactory(filterField: FilterField): BaseFilter { + let filterType: FilterType; + if (filterField.filterType === FieldTypeResource.CASE_FILTER) { + filterType = FilterType.CASE; + } else if (filterField.filterType === FieldTypeResource.TASK_FILTER) { + filterType = FilterType.TASK; + } return { - filter: SimpleFilter.empty(filterField.filterMetadata.filterType) + filter: SimpleFilter.empty(filterType) }; } export function filterFieldAllowedNetsFactory(factory: AllowedNetsServiceFactory, filterField: FilterField): AllowedNetsService { - return factory.createFromArray(filterField.allowedNets); + return factory.createFromArray(filterField.allowedNets ? filterField.allowedNets : []); } -export function filterFieldCategoriesFactory(factory: CategoryResolverService, filterField: FilterField): Array>> { - const result = filterField.filterMetadata.searchCategories.map(c => factory.toClass(c)); - return result; +export function filterFieldCategoriesFactory(filterField: FilterField, caseCategories: Array>>, + taskCategories: Array>>): Array>> { + if (filterField.filterType === FieldTypeResource.CASE_FILTER) { + return caseCategories; + } else if (filterField.filterType === FieldTypeResource.TASK_FILTER) { + return taskCategories; + } + return []; } @Component({ @@ -30,7 +52,8 @@ export function filterFieldCategoriesFactory(factory: CategoryResolverService, f {provide: NAE_BASE_FILTER, useFactory: filterFieldBaseFilterFactory, deps: [NAE_FILTER_FIELD]}, {provide: AllowedNetsService, useFactory: filterFieldAllowedNetsFactory, deps: [AllowedNetsServiceFactory, NAE_FILTER_FIELD]}, CategoryFactory, - {provide: NAE_SEARCH_CATEGORIES, useFactory: filterFieldCategoriesFactory, deps: [CategoryResolverService, NAE_FILTER_FIELD]}, + {provide: NAE_SEARCH_CATEGORIES, useFactory: filterFieldCategoriesFactory, deps: [NAE_FILTER_FIELD, + NAE_DEFAULT_CASE_SEARCH_CATEGORIES, NAE_DEFAULT_TASK_SEARCH_CATEGORIES]}, SearchService ] }) From 05881942013a33e7aee57202d8410edbba7e930a Mon Sep 17 00:00:00 2001 From: chvostek Date: Thu, 13 Aug 2026 19:41:12 +0200 Subject: [PATCH 30/55] [NAE-2466] Advanced search for PFQL - update CaseProcess category so when used in form there is no autocomplete --- .../src/lib/pfql/pfql-visitor.ts | 3 ++- .../lib/search/category-factory/category-factory.ts | 7 +++++-- .../category-factory/optional-dependencies.ts | 2 ++ .../search-categories-injection-token.ts | 3 +++ .../search/models/category/autocomplete-category.ts | 13 ++++++++++--- .../case-net-attribute-autocomplete-category.ts | 2 +- .../lib/search/models/category/case/case-process.ts | 11 +++++++++-- .../src/lib/search/models/category/category.ts | 9 ++++++++- .../category/net-attribute-autocomplete-category.ts | 2 +- .../task-net-attribute-autocomplete-category.ts | 2 +- .../src/lib/search/search-service/search.service.ts | 7 +++++-- .../tests/search-category-mock-dependencies.ts | 3 ++- .../filter-field-content.component.ts | 4 +++- .../search-predicate.component.ts | 10 ++++++---- 14 files changed, 58 insertions(+), 20 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts index a25cdf464a..cf57ea8241 100644 --- a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts +++ b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts @@ -112,7 +112,8 @@ export class PfqlVisitor extends QueryLangVisitor> { categoryFactory: this._categoryFactory, searchIndexResolver: undefined, allowedNetsService: this._allowedNetsService, - userResourceService: this._userResourceService + userResourceService: this._userResourceService, + ignoreNetsOnAutocompleteCategories: undefined, // todo 2466 auto }; } diff --git a/projects/netgrif-components-core/src/lib/search/category-factory/category-factory.ts b/projects/netgrif-components-core/src/lib/search/category-factory/category-factory.ts index 9dc6987490..0d08ccde8f 100644 --- a/projects/netgrif-components-core/src/lib/search/category-factory/category-factory.ts +++ b/projects/netgrif-components-core/src/lib/search/category-factory/category-factory.ts @@ -1,4 +1,4 @@ -import {Injectable, Optional, Type} from '@angular/core'; +import {Inject, Injectable, Optional, Type} from '@angular/core'; import {LoggerService} from '../../logger/services/logger.service'; import {OperatorService} from '../operator-service/operator.service'; import {Category} from '../models/category/category'; @@ -9,6 +9,7 @@ import {CategoryGeneratorMetadata} from '../models/persistance/generator-metadat import {CategoryResolverService} from './category-resolver.service'; import {AllowedNetsService} from '../../allowed-nets/services/allowed-nets.service'; import {Observable, ReplaySubject} from 'rxjs'; +import {NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY} from "./search-categories-injection-token"; /** * Can be used to generate {@link Category} class instances. @@ -28,12 +29,14 @@ export class CategoryFactory { protected _searchIndexResolverService: SearchIndexResolverService, protected _categoryResolver: CategoryResolverService, protected _allowedNetsService: AllowedNetsService, - @Optional() protected _userResourceService: UserResourceService) { + @Optional() protected _userResourceService: UserResourceService, + @Optional() @Inject(NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY) protected _ignoreNetsOnAutocompleteCategories: boolean) { this._optionalDependencies = { categoryFactory: this, searchIndexResolver: this._searchIndexResolverService, allowedNetsService: this._allowedNetsService, userResourceService: this._userResourceService, + ignoreNetsOnAutocompleteCategories: this._ignoreNetsOnAutocompleteCategories, }; } diff --git a/projects/netgrif-components-core/src/lib/search/category-factory/optional-dependencies.ts b/projects/netgrif-components-core/src/lib/search/category-factory/optional-dependencies.ts index e068ab1ab4..ffe7882359 100644 --- a/projects/netgrif-components-core/src/lib/search/category-factory/optional-dependencies.ts +++ b/projects/netgrif-components-core/src/lib/search/category-factory/optional-dependencies.ts @@ -20,4 +20,6 @@ export interface OptionalDependencies { * If the {@link CategoryFactory} cannot inject an instance of this service into itself `null` will be provided. */ userResourceService: UserResourceService | null; + // todo 2466 + ignoreNetsOnAutocompleteCategories?: boolean; } diff --git a/projects/netgrif-components-core/src/lib/search/category-factory/search-categories-injection-token.ts b/projects/netgrif-components-core/src/lib/search/category-factory/search-categories-injection-token.ts index 0009a4e2f8..72c2e15380 100644 --- a/projects/netgrif-components-core/src/lib/search/category-factory/search-categories-injection-token.ts +++ b/projects/netgrif-components-core/src/lib/search/category-factory/search-categories-injection-token.ts @@ -25,3 +25,6 @@ export const NAE_DEFAULT_CASE_SEARCH_CATEGORIES = new InjectionToken>>>('NaeDefaultTaskSearchCategories'); + +// todo 2466 +export const NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY = new InjectionToken('NaeIgnoreNetsOnAutocompleteCategory') diff --git a/projects/netgrif-components-core/src/lib/search/models/category/autocomplete-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/autocomplete-category.ts index c6c05e236b..45e5ecddf6 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/autocomplete-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/autocomplete-category.ts @@ -15,7 +15,7 @@ import {ResourceTypeQueryPrefix} from "./resource-type-query-prefix"; * * @typeparam T type of the object that the autocomplete option values use and in turn is used to generate queries */ -export abstract class AutocompleteCategory extends Category> implements AutocompleteOptions { +export abstract class AutocompleteCategory extends Category | string> implements AutocompleteOptions { /** * Autocomplete categories usually require a map to represent mapping of display names @@ -136,6 +136,10 @@ export abstract class AutocompleteCategory extends Category> impleme } protected isOperandValueSelected(newValue: SearchAutocompleteOption> | string): boolean { + if (this.inputType === SearchInputType.TEXT) { + return !!newValue; + } + return !(!newValue || typeof newValue === 'string'); } @@ -147,8 +151,11 @@ export abstract class AutocompleteCategory extends Category> impleme * @param value the FormControlValue * @returns the value used for query generation */ - protected transformCategoryValue(value: SearchAutocompleteOption>): Array { - return value.value; + protected transformCategoryValue(value: SearchAutocompleteOption> | string): Array | string { + if (this.inputType === SearchInputType.TEXT) { + return value as string; + } + return (value as SearchAutocompleteOption>).value; } protected serializeOperandValue(valueFormControl: FormControl): unknown { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-net-attribute-autocomplete-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-net-attribute-autocomplete-category.ts index 3ae57e55db..a967fb5041 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-net-attribute-autocomplete-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-net-attribute-autocomplete-category.ts @@ -32,7 +32,7 @@ export abstract class CaseNetAttributeAutocompleteCategory extends NetAttributeA this._processCategory.destroy(); } - protected getProcessCategory(): Category> { + protected getProcessCategory(): Category | string> { return this._processCategory; } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts index ccaae23459..b3db5c1cdd 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts @@ -12,6 +12,7 @@ import {CaseSearch} from './case-search.enum'; import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; import {take, filter} from "rxjs/operators"; import {SimpleExpression} from "../../../../pfql/model/simple-expression"; +import {SearchInputType} from "../search-input-type"; export class CaseProcess extends NoConfigurationAutocompleteCategory { @@ -29,6 +30,9 @@ export class CaseProcess extends NoConfigurationAutocompleteCategory { operators, ResourceTypeQueryPrefix.CASES); this._uniqueOptionsMap = new Map>(); + if (!!this._optionalDependencies.ignoreNetsOnAutocompleteCategories) { + this.inputType = SearchInputType.TEXT; + } } destroy() { @@ -93,11 +97,14 @@ export class CaseProcess extends NoConfigurationAutocompleteCategory { } } - protected generateQuery(userInput: Array>): Query { + protected generateQuery(userInput: Array | string>): Query { if (this.selectedOperator.numberOfOperands !== 1) { throw new Error('Only unary operators are currently supported by the CaseProcess implementation'); } - const operand = userInput[0]; + let operand = userInput[0]; + if (!Array.isArray(operand)) { + operand = [operand]; + } const queries = operand.map(id => this.selectedOperator.createQuery(this.pfqlKeywords, [id])); return Query.combineQueries(queries, BooleanOperator.OR).addPrefixAndGet(ResourceTypeQueryPrefix.CASES); } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/category.ts b/projects/netgrif-components-core/src/lib/search/models/category/category.ts index dd178cffec..7182f751ed 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/category.ts @@ -97,7 +97,7 @@ export abstract class Category { protected constructor(protected readonly _pfqlKeywords: Array, protected readonly _allowedOperators: Array>, public readonly translationPath: string, - protected readonly _inputType: SearchInputType, + protected _inputType: SearchInputType, protected _log: LoggerService, protected _operatorService: OperatorService, protected _resourceTypePrefix: ResourceTypeQueryPrefix) { @@ -199,6 +199,13 @@ export abstract class Category { return this._inputType; } + /** + * todo 2466 doc + */ + public set inputType(inputType: SearchInputType) { + this._inputType = inputType; + } + /** * @returns the set of Operators that can be used with this category. Iteration order determines the display order. */ diff --git a/projects/netgrif-components-core/src/lib/search/models/category/net-attribute-autocomplete-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/net-attribute-autocomplete-category.ts index 8eef9e749b..70adadbe02 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/net-attribute-autocomplete-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/net-attribute-autocomplete-category.ts @@ -76,7 +76,7 @@ export abstract class NetAttributeAutocompleteCategory extends NoConfigurationAu * * Currently it can be either the {@link CaseProcess} or the {@link TaskProcess} category class. */ - protected abstract getProcessCategory(): Category>; + protected abstract getProcessCategory(): Category | string>; /** * This method should return the appropriate identifier of a PetriNet. diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-net-attribute-autocomplete-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-net-attribute-autocomplete-category.ts index 74ee8bf36b..f644ec932f 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-net-attribute-autocomplete-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-net-attribute-autocomplete-category.ts @@ -31,7 +31,7 @@ export abstract class TaskNetAttributeAutocompleteCategory extends NetAttributeA this._processCategory.destroy(); } - protected getProcessCategory(): Category> { + protected getProcessCategory(): Category | string> { return this._processCategory; } diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts index fdae4ee0d8..e69457f2b4 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts @@ -26,6 +26,7 @@ import {ComplexExpression} from "../../pfql/model/complex-expression"; import {ResourceTypeQueryPrefix} from "../models/category/resource-type-query-prefix"; import {RawExpression} from "../../pfql/model/raw-expression"; import {PlainQueryCategory} from "../models/category/plain-query-category"; +import { NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY } from "../category-factory/search-categories-injection-token"; /** * Holds information about the filter that is currently applied to the view component, that provides this services. @@ -69,11 +70,13 @@ export class SearchService implements OnDestroy { * It is required if we want to load predicate filter from saved metadata * @param baseFilter Filter that should be applied to the view when no searching is being performed. * Injected trough the {@link NAE_BASE_FILTER} injection token. + * @param _ignoreNetsOnAutocompleteCategories todo 2466 * @param _injector injector from angular core */ constructor(protected _log: LoggerService, @Optional() protected _categoryFactory: CategoryFactory, @Inject(NAE_BASE_FILTER) baseFilter: BaseFilter, + @Optional() @Inject(NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY) protected _ignoreNetsOnAutocompleteCategories: boolean, protected _injector: Injector) { if (baseFilter.filter instanceof Filter) { this._baseFilter = baseFilter.filter.clone(); @@ -476,7 +479,7 @@ export class SearchService implements OnDestroy { categoryLoadings$.push(categoryLoading$); } else if (expression.type() === QueryItemType.COMPLEX_EXPRESSION) { const complexExpression: ComplexExpression = expression as ComplexExpression; - const subCategoryLoadings$: Array> = this.loadExpressionsIntoPredicate(predicate, complexExpression.items) + const subCategoryLoadings$: Array> = this.loadExpressionsIntoPredicate(predicate, complexExpression.items); categoryLoadings$.push(...subCategoryLoadings$); } else if (expression.type() === QueryItemType.RAW_EXPRESSION) { const categoryLoading$ = this.loadPlainQueryIntoPredicate(predicate, expression as RawExpression); @@ -500,7 +503,7 @@ export class SearchService implements OnDestroy { const branchId = predicate.addNewClausePredicate(BooleanOperator.OR); const localPredicate = predicate.getPredicateMap().get(branchId).getWrappedPredicate() as unknown as EditableClausePredicateWithGenerators; const category: Category = simpleExpr.category; - const categoryLoading$: Observable = category.loadFromPfqlExpression(simpleExpr); + const categoryLoading$: Observable = category.loadFromPfqlExpression(simpleExpr); // todo 2466 auto localPredicate.addNewPredicateFromGenerator(category); return categoryLoading$; } diff --git a/projects/netgrif-components-core/src/lib/utility/tests/search-category-mock-dependencies.ts b/projects/netgrif-components-core/src/lib/utility/tests/search-category-mock-dependencies.ts index dfea0073f5..b9d7704853 100644 --- a/projects/netgrif-components-core/src/lib/utility/tests/search-category-mock-dependencies.ts +++ b/projects/netgrif-components-core/src/lib/utility/tests/search-category-mock-dependencies.ts @@ -31,7 +31,8 @@ export const createMockDependencies: ( searchIndexResolver, new CategoryResolverService(), allowedNetsService, - userResourceService + userResourceService, + false ), searchIndexResolver, userResourceService, diff --git a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.ts b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.ts index 36ae7acfca..318c50d14f 100644 --- a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.ts @@ -15,7 +15,8 @@ import { FilterType, FieldTypeResource, NAE_DEFAULT_CASE_SEARCH_CATEGORIES, - NAE_DEFAULT_TASK_SEARCH_CATEGORIES + NAE_DEFAULT_TASK_SEARCH_CATEGORIES, + NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY } from '@netgrif/components-core'; export function filterFieldBaseFilterFactory(filterField: FilterField): BaseFilter { @@ -50,6 +51,7 @@ export function filterFieldCategoriesFactory(filterField: FilterField, caseCateg styleUrls: ['./filter-field-content.component.scss'], providers: [ {provide: NAE_BASE_FILTER, useFactory: filterFieldBaseFilterFactory, deps: [NAE_FILTER_FIELD]}, + {provide: NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY, useValue: true}, {provide: AllowedNetsService, useFactory: filterFieldAllowedNetsFactory, deps: [AllowedNetsServiceFactory, NAE_FILTER_FIELD]}, CategoryFactory, {provide: NAE_SEARCH_CATEGORIES, useFactory: filterFieldCategoriesFactory, deps: [NAE_FILTER_FIELD, diff --git a/projects/netgrif-components/src/lib/search/advanced-search/search-predicate-component/search-predicate.component.ts b/projects/netgrif-components/src/lib/search/advanced-search/search-predicate-component/search-predicate.component.ts index a5c822b30f..016fb11a3e 100644 --- a/projects/netgrif-components/src/lib/search/advanced-search/search-predicate-component/search-predicate.component.ts +++ b/projects/netgrif-components/src/lib/search/advanced-search/search-predicate-component/search-predicate.component.ts @@ -1,10 +1,11 @@ -import {Component, Inject, Type} from '@angular/core'; +import {Component, Inject, Optional, Type} from '@angular/core'; import { AbstractSearchPredicateComponent, AdvancedSearchComponentInitializationService, Category, LoggerService, NAE_SEARCH_CATEGORIES, - CategoryFactory + CategoryFactory, + NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY } from '@netgrif/components-core'; @Component({ @@ -17,7 +18,8 @@ export class SearchPredicateComponent extends AbstractSearchPredicateComponent { constructor(@Inject(NAE_SEARCH_CATEGORIES) searchCategories: Array>>, logger: LoggerService, initializationService: AdvancedSearchComponentInitializationService, - categoryFactory: CategoryFactory) { - super(searchCategories, logger, initializationService, categoryFactory); + categoryFactory: CategoryFactory, + @Optional() @Inject(NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY) ignoreNetsOnAutocompleteCategory: boolean) { + super(searchCategories, logger, initializationService, categoryFactory, ignoreNetsOnAutocompleteCategory); } } From 52217338f4b998f0df74d2ee2eb8c4d3b516ea9c Mon Sep 17 00:00:00 2001 From: chvostek Date: Fri, 14 Aug 2026 13:41:19 +0200 Subject: [PATCH 31/55] [NAE-2466] Advanced search for PFQL - add plain text for datafield initialization in CaseDataSet category --- .../src/assets/i18n/de.json | 1 + .../src/assets/i18n/en.json | 1 + .../src/assets/i18n/sk.json | 1 + .../models/category/case/case-dataset.ts | 88 +++++++++++++------ .../lib/search/models/configuration-input.ts | 20 ++++- .../search-configuration-input.component.html | 20 +++++ .../search-predicate.component.ts | 8 +- 7 files changed, 104 insertions(+), 35 deletions(-) diff --git a/projects/netgrif-components-core/src/assets/i18n/de.json b/projects/netgrif-components-core/src/assets/i18n/de.json index b60c8b3673..36cffe0f6e 100644 --- a/projects/netgrif-components-core/src/assets/i18n/de.json +++ b/projects/netgrif-components-core/src/assets/i18n/de.json @@ -155,6 +155,7 @@ "name": "Falldatei", "placeholder": { "field": "Wählen Sie das Datenfeld aus", + "plainField": "Eingeben data field", "value": "Geben Sie den Wert des Datenfeldes ein" } } diff --git a/projects/netgrif-components-core/src/assets/i18n/en.json b/projects/netgrif-components-core/src/assets/i18n/en.json index 74da0da840..7da12d79d8 100644 --- a/projects/netgrif-components-core/src/assets/i18n/en.json +++ b/projects/netgrif-components-core/src/assets/i18n/en.json @@ -155,6 +155,7 @@ "name": "Case data", "placeholder": { "field": "Select data field", + "plainField": "Enter data field", "value": "Enter data field value" } } diff --git a/projects/netgrif-components-core/src/assets/i18n/sk.json b/projects/netgrif-components-core/src/assets/i18n/sk.json index fa48b5dce2..0525bc4af4 100644 --- a/projects/netgrif-components-core/src/assets/i18n/sk.json +++ b/projects/netgrif-components-core/src/assets/i18n/sk.json @@ -155,6 +155,7 @@ "name": "Dáta prípadu", "placeholder": { "field": "Vyberte dátovú položku", + "plainField": "Zadajte data field", "value": "Zadajte hodnotu dátovej položky" } } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts index 2b282648e3..172a6736af 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts @@ -45,7 +45,7 @@ import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; import {FieldTypeResource} from "../../../../task-content/model/field-type-resource"; import {SimpleExpression} from "../../../../pfql/model/simple-expression"; import {DataSimpleExpression} from "../../../../pfql/model/data-simple-expression"; -import {take, map} from "rxjs/operators"; +import {take, map, debounceTime} from "rxjs/operators"; interface Datafield { netIdentifier: string; @@ -101,7 +101,6 @@ export class CaseDataset extends Category implements AutocompleteOpti logger, operators, ResourceTypeQueryPrefix.CASES); - this._processCategory = this._optionalDependencies.categoryFactory.get(CaseProcess) as CaseProcess; this._processCategory.selectDefaultOperator(); @@ -109,23 +108,37 @@ export class CaseDataset extends Category implements AutocompleteOpti this._userAutocomplete = new UserAutocomplete(this._optionalDependencies); this.createDatafieldOptions(); - this._DATAFIELD_INPUT = new ConfigurationInput( - SearchInputType.AUTOCOMPLETE, - 'search.category.case.dataset.placeholder.field', - true, - this._datafieldOptions, - (mapKeys, newValue) => { - return mapKeys.map(serializedMapKey => DatafieldMapKey.parse(serializedMapKey)) - .filter(mapKey => mapKey.title.toLocaleLowerCase().startsWith(newValue)); - } - ); + let dataFieldInputDebounceTime = 1; + if (!!this._optionalDependencies.ignoreNetsOnAutocompleteCategories) { + this._DATAFIELD_INPUT = new ConfigurationInput( + SearchInputType.TEXT, + 'search.category.case.dataset.placeholder.plainField', + true, + new Map>(), + () => { return [] } + ); + dataFieldInputDebounceTime = 600; + } else { + this._DATAFIELD_INPUT = new ConfigurationInput( + SearchInputType.AUTOCOMPLETE, + 'search.category.case.dataset.placeholder.field', + true, + this._datafieldOptions, + (mapKeys, newValue) => { + return mapKeys.map(serializedMapKey => DatafieldMapKey.parse(serializedMapKey)) + .filter(mapKey => mapKey.title.toLocaleLowerCase().startsWith(newValue)); + } + ); + } this._configurationInputs$ = new BehaviorSubject>([this._DATAFIELD_INPUT]); - this._DATAFIELD_INPUT.valueChanges$().subscribe(newValue => { - if (newValue === undefined || typeof newValue === 'string') { + this._DATAFIELD_INPUT.valueChanges$().pipe(debounceTime(dataFieldInputDebounceTime)).subscribe(newValue => { + if (newValue === undefined + || (this._DATAFIELD_INPUT.type === SearchInputType.AUTOCOMPLETE && typeof newValue === 'string')) { this._configurationInputs$.next([this._DATAFIELD_INPUT]); - } else if (this._configurationInputs$.getValue().length === 1) { + } else if (this._configurationInputs$.getValue().length === 1 + || (this._DATAFIELD_INPUT.type === SearchInputType.TEXT && typeof newValue === 'string')) { this._configurationInputs$.next([this._DATAFIELD_INPUT, this._OPERATOR_INPUT]); } this._operatorFormControl.setValue(undefined); @@ -150,6 +163,9 @@ export class CaseDataset extends Category implements AutocompleteOpti if (!this.hasSelectedDatafields) { throw new Error('Input type of arguments cannot be determined before selecting a data field during the configuration.'); } + if (!this._selectedDatafields) { + return SearchInputType.TEXT; + } return CaseDataset.FieldTypeToInputType(this._selectedDatafields[0].fieldType); } @@ -165,6 +181,21 @@ export class CaseDataset extends Category implements AutocompleteOpti if (!this.hasSelectedDatafields) { return []; } + const defaultOperators = [ + this._operatorService.getOperator(Substring), + this._operatorService.getOperator(Equals), + this._operatorService.getOperator(NotEquals), + this._operatorService.getOperator(MoreThan), + this._operatorService.getOperator(MoreThanEqual), + this._operatorService.getOperator(LessThan), + this._operatorService.getOperator(LessThanEqual), + this._operatorService.getOperator(IsNull), + this._operatorService.getOperator(Like) + ]; + + if (!this._selectedDatafields) { + return defaultOperators; + } switch (this._selectedDatafields[0].fieldType) { case FieldTypeResource.NUMBER.valueOf(): return [ @@ -211,17 +242,7 @@ export class CaseDataset extends Category implements AutocompleteOpti this._operatorService.getOperator(IsNull) ]; default: - return [ - this._operatorService.getOperator(Substring), - this._operatorService.getOperator(Equals), - this._operatorService.getOperator(NotEquals), - this._operatorService.getOperator(MoreThan), - this._operatorService.getOperator(MoreThanEqual), - this._operatorService.getOperator(LessThan), - this._operatorService.getOperator(LessThanEqual), - this._operatorService.getOperator(IsNull), - this._operatorService.getOperator(Like) - ]; + return defaultOperators; } } @@ -252,6 +273,9 @@ export class CaseDataset extends Category implements AutocompleteOpti protected get pfqlKeywords(): Array { if (!this.hasSelectedDatafields) { return []; + } else if (!this._selectedDatafields) { + const fieldId: string = this._DATAFIELD_INPUT.formControl.value + return [`data.${fieldId}.value`]; } else { return this._selectedDatafields.map(dataField => `data.${dataField.fieldId}.value`); } @@ -278,7 +302,15 @@ export class CaseDataset extends Category implements AutocompleteOpti queryGenerationStrategy = (d, ui) => this.standardQueryGenerationStrategy(d, ui); } - const queries = this._selectedDatafields.map(datafield => queryGenerationStrategy(datafield, userInput)); + let queries; + if (!this._selectedDatafields) { + queries = [queryGenerationStrategy({ + netIdentifier: undefined, + fieldId: this._DATAFIELD_INPUT.formControl.value, + fieldType: 'string'}, userInput)]; + } else { + queries = this._selectedDatafields.map(datafield => queryGenerationStrategy(datafield, userInput)); + } return Query.combineQueries(queries, BooleanOperator.OR); } @@ -296,7 +328,7 @@ export class CaseDataset extends Category implements AutocompleteOpti } protected generateNetConstraint(datafield: Datafield): Query { - return this._isLoadedFromPfql ? new Query(undefined, ResourceTypeQueryPrefix.CASES, true) + return this._isLoadedFromPfql || this._DATAFIELD_INPUT.type === SearchInputType.TEXT ? new Query(undefined, ResourceTypeQueryPrefix.CASES, true) : this._processCategory.generatePredicate([[datafield.netIdentifier]]).query; } diff --git a/projects/netgrif-components-core/src/lib/search/models/configuration-input.ts b/projects/netgrif-components-core/src/lib/search/models/configuration-input.ts index 270d19efee..d39db9721f 100644 --- a/projects/netgrif-components-core/src/lib/search/models/configuration-input.ts +++ b/projects/netgrif-components-core/src/lib/search/models/configuration-input.ts @@ -18,6 +18,8 @@ export class ConfigurationInput { protected _filteredOptions$: Observable>>; + protected _textInputConfirmed = false; + /** * @param type the type of the configuration input * @param label the translation path for the label of the input @@ -26,7 +28,7 @@ export class ConfigurationInput { * @param filterOptions a method that receives the keys of the available options and should return * the appropriately filtered autocomplete options */ - constructor(public type: SearchInputType.AUTOCOMPLETE | SearchInputType.OPERATOR | SearchInputType.PLAIN_QUERY, + constructor(public type: SearchInputType.AUTOCOMPLETE | SearchInputType.OPERATOR | SearchInputType.PLAIN_QUERY | SearchInputType.TEXT, public label: string, public displayBold: boolean, protected _autocompleteOptions: Map>, @@ -35,7 +37,7 @@ export class ConfigurationInput { this._filteredOptions$ = this._formControl.valueChanges.pipe( startWith(''), - filter(newValue => typeof newValue === 'string'), + filter(newValue => typeof newValue === 'string' && this.type !== SearchInputType.TEXT), map(newValue => { return filterOptions(Array.from(this._autocompleteOptions.keys()), newValue); }) @@ -47,6 +49,9 @@ export class ConfigurationInput { } public get isOptionSelected(): boolean { + if (this.type === SearchInputType.TEXT) { + return this._textInputConfirmed && !!this._formControl.value; + } return !!this._formControl.value && (typeof this._formControl.value !== 'string'); } @@ -58,6 +63,17 @@ export class ConfigurationInput { return this._filteredOptions$; } + public confirmInput(): void { + this._textInputConfirmed = true; + } + + public editInput(editable: boolean): void { + if (!editable) { + return; + } + this._textInputConfirmed = false; + } + /** * Value changes of the encapsulated `FormControl` object */ diff --git a/projects/netgrif-components/src/lib/search/advanced-search/search-configuration-input-component/search-configuration-input.component.html b/projects/netgrif-components/src/lib/search/advanced-search/search-configuration-input-component/search-configuration-input.component.html index 3eadd49952..9309f88b06 100644 --- a/projects/netgrif-components/src/lib/search/advanced-search/search-configuration-input-component/search-configuration-input.component.html +++ b/projects/netgrif-components/src/lib/search/advanced-search/search-configuration-input-component/search-configuration-input.component.html @@ -34,6 +34,26 @@
+ +
+ + + {{configuration.label | translate}} + + + + +
+ {{configuration.formControl.value}} +
+
+
diff --git a/projects/netgrif-components/src/lib/search/advanced-search/search-predicate-component/search-predicate.component.ts b/projects/netgrif-components/src/lib/search/advanced-search/search-predicate-component/search-predicate.component.ts index 016fb11a3e..3754fb0ac4 100644 --- a/projects/netgrif-components/src/lib/search/advanced-search/search-predicate-component/search-predicate.component.ts +++ b/projects/netgrif-components/src/lib/search/advanced-search/search-predicate-component/search-predicate.component.ts @@ -1,11 +1,10 @@ -import {Component, Inject, Optional, Type} from '@angular/core'; +import {Component, Inject, Type} from '@angular/core'; import { AbstractSearchPredicateComponent, AdvancedSearchComponentInitializationService, Category, LoggerService, NAE_SEARCH_CATEGORIES, CategoryFactory, - NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY } from '@netgrif/components-core'; @Component({ @@ -18,8 +17,7 @@ export class SearchPredicateComponent extends AbstractSearchPredicateComponent { constructor(@Inject(NAE_SEARCH_CATEGORIES) searchCategories: Array>>, logger: LoggerService, initializationService: AdvancedSearchComponentInitializationService, - categoryFactory: CategoryFactory, - @Optional() @Inject(NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY) ignoreNetsOnAutocompleteCategory: boolean) { - super(searchCategories, logger, initializationService, categoryFactory, ignoreNetsOnAutocompleteCategory); + categoryFactory: CategoryFactory) { + super(searchCategories, logger, initializationService, categoryFactory); } } From 205be29e9e09b4d27577bc4fb81c5a735419535b Mon Sep 17 00:00:00 2001 From: chvostek Date: Fri, 14 Aug 2026 13:57:16 +0200 Subject: [PATCH 32/55] [NAE-2466] Advanced search for PFQL - add plain text for process in TaskProcess --- .../src/lib/search/models/category/task/task-process.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts index f2356ecb57..b1fcd7f64c 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts @@ -12,6 +12,7 @@ import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; import {SimpleExpression} from "../../../../pfql/model/simple-expression"; import {filter, take} from "rxjs/operators"; import {SearchAutocompleteOption} from "../search-autocomplete-option"; +import {SearchInputType} from "../search-input-type"; export class TaskProcess extends NoConfigurationAutocompleteCategory { @@ -27,6 +28,9 @@ export class TaskProcess extends NoConfigurationAutocompleteCategory { logger, operators, ResourceTypeQueryPrefix.TASKS); + if (!!this._optionalDependencies.ignoreNetsOnAutocompleteCategories) { + this.inputType = SearchInputType.TEXT; + } } destroy() { @@ -81,7 +85,10 @@ export class TaskProcess extends NoConfigurationAutocompleteCategory { if (this.selectedOperator.numberOfOperands !== 1) { throw new Error('Only unary operators are currently supported by the TaskProcess implementation'); } - const operand = userInput[0]; + let operand = userInput[0]; + if (!Array.isArray(operand)) { + operand = [operand]; + } const queries = operand.map(id => this.selectedOperator.createQuery(this.pfqlKeywords, [id])); return Query.combineQueries(queries, BooleanOperator.OR).addPrefixAndGet(ResourceTypeQueryPrefix.TASKS); } From 614690e0f47999990995bb2d3e1621853d2134c6 Mon Sep 17 00:00:00 2001 From: chvostek Date: Mon, 17 Aug 2026 07:58:21 +0200 Subject: [PATCH 33/55] [NAE-2466] Advanced search for PFQL - rename method in query.ts - add plain input of transition into task-task.ts --- .../src/lib/search/models/category/case/case-dataset.ts | 4 ++-- .../src/lib/search/models/category/case/case-process.ts | 2 +- .../lib/search/models/category/case/case-simple-dataset.ts | 2 +- .../src/lib/search/models/category/category.ts | 2 +- .../models/category/net-attribute-autocomplete-category.ts | 7 ++++++- .../no-configuration-user-autocomplete-category.ts | 4 ++-- .../src/lib/search/models/category/plain-query-category.ts | 2 +- .../src/lib/search/models/category/task/task-process.ts | 2 +- .../src/lib/search/models/category/task/task-task.ts | 4 ++++ .../src/lib/search/models/query/query.ts | 2 +- 10 files changed, 20 insertions(+), 11 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts index 172a6736af..a28da2b157 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts @@ -318,13 +318,13 @@ export class CaseDataset extends Category implements AutocompleteOpti const valueQuery = this.selectedOperator.createQuery(this.pfqlKeywords, userInput, escapeInput); const netQuery = this.generateNetConstraint(datafield); const query: Query = Query.combineQueries([valueQuery, netQuery], BooleanOperator.AND); - return query.addPrefixAndGet(ResourceTypeQueryPrefix.CASES); + return query.ensurePrefixAndGet(ResourceTypeQueryPrefix.CASES); } protected isNullOperatorQueryGenerationStrategy(datafield: Datafield): Query { const constraint = this.generateNetConstraint(datafield); return (this._operatorService.getOperator(IsNull) as IsNull).createQueryWithConstraint(this.pfqlKeywords, constraint) - .addPrefixAndGet(ResourceTypeQueryPrefix.CASES); + .ensurePrefixAndGet(ResourceTypeQueryPrefix.CASES); } protected generateNetConstraint(datafield: Datafield): Query { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts index b3db5c1cdd..ed813da3fc 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts @@ -106,7 +106,7 @@ export class CaseProcess extends NoConfigurationAutocompleteCategory { operand = [operand]; } const queries = operand.map(id => this.selectedOperator.createQuery(this.pfqlKeywords, [id])); - return Query.combineQueries(queries, BooleanOperator.OR).addPrefixAndGet(ResourceTypeQueryPrefix.CASES); + return Query.combineQueries(queries, BooleanOperator.OR).ensurePrefixAndGet(ResourceTypeQueryPrefix.CASES); } get inputPlaceholder(): string { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-simple-dataset.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-simple-dataset.ts index a509916e61..b913cdb028 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-simple-dataset.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-simple-dataset.ts @@ -124,7 +124,7 @@ export class CaseSimpleDataset extends NoConfigurationCategory { this._netIdentifiers.map(id => this._processCategory.generatePredicate([[id]]).query), BooleanOperator.OR ); - return Query.combineQueries([valueQuery, netsQuery], BooleanOperator.AND).addPrefixAndGet(ResourceTypeQueryPrefix.CASES); + return Query.combineQueries([valueQuery, netsQuery], BooleanOperator.AND).ensurePrefixAndGet(ResourceTypeQueryPrefix.CASES); } serializeClass(): Categories | string { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/category.ts b/projects/netgrif-components-core/src/lib/search/models/category/category.ts index 7182f751ed..f3d0b00dc3 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/category.ts @@ -343,7 +343,7 @@ export abstract class Category { throw new Error('Category cannot generate a Query if no Operator is selected'); } let query: Query = this._operatorFormControl.value.createQuery(this.pfqlKeywords, userInput as unknown as Array); - return query.addPrefixAndGet(this._resourceTypePrefix); + return query.ensurePrefixAndGet(this._resourceTypePrefix); } /** diff --git a/projects/netgrif-components-core/src/lib/search/models/category/net-attribute-autocomplete-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/net-attribute-autocomplete-category.ts index 70adadbe02..6fdd0679f4 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/net-attribute-autocomplete-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/net-attribute-autocomplete-category.ts @@ -11,6 +11,7 @@ import {Subscription} from 'rxjs'; import {OperatorService} from '../../operator-service/operator.service'; import {OptionalDependencies} from '../../category-factory/optional-dependencies'; import {ResourceTypeQueryPrefix} from "./resource-type-query-prefix"; +import {SearchInputType} from "./search-input-type"; /** * A utility class for autocomplete search categories that are net specific, such as searching by roles, or tasks. @@ -100,6 +101,10 @@ export abstract class NetAttributeAutocompleteCategory extends NoConfigurationAu throw new Error('NetAttributeAutocompleteCategories currently doesn\'t support operators with arity other than 1!'); } + if (this.inputType === SearchInputType.TEXT && !!userInput[0]) { + return this.selectedOperator.createQuery(this.pfqlKeywords, [userInput[0]]).ensurePrefixAndGet(this._resourceTypePrefix); + } + const matchingPairs = userInput[0]; const queries = matchingPairs.map(pair => { @@ -108,6 +113,6 @@ export abstract class NetAttributeAutocompleteCategory extends NoConfigurationAu return Query.combineQueries([taskQuery, netQuery], BooleanOperator.AND); }); const query: Query = Query.combineQueries(queries, BooleanOperator.OR); - return query.addPrefixAndGet(this._resourceTypePrefix); + return query.ensurePrefixAndGet(this._resourceTypePrefix); } } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts index 4a84c2e2e2..3466426a1b 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts @@ -40,10 +40,10 @@ export abstract class NoConfigurationUserAutocompleteCategory extends NoConfigur } if (this.isSelectedOperator(IsNull)) { return (this.selectedOperator as IsNull).createQuery(this.pfqlKeywords) - .addPrefixAndGet(this._resourceTypePrefix); + .ensurePrefixAndGet(this._resourceTypePrefix); } else { return this.selectedOperator.createQuery(this.pfqlKeywords, Array.isArray(userInput[0]) ? userInput[0] : userInput, false) - .addPrefixAndGet(this._resourceTypePrefix); + .ensurePrefixAndGet(this._resourceTypePrefix); } } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/plain-query-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/plain-query-category.ts index b5138c1c9f..1c1ff30bbf 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/plain-query-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/plain-query-category.ts @@ -37,7 +37,7 @@ export abstract class PlainQueryCategory extends Category { return new Query('', this._resourceTypePrefix); } const pfqlQueryString: string = userInput[0]; - return new Query(pfqlQueryString).addPrefixAndGet(this._resourceTypePrefix); + return new Query(pfqlQueryString).ensurePrefixAndGet(this._resourceTypePrefix); } protected override operandValueChanges(operandIndex: number) { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts index b1fcd7f64c..e82cb0df31 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts @@ -90,7 +90,7 @@ export class TaskProcess extends NoConfigurationAutocompleteCategory { operand = [operand]; } const queries = operand.map(id => this.selectedOperator.createQuery(this.pfqlKeywords, [id])); - return Query.combineQueries(queries, BooleanOperator.OR).addPrefixAndGet(ResourceTypeQueryPrefix.TASKS); + return Query.combineQueries(queries, BooleanOperator.OR).ensurePrefixAndGet(ResourceTypeQueryPrefix.TASKS); } get inputPlaceholder(): string { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts index 085c351937..8aaa5d5963 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts @@ -13,6 +13,7 @@ import {Observable, of, Subject} from "rxjs"; import {filter, take} from "rxjs/operators"; import {NetAttributePair} from "../net-attribute-pair"; import {SearchAutocompleteOption} from "../search-autocomplete-option"; +import {SearchInputType} from "../search-input-type"; export class TaskTask extends TaskNetAttributeAutocompleteCategory { @@ -27,6 +28,9 @@ export class TaskTask extends TaskNetAttributeAutocompleteCategory { operators, optionalDependencies, ResourceTypeQueryPrefix.TASKS); + if (!!this._optionalDependencies.ignoreNetsOnAutocompleteCategories) { + this.inputType = SearchInputType.TEXT; + } } protected extractAttributes(petriNet: Net): Array { diff --git a/projects/netgrif-components-core/src/lib/search/models/query/query.ts b/projects/netgrif-components-core/src/lib/search/models/query/query.ts index 3052d335e8..9a33113999 100644 --- a/projects/netgrif-components-core/src/lib/search/models/query/query.ts +++ b/projects/netgrif-components-core/src/lib/search/models/query/query.ts @@ -115,7 +115,7 @@ export class Query { * @param resourceTypePrefix the resource type prefix to add to the query * @returns this Query instance with the updated value */ - public addPrefixAndGet(resourceTypePrefix: ResourceTypeQueryPrefix): Query { + public ensurePrefixAndGet(resourceTypePrefix: ResourceTypeQueryPrefix): Query { if (this.isEmpty) { this._value = resourceTypePrefix; return this; From 8c9f2d087e76c26799f4b6ea891be7a26d8b3023 Mon Sep 17 00:00:00 2001 From: chvostek Date: Mon, 17 Aug 2026 08:49:29 +0200 Subject: [PATCH 34/55] [NAE-2466] Advanced search for PFQL - implement loading PFQL query into case-dataset.ts and case-process.ts by Task form --- .../src/lib/pfql/pfql-visitor.ts | 3 ++- .../models/category/case/case-dataset.ts | 22 ++++++++++++++++--- .../models/category/case/case-process.ts | 4 ++++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts index cf57ea8241..33c2e7b661 100644 --- a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts +++ b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts @@ -77,6 +77,7 @@ import {UserService} from "../user/services/user.service"; import {CasePlainQuery} from "../search/models/category/case/case-plain-query"; import {RawExpression} from "./model/raw-expression"; import {TaskPlainQuery} from "../search/models/category/task/task-plain-query"; +import {NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY} from "../search/category-factory/search-categories-injection-token"; /** @@ -113,7 +114,7 @@ export class PfqlVisitor extends QueryLangVisitor> { searchIndexResolver: undefined, allowedNetsService: this._allowedNetsService, userResourceService: this._userResourceService, - ignoreNetsOnAutocompleteCategories: undefined, // todo 2466 auto + ignoreNetsOnAutocompleteCategories: injector.get(NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY), }; } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts index a28da2b157..a83e72045e 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts @@ -75,6 +75,7 @@ export class CaseDataset extends Category implements AutocompleteOpti protected _userAutocomplete: UserAutocomplete; protected _isLoadedFromPfql: boolean = false; + protected _operatorWasLoadedFromPfql = false; public static FieldTypeToInputType(fieldType: string): SearchInputType { switch (fieldType) { @@ -108,7 +109,7 @@ export class CaseDataset extends Category implements AutocompleteOpti this._userAutocomplete = new UserAutocomplete(this._optionalDependencies); this.createDatafieldOptions(); - let dataFieldInputDebounceTime = 1; + let dataFieldInputDebounceTime = 0; if (!!this._optionalDependencies.ignoreNetsOnAutocompleteCategories) { this._DATAFIELD_INPUT = new ConfigurationInput( SearchInputType.TEXT, @@ -117,7 +118,7 @@ export class CaseDataset extends Category implements AutocompleteOpti new Map>(), () => { return [] } ); - dataFieldInputDebounceTime = 600; + dataFieldInputDebounceTime = 500; } else { this._DATAFIELD_INPUT = new ConfigurationInput( SearchInputType.AUTOCOMPLETE, @@ -141,7 +142,11 @@ export class CaseDataset extends Category implements AutocompleteOpti || (this._DATAFIELD_INPUT.type === SearchInputType.TEXT && typeof newValue === 'string')) { this._configurationInputs$.next([this._DATAFIELD_INPUT, this._OPERATOR_INPUT]); } - this._operatorFormControl.setValue(undefined); + if (this._operatorWasLoadedFromPfql) { + this._operatorWasLoadedFromPfql = false; + } else { + this._operatorFormControl.setValue(undefined); + } }); } @@ -499,6 +504,17 @@ export class CaseDataset extends Category implements AutocompleteOpti return of(undefined); } + if (this._DATAFIELD_INPUT.type === SearchInputType.TEXT) { + this._DATAFIELD_INPUT.formControl.setValue(expression.dataFieldId); + this._DATAFIELD_INPUT.confirmInput(); + if (!this.selectOperatorFromPfqlExpression(expression)) { + return of(undefined); + } + this._operatorWasLoadedFromPfql = true; + this.setOperands([expression.operandValue]); + return of(undefined); + } + return this._datafieldOptionsInitialized$.pipe( take(1), map(() => { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts index ed813da3fc..d96e9dd20f 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts @@ -63,6 +63,10 @@ export class CaseProcess extends NoConfigurationAutocompleteCategory { if (!this.selectOperatorFromPfqlExpression(expression)) { return of(undefined); } + if (this._optionalDependencies.ignoreNetsOnAutocompleteCategories) { + this.setOperands([expression.operandValue]); + return of(undefined); + } const isDone$ = new Subject(); this._options$.pipe( filter(options => options.length > 0), From fd78c6b98d631113748633afb2439e09dec62594 Mon Sep 17 00:00:00 2001 From: chvostek Date: Mon, 17 Aug 2026 08:53:21 +0200 Subject: [PATCH 35/55] [NAE-2466] Advanced search for PFQL - implement loading PFQL query into task-process.ts and task-task.ts by Task form --- .../src/lib/search/models/category/task/task-process.ts | 4 ++++ .../src/lib/search/models/category/task/task-task.ts | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts index e82cb0df31..25c7aaea5f 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts @@ -59,6 +59,10 @@ export class TaskProcess extends NoConfigurationAutocompleteCategory { if (!this.selectOperatorFromPfqlExpression(expression)) { return of(undefined); } + if (this._optionalDependencies.ignoreNetsOnAutocompleteCategories) { + this.setOperands([expression.operandValue]); + return of(undefined); + } const isDone$ = new Subject(); this._options$.pipe( filter(options => options.length > 0), diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts index 8aaa5d5963..e48c6b5596 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts @@ -41,6 +41,10 @@ export class TaskTask extends TaskNetAttributeAutocompleteCategory { if (!this.selectOperatorFromPfqlExpression(expression)) { return of(undefined); } + if (this._optionalDependencies.ignoreNetsOnAutocompleteCategories) { + this.setOperands([expression.operandValue]); + return of(undefined); + } const isDone$ = new Subject(); this._options$.pipe( From cf7338461af88e1e02023fb27d40e4c60dbfbe53 Mon Sep 17 00:00:00 2001 From: chvostek Date: Mon, 17 Aug 2026 10:13:36 +0200 Subject: [PATCH 36/55] [NAE-2466] Advanced search for PFQL - update info text --- projects/netgrif-components-core/src/assets/i18n/de.json | 2 +- projects/netgrif-components-core/src/assets/i18n/en.json | 2 +- projects/netgrif-components-core/src/assets/i18n/sk.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/projects/netgrif-components-core/src/assets/i18n/de.json b/projects/netgrif-components-core/src/assets/i18n/de.json index 36cffe0f6e..e1df8cdbf9 100644 --- a/projects/netgrif-components-core/src/assets/i18n/de.json +++ b/projects/netgrif-components-core/src/assets/i18n/de.json @@ -206,7 +206,7 @@ }, "help": { "title": "Hilfe für den erweiterten Suchmodus", - "text": "Man kann den erweiterten Suchmodus verwenden, um komplexere Suchanfragen zu erstellen. Beginnen Sie mit der Auswahl einer Suchkategorie. Die Suchkategorie definiert, wonach Sie suchen. Manche Suchkategorien benötigen zusätzliche Konfiguration (z.B. die Falldatei Suchkategorie). Nachdem Sie die Suchkategorie auswählen, mussen Sie den Operator auswählen. Der Operator stellt fest, wie die Daten mit der Suchanfrage übereinstimmen müssen. Mit verschiedenen Operatoren kann man nach einer genauen Übereinstimmung oder nach Werten aus einem Bereich suchen. Nach der Operatorasuwahl muss man das gesuchte Wert eingeben. Die Suchanfragen können mit den Stichwörtern UND oder ODER verbunden werden. Das ODER Stichwort findet Einträge, die mindestens eines der kombinierten Suchanfragen erfühlen. Das UND Stichwort findet Einträge, die alle der kombinierten Suchanfragen, erfühlen." + "text": "Man kann den erweiterten Suchmodus verwenden, um komplexere Suchanfragen zu erstellen. Beginnen Sie mit der Auswahl einer Suchkategorie. Die Suchkategorie definiert, wonach Sie suchen. Manche Suchkategorien benötigen zusätzliche Konfiguration (z.B. die Falldatei Suchkategorie). Nachdem Sie die Suchkategorie auswählen, mussen Sie den Operator auswählen. Der Operator stellt fest, wie die Daten mit der Suchanfrage übereinstimmen müssen. Mit verschiedenen Operatoren kann man nach einer genauen Übereinstimmung oder nach Werten aus einem Bereich suchen. Nach der Operatorasuwahl muss man das gesuchte Wert eingeben. Die Suchanfragen können mit den Stichwörtern UND verbunden werden. Das UND Stichwort findet Einträge, die alle der kombinierten Suchanfragen, erfühlen. Wenn Sie komplexere Suchanfragen eingeben möchten, können Sie die Kategorie „Einfache Abfrage“ auswählen und eine beliebige gültige PFQL-Abfrage eingeben." }, "fullText": "Geben Sie den gesuchten Text ein", "and": "und", diff --git a/projects/netgrif-components-core/src/assets/i18n/en.json b/projects/netgrif-components-core/src/assets/i18n/en.json index 7da12d79d8..ede6879928 100644 --- a/projects/netgrif-components-core/src/assets/i18n/en.json +++ b/projects/netgrif-components-core/src/assets/i18n/en.json @@ -206,7 +206,7 @@ }, "help": { "title": "Advanced search help", - "text": "Advanced search can be used to create more complex search queries. Start by selecting a search category. Search category determines, what you want your query to look for. Some categories (like searching in case data) require further configuration. Afterwards you have to select a search operator. The operator determines how the query attempts to match your data. Are you looking for numbers from a specific range? Are you looking for an exact match? Finally you have to enter the searched value. You can combine simpler queries into more complicated ones by binding them with an OR or an AND keyword. Queries combined with OR find results that match at least one sub-query. Queries combined with AND find results that match all sub-queries." + "text": "Advanced search can be used to create more complex search queries. Start by selecting a search category. Search category determines, what you want your query to look for. Some categories (like searching in case data) require further configuration. Afterwards you have to select a search operator. The operator determines how the query attempts to match your data. Are you looking for numbers from a specific range? Are you looking for an exact match? Finally you have to enter the searched value. You can combine queries with AND keyword. Queries combined with AND find results that match all sub-queries. If you wish to enter more complex queries you can select plain query category and enter any valid PFQL query." }, "fullText": "Enter searched phrase", "and": "and", diff --git a/projects/netgrif-components-core/src/assets/i18n/sk.json b/projects/netgrif-components-core/src/assets/i18n/sk.json index 0525bc4af4..2fe6279b4b 100644 --- a/projects/netgrif-components-core/src/assets/i18n/sk.json +++ b/projects/netgrif-components-core/src/assets/i18n/sk.json @@ -206,7 +206,7 @@ }, "help": { "title": "Nápoveda pre rozšírené vyhľadávanie", - "text": "Rozšírené vyhľadávanie slúži na zostavenie komplikovanejších požiadaviek na vyhľadávanie. Na začiatku zvoľte kategóriu vyhľadávania. Kategória vyhľadávania určuje, podľa čoho má váš dopyt vyhľadávať. Niektoré kategórie, ako napríklad \"Dáta prípadu\" vyžadujú dodatočnú konfiguráciu. Po zvolení kategórie je nutné zvoliť operátor vyhľadávania. Operátor rozhoduje o tom, akým spôsobom sa hľadá zhoda s hľadaným výtazom a dátami. Operátorom je možné hľadať napríklad presnú zhodu, alebo hodnotu z rozsahu. Nakoniec je nutné zadať hľadanú hodnotu. Dopyty je možné kombinovať pomocou kľúčových slov A SÚČASNE a ALEBO. Dopyty kombinované slovom ALEBO nájdu výsledky, spĺňajúce aspoň jednu z podmienok. Dopyty kombinované slovom A SÚČASNE nájdu výsledky spĺňajúce všetky podmienky." + "text": "Rozšírené vyhľadávanie slúži na zostavenie komplikovanejších požiadaviek na vyhľadávanie. Na začiatku zvoľte kategóriu vyhľadávania. Kategória vyhľadávania určuje, podľa čoho má váš dopyt vyhľadávať. Niektoré kategórie, ako napríklad \"Dáta prípadu\" vyžadujú dodatočnú konfiguráciu. Po zvolení kategórie je nutné zvoliť operátor vyhľadávania. Operátor rozhoduje o tom, akým spôsobom sa hľadá zhoda s hľadaným výrazom a dátami. Operátorom je možné hľadať napríklad presnú zhodu, alebo hodnotu z rozsahu. Nakoniec je nutné zadať hľadanú hodnotu. Dopyty je možné kombinovať pomocou kľúčových slov A SÚČASNE. Dopyty kombinované slovom A SÚČASNE nájdu výsledky spĺňajúce všetky podmienky. If you wish to enter more complex queries you can select plain query category and enter any valid PFQL query. Ak potrebujete zadať komplexnejší dopyt, môžete zvoliť kategóriu 'Obyčajný dopyt', kde viete napísať ľubovoľný platný PFQL dopyt." }, "fullText": "Zadajte hľadaný text", "and": "a súčasne", From 71123956b9e52e4a7e43dc9720613d5722c084ee Mon Sep 17 00:00:00 2001 From: chvostek Date: Mon, 17 Aug 2026 15:46:48 +0200 Subject: [PATCH 37/55] [NAE-2466] Advanced search for PFQL - remove implementation for filter metadata - add todos --- ...bstract-filter-field-tab-view.component.ts | 5 +- .../filter-field/models/filter-field.ts | 6 - .../src/lib/panel/abstract/featured-value.ts | 5 - .../abstract/panel-with-immediate-data.ts | 5 - ...immediate-filter-text-content.component.ts | 4 +- ...bstract-immediate-filter-text.component.ts | 4 +- .../model/filter-text-injection-token.ts | 3 +- .../lib/resources/interface/immediate-data.ts | 5 - .../interface/task-set-data-request-body.ts | 5 - .../category-factory/category-factory.ts | 18 --- .../models/category/case/case-dataset.ts | 24 ---- .../category/case/case-simple-dataset.ts | 16 --- .../lib/search/models/category/category.ts | 130 +----------------- .../models/operator/equals-date-time.ts | 5 - .../lib/search/models/operator/equals-date.ts | 5 - .../src/lib/search/models/operator/equals.ts | 5 - .../models/operator/in-range-date-time.ts | 4 - .../search/models/operator/in-range-date.ts | 4 - .../lib/search/models/operator/in-range.ts | 4 - .../src/lib/search/models/operator/is-null.ts | 4 - .../models/operator/less-than-date-time.ts | 5 - .../search/models/operator/less-than-date.ts | 5 - .../operator/less-than-equal-date-time.ts | 5 - .../models/operator/less-than-equal-date.ts | 5 - .../search/models/operator/less-than-equal.ts | 5 - .../lib/search/models/operator/less-than.ts | 5 - .../src/lib/search/models/operator/like.ts | 4 - .../models/operator/more-than-date-time.ts | 5 - .../search/models/operator/more-than-date.ts | 5 - .../operator/more-than-equal-date-time.ts | 5 - .../models/operator/more-than-equal-date.ts | 5 - .../search/models/operator/more-than-equal.ts | 5 - .../lib/search/models/operator/more-than.ts | 5 - .../models/operator/not-equals-date-time.ts | 4 - .../search/models/operator/not-equals-date.ts | 4 - .../lib/search/models/operator/not-equals.ts | 5 - .../lib/search/models/operator/operator.ts | 14 -- .../lib/search/models/operator/substring.ts | 4 - .../filter-metadata-allowed-nets.ts | 16 --- .../models/persistance/filter-metadata.ts | 40 ------ .../models/persistance/generator-metadata.ts | 48 ------- .../persistance/saved-filter-metadata.ts | 28 ---- ...itable-clause-predicate-with-generators.ts | 10 -- .../predicate/predicate-with-generator.ts | 14 -- .../lib/search/models/predicate/predicate.ts | 17 --- .../operator-service/operator.service.ts | 5 - .../src/lib/search/public-api.ts | 4 - .../abstract-search.component.ts | 10 -- .../abstract-search-predicate.component.ts | 7 - .../search/search-service/search.service.ts | 83 +---------- .../task-content/model/resource-interface.ts | 2 - 51 files changed, 10 insertions(+), 630 deletions(-) delete mode 100644 projects/netgrif-components-core/src/lib/search/models/persistance/filter-metadata-allowed-nets.ts delete mode 100644 projects/netgrif-components-core/src/lib/search/models/persistance/filter-metadata.ts delete mode 100644 projects/netgrif-components-core/src/lib/search/models/persistance/generator-metadata.ts delete mode 100644 projects/netgrif-components-core/src/lib/search/models/persistance/saved-filter-metadata.ts diff --git a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view.component.ts b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view.component.ts index ce72960e88..cf427e4b9e 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view.component.ts @@ -21,8 +21,9 @@ export abstract class AbstractFilterFieldTabViewComponent { this.tabs = [ { label: { - text: this._filterField.filterMetadata[Dashboard.FILTER_TAB_VIEW_TITLE_KEY] ?? this._filterField.title, - icon: this._filterField.filterMetadata[Dashboard.FILTER_TAB_VIEW_ICON_KEY] ?? 'home' + // todo 2466 dynamic label + text: /*this._filterField.filterMetadata[Dashboard.FILTER_TAB_VIEW_TITLE_KEY] ??*/ this._filterField.title, + icon: /*this._filterField.filterMetadata[Dashboard.FILTER_TAB_VIEW_ICON_KEY] ??*/ 'home' }, canBeClosed: false, tabContentComponent: this.tabContentComponent(), diff --git a/projects/netgrif-components-core/src/lib/data-fields/filter-field/models/filter-field.ts b/projects/netgrif-components-core/src/lib/data-fields/filter-field/models/filter-field.ts index e1668fb47f..a44b9b3566 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/filter-field/models/filter-field.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/filter-field/models/filter-field.ts @@ -2,7 +2,6 @@ import {DataField} from '../../models/abstract-data-field'; import {Behavior} from '../../models/behavior'; import {Layout} from '../../models/layout'; import {Component, ComponentPrefixes} from '../../models/component'; -import {FilterMetadata} from '../../../search/models/persistance/filter-metadata'; import {Validation} from '../../models/validation'; import {FieldTypeResource} from "../../../task-content/model/field-type-resource"; @@ -19,11 +18,6 @@ export class FilterField extends DataField { super(stringId, title, initialValue, behavior, placeholder, description, layout, validations, component, parentTaskId); } - get filterMetadata(): FilterMetadata { - // todo 2466 remove - return undefined; - } - get filterType(): FieldTypeResource { return this._filterType; } diff --git a/projects/netgrif-components-core/src/lib/panel/abstract/featured-value.ts b/projects/netgrif-components-core/src/lib/panel/abstract/featured-value.ts index b18a4525c2..099a7a3c58 100644 --- a/projects/netgrif-components-core/src/lib/panel/abstract/featured-value.ts +++ b/projects/netgrif-components-core/src/lib/panel/abstract/featured-value.ts @@ -1,4 +1,3 @@ -import {FilterMetadataAllowedNets} from '../../search/models/persistance/filter-metadata-allowed-nets'; /** * Represents a value featured on a panel @@ -7,8 +6,4 @@ export interface FeaturedValue { value: string; icon: string; type: string; - /** - * Only for immediate filter fields - */ - filterMetadata?: FilterMetadataAllowedNets; } diff --git a/projects/netgrif-components-core/src/lib/panel/abstract/panel-with-immediate-data.ts b/projects/netgrif-components-core/src/lib/panel/abstract/panel-with-immediate-data.ts index 1fed87e5e9..782b48e60c 100644 --- a/projects/netgrif-components-core/src/lib/panel/abstract/panel-with-immediate-data.ts +++ b/projects/netgrif-components-core/src/lib/panel/abstract/panel-with-immediate-data.ts @@ -79,11 +79,6 @@ export abstract class AbstractPanelWithImmediateDataComponent extends AbstractPa ? immediate.name.defaultValue : this._translate.instant('dialog.submit')), icon: undefined, type: immediate.type }; - case 'filter': - return { - value: undefined, icon: undefined, type: immediate.type, - filterMetadata: {filterMetadata: immediate.filterMetadata, allowedNets: immediate.allowedNets} - }; case 'number': if (immediate.format !== undefined) { return this.formatCurrencyPipe(immediate.value, immediate.format.code, immediate.format.fractionSize, diff --git a/projects/netgrif-components-core/src/lib/panel/immediate/abstract-immediate-filter-text-content.component.ts b/projects/netgrif-components-core/src/lib/panel/immediate/abstract-immediate-filter-text-content.component.ts index 3bc0aae2be..0416e0c145 100644 --- a/projects/netgrif-components-core/src/lib/panel/immediate/abstract-immediate-filter-text-content.component.ts +++ b/projects/netgrif-components-core/src/lib/panel/immediate/abstract-immediate-filter-text-content.component.ts @@ -25,8 +25,8 @@ export abstract class AbstractImmediateFilterTextContentComponent implements OnD protected constructor(@Inject(NAE_FILTER_TEXT) protected _configuration: FilterTextConfiguration, protected _textSearchService: SearchService, protected _translateService: TranslateService) { - this._textSearchService.loadFromMetadata(this._configuration.metadata.filterMetadata); - this._searchServiceSub = this._textSearchService.loadingFromMetadata$.pipe(filter(loading => !loading), take(1)).subscribe(() => { + this._textSearchService.loadFromPfql(this._configuration.query); + this._searchServiceSub = this._textSearchService.loadingFromPfql$.pipe(filter(loading => !loading), take(1)).subscribe(() => { this.segments = this._textSearchService.createFilterTextSegments(); this.tooltip = this.segments.map(segment => { const translation = this._translateService.instant(segment.segment); diff --git a/projects/netgrif-components-core/src/lib/panel/immediate/abstract-immediate-filter-text.component.ts b/projects/netgrif-components-core/src/lib/panel/immediate/abstract-immediate-filter-text.component.ts index 9360a84735..e7bf9c7190 100644 --- a/projects/netgrif-components-core/src/lib/panel/immediate/abstract-immediate-filter-text.component.ts +++ b/projects/netgrif-components-core/src/lib/panel/immediate/abstract-immediate-filter-text.component.ts @@ -1,5 +1,4 @@ import {Component, Injector, Input, OnInit, StaticProvider} from '@angular/core'; -import {FilterMetadataAllowedNets} from '../../search/models/persistance/filter-metadata-allowed-nets'; import {ComponentPortal, ComponentType} from '@angular/cdk/portal'; import {AbstractImmediateFilterTextContentComponent} from './abstract-immediate-filter-text-content.component'; import {NAE_FILTER_TEXT} from './model/filter-text-injection-token'; @@ -11,7 +10,6 @@ import {NAE_FILTER_TEXT} from './model/filter-text-injection-token'; export abstract class AbstractImmediateFilterTextComponent implements OnInit { @Input() public ellipsis: boolean; - @Input() public filterMetadata: FilterMetadataAllowedNets; public portal: ComponentPortal; public initialized: boolean; @@ -20,7 +18,7 @@ export abstract class AbstractImmediateFilterTextComponent implements OnInit { ngOnInit(): void { const providers: Array = [ - {provide: NAE_FILTER_TEXT, useValue: {metadata: this.filterMetadata, ellipsis: this.ellipsis}} + {provide: NAE_FILTER_TEXT, useValue: {ellipsis: this.ellipsis}} ]; const injector = Injector.create({providers, parent: this._parenInjector}); this.portal = new ComponentPortal(this.getFilterTextContentComponent(), null, injector); diff --git a/projects/netgrif-components-core/src/lib/panel/immediate/model/filter-text-injection-token.ts b/projects/netgrif-components-core/src/lib/panel/immediate/model/filter-text-injection-token.ts index 61b3b58008..1afb847370 100644 --- a/projects/netgrif-components-core/src/lib/panel/immediate/model/filter-text-injection-token.ts +++ b/projects/netgrif-components-core/src/lib/panel/immediate/model/filter-text-injection-token.ts @@ -1,8 +1,7 @@ import {InjectionToken} from '@angular/core'; -import {FilterMetadataAllowedNets} from '../../../search/models/persistance/filter-metadata-allowed-nets'; export interface FilterTextConfiguration { - metadata: FilterMetadataAllowedNets; + query: string; ellipsis: boolean; } diff --git a/projects/netgrif-components-core/src/lib/resources/interface/immediate-data.ts b/projects/netgrif-components-core/src/lib/resources/interface/immediate-data.ts index c207fcc1e9..539b793792 100644 --- a/projects/netgrif-components-core/src/lib/resources/interface/immediate-data.ts +++ b/projects/netgrif-components-core/src/lib/resources/interface/immediate-data.ts @@ -1,4 +1,3 @@ -import {FilterMetadata} from '../../search/models/persistance/filter-metadata'; import {FormatFilter} from '../../data-fields/models/format-filter'; import {Component} from '../../data-fields/models/component'; @@ -27,10 +26,6 @@ export interface ImmediateData { * Only for Fields of type `CaseRef` and `Filter` */ allowedNets?: Array; - /** - * Only for Fields of type `Filter` - */ - filterMetadata?: FilterMetadata; /** * Only for Currency Number Fields */ diff --git a/projects/netgrif-components-core/src/lib/resources/interface/task-set-data-request-body.ts b/projects/netgrif-components-core/src/lib/resources/interface/task-set-data-request-body.ts index a1086d6ed9..93cc0613d5 100644 --- a/projects/netgrif-components-core/src/lib/resources/interface/task-set-data-request-body.ts +++ b/projects/netgrif-components-core/src/lib/resources/interface/task-set-data-request-body.ts @@ -1,4 +1,3 @@ -import {FilterMetadata} from '../../search/models/persistance/filter-metadata'; /** * Describes request body for task setData endpoint. @@ -31,10 +30,6 @@ export interface TaskSetDataRequestFields { * new `allowed nets` (for field types that support this) */ allowedNets?: ReadonlyArray; - /** - * new `filterMetadata` (for field types that support this) - */ - filterMetadata?: FilterMetadata; }; } diff --git a/projects/netgrif-components-core/src/lib/search/category-factory/category-factory.ts b/projects/netgrif-components-core/src/lib/search/category-factory/category-factory.ts index 0d08ccde8f..19f3897ae0 100644 --- a/projects/netgrif-components-core/src/lib/search/category-factory/category-factory.ts +++ b/projects/netgrif-components-core/src/lib/search/category-factory/category-factory.ts @@ -5,10 +5,8 @@ import {Category} from '../models/category/category'; import {OptionalDependencies} from './optional-dependencies'; import {UserResourceService} from '../../resources/engine-endpoint/user-resource.service'; import {SearchIndexResolverService} from '../search-keyword-resolver-service/search-index-resolver.service'; -import {CategoryGeneratorMetadata} from '../models/persistance/generator-metadata'; import {CategoryResolverService} from './category-resolver.service'; import {AllowedNetsService} from '../../allowed-nets/services/allowed-nets.service'; -import {Observable, ReplaySubject} from 'rxjs'; import {NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY} from "./search-categories-injection-token"; /** @@ -69,20 +67,4 @@ export class CategoryFactory { public getByNameWithDefaultOperator(serializedCategoryClass: string): Category { return this.getWithDefaultOperator(this._categoryResolver.toClass(serializedCategoryClass)); } - - /** - * Reconstructs a {@link Category} from saved metadata. The category is NOT in its initial state. - * It is in its final state instead and immediately provides a search predicate. - * @param metadata - the saved metadata generated by a previous {@link Category} instance - * @returns an Observable, that emits the deserialized Category, once the deserialization finishes - */ - public getFromMetadata(metadata: CategoryGeneratorMetadata): Observable> { - const result$ = new ReplaySubject>(1); - const category = this.get(this._categoryResolver.toClass(metadata.category)); - category.loadFromMetadata(metadata).subscribe(() => { - result$.next(category); - result$.complete(); - }); - return result$.asObservable(); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts index a83e72045e..e8cdd7828c 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts @@ -32,7 +32,6 @@ import { ConfigurationInput } from '../../configuration-input'; import { Categories } from '../categories'; import { FormControl } from '@angular/forms'; import moment, { Moment } from 'moment'; -import { CategoryMetadataConfiguration } from '../../persistance/generator-metadata'; import { MoreThanEqual } from '../../operator/more-than-equal'; import { LessThanEqual } from '../../operator/less-than-equal'; import { MoreThanEqualDate } from '../../operator/more-than-equal-date'; @@ -475,29 +474,6 @@ export class CaseDataset extends Category implements AutocompleteOpti } } - protected createMetadataConfiguration(): CategoryMetadataConfiguration { - const config = super.createMetadataConfiguration(); - config[CaseDataset.DATAFIELD_METADATA] = (this._DATAFIELD_INPUT.formControl.value as DatafieldMapKey).toSerializedForm(); - return config; - } - - protected loadConfigurationFromMetadata(configuration: CategoryMetadataConfiguration): Observable { - const result$ = new ReplaySubject(1); - this.datafieldOptionsInitialized$.subscribe(() => { - const serializedMapKey = configuration[CaseDataset.DATAFIELD_METADATA] as string; - this.selectDatafields(serializedMapKey, false); - if (!this.hasSelectedDatafields) { - throw new Error(`Searched data fields cannot be restored from the provided configuration (${serializedMapKey - }). Make sure, that the correct allowed nets are provided in this view.`); - } - super.loadConfigurationFromMetadata(configuration).subscribe(() => { - result$.next(); - result$.complete(); - }); - }); - return result$.asObservable(); - } - public override loadFromPfqlExpression(expression: SimpleExpression): Observable { if (!(expression instanceof DataSimpleExpression)) { this._log.error("Cannot load category CaseDataSet from wrong PFQL expression") diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-simple-dataset.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-simple-dataset.ts index b913cdb028..4d756a27f0 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-simple-dataset.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-simple-dataset.ts @@ -13,8 +13,6 @@ import {NoConfigurationCategory} from '../no-configuration-category'; import {CaseDataset} from './case-dataset'; import {DatafieldMapKey} from '../../datafield-map-key'; import {Categories} from '../categories'; -import {CategoryGeneratorMetadata} from '../../persistance/generator-metadata'; -import {Observable} from 'rxjs'; import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; import {FieldTypeResource} from "../../../../task-content/model/field-type-resource"; @@ -130,18 +128,4 @@ export class CaseSimpleDataset extends NoConfigurationCategory { serializeClass(): Categories | string { return Categories.CASE_SIMPLE_DATASET; } - - /** - * Serialization is not supported. Throws an error. - */ - createMetadata(): never { - throw new Error('CaseSimpleDataset does not support serialization!'); - } - - /** - * Deserialization is not supported. Throws an error. - */ - loadFromMetadata(metadata: CategoryGeneratorMetadata): Observable { - throw new Error('CaseSimpleDataset does not support deserialization!'); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/category.ts b/projects/netgrif-components-core/src/lib/search/models/category/category.ts index f3d0b00dc3..2ba5574df2 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/category.ts @@ -4,16 +4,13 @@ import {Query} from '../query/query'; import {ElementaryPredicate} from '../predicate/elementary-predicate'; import {SearchInputType} from './search-input-type'; import {FormControl} from '@angular/forms'; -import {BehaviorSubject, forkJoin, Observable, of, ReplaySubject, Subject} from 'rxjs'; -import {debounceTime, defaultIfEmpty, map} from 'rxjs/operators'; +import {BehaviorSubject, Observable, of, ReplaySubject} from 'rxjs'; +import {debounceTime, map} from 'rxjs/operators'; import {OperatorTemplatePart} from '../operator-template-part'; import {IncrementingCounter} from '../../../utility/incrementing-counter'; import {ConfigurationInput} from '../configuration-input'; -import {CategoryGeneratorMetadata, CategoryMetadataConfiguration} from '../persistance/generator-metadata'; import {Categories} from './categories'; import {OperatorService} from '../../operator-service/operator.service'; -import {Operators} from '../operator/operators'; -import {ofVoid} from '../../../utility/of-void'; import {FilterTextSegment} from '../persistance/filter-text-segment'; import {DATE_FORMAT_STRING, DATE_TIME_FORMAT_STRING} from '../../../moment/time-formats'; import {Type} from '@angular/core'; @@ -39,11 +36,6 @@ import {SimpleExpression} from "../../../pfql/model/simple-expression"; */ export abstract class Category { - /** - * The {@link CategoryMetadataConfiguration} key for this Category's {@link Operator} - */ - protected static readonly OPERATOR_METADATA = 'operator'; - /** * Contains the `FormControl` object that is used to drive the operator selection. * @@ -399,45 +391,6 @@ export abstract class Category { */ public abstract duplicate(): Category; - /** - * Provides the necessary information for the serialisation of this category's state. - * - * Not every state must be preservable. The default library implementation supports only the preservation of the final state when the - * Category is generating a predicate object. - * - * @returns an object containing all the necessary information for the reconstruction of this category's state, - * barring information about allowed nets. Returns `undefined` if the category is not in a state that generates a predicate. - * See [providesPredicate()]{@link Category#providesPredicate}. - */ - public createMetadata(): CategoryGeneratorMetadata | undefined { - if (!this.providesPredicate) { - return undefined; - } - return { - category: this.serializeClass(), - configuration: this.createMetadataConfiguration(), - values: this.createMetadataValues() - }; - } - - /** - * Restores the saved state contained in the provided metadata. - * - * @param metadata the metadata created by calling the [createMetadata()]{@link Category#createMetadata} method - * - * @returns an Observable. When the Observable emits the category has finished restoring its state. - */ - public loadFromMetadata(metadata: CategoryGeneratorMetadata): Observable { - const result$ = new ReplaySubject(1); - this.loadConfigurationFromMetadata(metadata.configuration).subscribe(() => { - this.loadValuesFromMetadata(metadata.values).subscribe(() => { - result$.next(); - result$.complete(); - }); - }); - return result$.asObservable(); - } - /** * Loads the category state from a PFQL expression. * @@ -552,35 +505,6 @@ export abstract class Category { */ abstract serializeClass(): Categories | string; - /** - * The default implementation serializes only the operator. - * If the category contains additional configuration, this method must be extended. - * - * @returns an object containing all the necessary information for the reconstruction of the configuration of this category instance - */ - protected createMetadataConfiguration(): CategoryMetadataConfiguration { - return { - [Category.OPERATOR_METADATA]: this.selectedOperator.serialize() - }; - } - - /** - * The default implementation returns the value of all operand form control objects up to the current number of operands. - * To serialize value of each operand the [serializeOperandValue()]{@link Category#serializeOperandValue} method is used. - * - * If the values used by this category are not serializable, then either this method, or the `serializeOperandValue` method, - * must be overridden. - * - * @returns an array containing values input by the user in a serializable form - */ - protected createMetadataValues(): Array { - const result = []; - for (let i = 0; i < this.selectedOperatorArity; i++) { - result.push(this.serializeOperandValue(this._operandsFormControls[i])); - } - return result; - } - /** * @param valueFormControl FormControl object of one operand * @returns the value of the operand in a serialized form. The default implementation returns the FormControls `value` attribute. @@ -589,56 +513,6 @@ export abstract class Category { return valueFormControl.value; } - /** - * Restored the saved configuration from the metadata created by the - * [createMetadataConfiguration()]{@link Category#createMetadataConfiguration} method. - * - * The default implementation restores only the saved operator. - * - * If the Category overrides the serialization method, it must override this method as well. - * - * @param configuration the serialized configuration - * - * @returns an Observable. When the Observable emits the category has finished loading its configuration. - */ - protected loadConfigurationFromMetadata(configuration: CategoryMetadataConfiguration): Observable { - const resolvedOperator = this._operatorService.getFromMetadata(configuration[Category.OPERATOR_METADATA] as Operators | string); - this.selectOperator(this.allowedOperators.findIndex(op => op === resolvedOperator)); - return ofVoid(); - } - - /** - * The default implementation sets the provided values into this Category's operand form controls. - * - * An operator must be set before calling this method! Otherwise an error will be thrown. - * - * If the number of values doesn't match the arity of the selected operator an error will be thrown! - * - * If this Category overrides the [serializeOperandValue()]{@link Category#serializeOperandValue}, it must also - * override its deserialization counterpart - [deserializeOperandValue()]{@link #Category#deserializeOperandValue}! - * - * @param values the serialized values that should be loaded into this Category instance - * - * @returns an Observable. When the Observable emits the category has finished loading its values. - */ - protected loadValuesFromMetadata(values: Array): Observable { - if (!this.isOperatorSelected()) { - throw new Error('An operator must be selected before Category values can be resolved from metadata!'); - } - if (this.selectedOperatorArity !== values.length) { - throw new Error(`The arity of the selected operator (${this.selectedOperatorArity - }) doesn't match the number of the provided values (${values.length})!`); - } - const deserializedValuesObservables = values.map(v => this.deserializeOperandValue(v)); - const result$ = new ReplaySubject(1); - forkJoin(deserializedValuesObservables).pipe(defaultIfEmpty([])).subscribe(deserializedValues => { - this.setOperands(deserializedValues); - result$.next(); - result$.complete(); - }); - return result$.asObservable(); - } - /** * @param value the serialized output of the [serializeOperandValue()]{@link Category#serializeOperandValue} method * @returns an `Observable` that emits the deserialized value, that can be set as FormControl value and then completes diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/equals-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/equals-date-time.ts index c9f7de2f02..c7c10162db 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/equals-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/equals-date-time.ts @@ -4,7 +4,6 @@ import {Moment} from 'moment'; import {Query} from '../query/query'; import {Operator} from './operator'; import {Operators} from './operators'; -import {NotEqualsDateTime} from "./not-equals-date-time"; /** * Equality operator for indexed fields that store a date time object in timestamp format. @@ -33,8 +32,4 @@ export class EqualsDateTime extends Operator { serialize(): Operators | string { return Operators.EQUALS_DATE_TIME; } - - override negated(): Operator { - return new NotEqualsDateTime(this._operators); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/equals-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/equals-date.ts index 953f8661a4..e1c852883d 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/equals-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/equals-date.ts @@ -4,7 +4,6 @@ import {Query} from '../query/query'; import {OperatorService} from '../../operator-service/operator.service'; import {InRangeDate} from './in-range-date'; import {Operators} from './operators'; -import {NotEqualsDate} from "./not-equals-date"; /** * Equality operator for indexed fields that store a date in timestamp format. @@ -33,8 +32,4 @@ export class EqualsDate extends Operator { serialize(): Operators | string { return Operators.EQUALS_DATE; } - - negated(): Operator { - return new NotEqualsDate(this._operators); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/equals.ts b/projects/netgrif-components-core/src/lib/search/models/operator/equals.ts index 23e1945e21..791d662ee0 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/equals.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/equals.ts @@ -1,6 +1,5 @@ import {Operator} from './operator'; import {Operators} from './operators'; -import {NotEquals} from "./not-equals"; /** * Strict equality operator. Will match if the field has the exact same value as the input. @@ -22,8 +21,4 @@ export class Equals extends Operator { return Operators.EQUALS; } - negated(): Operator { - return new NotEquals(); - } - } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date-time.ts index 9fdfcc24c4..17ba88c6fc 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date-time.ts @@ -43,8 +43,4 @@ export class InRangeDateTime extends Operator { serialize(): Operators | string { return Operators.IN_RANGE_DATE_TIME; } - - negated(): Operator { - throw new Error("Operator InRangeDateTime cannot be negated"); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date.ts index dd5306a2dc..ac5b6e0d88 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/in-range-date.ts @@ -40,8 +40,4 @@ export class InRangeDate extends Operator { serialize(): Operators | string { return Operators.IN_RANGE_DATE; } - - negated(): Operator { - throw new Error("Operator InRangeDate cannot be negated"); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/in-range.ts b/projects/netgrif-components-core/src/lib/search/models/operator/in-range.ts index f706d32ee5..182f015508 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/in-range.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/in-range.ts @@ -22,8 +22,4 @@ export class InRange extends Operator { serialize(): Operators | string { return Operators.IN_RANGE; } - - negated(): Operator { - throw new Error("Operator InRange cannot be negated"); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/is-null.ts b/projects/netgrif-components-core/src/lib/search/models/operator/is-null.ts index e75dbae8c9..741fa706f9 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/is-null.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/is-null.ts @@ -74,8 +74,4 @@ export class IsNull extends Operator { serialize(): Operators | string { return Operators.IS_NULL; } - - negated(): Operator { - throw new Error("Operator IsNull cannot be negated"); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date-time.ts index 86254459ec..f5560abcf2 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date-time.ts @@ -4,7 +4,6 @@ import {LessThan} from './less-than'; import {OperatorService} from '../../operator-service/operator.service'; import {Query} from '../query/query'; import {Operators} from './operators'; -import {MoreThanEqualDateTime} from "./more-than-equal-date-time"; /** * A strict less than operator for DateTime fields @@ -33,8 +32,4 @@ export class LessThanDateTime extends Operator { serialize(): Operators | string { return Operators.LESS_THAN_DATE_TIME; } - - negated(): Operator { - return new MoreThanEqualDateTime(this._operators); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date.ts index b2913a282b..83f777e1e8 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-date.ts @@ -4,7 +4,6 @@ import {OperatorService} from '../../operator-service/operator.service'; import {Query} from '../query/query'; import {LessThan} from './less-than'; import {Operators} from './operators'; -import {MoreThanEqualDate} from "./more-than-equal-date"; /** * A strict less than operator for Date fields @@ -31,8 +30,4 @@ export class LessThanDate extends Operator { serialize(): Operators | string { return Operators.LESS_THAN_DATE; } - - negated(): Operator { - return new MoreThanEqualDate(this._operators); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date-time.ts index fa42ed6d37..b9525a445e 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date-time.ts @@ -4,7 +4,6 @@ import {LessThanEqual} from './less-than-equal'; import {OperatorService} from '../../operator-service/operator.service'; import {Operators} from './operators'; import {Query} from '../query/query'; -import {MoreThanDateTime} from "./more-than-date-time"; /** * Less or equal than operator for Datetime fields @@ -33,8 +32,4 @@ export class LessThanEqualDateTime extends Operator { serialize(): Operators | string { return Operators.LESS_THAN_DATE_TIME; } - - negated(): Operator { - return new MoreThanDateTime(this._operators); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date.ts index 96da873516..6d1f1d9621 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal-date.ts @@ -4,7 +4,6 @@ import {OperatorService} from '../../operator-service/operator.service'; import {Query} from '../query/query'; import {Operators} from './operators'; import {LessThanDate} from './less-than-date'; -import {MoreThanDate} from "./more-than-date"; /** * Less or equal than operator for Date fields @@ -32,8 +31,4 @@ export class LessThanEqualDate extends Operator { serialize(): Operators | string { return Operators.LESS_THAN_EQUAL_DATE; } - - negated(): Operator { - return new MoreThanDate(this._operators); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal.ts index 201e1c3c83..d8dd4313f5 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than-equal.ts @@ -1,6 +1,5 @@ import {Operator} from './operator'; import {Operators} from './operators'; -import {MoreThan} from "./more-than"; /** * Less or equal than operator for numeric or string fields @@ -18,8 +17,4 @@ export class LessThanEqual extends Operator { serialize(): Operators | string { return Operators.LESS_THAN_EQUAL; } - - negated(): Operator { - return new MoreThan(); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/less-than.ts b/projects/netgrif-components-core/src/lib/search/models/operator/less-than.ts index dd8eead751..3c07dfaeec 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/less-than.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/less-than.ts @@ -1,6 +1,5 @@ import {Operator} from './operator'; import {Operators} from './operators'; -import {MoreThanEqual} from "./more-than-equal"; /** * A strict less than operator for numeric or string fields. @@ -17,8 +16,4 @@ export class LessThan extends Operator { serialize(): Operators | string { return Operators.LESS_THAN; } - - negated(): Operator { - return new MoreThanEqual(); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/like.ts b/projects/netgrif-components-core/src/lib/search/models/operator/like.ts index 21a07be461..c848d00b3c 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/like.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/like.ts @@ -28,8 +28,4 @@ export class Like extends Operator { serialize(): Operators | string { return Operators.LIKE; } - - negated(): Operator { - throw new Error("Operator Like cannot be negated"); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date-time.ts index ab37944aa9..e1e81b14f5 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date-time.ts @@ -4,7 +4,6 @@ import {MoreThan} from './more-than'; import {OperatorService} from '../../operator-service/operator.service'; import {Query} from '../query/query'; import {Operators} from './operators'; -import {LessThanEqualDateTime} from "./less-than-equal-date-time"; /** * A strict greater than operator for DateTime fields @@ -35,8 +34,4 @@ export class MoreThanDateTime extends Operator { serialize(): Operators | string { return Operators.MORE_THAN_DATE_TIME; } - - negated(): Operator { - return new LessThanEqualDateTime(this._operators); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date.ts index fdef6a8fb0..d7232b1a44 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-date.ts @@ -4,7 +4,6 @@ import {Query} from '../query/query'; import {MoreThan} from './more-than'; import moment, {Moment} from 'moment'; import {Operators} from './operators'; -import {LessThanEqualDate} from "./less-than-equal-date"; /** * A strict greater than operator for Date fields @@ -33,8 +32,4 @@ export class MoreThanDate extends Operator { serialize(): Operators | string { return Operators.MORE_THAN_DATE; } - - negated(): Operator { - return new LessThanEqualDate(this._operators); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date-time.ts index bf83f05a8e..9065ca9881 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date-time.ts @@ -4,7 +4,6 @@ import {MoreThanEqual} from './more-than-equal'; import {OperatorService} from '../../operator-service/operator.service'; import {Operators} from './operators'; import {Query} from '../query/query'; -import {LessThanDateTime} from "./less-than-date-time"; /** * Greater or equal than operator for Datetime fields @@ -33,8 +32,4 @@ export class MoreThanEqualDateTime extends Operator { serialize(): Operators | string { return Operators.MORE_THAN_EQUAL_DATE_TIME; } - - negated(): Operator { - return new LessThanDateTime(this._operators); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date.ts index c7c16e1cd0..bb30c09590 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal-date.ts @@ -4,7 +4,6 @@ import {OperatorService} from '../../operator-service/operator.service'; import {MoreThanEqual} from './more-than-equal'; import {Operators} from './operators'; import {Query} from '../query/query'; -import {LessThanDate} from "./less-than-date"; /** * Greater or equal than operator for Date fields @@ -31,8 +30,4 @@ export class MoreThanEqualDate extends Operator { serialize(): Operators | string { return Operators.MORE_THAN_EQUAL_DATE; } - - negated(): Operator { - return new LessThanDate(this._operators); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal.ts index 6bcc08a594..85426df5e4 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than-equal.ts @@ -1,6 +1,5 @@ import {Operator} from './operator'; import {Operators} from './operators'; -import {LessThan} from "./less-than"; /** * Greater or equal than operator for numeric or string fields @@ -18,8 +17,4 @@ export class MoreThanEqual extends Operator { serialize(): Operators | string { return Operators.LESS_THAN_EQUAL; } - - negated(): Operator { - return new LessThan(); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/more-than.ts b/projects/netgrif-components-core/src/lib/search/models/operator/more-than.ts index b29ac052aa..34de7437aa 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/more-than.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/more-than.ts @@ -1,6 +1,5 @@ import {Operator} from './operator'; import {Operators} from './operators'; -import {LessThanEqual} from "./less-than-equal"; /** * A strict greater than operator for numeric or string fields. @@ -17,8 +16,4 @@ export class MoreThan extends Operator { serialize(): Operators | string { return Operators.MORE_THAN; } - - negated(): Operator { - return new LessThanEqual(); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date-time.ts b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date-time.ts index fd6cbd6eb8..9652341afb 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date-time.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date-time.ts @@ -29,8 +29,4 @@ export class NotEqualsDateTime extends Operator { serialize(): Operators | string { return Operators.NOT_EQUALS_DATE_TIME; } - - negated(): Operator { - return new EqualsDateTime(this._operators); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date.ts b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date.ts index 94dbdde641..e6e39430a1 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals-date.ts @@ -32,8 +32,4 @@ export class NotEqualsDate extends Operator { serialize(): Operators | string { return Operators.NOT_EQUALS_DATE; } - - negated(): Operator { - return new EqualsDate(this._operators); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals.ts b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals.ts index 5ca75f93cc..100b41f5a7 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/not-equals.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/not-equals.ts @@ -1,6 +1,5 @@ import {Operator} from './operator'; import {Operators} from './operators'; -import {Equals} from "./equals"; /** * Inequality operator. Will match if the field has a different value than the input. @@ -20,8 +19,4 @@ export class NotEquals extends Operator { serialize(): Operators | string { return Operators.NOT_EQUALS; } - - negated(): Operator { - return new Equals(); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts b/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts index f815f0603c..5b3822f4ac 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts @@ -57,20 +57,6 @@ export abstract class Operator { return this._type; } - /** - * Returns a new operator instance that represents the logical negation of this operator. - * - * This method creates a negated version of the current operator, which can be used to - * construct inverse queries. For example, an "equals" operator would return a "not equals" - * operator, and vice versa. - * - * The returned operator should have the same arity as the original but produce logically - * opposite query results when applied to the same arguments. - * - * @returns a new Operator instance that represents the negation of this operator - */ - public abstract negated(): Operator; - /** * Escapes all escapable Elasticsearch symbols. Removes all unescapable Elasticsearch symbols. * diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/substring.ts b/projects/netgrif-components-core/src/lib/search/models/operator/substring.ts index ee403860a5..b30d22a8fa 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/substring.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/substring.ts @@ -17,8 +17,4 @@ export class Substring extends Operator { serialize(): Operators | string { return Operators.SUBSTRING; } - - negated(): Operator { - throw new Error("Operator Substring cannot be negated"); - } } diff --git a/projects/netgrif-components-core/src/lib/search/models/persistance/filter-metadata-allowed-nets.ts b/projects/netgrif-components-core/src/lib/search/models/persistance/filter-metadata-allowed-nets.ts deleted file mode 100644 index de2e347b8d..0000000000 --- a/projects/netgrif-components-core/src/lib/search/models/persistance/filter-metadata-allowed-nets.ts +++ /dev/null @@ -1,16 +0,0 @@ -import {FilterMetadata} from './filter-metadata'; - -/** - * The bare minimum of information necessary for the reconstruction of a saved filter - */ -export interface FilterMetadataAllowedNets { - // todo 2466 remove? - /** - * Allowed nets used to create the filter - */ - allowedNets: Array; - /** - * Serialized advanced search state of the saved filter - */ - filterMetadata: FilterMetadata; -} diff --git a/projects/netgrif-components-core/src/lib/search/models/persistance/filter-metadata.ts b/projects/netgrif-components-core/src/lib/search/models/persistance/filter-metadata.ts deleted file mode 100644 index 4f9509962c..0000000000 --- a/projects/netgrif-components-core/src/lib/search/models/persistance/filter-metadata.ts +++ /dev/null @@ -1,40 +0,0 @@ -import {FilterType} from '../../../filter/models/filter-type'; -import {PredicateTreeMetadata} from './generator-metadata'; - -/** - * Saved filter generated by the {@link AbstractAdvancedSearchComponent}. - */ -export interface FilterMetadata { - // todo 2466 remove? - filterType: FilterType; - predicateMetadata: PredicateTreeMetadata; - /** - * Serialized {@link Category} classes, that were available in the saved search component. - */ - searchCategories?: Array; - /** - * Whether the search categories default to the view the filter will be loaded in should be merged with the saved categories. - * - * Defaults to a falsy value. - * - * If falsy, only the categories stored in [searchCategories]{@link FilterMetadata#searchCategories} will be used. - */ - defaultSearchCategories?: boolean; - /** - * Whether the allowed nets used to generate category metadata can be inherited from frontend providers. - * - * Defaults to a falsy value. - * - * If falsy, only the allowed nets stored in the filter data field will be used to generate category metadata. - */ - inheritAllowedNets?: boolean; - /** - * Whether all available nets should be used when generating category metadata. - * - * Defaults to a falsy value. - * - * If truthy, all nets available in the system will be used to generate category metadata, - * ignoring both the allowed nets stored in the filter data field and inherited allowed nets. - */ - allAllowedNets?: boolean; -} diff --git a/projects/netgrif-components-core/src/lib/search/models/persistance/generator-metadata.ts b/projects/netgrif-components-core/src/lib/search/models/persistance/generator-metadata.ts deleted file mode 100644 index cd543d3b9e..0000000000 --- a/projects/netgrif-components-core/src/lib/search/models/persistance/generator-metadata.ts +++ /dev/null @@ -1,48 +0,0 @@ -import {Categories} from '../category/categories'; - -/** - * Holds serializable information necessary for recreation of any {@link Category} instance in any internal state. - * - * Is used to persist search GUI state. - */ -export interface CategoryGeneratorMetadata { - category: Categories | string; - configuration: CategoryMetadataConfiguration; - values: Array; -} - -/** - * The keys are some configuration options that make sense to the {@link Category} instance that generated - * the {@link CategoryGeneratorMetadata} object. - * - * The values are some serializable data, that the Category needs to restore its state. - */ -export interface CategoryMetadataConfiguration { - [k: string]: unknown; -} - -/** - * The two nested arrays represent a predicate tree with 3 levels. The root node of the tree is a predicate consisting of a conjunction - * (AND) of its subtrees. - * - * The single array represents a predicate tree with 2 levels. The root node of the tree is a predicate consisting of a disjunction (OR) of - * its subtrees. - * - * The {@link CategoryGeneratorMetadata} represents a predicate tree with 1 level - a leaf node. - */ -export type GeneratorMetadata = PredicateTreeMetadata | Array | CategoryGeneratorMetadata; - -/** - * Serialized [advanced search]{@link AbstractAdvancedSearchComponent} filter predicate tree. - * - * The nested array represent nested predicate trees with boolean operators. - * The structure of the tree mirrors the search component. - * - * The top level array is a conjunction (AND) of its subtrees. - * - * The second level array is a disjunction (OR) of the leaves. - * - * The {@link CategoryGeneratorMetadata} is a leaf node of the predicate tree containing a single query - * generated by {@link AbstractSearchPredicateComponent} (and by extension by a {@link Category}). - */ -export type PredicateTreeMetadata = Array>; diff --git a/projects/netgrif-components-core/src/lib/search/models/persistance/saved-filter-metadata.ts b/projects/netgrif-components-core/src/lib/search/models/persistance/saved-filter-metadata.ts deleted file mode 100644 index de15147cc0..0000000000 --- a/projects/netgrif-components-core/src/lib/search/models/persistance/saved-filter-metadata.ts +++ /dev/null @@ -1,28 +0,0 @@ -import {Filter} from '../../../filter/models/filter'; -import {Case} from '../../../resources/interface/case'; -import {FilterMetadataAllowedNets} from './filter-metadata-allowed-nets'; - -/** - * All the necessary data for full reconstruction of a saved filter - */ -export interface SavedFilterMetadata extends FilterMetadataAllowedNets { - // todo 2466 remove? - /** - * The view ID of the view the filter was created in - */ - originViewId: string; - /** - * The filter object represented by the provided metadata - */ - filter: Filter; - /** - * The filter's case object. - * - * Only present if the filter is loaded. When the filter is saved onle the case id is returned - */ - filterCase?: Case; - /** - * ID of the filter's case. - */ - filterCaseId: string; -} diff --git a/projects/netgrif-components-core/src/lib/search/models/predicate/editable-clause-predicate-with-generators.ts b/projects/netgrif-components-core/src/lib/search/models/predicate/editable-clause-predicate-with-generators.ts index 64262b65df..a6f665833c 100644 --- a/projects/netgrif-components-core/src/lib/search/models/predicate/editable-clause-predicate-with-generators.ts +++ b/projects/netgrif-components-core/src/lib/search/models/predicate/editable-clause-predicate-with-generators.ts @@ -12,16 +12,6 @@ export class EditableClausePredicateWithGenerators extends EditableClausePredica constructor(operator: BooleanOperator, parentNotifier?: Subject, initiallyVisible = true, bracketSubPredicateText = false) { super(operator, parentNotifier, initiallyVisible, bracketSubPredicateText); - this._metadataGenerator = () => { - const result = []; - for (const predicate of this._predicates.values()) { - const metadata = predicate.createGeneratorMetadata(); - if (metadata !== undefined) { - result.push(metadata); - } - } - return result.length > 0 ? result : undefined; - }; } addNewClausePredicate(operator: BooleanOperator, initiallyVisible = true): number { diff --git a/projects/netgrif-components-core/src/lib/search/models/predicate/predicate-with-generator.ts b/projects/netgrif-components-core/src/lib/search/models/predicate/predicate-with-generator.ts index 04d384274f..0f3ac52cbe 100644 --- a/projects/netgrif-components-core/src/lib/search/models/predicate/predicate-with-generator.ts +++ b/projects/netgrif-components-core/src/lib/search/models/predicate/predicate-with-generator.ts @@ -19,7 +19,6 @@ export class PredicateWithGenerator extends Predicate { constructor(protected _predicate: Predicate, protected _generator?: Category, initiallyVisible?: boolean) { super(); this._visible = initiallyVisible ?? !_generator; - this.initializeMetadataGenerator(); this.initializeFilterTextSegmentsGenerator(); } @@ -75,19 +74,6 @@ export class PredicateWithGenerator extends Predicate { } } - private initializeMetadataGenerator() { - this._metadataGenerator = () => { - try { - return this._predicate.createGeneratorMetadata(); - } catch (e) { - if (this._generator && this._generator.providesPredicate) { - return this._generator.createMetadata(); - } - throw e; - } - }; - } - private initializeFilterTextSegmentsGenerator() { this._filterTextSegmentsGenerator = () => { const segments = this._predicate.createFilterTextSegments(); diff --git a/projects/netgrif-components-core/src/lib/search/models/predicate/predicate.ts b/projects/netgrif-components-core/src/lib/search/models/predicate/predicate.ts index 739bb57817..cb8872fe06 100644 --- a/projects/netgrif-components-core/src/lib/search/models/predicate/predicate.ts +++ b/projects/netgrif-components-core/src/lib/search/models/predicate/predicate.ts @@ -1,5 +1,4 @@ import {Query} from '../query/query'; -import {GeneratorMetadata} from '../persistance/generator-metadata'; import {FilterTextSegment} from '../persistance/filter-text-segment'; import {BooleanOperator} from '../boolean-operator'; @@ -12,7 +11,6 @@ import {BooleanOperator} from '../boolean-operator'; export abstract class Predicate { protected _visible: boolean; - protected _metadataGenerator: () => GeneratorMetadata | undefined; protected _filterTextSegmentsGenerator: () => Array; /** @@ -20,9 +18,6 @@ export abstract class Predicate { */ protected constructor(initiallyVisible = true) { this._visible = !!initiallyVisible; - this._metadataGenerator = () => { - throw new Error('This predicate has no metadata generator registered!'); - }; this._filterTextSegmentsGenerator = () => { return []; }; @@ -87,18 +82,6 @@ export abstract class Predicate { this._visible = true; } - public setMetadataGenerator(metadataGenerator: () => GeneratorMetadata | undefined) { - this._metadataGenerator = metadataGenerator; - } - - /** - * @returns an object containing the necessary information for the reconstruction of the entire predicate tree in serializable form. - * Returns `undefined` if the predicate tree rooted at this node is incomplete and would evaluate into an empty filter. - */ - public createGeneratorMetadata(): GeneratorMetadata | undefined { - return this._metadataGenerator(); - } - public setFilterTextSegmentsGenerator(filterTextSegmentsGenerator: () => Array) { this._filterTextSegmentsGenerator = filterTextSegmentsGenerator; } diff --git a/projects/netgrif-components-core/src/lib/search/operator-service/operator.service.ts b/projects/netgrif-components-core/src/lib/search/operator-service/operator.service.ts index f57f72381d..09cb899a4a 100644 --- a/projects/netgrif-components-core/src/lib/search/operator-service/operator.service.ts +++ b/projects/netgrif-components-core/src/lib/search/operator-service/operator.service.ts @@ -1,6 +1,5 @@ import {Injectable, Type} from '@angular/core'; import {Operator} from '../models/operator/operator'; -import {Operators} from '../models/operator/operators'; import {OperatorResolverService} from './operator-resolver.service'; /** @@ -23,10 +22,6 @@ export class OperatorService { return this._operators.get(operatorClass); } - public getFromMetadata(metadata: Operators | string): Operator { - return this.getOperator(this._operatorResolver.toClass(metadata)); - } - private createOperatorIfNotInMap(operatorClass: Type>): void { if (!this._operators.has(operatorClass)) { this._operators.set(operatorClass, new operatorClass(this)); diff --git a/projects/netgrif-components-core/src/lib/search/public-api.ts b/projects/netgrif-components-core/src/lib/search/public-api.ts index 6505845071..9a8f91d0fa 100644 --- a/projects/netgrif-components-core/src/lib/search/public-api.ts +++ b/projects/netgrif-components-core/src/lib/search/public-api.ts @@ -65,11 +65,7 @@ export * from './models/category/net-attribute-pair'; export * from './models/category/name-id-pair'; export * from './models/component-configuration/search-component-configuration'; export * from './models/base-filter'; -export * from './models/persistance/generator-metadata'; -export * from './models/persistance/filter-metadata'; -export * from './models/persistance/saved-filter-metadata'; export * from './models/persistance/filter-text-segment'; -export * from './models/persistance/filter-metadata-allowed-nets'; export * from './category-factory/optional-dependencies'; export * from './category-factory/category-serialisation-pair'; diff --git a/projects/netgrif-components-core/src/lib/search/search-component/abstract-search.component.ts b/projects/netgrif-components-core/src/lib/search/search-component/abstract-search.component.ts index a8951583a1..5d839c572d 100644 --- a/projects/netgrif-components-core/src/lib/search/search-component/abstract-search.component.ts +++ b/projects/netgrif-components-core/src/lib/search/search-component/abstract-search.component.ts @@ -9,7 +9,6 @@ import {SearchMode} from '../models/component-configuration/search-mode'; import {AllowedNetsService} from '../../allowed-nets/services/allowed-nets.service'; import {NAE_SEARCH_CATEGORIES} from '../category-factory/search-categories-injection-token'; import {Category} from '../models/category/category'; -import {SavedFilterMetadata} from '../models/persistance/saved-filter-metadata'; import {ViewIdService} from '../../user/services/view-id.service'; import {NAE_FILTERS_FILTER} from '../../filter/models/filters-filter-injection-token'; import {Filter} from '../../filter/models/filter'; @@ -46,15 +45,6 @@ export abstract class AbstractSearchComponent implements SearchComponentConfigur @Input() public disabled: boolean; - /** - * The emitted data contains the filter case object - */ - @Output() filterLoaded: EventEmitter = new EventEmitter(); - /** - * The emitted data contains only the saved case's ID - */ - @Output() filterSaved: EventEmitter = new EventEmitter(); - protected constructor(protected _searchService: SearchService, protected _logger: LoggerService, protected _dialogService: DialogService, diff --git a/projects/netgrif-components-core/src/lib/search/search-predicate-component/abstract-search-predicate.component.ts b/projects/netgrif-components-core/src/lib/search/search-predicate-component/abstract-search-predicate.component.ts index b6e02f6dac..5c39814c25 100644 --- a/projects/netgrif-components-core/src/lib/search/search-predicate-component/abstract-search-predicate.component.ts +++ b/projects/netgrif-components-core/src/lib/search/search-predicate-component/abstract-search-predicate.component.ts @@ -66,13 +66,6 @@ export abstract class AbstractSearchPredicateComponent implements OnInit, OnDest + ' Behavior in this case is undefined.'); } - this.predicate.setMetadataGenerator(() => { - if (!!this._selectedCategory) { - return this._selectedCategory.createMetadata(); - } - return undefined; - }); - this.predicate.setFilterTextSegmentsGenerator(() => { if (!!this._selectedCategory) { return this._selectedCategory.createFilterTextSegments(); diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts index e69457f2b4..18eef31036 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts @@ -7,17 +7,15 @@ import {SimpleFilter} from '../../filter/models/simple-filter'; import {MergeOperator} from '../../filter/models/merge-operator'; import {PredicateRemovalEvent} from '../models/predicate-removal-event'; import {Query} from '../models/query/query'; -import {distinctUntilChanged, filter, map, tap} from 'rxjs/operators'; +import {distinctUntilChanged, filter, map} from 'rxjs/operators'; import {EditableClausePredicateWithGenerators} from '../models/predicate/editable-clause-predicate-with-generators'; import {Category} from '../models/category/category'; -import {PredicateTreeMetadata} from '../models/persistance/generator-metadata'; import {NAE_BASE_FILTER} from '../models/base-filter-injection-token'; import {BaseFilter} from '../models/base-filter'; import {LoggerService} from '../../logger/services/logger.service'; import {CategoryFactory} from '../category-factory/category-factory'; import {FilterType} from '../../filter/models/filter-type'; import {LoadingEmitter} from '../../utility/loading-emitter'; -import {FilterMetadata} from '../models/persistance/filter-metadata'; import {FilterTextSegment} from '../models/persistance/filter-text-segment'; import {QueryItem, QueryItemType} from "../../pfql/model/query-item-type"; import {parseQuery} from "../../pfql/pfql-utils"; @@ -54,7 +52,6 @@ export class SearchService implements OnDestroy { * The index of a removed {@link Predicate} is emmited into this stream */ protected _predicateRemoved$: Subject; - protected _loadingFromMetadata$: LoadingEmitter; protected _loadingFromPfql$: LoadingEmitter; /** * The `rootPredicate` uses this stream to notify the search service about changes to the held query @@ -90,7 +87,6 @@ export class SearchService implements OnDestroy { this._rootPredicate = new EditableClausePredicateWithGenerators(BooleanOperator.AND, this._predicateQueryChanged$, undefined, true); this._activeFilter = new BehaviorSubject(this._baseFilter); this._predicateRemoved$ = new Subject(); - this._loadingFromMetadata$ = new LoadingEmitter(); this._loadingFromPfql$ = new LoadingEmitter(); if (baseFilter.filter instanceof Observable) { @@ -113,7 +109,6 @@ export class SearchService implements OnDestroy { this.subFilter.unsubscribe(); } this.subPredicateChanged?.unsubscribe(); - this._loadingFromMetadata$.complete(); this._loadingFromPfql$.complete(); this._rootPredicate.destroy(); } @@ -181,15 +176,6 @@ export class SearchService implements OnDestroy { return this.baseFilter.type; } - /** - * @returns whether the search service is currently loading its state from metadata or not. - * - * See [loadFromMetadata()]{@link SearchService#loadFromMetadata} - */ - public get loadingFromMetadata(): boolean { - return this._loadingFromMetadata$.value; - } - /** * @returns whether the search service is currently loading its state from PFQL query or not. * @@ -199,16 +185,6 @@ export class SearchService implements OnDestroy { return this._loadingFromPfql$.value; } - /** - * @returns an `Observable` that emits `true` if the search service is currently loading its state from metadata, - * emits `false` otherwise. - * - * See [loadFromMetadata()]{@link SearchService#loadFromMetadata} - */ - public get loadingFromMetadata$(): Observable { - return this._loadingFromMetadata$.asObservable(); - } - /** * @returns an `Observable` that emits `true` if the search service is currently loading its state from PFQL query, * emits `false` otherwise. @@ -352,63 +328,6 @@ export class SearchService implements OnDestroy { this._activeFilter.next(newFilter); } - /** - * @returns `undefined` if the predicate tree contains no complete query. - * Otherwise returns the serialized form of the completed queries in the predicate tree. - */ - public createPredicateMetadata(): PredicateTreeMetadata | undefined { - return this._rootPredicate.createGeneratorMetadata() as PredicateTreeMetadata; - } - - /** - * Replaces the current predicate filter by the one corresponding to the provided generator metadata. - * - * The {@link CategoryFactory} instance must be provided for this service if we want to use this method. Logs an error and does nothing. - * - * The `filterType` of this search service must match the `filterType` of the provided metadata. Otherwise an error is thrown. - * - * @param metadata the serialized state of the predicate tree that should be restored to this search service - */ - public loadFromMetadata(metadata: FilterMetadata) { - if (this._categoryFactory === null) { - this._log.error('A CategoryFactory instance must be provided for the SearchService' - + ' if you want to reconstruct a predicate filter from saved metadata'); - return; - } - - if (metadata.filterType !== this.filterType) { - throw Error(`The filter type of the provided metadata (${metadata.filterType - }) does not match the filter type of the search service (${this.filterType})!`); - } - - this.clearPredicates(true); - this._loadingFromMetadata$.on(); - - const generatorObservables = []; - if (Array.isArray(metadata.predicateMetadata)) { - for (const clause of metadata.predicateMetadata) { - const branchId = this._rootPredicate.addNewClausePredicate(BooleanOperator.OR); - const branchPredicate = ( - this._rootPredicate.getPredicateMap().get(branchId) - .getWrappedPredicate() as unknown as EditableClausePredicateWithGenerators - ); - for (const predicate of clause) { - const localBranchReference = branchPredicate; - generatorObservables.push( - this._categoryFactory.getFromMetadata(predicate).pipe(tap(generator => { - localBranchReference.addNewPredicateFromGenerator(generator); - })) - ); - } - } - } - - forkJoin(generatorObservables).subscribe(() => { - this._loadingFromMetadata$.off(); - this.updateActiveFilter(); - }); - } - /** * Loads a PFQL query string into the search service's predicate tree structure. * diff --git a/projects/netgrif-components-core/src/lib/task-content/model/resource-interface.ts b/projects/netgrif-components-core/src/lib/task-content/model/resource-interface.ts index 912638e8e9..0efa353c63 100644 --- a/projects/netgrif-components-core/src/lib/task-content/model/resource-interface.ts +++ b/projects/netgrif-components-core/src/lib/task-content/model/resource-interface.ts @@ -4,7 +4,6 @@ import {Validation} from '../../data-fields/models/validation'; import {FieldTypeResource} from './field-type-resource'; import {FormatFilter} from '../../data-fields/models/format-filter'; import {Component} from '../../data-fields/models/component'; -import {FilterMetadata} from '../../search/models/persistance/filter-metadata'; export interface DataFieldResource { stringId: string; @@ -31,6 +30,5 @@ export interface DataFieldResource { [k: string]: string }; allowedNets?: Array; - filterMetadata?: FilterMetadata; parentTaskId?: string; } From 5bfbae23a687e47ee21a28a91079d69ff3bf3a0c Mon Sep 17 00:00:00 2001 From: chvostek Date: Fri, 28 Aug 2026 12:58:52 +0200 Subject: [PATCH 38/55] [NAE-2466] Advanced search for PFQL - add documentation --- .../src/lib/pfql/pfql-visitor.ts | 43 +++++++++++++++++-- .../category-factory/optional-dependencies.ts | 6 ++- .../search-categories-injection-token.ts | 9 +++- .../models/category/case/case-plain-query.ts | 6 ++- .../lib/search/models/category/category.ts | 13 +++++- .../models/category/task/task-plain-query.ts | 7 ++- .../search/search-service/search.service.ts | 26 +++++++++-- 7 files changed, 97 insertions(+), 13 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts index 33c2e7b661..1b823cef07 100644 --- a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts +++ b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts @@ -175,7 +175,16 @@ export class PfqlVisitor extends QueryLangVisitor> { }; /** - * todo 2466 doc + /** + * Visits a case OR expression and processes multiple AND expressions joined by OR operators. + * + * When multiple AND expressions are connected with OR operators, the entire expression is treated + * as a raw query string and wrapped in a case plain query, since complex OR logic requires + * special handling beyond simple query composition. + * + * @param ctx - The case OR expression parse tree context + * @returns An array containing either the visited AND expression items if there's only one, + * or a single raw expression wrapping the entire query text if multiple OR-connected expressions exist */ override visitCaseOrExpression = (ctx: CaseOrExpressionContext): Array => { const andExpressionContexts = ctx.caseAndExpression(); @@ -213,7 +222,15 @@ export class PfqlVisitor extends QueryLangVisitor> { }; /** - * todo 2466 doc + * Visits a task OR expression and processes multiple AND expressions joined by OR operators. + * + * When multiple AND expressions are connected with OR operators, the entire expression is treated + * as a raw query string and wrapped in a task plain query, since complex OR logic requires + * special handling beyond simple query composition. + * + * @param ctx - The task OR expression parse tree context + * @returns An array containing either the visited AND expression items if there's only one, + * or a single raw expression wrapping the entire query text if multiple OR-connected expressions exist */ override visitTaskOrExpression = (ctx: TaskOrExpressionContext): Array => { const andExpressionContexts = ctx.taskAndExpression(); @@ -804,13 +821,31 @@ export class PfqlVisitor extends QueryLangVisitor> { return new SimpleExpression(operator, undefined); } - // todo 2466 doc + /** + * Handles a case raw query by wrapping it in a case plain query expression. + * + * This method is used when the query contains complex expressions that cannot be parsed + * into structured query items (e.g., complex OR expressions with multiple branches or negations). + * The raw query text is preserved and processed as a plain text query. + * + * @param query - The raw query string to be wrapped + * @returns A raw expression containing the case plain query category and the original query text + */ protected handleCaseRawQuery(query: string): RawExpression { const category: CasePlainQuery = new CasePlainQuery(this._operatorService, this._logger); return new RawExpression(category, query); } - // todo 2466 doc + /** + * Handles a task raw query by wrapping it in a task plain query expression. + * + * This method is used when the query contains complex expressions that cannot be parsed + * into structured query items (e.g., complex OR expressions with multiple branches or negations). + * The raw query text is preserved and processed as a plain text query. + * + * @param query - The raw query string to be wrapped + * @returns A raw expression containing the task plain query category and the original query text + */ protected handleTaskRawQuery(query: string): RawExpression { const category: TaskPlainQuery = new TaskPlainQuery(this._operatorService, this._logger); return new RawExpression(category, query); diff --git a/projects/netgrif-components-core/src/lib/search/category-factory/optional-dependencies.ts b/projects/netgrif-components-core/src/lib/search/category-factory/optional-dependencies.ts index ffe7882359..09207d1bf7 100644 --- a/projects/netgrif-components-core/src/lib/search/category-factory/optional-dependencies.ts +++ b/projects/netgrif-components-core/src/lib/search/category-factory/optional-dependencies.ts @@ -20,6 +20,10 @@ export interface OptionalDependencies { * If the {@link CategoryFactory} cannot inject an instance of this service into itself `null` will be provided. */ userResourceService: UserResourceService | null; - // todo 2466 + /** + * When set to `true`, autocomplete categories will ignore net filtering. + * This can be useful when you want autocomplete suggestions to include results from all nets, + * regardless of the currently selected net context. + */ ignoreNetsOnAutocompleteCategories?: boolean; } diff --git a/projects/netgrif-components-core/src/lib/search/category-factory/search-categories-injection-token.ts b/projects/netgrif-components-core/src/lib/search/category-factory/search-categories-injection-token.ts index 72c2e15380..163be82e28 100644 --- a/projects/netgrif-components-core/src/lib/search/category-factory/search-categories-injection-token.ts +++ b/projects/netgrif-components-core/src/lib/search/category-factory/search-categories-injection-token.ts @@ -26,5 +26,12 @@ export const NAE_DEFAULT_CASE_SEARCH_CATEGORIES = new InjectionToken>>>('NaeDefaultTaskSearchCategories'); -// todo 2466 +/** + * Determines whether nets (process definitions) should be ignored when using autocomplete functionality in search categories. + * + * When set to `true`, the autocomplete feature will not suggest or include nets in the results. + * This is useful when you want to limit autocomplete suggestions to other entity types. + * + * @default false + */ export const NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY = new InjectionToken('NaeIgnoreNetsOnAutocompleteCategory') diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-plain-query.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-plain-query.ts index e33d7578f5..67fe3cbb8f 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-plain-query.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-plain-query.ts @@ -5,7 +5,11 @@ import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; import {Categories} from "../categories"; import {PlainQueryCategory} from "../plain-query-category"; -// todo 2466 doc +/** + * Represents a plain query category for case resources. + * This class extends PlainQueryCategory and provides case-specific query functionality + * with serialization support for the CASES resource type. + */ export class CasePlainQuery extends PlainQueryCategory { constructor(operators: OperatorService, logger: LoggerService) { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/category.ts b/projects/netgrif-components-core/src/lib/search/models/category/category.ts index 2ba5574df2..989f56ccd6 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/category.ts @@ -192,7 +192,12 @@ export abstract class Category { } /** - * todo 2466 doc + * Sets the required input type for arguments for this category. + * + * This setter allows changing the input type dynamically, which can be useful when the argument input type + * depends on runtime conditions (e.g., in {@link CaseDataset} category where the input type depends on the selected data field type). + * + * @param inputType the new input type to be set for this category */ public set inputType(inputType: SearchInputType) { this._inputType = inputType; @@ -224,7 +229,11 @@ export abstract class Category { } /** - * todo 2466 doc + * Returns the current array of `FormControl` objects that contains as many controls as is the arity of the selected operator. + * Unlike the [operandsFormControls$]{@link Category#operandsFormControls$} observable, this getter returns the actual array + * instance directly without wrapping it in an observable. + * + * @returns an array of `FormControl` objects for the operands, or an empty array if no operator is selected */ public get operandsFormControls(): Array { return this._operandsFormControls; diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-plain-query.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-plain-query.ts index 803cc2037e..2410d7782c 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-plain-query.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-plain-query.ts @@ -5,7 +5,12 @@ import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; import {Categories} from "../categories"; import {PlainQueryCategory} from "../plain-query-category"; -// todo 2466 doc +/** + * Plain query category implementation for task-related search operations. + * + * This class extends {@link PlainQueryCategory} to provide task-specific query functionality, + * using the TASKS resource type prefix for query generation. + */ export class TaskPlainQuery extends PlainQueryCategory { constructor(operators: OperatorService, logger: LoggerService) { diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts index 18eef31036..35cbd99881 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts @@ -387,7 +387,17 @@ export class SearchService implements OnDestroy { } /** - * todo 2466 + * Recursively loads an array of query items (expressions and logical operators) into a predicate node. + * + * Processes each query item in the array: + * - For simple expressions: loads them as individual predicates using {@link loadSimpleExpressionIntoPredicate} + * - For complex expressions: recursively processes their nested items + * - For raw expressions: loads them as plain query predicates using {@link loadPlainQueryIntoPredicate} + * - Logical operators are filtered out and not processed + * + * @param predicate the predicate node into which the query items should be loaded + * @param items array of query items to process and load into the predicate tree + * @returns an array of observables that emit when each category's data has been loaded from its expression */ protected loadExpressionsIntoPredicate(predicate: EditableClausePredicateWithGenerators, items: Array): Array> { const expressions: Array = items.filter(item => item.type() !== QueryItemType.LOGICAL_OPERATOR); @@ -422,12 +432,22 @@ export class SearchService implements OnDestroy { const branchId = predicate.addNewClausePredicate(BooleanOperator.OR); const localPredicate = predicate.getPredicateMap().get(branchId).getWrappedPredicate() as unknown as EditableClausePredicateWithGenerators; const category: Category = simpleExpr.category; - const categoryLoading$: Observable = category.loadFromPfqlExpression(simpleExpr); // todo 2466 auto + const categoryLoading$: Observable = category.loadFromPfqlExpression(simpleExpr); localPredicate.addNewPredicateFromGenerator(category); return categoryLoading$; } - // todo 2466 doc + /** + * Loads a raw PFQL expression into a predicate node. + * + * Creates a new clause predicate branch, extracts the plain query category from the raw expression, + * loads the expression data into the category, and adds the category as a new predicate generator + * to the created branch. + * + * @param predicate the predicate node into which the raw expression should be loaded + * @param expression the raw expression to load + * @returns an observable that emits when the category data has been loaded from the expression + */ protected loadPlainQueryIntoPredicate(predicate: EditableClausePredicateWithGenerators, expression: RawExpression): Observable{ const branchId = predicate.addNewClausePredicate(BooleanOperator.OR); const localPredicate = predicate.getPredicateMap().get(branchId).getWrappedPredicate() as unknown as EditableClausePredicateWithGenerators; From 7968664b67b171650348b95bd77eb60d6ac43038 Mon Sep 17 00:00:00 2001 From: chvostek Date: Fri, 28 Aug 2026 13:16:11 +0200 Subject: [PATCH 39/55] [NAE-2466] Advanced search for PFQL - update documentation --- .../src/lib/search/search-service/search.service.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts index 35cbd99881..0afcccfac4 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts @@ -67,7 +67,8 @@ export class SearchService implements OnDestroy { * It is required if we want to load predicate filter from saved metadata * @param baseFilter Filter that should be applied to the view when no searching is being performed. * Injected trough the {@link NAE_BASE_FILTER} injection token. - * @param _ignoreNetsOnAutocompleteCategories todo 2466 + * @param _ignoreNetsOnAutocompleteCategories boolean flag that determines whether net-related categories should be ignored + * when providing autocomplete suggestions. Injected through the {@link NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY} injection token. * @param _injector injector from angular core */ constructor(protected _log: LoggerService, From a3ce92fe0c894d29141a3e5f6bd5db1788937a75 Mon Sep 17 00:00:00 2001 From: chvostek Date: Mon, 31 Aug 2026 08:48:52 +0200 Subject: [PATCH 40/55] [NAE-2466] Advanced search for PFQL - remove filter metadata implementation - update advanced search immediate field representation - fix process identifier column search - resolve some todos --- ...e-config-content1-case-view.component.html | 2 +- ...tle-config-content1-case-view.component.ts | 18 ----------- ...e-config-content2-case-view.component.html | 2 +- ...tle-config-content2-case-view.component.ts | 18 ----------- ...e-config-content3-case-view.component.html | 2 +- ...tle-config-content3-case-view.component.ts | 19 +---------- .../single-tabbed-case-view.component.html | 3 +- .../single-tabbed-case-view.component.ts | 18 ----------- .../tabbed-case-view.component.html | 3 +- .../tabbed-case-view.component.ts | 19 +---------- .../src/lib/panel/abstract/featured-value.ts | 5 +++ .../abstract/panel-with-immediate-data.ts | 4 +++ ...bstract-immediate-filter-text.component.ts | 15 ++++++++- .../model/filter-text-injection-token.ts | 2 ++ .../src/lib/pfql/pfql-visitor.ts | 2 -- .../header-search.service.ts | 4 ++- .../models/category/case/case-process.ts | 3 +- .../models/category/plain-query-category.ts | 4 +-- .../src/lib/search/models/search-index.ts | 1 - .../search-index-resolver.service.ts | 2 -- .../default-case-ref-list-view.component.html | 2 +- .../default-case-ref-list-view.component.ts | 6 ---- .../default-tabbed-case-view.component.html | 2 +- .../default-tabbed-case-view.component.ts | 14 -------- ...immediate-filter-text-content.component.ts | 32 ++++++++++--------- .../panel-item/panel-item.component.html | 11 +++++-- 26 files changed, 67 insertions(+), 146 deletions(-) diff --git a/projects/nae-example-app/src/app/doc/demo-title-config/content/1/demo-title-config-content1-case-view.component.html b/projects/nae-example-app/src/app/doc/demo-title-config/content/1/demo-title-config-content1-case-view.component.html index 92593fa0c7..a296bd6028 100644 --- a/projects/nae-example-app/src/app/doc/demo-title-config/content/1/demo-title-config-content1-case-view.component.html +++ b/projects/nae-example-app/src/app/doc/demo-title-config/content/1/demo-title-config-content1-case-view.component.html @@ -3,7 +3,7 @@
- +
diff --git a/projects/nae-example-app/src/app/doc/demo-title-config/content/1/demo-title-config-content1-case-view.component.ts b/projects/nae-example-app/src/app/doc/demo-title-config/content/1/demo-title-config-content1-case-view.component.ts index 6bea613a9f..a905e6158e 100644 --- a/projects/nae-example-app/src/app/doc/demo-title-config/content/1/demo-title-config-content1-case-view.component.ts +++ b/projects/nae-example-app/src/app/doc/demo-title-config/content/1/demo-title-config-content1-case-view.component.ts @@ -12,7 +12,6 @@ import { NAE_BASE_FILTER, NAE_SEARCH_CATEGORIES, NAE_TAB_DATA, - SavedFilterMetadata, SearchService, SimpleFilter, AbstractTabbedCaseViewComponent, @@ -89,21 +88,4 @@ export class DemoTitleConfigContent1CaseViewComponent extends AbstractTabbedCase super.initializeHeader(this.caseHeaderComponent); } - loadFilter(filterData: SavedFilterMetadata) { - this._injectedTabData.tabViewRef.openTab({ - label: { - text: filterData.filter.title - }, - canBeClosed: true, - tabContentComponent: DemoTitleConfigContent1CaseViewComponent, - injectedObject: {...this._injectedTabData, loadFilter: filterData.filter}, - order: this._injectedTabData.tabViewOrder, - parentUniqueId: this._injectedTabData.tabUniqueId - }, this._autoswitchToTaskTab, this._openExistingTab); - } - - saveFilter(filterData: SavedFilterMetadata) { - console.log(filterData); - } - } diff --git a/projects/nae-example-app/src/app/doc/demo-title-config/content/2/demo-title-config-content2-case-view.component.html b/projects/nae-example-app/src/app/doc/demo-title-config/content/2/demo-title-config-content2-case-view.component.html index 92593fa0c7..a296bd6028 100644 --- a/projects/nae-example-app/src/app/doc/demo-title-config/content/2/demo-title-config-content2-case-view.component.html +++ b/projects/nae-example-app/src/app/doc/demo-title-config/content/2/demo-title-config-content2-case-view.component.html @@ -3,7 +3,7 @@
- +
diff --git a/projects/nae-example-app/src/app/doc/demo-title-config/content/2/demo-title-config-content2-case-view.component.ts b/projects/nae-example-app/src/app/doc/demo-title-config/content/2/demo-title-config-content2-case-view.component.ts index d6a3c527fa..8aa501dd71 100644 --- a/projects/nae-example-app/src/app/doc/demo-title-config/content/2/demo-title-config-content2-case-view.component.ts +++ b/projects/nae-example-app/src/app/doc/demo-title-config/content/2/demo-title-config-content2-case-view.component.ts @@ -12,7 +12,6 @@ import { NAE_BASE_FILTER, NAE_SEARCH_CATEGORIES, NAE_TAB_DATA, - SavedFilterMetadata, SearchService, SimpleFilter, AbstractTabbedCaseViewComponent, @@ -87,21 +86,4 @@ export class DemoTitleConfigContent2CaseViewComponent extends AbstractTabbedCase super.initializeHeader(this.caseHeaderComponent); } - loadFilter(filterData: SavedFilterMetadata) { - this._injectedTabData.tabViewRef.openTab({ - label: { - text: filterData.filter.title - }, - canBeClosed: true, - tabContentComponent: DemoTitleConfigContent2CaseViewComponent, - injectedObject: {...this._injectedTabData, loadFilter: filterData.filter}, - order: this._injectedTabData.tabViewOrder, - parentUniqueId: this._injectedTabData.tabUniqueId - }, this._autoswitchToTaskTab, this._openExistingTab); - } - - saveFilter(filterData: SavedFilterMetadata) { - console.log(filterData); - } - } diff --git a/projects/nae-example-app/src/app/doc/demo-title-config/content/3/demo-title-config-content3-case-view.component.html b/projects/nae-example-app/src/app/doc/demo-title-config/content/3/demo-title-config-content3-case-view.component.html index 92593fa0c7..a296bd6028 100644 --- a/projects/nae-example-app/src/app/doc/demo-title-config/content/3/demo-title-config-content3-case-view.component.html +++ b/projects/nae-example-app/src/app/doc/demo-title-config/content/3/demo-title-config-content3-case-view.component.html @@ -3,7 +3,7 @@
- +
diff --git a/projects/nae-example-app/src/app/doc/demo-title-config/content/3/demo-title-config-content3-case-view.component.ts b/projects/nae-example-app/src/app/doc/demo-title-config/content/3/demo-title-config-content3-case-view.component.ts index 4a0bf93b3c..4d09ef391e 100644 --- a/projects/nae-example-app/src/app/doc/demo-title-config/content/3/demo-title-config-content3-case-view.component.ts +++ b/projects/nae-example-app/src/app/doc/demo-title-config/content/3/demo-title-config-content3-case-view.component.ts @@ -14,7 +14,7 @@ import { Filter, FilterType, NAE_BASE_FILTER, - AllowedNetsServiceFactory, SavedFilterMetadata, AllowedNetsService + AllowedNetsServiceFactory, AllowedNetsService } from '@netgrif/components-core'; import {HeaderComponent} from '@netgrif/components'; import {Subject} from 'rxjs'; @@ -85,21 +85,4 @@ export class DemoTitleConfigContent3CaseViewComponent extends AbstractTabbedCase super.initializeHeader(this.caseHeaderComponent); } - loadFilter(filterData: SavedFilterMetadata) { - this._injectedTabData.tabViewRef.openTab({ - label: { - text: filterData.filter.title - }, - canBeClosed: true, - tabContentComponent: DemoTitleConfigContent3CaseViewComponent, - injectedObject: {...this._injectedTabData, loadFilter: filterData.filter}, - order: this._injectedTabData.tabViewOrder, - parentUniqueId: this._injectedTabData.tabUniqueId - }, this._autoswitchToTaskTab, this._openExistingTab); - } - - saveFilter(filterData: SavedFilterMetadata) { - console.log(filterData); - } - } diff --git a/projects/nae-example-app/src/app/doc/single-tabbed-view/single-tabbed-case-view/single-tabbed-case-view.component.html b/projects/nae-example-app/src/app/doc/single-tabbed-view/single-tabbed-case-view/single-tabbed-case-view.component.html index bd82ac967c..892eb43ef8 100644 --- a/projects/nae-example-app/src/app/doc/single-tabbed-view/single-tabbed-case-view/single-tabbed-case-view.component.html +++ b/projects/nae-example-app/src/app/doc/single-tabbed-view/single-tabbed-case-view/single-tabbed-case-view.component.html @@ -3,8 +3,7 @@
- +
diff --git a/projects/nae-example-app/src/app/doc/single-tabbed-view/single-tabbed-case-view/single-tabbed-case-view.component.ts b/projects/nae-example-app/src/app/doc/single-tabbed-view/single-tabbed-case-view/single-tabbed-case-view.component.ts index 41adca99bb..6c0932b985 100644 --- a/projects/nae-example-app/src/app/doc/single-tabbed-view/single-tabbed-case-view/single-tabbed-case-view.component.ts +++ b/projects/nae-example-app/src/app/doc/single-tabbed-view/single-tabbed-case-view/single-tabbed-case-view.component.ts @@ -7,7 +7,6 @@ import { LoggerService, NAE_TAB_DATA, OverflowService, - SavedFilterMetadata, SearchService, ViewIdService } from '@netgrif/components-core'; @@ -43,21 +42,4 @@ export class SingleTabbedCaseViewComponent extends AbstractTabbedCaseViewCompone super.initializeHeader(this.caseHeaderComponent); } - loadFilter(filterData: SavedFilterMetadata) { - this._injectedTabData.tabViewRef.openTab({ - label: { - text: filterData.filter.title - }, - canBeClosed: true, - tabContentComponent: SingleTabbedCaseViewComponent, - injectedObject: {...this._injectedTabData, loadFilter: filterData.filter}, - order: this._injectedTabData.tabViewOrder, - parentUniqueId: this._injectedTabData.tabUniqueId - }, this._autoswitchToTaskTab, this._openExistingTab); - } - - saveFilter(filterData: SavedFilterMetadata) { - console.log(filterData); - } - } diff --git a/projects/nae-example-app/src/app/doc/tabbed-case-view/tabbed-case-view/tabbed-case-view.component.html b/projects/nae-example-app/src/app/doc/tabbed-case-view/tabbed-case-view/tabbed-case-view.component.html index 7aae5cfb58..fd20ec2d0e 100644 --- a/projects/nae-example-app/src/app/doc/tabbed-case-view/tabbed-case-view/tabbed-case-view.component.html +++ b/projects/nae-example-app/src/app/doc/tabbed-case-view/tabbed-case-view/tabbed-case-view.component.html @@ -5,8 +5,7 @@
- +
; public initialized: boolean; @@ -17,8 +20,18 @@ export abstract class AbstractImmediateFilterTextComponent implements OnInit { } ngOnInit(): void { + let filterType: FilterType; + if (this.type === 'case') { + filterType = FilterType.CASE; + } else if (this.type === 'task') { + filterType = FilterType.TASK; + } const providers: Array = [ - {provide: NAE_FILTER_TEXT, useValue: {ellipsis: this.ellipsis}} + {provide: NAE_FILTER_TEXT, useValue: { + ellipsis: this.ellipsis, + query: this.query, + type: filterType + }} ]; const injector = Injector.create({providers, parent: this._parenInjector}); this.portal = new ComponentPortal(this.getFilterTextContentComponent(), null, injector); diff --git a/projects/netgrif-components-core/src/lib/panel/immediate/model/filter-text-injection-token.ts b/projects/netgrif-components-core/src/lib/panel/immediate/model/filter-text-injection-token.ts index 1afb847370..ccc9d4af5d 100644 --- a/projects/netgrif-components-core/src/lib/panel/immediate/model/filter-text-injection-token.ts +++ b/projects/netgrif-components-core/src/lib/panel/immediate/model/filter-text-injection-token.ts @@ -1,7 +1,9 @@ import {InjectionToken} from '@angular/core'; +import {FilterType} from "../../../filter/models/filter-type"; export interface FilterTextConfiguration { query: string; + type: FilterType; ellipsis: boolean; } diff --git a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts index 1b823cef07..f06364b278 100644 --- a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts +++ b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts @@ -638,8 +638,6 @@ export class PfqlVisitor extends QueryLangVisitor> { return [expr]; }; - // todo 2466 implement handler dispatcher? - /** * Handles a string comparison context and creates a simple expression with the appropriate operator and value. * diff --git a/projects/netgrif-components-core/src/lib/search/header-search-service/header-search.service.ts b/projects/netgrif-components-core/src/lib/search/header-search-service/header-search.service.ts index b26d552a74..dac4dfa3eb 100644 --- a/projects/netgrif-components-core/src/lib/search/header-search-service/header-search.service.ts +++ b/projects/netgrif-components-core/src/lib/search/header-search-service/header-search.service.ts @@ -21,6 +21,7 @@ import {CaseSimpleDataset} from '../models/category/case/case-simple-dataset'; import {TranslateService} from '@ngx-translate/core'; import {LoggerService} from '../../logger/services/logger.service'; import {Subscription} from 'rxjs'; +import {CaseProcess} from "../models/category/case/case-process"; /** * Holds the Id of the predicate in the {@link SearchService} @@ -75,7 +76,8 @@ export class HeaderSearchService implements OnDestroy { {k: CaseMetaField.TITLE, v: CaseTitle}, {k: CaseMetaField.CREATION_DATE, v: CaseCreationDate}, {k: CaseMetaField.AUTHOR, v: CaseAuthor}, - {k: CaseMetaField.MONGO_ID, v: CaseStringId} + {k: CaseMetaField.MONGO_ID, v: CaseStringId}, + {k: CaseMetaField.PROCESS_IDENTIFIER, v: CaseProcess}, ].forEach(pair => { this._typeToCategory.set(pair.k, this._categoryFactory.getWithDefaultOperator(pair.v)); }); diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts index d96e9dd20f..444add70df 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts @@ -13,6 +13,7 @@ import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; import {take, filter} from "rxjs/operators"; import {SimpleExpression} from "../../../../pfql/model/simple-expression"; import {SearchInputType} from "../search-input-type"; +import {Substring} from "../../operator/substring"; export class CaseProcess extends NoConfigurationAutocompleteCategory { @@ -24,7 +25,7 @@ export class CaseProcess extends NoConfigurationAutocompleteCategory { constructor(operators: OperatorService, logger: LoggerService, protected _optionalDependencies: OptionalDependencies) { super([CaseSearch.PROCESS_IDENTIFIER], - [operators.getOperator(Equals), operators.getOperator(NotEquals)], + [operators.getOperator(Substring), operators.getOperator(Equals), operators.getOperator(NotEquals)], `${CaseProcess._i18n}.name`, logger, operators, diff --git a/projects/netgrif-components-core/src/lib/search/models/category/plain-query-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/plain-query-category.ts index 1c1ff30bbf..4a00372564 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/plain-query-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/plain-query-category.ts @@ -11,7 +11,7 @@ import {ResourceTypeQueryPrefix} from "./resource-type-query-prefix"; import {RawExpression} from "../../../pfql/model/raw-expression"; export abstract class PlainQueryCategory extends Category { - private static readonly _title = 'search.category.plainText'; // todo 2466 add translation + private static readonly _title = 'search.category.plainText'; protected _configurationInput: ConfigurationInput; @@ -19,7 +19,7 @@ export abstract class PlainQueryCategory extends Category { super([], [], `${PlainQueryCategory._title}.name`, SearchInputType.PLAIN_QUERY, logger, operators, resourceType); this._configurationInput = new ConfigurationInput( SearchInputType.PLAIN_QUERY, - 'search.category.plainText.name', + `${PlainQueryCategory._title}.name`, false, new Map>(), () => { diff --git a/projects/netgrif-components-core/src/lib/search/models/search-index.ts b/projects/netgrif-components-core/src/lib/search/models/search-index.ts index 27c9384217..5c204be2b7 100644 --- a/projects/netgrif-components-core/src/lib/search/models/search-index.ts +++ b/projects/netgrif-components-core/src/lib/search/models/search-index.ts @@ -1,5 +1,4 @@ export enum SearchIndex { - // todo 2466 later remove? /** * Indexed as TEXT * diff --git a/projects/netgrif-components-core/src/lib/search/search-keyword-resolver-service/search-index-resolver.service.ts b/projects/netgrif-components-core/src/lib/search/search-keyword-resolver-service/search-index-resolver.service.ts index d6911b2802..141abf53dc 100644 --- a/projects/netgrif-components-core/src/lib/search/search-keyword-resolver-service/search-index-resolver.service.ts +++ b/projects/netgrif-components-core/src/lib/search/search-keyword-resolver-service/search-index-resolver.service.ts @@ -15,8 +15,6 @@ import {SearchIndex} from '../models/search-index'; }) export class SearchIndexResolverService { - // todo 2466 needed? - public readonly KEYWORD = '.keyword'; constructor() { } diff --git a/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/refs/default-case-ref-list-view/default-case-ref-list-view.component.html b/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/refs/default-case-ref-list-view/default-case-ref-list-view.component.html index 72bbc7c7bd..66da0333e5 100644 --- a/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/refs/default-case-ref-list-view/default-case-ref-list-view.component.html +++ b/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/refs/default-case-ref-list-view/default-case-ref-list-view.component.html @@ -3,7 +3,7 @@
- +
diff --git a/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/refs/default-case-ref-list-view/default-case-ref-list-view.component.ts b/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/refs/default-case-ref-list-view/default-case-ref-list-view.component.ts index 28babc1347..f0297c4ebe 100644 --- a/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/refs/default-case-ref-list-view/default-case-ref-list-view.component.ts +++ b/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/refs/default-case-ref-list-view/default-case-ref-list-view.component.ts @@ -14,7 +14,6 @@ import { EnumerationField, Filter, FilterType, - MergeOperator, MultichoiceField, NAE_BASE_FILTER, NAE_CASE_REF_CREATE_CASE, @@ -23,7 +22,6 @@ import { NAE_TAB_DATA, NAE_VIEW_ID_SEGMENT, OverflowService, - SavedFilterMetadata, SearchMode, SearchService, SimpleFilter, @@ -141,8 +139,4 @@ export class DefaultCaseRefListViewComponent extends AbstractCaseViewComponent i createdCase(caze: Case) { this.handleCaseClick(caze); } - - loadFilter(filterData: SavedFilterMetadata) { - this.searchService.updateWithFullFilter(this.initFilter.merge(filterData.filter, MergeOperator.AND)); - } } diff --git a/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/tabbed/default-tabbed-case-view/default-tabbed-case-view.component.html b/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/tabbed/default-tabbed-case-view/default-tabbed-case-view.component.html index c4d15b61d4..2ebc12c0c2 100644 --- a/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/tabbed/default-tabbed-case-view/default-tabbed-case-view.component.html +++ b/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/tabbed/default-tabbed-case-view/default-tabbed-case-view.component.html @@ -5,7 +5,7 @@
+ [initialSearchMode]="initialSearchMode">
- + + From 5ba60548d1c31012ae2158dc471f3c7a5d5e8ce9 Mon Sep 17 00:00:00 2001 From: chvostek Date: Mon, 31 Aug 2026 15:57:25 +0200 Subject: [PATCH 41/55] [NAE-2466] Advanced search for PFQL - fix tests --- ...act-filter-field-content.component.spec.ts | 14 +- ...r-field-tab-view-content.component.spec.ts | 12 +- ...ct-filter-field-tab-view.component.spec.ts | 6 +- ...bstract-filter-field-tab-view.component.ts | 5 +- .../abstract-filter-field.component.spec.ts | 12 +- ...act-filter-default-field.component.spec.ts | 11 +- .../filter-field/models/filter-field.spec.ts | 6 +- ...ct-immediate-filter-text.component.spec.ts | 3 +- .../src/lib/pfql/pfql-utils.ts | 1 - .../src/lib/pfql/pfql-visitor.ts | 2 - .../default-categories-factories.spec.ts | 4 +- .../models/category/case/case-author.spec.ts | 84 ++++--- .../case/case-creation-date-time.spec.ts | 42 +--- .../category/case/case-creation-date.spec.ts | 48 ++-- .../models/category/case/case-dataset.spec.ts | 211 +++--------------- .../models/category/case/case-process.spec.ts | 53 +---- .../models/category/case/case-process.ts | 25 +-- .../category/case/case-string-id.spec.ts | 38 +--- .../models/category/case/case-title.spec.ts | 38 +--- ...onfiguration-user-autocomplete-category.ts | 22 +- .../category/task/task-assignee.spec.ts | 86 ++++--- .../models/category/task/task-process.spec.ts | 56 ++--- .../models/category/task/task-process.ts | 34 ++- .../models/category/task/task-task.spec.ts | 57 ++--- .../search/models/category/task/task-task.ts | 37 ++- .../src/lib/search/models/operator/like.ts | 2 +- .../lib/search/models/operator/operator.ts | 2 - .../search-service/search.service.spec.ts | 120 +++++----- .../search-category-mock-dependencies.ts | 11 +- .../case-ref-default.component.spec.ts | 9 +- ...numeration-caseref-field.component.spec.ts | 10 +- .../filter-default-field.component.spec.ts | 6 +- .../filter-field-content.component.spec.ts | 13 +- .../filter-field.component.spec.ts | 7 +- ...ilter-string-query-field.component.spec.ts | 6 +- ...r-field-tab-view-content.component.spec.ts | 6 +- ...ultichoice-caseref-field.component.spec.ts | 8 +- .../filter-field-tab-view.component.spec.ts | 6 +- ...fault-case-ref-list-view.component.spec.ts | 9 +- ...default-simple-case-view.component.spec.ts | 8 +- ...default-simple-task-view.component.spec.ts | 8 +- ...default-single-task-view.component.spec.ts | 10 +- .../default-tab-view.component.spec.ts | 14 +- ...default-tabbed-case-view.component.spec.ts | 8 +- ...iate-filter-text-content.component.spec.ts | 3 +- .../immediate-filter-text.component.spec.ts | 16 +- 46 files changed, 425 insertions(+), 764 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-content.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-content.component.spec.ts index c37e8b9db5..e466cacb50 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-content.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-content.component.spec.ts @@ -4,10 +4,10 @@ import {FilterField} from './models/filter-field'; import {SearchService} from '../../search/search-service/search.service'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {NAE_FILTER_FIELD} from './models/filter-field-injection-token'; -import {FilterType} from '../../filter/models/filter-type'; import {Subject} from 'rxjs'; import {NoopAnimationsModule} from '@angular/platform-browser/animations'; import {HttpClientTestingModule} from '@angular/common/http/testing'; +import {FieldTypeResource} from "../../task-content/model/field-type-resource"; describe('AbstractFilterFieldContentComponent', () => { let component: TestFilterContentComponent; @@ -17,13 +17,11 @@ describe('AbstractFilterFieldContentComponent', () => { let mockSearchService; beforeEach(() => { - field = new FilterField('', '', '', { - filterType: FilterType.CASE, predicateMetadata: [], searchCategories: [] - }, [], {}, '', ''); + field = new FilterField('', '', '', FieldTypeResource.CASE_FILTER, [], {}, '', ''); mockSearchService = { - loadFromMetadata: () => {}, - loadingFromMetadata$: new Subject() + loadFromPfql: () => {}, + loadingFromPfql$: new Subject() }; TestBed.configureTestingModule({ @@ -42,7 +40,7 @@ describe('AbstractFilterFieldContentComponent', () => { }); afterEach(() => { - mockSearchService.loadingFromMetadata$.complete(); + mockSearchService.loadingFromPfql$.complete(); TestBed.resetTestingModule(); }); @@ -53,7 +51,7 @@ describe('AbstractFilterFieldContentComponent', () => { it('should finish loading', () => { expect(component).toBeTruthy(); expect(component.filterLoaded).toBeFalse(); - mockSearchService.loadingFromMetadata$.next(false); + mockSearchService.loadingFromPfql$.next(false); expect(component.filterLoaded).toBeTrue(); }); diff --git a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view-content.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view-content.component.spec.ts index 01989c2c6b..e3467d2436 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view-content.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view-content.component.spec.ts @@ -2,7 +2,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { AbstractFilterFieldTabViewContentComponent } from './abstract-filter-field-tab-view-content.component'; import { Component, Inject, Injector } from '@angular/core'; import { FilterField } from './models/filter-field'; -import { FilterType } from '../../filter/models/filter-type'; import { NAE_FILTER_FIELD } from './models/filter-field-injection-token'; import { SearchService } from '../../search/search-service/search.service'; import { Subject } from 'rxjs'; @@ -11,6 +10,7 @@ import { HttpClientTestingModule } from '@angular/common/http/testing'; import { Dashboard } from '../text-field/dashboard-portal-text-field/dashboard-view-constants'; import { ComponentPortal } from '@angular/cdk/portal'; import {ComponentRegistryService} from "../../registry/component-registry.service"; +import {FieldTypeResource} from "../../task-content/model/field-type-resource"; describe('AbstractFilterFieldTabViewContentComponent', () => { let component: TestFilterFieldTabViewContentComponent; @@ -22,13 +22,11 @@ describe('AbstractFilterFieldTabViewContentComponent', () => { let registry: ComponentRegistryService; beforeEach(async () => { - field = new FilterField('', '', '', { - filterType: FilterType.CASE, predicateMetadata: [], searchCategories: [] - }, [], {}, '', ''); + field = new FilterField('', '', '', FieldTypeResource.CASE_FILTER, [], {}, '', ''); mockSearchService = { - loadFromMetadata: () => {}, - loadingFromMetadata$: new Subject() + loadFromPfql: () => {}, + loadingFromPfql$: new Subject() }; await TestBed.configureTestingModule({ @@ -51,7 +49,7 @@ describe('AbstractFilterFieldTabViewContentComponent', () => { }); afterEach(() => { - mockSearchService.loadingFromMetadata$.complete(); + mockSearchService.loadingFromPfql$.complete(); TestBed.resetTestingModule(); }); diff --git a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view.component.spec.ts index 341e44ec7f..c5e0da29ce 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view.component.spec.ts @@ -2,12 +2,12 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { AbstractFilterFieldTabViewComponent } from './abstract-filter-field-tab-view.component'; import { FilterField } from './models/filter-field'; -import { FilterType } from '../../filter/models/filter-type'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { NAE_FILTER_FIELD } from './models/filter-field-injection-token'; import { Component, Inject } from '@angular/core'; import {ComponentRegistryService} from "../../registry/component-registry.service"; +import {FieldTypeResource} from "../../task-content/model/field-type-resource"; describe('AbstractFilterFieldTabViewComponent', () => { let component: TestFilterFieldTabViewComponent; let fixture: ComponentFixture; @@ -15,9 +15,7 @@ describe('AbstractFilterFieldTabViewComponent', () => { let field: FilterField; beforeEach(async () => { - field = new FilterField('', '', '', { - filterType: FilterType.CASE, predicateMetadata: [], searchCategories: [] - }, [], {}, '', ''); + field = new FilterField('', '', '', FieldTypeResource.CASE_FILTER, [], {}, '', ''); await TestBed.configureTestingModule({ imports: [NoopAnimationsModule, HttpClientTestingModule], diff --git a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view.component.ts b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view.component.ts index cf427e4b9e..c1081ed403 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view.component.ts @@ -21,9 +21,8 @@ export abstract class AbstractFilterFieldTabViewComponent { this.tabs = [ { label: { - // todo 2466 dynamic label - text: /*this._filterField.filterMetadata[Dashboard.FILTER_TAB_VIEW_TITLE_KEY] ??*/ this._filterField.title, - icon: /*this._filterField.filterMetadata[Dashboard.FILTER_TAB_VIEW_ICON_KEY] ??*/ 'home' + text: this._filterField.title, + icon: 'home' }, canBeClosed: false, tabContentComponent: this.tabContentComponent(), diff --git a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field.component.spec.ts index 5e6f31e97e..6e62b792d2 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field.component.spec.ts @@ -3,10 +3,10 @@ import {ComponentFixture, TestBed} from '@angular/core/testing'; import {Component, Inject, Optional} from '@angular/core'; import {NAE_INFORM_ABOUT_INVALID_DATA} from '../models/invalid-data-policy-token'; import {FilterField} from './models/filter-field'; -import {FilterType} from '../../filter/models/filter-type'; -import {of, Subject} from 'rxjs'; +import {Subject} from 'rxjs'; import {NoopAnimationsModule} from '@angular/platform-browser/animations'; import {HttpClientTestingModule} from '@angular/common/http/testing'; +import {FieldTypeResource} from "../../task-content/model/field-type-resource"; describe('AbstractFilterFieldComponent', () => { let component: TestFilterComponent; @@ -16,8 +16,8 @@ describe('AbstractFilterFieldComponent', () => { beforeEach(() => { mockSearchService = { - loadFromMetadata: () => {}, - loadingFromMetadata$: new Subject() + loadFromPfql: () => {}, + loadingFromPfql$: new Subject() }; TestBed.configureTestingModule({ @@ -57,7 +57,5 @@ class TestFilterComponent extends AbstractFilterFieldComponent { template: '' }) class TestWrapperComponent { - field = new FilterField('', '', '', { - filterType: FilterType.CASE, predicateMetadata: [], searchCategories: [] - }, [], {}, '', ''); + field = new FilterField('', '', '', FieldTypeResource.CASE_FILTER, [], {}, '', ''); } diff --git a/projects/netgrif-components-core/src/lib/data-fields/filter-field/filter-default-field/abstract-filter-default-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/filter-field/filter-default-field/abstract-filter-default-field.component.spec.ts index 9caf542c59..a2672fc230 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/filter-field/filter-default-field/abstract-filter-default-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/filter-field/filter-default-field/abstract-filter-default-field.component.spec.ts @@ -2,17 +2,16 @@ import {ComponentFixture, TestBed} from "@angular/core/testing"; import {of, Subject} from "rxjs"; import {NoopAnimationsModule} from "@angular/platform-browser/animations"; import {HttpClientTestingModule} from "@angular/common/http/testing"; -import {BrowserDynamicTestingModule} from "@angular/platform-browser-dynamic/testing"; import {Component, Inject, Injector, Optional} from "@angular/core"; import {ComponentType} from "@angular/cdk/portal"; import {AbstractFilterFieldContentComponent} from "../abstract-filter-field-content.component"; import {FilterField} from "../models/filter-field"; -import {FilterType} from "../../../filter/models/filter-type"; import {SearchService} from "../../../search/search-service/search.service"; import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../../models/data-field-portal-data-injection-token"; import {AbstractFilterDefaultFieldComponent} from "./abstract-filter-default-field.component"; import {FormControl} from "@angular/forms"; import {WrappedBoolean} from "../../data-field-template/models/wrapped-boolean"; +import {FieldTypeResource} from "../../../task-content/model/field-type-resource"; describe('AbstractFilterDefaultFieldComponent', () => { let component: TestFilterComponent; @@ -22,17 +21,15 @@ describe('AbstractFilterDefaultFieldComponent', () => { beforeEach(() => { mockSearchService = { - loadFromMetadata: () => {}, - loadingFromMetadata$: new Subject() + loadFromPfql: () => {}, + loadingFromPfql$: new Subject() }; TestBed.configureTestingModule({ imports: [NoopAnimationsModule, HttpClientTestingModule], providers: [ {provide: DATA_FIELD_PORTAL_DATA, useValue: { - dataField: new FilterField('', '', '', { - filterType: FilterType.CASE, predicateMetadata: [], searchCategories: [] - }, [], {}, '', ''), + dataField: new FilterField('', '', '', FieldTypeResource.CASE_FILTER, [], {}, '', ''), formControlRef: new FormControl(), showLargeLayout: new WrappedBoolean() } as DataFieldPortalData diff --git a/projects/netgrif-components-core/src/lib/data-fields/filter-field/models/filter-field.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/filter-field/models/filter-field.spec.ts index 512970e105..014094ea7b 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/filter-field/models/filter-field.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/filter-field/models/filter-field.spec.ts @@ -1,12 +1,10 @@ import {FilterField} from './filter-field'; -import {FilterType} from '../../../filter/models/filter-type'; import {TestBed} from '@angular/core/testing'; +import {FieldTypeResource} from "../../../task-content/model/field-type-resource"; describe('FilterField', () => { it('should create an instance', () => { - expect(new FilterField('', '', '', { - filterType: FilterType.CASE, predicateMetadata: [], searchCategories: [] - }, [], {}, '', '')).toBeTruthy(); + expect(new FilterField('', '', '', FieldTypeResource.CASE_FILTER, [], {}, '', '')).toBeTruthy(); }); afterEach(() => { diff --git a/projects/netgrif-components-core/src/lib/panel/immediate/abstract-immediate-filter-text.component.spec.ts b/projects/netgrif-components-core/src/lib/panel/immediate/abstract-immediate-filter-text.component.spec.ts index 7fb7f26bc5..8566a3cc2a 100644 --- a/projects/netgrif-components-core/src/lib/panel/immediate/abstract-immediate-filter-text.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/panel/immediate/abstract-immediate-filter-text.component.spec.ts @@ -46,7 +46,8 @@ class TestImmediateFilterTextComponent extends AbstractImmediateFilterTextCompon constructor(parenInjector: Injector) { super(parenInjector); this.ellipsis = true; - this.filterMetadata = {allowedNets: [], filterMetadata: {filterType: FilterType.CASE, predicateMetadata: [], searchCategories: []}}; + this.query = 'cases: title eq \'awd\''; + this.type = 'case'; } protected getFilterTextContentComponent(): ComponentType { diff --git a/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts b/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts index a0d211e5c4..848280abbb 100644 --- a/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts +++ b/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts @@ -36,7 +36,6 @@ import {LoggerService} from "../logger/services/logger.service"; * @returns An array of QueryItem objects representing the parsed query structure */ export function parseQuery(query: string, injector: Injector): Array { - // todo 2466 injector as parameter? const logger = injector.get(LoggerService); try { const inputStream = CharStream.fromString(query); diff --git a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts index f06364b278..52768c916c 100644 --- a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts +++ b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts @@ -561,8 +561,6 @@ export class PfqlVisitor extends QueryLangVisitor> { return [dataExpr]; }; - // todo 2466 user field comparison ? ... ak je v string comparison mongo id, tak je to mozno user id? - /** * Visits a basic process identifier comparison and creates a case process search expression. * diff --git a/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.spec.ts b/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.spec.ts index 27ff0c0be3..0b9fd6818c 100644 --- a/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/category-factory/default-categories-factories.spec.ts @@ -55,7 +55,7 @@ describe('Default search categories factory methods', () => { expect(testService).toBeTruthy(); expect(testService.searchCategories).toBeTruthy(); expect(Array.isArray(testService.searchCategories)).toBeTrue(); - expect(testService.searchCategories.length).toBe(7); + expect(testService.searchCategories.length).toBe(8); for (const category of testService.searchCategories) { expect(category).toBeTruthy(); } @@ -93,7 +93,7 @@ describe('Default search categories factory methods', () => { expect(testService).toBeTruthy(); expect(testService.searchCategories).toBeTruthy(); expect(Array.isArray(testService.searchCategories)).toBeTrue(); - expect(testService.searchCategories.length).toBe(3); + expect(testService.searchCategories.length).toBe(4); for (const category of testService.searchCategories) { expect(category).toBeTruthy(); } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-author.spec.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-author.spec.ts index 3b1762c962..620f3c5144 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-author.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-author.spec.ts @@ -2,20 +2,27 @@ import {CaseAuthor} from './case-author'; import {OperatorService} from '../../../operator-service/operator.service'; import {OperatorResolverService} from '../../../operator-service/operator-resolver.service'; import {Equals} from '../../operator/equals'; -import {Categories} from '../categories'; -import {Operators} from '../../operator/operators'; import {configureCategory} from '../../../../utility/tests/utility/configure-category'; import {createMockDependencies} from '../../../../utility/tests/search-category-mock-dependencies'; import {mockUserAutocompleteValue} from '../../../../utility/tests/mocks/mock-user-autocomplete-value'; import {TestBed} from '@angular/core/testing'; +import {SimpleExpression} from "../../../../pfql/model/simple-expression"; +import {Observable, of} from "rxjs"; +import {Page} from "../../../../resources/interface/page"; +import {UserResource} from "../../../../resources/interface/user-resource"; +import {createMockPage} from "../../../../utility/tests/utility/create-mock-page"; +import {UserResourceService} from "../../../../resources/engine-endpoint/user-resource.service"; describe('CaseAuthor', () => { let category: CaseAuthor; let operatorService: OperatorService; + let userResourceService: MockUserResourceService; beforeEach(() => { operatorService = new OperatorService(new OperatorResolverService()); - category = new CaseAuthor(operatorService, null, createMockDependencies(undefined, operatorService)); + userResourceService = new MockUserResourceService(); + category = new CaseAuthor(operatorService, null, createMockDependencies(undefined, operatorService, + userResourceService as unknown as UserResourceService)); }); afterEach(() => { @@ -33,42 +40,57 @@ describe('CaseAuthor', () => { expect(category.isOperatorSelected()).toBeTrue(); }); - it('should not serialize incomplete instance', () => { - expect(category.createMetadata()).toBeUndefined(); - }); - - it('should serialize complete instance', () => { + it('should load pfql expression', (done) => { configureCategory(category, operatorService, Equals, [mockUserAutocompleteValue('Test User', true, 'userId')]); - const mockedSerializedValue = mockUserAutocompleteValue('Test User', true, 'userId'); - delete mockedSerializedValue.icon; + const loadedCategory = new CaseAuthor(operatorService, null, createMockDependencies(undefined, + operatorService, userResourceService as unknown as UserResourceService)); + const expression = new SimpleExpression(new Equals(), mockUserAutocompleteValue('Test User', true, 'userId'), category); + loadedCategory.loadFromPfqlExpression(expression).subscribe(() => { + expect(loadedCategory.isOperatorSelected()).toBeTrue(); + expect(loadedCategory.providesPredicate).toBeTrue(); + + expect((loadedCategory as any)._operandsFormControls[0].value).toEqual((category as any)._operandsFormControls[0].value); - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - expect(metadata.values).toEqual([mockedSerializedValue]); - expect(metadata.category).toBe(Categories.CASE_AUTHOR); - expect(metadata.configuration?.operator).toBe(Operators.EQUALS); + done(); + }); }); - it('should deserialize stored instance', (done) => { + it('should generate pfql query', () => { configureCategory(category, operatorService, Equals, [mockUserAutocompleteValue('Test User', true, 'userId')]); + const predicate = category.generatePredicate([['userId']]); + expect(predicate.query.value).toEqual(`cases: author eq 'userId'`); + }); +}); - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - const deserialized = new CaseAuthor(operatorService, null, createMockDependencies(undefined, operatorService)); - deserialized.loadFromMetadata(metadata).subscribe(() => { - expect(deserialized.isOperatorSelected()).toBeTrue(); - expect(deserialized.providesPredicate).toBeTrue(); - expect((deserialized as any)._operandsFormControls[0].value).toEqual((category as any)._operandsFormControls[0].value); +class MockUserResourceService { - const deserializedMetadata = deserialized.createMetadata(); - expect(deserializedMetadata).toBeTruthy(); - expect(deserializedMetadata.configuration).toEqual(metadata.configuration); - expect(deserializedMetadata.category).toEqual(metadata.category); - expect(deserializedMetadata.values).toEqual(metadata.values); + public search(): Observable> { + return of(createMockPage([{ + name: 'Test', + surname: 'User', + id: 'userId', + email: 'Test User', + fullName: `Test User`, + groups: [], + authorities: [], + nextGroups: [], + processRoles: [] + }])); + } - done(); + public getUser(userId: string): Observable { + return of({ + name: 'Test', + surname: 'User', + id: 'userId', + email: 'Test User', + fullName: `Test User`, + groups: [], + authorities: [], + nextGroups: [], + processRoles: [] }); - }); -}); + } +} diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date-time.spec.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date-time.spec.ts index 71edbeac53..c9a1bd1a3d 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date-time.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date-time.spec.ts @@ -1,13 +1,12 @@ import {OperatorService} from '../../../operator-service/operator.service'; import {OperatorResolverService} from '../../../operator-service/operator-resolver.service'; import {configureCategory} from '../../../../utility/tests/utility/configure-category'; -import {Categories} from '../categories'; -import {Operators} from '../../operator/operators'; import moment from 'moment'; import {CaseCreationDateTime} from './case-creation-date-time'; import {EqualsDateTime} from '../../operator/equals-date-time'; import {TestBed} from '@angular/core/testing'; import {InRangeDateTime} from "../../operator/in-range-date-time"; +import {SimpleExpression} from "../../../../pfql/model/simple-expression"; describe('CaseCreationDateTime', () => { let category: CaseCreationDateTime; @@ -33,42 +32,21 @@ describe('CaseCreationDateTime', () => { expect(category.isOperatorSelected()).toBeTrue(); }); - it('should not serialize incomplete instance', () => { - expect(category.createMetadata()).toBeUndefined(); - }); - - it('should serialize complete instance', () => { + it('should load pfql expression', (done) => { configureCategory(category, operatorService, EqualsDateTime, [moment('2021-08-18 15:28')]); - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - expect(metadata.values).toEqual([moment('2021-08-18 15:28').valueOf()]); - expect(metadata.category).toBe(Categories.CASE_CREATION_DATE_TIME); - expect(metadata.configuration?.operator).toBe(Operators.EQUALS_DATE_TIME); - }); - - it('should deserialize stored instance', (done) => { - configureCategory(category, operatorService, EqualsDateTime, [moment('2021-08-18 15:28')]); - - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - const deserialized = new CaseCreationDateTime(operatorService, null); - deserialized.loadFromMetadata(metadata).subscribe(() => { - expect(deserialized.isOperatorSelected()).toBeTrue(); - expect(deserialized.providesPredicate).toBeTrue(); + const loadedCategory = new CaseCreationDateTime(operatorService, null); + const expression = new SimpleExpression(new EqualsDateTime(operatorService), moment('2021-08-18 15:28'), category); + loadedCategory.loadFromPfqlExpression(expression).subscribe(() => { + expect(loadedCategory.isOperatorSelected()).toBeTrue(); + expect(loadedCategory.providesPredicate).toBeTrue(); const originalMoment = (category as any)._operandsFormControls[0].value; - const deserializedMoment = (deserialized as any)._operandsFormControls[0].value; + const loadedMoment = (loadedCategory as any)._operandsFormControls[0].value; expect(moment.isMoment(originalMoment)).toBeTrue(); - expect(moment.isMoment(deserializedMoment)).toBeTrue(); - expect(deserializedMoment.isSame(originalMoment)).toBeTrue(); - - const deserializedMetadata = deserialized.createMetadata(); - expect(deserializedMetadata).toBeTruthy(); - expect(deserializedMetadata.configuration).toEqual(metadata.configuration); - expect(deserializedMetadata.category).toEqual(metadata.category); - expect(deserializedMetadata.values).toEqual(metadata.values); + expect(moment.isMoment(loadedMoment)).toBeTrue(); + expect(loadedMoment.isSame(originalMoment)).toBeTrue(); done(); }); diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date.spec.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date.spec.ts index a764eb4f36..bdcd525ab5 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-creation-date.spec.ts @@ -2,11 +2,10 @@ import {CaseCreationDate} from './case-creation-date'; import {OperatorService} from '../../../operator-service/operator.service'; import {OperatorResolverService} from '../../../operator-service/operator-resolver.service'; import {configureCategory} from '../../../../utility/tests/utility/configure-category'; -import {Categories} from '../categories'; -import {Operators} from '../../operator/operators'; import moment from 'moment'; import {EqualsDate} from '../../operator/equals-date'; import {TestBed} from '@angular/core/testing'; +import {SimpleExpression} from "../../../../pfql/model/simple-expression"; describe('CaseCreationDate', () => { let category: CaseCreationDate; @@ -32,44 +31,29 @@ describe('CaseCreationDate', () => { expect(category.isOperatorSelected()).toBeTrue(); }); - it('should not serialize incomplete instance', () => { - expect(category.createMetadata()).toBeUndefined(); - }); - - it('should serialize complete instance', () => { - configureCategory(category, operatorService, EqualsDate, [moment('2021-03-23')]); - - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - expect(metadata.values).toEqual([moment('2021-03-23').valueOf()]); - expect(metadata.category).toBe(Categories.CASE_CREATION_DATE); - expect(metadata.configuration?.operator).toBe(Operators.EQUALS_DATE); - }); - - it('should deserialize stored instance', (done) => { + it('should load pfql expression', (done) => { configureCategory(category, operatorService, EqualsDate, [moment('2021-03-23')]); - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - const deserialized = new CaseCreationDate(operatorService, null); - deserialized.loadFromMetadata(metadata).subscribe(() => { - expect(deserialized.isOperatorSelected()).toBeTrue(); - expect(deserialized.providesPredicate).toBeTrue(); + const loadedCategory = new CaseCreationDate(operatorService, null); + const expression = new SimpleExpression(new EqualsDate(operatorService), moment('2021-03-23'), category); + loadedCategory.loadFromPfqlExpression(expression).subscribe(() => { + expect(loadedCategory.isOperatorSelected()).toBeTrue(); + expect(loadedCategory.providesPredicate).toBeTrue(); const originalMoment = (category as any)._operandsFormControls[0].value; - const deserializedMoment = (deserialized as any)._operandsFormControls[0].value; + const loadedMoment = (loadedCategory as any)._operandsFormControls[0].value; expect(moment.isMoment(originalMoment)).toBeTrue(); - expect(moment.isMoment(deserializedMoment)).toBeTrue(); - expect(deserializedMoment.isSame(originalMoment)).toBeTrue(); - - const deserializedMetadata = deserialized.createMetadata(); - expect(deserializedMetadata).toBeTruthy(); - expect(deserializedMetadata.configuration).toEqual(metadata.configuration); - expect(deserializedMetadata.category).toEqual(metadata.category); - expect(deserializedMetadata.values).toEqual(metadata.values); + expect(moment.isMoment(loadedMoment)).toBeTrue(); + expect(loadedMoment.isSame(originalMoment)).toBeTrue(); done(); }); }); + + it('should generate pfql query', () => { + configureCategory(category, operatorService, EqualsDate, [moment('2021-03-23')]); + const predicate = category.generatePredicate([moment('2021-03-23')]); + expect(predicate.query.value).toEqual(`cases: creationDate in (2021-03-23 : 2021-03-24)`); + }); }); diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.spec.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.spec.ts index 69dc01d6d6..89da043d0f 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.spec.ts @@ -9,8 +9,6 @@ import {createMockNet} from '../../../../utility/tests/utility/create-mock-net'; import {filter, take} from 'rxjs/operators'; import {configureCategory} from '../../../../utility/tests/utility/configure-category'; import {Equals} from '../../operator/equals'; -import {Categories} from '../categories'; -import {CategoryGeneratorMetadata} from '../../persistance/generator-metadata'; import {Operator} from '../../operator/operator'; import {Type} from '@angular/core'; import {DatafieldMapKey} from '../../datafield-map-key'; @@ -18,6 +16,7 @@ import {SearchAutocompleteOption} from '../search-autocomplete-option'; import moment from 'moment'; import {EqualsDate} from '../../operator/equals-date'; import {EqualsDateTime} from '../../operator/equals-date-time'; +import {DataSimpleExpression} from "../../../../pfql/model/data-simple-expression"; describe('CaseDataset', () => { let operatorService: OperatorService; @@ -30,7 +29,7 @@ describe('CaseDataset', () => { beforeEach(waitForAsync(async () => { allowedNets$ = new ReplaySubject>(1); - category = await new CaseDataset(operatorService, null, createMockDependencies(allowedNets$, operatorService)); + category = new CaseDataset(operatorService, null, createMockDependencies(allowedNets$, operatorService)); })); afterEach(() => { @@ -66,12 +65,7 @@ describe('CaseDataset', () => { }); }); - it('should not serialize incomplete instance', () => { - allowedNets$.next([]); - expect(category.createMetadata()).toBeUndefined(); - }); - - describe('serialization / deserialization', () => { + describe('loading from pfql', () => { beforeEach(() => { const data = [ {stringId: 'textField', title: 'title', type: 'text'}, @@ -99,158 +93,70 @@ describe('CaseDataset', () => { TestBed.resetTestingModule(); }); - describe('should serialize', () => { + describe('should load from pfql', () => { it('text field search', (done) => { const v = 'value'; - serializationTest(done, category, Equals, 'text', v, (metadata) => { - expect(metadata.values).toEqual([v]); - }, operatorService); - }); - it('enumeration field search', (done) => { - const v = 'value'; - serializationTest(done, category, Equals, 'enumeration', v, (metadata) => { - expect(metadata.values).toEqual([v]); - }, operatorService); - }); - it('enumeration_map field search', (done) => { - const v = 'value'; - serializationTest(done, category, Equals, 'enumeration_map', v, (metadata) => { - expect(metadata.values).toEqual([v]); - }, operatorService); - }); - it('multichoice field search', (done) => { - const v = 'value'; - serializationTest(done, category, Equals, 'multichoice', v, (metadata) => { - expect(metadata.values).toEqual([v]); - }, operatorService); - }); - it('multichoice_map field search', (done) => { - const v = 'value'; - serializationTest(done, category, Equals, 'multichoice_map', v, (metadata) => { - expect(metadata.values).toEqual([v]); - }, operatorService); - }); - it('file field search', (done) => { - const v = 'value'; - serializationTest(done, category, Equals, 'file', v, (metadata) => { - expect(metadata.values).toEqual([v]); - }, operatorService); - }); - it('fileList field search', (done) => { - const v = 'value'; - serializationTest(done, category, Equals, 'fileList', v, (metadata) => { - expect(metadata.values).toEqual([v]); - }, operatorService); - }); - it('userList field search', (done) => { - const v = 'value'; - serializationTest(done, category, Equals, 'userList', v, (metadata) => { - expect(metadata.values).toEqual([v]); - }, operatorService); - }); - it('number field search', (done) => { - const v = 10; - serializationTest(done, category, Equals, 'number', v, (metadata) => { - expect(metadata.values).toEqual([v]); - }, operatorService); - }); - it('boolean field search', (done) => { - const v = true; - serializationTest(done, category, Equals, 'boolean', v, (metadata) => { - expect(metadata.values).toEqual([v]); - }, operatorService); - }); - it('user field search', (done) => { - const v = mockUserSearchValue('Test User', '7'); - serializationTest(done, category, Equals, 'user', v, (metadata) => { - const mockedSerializedValue = mockUserSearchValue('Test User', '7'); - delete mockedSerializedValue.icon; - expect(metadata.values).toEqual([mockedSerializedValue]); - }, operatorService); - }); - it('date field search', (done) => { - const v = moment('2021-03-26'); - serializationTest(done, category, EqualsDate, 'date', v, (metadata) => { - expect(metadata.values).toEqual([v.valueOf()]); - }, operatorService); - }); - it('dateTime field search', (done) => { - const v = moment('2021-03-26 12:37'); - serializationTest(done, category, EqualsDateTime, 'dateTime', v, (metadata) => { - expect(metadata.values).toEqual([v.valueOf()]); - }, operatorService); - }); - afterEach(() => { - allowedNets$.complete(); - category.destroy(); - TestBed.resetTestingModule(); - }); - }); - - describe('should deserialize', () => { - it('text field search', (done) => { - const v = 'value'; - deserializationTest(done, category, Equals, 'text', v, (d, c) => valueObjectsComparison(d, c), + loadFromPfqlTest(done, category, Equals, 'text', 'textField', v, (d, c) => valueObjectsComparison(d, c), operatorService, allowedNets$); }); it('enumeration field search', (done) => { const v = 'value'; - deserializationTest(done, category, Equals, 'enumeration', v, (d, c) => valueObjectsComparison(d, c), + loadFromPfqlTest(done, category, Equals, 'enumeration', 'enumerationField', v, (d, c) => valueObjectsComparison(d, c), operatorService, allowedNets$); }); it('enumeration_map field search', (done) => { const v = 'value'; - deserializationTest(done, category, Equals, 'enumeration_map', v, (d, c) => valueObjectsComparison(d, c), + loadFromPfqlTest(done, category, Equals, 'enumeration_map', 'enumeration_mapField', v, (d, c) => valueObjectsComparison(d, c), operatorService, allowedNets$); }); it('multichoice field search', (done) => { const v = 'value'; - deserializationTest(done, category, Equals, 'multichoice', v, (d, c) => valueObjectsComparison(d, c), + loadFromPfqlTest(done, category, Equals, 'multichoice', 'multichoiceField', v, (d, c) => valueObjectsComparison(d, c), operatorService, allowedNets$); }); it('multichoice_map field search', (done) => { const v = 'value'; - deserializationTest(done, category, Equals, 'multichoice_map', v, (d, c) => valueObjectsComparison(d, c), + loadFromPfqlTest(done, category, Equals, 'multichoice_map', 'multichoice_mapField', v, (d, c) => valueObjectsComparison(d, c), operatorService, allowedNets$); }); it('file field search', (done) => { const v = 'value'; - deserializationTest(done, category, Equals, 'file', v, (d, c) => valueObjectsComparison(d, c), + loadFromPfqlTest(done, category, Equals, 'file', 'fileField', v, (d, c) => valueObjectsComparison(d, c), operatorService, allowedNets$); }); it('fileList field search', (done) => { const v = 'value'; - deserializationTest(done, category, Equals, 'fileList', v, (d, c) => valueObjectsComparison(d, c), + loadFromPfqlTest(done, category, Equals, 'fileList', 'fileListField', v, (d, c) => valueObjectsComparison(d, c), operatorService, allowedNets$); }); it('userList field search', (done) => { const v = 'value'; - deserializationTest(done, category, Equals, 'userList', v, (d, c) => valueObjectsComparison(d, c), + loadFromPfqlTest(done, category, Equals, 'userList', 'userListField', v, (d, c) => valueObjectsComparison(d, c), operatorService, allowedNets$); }); it('number field search', (done) => { const v = 10; - deserializationTest(done, category, Equals, 'number', v, (d, c) => valueObjectsComparison(d, c), + loadFromPfqlTest(done, category, Equals, 'number', 'numberField', v, (d, c) => valueObjectsComparison(d, c), operatorService, allowedNets$); }); it('boolean field search', (done) => { const v = true; - deserializationTest(done, category, Equals, 'boolean', v, (d, c) => valueObjectsComparison(d, c), + loadFromPfqlTest(done, category, Equals, 'boolean', 'booleanField', v, (d, c) => valueObjectsComparison(d, c), operatorService, allowedNets$); }); it('user field search', (done) => { const v = mockUserSearchValue('Test User', '7'); - deserializationTest(done, category, Equals, 'user', v, (d, c) => valueObjectsComparison(d, c), + loadFromPfqlTest(done, category, Equals, 'user', 'userField', v, (d, c) => valueObjectsComparison(d, c), operatorService, allowedNets$); }); it('date field search', (done) => { const v = moment('2021-03-30'); - deserializationTest(done, category, EqualsDate, 'date', v, (d, c) => momentObjectsComparison(d, c), + loadFromPfqlTest(done, category, EqualsDate, 'date', 'dateField', v, (d, c) => momentObjectsComparison(d, c), operatorService, allowedNets$); }); it('dateTime field search', (done) => { const v = moment('2021-03-30 10:39'); - deserializationTest(done, category, EqualsDateTime, 'dateTime', v, (d, c) => momentObjectsComparison(d, c), + loadFromPfqlTest(done, category, EqualsDateTime, 'dateTime', 'dateTimeField', v, (d, c) => momentObjectsComparison(d, c), operatorService, allowedNets$); }); afterEach(() => { @@ -262,57 +168,13 @@ describe('CaseDataset', () => { }); }); -function serializationTest(done: DoneFn, - category: CaseDataset, - operator: Type>, - fieldType: string, - value: any, - valueExpectation: (metadata: CategoryGeneratorMetadata) => void, - operatorService: OperatorService) { - category.configurationInputs$.pipe(take(1)).subscribe(inputs => { - expect(inputs).toBeTruthy(); - expect(Array.isArray(inputs)).toBeTrue(); - expect(inputs.length).toBe(1); - - expect(category.hasSelectedDatafields).toBeFalse(); - expect(category.isOperatorSelected()).toBeFalse(); - inputs[0].filteredOptions$.pipe(filter(o => o.length > 0), take(1)).subscribe(options => { - const option = options.find(o => { - const key = DatafieldMapKey.parse(o.value as string); - // for search purposes, enumeration and multichoice maps are equivalent to their simpler counterparts - if (fieldType === 'enumeration_map') { - fieldType = 'enumeration'; - } else if (fieldType === 'multichoice_map') { - fieldType = 'multichoice'; - } - return key.type === fieldType; - }); - expect(option).toBeTruthy(); - - category.selectDatafields(option.value as string, false); - expect(category.hasSelectedDatafields).toBeTrue(); - expect(category.isOperatorSelected()).toBeFalse(); - - configureCategory(category, operatorService, operator, [value]); - expect(category.isOperatorSelected()).toBeTrue(); - - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - valueExpectation(metadata); - expect(metadata.category).toBe(Categories.CASE_DATASET); - expect(metadata.configuration?.operator).toBe(operatorService.getOperator(operator).serialize()); - - done(); - }); - }); -} - -function deserializationTest(done: DoneFn, +function loadFromPfqlTest(done: DoneFn, category: CaseDataset, operator: Type>, fieldType: string, + fieldIdentifier, value: any, - expectDeserializedValueToBeEqual: (deserialized: any, category: any) => void, + expectLoadedValueToBeEqual: (loadingCategory: any, category: any) => void, operatorService: OperatorService, allowedNets$: Observable>) { category.configurationInputs$.pipe(take(1)).subscribe(inputs => { @@ -336,21 +198,14 @@ function deserializationTest(done: DoneFn, category.selectDatafields(option.value as string, false); configureCategory(category, operatorService, operator, [value]); - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - const deserialized = new CaseDataset(operatorService, null, createMockDependencies(allowedNets$, operatorService)); - deserialized.loadFromMetadata(metadata).subscribe(() => { - expect(deserialized.hasSelectedDatafields).toBeTrue(); - expect(deserialized.isOperatorSelected()).toBeTrue(); - expect(deserialized.providesPredicate).toBeTrue(); - - expectDeserializedValueToBeEqual(deserialized, category); + const loadedCategory = new CaseDataset(operatorService, null, createMockDependencies(allowedNets$, operatorService)); + const expression = new DataSimpleExpression(fieldIdentifier, operatorService.getOperator(operator), value, category); + loadedCategory.loadFromPfqlExpression(expression).subscribe(() => { + expect(loadedCategory.hasSelectedDatafields).toBeTrue(); + expect(loadedCategory.isOperatorSelected()).toBeTrue(); + expect(loadedCategory.providesPredicate).toBeTrue(); - const deserializedMetadata = deserialized.createMetadata(); - expect(deserializedMetadata).toBeTruthy(); - expect(deserializedMetadata.configuration).toEqual(metadata.configuration); - expect(deserializedMetadata.category).toEqual(metadata.category); - expect(deserializedMetadata.values).toEqual(metadata.values); + expectLoadedValueToBeEqual(loadedCategory, category); done(); }); @@ -358,17 +213,17 @@ function deserializationTest(done: DoneFn, }); } -function valueObjectsComparison(deserialized: any, category: any) { - expect(deserialized._operandsFormControls[0].value).toEqual(category._operandsFormControls[0].value); +function valueObjectsComparison(loadedCategory: any, category: any) { + expect(loadedCategory._operandsFormControls[0].value).toEqual(category._operandsFormControls[0].value); } -function momentObjectsComparison(deserialized: any, category: any) { +function momentObjectsComparison(loadedCategory: any, category: any) { const originalMoment = (category as any)._operandsFormControls[0].value; - const deserializedMoment = (deserialized as any)._operandsFormControls[0].value; + const loadedMoment = (loadedCategory as any)._operandsFormControls[0].value; expect(moment.isMoment(originalMoment)).toBeTrue(); - expect(moment.isMoment(deserializedMoment)).toBeTrue(); - expect(deserializedMoment.isSame(originalMoment)).toBeTrue(); + expect(moment.isMoment(loadedMoment)).toBeTrue(); + expect(loadedMoment.isSame(originalMoment)).toBeTrue(); } function mockUserSearchValue(userName: string, userId: string): SearchAutocompleteOption> { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.spec.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.spec.ts index 03452ac899..7552678a44 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.spec.ts @@ -8,9 +8,8 @@ import {createMockNet} from '../../../../utility/tests/utility/create-mock-net'; import {OperatorResolverService} from '../../../operator-service/operator-resolver.service'; import {configureCategory} from '../../../../utility/tests/utility/configure-category'; import {Equals} from '../../operator/equals'; -import {Categories} from '../categories'; -import {Operators} from '../../operator/operators'; import {filter, take} from 'rxjs/operators'; +import {SimpleExpression} from "../../../../pfql/model/simple-expression"; describe('CaseProcess', () => { let operatorService: OperatorService; @@ -85,32 +84,7 @@ describe('CaseProcess', () => { expect(optionB.value.some(o => o === 'B')).toBeTrue(); }); - it('should not serialize incomplete instance', () => { - allowedNets$.next([]); - expect(category.createMetadata()).toBeUndefined(); - }); - - it('should serialize complete instance', () => { - allowedNets$.next([ - createMockNet('', 'A', 'A'), - createMockNet('', 'B', 'A'), - ]); - - const options = category.options; - expect(options.length).toBe(1); - const option = options[0]; - expect(option.text).toBe('A'); - - configureCategory(category, operatorService, Equals, [option]); - - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - expect(metadata.values).toEqual([option.text]); - expect(metadata.category).toBe(Categories.CASE_PROCESS); - expect(metadata.configuration?.operator).toBe(Operators.EQUALS); - }); - - it('should deserialize stored instance', (done) => { + it('should load pfql expression', (done) => { allowedNets$.next([ createMockNet('', 'A', 'A'), createMockNet('', 'B', 'A'), @@ -123,23 +97,16 @@ describe('CaseProcess', () => { configureCategory(category, operatorService, Equals, [option]); - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - const deserialized = new CaseProcess(operatorService, null, createMockDependencies(allowedNets$, operatorService)); + const loadedCategory = new CaseProcess(operatorService, null, createMockDependencies(allowedNets$, operatorService)); + const expression = new SimpleExpression(new Equals(), 'A', category); // wait for autocomplete options to initialize - deserialized.options$.pipe(filter(o => o.length > 0), take(1)).subscribe(() => { - deserialized.loadFromMetadata(metadata).subscribe(() => { - expect(deserialized.isOperatorSelected()).toBeTrue(); - expect(deserialized.providesPredicate).toBeTrue(); - - expect((deserialized as any)._operandsFormControls[0].value).toEqual((category as any)._operandsFormControls[0].value); - - const deserializedMetadata = deserialized.createMetadata(); - expect(deserializedMetadata).toBeTruthy(); - expect(deserializedMetadata.configuration).toEqual(metadata.configuration); - expect(deserializedMetadata.category).toEqual(metadata.category); - expect(deserializedMetadata.values).toEqual(metadata.values); + loadedCategory.options$.pipe(filter(o => o.length > 0), take(1)).subscribe(() => { + loadedCategory.loadFromPfqlExpression(expression).subscribe(() => { + expect(loadedCategory.isOperatorSelected()).toBeTrue(); + expect(loadedCategory.providesPredicate).toBeTrue(); + + expect((loadedCategory as any)._operandsFormControls[0].value).toEqual((category as any)._operandsFormControls[0].value); done(); }); diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts index 444add70df..e23561d4d4 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-process.ts @@ -7,10 +7,10 @@ import {OptionalDependencies} from '../../../category-factory/optional-dependenc import {NoConfigurationAutocompleteCategory} from '../no-configuration-autocomplete-category'; import {NotEquals} from '../../operator/not-equals'; import {Categories} from '../categories'; -import {Observable, of, Subject, Subscription} from 'rxjs'; +import {Observable, of, Subscription} from 'rxjs'; import {CaseSearch} from './case-search.enum'; import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; -import {take, filter} from "rxjs/operators"; +import {take, filter, map} from "rxjs/operators"; import {SimpleExpression} from "../../../../pfql/model/simple-expression"; import {SearchInputType} from "../search-input-type"; import {Substring} from "../../operator/substring"; @@ -68,19 +68,16 @@ export class CaseProcess extends NoConfigurationAutocompleteCategory { this.setOperands([expression.operandValue]); return of(undefined); } - const isDone$ = new Subject(); - this._options$.pipe( + return this._options$.pipe( filter(options => options.length > 0), - take(1) - ).subscribe(options => { - const found = options.find(option => option.value.includes(expression.operandValue)); - if (found) { - this.setOperands([found] as any); - } - isDone$.next(); - isDone$.complete(); - }); - return isDone$.asObservable(); + take(1), + map(options => { + const found = options.find(option => option.value.includes(expression.operandValue)); + if (found) { + this.setOperands([found] as any); + } + }) + ); } /** diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-string-id.spec.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-string-id.spec.ts index 79b67a9042..1269b35300 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-string-id.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-string-id.spec.ts @@ -3,9 +3,8 @@ import {OperatorService} from '../../../operator-service/operator.service'; import {OperatorResolverService} from '../../../operator-service/operator-resolver.service'; import {configureCategory} from '../../../../utility/tests/utility/configure-category'; import {Equals} from '../../operator/equals'; -import {Categories} from '../categories'; -import {Operators} from '../../operator/operators'; import {TestBed} from '@angular/core/testing'; +import {SimpleExpression} from "../../../../pfql/model/simple-expression"; describe('CaseStringId', () => { let category: CaseStringId; @@ -31,37 +30,16 @@ describe('CaseStringId', () => { expect(category.isOperatorSelected()).toBeTrue(); }); - it('should not serialize incomplete instance', () => { - expect(category.createMetadata()).toBeUndefined(); - }); - - it('should serialize complete instance', () => { + it('should load pfql expression', (done) => { configureCategory(category, operatorService, Equals, ['foo']); - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - expect(metadata.values).toEqual(['foo']); - expect(metadata.category).toBe(Categories.CASE_STRING_ID); - expect(metadata.configuration?.operator).toBe(Operators.EQUALS); - }); - - it('should deserialize stored instance', (done) => { - configureCategory(category, operatorService, Equals, ['foo']); - - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - const deserialized = new CaseStringId(operatorService, null); - deserialized.loadFromMetadata(metadata).subscribe(() => { - expect(deserialized.isOperatorSelected()).toBeTrue(); - expect(deserialized.providesPredicate).toBeTrue(); - - expect((deserialized as any)._operandsFormControls[0].value).toEqual((category as any)._operandsFormControls[0].value); + const loadedCategory = new CaseStringId(operatorService, null); + const expression = new SimpleExpression(new Equals(), 'foo', category); + loadedCategory.loadFromPfqlExpression(expression).subscribe(() => { + expect(loadedCategory.isOperatorSelected()).toBeTrue(); + expect(loadedCategory.providesPredicate).toBeTrue(); - const deserializedMetadata = deserialized.createMetadata(); - expect(deserializedMetadata).toBeTruthy(); - expect(deserializedMetadata.configuration).toEqual(metadata.configuration); - expect(deserializedMetadata.category).toEqual(metadata.category); - expect(deserializedMetadata.values).toEqual(metadata.values); + expect((loadedCategory as any)._operandsFormControls[0].value).toEqual((category as any)._operandsFormControls[0].value); done(); }); diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.spec.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.spec.ts index 93d68a0222..5218bdccad 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-title.spec.ts @@ -3,14 +3,13 @@ import {OperatorService} from '../../../operator-service/operator.service'; import {OperatorResolverService} from '../../../operator-service/operator-resolver.service'; import {configureCategory} from '../../../../utility/tests/utility/configure-category'; import {Equals} from '../../operator/equals'; -import {Categories} from '../categories'; -import {Operators} from '../../operator/operators'; import {TestBed} from '@angular/core/testing'; import {Substring} from '../../operator/substring'; import {CaseSearch} from './case-search.enum'; import {SearchIndexResolverService} from '../../../search-keyword-resolver-service/search-index-resolver.service'; import {OptionalDependencies} from '../../../category-factory/optional-dependencies'; import {NotEquals} from "../../operator/not-equals"; +import {SimpleExpression} from "../../../../pfql/model/simple-expression"; describe('CaseTitle', () => { let category: CaseTitle; @@ -39,37 +38,16 @@ describe('CaseTitle', () => { expect(category.isOperatorSelected()).toBeTrue(); }); - it('should not serialize incomplete instance', () => { - expect(category.createMetadata()).toBeUndefined(); - }); - - it('should serialize complete instance', () => { + it('should load pfql expression', (done) => { configureCategory(category, operatorService, Equals, ['foo']); - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - expect(metadata.values).toEqual(['foo']); - expect(metadata.category).toBe(Categories.CASE_TITLE); - expect(metadata.configuration?.operator).toBe(Operators.EQUALS); - }); - - it('should deserialize stored instance', (done) => { - configureCategory(category, operatorService, Equals, ['foo']); - - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - const deserialized = new CaseTitle(operatorService, null); - deserialized.loadFromMetadata(metadata).subscribe(() => { - expect(deserialized.isOperatorSelected()).toBeTrue(); - expect(deserialized.providesPredicate).toBeTrue(); - - expect((deserialized as any)._operandsFormControls[0].value).toEqual((category as any)._operandsFormControls[0].value); + const loadedCategory = new CaseTitle(operatorService, null); + const expression = new SimpleExpression(new Equals(), 'foo', category); + loadedCategory.loadFromPfqlExpression(expression).subscribe(() => { + expect(loadedCategory.isOperatorSelected()).toBeTrue(); + expect(loadedCategory.providesPredicate).toBeTrue(); - const deserializedMetadata = deserialized.createMetadata(); - expect(deserializedMetadata).toBeTruthy(); - expect(deserializedMetadata.configuration).toEqual(metadata.configuration); - expect(deserializedMetadata.category).toEqual(metadata.category); - expect(deserializedMetadata.values).toEqual(metadata.values); + expect((loadedCategory as any)._operandsFormControls[0].value).toEqual((category as any)._operandsFormControls[0].value); done(); }); diff --git a/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts b/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts index 3466426a1b..ea5e485efe 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/no-configuration-user-autocomplete-category.ts @@ -4,12 +4,12 @@ import {Operator} from '../operator/operator'; import {LoggerService} from '../../../logger/services/logger.service'; import {OperatorService} from '../../operator-service/operator.service'; import {OptionalDependencies} from '../../category-factory/optional-dependencies'; -import {Observable, of, Subject} from 'rxjs'; +import {Observable, of} from 'rxjs'; import {SearchAutocompleteOption} from './search-autocomplete-option'; import {Query} from '../query/query'; import {FormControl} from '@angular/forms'; import {ResourceTypeQueryPrefix} from "./resource-type-query-prefix"; -import {take} from "rxjs/operators"; +import {map, take} from "rxjs/operators"; import {SimpleExpression} from "../../../pfql/model/simple-expression"; import {IsNull} from "../operator/is-null"; @@ -64,19 +64,11 @@ export abstract class NoConfigurationUserAutocompleteCategory extends NoConfigur this._generatedPredicate$.next(this.generatePredicate([])) return of(undefined); } - const isDone$ = new Subject(); - const optionToBeSelected$ = this._userAutocomplete.getOptionFromExpressionValue$(expression.operandValue); - optionToBeSelected$.pipe(take(1)).subscribe({ - next: optionToBeSelected => { + return this._userAutocomplete.getOptionFromExpressionValue$(expression.operandValue).pipe( + take(1), + map(optionToBeSelected => { this.setOperands([optionToBeSelected] as any); - isDone$.next(); - isDone$.complete(); - }, - error: error => { - isDone$.next(); - isDone$.complete(); - } - }); - return isDone$.asObservable(); + }) + ); } } diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-assignee.spec.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-assignee.spec.ts index 334b8913b0..c65176ad14 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-assignee.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-assignee.spec.ts @@ -2,28 +2,34 @@ import {TaskAssignee} from './task-assignee'; import {OperatorService} from '../../../operator-service/operator.service'; import {createMockDependencies} from '../../../../utility/tests/search-category-mock-dependencies'; import {TestBed, waitForAsync} from '@angular/core/testing'; -import {ReplaySubject} from 'rxjs'; +import {Observable, of, ReplaySubject} from 'rxjs'; import {OperatorResolverService} from '../../../operator-service/operator-resolver.service'; import {Net} from '../../../../process/net'; import {configureCategory} from '../../../../utility/tests/utility/configure-category'; import {Equals} from '../../operator/equals'; -import {Categories} from '../categories'; -import {Operators} from '../../operator/operators'; import {mockUserAutocompleteValue} from '../../../../utility/tests/mocks/mock-user-autocomplete-value'; +import {SimpleExpression} from "../../../../pfql/model/simple-expression"; +import {Page} from "../../../../resources/interface/page"; +import {UserResource} from "../../../../resources/interface/user-resource"; +import {createMockPage} from "../../../../utility/tests/utility/create-mock-page"; +import {UserResourceService} from "../../../../resources/engine-endpoint/user-resource.service"; describe('TaskAssignee', () => { let operatorService: OperatorService; + let userResourceService: MockUserResourceService; let category: TaskAssignee; let allowedNets$: ReplaySubject>; beforeAll(() => { operatorService = new OperatorService(new OperatorResolverService()); + userResourceService = new MockUserResourceService(); }); beforeEach(waitForAsync(async () => { allowedNets$ = new ReplaySubject>(1); allowedNets$.next([]); - category = await new TaskAssignee(operatorService, null, createMockDependencies(allowedNets$, operatorService)); + category = await new TaskAssignee(operatorService, null, createMockDependencies(allowedNets$, + operatorService, userResourceService as unknown as UserResourceService)); })); afterEach(() => { @@ -42,42 +48,56 @@ describe('TaskAssignee', () => { expect(category.isOperatorSelected()).toBeTrue(); }); - it('should not serialize incomplete instance', () => { - expect(category.createMetadata()).toBeUndefined(); - }); - - it('should serialize complete instance', () => { + it('should load pfql expression', (done) => { configureCategory(category, operatorService, Equals, [mockUserAutocompleteValue('Test User', true, 'userId')]); - const mockedSerializedValue = mockUserAutocompleteValue('Test User', true, 'userId'); - delete mockedSerializedValue.icon; + const loadedCategory = new TaskAssignee(operatorService, null, createMockDependencies(allowedNets$, + operatorService, userResourceService as unknown as UserResourceService)); + const expression = new SimpleExpression(new Equals(), mockUserAutocompleteValue('Test User', true, 'userId'), category); + loadedCategory.loadFromPfqlExpression(expression).subscribe(() => { + expect(loadedCategory.isOperatorSelected()).toBeTrue(); + expect(loadedCategory.providesPredicate).toBeTrue(); + + expect((loadedCategory as any)._operandsFormControls[0].value).toEqual((category as any)._operandsFormControls[0].value); - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - expect(metadata.values).toEqual([mockedSerializedValue]); - expect(metadata.category).toBe(Categories.TASK_ASSIGNEE); - expect(metadata.configuration?.operator).toBe(Operators.EQUALS); + done(); + }); }); - it('should deserialize stored instance', (done) => { + it('should generate pfql query', () => { configureCategory(category, operatorService, Equals, [mockUserAutocompleteValue('Test User', true, 'userId')]); + let predicate = category.generatePredicate(['userId']); + expect(predicate.query.value.includes(`tasks: userId eq 'userId'`)).toBeTrue(); + }); +}) - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - const deserialized = new TaskAssignee(operatorService, null, createMockDependencies(allowedNets$, operatorService)); - deserialized.loadFromMetadata(metadata).subscribe(() => { - expect(deserialized.isOperatorSelected()).toBeTrue(); - expect(deserialized.providesPredicate).toBeTrue(); - - expect((deserialized as any)._operandsFormControls[0].value).toEqual((category as any)._operandsFormControls[0].value); +class MockUserResourceService { - const deserializedMetadata = deserialized.createMetadata(); - expect(deserializedMetadata).toBeTruthy(); - expect(deserializedMetadata.configuration).toEqual(metadata.configuration); - expect(deserializedMetadata.category).toEqual(metadata.category); - expect(deserializedMetadata.values).toEqual(metadata.values); + public search(): Observable> { + return of(createMockPage([{ + name: 'Test', + surname: 'User', + id: 'userId', + email: 'Test User', + fullName: `Test User`, + groups: [], + authorities: [], + nextGroups: [], + processRoles: [] + }])); + } - done(); + public getUser(userId: string): Observable { + return of({ + name: 'Test', + surname: 'User', + id: 'userId', + email: 'Test User', + fullName: `Test User`, + groups: [], + authorities: [], + nextGroups: [], + processRoles: [] }); - }); -}); + } +} diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.spec.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.spec.ts index 5280a2df6e..95bf06cbed 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.spec.ts @@ -8,9 +8,8 @@ import {Net} from '../../../../process/net'; import {createMockNet} from '../../../../utility/tests/utility/create-mock-net'; import {configureCategory} from '../../../../utility/tests/utility/configure-category'; import {Equals} from '../../operator/equals'; -import {Categories} from '../categories'; -import {Operators} from '../../operator/operators'; import {filter, take} from 'rxjs/operators'; +import {SimpleExpression} from "../../../../pfql/model/simple-expression"; describe('TaskProcess', () => { let operatorService: OperatorService; @@ -83,12 +82,7 @@ describe('TaskProcess', () => { expect(optionB.value.some(o => o === '3')).toBeTrue(); }); - it('should not serialize incomplete instance', () => { - allowedNets$.next([]); - expect(category.createMetadata()).toBeUndefined(); - }); - - it('should serialize complete instance', () => { + it('should load pfql expression', (done) => { allowedNets$.next([ createMockNet('1', '', 'A'), createMockNet('2', '', 'A'), @@ -101,17 +95,25 @@ describe('TaskProcess', () => { configureCategory(category, operatorService, Equals, [option]); - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - expect(metadata.values).toEqual([option.text]); - expect(metadata.category).toBe(Categories.TASK_PROCESS); - expect(metadata.configuration?.operator).toBe(Operators.EQUALS); + const loadedCategory = new TaskProcess(operatorService, null, createMockDependencies(allowedNets$, operatorService)); + const expression = new SimpleExpression(new Equals(), '1', category); + + // wait for autocomplete options to initialize + loadedCategory.options$.pipe(filter(o => o.length > 0), take(1)).subscribe(() => { + loadedCategory.loadFromPfqlExpression(expression).subscribe(() => { + expect(loadedCategory.isOperatorSelected()).toBeTrue(); + expect(loadedCategory.providesPredicate).toBeTrue(); + + expect((loadedCategory as any)._operandsFormControls[0].value).toEqual((category as any)._operandsFormControls[0].value); + + done(); + }); + }); }); - it('should deserialize stored instance', (done) => { + it('should generate pfql query', () => { allowedNets$.next([ createMockNet('1', '', 'A'), - createMockNet('2', '', 'A'), ]); const options = category.options; @@ -120,27 +122,7 @@ describe('TaskProcess', () => { expect(option.text).toBe('A'); configureCategory(category, operatorService, Equals, [option]); - - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - const deserialized = new TaskProcess(operatorService, null, createMockDependencies(allowedNets$, operatorService)); - - // wait for autocomplete options to initialize - deserialized.options$.pipe(filter(o => o.length > 0), take(1)).subscribe(() => { - deserialized.loadFromMetadata(metadata).subscribe(() => { - expect(deserialized.isOperatorSelected()).toBeTrue(); - expect(deserialized.providesPredicate).toBeTrue(); - - expect((deserialized as any)._operandsFormControls[0].value).toEqual((category as any)._operandsFormControls[0].value); - - const deserializedMetadata = deserialized.createMetadata(); - expect(deserializedMetadata).toBeTruthy(); - expect(deserializedMetadata.configuration).toEqual(metadata.configuration); - expect(deserializedMetadata.category).toEqual(metadata.category); - expect(deserializedMetadata.values).toEqual(metadata.values); - - done(); - }); - }); + let predicate = category.generatePredicate(['1']); + expect(predicate.query.value.includes(`tasks: processId eq '1'`)).toBeTrue(); }); }); diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts index 25c7aaea5f..fc4f6ab9a1 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-process.ts @@ -10,7 +10,7 @@ import {Categories} from '../categories'; import {Observable, of, Subject, Subscription} from 'rxjs'; import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; import {SimpleExpression} from "../../../../pfql/model/simple-expression"; -import {filter, take} from "rxjs/operators"; +import {filter, take, map} from "rxjs/operators"; import {SearchAutocompleteOption} from "../search-autocomplete-option"; import {SearchInputType} from "../search-input-type"; @@ -63,26 +63,22 @@ export class TaskProcess extends NoConfigurationAutocompleteCategory { this.setOperands([expression.operandValue]); return of(undefined); } - const isDone$ = new Subject(); - this._options$.pipe( + return this._options$.pipe( filter(options => options.length > 0), - take(1) - ).subscribe(options => { - let selectedOption: SearchAutocompleteOption | undefined; - for (const option of options) { - if (option.value.some(netId => netId === expression.operandValue)) { - selectedOption = option; - break; + take(1), + map(options => { + let selectedOption: SearchAutocompleteOption | undefined; + for (const option of options) { + if (option.value.some(netId => netId === expression.operandValue)) { + selectedOption = option; + break; + } } - } - if (!!selectedOption) { - this.setOperands([selectedOption] as any); - } - isDone$.next(); - isDone$.complete(); - }) - - return isDone$.asObservable(); + if (!!selectedOption) { + this.setOperands([selectedOption] as any); + } + }) + ); } protected generateQuery(userInput: Array>): Query { diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.spec.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.spec.ts index 407dc6121c..b068697d72 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.spec.ts @@ -8,9 +8,8 @@ import {Net} from '../../../../process/net'; import {createMockNet} from '../../../../utility/tests/utility/create-mock-net'; import {configureCategory} from '../../../../utility/tests/utility/configure-category'; import {Equals} from '../../operator/equals'; -import {Categories} from '../categories'; -import {Operators} from '../../operator/operators'; import {filter, take} from 'rxjs/operators'; +import {SimpleExpression} from "../../../../pfql/model/simple-expression"; describe('TaskTask', () => { let operatorService: OperatorService; @@ -73,12 +72,7 @@ describe('TaskTask', () => { expect(option2.value.some(o => o.attributeId === 'sid3')).toBeTrue(); }); - it('should not serialize incomplete instance', () => { - allowedNets$.next([]); - expect(category.createMetadata()).toBeUndefined(); - }); - - it('should serialize complete instance', () => { + it('should load pfql expression', (done) => { allowedNets$.next([ createMockNet('', 'A', 'A', undefined, [{title: 'transition1', stringId: 'sid1'}]), createMockNet('', 'B', 'B', undefined, [{title: 'transition1', stringId: 'sid2'}]), @@ -91,17 +85,26 @@ describe('TaskTask', () => { configureCategory(category, operatorService, Equals, [option]); - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - expect(metadata.values).toEqual([option.text]); - expect(metadata.category).toBe(Categories.TASK_TASK); - expect(metadata.configuration?.operator).toBe(Operators.EQUALS); + const loadedCategory = new TaskTask(operatorService, null, createMockDependencies(allowedNets$, operatorService)); + const expression = new SimpleExpression(new Equals(), 'sid1', category); + + // wait for autocomplete options to initialize + loadedCategory.options$.pipe(filter(o => o.length > 0), take(1)).subscribe(() => { + loadedCategory.loadFromPfqlExpression(expression).subscribe(() => { + expect(loadedCategory.isOperatorSelected()).toBeTrue(); + expect(loadedCategory.providesPredicate).toBeTrue(); + + expect((loadedCategory as any)._operandsFormControls[0].value).toEqual((category as any)._operandsFormControls[0].value); + + done(); + }); + }); }); - it('should deserialize stored instance', (done) => { + + it('should generate pfql query', () => { allowedNets$.next([ createMockNet('', 'A', 'A', undefined, [{title: 'transition1', stringId: 'sid1'}]), - createMockNet('', 'B', 'B', undefined, [{title: 'transition1', stringId: 'sid2'}]), ]); const options = category.options; @@ -110,27 +113,7 @@ describe('TaskTask', () => { expect(option.text).toBe('transition1'); configureCategory(category, operatorService, Equals, [option]); - - const metadata = category.createMetadata(); - expect(metadata).toBeTruthy(); - const deserialized = new TaskTask(operatorService, null, createMockDependencies(allowedNets$, operatorService)); - - // wait for autocomplete options to initialize - deserialized.options$.pipe(filter(o => o.length > 0), take(1)).subscribe(() => { - deserialized.loadFromMetadata(metadata).subscribe(() => { - expect(deserialized.isOperatorSelected()).toBeTrue(); - expect(deserialized.providesPredicate).toBeTrue(); - - expect((deserialized as any)._operandsFormControls[0].value).toEqual((category as any)._operandsFormControls[0].value); - - const deserializedMetadata = deserialized.createMetadata(); - expect(deserializedMetadata).toBeTruthy(); - expect(deserializedMetadata.configuration).toEqual(metadata.configuration); - expect(deserializedMetadata.category).toEqual(metadata.category); - expect(deserializedMetadata.values).toEqual(metadata.values); - - done(); - }); - }); + let predicate = category.generatePredicate([[{netId: 'A', attributeId: 'sid1'}]]); + expect(predicate.query.value).toEqual('tasks: (transitionId eq \'sid1\') AND (processId eq \'A\')'); }); }); diff --git a/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts b/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts index e48c6b5596..4c4f2c24bf 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/task/task-task.ts @@ -9,8 +9,8 @@ import {NameIdPair} from '../name-id-pair'; import {Categories} from '../categories'; import {ResourceTypeQueryPrefix} from "../resource-type-query-prefix"; import {SimpleExpression} from "../../../../pfql/model/simple-expression"; -import {Observable, of, Subject} from "rxjs"; -import {filter, take} from "rxjs/operators"; +import {Observable, of} from "rxjs"; +import {filter, take, map} from "rxjs/operators"; import {NetAttributePair} from "../net-attribute-pair"; import {SearchAutocompleteOption} from "../search-autocomplete-option"; import {SearchInputType} from "../search-input-type"; @@ -45,27 +45,22 @@ export class TaskTask extends TaskNetAttributeAutocompleteCategory { this.setOperands([expression.operandValue]); return of(undefined); } - - const isDone$ = new Subject(); - this._options$.pipe( + return this._options$.pipe( filter(options => options.length > 0), - take(1) - ).subscribe(options => { - let selectedOption: SearchAutocompleteOption | undefined; - for (const option of options) { - if (option.value.some(pair => pair.attributeId === expression.operandValue)) { - selectedOption = option; - break; + take(1), + map(options => { + let selectedOption: SearchAutocompleteOption | undefined; + for (const option of options) { + if (option.value.some(pair => pair.attributeId === expression.operandValue)) { + selectedOption = option; + break; + } } - } - if (!!selectedOption) { - this.setOperands([selectedOption] as any); - } - isDone$.next(); - isDone$.complete(); - }) - - return isDone$.asObservable(); + if (!!selectedOption) { + this.setOperands([selectedOption] as any); + } + }) + ); } get inputPlaceholder(): string { diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/like.ts b/projects/netgrif-components-core/src/lib/search/models/operator/like.ts index c848d00b3c..21dbfa9cf4 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/like.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/like.ts @@ -16,7 +16,7 @@ export class Like extends Operator { createQuery(pfqlKeywords: Array, args: Array): Query { this.checkArgumentsCount(args); - const escaped = Operator.escapeInput(args[0]); // todo 2466 escape? + const escaped = Operator.escapeInput(args[0]); return Operator.forEachKeyword(pfqlKeywords, keyword => escaped.wasEscaped ? new Query(`${keyword} eq '${escaped.value}'`) : new Query(`${keyword} eq '${escaped.value}'*`)); } diff --git a/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts b/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts index 5b3822f4ac..d06f3feb14 100644 --- a/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts +++ b/projects/netgrif-components-core/src/lib/search/models/operator/operator.ts @@ -66,7 +66,6 @@ export abstract class Operator { * @returns user input with the escapable characters escaped and the unescapable characters removed */ public static escapeInput(input: string): EscapeResult { - // todo 2466 escaping? if (typeof input === 'string') { let escaped = false; let output = ''; @@ -138,7 +137,6 @@ export abstract class Operator { public createQuery(pfqlKeywords: Array, args: Array, escapeArgs = true, wrapInQuotes = true): Query { this.checkArgumentsCount(args); return Operator.forEachKeyword(pfqlKeywords, (keyword: string) => { - // todo 2466 escape? const escapedValue = escapeArgs ? Operator.escapeInput(args[0] as unknown as string) : ({value: args[0] as unknown as string, wasEscaped: false}); const wrappedValue = Operator.wrapInputWithQuotes(escapedValue.value, wrapInQuotes); diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts index f2c6b51801..660e994ac0 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts @@ -13,7 +13,6 @@ import {AllowedNetsServiceFactory} from '../../allowed-nets/services/factory/all import {CaseCreationDate} from '../models/category/case/case-creation-date'; import moment from 'moment'; import {CaseSearchRequestBody} from '../../filter/models/case-search-request-body'; -import {FilterMetadata} from '../models/persistance/filter-metadata'; import {FilterType} from '../../filter/models/filter-type'; import {of} from 'rxjs'; import {SimpleFilter} from '../../filter/models/simple-filter'; @@ -75,65 +74,66 @@ describe('SearchService', () => { expect(service.rootPredicate.getPredicateMap().get(id)).toBeTruthy(); }); - describe('serialization / deserialization', () => { - let serializedSearch: FilterMetadata; - - beforeEach(() => { - const predicate1 = categoryFactory.getWithDefaultOperator(CaseTitle); - predicate1.setOperands(['title']); - - const predicate2 = categoryFactory.getWithDefaultOperator(CaseCreationDate); - predicate2.setOperands([moment('2021-03-31').valueOf()]); - - const meta1 = predicate1.createMetadata(); - expect(meta1).toBeTruthy(); - const meta2 = predicate2.createMetadata(); - expect(meta2).toBeTruthy(); - - serializedSearch = { - filterType: FilterType.CASE, - predicateMetadata: [[meta1, meta2]], - searchCategories: [] // they don't play a role for this test - }; - }); - - it('should deserialize saved search', (done) => { - expect(service.additionalFiltersApplied).toBeFalse(); - - service.loadFromMetadata(serializedSearch); - service.activeFilter$.subscribe(f => { - expect(service.additionalFiltersApplied).toBeTrue(); - - expect(f).toBeTruthy(); - const filters = f.getRequestBody() as Array; - expect(Array.isArray(filters)).toBeTrue(); - expect(filters.length).toBe(2); - expect(filters[0]).toEqual({}); - expect(filters[1].query).toBeTruthy(); - - done(); - }); - }); - - it('should serialize search', (done) => { - expect(service.additionalFiltersApplied).toBeFalse(); - - service.loadFromMetadata(serializedSearch); - service.activeFilter$.subscribe(f => { - expect(service.additionalFiltersApplied).toBeTrue(); - - const serialized = service.createPredicateMetadata(); - expect(serialized).toBeTruthy(); - expect(serialized).toEqual(serializedSearch.predicateMetadata); - - done(); - }); - }); - - afterEach(() => { - TestBed.resetTestingModule(); - }); - }); + // todo 2466 major test for pfql loading + // describe('serialization / deserialization', () => { + // let serializedSearch: FilterMetadata; + // + // beforeEach(() => { + // const predicate1 = categoryFactory.getWithDefaultOperator(CaseTitle); + // predicate1.setOperands(['title']); + // + // const predicate2 = categoryFactory.getWithDefaultOperator(CaseCreationDate); + // predicate2.setOperands([moment('2021-03-31').valueOf()]); + // + // const meta1 = predicate1.createMetadata(); + // expect(meta1).toBeTruthy(); + // const meta2 = predicate2.createMetadata(); + // expect(meta2).toBeTruthy(); + // + // serializedSearch = { + // filterType: FilterType.CASE, + // predicateMetadata: [[meta1, meta2]], + // searchCategories: [] // they don't play a role for this test + // }; + // }); + // + // it('should deserialize saved search', (done) => { + // expect(service.additionalFiltersApplied).toBeFalse(); + // + // service.loadFromMetadata(serializedSearch); + // service.activeFilter$.subscribe(f => { + // expect(service.additionalFiltersApplied).toBeTrue(); + // + // expect(f).toBeTruthy(); + // const filters = f.getRequestBody() as Array; + // expect(Array.isArray(filters)).toBeTrue(); + // expect(filters.length).toBe(2); + // expect(filters[0]).toEqual({}); + // expect(filters[1].query).toBeTruthy(); + // + // done(); + // }); + // }); + // + // it('should serialize search', (done) => { + // expect(service.additionalFiltersApplied).toBeFalse(); + // + // service.loadFromMetadata(serializedSearch); + // service.activeFilter$.subscribe(f => { + // expect(service.additionalFiltersApplied).toBeTrue(); + // + // const serialized = service.createPredicateMetadata(); + // expect(serialized).toBeTruthy(); + // expect(serialized).toEqual(serializedSearch.predicateMetadata); + // + // done(); + // }); + // }); + // + // afterEach(() => { + // TestBed.resetTestingModule(); + // }); + // }); afterEach(() => { TestBed.resetTestingModule(); diff --git a/projects/netgrif-components-core/src/lib/utility/tests/search-category-mock-dependencies.ts b/projects/netgrif-components-core/src/lib/utility/tests/search-category-mock-dependencies.ts index b9d7704853..a05aebf3a1 100644 --- a/projects/netgrif-components-core/src/lib/utility/tests/search-category-mock-dependencies.ts +++ b/projects/netgrif-components-core/src/lib/utility/tests/search-category-mock-dependencies.ts @@ -15,11 +15,13 @@ const opService = new OperatorService(opResolver); export const createMockDependencies: ( allowedNets$?: Observable>, operatorService?: OperatorService, - userResourceService?: UserResourceService) => OptionalDependencies = + userResourceService?: UserResourceService, + ignoreNetsOnAutocompleteCategory?: boolean) => OptionalDependencies = ( allowedNets$: Observable> = of([]), operatorService?: OperatorService, - userResourceService = {getAll: () => of({content: [], pagination: {}})} as UserResourceService + userResourceService = {getAll: () => of({content: [], pagination: {}})} as UserResourceService, + ignoreNetsOnAutocompleteCategory: boolean = false ) => { const searchIndexResolver = new SearchIndexResolverService(); const allowedNetsService = {allowedNets$} as AllowedNetsService; @@ -32,10 +34,11 @@ export const createMockDependencies: ( new CategoryResolverService(), allowedNetsService, userResourceService, - false + ignoreNetsOnAutocompleteCategory ), searchIndexResolver, userResourceService, - allowedNetsService + allowedNetsService, + ignoreNetsOnAutocompleteCategories: ignoreNetsOnAutocompleteCategory, }; }; diff --git a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-default/case-ref-default.component.spec.ts b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-default/case-ref-default.component.spec.ts index 135c54be2d..3c134dc0a1 100644 --- a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-default/case-ref-default.component.spec.ts +++ b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-default/case-ref-default.component.spec.ts @@ -4,7 +4,8 @@ import { CaseRefDefaultComponent } from './case-ref-default.component'; import {NavigationComponentModule} from '../../../navigation/navigation.module'; import { CaseRefField, - FilterField, FilterType, + FilterField, + FieldTypeResource, NAE_TAB_DATA, NAE_VIEW_ID_SEGMENT, OverflowService, @@ -49,11 +50,7 @@ describe('CaseRefDefaultComponent', () => { `${GroupNavigationConstants.ITEM_FIELD_CASE_FILTER}`, '', '', - { - filterType: FilterType.CASE, - predicateMetadata: [], - searchCategories: [] - }, + FieldTypeResource.CASE_FILTER, [], {visible: true}, '', diff --git a/projects/netgrif-components/src/lib/data-fields/enumeration-field/enumeration-caseref-field/enumeration-caseref-field.component.spec.ts b/projects/netgrif-components/src/lib/data-fields/enumeration-field/enumeration-caseref-field/enumeration-caseref-field.component.spec.ts index 0bdce5b5d1..08162e1fec 100644 --- a/projects/netgrif-components/src/lib/data-fields/enumeration-field/enumeration-caseref-field/enumeration-caseref-field.component.spec.ts +++ b/projects/netgrif-components/src/lib/data-fields/enumeration-field/enumeration-caseref-field/enumeration-caseref-field.component.spec.ts @@ -2,7 +2,9 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { EnumerationCaserefFieldComponent } from './enumeration-caseref-field.component'; import {NavigationComponentModule} from '../../../navigation/navigation.module'; import { - FilterField, FilterType, MultichoiceField, + FilterField, + FieldTypeResource, + MultichoiceField, NAE_TAB_DATA, NAE_VIEW_ID_SEGMENT, OverflowService, @@ -47,11 +49,7 @@ describe('EnumerationCaserefFieldComponent', () => { `${GroupNavigationConstants.ITEM_FIELD_CASE_FILTER}`, '', '', - { - filterType: FilterType.CASE, - predicateMetadata: [], - searchCategories: [] - }, + FieldTypeResource.CASE_FILTER, [], {visible: true}, '', diff --git a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-default-field/filter-default-field.component.spec.ts b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-default-field/filter-default-field.component.spec.ts index a302d8e126..27d4f31ed3 100644 --- a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-default-field/filter-default-field.component.spec.ts +++ b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-default-field/filter-default-field.component.spec.ts @@ -3,7 +3,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { FilterDefaultFieldComponent } from './filter-default-field.component'; import { ConfigurationService, - DATA_FIELD_PORTAL_DATA, DataFieldPortalData, FilterField, FilterType, + DATA_FIELD_PORTAL_DATA, DataFieldPortalData, FilterField, FieldTypeResource, MaterialModule, TestConfigurationService, WrappedBoolean } from "@netgrif/components-core"; @@ -29,9 +29,7 @@ describe('FilterDefaultFieldComponent', () => { providers: [ {provide: ConfigurationService, useClass: TestConfigurationService}, {provide: DATA_FIELD_PORTAL_DATA, useValue: { - dataField: new FilterField('', '', '', { - filterType: FilterType.CASE, predicateMetadata: [], searchCategories: [] - }, [], {}, '', ''), + dataField: new FilterField('', '', '', FieldTypeResource.CASE_FILTER, [], {}, '', ''), formControlRef: new FormControl(), showLargeLayout: new WrappedBoolean() } as DataFieldPortalData diff --git a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.spec.ts b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.spec.ts index f6d102b546..0a322feea4 100644 --- a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.spec.ts +++ b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.spec.ts @@ -1,7 +1,10 @@ import {ComponentFixture, TestBed} from '@angular/core/testing'; import {FilterFieldContentComponent} from './filter-field-content.component'; import {HttpClientTestingModule} from '@angular/common/http/testing'; -import {ConfigurationService, TestConfigurationService, FilterField, FilterType, NAE_FILTER_FIELD} from '@netgrif/components-core'; +import { + ConfigurationService, TestConfigurationService, FilterField, FieldTypeResource, NAE_FILTER_FIELD, + NAE_DEFAULT_CASE_SEARCH_CATEGORIES, NAE_DEFAULT_TASK_SEARCH_CATEGORIES +} from '@netgrif/components-core'; import {AdvancedSearchComponentModule} from '../../../search/advanced-search/advanced-search.module'; describe('FilterFieldContentComponent', () => { @@ -9,9 +12,7 @@ describe('FilterFieldContentComponent', () => { let fixture: ComponentFixture; beforeEach(async () => { - const field = new FilterField('', '', '', { - filterType: FilterType.CASE, predicateMetadata: [], searchCategories: [] - }, [], {}, '', ''); + const field = new FilterField('', '', '', FieldTypeResource.CASE_FILTER, [], {}, '', ''); await TestBed.configureTestingModule({ imports: [ @@ -20,7 +21,9 @@ describe('FilterFieldContentComponent', () => { ], providers: [ {provide: ConfigurationService, useClass: TestConfigurationService}, - {provide: NAE_FILTER_FIELD, useValue: field} + {provide: NAE_FILTER_FIELD, useValue: field}, + NAE_DEFAULT_CASE_SEARCH_CATEGORIES, + NAE_DEFAULT_TASK_SEARCH_CATEGORIES ], declarations: [ FilterFieldContentComponent diff --git a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field.component.spec.ts b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field.component.spec.ts index fdebf7762c..16f1c067b4 100644 --- a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field.component.spec.ts +++ b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field.component.spec.ts @@ -2,8 +2,7 @@ import {ComponentFixture, TestBed} from '@angular/core/testing'; import {FilterFieldComponent} from './filter-field.component'; import {DataFieldTemplateComponent} from '../data-field-template/data-field-template.component'; import {FilterFieldContentComponent} from './filter-field-content/filter-field-content.component'; -import {BrowserDynamicTestingModule} from '@angular/platform-browser-dynamic/testing'; -import {MaterialModule, FilterType, FilterField, ConfigurationService, TestConfigurationService} from '@netgrif/components-core'; +import {MaterialModule, FieldTypeResource, FilterField, ConfigurationService, TestConfigurationService} from '@netgrif/components-core'; import {RequiredLabelComponent} from '../required-label/required-label.component'; import {Component} from '@angular/core'; import {HttpClientTestingModule} from '@angular/common/http/testing'; @@ -53,7 +52,5 @@ describe('FilterFieldComponent', () => { template: '' }) class TestWrapperComponent { - field = new FilterField('', '', '', { - filterType: FilterType.CASE, predicateMetadata: [], searchCategories: [] - }, [], {}, '', ''); + field = new FilterField('', '', '', FieldTypeResource.CASE_FILTER, [], {}, '', ''); } diff --git a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-string-query-field/filter-string-query-field.component.spec.ts b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-string-query-field/filter-string-query-field.component.spec.ts index 1cd0a8310b..2ff9213250 100644 --- a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-string-query-field/filter-string-query-field.component.spec.ts +++ b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-string-query-field/filter-string-query-field.component.spec.ts @@ -7,7 +7,7 @@ import { FilterField, DataFieldPortalData, DATA_FIELD_PORTAL_DATA, - FilterType, + FieldTypeResource, ConfigurationService, TestConfigurationService, WrappedBoolean @@ -33,9 +33,7 @@ describe('FilterStringQueryFieldComponent', () => { providers: [ {provide: ConfigurationService, useClass: TestConfigurationService}, {provide: DATA_FIELD_PORTAL_DATA, useValue: { - dataField: new FilterField('', '', '', { - filterType: FilterType.CASE, predicateMetadata: [], searchCategories: [] - }, [], {}, '', ''), + dataField: new FilterField('', '', '', FieldTypeResource.CASE_FILTER, [], {}, '', ''), formControlRef: new FormControl(), showLargeLayout: new WrappedBoolean() } as DataFieldPortalData diff --git a/projects/netgrif-components/src/lib/data-fields/filter-field/tab-view-filter-field/filter-field-tab-view-content.component.spec.ts b/projects/netgrif-components/src/lib/data-fields/filter-field/tab-view-filter-field/filter-field-tab-view-content.component.spec.ts index ea3ce3e624..904bd47acf 100644 --- a/projects/netgrif-components/src/lib/data-fields/filter-field/tab-view-filter-field/filter-field-tab-view-content.component.spec.ts +++ b/projects/netgrif-components/src/lib/data-fields/filter-field/tab-view-filter-field/filter-field-tab-view-content.component.spec.ts @@ -4,7 +4,7 @@ import { ConfigurationService, TestConfigurationService, FilterField, - FilterType, + FieldTypeResource, NAE_FILTER_FIELD, SearchService, NAE_BASE_FILTER, SimpleFilter, BaseFilter } from '@netgrif/components-core'; @@ -16,9 +16,7 @@ describe('FilterFieldTabViewContentComponent', () => { let fixture: ComponentFixture; beforeEach(async () => { - const field = new FilterField('', '', '', { - filterType: FilterType.CASE, predicateMetadata: [], searchCategories: [] - }, [], {}, '', ''); + const field = new FilterField('', '', '', FieldTypeResource.CASE_FILTER, [], {}, '', ''); await TestBed.configureTestingModule({ imports: [ diff --git a/projects/netgrif-components/src/lib/data-fields/multichoice-field/multichoice-caseref-field/multichoice-caseref-field.component.spec.ts b/projects/netgrif-components/src/lib/data-fields/multichoice-field/multichoice-caseref-field/multichoice-caseref-field.component.spec.ts index cdd90f976c..617b4f0e53 100644 --- a/projects/netgrif-components/src/lib/data-fields/multichoice-field/multichoice-caseref-field/multichoice-caseref-field.component.spec.ts +++ b/projects/netgrif-components/src/lib/data-fields/multichoice-field/multichoice-caseref-field/multichoice-caseref-field.component.spec.ts @@ -2,7 +2,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MultichoiceCaserefFieldComponent } from './multichoice-caseref-field.component'; import {NavigationComponentModule} from '../../../navigation/navigation.module'; import { - FilterField, FilterType, MultichoiceField, + FilterField, FieldTypeResource, MultichoiceField, NAE_TAB_DATA, NAE_VIEW_ID_SEGMENT, OverflowService, @@ -47,11 +47,7 @@ describe('MultichoiceCaserefFieldComponent', () => { `${GroupNavigationConstants.ITEM_FIELD_CASE_FILTER}`, '', '', - { - filterType: FilterType.CASE, - predicateMetadata: [], - searchCategories: [] - }, + FieldTypeResource.CASE_FILTER, [], {visible: true}, '', diff --git a/projects/netgrif-components/src/lib/filter-field-content/filter-field-tab-view/filter-field-tab-view.component.spec.ts b/projects/netgrif-components/src/lib/filter-field-content/filter-field-tab-view/filter-field-tab-view.component.spec.ts index abbdc2d29e..93382077e0 100644 --- a/projects/netgrif-components/src/lib/filter-field-content/filter-field-tab-view/filter-field-tab-view.component.spec.ts +++ b/projects/netgrif-components/src/lib/filter-field-content/filter-field-tab-view/filter-field-tab-view.component.spec.ts @@ -3,7 +3,7 @@ import { FilterFieldTabViewComponent } from './filter-field-tab-view.component'; import { ConfigurationService, FilterField, - FilterType, + FieldTypeResource, NAE_FILTER_FIELD, TestConfigurationService } from '@netgrif/components-core'; @@ -15,9 +15,7 @@ describe('FilterFieldTabViewComponent', () => { let fixture: ComponentFixture; beforeEach(async () => { - const field = new FilterField('', '', '', { - filterType: FilterType.CASE, predicateMetadata: [], searchCategories: [] - }, [], {}, '', ''); + const field = new FilterField('', '', '', FieldTypeResource.CASE_FILTER, [], {}, '', ''); await TestBed.configureTestingModule({ imports: [ diff --git a/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/refs/default-case-ref-list-view/default-case-ref-list-view.component.spec.ts b/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/refs/default-case-ref-list-view/default-case-ref-list-view.component.spec.ts index 949b085f87..3407336592 100644 --- a/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/refs/default-case-ref-list-view/default-case-ref-list-view.component.spec.ts +++ b/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/refs/default-case-ref-list-view/default-case-ref-list-view.component.spec.ts @@ -3,7 +3,8 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { DefaultCaseRefListViewComponent } from './default-case-ref-list-view.component'; import {NavigationComponentModule} from '../../../../navigation.module'; import { - FilterField, FilterType, + FilterField, + FieldTypeResource, NAE_TAB_DATA, NAE_VIEW_ID_SEGMENT, OverflowService, @@ -51,11 +52,7 @@ describe('DefaultCaseRefListViewComponent', () => { `${GroupNavigationConstants.ITEM_FIELD_CASE_FILTER}`, '', '', - { - filterType: FilterType.CASE, - predicateMetadata: [], - searchCategories: [] - }, + FieldTypeResource.CASE_FILTER, [], {visible: true}, '', diff --git a/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/simple-views/default-simple-case-view/default-simple-case-view.component.spec.ts b/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/simple-views/default-simple-case-view/default-simple-case-view.component.spec.ts index 73a5bbbabb..15202c606d 100644 --- a/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/simple-views/default-simple-case-view/default-simple-case-view.component.spec.ts +++ b/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/simple-views/default-simple-case-view/default-simple-case-view.component.spec.ts @@ -16,7 +16,7 @@ import { TestMockDependenciesModule, TextField, I18nField, - FilterType, + FieldTypeResource, AuthenticationModule, StringCollectionField, } from '@netgrif/components-core'; @@ -105,11 +105,7 @@ describe('SimpleCaseViewComponent', () => { GroupNavigationConstants.ITEM_FIELD_CASE_FILTER, '', '', - { - filterType: FilterType.CASE, - predicateMetadata: [], - searchCategories: [] - }, + FieldTypeResource.CASE_FILTER, [], {visible: true}, '', diff --git a/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/simple-views/default-simple-task-view/default-simple-task-view.component.spec.ts b/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/simple-views/default-simple-task-view/default-simple-task-view.component.spec.ts index 5448433c7d..146f5f9e16 100644 --- a/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/simple-views/default-simple-task-view/default-simple-task-view.component.spec.ts +++ b/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/simple-views/default-simple-task-view/default-simple-task-view.component.spec.ts @@ -2,7 +2,7 @@ import {ComponentFixture, TestBed} from '@angular/core/testing'; import {DefaultSimpleTaskViewComponent} from './default-simple-task-view.component'; import {NavigationComponentModule} from '../../../../navigation.module'; import { - FilterField, FilterType, TextField, BooleanField, MultichoiceField, EnumerationField, I18nField, + FilterField, FieldTypeResource, TextField, BooleanField, MultichoiceField, EnumerationField, I18nField, NAE_NAVIGATION_ITEM_TASK_DATA, OverflowService, TestMockDependenciesModule, @@ -35,11 +35,7 @@ describe('DefaultSimpleTaskViewComponent', () => { GroupNavigationConstants.ITEM_FIELD_TASK_FILTER, '', '', - { - filterType: FilterType.TASK, - predicateMetadata: [], - searchCategories: [] - }, + FieldTypeResource.CASE_FILTER, [], {visible: true}, '', diff --git a/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/simple-views/default-single-task-view/default-single-task-view.component.spec.ts b/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/simple-views/default-single-task-view/default-single-task-view.component.spec.ts index 6861d12c16..287a62cfd7 100644 --- a/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/simple-views/default-single-task-view/default-single-task-view.component.spec.ts +++ b/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/simple-views/default-single-task-view/default-single-task-view.component.spec.ts @@ -8,8 +8,10 @@ import {RouterTestingModule} from "@angular/router/testing"; import {Observable} from "rxjs"; import { AuthenticationMethodService, - ConfigurationService, FilterType, + ConfigurationService, + FieldTypeResource, MaterialModule, + FilterType, NAE_TAB_DATA, SimpleFilter, TestConfigurationService, GroupNavigationConstants, @@ -46,11 +48,7 @@ describe('DefaultSingleTaskViewComponent', () => { GroupNavigationConstants.ITEM_FIELD_TASK_FILTER, '', '', - { - filterType: FilterType.TASK, - predicateMetadata: [], - searchCategories: [] - }, + FieldTypeResource.CASE_FILTER, [], {visible: true}, '', diff --git a/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/tabbed/default-tab-view/default-tab-view.component.spec.ts b/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/tabbed/default-tab-view/default-tab-view.component.spec.ts index 706313f3b5..07865ba70d 100644 --- a/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/tabbed/default-tab-view/default-tab-view.component.spec.ts +++ b/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/tabbed/default-tab-view/default-tab-view.component.spec.ts @@ -5,7 +5,7 @@ import { BooleanField, EnumerationField, FilterField, - FilterType, + FieldTypeResource, GroupNavigationConstants, I18nField, LanguageService, @@ -149,11 +149,7 @@ describe('DefaultTabViewComponent', () => { GroupNavigationConstants.ITEM_FIELD_TASK_FILTER, '', '', - { - filterType: FilterType.TASK, - predicateMetadata: [], - searchCategories: [] - }, + FieldTypeResource.CASE_FILTER, [], {visible: true}, '', @@ -167,11 +163,7 @@ describe('DefaultTabViewComponent', () => { GroupNavigationConstants.ITEM_FIELD_CASE_FILTER, '', '', - { - filterType: FilterType.CASE, - predicateMetadata: [], - searchCategories: [] - }, + FieldTypeResource.CASE_FILTER, [], {visible: true}, '', diff --git a/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/tabbed/default-tabbed-case-view/default-tabbed-case-view.component.spec.ts b/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/tabbed/default-tabbed-case-view/default-tabbed-case-view.component.spec.ts index 634dca0322..ac8fefd64b 100644 --- a/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/tabbed/default-tabbed-case-view/default-tabbed-case-view.component.spec.ts +++ b/projects/netgrif-components/src/lib/navigation/group-navigation-component-resolver/default-components/tabbed/default-tabbed-case-view/default-tabbed-case-view.component.spec.ts @@ -4,7 +4,7 @@ import {NavigationComponentModule} from '../../../../navigation.module'; import { BooleanField, FilterField, - FilterType, + FieldTypeResource, GroupNavigationConstants, HeaderMode, NAE_NAVIGATION_ITEM_TASK_DATA, @@ -63,11 +63,7 @@ describe('DefaultTabbedCaseViewComponent', () => { `${GroupNavigationConstants.ITEM_FIELD_CASE_FILTER}`, '', '', - { - filterType: FilterType.CASE, - predicateMetadata: [], - searchCategories: [] - }, + FieldTypeResource.CASE_FILTER, [], {visible: true}, '', diff --git a/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text-content/immediate-filter-text-content.component.spec.ts b/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text-content/immediate-filter-text-content.component.spec.ts index 29d1d4f1dd..ce879ea841 100644 --- a/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text-content/immediate-filter-text-content.component.spec.ts +++ b/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text-content/immediate-filter-text-content.component.spec.ts @@ -6,7 +6,7 @@ import { TestConfigurationService, ConfigurationService, NAE_FILTER_TEXT, - FilterType + FilterType, AllowedNetsService } from '@netgrif/components-core'; import {HttpClientTestingModule} from '@angular/common/http/testing'; @@ -24,6 +24,7 @@ describe('ImmediateFilterTextContentComponent', () => { ], providers: [ {provide: ConfigurationService, useClass: TestConfigurationService}, + AllowedNetsService, { provide: NAE_FILTER_TEXT, useValue: { diff --git a/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text/immediate-filter-text.component.spec.ts b/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text/immediate-filter-text.component.spec.ts index 7d64a2be12..a70a899ecd 100644 --- a/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text/immediate-filter-text.component.spec.ts +++ b/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text/immediate-filter-text.component.spec.ts @@ -3,9 +3,7 @@ import {ImmediateFilterTextComponent} from './immediate-filter-text.component'; import { MaterialModule, ConfigurationService, - TestConfigurationService, - FilterMetadataAllowedNets, - FilterType + TestConfigurationService, AllowedNetsService, } from '@netgrif/components-core'; import {PanelComponentModule} from '../../panel.module'; import {Component} from '@angular/core'; @@ -21,6 +19,7 @@ describe('ImmediateFilterTextComponent', () => { MaterialModule, PanelComponentModule ], providers: [ + AllowedNetsService, {provide: ConfigurationService, useClass: TestConfigurationService}, ] }) @@ -44,19 +43,10 @@ describe('ImmediateFilterTextComponent', () => { @Component({ selector: 'nc-test-wrapper', - template: '' + template: '' }) class TestWrapperComponent { - public filterMetadata: FilterMetadataAllowedNets = { - allowedNets: [], - filterMetadata: { - predicateMetadata: [], - filterType: FilterType.CASE, - searchCategories: [] - } - }; - constructor() { } } From c4855249a855e4202750bef3b07cbca0b8c9b4ca Mon Sep 17 00:00:00 2001 From: chvostek Date: Tue, 1 Sep 2026 16:45:02 +0200 Subject: [PATCH 42/55] [NAE-2466] Advanced search for PFQL - fix tests --- .../filter-default-field.component.spec.ts | 4 +++- .../filter-field-content.component.spec.ts | 9 +++++---- ...immediate-filter-text-content.component.spec.ts | 14 +++++++------- .../immediate-filter-text.component.spec.ts | 4 ++-- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-default-field/filter-default-field.component.spec.ts b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-default-field/filter-default-field.component.spec.ts index 27d4f31ed3..c11816d6cd 100644 --- a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-default-field/filter-default-field.component.spec.ts +++ b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-default-field/filter-default-field.component.spec.ts @@ -14,6 +14,7 @@ import {RequiredLabelComponent} from "../../required-label/required-label.compon import {FilterFieldComponent} from "../filter-field.component"; import {FilterFieldContentComponent} from "../filter-field-content/filter-field-content.component"; import {FormControl} from "@angular/forms"; +import {NoopAnimationsModule} from "@angular/platform-browser/animations"; describe('FilterDefaultFieldComponent', () => { let component: FilterDefaultFieldComponent; @@ -24,7 +25,8 @@ describe('FilterDefaultFieldComponent', () => { imports: [ MaterialModule, AdvancedSearchComponentModule, - HttpClientTestingModule + HttpClientTestingModule, + NoopAnimationsModule, ], providers: [ {provide: ConfigurationService, useClass: TestConfigurationService}, diff --git a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.spec.ts b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.spec.ts index 0a322feea4..c8d0198b66 100644 --- a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.spec.ts +++ b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.spec.ts @@ -3,9 +3,10 @@ import {FilterFieldContentComponent} from './filter-field-content.component'; import {HttpClientTestingModule} from '@angular/common/http/testing'; import { ConfigurationService, TestConfigurationService, FilterField, FieldTypeResource, NAE_FILTER_FIELD, - NAE_DEFAULT_CASE_SEARCH_CATEGORIES, NAE_DEFAULT_TASK_SEARCH_CATEGORIES + DefaultSearchCategoriesModule } from '@netgrif/components-core'; import {AdvancedSearchComponentModule} from '../../../search/advanced-search/advanced-search.module'; +import {NoopAnimationsModule} from "@angular/platform-browser/animations"; describe('FilterFieldContentComponent', () => { let component: FilterFieldContentComponent; @@ -17,13 +18,13 @@ describe('FilterFieldContentComponent', () => { await TestBed.configureTestingModule({ imports: [ AdvancedSearchComponentModule, - HttpClientTestingModule + HttpClientTestingModule, + DefaultSearchCategoriesModule, + NoopAnimationsModule, ], providers: [ {provide: ConfigurationService, useClass: TestConfigurationService}, {provide: NAE_FILTER_FIELD, useValue: field}, - NAE_DEFAULT_CASE_SEARCH_CATEGORIES, - NAE_DEFAULT_TASK_SEARCH_CATEGORIES ], declarations: [ FilterFieldContentComponent diff --git a/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text-content/immediate-filter-text-content.component.spec.ts b/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text-content/immediate-filter-text-content.component.spec.ts index ce879ea841..4a17860bca 100644 --- a/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text-content/immediate-filter-text-content.component.spec.ts +++ b/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text-content/immediate-filter-text-content.component.spec.ts @@ -6,7 +6,9 @@ import { TestConfigurationService, ConfigurationService, NAE_FILTER_TEXT, - FilterType, AllowedNetsService + AllowedNetsService, + TestNoAllowedNetsFactory, + AllowedNetsServiceFactory } from '@netgrif/components-core'; import {HttpClientTestingModule} from '@angular/common/http/testing'; @@ -24,15 +26,13 @@ describe('ImmediateFilterTextContentComponent', () => { ], providers: [ {provide: ConfigurationService, useClass: TestConfigurationService}, - AllowedNetsService, + {provide: AllowedNetsService, useFactory: TestNoAllowedNetsFactory, deps: [AllowedNetsServiceFactory]}, { provide: NAE_FILTER_TEXT, useValue: { - metadata: { - allowedNets: [], filterMetadata: { - filterType: FilterType.CASE, predicateMetadata: [], searchCategories: [] - } - }, ellipsis: true + query: 'cases: creationDate eq 2026-09-01', + type: 'case', + ellipsis: true } }, ] diff --git a/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text/immediate-filter-text.component.spec.ts b/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text/immediate-filter-text.component.spec.ts index a70a899ecd..e869faa75d 100644 --- a/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text/immediate-filter-text.component.spec.ts +++ b/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text/immediate-filter-text.component.spec.ts @@ -3,7 +3,7 @@ import {ImmediateFilterTextComponent} from './immediate-filter-text.component'; import { MaterialModule, ConfigurationService, - TestConfigurationService, AllowedNetsService, + TestConfigurationService, AllowedNetsService, TestNoAllowedNetsFactory, AllowedNetsServiceFactory, } from '@netgrif/components-core'; import {PanelComponentModule} from '../../panel.module'; import {Component} from '@angular/core'; @@ -19,7 +19,7 @@ describe('ImmediateFilterTextComponent', () => { MaterialModule, PanelComponentModule ], providers: [ - AllowedNetsService, + {provide: AllowedNetsService, useFactory: TestNoAllowedNetsFactory, deps: [AllowedNetsServiceFactory]}, {provide: ConfigurationService, useClass: TestConfigurationService}, ] }) From 18668660b89a3477fe9dbae709cf7ec74186181d Mon Sep 17 00:00:00 2001 From: chvostek Date: Tue, 1 Sep 2026 18:04:44 +0200 Subject: [PATCH 43/55] [NAE-2466] Advanced search for PFQL - add search service test --- .../search-service/search.service.spec.ts | 131 +++++++++--------- 1 file changed, 64 insertions(+), 67 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts index 660e994ac0..0fba32a14f 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts @@ -1,4 +1,4 @@ -import {TestBed} from '@angular/core/testing'; +import {TestBed, waitForAsync} from '@angular/core/testing'; import {SearchService} from './search.service'; import {NoopAnimationsModule} from '@angular/platform-browser/animations'; import {CategoryFactory} from '../category-factory/category-factory'; @@ -10,13 +10,20 @@ import {NAE_BASE_FILTER} from '../models/base-filter-injection-token'; import {TestCaseBaseFilterProvider, TestNoAllowedNetsFactory} from '../../utility/tests/test-factory-methods'; import {AllowedNetsService} from '../../allowed-nets/services/allowed-nets.service'; import {AllowedNetsServiceFactory} from '../../allowed-nets/services/factory/allowed-nets-service-factory'; -import {CaseCreationDate} from '../models/category/case/case-creation-date'; -import moment from 'moment'; import {CaseSearchRequestBody} from '../../filter/models/case-search-request-body'; import {FilterType} from '../../filter/models/filter-type'; import {of} from 'rxjs'; import {SimpleFilter} from '../../filter/models/simple-filter'; import {PetriNetRequestBody} from '../../resources/interface/petri-net-request-body'; +import {TaskSearchRequestBody} from "../../filter/models/task-search-request-body"; +import { + AuthenticationMethodService, + MockAuthenticationMethodService, + MockUserService, + User, + UserService +} from "@netgrif/components-core"; +import {Injectable} from "@angular/core"; describe('SearchService', () => { let service: SearchService; @@ -33,11 +40,10 @@ describe('SearchService', () => { providers: [ CategoryFactory, SearchService, - { - provide: NAE_BASE_FILTER, - useFactory: TestCaseBaseFilterProvider - }, + {provide: NAE_BASE_FILTER, useFactory: TestCaseBaseFilterProvider}, {provide: ConfigurationService, useClass: TestConfigurationService}, + {provide: AuthenticationMethodService, useClass: MockAuthenticationMethodService}, + {provide: UserService, useClass: CustomMockUserService}, {provide: AllowedNetsService, useFactory: TestNoAllowedNetsFactory, deps: [AllowedNetsServiceFactory]} ] }); @@ -74,66 +80,41 @@ describe('SearchService', () => { expect(service.rootPredicate.getPredicateMap().get(id)).toBeTruthy(); }); - // todo 2466 major test for pfql loading - // describe('serialization / deserialization', () => { - // let serializedSearch: FilterMetadata; - // - // beforeEach(() => { - // const predicate1 = categoryFactory.getWithDefaultOperator(CaseTitle); - // predicate1.setOperands(['title']); - // - // const predicate2 = categoryFactory.getWithDefaultOperator(CaseCreationDate); - // predicate2.setOperands([moment('2021-03-31').valueOf()]); - // - // const meta1 = predicate1.createMetadata(); - // expect(meta1).toBeTruthy(); - // const meta2 = predicate2.createMetadata(); - // expect(meta2).toBeTruthy(); - // - // serializedSearch = { - // filterType: FilterType.CASE, - // predicateMetadata: [[meta1, meta2]], - // searchCategories: [] // they don't play a role for this test - // }; - // }); - // - // it('should deserialize saved search', (done) => { - // expect(service.additionalFiltersApplied).toBeFalse(); - // - // service.loadFromMetadata(serializedSearch); - // service.activeFilter$.subscribe(f => { - // expect(service.additionalFiltersApplied).toBeTrue(); - // - // expect(f).toBeTruthy(); - // const filters = f.getRequestBody() as Array; - // expect(Array.isArray(filters)).toBeTrue(); - // expect(filters.length).toBe(2); - // expect(filters[0]).toEqual({}); - // expect(filters[1].query).toBeTruthy(); - // - // done(); - // }); - // }); - // - // it('should serialize search', (done) => { - // expect(service.additionalFiltersApplied).toBeFalse(); - // - // service.loadFromMetadata(serializedSearch); - // service.activeFilter$.subscribe(f => { - // expect(service.additionalFiltersApplied).toBeTrue(); - // - // const serialized = service.createPredicateMetadata(); - // expect(serialized).toBeTruthy(); - // expect(serialized).toEqual(serializedSearch.predicateMetadata); - // - // done(); - // }); - // }); - // - // afterEach(() => { - // TestBed.resetTestingModule(); - // }); - // }); + it('should load pfql query in case category', (done) => { + expect(service.additionalFiltersApplied).toBeFalse(); + + service.loadFromPfql('cases: title neq \'someOtherTitle\''); + service.activeFilter$.subscribe(f => { + expect(service.additionalFiltersApplied).toBeTrue(); + + expect(f).toBeTruthy(); + const filters = f.getRequestBody() as Array; + expect(Array.isArray(filters)).toBeTrue(); + expect(filters.length).toBe(2); + expect(filters[0]).toEqual({}); + expect(filters[1].query).toEqual('cases: title neq \'someOtherTitle\''); + + done(); + }); + }); + + it('should load pfql query in task category', (done) => { + expect(service.additionalFiltersApplied).toBeFalse(); + + service.loadFromPfql('tasks: title eq \'myTitle\''); + service.activeFilter$.subscribe(f => { + expect(service.additionalFiltersApplied).toBeTrue(); + + expect(f).toBeTruthy(); + const filters = f.getRequestBody() as Array; + expect(Array.isArray(filters)).toBeTrue(); + expect(filters.length).toBe(2); + expect(filters[0]).toEqual({}); + expect(filters[1].query).toEqual('tasks: title eq \'myTitle\''); + + done(); + }); + }); afterEach(() => { TestBed.resetTestingModule(); @@ -190,3 +171,19 @@ describe('SearchService', () => { TestBed.resetTestingModule(); }); }); + +@Injectable() +class CustomMockUserService extends MockUserService { + constructor() { + super(); + this._user = new User('123', 'test@netgrif.com', 'Test', 'User', ['ROLE_USER'], [{ + stringId: 'id', + name: 'id', + description: '', + importId: 'id', + netImportId: 'identifier', + netVersion: '1.0.0', + netStringId: 'stringId', + }]); + } +} From aa01a02f9f31b9369daa9bccc4870a9c5ec122af Mon Sep 17 00:00:00 2001 From: chvostek Date: Tue, 1 Sep 2026 18:05:21 +0200 Subject: [PATCH 44/55] [NAE-2466] Advanced search for PFQL - remove unwanted import --- .../src/lib/search/search-service/search.service.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts index 0fba32a14f..1003a9c668 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts @@ -1,4 +1,4 @@ -import {TestBed, waitForAsync} from '@angular/core/testing'; +import {TestBed} from '@angular/core/testing'; import {SearchService} from './search.service'; import {NoopAnimationsModule} from '@angular/platform-browser/animations'; import {CategoryFactory} from '../category-factory/category-factory'; From 45efdf656d9cd8fab5226a79adf31a8dd9ca4e59 Mon Sep 17 00:00:00 2001 From: chvostek Date: Tue, 1 Sep 2026 20:58:54 +0200 Subject: [PATCH 45/55] [NAE-2466] Advanced search for PFQL - fix after merge --- .../src/lib/header/models/meta-fields-factory.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/projects/netgrif-components-core/src/lib/header/models/meta-fields-factory.ts b/projects/netgrif-components-core/src/lib/header/models/meta-fields-factory.ts index 9da3c1f3a3..0a8760808f 100644 --- a/projects/netgrif-components-core/src/lib/header/models/meta-fields-factory.ts +++ b/projects/netgrif-components-core/src/lib/header/models/meta-fields-factory.ts @@ -6,7 +6,6 @@ import {WorkflowMetaField} from "../workflow-header/workflow-meta-enum"; /** Returns meta-headers for case view */ export function getCaseMetaHeaders(): HeaderColumn[] { return [ - new HeaderColumn(HeaderColumnType.META, CaseMetaField.VISUAL_ID, 'headers.caseMeta.visualID', 'text'), new HeaderColumn(HeaderColumnType.META, CaseMetaField.MONGO_ID, 'headers.caseMeta.mongoID', 'text', false), new HeaderColumn(HeaderColumnType.META, CaseMetaField.TITLE, 'headers.caseMeta.title', 'text'), new HeaderColumn(HeaderColumnType.META, CaseMetaField.AUTHOR, 'headers.caseMeta.author', 'user'), From b8fe6046f78632023e49cf9ddebe55aad3b092be Mon Sep 17 00:00:00 2001 From: chvostek Date: Wed, 2 Sep 2026 19:17:42 +0200 Subject: [PATCH 46/55] [NAE-2466] Advanced search for PFQL - rework dependency injection for PFQL components --- .../src/lib/pfql/pfql-utils.ts | 7 +-- .../src/lib/pfql/pfql-visitor.ts | 25 ++++----- .../search-service/search.service.spec.ts | 56 ++++++++++++++++--- .../search/search-service/search.service.ts | 7 ++- .../mock-authentication-method-service.ts | 2 + .../filter-field-content.component.ts | 6 +- 6 files changed, 70 insertions(+), 33 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts b/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts index 848280abbb..3310cbbf46 100644 --- a/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts +++ b/projects/netgrif-components-core/src/lib/pfql/pfql-utils.ts @@ -32,18 +32,17 @@ import {LoggerService} from "../logger/services/logger.service"; * Parses a PFQL query string into an array of query items. * * @param query - The PFQL query string to parse - * @param injector - Angular injector used for dependency injection during parsing + * @param logger - logger service to log messages + * @param visitor - service to parse a query tree into QueryItems * @returns An array of QueryItem objects representing the parsed query structure */ -export function parseQuery(query: string, injector: Injector): Array { - const logger = injector.get(LoggerService); +export function parseQuery(query: string, logger: LoggerService, visitor: PfqlVisitor): Array { try { const inputStream = CharStream.fromString(query); const lexer = new QueryLangLexer(inputStream); const tokenStream = new CommonTokenStream(lexer); const parser = new QueryLangParser(tokenStream); const tree = parser.query(); - const visitor = new PfqlVisitor(injector); let items: Array = visitor.visit(tree); return reduceComplexToSimpleExpressions(items); diff --git a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts index 52768c916c..ae47b0e501 100644 --- a/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts +++ b/projects/netgrif-components-core/src/lib/pfql/pfql-visitor.ts @@ -45,7 +45,7 @@ import { } from "./generated/QueryLangParser"; import {LoggerService} from "../logger/services/logger.service"; import {CaseTitle} from "../search/models/category/case/case-title"; -import {Injector} from "@angular/core"; +import {Injectable, Inject, Optional} from "@angular/core"; import {OperatorService} from "../search/operator-service/operator.service"; import {QueryItem} from "./model/query-item-type"; import {LogicalOperator} from "./model/logical-operator"; @@ -91,30 +91,25 @@ import {NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY} from "../search/category-facto * - Multiple comparison operators (equality, ranges, null checks, like patterns) * - Data field queries with type-specific comparisons */ +@Injectable() export class PfqlVisitor extends QueryLangVisitor> { - protected _logger: LoggerService; - protected _operatorService: OperatorService - protected _userResourceService: UserResourceService; - protected _userService: UserService; - protected _categoryFactory: CategoryFactory; - protected _allowedNetsService: AllowedNetsService; protected _categoryOptionalDependencies: OptionalDependencies; - public constructor(injector: Injector) { + public constructor(protected _logger: LoggerService, + protected _operatorService: OperatorService, + protected _userResourceService: UserResourceService, + protected _userService: UserService, + protected _categoryFactory: CategoryFactory, + protected _allowedNetsService: AllowedNetsService, + @Optional() @Inject(NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY) ignoreNetsOnAutocompleteCategory: boolean) { super(); - this._logger = injector.get(LoggerService); - this._operatorService = injector.get(OperatorService); - this._userResourceService = injector.get(UserResourceService); - this._userService = injector.get(UserService); - this._categoryFactory = injector.get(CategoryFactory); - this._allowedNetsService = injector.get(AllowedNetsService); this._categoryOptionalDependencies = { categoryFactory: this._categoryFactory, searchIndexResolver: undefined, allowedNetsService: this._allowedNetsService, userResourceService: this._userResourceService, - ignoreNetsOnAutocompleteCategories: injector.get(NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY), + ignoreNetsOnAutocompleteCategories: ignoreNetsOnAutocompleteCategory, }; } diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts index 1003a9c668..5d17c1906f 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts @@ -7,7 +7,11 @@ import {ConfigurationService} from '../../configuration/configuration.service'; import {TestConfigurationService} from '../../utility/tests/test-config'; import {HttpClientTestingModule} from '@angular/common/http/testing'; import {NAE_BASE_FILTER} from '../models/base-filter-injection-token'; -import {TestCaseBaseFilterProvider, TestNoAllowedNetsFactory} from '../../utility/tests/test-factory-methods'; +import { + TestCaseBaseFilterProvider, + TestNoAllowedNetsFactory, + TestTaskBaseFilterProvider, +} from '../../utility/tests/test-factory-methods'; import {AllowedNetsService} from '../../allowed-nets/services/allowed-nets.service'; import {AllowedNetsServiceFactory} from '../../allowed-nets/services/factory/allowed-nets-service-factory'; import {CaseSearchRequestBody} from '../../filter/models/case-search-request-body'; @@ -17,32 +21,34 @@ import {SimpleFilter} from '../../filter/models/simple-filter'; import {PetriNetRequestBody} from '../../resources/interface/petri-net-request-body'; import {TaskSearchRequestBody} from "../../filter/models/task-search-request-body"; import { - AuthenticationMethodService, - MockAuthenticationMethodService, MockUserService, User, UserService } from "@netgrif/components-core"; import {Injectable} from "@angular/core"; +import {PfqlVisitor} from "../../pfql/pfql-visitor"; +import {AuthenticationModule} from "../../authentication/authentication.module"; +import {NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY} from "../category-factory/search-categories-injection-token"; describe('SearchService', () => { let service: SearchService; let categoryFactory: CategoryFactory; - describe('with static base filter', () => { + describe('with static case base filter', () => { beforeEach(() => { TestBed.configureTestingModule({ imports: [ NoopAnimationsModule, - HttpClientTestingModule + HttpClientTestingModule, + AuthenticationModule ], providers: [ CategoryFactory, SearchService, + PfqlVisitor, {provide: NAE_BASE_FILTER, useFactory: TestCaseBaseFilterProvider}, {provide: ConfigurationService, useClass: TestConfigurationService}, - {provide: AuthenticationMethodService, useClass: MockAuthenticationMethodService}, {provide: UserService, useClass: CustomMockUserService}, {provide: AllowedNetsService, useFactory: TestNoAllowedNetsFactory, deps: [AllowedNetsServiceFactory]} ] @@ -98,10 +104,39 @@ describe('SearchService', () => { }); }); + afterEach(() => { + TestBed.resetTestingModule(); + }); + }); + + describe('with static task base filter', () => { + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + NoopAnimationsModule, + HttpClientTestingModule, + AuthenticationModule + ], + providers: [ + CategoryFactory, + SearchService, + PfqlVisitor, + {provide: NAE_BASE_FILTER, useFactory: TestTaskBaseFilterProvider}, + {provide: ConfigurationService, useClass: TestConfigurationService}, + {provide: UserService, useClass: CustomMockUserService}, + {provide: NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY, useValue: true}, + {provide: AllowedNetsService, useFactory: TestNoAllowedNetsFactory, deps: [AllowedNetsServiceFactory]} + ] + }); + service = TestBed.inject(SearchService); + categoryFactory = TestBed.inject(CategoryFactory); + }); + it('should load pfql query in task category', (done) => { expect(service.additionalFiltersApplied).toBeFalse(); - service.loadFromPfql('tasks: title eq \'myTitle\''); + service.loadFromPfql('tasks: transitionId eq \'myTransition\''); service.activeFilter$.subscribe(f => { expect(service.additionalFiltersApplied).toBeTrue(); @@ -110,7 +145,7 @@ describe('SearchService', () => { expect(Array.isArray(filters)).toBeTrue(); expect(filters.length).toBe(2); expect(filters[0]).toEqual({}); - expect(filters[1].query).toEqual('tasks: title eq \'myTitle\''); + expect(filters[1].query).toEqual('tasks: transitionId eq \'myTransition\''); done(); }); @@ -127,16 +162,19 @@ describe('SearchService', () => { TestBed.configureTestingModule({ imports: [ NoopAnimationsModule, - HttpClientTestingModule + HttpClientTestingModule, + AuthenticationModule ], providers: [ CategoryFactory, SearchService, + PfqlVisitor, { provide: NAE_BASE_FILTER, useValue: {filter: of(SimpleFilter.emptyCaseFilter()), filterType: FilterType.CASE} }, {provide: ConfigurationService, useClass: TestConfigurationService}, + {provide: UserService, useClass: CustomMockUserService}, {provide: AllowedNetsService, useFactory: TestNoAllowedNetsFactory, deps: [AllowedNetsServiceFactory]} ] }); diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts index 0afcccfac4..d00deda301 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.ts @@ -25,6 +25,7 @@ import {ResourceTypeQueryPrefix} from "../models/category/resource-type-query-pr import {RawExpression} from "../../pfql/model/raw-expression"; import {PlainQueryCategory} from "../models/category/plain-query-category"; import { NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY } from "../category-factory/search-categories-injection-token"; +import { PfqlVisitor } from "../../pfql/pfql-visitor"; /** * Holds information about the filter that is currently applied to the view component, that provides this services. @@ -69,13 +70,13 @@ export class SearchService implements OnDestroy { * Injected trough the {@link NAE_BASE_FILTER} injection token. * @param _ignoreNetsOnAutocompleteCategories boolean flag that determines whether net-related categories should be ignored * when providing autocomplete suggestions. Injected through the {@link NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY} injection token. - * @param _injector injector from angular core + * @param _visitor service to parse query tree into QueryItems */ constructor(protected _log: LoggerService, @Optional() protected _categoryFactory: CategoryFactory, @Inject(NAE_BASE_FILTER) baseFilter: BaseFilter, @Optional() @Inject(NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY) protected _ignoreNetsOnAutocompleteCategories: boolean, - protected _injector: Injector) { + @Optional() protected _visitor: PfqlVisitor) { if (baseFilter.filter instanceof Filter) { this._baseFilter = baseFilter.filter.clone(); } else if (baseFilter.filter instanceof Observable) { @@ -350,7 +351,7 @@ export class SearchService implements OnDestroy { this._loadingFromPfql$.on(); this.clearPredicates(true, false); - const queryItems: Array = parseQuery(query, this._injector); + const queryItems: Array = parseQuery(query, this._log, this._visitor); if (!queryItems) { this._log.warn(`Could not parse query '${query}. Clearing the search...`) return; diff --git a/projects/netgrif-components-core/src/lib/utility/tests/mocks/mock-authentication-method-service.ts b/projects/netgrif-components-core/src/lib/utility/tests/mocks/mock-authentication-method-service.ts index 632356d356..696a2a2571 100644 --- a/projects/netgrif-components-core/src/lib/utility/tests/mocks/mock-authentication-method-service.ts +++ b/projects/netgrif-components-core/src/lib/utility/tests/mocks/mock-authentication-method-service.ts @@ -2,7 +2,9 @@ import {Observable, of} from 'rxjs'; import {AuthenticationMethodService} from '../../../authentication/services/authentication-method.service'; import {Credentials} from '../../../authentication/models/credentials'; import {UserResource} from '../../../resources/interface/user-resource'; +import {Injectable} from "@angular/core"; +@Injectable() export class MockAuthenticationMethodService extends AuthenticationMethodService { login(credentials: Credentials): Observable { return of({email: 'mail', id: 'id', name: 'name', surname: 'surname', fullName: 'name surname', diff --git a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.ts b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.ts index 318c50d14f..149f0cb323 100644 --- a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.ts @@ -16,7 +16,8 @@ import { FieldTypeResource, NAE_DEFAULT_CASE_SEARCH_CATEGORIES, NAE_DEFAULT_TASK_SEARCH_CATEGORIES, - NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY + NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY, + PfqlVisitor } from '@netgrif/components-core'; export function filterFieldBaseFilterFactory(filterField: FilterField): BaseFilter { @@ -56,7 +57,8 @@ export function filterFieldCategoriesFactory(filterField: FilterField, caseCateg CategoryFactory, {provide: NAE_SEARCH_CATEGORIES, useFactory: filterFieldCategoriesFactory, deps: [NAE_FILTER_FIELD, NAE_DEFAULT_CASE_SEARCH_CATEGORIES, NAE_DEFAULT_TASK_SEARCH_CATEGORIES]}, - SearchService + SearchService, + PfqlVisitor ] }) export class FilterFieldContentComponent extends AbstractFilterFieldContentComponent { From e304ab6c9e075f77d77fd537959f2659698617d5 Mon Sep 17 00:00:00 2001 From: chvostek Date: Wed, 2 Sep 2026 21:04:01 +0200 Subject: [PATCH 47/55] [NAE-2466] Advanced search for PFQL - fix tests --- .../search-service/search.service.spec.ts | 10 +++++--- .../filter-field-content.component.spec.ts | 23 ++++++++++++++++++- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts b/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts index 5d17c1906f..b95a5d3317 100644 --- a/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts +++ b/projects/netgrif-components-core/src/lib/search/search-service/search.service.spec.ts @@ -29,6 +29,7 @@ import {Injectable} from "@angular/core"; import {PfqlVisitor} from "../../pfql/pfql-visitor"; import {AuthenticationModule} from "../../authentication/authentication.module"; import {NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY} from "../category-factory/search-categories-injection-token"; +import {RouterTestingModule} from "@angular/router/testing"; describe('SearchService', () => { let service: SearchService; @@ -41,7 +42,8 @@ describe('SearchService', () => { imports: [ NoopAnimationsModule, HttpClientTestingModule, - AuthenticationModule + AuthenticationModule, + RouterTestingModule.withRoutes([]), ], providers: [ CategoryFactory, @@ -116,7 +118,8 @@ describe('SearchService', () => { imports: [ NoopAnimationsModule, HttpClientTestingModule, - AuthenticationModule + AuthenticationModule, + RouterTestingModule.withRoutes([]), ], providers: [ CategoryFactory, @@ -163,7 +166,8 @@ describe('SearchService', () => { imports: [ NoopAnimationsModule, HttpClientTestingModule, - AuthenticationModule + AuthenticationModule, + RouterTestingModule.withRoutes([]), ], providers: [ CategoryFactory, diff --git a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.spec.ts b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.spec.ts index c8d0198b66..cd89157e32 100644 --- a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.spec.ts +++ b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.spec.ts @@ -3,10 +3,12 @@ import {FilterFieldContentComponent} from './filter-field-content.component'; import {HttpClientTestingModule} from '@angular/common/http/testing'; import { ConfigurationService, TestConfigurationService, FilterField, FieldTypeResource, NAE_FILTER_FIELD, - DefaultSearchCategoriesModule + DefaultSearchCategoriesModule, UserService, MockUserService, User, AuthenticationModule } from '@netgrif/components-core'; import {AdvancedSearchComponentModule} from '../../../search/advanced-search/advanced-search.module'; import {NoopAnimationsModule} from "@angular/platform-browser/animations"; +import {Injectable} from "@angular/core"; +import {RouterTestingModule} from "@angular/router/testing"; describe('FilterFieldContentComponent', () => { let component: FilterFieldContentComponent; @@ -21,10 +23,13 @@ describe('FilterFieldContentComponent', () => { HttpClientTestingModule, DefaultSearchCategoriesModule, NoopAnimationsModule, + AuthenticationModule, + RouterTestingModule.withRoutes([]), ], providers: [ {provide: ConfigurationService, useClass: TestConfigurationService}, {provide: NAE_FILTER_FIELD, useValue: field}, + {provide: UserService, useClass: CustomMockUserService}, ], declarations: [ FilterFieldContentComponent @@ -46,3 +51,19 @@ describe('FilterFieldContentComponent', () => { expect(component).toBeTruthy(); }); }); + +@Injectable() +class CustomMockUserService extends MockUserService { + constructor() { + super(); + this._user = new User('123', 'test@netgrif.com', 'Test', 'User', ['ROLE_USER'], [{ + stringId: 'id', + name: 'id', + description: '', + importId: 'id', + netImportId: 'identifier', + netVersion: '1.0.0', + netStringId: 'stringId', + }]); + } +} From eebc85d89b949f20d76d5e96766bdd6e448b70fa Mon Sep 17 00:00:00 2001 From: chvostek Date: Wed, 2 Sep 2026 21:18:47 +0200 Subject: [PATCH 48/55] [NAE-2466] Advanced search for PFQL - update maximumError to 6.5 MB --- angular.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/angular.json b/angular.json index aad715ac92..5b2b0c4efd 100644 --- a/angular.json +++ b/angular.json @@ -171,7 +171,7 @@ { "type": "initial", "maximumWarning": "2mb", - "maximumError": "6mb" + "maximumError": "6.5mb" }, { "type": "anyComponentStyle", From f4c719edda696f12dd578ae107ccac4383a29f09 Mon Sep 17 00:00:00 2001 From: chvostek Date: Thu, 3 Sep 2026 15:35:01 +0200 Subject: [PATCH 49/55] [NAE-2466] Advanced search for PFQL - fix behavior for advanced search field content --- .../abstract-filter-field-content.component.ts | 12 ++++++++---- ...stract-filter-field-tab-view-content.component.ts | 8 +++++--- .../filter-field-content.component.ts | 10 ++++++---- .../filter-field-tab-view-content.component.ts | 9 +++++---- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-content.component.ts b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-content.component.ts index 5eecb790f2..21c8acb78e 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-content.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-content.component.ts @@ -1,23 +1,27 @@ -import {Component, Inject, OnDestroy} from '@angular/core'; +import {Component, Inject, OnDestroy, Optional} from '@angular/core'; import {NAE_FILTER_FIELD} from './models/filter-field-injection-token'; import {FilterField} from './models/filter-field'; import {SearchService} from '../../search/search-service/search.service'; import {filter, take} from 'rxjs/operators'; import {Subscription, Observable} from 'rxjs'; import {Query} from "../../search/models/query/query"; +import {AbstractBaseDataFieldComponent} from "../base-component/abstract-base-data-field.component"; +import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../models/data-field-portal-data-injection-token"; @Component({ selector: 'ncc-abstract-filtercontent-field', template: '' }) -export abstract class AbstractFilterFieldContentComponent implements OnDestroy { +export abstract class AbstractFilterFieldContentComponent extends AbstractBaseDataFieldComponent implements OnDestroy { public filterLoaded = false; private readonly _searchServiceSub: Subscription; protected constructor(@Inject(NAE_FILTER_FIELD) protected _filterField: FilterField, - protected _fieldSearchService: SearchService) { + protected _fieldSearchService: SearchService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { + super(dataFieldPortalData); this._fieldSearchService.loadFromPfql(this._filterField.value); this._searchServiceSub = this._fieldSearchService.loadingFromPfql$.pipe(filter(loading => !loading), take(1)).subscribe(() => { this.filterLoaded = true; @@ -25,7 +29,7 @@ export abstract class AbstractFilterFieldContentComponent implements OnDestroy { } public get editable(): boolean { - return !!this._filterField.behavior.editable; + return !!this._filterField.behavior.editable && !this.formControlRef.disabled; } ngOnDestroy(): void { diff --git a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view-content.component.ts b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view-content.component.ts index 6cb7bbeead..0f2e8bf5ec 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view-content.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view-content.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component, Inject, Injector} from '@angular/core'; +import { AfterViewInit, Component, Inject, Injector, Optional } from '@angular/core'; import { ComponentPortal } from '@angular/cdk/portal'; import { FilterField } from './models/filter-field'; import { NAE_BASE_FILTER } from '../../search/models/base-filter-injection-token'; @@ -12,6 +12,7 @@ import { NAE_FILTER_FIELD } from './models/filter-field-injection-token'; import { SearchService } from '../../search/search-service/search.service'; import { AbstractFilterFieldContentComponent } from './abstract-filter-field-content.component'; import {ComponentRegistryService} from "../../registry/component-registry.service"; +import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../models/data-field-portal-data-injection-token"; @Component({ selector: 'ncc-abstract-filter-field-tab-view-content', @@ -24,8 +25,9 @@ export abstract class AbstractFilterFieldTabViewContentComponent extends Abstrac protected constructor(protected registry: ComponentRegistryService, protected injector: Injector, @Inject(NAE_FILTER_FIELD) filterField: FilterField, - searchService: SearchService) { - super(filterField, searchService) + searchService: SearchService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { + super(filterField, searchService, dataFieldPortalData) } ngAfterViewInit(): void { diff --git a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.ts b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.ts index 149f0cb323..283961c4fb 100644 --- a/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/filter-field/filter-field-content/filter-field-content.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject, Type} from '@angular/core'; +import {Component, Inject, Optional, Type} from '@angular/core'; import { AbstractFilterFieldContentComponent, SearchService, @@ -17,7 +17,8 @@ import { NAE_DEFAULT_CASE_SEARCH_CATEGORIES, NAE_DEFAULT_TASK_SEARCH_CATEGORIES, NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY, - PfqlVisitor + PfqlVisitor, + DATA_FIELD_PORTAL_DATA, DataFieldPortalData } from '@netgrif/components-core'; export function filterFieldBaseFilterFactory(filterField: FilterField): BaseFilter { @@ -64,8 +65,9 @@ export function filterFieldCategoriesFactory(filterField: FilterField, caseCateg export class FilterFieldContentComponent extends AbstractFilterFieldContentComponent { constructor(@Inject(NAE_FILTER_FIELD) filterField: FilterField, - fieldSearchService: SearchService) { - super(filterField, fieldSearchService); + fieldSearchService: SearchService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { + super(filterField, fieldSearchService, dataFieldPortalData); } } diff --git a/projects/netgrif-components/src/lib/data-fields/filter-field/tab-view-filter-field/filter-field-tab-view-content.component.ts b/projects/netgrif-components/src/lib/data-fields/filter-field/tab-view-filter-field/filter-field-tab-view-content.component.ts index 7a0c2de613..a9c593aa09 100644 --- a/projects/netgrif-components/src/lib/data-fields/filter-field/tab-view-filter-field/filter-field-tab-view-content.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/filter-field/tab-view-filter-field/filter-field-tab-view-content.component.ts @@ -1,4 +1,4 @@ -import { Component, Inject, Injector } from '@angular/core'; +import {Component, Inject, Injector, Optional} from '@angular/core'; import { ComponentRegistryService, NAE_FILTER_FIELD, @@ -8,7 +8,7 @@ import { NAE_BASE_FILTER, AllowedNetsService, AllowedNetsServiceFactory, - CategoryFactory, NAE_SEARCH_CATEGORIES, CategoryResolverService + CategoryFactory, NAE_SEARCH_CATEGORIES, CategoryResolverService, DATA_FIELD_PORTAL_DATA, DataFieldPortalData } from '@netgrif/components-core'; import { filterFieldAllowedNetsFactory, @@ -32,7 +32,8 @@ export class FilterFieldTabViewContentComponent extends AbstractFilterFieldTabVi constructor(registry: ComponentRegistryService, injector: Injector, @Inject(NAE_FILTER_FIELD) filterField: FilterField, - searchService: SearchService) { - super(registry, injector, filterField, searchService) + searchService: SearchService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { + super(registry, injector, filterField, searchService, dataFieldPortalData) } } From 577db34ecff25670fd61396bee858245499d2d88 Mon Sep 17 00:00:00 2001 From: chvostek Date: Thu, 3 Sep 2026 16:03:38 +0200 Subject: [PATCH 50/55] [NAE-2466] Advanced search for PFQL - fix tests --- ...tract-filter-field-content.component.spec.ts | 17 +++++++++++++---- .../abstract-filter-field-content.component.ts | 2 +- ...ter-field-tab-view-content.component.spec.ts | 8 +++++--- ...tract-filter-default-field.component.spec.ts | 2 +- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-content.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-content.component.spec.ts index e466cacb50..3be135f9ea 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-content.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-content.component.spec.ts @@ -1,5 +1,5 @@ import {AbstractFilterFieldContentComponent} from './abstract-filter-field-content.component'; -import {Component, Inject} from '@angular/core'; +import {Component, Inject, Optional} from '@angular/core'; import {FilterField} from './models/filter-field'; import {SearchService} from '../../search/search-service/search.service'; import {ComponentFixture, TestBed} from '@angular/core/testing'; @@ -8,6 +8,9 @@ import {Subject} from 'rxjs'; import {NoopAnimationsModule} from '@angular/platform-browser/animations'; import {HttpClientTestingModule} from '@angular/common/http/testing'; import {FieldTypeResource} from "../../task-content/model/field-type-resource"; +import {DATA_FIELD_PORTAL_DATA} from "@netgrif/components-core"; +import {DataFieldPortalData} from "../models/data-field-portal-data-injection-token"; +import {FormControl} from "@angular/forms"; describe('AbstractFilterFieldContentComponent', () => { let component: TestFilterContentComponent; @@ -28,7 +31,12 @@ describe('AbstractFilterFieldContentComponent', () => { imports: [NoopAnimationsModule, HttpClientTestingModule], providers: [ {provide: NAE_FILTER_FIELD, useValue: field}, - {provide: SearchService, useValue: mockSearchService} + {provide: SearchService, useValue: mockSearchService}, + {provide: DATA_FIELD_PORTAL_DATA, useValue: { + dataField: field, + formControlRef: new FormControl(), + } as DataFieldPortalData + } ], declarations: [ TestFilterContentComponent @@ -70,7 +78,8 @@ describe('AbstractFilterFieldContentComponent', () => { }) class TestFilterContentComponent extends AbstractFilterFieldContentComponent { constructor(@Inject(NAE_FILTER_FIELD) filterField: FilterField, - fieldSearchService: SearchService) { - super(filterField, fieldSearchService); + fieldSearchService: SearchService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { + super(filterField, fieldSearchService, dataFieldPortalData); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-content.component.ts b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-content.component.ts index 21c8acb78e..1ba4e7005b 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-content.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-content.component.ts @@ -29,7 +29,7 @@ export abstract class AbstractFilterFieldContentComponent extends AbstractBaseDa } public get editable(): boolean { - return !!this._filterField.behavior.editable && !this.formControlRef.disabled; + return !!this._filterField.behavior.editable && !this.formControlRef?.disabled; } ngOnDestroy(): void { diff --git a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view-content.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view-content.component.spec.ts index e3467d2436..e19caff066 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view-content.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/filter-field/abstract-filter-field-tab-view-content.component.spec.ts @@ -1,6 +1,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { AbstractFilterFieldTabViewContentComponent } from './abstract-filter-field-tab-view-content.component'; -import { Component, Inject, Injector } from '@angular/core'; +import { Component, Inject, Injector, Optional } from '@angular/core'; import { FilterField } from './models/filter-field'; import { NAE_FILTER_FIELD } from './models/filter-field-injection-token'; import { SearchService } from '../../search/search-service/search.service'; @@ -11,6 +11,7 @@ import { Dashboard } from '../text-field/dashboard-portal-text-field/dashboard-v import { ComponentPortal } from '@angular/cdk/portal'; import {ComponentRegistryService} from "../../registry/component-registry.service"; import {FieldTypeResource} from "../../task-content/model/field-type-resource"; +import {DATA_FIELD_PORTAL_DATA, DataFieldPortalData} from "../models/data-field-portal-data-injection-token"; describe('AbstractFilterFieldTabViewContentComponent', () => { let component: TestFilterFieldTabViewContentComponent; @@ -72,8 +73,9 @@ class TestFilterFieldTabViewContentComponent extends AbstractFilterFieldTabViewC constructor(registry: ComponentRegistryService, injector: Injector, @Inject(NAE_FILTER_FIELD) filterField: FilterField, - searchService: SearchService) { - super(registry, injector, filterField, searchService); + searchService: SearchService, + @Optional() @Inject(DATA_FIELD_PORTAL_DATA) dataFieldPortalData: DataFieldPortalData) { + super(registry, injector, filterField, searchService, dataFieldPortalData); } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/filter-field/filter-default-field/abstract-filter-default-field.component.spec.ts b/projects/netgrif-components-core/src/lib/data-fields/filter-field/filter-default-field/abstract-filter-default-field.component.spec.ts index a2672fc230..eb9ff9a68d 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/filter-field/filter-default-field/abstract-filter-default-field.component.spec.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/filter-field/filter-default-field/abstract-filter-default-field.component.spec.ts @@ -88,6 +88,6 @@ class TestFilterContentComponent extends AbstractFilterFieldContentComponent { loadFromMetadata: () => { }, loadingFromMetadata$: of(false) - } as unknown as SearchService); + } as unknown as SearchService, undefined); } } From 0b440a8f0077319252acfec390e596f48f876f09 Mon Sep 17 00:00:00 2001 From: chvostek Date: Sun, 6 Sep 2026 09:55:44 +0200 Subject: [PATCH 51/55] [NAE-2466] Advanced search for PFQL - fix missing provider --- .../immediate-filter-text-content.component.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text-content/immediate-filter-text-content.component.ts b/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text-content/immediate-filter-text-content.component.ts index 42e7063f9b..f598be3502 100644 --- a/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text-content/immediate-filter-text-content.component.ts +++ b/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text-content/immediate-filter-text-content.component.ts @@ -14,6 +14,7 @@ import { FilterType, NAE_DEFAULT_CASE_SEARCH_CATEGORIES, NAE_DEFAULT_TASK_SEARCH_CATEGORIES, + PfqlVisitor, } from '@netgrif/components-core'; import {TranslateService} from '@ngx-translate/core'; @@ -44,6 +45,7 @@ export function filterTextCategoriesFactory(configuration: FilterTextConfigurati NAE_DEFAULT_CASE_SEARCH_CATEGORIES, NAE_DEFAULT_TASK_SEARCH_CATEGORIES]}, CategoryFactory, SearchService, + PfqlVisitor, ] }) export class ImmediateFilterTextContentComponent extends AbstractImmediateFilterTextContentComponent { From 0b56fca54a5f0f7fb4c4a47d68fde4a685a64375 Mon Sep 17 00:00:00 2001 From: chvostek Date: Sun, 6 Sep 2026 10:52:41 +0200 Subject: [PATCH 52/55] [NAE-2466] Advanced search for PFQL - fix missing token - fix case dataset as immediate field --- .../src/lib/search/models/category/case/case-dataset.ts | 7 ++++++- .../immediate-filter-text-content.component.ts | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts index e8cdd7828c..c1da60da66 100644 --- a/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts +++ b/projects/netgrif-components-core/src/lib/search/models/category/case/case-dataset.ts @@ -517,6 +517,11 @@ export class CaseDataset extends Category implements AutocompleteOpti } protected createConfigurationFilterTextSegments(): Array { - return [{segment: this._configurationInputs$.value[0].formControl.value.text, bold: true}]; + const configInput = this._configurationInputs$.value[0]; + let dataFieldId: string = configInput.formControl.value.text; + if (!dataFieldId) { + dataFieldId = configInput.formControl.value + } + return [{segment: dataFieldId, bold: true}]; } } diff --git a/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text-content/immediate-filter-text-content.component.ts b/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text-content/immediate-filter-text-content.component.ts index f598be3502..a3c2f8b2ab 100644 --- a/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text-content/immediate-filter-text-content.component.ts +++ b/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text-content/immediate-filter-text-content.component.ts @@ -46,6 +46,7 @@ export function filterTextCategoriesFactory(configuration: FilterTextConfigurati CategoryFactory, SearchService, PfqlVisitor, + {provide: NAE_IGNORE_NETS_ON_AUTOCOMPLETE_CATEGORY, useValue: true}, ] }) export class ImmediateFilterTextContentComponent extends AbstractImmediateFilterTextContentComponent { From e7ca702836805175d5792f02704fe80a661dcd5f Mon Sep 17 00:00:00 2001 From: chvostek Date: Sun, 6 Sep 2026 11:03:23 +0200 Subject: [PATCH 53/55] [NAE-2466] Advanced search for PFQL - fix tests --- ...iate-filter-text-content.component.spec.ts | 23 +++++++++++++++- .../immediate-filter-text.component.spec.ts | 27 ++++++++++++++++--- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text-content/immediate-filter-text-content.component.spec.ts b/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text-content/immediate-filter-text-content.component.spec.ts index 4a17860bca..51bb2af7c1 100644 --- a/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text-content/immediate-filter-text-content.component.spec.ts +++ b/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text-content/immediate-filter-text-content.component.spec.ts @@ -8,9 +8,11 @@ import { NAE_FILTER_TEXT, AllowedNetsService, TestNoAllowedNetsFactory, - AllowedNetsServiceFactory + AllowedNetsServiceFactory, MockUserService, User, UserService, AuthenticationModule } from '@netgrif/components-core'; import {HttpClientTestingModule} from '@angular/common/http/testing'; +import {Injectable} from "@angular/core"; +import {RouterTestingModule} from "@angular/router/testing"; describe('ImmediateFilterTextContentComponent', () => { let component: ImmediateFilterTextContentComponent; @@ -23,10 +25,13 @@ describe('ImmediateFilterTextContentComponent', () => { MaterialModule, TranslateLibModule, HttpClientTestingModule, + AuthenticationModule, + RouterTestingModule.withRoutes([]), ], providers: [ {provide: ConfigurationService, useClass: TestConfigurationService}, {provide: AllowedNetsService, useFactory: TestNoAllowedNetsFactory, deps: [AllowedNetsServiceFactory]}, + {provide: UserService, useClass: CustomMockUserService}, { provide: NAE_FILTER_TEXT, useValue: { @@ -54,3 +59,19 @@ describe('ImmediateFilterTextContentComponent', () => { expect(component).toBeTruthy(); }); }); + +@Injectable() +class CustomMockUserService extends MockUserService { + constructor() { + super(); + this._user = new User('123', 'test@netgrif.com', 'Test', 'User', ['ROLE_USER'], [{ + stringId: 'id', + name: 'id', + description: '', + importId: 'id', + netImportId: 'identifier', + netVersion: '1.0.0', + netStringId: 'stringId', + }]); + } +} diff --git a/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text/immediate-filter-text.component.spec.ts b/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text/immediate-filter-text.component.spec.ts index e869faa75d..4f63c46cf2 100644 --- a/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text/immediate-filter-text.component.spec.ts +++ b/projects/netgrif-components/src/lib/panel/immediate/immediate-filter-text/immediate-filter-text.component.spec.ts @@ -3,10 +3,12 @@ import {ImmediateFilterTextComponent} from './immediate-filter-text.component'; import { MaterialModule, ConfigurationService, - TestConfigurationService, AllowedNetsService, TestNoAllowedNetsFactory, AllowedNetsServiceFactory, + TestConfigurationService, AllowedNetsService, TestNoAllowedNetsFactory, AllowedNetsServiceFactory, MockUserService, + User, AuthenticationModule, UserService, } from '@netgrif/components-core'; import {PanelComponentModule} from '../../panel.module'; -import {Component} from '@angular/core'; +import {Component, Injectable} from '@angular/core'; +import {RouterTestingModule} from "@angular/router/testing"; describe('ImmediateFilterTextComponent', () => { let component: ImmediateFilterTextComponent; @@ -17,10 +19,13 @@ describe('ImmediateFilterTextComponent', () => { declarations: [TestWrapperComponent], imports: [ MaterialModule, - PanelComponentModule + PanelComponentModule, + AuthenticationModule, + RouterTestingModule.withRoutes([]), ], providers: [ {provide: AllowedNetsService, useFactory: TestNoAllowedNetsFactory, deps: [AllowedNetsServiceFactory]}, {provide: ConfigurationService, useClass: TestConfigurationService}, + {provide: UserService, useClass: CustomMockUserService}, ] }) .compileComponents(); @@ -50,3 +55,19 @@ class TestWrapperComponent { constructor() { } } + +@Injectable() +class CustomMockUserService extends MockUserService { + constructor() { + super(); + this._user = new User('123', 'test@netgrif.com', 'Test', 'User', ['ROLE_USER'], [{ + stringId: 'id', + name: 'id', + description: '', + importId: 'id', + netImportId: 'identifier', + netVersion: '1.0.0', + netStringId: 'stringId', + }]); + } +} From ebc1abe8c04a5479547183199f0bef7c92e552ff Mon Sep 17 00:00:00 2001 From: chvostek Date: Thu, 10 Sep 2026 15:10:08 +0200 Subject: [PATCH 54/55] [NAE-2466] Advanced search for PFQL - resolve PR comments --- projects/netgrif-components-core/src/assets/i18n/sk.json | 2 +- .../src/lib/pfql/model/complex-expression.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/netgrif-components-core/src/assets/i18n/sk.json b/projects/netgrif-components-core/src/assets/i18n/sk.json index 0ee29c4b2c..b76af8baae 100644 --- a/projects/netgrif-components-core/src/assets/i18n/sk.json +++ b/projects/netgrif-components-core/src/assets/i18n/sk.json @@ -206,7 +206,7 @@ }, "help": { "title": "Nápoveda pre rozšírené vyhľadávanie", - "text": "Rozšírené vyhľadávanie slúži na zostavenie komplikovanejších požiadaviek na vyhľadávanie. Na začiatku zvoľte kategóriu vyhľadávania. Kategória vyhľadávania určuje, podľa čoho má váš dopyt vyhľadávať. Niektoré kategórie, ako napríklad \"Dáta prípadu\" vyžadujú dodatočnú konfiguráciu. Po zvolení kategórie je nutné zvoliť operátor vyhľadávania. Operátor rozhoduje o tom, akým spôsobom sa hľadá zhoda s hľadaným výrazom a dátami. Operátorom je možné hľadať napríklad presnú zhodu, alebo hodnotu z rozsahu. Nakoniec je nutné zadať hľadanú hodnotu. Dopyty je možné kombinovať pomocou kľúčových slov A SÚČASNE. Dopyty kombinované slovom A SÚČASNE nájdu výsledky spĺňajúce všetky podmienky. If you wish to enter more complex queries you can select plain query category and enter any valid PFQL query. Ak potrebujete zadať komplexnejší dopyt, môžete zvoliť kategóriu 'Obyčajný dopyt', kde viete napísať ľubovoľný platný PFQL dopyt." + "text": "Rozšírené vyhľadávanie slúži na zostavenie komplikovanejších požiadaviek na vyhľadávanie. Na začiatku zvoľte kategóriu vyhľadávania. Kategória vyhľadávania určuje, podľa čoho má váš dopyt vyhľadávať. Niektoré kategórie, ako napríklad \"Dáta prípadu\" vyžadujú dodatočnú konfiguráciu. Po zvolení kategórie je nutné zvoliť operátor vyhľadávania. Operátor rozhoduje o tom, akým spôsobom sa hľadá zhoda s hľadaným výrazom a dátami. Operátorom je možné hľadať napríklad presnú zhodu, alebo hodnotu z rozsahu. Nakoniec je nutné zadať hľadanú hodnotu. Dopyty je možné kombinovať pomocou kľúčových slov A SÚČASNE. Dopyty kombinované slovom A SÚČASNE nájdu výsledky spĺňajúce všetky podmienky. Ak potrebujete zadať komplexnejší dopyt, môžete zvoliť kategóriu 'Obyčajný dopyt', kde viete napísať ľubovoľný platný PFQL dopyt." }, "fullText": "Zadajte hľadaný text", "and": "a súčasne", diff --git a/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts b/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts index 42b32dc596..689fac383c 100644 --- a/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts +++ b/projects/netgrif-components-core/src/lib/pfql/model/complex-expression.ts @@ -11,7 +11,7 @@ import {QueryItem, QueryItemType} from "./query-item-type"; export class ComplexExpression implements QueryItemInterface { protected _items: QueryItem[]; - public constructor(items: QueryItem[]) { + public constructor(items?: QueryItem[]) { this._items = !items ? [] : items; } From 790f1dd96da987fa3a767f26fb08dfa37b3ff173 Mon Sep 17 00:00:00 2001 From: chvostek Date: Fri, 11 Sep 2026 11:11:22 +0200 Subject: [PATCH 55/55] [NAE-2466] Advanced search for PFQL - move antlr dependency to core --- package.json | 1 - projects/netgrif-components-core/package.json | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 4bcccfb295..b80a2cf195 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,6 @@ "angular-resizable-element": "~7.0.0", "angular-resize-event": "~3.2.0", "angular2-hotkeys": "~16.0.0", - "antlr4ng": "^3.0.16", "easymde": "~2.16.1", "escape-string-regexp": "^4.0.0", "hammerjs": "~2.0.8", diff --git a/projects/netgrif-components-core/package.json b/projects/netgrif-components-core/package.json index 9a7e5b8cc0..f963345d27 100644 --- a/projects/netgrif-components-core/package.json +++ b/projects/netgrif-components-core/package.json @@ -60,6 +60,7 @@ "moment": "~2.29.4", "natural-orderby": "~2.0.3", "rxjs": "~6.6.7", - "zone.js": "~0.14.0" + "zone.js": "~0.14.0", + "antlr4ng": "^3.0.16" } }