From 68b6b4056e4437da055ff7561a4fd22fdb5a1aca Mon Sep 17 00:00:00 2001 From: Riccardo Leder Date: Tue, 30 Sep 2025 15:51:54 +0200 Subject: [PATCH 1/2] add tag exclusion to relative filter generation --- spec/filter/util.spec.ts | 30 ++++++++++++++++++++++++++++++ src/filter/util.ts | 28 +++++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/spec/filter/util.spec.ts b/spec/filter/util.spec.ts index 1d4a450..491807b 100644 --- a/spec/filter/util.spec.ts +++ b/spec/filter/util.spec.ts @@ -87,5 +87,35 @@ describe('haystack', () => { ) ).toEqual('id == @id') }) + + it('returns a haystack filter without excluded tags', () => { + expect( + makeRelativeHaystackFilter( + new HDict({ + id: HRef.make('id'), + dis: 'an equip', + equip: HMarker.make(), + his: HMarker.make(), + aux: HMarker.make(), + }) + ) + ).toEqual('equip and dis == "an equip"') + }) + + it('returns a haystack filter without custom excluded tags', () => { + expect( + makeRelativeHaystackFilter( + new HDict({ + id: HRef.make('id'), + dis: 'an equip', + equip: HMarker.make(), + customTag: HMarker.make(), + }), + { + excludeTags: ['customTag'], + } + ) + ).toEqual('equip and dis == "an equip"') + }) }) // makeRelativeHaystackFilter() }) diff --git a/src/filter/util.ts b/src/filter/util.ts index 1076d8f..7837a1b 100644 --- a/src/filter/util.ts +++ b/src/filter/util.ts @@ -10,6 +10,22 @@ import { valueIsKind } from '../core/HVal' import { Kind } from '../core/Kind' import { HFilterBuilder } from '../filter/HFilterBuilder' +/** + * Default list of tags to exclude from the relativization. + */ +export const RELATIVE_FILTER_EXCLUDED_TAGS = [ + 'aux', + 'his', + 'hisCollectCOV', + 'hisCollectNA', + 'hisTotalized', + 'haystackPoint', + 'bacnetPoint', + 'axStatus', + 'axAnnotated', + 'demoPoint', +] + /** * Relativization options. */ @@ -23,6 +39,11 @@ export interface RelativizeOptions { * True (or undefined) if a point's kind should be used in the relativization. */ useKind?: boolean + + /** + * List of tags to exclude from the relativization. + */ + excludeTags?: string[] } /** @@ -37,12 +58,17 @@ export function makeRelativeHaystackFilter( ): string { const useDisplayName = options?.useDisplayName ?? true const useKind = options?.useKind ?? true + const excludeTags = options?.excludeTags ?? RELATIVE_FILTER_EXCLUDED_TAGS + const excludedTagSet = new Set(excludeTags) const builder = new HFilterBuilder() // Build the marker tags. for (const { name, value } of record) { - if (valueIsKind(value, Kind.Marker)) { + if ( + valueIsKind(value, Kind.Marker) && + !excludedTagSet.has(name) + ) { if (!builder.isEmpty()) { builder.and() } From 9b32acbe9385770537d14971c3e10cc1bef29db6 Mon Sep 17 00:00:00 2001 From: Riccardo Leder Date: Wed, 1 Oct 2025 17:49:09 +0200 Subject: [PATCH 2/2] refactor tag exclusion from relative filter --- spec/filter/util.spec.ts | 26 ++++++++++++++++- src/filter/util.ts | 61 +++++++++++++++++++++++++--------------- 2 files changed, 63 insertions(+), 24 deletions(-) diff --git a/spec/filter/util.spec.ts b/spec/filter/util.spec.ts index 491807b..de894f8 100644 --- a/spec/filter/util.spec.ts +++ b/spec/filter/util.spec.ts @@ -7,6 +7,8 @@ import { HRef } from '../../src/core/HRef' import { makeRelativeHaystackFilter } from '../../src/filter/util' import { HMarker } from '../../src/core/HMarker' import { HStr } from '../../src/core/HStr' +import { HSymbol } from '../../src/core/HSymbol' +import { HNamespace } from '../../src/core/HNamespace' describe('haystack', () => { describe('makeRelativeHaystackFilter()', () => { @@ -102,6 +104,28 @@ describe('haystack', () => { ).toEqual('equip and dis == "an equip"') }) + it('returns a haystack filter without connPoint subtype tags', () => { + const mockNamespace = { + allSubTypesOf: () => [ + HDict.make({ def: HSymbol.make('demoPoint') }), + ], + } as unknown as HNamespace + + expect( + makeRelativeHaystackFilter( + new HDict({ + id: HRef.make('id'), + dis: 'an equip', + equip: HMarker.make(), + demoPoint: HMarker.make(), + }), + { + namespace: mockNamespace, + } + ) + ).toEqual('equip and dis == "an equip"') + }) + it('returns a haystack filter without custom excluded tags', () => { expect( makeRelativeHaystackFilter( @@ -112,7 +136,7 @@ describe('haystack', () => { customTag: HMarker.make(), }), { - excludeTags: ['customTag'], + getExcludedTags: () => ['customTag'], } ) ).toEqual('equip and dis == "an equip"') diff --git a/src/filter/util.ts b/src/filter/util.ts index 7837a1b..0782136 100644 --- a/src/filter/util.ts +++ b/src/filter/util.ts @@ -2,6 +2,7 @@ * Copyright (c) 2025, J2 Innovations. All Rights Reserved */ +import { HNamespace } from '../core/HNamespace' import { HDict } from '../core/dict/HDict' import { HMarker } from '../core/HMarker' import { HRef } from '../core/HRef' @@ -10,40 +11,29 @@ import { valueIsKind } from '../core/HVal' import { Kind } from '../core/Kind' import { HFilterBuilder } from '../filter/HFilterBuilder' -/** - * Default list of tags to exclude from the relativization. - */ -export const RELATIVE_FILTER_EXCLUDED_TAGS = [ - 'aux', - 'his', - 'hisCollectCOV', - 'hisCollectNA', - 'hisTotalized', - 'haystackPoint', - 'bacnetPoint', - 'axStatus', - 'axAnnotated', - 'demoPoint', -] - /** * Relativization options. */ export interface RelativizeOptions { /** - * True (or undefined) if the display name should be used in the relativization. + * True (or undefined) if the display name should be used in the relative filter. */ useDisplayName?: boolean /** - * True (or undefined) if a point's kind should be used in the relativization. + * True (or undefined) if a point's kind should be used in the relative filter. */ useKind?: boolean /** - * List of tags to exclude from the relativization. + * The namespace to use for determining excluded tags. + */ + namespace?: HNamespace + + /** + * Optional function to determine the list of tags that should be excluded from the relative filter. */ - excludeTags?: string[] + getExcludedTags?: (namespace?: HNamespace) => string[] } /** @@ -58,8 +48,9 @@ export function makeRelativeHaystackFilter( ): string { const useDisplayName = options?.useDisplayName ?? true const useKind = options?.useKind ?? true - const excludeTags = options?.excludeTags ?? RELATIVE_FILTER_EXCLUDED_TAGS - const excludedTagSet = new Set(excludeTags) + const getExcludedTags = + options?.getExcludedTags ?? getDefaultRelativizationExcludedTags + const excludedTags = new Set(getExcludedTags(options?.namespace)) const builder = new HFilterBuilder() @@ -67,7 +58,7 @@ export function makeRelativeHaystackFilter( for (const { name, value } of record) { if ( valueIsKind(value, Kind.Marker) && - !excludedTagSet.has(name) + !excludedTags.has(name) ) { if (!builder.isEmpty()) { builder.and() @@ -99,6 +90,30 @@ export function makeRelativeHaystackFilter( return builder.build() } +export function getDefaultRelativizationExcludedTags( + namespace?: HNamespace +): string[] { + const excludedTags = [ + 'aux', + 'his', + 'hisCollectCOV', + 'hisCollectNA', + 'hisTotalized', + 'axStatus', + 'axAnnotated', + ] + + if (namespace) { + const connectorPointTags = namespace + .allSubTypesOf('connPoint') + .map((def) => def.defName) + + excludedTags.push(...connectorPointTags) + } + + return excludedTags +} + function addPointKindToFilter(record: HDict, builder: HFilterBuilder): void { const kind = record.get('kind')?.value if (kind) {