diff --git a/spec/filter/util.spec.ts b/spec/filter/util.spec.ts index 1d4a450..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()', () => { @@ -87,5 +89,57 @@ 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 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( + new HDict({ + id: HRef.make('id'), + dis: 'an equip', + equip: HMarker.make(), + customTag: HMarker.make(), + }), + { + getExcludedTags: () => ['customTag'], + } + ) + ).toEqual('equip and dis == "an equip"') + }) }) // makeRelativeHaystackFilter() }) diff --git a/src/filter/util.ts b/src/filter/util.ts index 1076d8f..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' @@ -15,14 +16,24 @@ import { HFilterBuilder } from '../filter/HFilterBuilder' */ 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 + + /** + * 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. + */ + getExcludedTags?: (namespace?: HNamespace) => string[] } /** @@ -37,12 +48,18 @@ export function makeRelativeHaystackFilter( ): string { const useDisplayName = options?.useDisplayName ?? true const useKind = options?.useKind ?? true + const getExcludedTags = + options?.getExcludedTags ?? getDefaultRelativizationExcludedTags + const excludedTags = new Set(getExcludedTags(options?.namespace)) const builder = new HFilterBuilder() // Build the marker tags. for (const { name, value } of record) { - if (valueIsKind(value, Kind.Marker)) { + if ( + valueIsKind(value, Kind.Marker) && + !excludedTags.has(name) + ) { if (!builder.isEmpty()) { builder.and() } @@ -73,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) {