@ifc-lite/rules 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/LICENSE +373 -0
  2. package/README.md +45 -0
  3. package/dist/engine/rule-engine-chunk.d.ts +25 -0
  4. package/dist/engine/rule-engine-chunk.d.ts.map +1 -0
  5. package/dist/engine/rule-engine-chunk.js +43 -0
  6. package/dist/engine/rule-engine-chunk.js.map +1 -0
  7. package/dist/engine/rule-engine-compare.d.ts +17 -0
  8. package/dist/engine/rule-engine-compare.d.ts.map +1 -0
  9. package/dist/engine/rule-engine-compare.js +69 -0
  10. package/dist/engine/rule-engine-compare.js.map +1 -0
  11. package/dist/engine/rule-engine-requirements.d.ts +37 -0
  12. package/dist/engine/rule-engine-requirements.d.ts.map +1 -0
  13. package/dist/engine/rule-engine-requirements.js +293 -0
  14. package/dist/engine/rule-engine-requirements.js.map +1 -0
  15. package/dist/engine/rule-engine-sets.d.ts +46 -0
  16. package/dist/engine/rule-engine-sets.d.ts.map +1 -0
  17. package/dist/engine/rule-engine-sets.js +298 -0
  18. package/dist/engine/rule-engine-sets.js.map +1 -0
  19. package/dist/engine/rule-engine-unit.d.ts +23 -0
  20. package/dist/engine/rule-engine-unit.d.ts.map +1 -0
  21. package/dist/engine/rule-engine-unit.js +64 -0
  22. package/dist/engine/rule-engine-unit.js.map +1 -0
  23. package/dist/engine/rule-engine.d.ts +29 -0
  24. package/dist/engine/rule-engine.d.ts.map +1 -0
  25. package/dist/engine/rule-engine.js +244 -0
  26. package/dist/engine/rule-engine.js.map +1 -0
  27. package/dist/filter/effective-filter-fields.d.ts +13 -0
  28. package/dist/filter/effective-filter-fields.d.ts.map +1 -0
  29. package/dist/filter/effective-filter-fields.js +44 -0
  30. package/dist/filter/effective-filter-fields.js.map +1 -0
  31. package/dist/filter/entity-predefined-type.d.ts +24 -0
  32. package/dist/filter/entity-predefined-type.d.ts.map +1 -0
  33. package/dist/filter/entity-predefined-type.js +34 -0
  34. package/dist/filter/entity-predefined-type.js.map +1 -0
  35. package/dist/filter/filter-evaluate-groups.d.ts +36 -0
  36. package/dist/filter/filter-evaluate-groups.d.ts.map +1 -0
  37. package/dist/filter/filter-evaluate-groups.js +111 -0
  38. package/dist/filter/filter-evaluate-groups.js.map +1 -0
  39. package/dist/filter/filter-evaluate-model-tag.d.ts +22 -0
  40. package/dist/filter/filter-evaluate-model-tag.d.ts.map +1 -0
  41. package/dist/filter/filter-evaluate-model-tag.js +35 -0
  42. package/dist/filter/filter-evaluate-model-tag.js.map +1 -0
  43. package/dist/filter/filter-evaluate-mutations.d.ts +51 -0
  44. package/dist/filter/filter-evaluate-mutations.d.ts.map +1 -0
  45. package/dist/filter/filter-evaluate-mutations.js +111 -0
  46. package/dist/filter/filter-evaluate-mutations.js.map +1 -0
  47. package/dist/filter/filter-evaluate-yield.d.ts +9 -0
  48. package/dist/filter/filter-evaluate-yield.d.ts.map +1 -0
  49. package/dist/filter/filter-evaluate-yield.js +32 -0
  50. package/dist/filter/filter-evaluate-yield.js.map +1 -0
  51. package/dist/filter/filter-evaluate.d.ts +120 -0
  52. package/dist/filter/filter-evaluate.d.ts.map +1 -0
  53. package/dist/filter/filter-evaluate.js +408 -0
  54. package/dist/filter/filter-evaluate.js.map +1 -0
  55. package/dist/filter/filter-group-rule.d.ts +23 -0
  56. package/dist/filter/filter-group-rule.d.ts.map +1 -0
  57. package/dist/filter/filter-group-rule.js +69 -0
  58. package/dist/filter/filter-group-rule.js.map +1 -0
  59. package/dist/filter/filter-groups.d.ts +65 -0
  60. package/dist/filter/filter-groups.d.ts.map +1 -0
  61. package/dist/filter/filter-groups.js +136 -0
  62. package/dist/filter/filter-groups.js.map +1 -0
  63. package/dist/filter/filter-iteration-source.d.ts +26 -0
  64. package/dist/filter/filter-iteration-source.d.ts.map +1 -0
  65. package/dist/filter/filter-iteration-source.js +154 -0
  66. package/dist/filter/filter-iteration-source.js.map +1 -0
  67. package/dist/filter/filter-iteration.d.ts +5 -0
  68. package/dist/filter/filter-iteration.d.ts.map +1 -0
  69. package/dist/filter/filter-iteration.js +25 -0
  70. package/dist/filter/filter-iteration.js.map +1 -0
  71. package/dist/filter/filter-match.d.ts +114 -0
  72. package/dist/filter/filter-match.d.ts.map +1 -0
  73. package/dist/filter/filter-match.js +302 -0
  74. package/dist/filter/filter-match.js.map +1 -0
  75. package/dist/filter/filter-ops.d.ts +90 -0
  76. package/dist/filter/filter-ops.d.ts.map +1 -0
  77. package/dist/filter/filter-ops.js +202 -0
  78. package/dist/filter/filter-ops.js.map +1 -0
  79. package/dist/filter/filter-rule-guards.d.ts +4 -0
  80. package/dist/filter/filter-rule-guards.d.ts.map +1 -0
  81. package/dist/filter/filter-rule-guards.js +74 -0
  82. package/dist/filter/filter-rule-guards.js.map +1 -0
  83. package/dist/filter/filter-rules.d.ts +275 -0
  84. package/dist/filter/filter-rules.d.ts.map +1 -0
  85. package/dist/filter/filter-rules.js +68 -0
  86. package/dist/filter/filter-rules.js.map +1 -0
  87. package/dist/filter/lens-material-names.d.ts +13 -0
  88. package/dist/filter/lens-material-names.d.ts.map +1 -0
  89. package/dist/filter/lens-material-names.js +36 -0
  90. package/dist/filter/lens-material-names.js.map +1 -0
  91. package/dist/filter/measure-units.d.ts +29 -0
  92. package/dist/filter/measure-units.d.ts.map +1 -0
  93. package/dist/filter/measure-units.js +72 -0
  94. package/dist/filter/measure-units.js.map +1 -0
  95. package/dist/filter/model-tag.d.ts +65 -0
  96. package/dist/filter/model-tag.d.ts.map +1 -0
  97. package/dist/filter/model-tag.js +57 -0
  98. package/dist/filter/model-tag.js.map +1 -0
  99. package/dist/filter/read-measure-subject.d.ts +28 -0
  100. package/dist/filter/read-measure-subject.d.ts.map +1 -0
  101. package/dist/filter/read-measure-subject.js +116 -0
  102. package/dist/filter/read-measure-subject.js.map +1 -0
  103. package/dist/filter/read-subject.d.ts +72 -0
  104. package/dist/filter/read-subject.d.ts.map +1 -0
  105. package/dist/filter/read-subject.js +128 -0
  106. package/dist/filter/read-subject.js.map +1 -0
  107. package/dist/filter/subject-match.d.ts +27 -0
  108. package/dist/filter/subject-match.d.ts.map +1 -0
  109. package/dist/filter/subject-match.js +52 -0
  110. package/dist/filter/subject-match.js.map +1 -0
  111. package/dist/filter/subject-read-options.d.ts +33 -0
  112. package/dist/filter/subject-read-options.d.ts.map +1 -0
  113. package/dist/filter/subject-read-options.js +8 -0
  114. package/dist/filter/subject-read-options.js.map +1 -0
  115. package/dist/ids/ids-facet-to-rules.d.ts +20 -0
  116. package/dist/ids/ids-facet-to-rules.d.ts.map +1 -0
  117. package/dist/ids/ids-facet-to-rules.js +230 -0
  118. package/dist/ids/ids-facet-to-rules.js.map +1 -0
  119. package/dist/ids/ids-regex.d.ts +44 -0
  120. package/dist/ids/ids-regex.d.ts.map +1 -0
  121. package/dist/ids/ids-regex.js +334 -0
  122. package/dist/ids/ids-regex.js.map +1 -0
  123. package/dist/ids/ids-to-rule-set.d.ts +39 -0
  124. package/dist/ids/ids-to-rule-set.d.ts.map +1 -0
  125. package/dist/ids/ids-to-rule-set.js +103 -0
  126. package/dist/ids/ids-to-rule-set.js.map +1 -0
  127. package/dist/ids/ids-xml-writer.d.ts +11 -0
  128. package/dist/ids/ids-xml-writer.d.ts.map +1 -0
  129. package/dist/ids/ids-xml-writer.js +172 -0
  130. package/dist/ids/ids-xml-writer.js.map +1 -0
  131. package/dist/ids/rule-set-to-ids.d.ts +45 -0
  132. package/dist/ids/rule-set-to-ids.d.ts.map +1 -0
  133. package/dist/ids/rule-set-to-ids.js +140 -0
  134. package/dist/ids/rule-set-to-ids.js.map +1 -0
  135. package/dist/ids/rule-to-ids-facets.d.ts +52 -0
  136. package/dist/ids/rule-to-ids-facets.d.ts.map +1 -0
  137. package/dist/ids/rule-to-ids-facets.js +291 -0
  138. package/dist/ids/rule-to-ids-facets.js.map +1 -0
  139. package/dist/ids/stored-unit-scale.d.ts +15 -0
  140. package/dist/ids/stored-unit-scale.d.ts.map +1 -0
  141. package/dist/ids/stored-unit-scale.js +64 -0
  142. package/dist/ids/stored-unit-scale.js.map +1 -0
  143. package/dist/index.d.ts +39 -0
  144. package/dist/index.d.ts.map +1 -0
  145. package/dist/index.js +46 -0
  146. package/dist/index.js.map +1 -0
  147. package/dist/rule-set/between-chip.d.ts +54 -0
  148. package/dist/rule-set/between-chip.d.ts.map +1 -0
  149. package/dist/rule-set/between-chip.js +95 -0
  150. package/dist/rule-set/between-chip.js.map +1 -0
  151. package/dist/rule-set/requirement-invariants.d.ts +25 -0
  152. package/dist/rule-set/requirement-invariants.d.ts.map +1 -0
  153. package/dist/rule-set/requirement-invariants.js +29 -0
  154. package/dist/rule-set/requirement-invariants.js.map +1 -0
  155. package/dist/rule-set/requirement-text.d.ts +20 -0
  156. package/dist/rule-set/requirement-text.d.ts.map +1 -0
  157. package/dist/rule-set/requirement-text.js +179 -0
  158. package/dist/rule-set/requirement-text.js.map +1 -0
  159. package/dist/rule-set/rule-set-io-requirement.d.ts +22 -0
  160. package/dist/rule-set/rule-set-io-requirement.d.ts.map +1 -0
  161. package/dist/rule-set/rule-set-io-requirement.js +140 -0
  162. package/dist/rule-set/rule-set-io-requirement.js.map +1 -0
  163. package/dist/rule-set/rule-set-io-shared.d.ts +24 -0
  164. package/dist/rule-set/rule-set-io-shared.d.ts.map +1 -0
  165. package/dist/rule-set/rule-set-io-shared.js +48 -0
  166. package/dist/rule-set/rule-set-io-shared.js.map +1 -0
  167. package/dist/rule-set/rule-set-io-subject.d.ts +10 -0
  168. package/dist/rule-set/rule-set-io-subject.d.ts.map +1 -0
  169. package/dist/rule-set/rule-set-io-subject.js +67 -0
  170. package/dist/rule-set/rule-set-io-subject.js.map +1 -0
  171. package/dist/rule-set/rule-set-io.d.ts +37 -0
  172. package/dist/rule-set/rule-set-io.d.ts.map +1 -0
  173. package/dist/rule-set/rule-set-io.js +142 -0
  174. package/dist/rule-set/rule-set-io.js.map +1 -0
  175. package/dist/rule-set/rule-set.d.ts +109 -0
  176. package/dist/rule-set/rule-set.d.ts.map +1 -0
  177. package/dist/rule-set/rule-set.js +5 -0
  178. package/dist/rule-set/rule-set.js.map +1 -0
  179. package/package.json +59 -0
@@ -0,0 +1,65 @@
1
+ /**
2
+ * User-facing MODEL tags (issue #4215): free-form labels a coordinator puts on
3
+ * the models of a federation ("Building A", "Structure", "Tender") so the same
4
+ * set of models can be picked out again in the hierarchy, the advanced filter,
5
+ * clash set filters and list scope.
6
+ *
7
+ * Not to be confused with:
8
+ * - the IFC `Tag` attribute on an element (`IfcElement.Tag`, and
9
+ * `ClashElement.tag` which is the element's IFC class) — these labels never
10
+ * touch IFC data and manufacture no property set;
11
+ * - the plugin API's `SourceTag`, which is cloud-source PROVENANCE
12
+ * (provider / project / file / revision), written by the loader and never
13
+ * by the user.
14
+ *
15
+ * Identity is the `id`, never the name: a saved rule stores tag ids, so
16
+ * renaming a tag changes what the chip says and nothing about what matches.
17
+ * Assignments are keyed by the runtime model id in the store and by the
18
+ * model's content fingerprint in the portable federation setup file.
19
+ */
20
+ export interface ModelTag {
21
+ /** Stable identity (UUID). Saved rules and setup files reference this. */
22
+ id: string;
23
+ /** Display name. Unique per federation, compared case-insensitively. */
24
+ name: string;
25
+ /** Optional CSS colour for the chip. */
26
+ color?: string;
27
+ }
28
+ /**
29
+ * The four membership predicates every consumer (search, clash, lists) reads
30
+ * the same way:
31
+ * - `hasAny` — the model carries at least one of `tagIds`
32
+ * - `hasAll` — the model carries every one of `tagIds`
33
+ * - `hasNone` — the model carries none of `tagIds`
34
+ * - `untagged` — the model carries no tag at all (`tagIds` is ignored)
35
+ */
36
+ export type ModelTagOp = 'hasAny' | 'hasAll' | 'hasNone' | 'untagged';
37
+ export declare const MODEL_TAG_OPS: readonly ModelTagOp[];
38
+ export declare function isModelTagOp(value: unknown): value is ModelTagOp;
39
+ /**
40
+ * The name key two tags are compared by: trimmed, case-folded. Locale-
41
+ * independent on purpose: the key decides identity across machines (a setup
42
+ * file's "Structure" must land on this machine's "structure"), and
43
+ * `toLocaleLowerCase` folds "I" differently under a Turkish host locale.
44
+ */
45
+ export declare function normalizeModelTagName(name: string): string;
46
+ /**
47
+ * Does a model carrying `memberTagIds` satisfy `op` over `ruleTagIds`?
48
+ *
49
+ * `definedTagIds` is the set of tags that currently EXIST. A rule naming a tag
50
+ * that no longer exists is UNRESOLVED and matches nothing, whatever the op:
51
+ * `hasNone [deleted]` would otherwise be true of every model — the silent
52
+ * broadening the issue forbids — and `hasAny [deleted]` false of every model,
53
+ * which happens to be the same answer but for the wrong reason. Callers
54
+ * surface the unresolved ids through {@link unresolvedModelTagIds} rather than
55
+ * inferring them from an empty result.
56
+ *
57
+ * `untagged` names no tag and so can never be unresolved.
58
+ */
59
+ export declare function modelTagRuleMatches(op: ModelTagOp, ruleTagIds: readonly string[], memberTagIds: ReadonlySet<string> | undefined, definedTagIds: ReadonlySet<string>): boolean;
60
+ /** The tag ids `rule` names that are not in `definedTagIds`, in rule order, deduped. */
61
+ export declare function unresolvedModelTagIds(rule: {
62
+ op: ModelTagOp;
63
+ tagIds: readonly string[];
64
+ }, definedTagIds: ReadonlySet<string>): string[];
65
+ //# sourceMappingURL=model-tag.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-tag.d.ts","sourceRoot":"","sources":["../../src/filter/model-tag.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,WAAW,QAAQ;IACvB,0EAA0E;IAC1E,EAAE,EAAE,MAAM,CAAC;IACX,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,CAAC;AAEtE,eAAO,MAAM,aAAa,EAAE,SAAS,UAAU,EAAgD,CAAC;AAEhG,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAEhE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,UAAU,EACd,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS,EAC7C,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,GACjC,OAAO,CAUT;AAED,wFAAwF;AACxF,wBAAgB,qBAAqB,CACnC,IAAI,EAAE;IAAE,EAAE,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,EACnD,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,GACjC,MAAM,EAAE,CAOV"}
@@ -0,0 +1,57 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ export const MODEL_TAG_OPS = ['hasAny', 'hasAll', 'hasNone', 'untagged'];
5
+ export function isModelTagOp(value) {
6
+ return typeof value === 'string' && MODEL_TAG_OPS.includes(value);
7
+ }
8
+ /**
9
+ * The name key two tags are compared by: trimmed, case-folded. Locale-
10
+ * independent on purpose: the key decides identity across machines (a setup
11
+ * file's "Structure" must land on this machine's "structure"), and
12
+ * `toLocaleLowerCase` folds "I" differently under a Turkish host locale.
13
+ */
14
+ export function normalizeModelTagName(name) {
15
+ return name.trim().toLowerCase();
16
+ }
17
+ /**
18
+ * Does a model carrying `memberTagIds` satisfy `op` over `ruleTagIds`?
19
+ *
20
+ * `definedTagIds` is the set of tags that currently EXIST. A rule naming a tag
21
+ * that no longer exists is UNRESOLVED and matches nothing, whatever the op:
22
+ * `hasNone [deleted]` would otherwise be true of every model — the silent
23
+ * broadening the issue forbids — and `hasAny [deleted]` false of every model,
24
+ * which happens to be the same answer but for the wrong reason. Callers
25
+ * surface the unresolved ids through {@link unresolvedModelTagIds} rather than
26
+ * inferring them from an empty result.
27
+ *
28
+ * `untagged` names no tag and so can never be unresolved.
29
+ */
30
+ export function modelTagRuleMatches(op, ruleTagIds, memberTagIds, definedTagIds) {
31
+ const members = memberTagIds ?? EMPTY;
32
+ if (op === 'untagged')
33
+ return members.size === 0;
34
+ if (ruleTagIds.length === 0)
35
+ return false;
36
+ for (const id of ruleTagIds)
37
+ if (!definedTagIds.has(id))
38
+ return false;
39
+ switch (op) {
40
+ case 'hasAny': return ruleTagIds.some((id) => members.has(id));
41
+ case 'hasAll': return ruleTagIds.every((id) => members.has(id));
42
+ case 'hasNone': return !ruleTagIds.some((id) => members.has(id));
43
+ }
44
+ }
45
+ /** The tag ids `rule` names that are not in `definedTagIds`, in rule order, deduped. */
46
+ export function unresolvedModelTagIds(rule, definedTagIds) {
47
+ if (rule.op === 'untagged')
48
+ return [];
49
+ const out = [];
50
+ for (const id of rule.tagIds) {
51
+ if (!definedTagIds.has(id) && !out.includes(id))
52
+ out.push(id);
53
+ }
54
+ return out;
55
+ }
56
+ const EMPTY = new Set();
57
+ //# sourceMappingURL=model-tag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-tag.js","sourceRoot":"","sources":["../../src/filter/model-tag.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAyC/D,MAAM,CAAC,MAAM,aAAa,GAA0B,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;AAEhG,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAK,aAAmC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC3F,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AACnC,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CACjC,EAAc,EACd,UAA6B,EAC7B,YAA6C,EAC7C,aAAkC;IAElC,MAAM,OAAO,GAAG,YAAY,IAAI,KAAK,CAAC;IACtC,IAAI,EAAE,KAAK,UAAU;QAAE,OAAO,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC;IACjD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1C,KAAK,MAAM,EAAE,IAAI,UAAU;QAAE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,OAAO,KAAK,CAAC;IACtE,QAAQ,EAAE,EAAE,CAAC;QACX,KAAK,QAAQ,CAAC,CAAC,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/D,KAAK,QAAQ,CAAC,CAAC,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAChE,KAAK,SAAS,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACnE,CAAC;AACH,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,qBAAqB,CACnC,IAAmD,EACnD,aAAkC;IAElC,IAAI,IAAI,CAAC,EAAE,KAAK,UAAU;QAAE,OAAO,EAAE,CAAC;IACtC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAC7B,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,KAAK,GAAwB,IAAI,GAAG,EAAE,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * `property` and `quantity` subjects for `readSubject`: the values, the
3
+ * unit each is recorded in (#5300), its SI factor (#5225), and the
4
+ * `inherit` option (#5433). Split out of `read-subject.ts` for size.
5
+ *
6
+ * `inherit` (`SubjectReadOptions`):
7
+ * - absent: the element's own values; a property also reads its type's
8
+ * property sets, per IFC's own inheritance (as it always has).
9
+ * - `'type'`: a quantity also reads its type's quantity sets (properties
10
+ * already do, so for them it changes nothing).
11
+ * - `'aggregation'`: when the element has no value of its own (type values
12
+ * included, quantities too), the nearest `IfcRelAggregates` ancestor
13
+ * that has one supplies it. The walk is iterative with a visited set (AGENTS.md
14
+ * "Bounding walks"), so a cyclic aggregation in a broken file ends.
15
+ */
16
+ import { type IfcDataStore } from '@ifc-lite/parser';
17
+ import type { PropertyRule, QuantityRule } from './filter-rules.js';
18
+ type MeasureSubject = Omit<PropertyRule, 'op' | 'value' | 'valueKind'> | Omit<QuantityRule, 'op' | 'value'>;
19
+ export interface MeasureValue {
20
+ present: boolean;
21
+ values: ReadonlyArray<string | number>;
22
+ unit?: string;
23
+ valueUnits: ReadonlyArray<string | undefined>;
24
+ valueSiScales: ReadonlyArray<number | undefined>;
25
+ }
26
+ export declare function readMeasureSubject(subject: MeasureSubject, store: IfcDataStore, expressId: number): MeasureValue;
27
+ export {};
28
+ //# sourceMappingURL=read-measure-subject.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-measure-subject.d.ts","sourceRoot":"","sources":["../../src/filter/read-measure-subject.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAOL,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIpE,KAAK,cAAc,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,GAAG,OAAO,GAAG,WAAW,CAAC,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,GAAG,OAAO,CAAC,CAAC;AAE5G,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,aAAa,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC9C,aAAa,EAAE,aAAa,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CAClD;AAwED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY,CAiBhH"}
@@ -0,0 +1,116 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /**
5
+ * `property` and `quantity` subjects for `readSubject`: the values, the
6
+ * unit each is recorded in (#5300), its SI factor (#5225), and the
7
+ * `inherit` option (#5433). Split out of `read-subject.ts` for size.
8
+ *
9
+ * `inherit` (`SubjectReadOptions`):
10
+ * - absent: the element's own values; a property also reads its type's
11
+ * property sets, per IFC's own inheritance (as it always has).
12
+ * - `'type'`: a quantity also reads its type's quantity sets (properties
13
+ * already do, so for them it changes nothing).
14
+ * - `'aggregation'`: when the element has no value of its own (type values
15
+ * included, quantities too), the nearest `IfcRelAggregates` ancestor
16
+ * that has one supplies it. The walk is iterative with a visited set (AGENTS.md
17
+ * "Bounding walks"), so a cyclic aggregation in a broken file ends.
18
+ */
19
+ import { extractPropertiesOnDemand, extractQuantitiesOnDemand, extractTypePropertiesOnDemand, extractTypeQuantitiesOnDemand, mergeInheritedPropertySets, mergeInheritedQuantitySets, } from '@ifc-lite/parser';
20
+ import { RelationshipType } from '@ifc-lite/data';
21
+ import { nameMatches, stringifyValue } from './filter-match.js';
22
+ import { projectSiScale, projectUnitSymbol, quantityValueSiScale, QUANTITY_MEASURE_TYPE } from './measure-units.js';
23
+ /** `expressId`'s type-level property sets via `IfcRelDefinesByType`. */
24
+ function inheritedTypePsets(store, expressId) {
25
+ if (!store.relationships)
26
+ return [];
27
+ const typeIds = store.relationships.getRelated(expressId, RelationshipType.DefinesByType, 'inverse');
28
+ if (typeIds.length === 0)
29
+ return [];
30
+ if (store.source && store.source.length > 0) {
31
+ return extractTypePropertiesOnDemand(store, expressId)?.properties ?? [];
32
+ }
33
+ return (store.properties?.getForEntity?.(typeIds[0]) ?? []);
34
+ }
35
+ function readProperty(subject, store, expressId) {
36
+ const merged = mergeInheritedPropertySets(extractPropertiesOnDemand(store, expressId), inheritedTypePsets(store, expressId));
37
+ const values = [];
38
+ const valueUnits = [];
39
+ const valueSiScales = [];
40
+ for (const set of merged) {
41
+ if (!nameMatches(subject.setName, set.name, subject.setNameKind))
42
+ continue;
43
+ for (const p of set.properties) {
44
+ if (!nameMatches(subject.propertyName, p.name, subject.propertyNameKind))
45
+ continue;
46
+ values.push(stringifyValue(p.value));
47
+ // Own and type-level rows alike carry the property's explicit `Unit`
48
+ // when it has one (both come from `extractPsetsFromIds`).
49
+ valueUnits.push(p.unit ?? projectUnitSymbol(store, p.dataType));
50
+ valueSiScales.push(p.unit !== undefined ? p.unitSiScale : projectSiScale(store, p.dataType));
51
+ }
52
+ }
53
+ return { present: values.some((v) => v.trim().length > 0), values, valueUnits, valueSiScales };
54
+ }
55
+ /**
56
+ * `expressId`'s type-level quantity sets: parsed from the source, or for a
57
+ * table-backed (server-parsed) store with no source, the type's rows in
58
+ * `store.quantities`, the same branch `inheritedTypePsets` takes (review, #5440).
59
+ */
60
+ function inheritedTypeQsets(store, expressId) {
61
+ if (store.source && store.source.length > 0)
62
+ return extractTypeQuantitiesOnDemand(store, expressId)?.quantities ?? [];
63
+ const typeIds = store.relationships?.getRelated(expressId, RelationshipType.DefinesByType, 'inverse') ?? [];
64
+ return typeIds.length > 0 ? (store.quantities?.getForEntity?.(typeIds[0]) ?? []) : [];
65
+ }
66
+ function readQuantity(subject, store, expressId) {
67
+ const own = extractQuantitiesOnDemand(store, expressId);
68
+ // Both options read the type's quantities: 'aggregation' falls back to
69
+ // the aggregate parent only when neither the element nor its type has
70
+ // the value, the same "own (type included) first" rule as properties.
71
+ const sets = subject.inherit === 'type' || subject.inherit === 'aggregation'
72
+ ? mergeInheritedQuantitySets(own, inheritedTypeQsets(store, expressId))
73
+ : own;
74
+ const values = [];
75
+ const valueUnits = [];
76
+ const valueSiScales = [];
77
+ for (const qset of sets) {
78
+ if (!nameMatches(subject.setName, qset.name, subject.setNameKind))
79
+ continue;
80
+ for (const q of qset.quantities) {
81
+ if (!nameMatches(subject.quantityName, q.name, subject.quantityNameKind))
82
+ continue;
83
+ values.push(q.value);
84
+ // An explicit `IfcPhysicalSimpleQuantity.Unit` overrides the project
85
+ // assignment, for display as much as for the check.
86
+ valueUnits.push(q.explicitUnit ?? projectUnitSymbol(store, QUANTITY_MEASURE_TYPE[q.type]));
87
+ valueSiScales.push(quantityValueSiScale(store, q));
88
+ }
89
+ }
90
+ return { present: values.length > 0, values, unit: valueUnits.find((u) => u !== undefined), valueUnits, valueSiScales };
91
+ }
92
+ function readOwn(subject, store, expressId) {
93
+ return subject.kind === 'property' ? readProperty(subject, store, expressId) : readQuantity(subject, store, expressId);
94
+ }
95
+ export function readMeasureSubject(subject, store, expressId) {
96
+ const own = readOwn(subject, store, expressId);
97
+ if (own.present || subject.inherit !== 'aggregation' || !store.relationships)
98
+ return own;
99
+ const visited = new Set([expressId]);
100
+ let frontier = store.relationships.getRelated(expressId, RelationshipType.Aggregates, 'inverse');
101
+ while (frontier.length > 0) {
102
+ const next = [];
103
+ for (const parent of frontier) {
104
+ if (visited.has(parent))
105
+ continue;
106
+ visited.add(parent);
107
+ const value = readOwn(subject, store, parent);
108
+ if (value.present)
109
+ return value;
110
+ next.push(...store.relationships.getRelated(parent, RelationshipType.Aggregates, 'inverse'));
111
+ }
112
+ frontier = next;
113
+ }
114
+ return own;
115
+ }
116
+ //# sourceMappingURL=read-measure-subject.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-measure-subject.js","sourceRoot":"","sources":["../../src/filter/read-measure-subject.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * `readSubject` — the ONE reader the information-validation engine (#5138 PR
3
+ * 3, `lib/validation/rule-engine*.ts`) uses to pull a `Subject`'s raw values
4
+ * off one element, before any operator is applied. New file rather than
5
+ * grown into `filter-match.ts` (already 353 lines; the plan's own size
6
+ * budget note applies) — and, more importantly, a NEW function rather than a
7
+ * literal `matchXRule → op(readSubject(...))` refactor of the existing
8
+ * search matchers there.
9
+ *
10
+ * Why not the refactor the plan describes as the default: every existing
11
+ * matcher's absent-handling is tuned to SEARCH's own convention, and that
12
+ * convention is not uniform across rule kinds — `stringOpMatches` (used by
13
+ * `name`/`type`/`parent` inline in `filter-evaluate.ts`) matches `ne` /
14
+ * `notContains` / `notMatches` TRUE on an absent candidate (a missing Name
15
+ * satisfies "Name != Foo"), while `matchAttributeRule` / `matchPropertyRule`
16
+ * already fail every op but `isNotSet` on absent. Validation needs the
17
+ * SECOND convention for every subject, uniformly (plan §4 item 2: "every
18
+ * operator except isNotSet fails on present === false with absent" — so
19
+ * `ne`/`notContains`/`notMatches` become proper negations, not "vacuously
20
+ * true on absent"). Reusing `stringOpMatches`'s existing undefined branch
21
+ * for `name`/`type`/`parent` would import the WRONG convention; changing
22
+ * that branch would change search's own `ne`/`notContains` results
23
+ * (`filter-evaluate-absent-name.test.ts` pins the current behaviour). So
24
+ * `readSubject` reads values only — presence and per-op pass/fail rules are
25
+ * the validation engine's own concern (`rule-engine-requirements.ts`),
26
+ * applied via `matchStringAnyNone`/`valueOpMatches`/`numericOpMatches`
27
+ * (`filter-ops.ts`) with an empty candidate list standing in for "absent",
28
+ * which already fails every op (`matchStringAnyNone`'s own `candidates.
29
+ * length === 0` branch — see that engine module for how this is used).
30
+ *
31
+ * `filter-match.ts` is UNCHANGED by this file (0-line diff) — every matcher
32
+ * it exports keeps meaning exactly what it means today.
33
+ */
34
+ import { type IfcDataStore } from '@ifc-lite/parser';
35
+ import type { Subject } from '../rule-set/rule-set.js';
36
+ /** What `readSubject` needs about the element it reads. No `mutationView` —
37
+ * the engine reads the model as loaded, not with live in-session edits
38
+ * applied (those are a follow-up; noted in the PR body). */
39
+ export interface ReadSubjectContext {
40
+ store: IfcDataStore;
41
+ expressId: number;
42
+ }
43
+ /** The result `readSubject` returns for every `Subject` kind. */
44
+ export interface SubjectValue {
45
+ /** At least one value, after `String(v).trim()`, is non-empty (plan §4.2). */
46
+ present: boolean;
47
+ values: ReadonlyArray<string | number>;
48
+ /** Quantity subjects only — the stored unit label, when known. */
49
+ unit?: string;
50
+ /**
51
+ * Property and quantity subjects only: the unit each entry of `values` is
52
+ * recorded in, index for index (#5300). The value's own explicit `Unit`
53
+ * when the file declares one, otherwise the project unit for its measure
54
+ * type; `undefined` for a value that has no unit (a label, a count, an
55
+ * untyped property).
56
+ */
57
+ valueUnits?: ReadonlyArray<string | undefined>;
58
+ /**
59
+ * Property and quantity subjects only, aligned with `values`: the factor
60
+ * that turns each value into SI base units, from the same unit as
61
+ * `valueUnits`; `undefined` for a value with no unit (#5225).
62
+ */
63
+ valueSiScales?: ReadonlyArray<number | undefined>;
64
+ }
65
+ /**
66
+ * Read one `Subject`'s raw values off `ctx.expressId`. Callers may pass a
67
+ * full `FilterRule` in place of a `Subject` — every rule kind's shape is a
68
+ * structural superset of its `Subject` (`SubjectOf<R>` in `rule-set.ts`), so
69
+ * the extra `op`/`value`/`values` fields are simply ignored here.
70
+ */
71
+ export declare function readSubject(subject: Subject, ctx: ReadSubjectContext): SubjectValue;
72
+ //# sourceMappingURL=read-subject.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-subject.d.ts","sourceRoot":"","sources":["../../src/filter/read-subject.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAIL,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAMvD;;6DAE6D;AAC7D,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,iEAAiE;AACjE,MAAM,WAAW,YAAY;IAC3B,8EAA8E;IAC9E,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IACvC,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,aAAa,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC/C;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CACnD;AAiBD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,kBAAkB,GAAG,YAAY,CA+DnF"}
@@ -0,0 +1,128 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /**
5
+ * `readSubject` — the ONE reader the information-validation engine (#5138 PR
6
+ * 3, `lib/validation/rule-engine*.ts`) uses to pull a `Subject`'s raw values
7
+ * off one element, before any operator is applied. New file rather than
8
+ * grown into `filter-match.ts` (already 353 lines; the plan's own size
9
+ * budget note applies) — and, more importantly, a NEW function rather than a
10
+ * literal `matchXRule → op(readSubject(...))` refactor of the existing
11
+ * search matchers there.
12
+ *
13
+ * Why not the refactor the plan describes as the default: every existing
14
+ * matcher's absent-handling is tuned to SEARCH's own convention, and that
15
+ * convention is not uniform across rule kinds — `stringOpMatches` (used by
16
+ * `name`/`type`/`parent` inline in `filter-evaluate.ts`) matches `ne` /
17
+ * `notContains` / `notMatches` TRUE on an absent candidate (a missing Name
18
+ * satisfies "Name != Foo"), while `matchAttributeRule` / `matchPropertyRule`
19
+ * already fail every op but `isNotSet` on absent. Validation needs the
20
+ * SECOND convention for every subject, uniformly (plan §4 item 2: "every
21
+ * operator except isNotSet fails on present === false with absent" — so
22
+ * `ne`/`notContains`/`notMatches` become proper negations, not "vacuously
23
+ * true on absent"). Reusing `stringOpMatches`'s existing undefined branch
24
+ * for `name`/`type`/`parent` would import the WRONG convention; changing
25
+ * that branch would change search's own `ne`/`notContains` results
26
+ * (`filter-evaluate-absent-name.test.ts` pins the current behaviour). So
27
+ * `readSubject` reads values only — presence and per-op pass/fail rules are
28
+ * the validation engine's own concern (`rule-engine-requirements.ts`),
29
+ * applied via `matchStringAnyNone`/`valueOpMatches`/`numericOpMatches`
30
+ * (`filter-ops.ts`) with an empty candidate list standing in for "absent",
31
+ * which already fails every op (`matchStringAnyNone`'s own `candidates.
32
+ * length === 0` branch — see that engine module for how this is used).
33
+ *
34
+ * `filter-match.ts` is UNCHANGED by this file (0-line diff) — every matcher
35
+ * it exports keeps meaning exactly what it means today.
36
+ */
37
+ import { extractAllEntityAttributes, extractAllMaterialsOnDemand, extractClassificationsOnDemand, } from '@ifc-lite/parser';
38
+ import { RelationshipType, collectSpatialAncestors } from '@ifc-lite/data';
39
+ import { stringifyValue, defaultStoreyName, materialNamesOf } from './filter-match.js';
40
+ import { resolveEntityPredefinedType } from './entity-predefined-type.js';
41
+ import { readMeasureSubject } from './read-measure-subject.js';
42
+ import { assignedGroupNames } from './filter-group-rule.js';
43
+ function fromStrings(values) {
44
+ const defined = values.filter((v) => v !== undefined);
45
+ return { present: defined.some((v) => v.trim().length > 0), values: defined };
46
+ }
47
+ /** `expressId`'s relating TYPE object's Name, via `IfcRelDefinesByType` — the
48
+ * read-only twin of `filter-evaluate.ts`'s `relatingTypeNameOf`. */
49
+ function relatingTypeName(store, expressId) {
50
+ if (!store.relationships)
51
+ return undefined;
52
+ const typeIds = store.relationships.getRelated(expressId, RelationshipType.DefinesByType, 'inverse');
53
+ if (typeIds.length === 0)
54
+ return undefined;
55
+ return store.entities.getNameOrUndefined(typeIds[0]);
56
+ }
57
+ /**
58
+ * Read one `Subject`'s raw values off `ctx.expressId`. Callers may pass a
59
+ * full `FilterRule` in place of a `Subject` — every rule kind's shape is a
60
+ * structural superset of its `Subject` (`SubjectOf<R>` in `rule-set.ts`), so
61
+ * the extra `op`/`value`/`values` fields are simply ignored here.
62
+ */
63
+ export function readSubject(subject, ctx) {
64
+ const { store, expressId } = ctx;
65
+ switch (subject.kind) {
66
+ case 'attribute': {
67
+ const wanted = subject.name.toLowerCase();
68
+ const found = extractAllEntityAttributes(store, expressId).find((a) => a.name.toLowerCase() === wanted);
69
+ return fromStrings([found === undefined ? undefined : stringifyValue(found.value)]);
70
+ }
71
+ case 'property':
72
+ case 'quantity':
73
+ return readMeasureSubject(subject, store, expressId);
74
+ case 'classification': {
75
+ const sys = subject.system?.trim().toLowerCase();
76
+ const refs = extractClassificationsOnDemand(store, expressId).filter((r) => !r.unresolved && (!sys || (r.system ?? '').toLowerCase() === sys));
77
+ // BOTH the code AND the name per ref, not one-or-the-other — review
78
+ // finding: classification matching is code OR name
79
+ // (`matchClassificationRule`, filter-match.ts), so a rule matching
80
+ // either value must see it here too. A ref with `{identification:
81
+ // '123', name:'Fire rating'}` contributes TWO values; deduped so a
82
+ // ref whose code and name happen to be identical doesn't double-count.
83
+ const values = new Set();
84
+ for (const r of refs) {
85
+ if (r.identification)
86
+ values.add(r.identification);
87
+ if (r.name)
88
+ values.add(r.name);
89
+ }
90
+ return fromStrings([...values]);
91
+ }
92
+ case 'material': {
93
+ const names = new Set();
94
+ for (const info of extractAllMaterialsOnDemand(store, expressId)) {
95
+ for (const n of materialNamesOf(info))
96
+ names.add(n);
97
+ }
98
+ return fromStrings([...names]);
99
+ }
100
+ case 'name':
101
+ return fromStrings([store.entities.getNameOrUndefined(expressId)]);
102
+ case 'type':
103
+ return fromStrings([relatingTypeName(store, expressId)]);
104
+ case 'ifcType':
105
+ return fromStrings([store.entities.getTypeName(expressId)]);
106
+ case 'predefinedType':
107
+ return fromStrings([resolveEntityPredefinedType(store, expressId)]);
108
+ case 'globalId':
109
+ return fromStrings([store.entities.getGlobalId(expressId)]);
110
+ case 'storey': {
111
+ const name = defaultStoreyName(store, expressId);
112
+ return fromStrings([name.length > 0 ? name : undefined]);
113
+ }
114
+ case 'group': {
115
+ // Present = assigned to at least one such group, named or not (#5226):
116
+ // membership is the fact, a group's Name is only what value ops read.
117
+ const names = assignedGroupNames(store, expressId, subject.groupClass);
118
+ return { present: names.length > 0, values: names.filter((n) => n !== undefined) };
119
+ }
120
+ case 'parent': {
121
+ const names = store.relationships
122
+ ? collectSpatialAncestors(store.relationships, expressId).map((id) => store.entities.getNameOrUndefined(id))
123
+ : [];
124
+ return fromStrings(names);
125
+ }
126
+ }
127
+ }
128
+ //# sourceMappingURL=read-subject.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-subject.js","sourceRoot":"","sources":["../../src/filter/read-subject.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * `property` / `quantity` rules that set a {@link SubjectReadOptions} field
3
+ * are read through `readSubject`, the reader validation already uses, so
4
+ * the option means one thing in search, applicability and validation.
5
+ *
6
+ * `readSubject` reads the model as loaded. A live in-session edit is
7
+ * applied to plain property rules through the mutation overlay
8
+ * (`filter-evaluate-mutations.ts`), but not to a rule that sets one of these
9
+ * options. Validation has the same limitation today (see `read-subject.ts`).
10
+ */
11
+ import type { IfcDataStore } from '@ifc-lite/parser';
12
+ import type { PropertyRule, QuantityRule } from './filter-rules.js';
13
+ import { type SubjectValue } from './read-subject.js';
14
+ /**
15
+ * `subject` with every value that has a unit converted to SI base units.
16
+ * A value with no SI factor (a label, a count) is left as it is.
17
+ */
18
+ export declare function toSiValues(subject: SubjectValue): SubjectValue;
19
+ /** The subject's values as the rule compares them. */
20
+ export declare function readRuleSubject(rule: PropertyRule | QuantityRule, store: IfcDataStore, expressId: number): SubjectValue;
21
+ /**
22
+ * Search semantics (`matchPropertyRule` / `matchQuantityRule`), read through
23
+ * `readSubject`: presence ops ask whether any value exists, every other op
24
+ * passes when ANY value satisfies it.
25
+ */
26
+ export declare function matchRuleThroughSubject(rule: PropertyRule | QuantityRule, store: IfcDataStore, expressId: number): boolean;
27
+ //# sourceMappingURL=subject-match.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subject-match.d.ts","sourceRoot":"","sources":["../../src/filter/subject-match.ts"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEpE,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEnE;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,YAAY,CAgB9D;AAED,sDAAsD;AACtD,wBAAgB,eAAe,CAC7B,IAAI,EAAE,YAAY,GAAG,YAAY,EACjC,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,GAChB,YAAY,CAGd;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,YAAY,GAAG,YAAY,EACjC,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAQT"}
@@ -0,0 +1,52 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ import { numericOpMatches, valueOpMatches } from './filter-ops.js';
5
+ import { readSubject } from './read-subject.js';
6
+ /**
7
+ * `subject` with every value that has a unit converted to SI base units.
8
+ * A value with no SI factor (a label, a count) is left as it is.
9
+ */
10
+ export function toSiValues(subject) {
11
+ const scales = subject.valueSiScales;
12
+ if (!scales)
13
+ return subject;
14
+ let converted = false;
15
+ const values = subject.values.map((value, i) => {
16
+ const scale = scales[i];
17
+ if (scale === undefined)
18
+ return value;
19
+ const n = typeof value === 'number' ? value : Number(value);
20
+ if (typeof value === 'string' && value.trim() === '')
21
+ return value;
22
+ if (!Number.isFinite(n))
23
+ return value;
24
+ converted = true;
25
+ const si = n * scale;
26
+ return typeof value === 'number' ? si : String(si);
27
+ });
28
+ // The stored unit label no longer describes the values; say they are SI.
29
+ return converted ? { ...subject, values, unit: 'SI' } : subject;
30
+ }
31
+ /** The subject's values as the rule compares them. */
32
+ export function readRuleSubject(rule, store, expressId) {
33
+ const subject = readSubject(rule, { store, expressId });
34
+ return rule.valueUnit === 'si' ? toSiValues(subject) : subject;
35
+ }
36
+ /**
37
+ * Search semantics (`matchPropertyRule` / `matchQuantityRule`), read through
38
+ * `readSubject`: presence ops ask whether any value exists, every other op
39
+ * passes when ANY value satisfies it.
40
+ */
41
+ export function matchRuleThroughSubject(rule, store, expressId) {
42
+ const subject = readRuleSubject(rule, store, expressId);
43
+ if (rule.kind === 'quantity') {
44
+ return subject.values.some((v) => numericOpMatches(rule.op, Number(v), rule.value));
45
+ }
46
+ if (rule.op === 'isSet')
47
+ return subject.present;
48
+ if (rule.op === 'isNotSet')
49
+ return !subject.present;
50
+ return subject.values.some((v) => valueOpMatches(rule.op, String(v), rule.value, rule.valueKind));
51
+ }
52
+ //# sourceMappingURL=subject-match.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subject-match.js","sourceRoot":"","sources":["../../src/filter/subject-match.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAe/D,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,WAAW,EAAqB,MAAM,mBAAmB,CAAC;AAEnE;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,OAAqB;IAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IACrC,IAAI,CAAC,MAAM;QAAE,OAAO,OAAO,CAAC;IAC5B,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QACtC,MAAM,CAAC,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,KAAK,CAAC;QACnE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QACtC,SAAS,GAAG,IAAI,CAAC;QACjB,MAAM,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC;QACrB,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IACH,yEAAyE;IACzE,OAAO,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;AAClE,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,eAAe,CAC7B,IAAiC,EACjC,KAAmB,EACnB,SAAiB;IAEjB,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IACxD,OAAO,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;AACjE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CACrC,IAAiC,EACjC,KAAmB,EACnB,SAAiB;IAEjB,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IACxD,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC7B,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACtF,CAAC;IACD,IAAI,IAAI,CAAC,EAAE,KAAK,OAAO;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC;IAChD,IAAI,IAAI,CAAC,EAAE,KAAK,UAAU;QAAE,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;IACpD,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;AACpG,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Options on `property` and `quantity` rules that change HOW the value is
3
+ * read, not what it is compared with. Their own module because
4
+ * `filter-rules.ts` sits at the module-size cap; `PropertyRule` and
5
+ * `QuantityRule` extend this interface.
6
+ *
7
+ * A rule that sets any of these is matched through `readSubject` (see
8
+ * `subject-match.ts`) in search and applicability as well as in validation,
9
+ * so the option means the same thing in every context.
10
+ */
11
+ export interface SubjectReadOptions {
12
+ /**
13
+ * `'si'`: the rule's numeric operand is in SI base units (metres, square
14
+ * metres, cubic metres), the way IDS states measure values. Each value is
15
+ * converted to SI with its own unit (an explicit `Unit` on the property or
16
+ * quantity, else the project unit for its measure type) before comparing.
17
+ * Values with no unit (labels, counts) are compared as stored. Absent:
18
+ * the operand is in the model's own units (#5225).
19
+ */
20
+ valueUnit?: 'si';
21
+ /**
22
+ * Where a missing value may come from (#5433). `'type'`: a quantity also
23
+ * reads its type's quantity sets (properties always read their type's
24
+ * property sets). `'aggregation'`: an element with no value of its own
25
+ * (its type's included, for quantities too) takes the nearest
26
+ * `IfcRelAggregates` ancestor's. Never implicit: absent
27
+ * means the element's own (and, for properties, its type's) values only.
28
+ */
29
+ inherit?: 'type' | 'aggregation';
30
+ }
31
+ /** Whether `rule` has to be matched through the subject reader. */
32
+ export declare function readsThroughSubject(rule: SubjectReadOptions): boolean;
33
+ //# sourceMappingURL=subject-read-options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subject-read-options.d.ts","sourceRoot":"","sources":["../../src/filter/subject-read-options.ts"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AAEH,MAAM,WAAW,kBAAkB;IACjC;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;CAClC;AAED,mEAAmE;AACnE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAErE"}