@ifc-lite/ids 1.15.53 → 1.16.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.
- package/dist/bridge/ancestors.d.ts +14 -0
- package/dist/bridge/ancestors.d.ts.map +1 -0
- package/dist/bridge/ancestors.js +76 -0
- package/dist/bridge/ancestors.js.map +1 -0
- package/dist/bridge/classifications.d.ts +39 -0
- package/dist/bridge/classifications.d.ts.map +1 -1
- package/dist/bridge/classifications.js +112 -2
- package/dist/bridge/classifications.js.map +1 -1
- package/dist/bridge/data-accessor.d.ts +10 -1
- package/dist/bridge/data-accessor.d.ts.map +1 -1
- package/dist/bridge/data-accessor.js +25 -66
- package/dist/bridge/data-accessor.js.map +1 -1
- package/dist/bridge/index.d.ts +3 -0
- package/dist/bridge/index.d.ts.map +1 -1
- package/dist/bridge/index.js +1 -0
- package/dist/bridge/index.js.map +1 -1
- package/dist/bridge/property-overlay-resolver.d.ts +70 -0
- package/dist/bridge/property-overlay-resolver.d.ts.map +1 -0
- package/dist/bridge/property-overlay-resolver.js +122 -0
- package/dist/bridge/property-overlay-resolver.js.map +1 -0
- package/dist/bridge/units.d.ts +27 -0
- package/dist/bridge/units.d.ts.map +1 -1
- package/dist/bridge/units.js +79 -15
- package/dist/bridge/units.js.map +1 -1
- package/dist/facets/classification-facet.d.ts.map +1 -1
- package/dist/facets/classification-facet.js +76 -4
- package/dist/facets/classification-facet.js.map +1 -1
- package/dist/translation/locales/de.d.ts +2 -0
- package/dist/translation/locales/de.d.ts.map +1 -1
- package/dist/translation/locales/de.js +2 -0
- package/dist/translation/locales/de.js.map +1 -1
- package/dist/translation/locales/en.d.ts +2 -0
- package/dist/translation/locales/en.d.ts.map +1 -1
- package/dist/translation/locales/en.js +2 -0
- package/dist/translation/locales/en.js.map +1 -1
- package/dist/translation/locales/fr.d.ts +2 -0
- package/dist/translation/locales/fr.d.ts.map +1 -1
- package/dist/translation/locales/fr.js +2 -0
- package/dist/translation/locales/fr.js.map +1 -1
- package/dist/translation/service.d.ts +1 -3
- package/dist/translation/service.d.ts.map +1 -1
- package/dist/translation/service.js +3 -3
- package/dist/translation/service.js.map +1 -1
- package/dist/types.d.ts +3 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/validation/validator.d.ts +5 -0
- package/dist/validation/validator.d.ts.map +1 -1
- package/dist/validation/validator.js +7 -7
- package/dist/validation/validator.js.map +1 -1
- package/package.json +4 -3
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type IfcDataStore } from '@ifc-lite/parser';
|
|
2
|
+
import type { PartOfRelation, ParentInfo } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* BFS walk of the partOf ancestor graph for `expressId`, following the
|
|
5
|
+
* edge type(s) `relationType` maps to. IDS partOf is transitive, so any
|
|
6
|
+
* reachable ancestor counts; the merged voids/fills relation walks two
|
|
7
|
+
* edge types per node, so the queue follows each mapped type in turn.
|
|
8
|
+
*
|
|
9
|
+
* The three type/name resolvers are passed in rather than closed over so
|
|
10
|
+
* this can run standalone from the accessor's own method table (which is
|
|
11
|
+
* how `IFCDataAccessor.getAncestors` calls it).
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolvePartOfAncestors(store: IfcDataStore, expressId: number, relationType: PartOfRelation, getEntityType: (expressId: number) => string | undefined, getPredefinedTypeRaw: (expressId: number) => string | undefined, getObjectType: (expressId: number) => string | undefined): ParentInfo[];
|
|
14
|
+
//# sourceMappingURL=ancestors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ancestors.d.ts","sourceRoot":"","sources":["../../src/bridge/ancestors.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGrD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA2B9D;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,cAAc,EAC5B,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,EACxD,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,EAC/D,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,GACvD,UAAU,EAAE,CAkCd"}
|
|
@@ -0,0 +1,76 @@
|
|
|
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 { RelationshipType } from '@ifc-lite/data';
|
|
5
|
+
// Map IDS PartOf relations to the numeric RelationshipType enum the
|
|
6
|
+
// graph keys on. Passing strings here was a long-standing silent bug:
|
|
7
|
+
// `getRelated` matched nothing → every partOf check looked like
|
|
8
|
+
// "no parent" → fail-when-required, pass-when-prohibited.
|
|
9
|
+
//
|
|
10
|
+
// Each relation maps to a LIST of edge types the ancestor walk follows.
|
|
11
|
+
// All but the merged voids/fills token map to a single type; the IDS XSD
|
|
12
|
+
// merged voids + fills into one enumeration value
|
|
13
|
+
// (`IFCRELVOIDSELEMENT IFCRELFILLSELEMENT`) that links an element to its
|
|
14
|
+
// host building element through an opening — a window fills an opening
|
|
15
|
+
// (`FillsElement`) that voids a wall (`VoidsElement`). Walking both edge
|
|
16
|
+
// types inverse-direction reaches the opening and the wall in turn.
|
|
17
|
+
const PARTOF_REL_MAP = {
|
|
18
|
+
IfcRelAggregates: [RelationshipType.Aggregates],
|
|
19
|
+
IfcRelAssignsToGroup: [RelationshipType.AssignsToGroup],
|
|
20
|
+
IfcRelContainedInSpatialStructure: [RelationshipType.ContainsElements],
|
|
21
|
+
IfcRelNests: [RelationshipType.Aggregates],
|
|
22
|
+
IfcRelVoidsElement: [RelationshipType.VoidsElement],
|
|
23
|
+
IfcRelFillsElement: [RelationshipType.FillsElement],
|
|
24
|
+
'IfcRelVoidsElement IfcRelFillsElement': [
|
|
25
|
+
RelationshipType.VoidsElement,
|
|
26
|
+
RelationshipType.FillsElement,
|
|
27
|
+
],
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* BFS walk of the partOf ancestor graph for `expressId`, following the
|
|
31
|
+
* edge type(s) `relationType` maps to. IDS partOf is transitive, so any
|
|
32
|
+
* reachable ancestor counts; the merged voids/fills relation walks two
|
|
33
|
+
* edge types per node, so the queue follows each mapped type in turn.
|
|
34
|
+
*
|
|
35
|
+
* The three type/name resolvers are passed in rather than closed over so
|
|
36
|
+
* this can run standalone from the accessor's own method table (which is
|
|
37
|
+
* how `IFCDataAccessor.getAncestors` calls it).
|
|
38
|
+
*/
|
|
39
|
+
export function resolvePartOfAncestors(store, expressId, relationType, getEntityType, getPredefinedTypeRaw, getObjectType) {
|
|
40
|
+
const relationships = store.relationships;
|
|
41
|
+
if (!relationships?.getRelated)
|
|
42
|
+
return [];
|
|
43
|
+
const relTypes = PARTOF_REL_MAP[relationType];
|
|
44
|
+
if (!relTypes || relTypes.length === 0)
|
|
45
|
+
return [];
|
|
46
|
+
const out = [];
|
|
47
|
+
const seen = new Set([expressId]);
|
|
48
|
+
const queue = [expressId];
|
|
49
|
+
while (queue.length > 0) {
|
|
50
|
+
const id = queue.shift();
|
|
51
|
+
for (const relType of relTypes) {
|
|
52
|
+
const parents = relationships.getRelated(id, relType, 'inverse');
|
|
53
|
+
for (const parentId of parents || []) {
|
|
54
|
+
if (seen.has(parentId))
|
|
55
|
+
continue;
|
|
56
|
+
seen.add(parentId);
|
|
57
|
+
out.push({
|
|
58
|
+
expressId: parentId,
|
|
59
|
+
entityType: getEntityType(parentId) || 'Unknown',
|
|
60
|
+
// Raw enum token first (BEAM, USERDEFINED, …) — NOT
|
|
61
|
+
// getObjectType. getObjectType collapses USERDEFINED to the
|
|
62
|
+
// accompanying user-defined name, which loses the literal
|
|
63
|
+
// "USERDEFINED" token a spec may legitimately ask for (the
|
|
64
|
+
// same case entity-facet.ts's rawType branch accepts for a
|
|
65
|
+
// direct entity check). The user-defined name is carried
|
|
66
|
+
// separately in `objectType` as a fallback for partof-facet.
|
|
67
|
+
predefinedType: getPredefinedTypeRaw(parentId),
|
|
68
|
+
objectType: getObjectType(parentId),
|
|
69
|
+
});
|
|
70
|
+
queue.push(parentId);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=ancestors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ancestors.js","sourceRoot":"","sources":["../../src/bridge/ancestors.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAG/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAIlD,oEAAoE;AACpE,sEAAsE;AACtE,gEAAgE;AAChE,0DAA0D;AAC1D,EAAE;AACF,wEAAwE;AACxE,yEAAyE;AACzE,kDAAkD;AAClD,yEAAyE;AACzE,uEAAuE;AACvE,yEAAyE;AACzE,oEAAoE;AACpE,MAAM,cAAc,GAAwD;IAC1E,gBAAgB,EAAE,CAAC,gBAAgB,CAAC,UAAU,CAAC;IAC/C,oBAAoB,EAAE,CAAC,gBAAgB,CAAC,cAAc,CAAC;IACvD,iCAAiC,EAAE,CAAC,gBAAgB,CAAC,gBAAgB,CAAC;IACtE,WAAW,EAAE,CAAC,gBAAgB,CAAC,UAAU,CAAC;IAC1C,kBAAkB,EAAE,CAAC,gBAAgB,CAAC,YAAY,CAAC;IACnD,kBAAkB,EAAE,CAAC,gBAAgB,CAAC,YAAY,CAAC;IACnD,uCAAuC,EAAE;QACvC,gBAAgB,CAAC,YAAY;QAC7B,gBAAgB,CAAC,YAAY;KAC9B;CACF,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,UAAU,sBAAsB,CACpC,KAAmB,EACnB,SAAiB,EACjB,YAA4B,EAC5B,aAAwD,EACxD,oBAA+D,EAC/D,aAAwD;IAExD,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;IAC1C,IAAI,CAAC,aAAa,EAAE,UAAU;QAAE,OAAO,EAAE,CAAC;IAC1C,MAAM,QAAQ,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;IAC9C,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAElD,MAAM,GAAG,GAAiB,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,IAAI,GAAG,CAAS,CAAC,SAAS,CAAC,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,CAAC,SAAS,CAAC,CAAC;IAC1B,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,EAAG,CAAC;QAC1B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,OAAO,GAAG,aAAa,CAAC,UAAU,CAAC,EAAE,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;YACjE,KAAK,MAAM,QAAQ,IAAI,OAAO,IAAI,EAAE,EAAE,CAAC;gBACrC,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;oBAAE,SAAS;gBACjC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBACnB,GAAG,CAAC,IAAI,CAAC;oBACP,SAAS,EAAE,QAAQ;oBACnB,UAAU,EAAE,aAAa,CAAC,QAAQ,CAAC,IAAI,SAAS;oBAChD,oDAAoD;oBACpD,4DAA4D;oBAC5D,0DAA0D;oBAC1D,2DAA2D;oBAC3D,2DAA2D;oBAC3D,yDAAyD;oBACzD,6DAA6D;oBAC7D,cAAc,EAAE,oBAAoB,CAAC,QAAQ,CAAC;oBAC9C,UAAU,EAAE,aAAa,CAAC,QAAQ,CAAC;iBACpC,CAAC,CAAC;gBACH,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -12,4 +12,43 @@ import type { ClassificationInfo } from '../types.js';
|
|
|
12
12
|
* for `EF_25_10` matches an actual leaf of `EF_25_10_25`.
|
|
13
13
|
*/
|
|
14
14
|
export declare function resolveClassifications(store: IfcDataStore, expressId: number): ClassificationInfo[];
|
|
15
|
+
/**
|
|
16
|
+
* Could an entity of this upper-cased type name be a `RelatedResourceObjects`
|
|
17
|
+
* target of an `IfcExternalReferenceRelationship`? The IFC schema restricts
|
|
18
|
+
* that role to `IfcResourceObjectSelect` members — subtypes of
|
|
19
|
+
* `IfcMaterialDefinition` or `IfcProfileDef` — never an `IfcRoot` subtype
|
|
20
|
+
* (`IfcWall`, `IfcDoor`, …), which can only be classified via
|
|
21
|
+
* `IfcRelAssociatesClassification`.
|
|
22
|
+
*
|
|
23
|
+
* This is a schema-hierarchy fact, answered here via `@ifc-lite/codegen`'s
|
|
24
|
+
* generated `SCHEMA_REGISTRY.entities[type].inheritanceChain` (through
|
|
25
|
+
* `isProperSubtypeOfAny` — `IfcMaterialDefinition` and `IfcProfileDef` are
|
|
26
|
+
* themselves abstract with no concrete instances, so the CONCRETE-MEMBER
|
|
27
|
+
* question this predicate answers wants the self-match excluded) rather
|
|
28
|
+
* than a string test — `startsWith`, `endsWith` and `includes` variants of
|
|
29
|
+
* this predicate were each wrong at a different edge across three separate
|
|
30
|
+
* incidents (ifc-lite #3999):
|
|
31
|
+
*
|
|
32
|
+
* 1. `startsWith('IFCMATERIAL')` admitted `IfcMaterialList` (an
|
|
33
|
+
* `IfcMaterialSelect` member, not `IfcMaterialDefinition`),
|
|
34
|
+
* `IfcMaterialLayerSetUsage`, `IfcMaterialDefinitionRepresentation`,
|
|
35
|
+
* `IfcMaterialRelationship` — none is `IfcMaterialDefinition`.
|
|
36
|
+
* 2. `endsWith('PROFILEDEF')` missed `IfcArbitraryProfileDefWithVoids`, a
|
|
37
|
+
* genuine `IfcProfileDef` subtype whose name doesn't end that way.
|
|
38
|
+
* 3. `includes('PROFILEDEF')` (the fix for #2) admitted
|
|
39
|
+
* `IfcRelAssociatesProfileDef`, a *rooted* relationship that points AT
|
|
40
|
+
* a profile def via `RelatingProfileDef`, not a profile def itself.
|
|
41
|
+
*
|
|
42
|
+
* `isProperSubtypeOfAny` reads the actual `SUBTYPE OF` chain the schemas declare,
|
|
43
|
+
* so none of those three edges is reachable by construction —
|
|
44
|
+
* `is-non-rooted-classifiable-resource.exp-derived.test.ts` still
|
|
45
|
+
* independently re-derives the answer from the `.exp` files and asserts
|
|
46
|
+
* agreement for every entity in both schemas, as a check against a bug in
|
|
47
|
+
* codegen's own chain computation, not just against a string test.
|
|
48
|
+
*
|
|
49
|
+
* Pulled out of `isNonRootedClassifiableResource` as a pure function of the
|
|
50
|
+
* type name so that test can exercise it directly against every entity name
|
|
51
|
+
* in both schemas, without building a store for each one.
|
|
52
|
+
*/
|
|
53
|
+
export declare function isNonRootedClassifiableResourceType(upperType: string): boolean;
|
|
15
54
|
//# sourceMappingURL=classifications.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classifications.d.ts","sourceRoot":"","sources":["../../src/bridge/classifications.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,YAAY,EAGlB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"classifications.d.ts","sourceRoot":"","sources":["../../src/bridge/classifications.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,YAAY,EAGlB,MAAM,kBAAkB,CAAC;AAI1B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAWtD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,GAChB,kBAAkB,EAAE,CA+BtB;AA0HD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,mCAAmC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAK9E"}
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
4
|
import { EntityExtractor, extractClassificationsOnDemand, } from '@ifc-lite/parser';
|
|
5
|
+
import { isProperSubtypeOfAny } from '@ifc-lite/codegen';
|
|
6
|
+
import * as IFC4_SCHEMA from '@ifc-lite/codegen/ifc4';
|
|
7
|
+
import * as IFC4X3_SCHEMA from '@ifc-lite/codegen/ifc4x3';
|
|
5
8
|
/**
|
|
6
9
|
* Resolve every classification associated with `expressId`, including
|
|
7
10
|
* 1. the standard `IfcRelAssociatesClassification` path (handled by
|
|
@@ -26,7 +29,13 @@ export function resolveClassifications(store, expressId) {
|
|
|
26
29
|
// even when the value is empty — so optional-cardinality value
|
|
27
30
|
// mismatches register as a value mismatch rather than as a
|
|
28
31
|
// missing-classification (which optional pardons).
|
|
29
|
-
out.push({
|
|
32
|
+
out.push({
|
|
33
|
+
system,
|
|
34
|
+
value: baseValue,
|
|
35
|
+
name: c.name,
|
|
36
|
+
unresolved: c.unresolved,
|
|
37
|
+
presenceUnknown: c.presenceUnknown,
|
|
38
|
+
});
|
|
30
39
|
if (Array.isArray(c.path)) {
|
|
31
40
|
for (const code of c.path) {
|
|
32
41
|
if (code && code !== baseValue) {
|
|
@@ -43,10 +52,44 @@ export function resolveClassifications(store, expressId) {
|
|
|
43
52
|
* `IfcRelAssociatesClassification`. The parser doesn't categorize
|
|
44
53
|
* external-ref edges into the relationship graph today, so we scan
|
|
45
54
|
* the type table directly.
|
|
55
|
+
*
|
|
56
|
+
* On a server-parsed (source-empty) store this type table is not merely
|
|
57
|
+
* incomplete — it structurally cannot contain `IFCEXTERNALREFERENCERELATIONSHIP`
|
|
58
|
+
* (or `IFCMATERIAL`/`IFCPROFILEDEF`) entries at all: the server pipeline's
|
|
59
|
+
* `IfcTypeEnum` (packages/data/src/types.ts) has no slot for any of them, and
|
|
60
|
+
* the server resolves classifications only via `IfcRelAssociatesClassification`
|
|
61
|
+
* (apps/server/src/services/data_model/classifications.rs). So an empty
|
|
62
|
+
* `byType` lookup here proves nothing about whether THIS entity carries a
|
|
63
|
+
* classification through this pathway — unlike the sibling
|
|
64
|
+
* `IfcRelAssociatesClassification` path (#3951), there is no
|
|
65
|
+
* relationship-graph fallback at all for this one (#3954): presence cannot
|
|
66
|
+
* be proven OR disproven without source bytes.
|
|
46
67
|
*/
|
|
47
68
|
function appendExternalReferenceClassifications(store, expressId, list) {
|
|
69
|
+
if (!store.source?.length) {
|
|
70
|
+
// Only fall back to "cannot determine" when:
|
|
71
|
+
// 1. the IfcRelAssociatesClassification path (already applied to `list`
|
|
72
|
+
// by the caller) found nothing — an entity already confirmed
|
|
73
|
+
// classified, or confirmed-but-unresolved, through that path doesn't
|
|
74
|
+
// also rely on this non-rooted-resource pathway, so leave it
|
|
75
|
+
// untouched rather than diluting a real match/mismatch into
|
|
76
|
+
// "unresolved"; and
|
|
77
|
+
// 2. `expressId` could actually BE a `RelatedResourceObjects` target —
|
|
78
|
+
// the IFC schema restricts that role to non-rooted resource-level
|
|
79
|
+
// entities (IfcResourceObjectSelect: IfcMaterial(Select) members,
|
|
80
|
+
// IfcProfileDef, …), never an IfcRoot subtype like IfcWall. A rooted
|
|
81
|
+
// element's `list.length === 0` genuinely means unclassified — no
|
|
82
|
+
// external-ref ambiguity is even schema-possible for it — so
|
|
83
|
+
// blanket-marking every empty result as unresolved would regress the
|
|
84
|
+
// overwhelming common case (a genuinely unclassified wall/door/etc.)
|
|
85
|
+
// into a false "cannot determine" on every server-parsed model.
|
|
86
|
+
if (list.length === 0 && isNonRootedClassifiableResource(store, expressId)) {
|
|
87
|
+
list.push({ unresolved: true, presenceUnknown: true });
|
|
88
|
+
}
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
48
91
|
const erRefs = store.entityIndex?.byType?.get?.('IFCEXTERNALREFERENCERELATIONSHIP') || [];
|
|
49
|
-
if (erRefs.length === 0
|
|
92
|
+
if (erRefs.length === 0)
|
|
50
93
|
return;
|
|
51
94
|
const ex = new EntityExtractor(store.source);
|
|
52
95
|
for (const erId of erRefs) {
|
|
@@ -111,4 +154,71 @@ function appendExternalReferenceClassifications(store, expressId, list) {
|
|
|
111
154
|
list.push(info);
|
|
112
155
|
}
|
|
113
156
|
}
|
|
157
|
+
/**
|
|
158
|
+
* The schema registries this predicate checks type membership against — the
|
|
159
|
+
* union of IFC4 and IFC4X3, since a type introduced in only one of them
|
|
160
|
+
* (`IfcOpenCrossProfileDef`, IFC4X3-only) must still be recognised when a
|
|
161
|
+
* store built from the OTHER schema is queried against it (a server-parsed
|
|
162
|
+
* store's `EntityRef.type` names an entity, not a schema version).
|
|
163
|
+
*/
|
|
164
|
+
const HIERARCHY_REGISTRIES = [
|
|
165
|
+
IFC4_SCHEMA.SCHEMA_REGISTRY,
|
|
166
|
+
IFC4X3_SCHEMA.SCHEMA_REGISTRY,
|
|
167
|
+
];
|
|
168
|
+
/**
|
|
169
|
+
* Could an entity of this upper-cased type name be a `RelatedResourceObjects`
|
|
170
|
+
* target of an `IfcExternalReferenceRelationship`? The IFC schema restricts
|
|
171
|
+
* that role to `IfcResourceObjectSelect` members — subtypes of
|
|
172
|
+
* `IfcMaterialDefinition` or `IfcProfileDef` — never an `IfcRoot` subtype
|
|
173
|
+
* (`IfcWall`, `IfcDoor`, …), which can only be classified via
|
|
174
|
+
* `IfcRelAssociatesClassification`.
|
|
175
|
+
*
|
|
176
|
+
* This is a schema-hierarchy fact, answered here via `@ifc-lite/codegen`'s
|
|
177
|
+
* generated `SCHEMA_REGISTRY.entities[type].inheritanceChain` (through
|
|
178
|
+
* `isProperSubtypeOfAny` — `IfcMaterialDefinition` and `IfcProfileDef` are
|
|
179
|
+
* themselves abstract with no concrete instances, so the CONCRETE-MEMBER
|
|
180
|
+
* question this predicate answers wants the self-match excluded) rather
|
|
181
|
+
* than a string test — `startsWith`, `endsWith` and `includes` variants of
|
|
182
|
+
* this predicate were each wrong at a different edge across three separate
|
|
183
|
+
* incidents (ifc-lite #3999):
|
|
184
|
+
*
|
|
185
|
+
* 1. `startsWith('IFCMATERIAL')` admitted `IfcMaterialList` (an
|
|
186
|
+
* `IfcMaterialSelect` member, not `IfcMaterialDefinition`),
|
|
187
|
+
* `IfcMaterialLayerSetUsage`, `IfcMaterialDefinitionRepresentation`,
|
|
188
|
+
* `IfcMaterialRelationship` — none is `IfcMaterialDefinition`.
|
|
189
|
+
* 2. `endsWith('PROFILEDEF')` missed `IfcArbitraryProfileDefWithVoids`, a
|
|
190
|
+
* genuine `IfcProfileDef` subtype whose name doesn't end that way.
|
|
191
|
+
* 3. `includes('PROFILEDEF')` (the fix for #2) admitted
|
|
192
|
+
* `IfcRelAssociatesProfileDef`, a *rooted* relationship that points AT
|
|
193
|
+
* a profile def via `RelatingProfileDef`, not a profile def itself.
|
|
194
|
+
*
|
|
195
|
+
* `isProperSubtypeOfAny` reads the actual `SUBTYPE OF` chain the schemas declare,
|
|
196
|
+
* so none of those three edges is reachable by construction —
|
|
197
|
+
* `is-non-rooted-classifiable-resource.exp-derived.test.ts` still
|
|
198
|
+
* independently re-derives the answer from the `.exp` files and asserts
|
|
199
|
+
* agreement for every entity in both schemas, as a check against a bug in
|
|
200
|
+
* codegen's own chain computation, not just against a string test.
|
|
201
|
+
*
|
|
202
|
+
* Pulled out of `isNonRootedClassifiableResource` as a pure function of the
|
|
203
|
+
* type name so that test can exercise it directly against every entity name
|
|
204
|
+
* in both schemas, without building a store for each one.
|
|
205
|
+
*/
|
|
206
|
+
export function isNonRootedClassifiableResourceType(upperType) {
|
|
207
|
+
return (isProperSubtypeOfAny(HIERARCHY_REGISTRIES, upperType, 'IfcMaterialDefinition') ||
|
|
208
|
+
isProperSubtypeOfAny(HIERARCHY_REGISTRIES, upperType, 'IfcProfileDef'));
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Could `expressId` be a `RelatedResourceObjects` target of an
|
|
212
|
+
* `IfcExternalReferenceRelationship`? See `isNonRootedClassifiableResourceType`
|
|
213
|
+
* for the schema rule this applies. `EntityRef.type` is available from the
|
|
214
|
+
* type-table index without reading `source` bytes (it's set from the raw
|
|
215
|
+
* STEP/server type name, not extracted attributes), so this check costs
|
|
216
|
+
* nothing on a server-parsed store.
|
|
217
|
+
*/
|
|
218
|
+
function isNonRootedClassifiableResource(store, expressId) {
|
|
219
|
+
const type = store.entityIndex?.byId?.get?.(expressId)?.type;
|
|
220
|
+
if (typeof type !== 'string')
|
|
221
|
+
return false;
|
|
222
|
+
return isNonRootedClassifiableResourceType(type.toUpperCase());
|
|
223
|
+
}
|
|
114
224
|
//# sourceMappingURL=classifications.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classifications.js","sourceRoot":"","sources":["../../src/bridge/classifications.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D,OAAO,EAEL,eAAe,EACf,8BAA8B,GAC/B,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"classifications.js","sourceRoot":"","sources":["../../src/bridge/classifications.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type IfcDataStore } from '@ifc-lite/parser';
|
|
2
2
|
import type { IFCDataAccessor } from '../types.js';
|
|
3
|
+
import { type PropertyOverride, type PropertyOverlayResolver } from './property-overlay-resolver.js';
|
|
4
|
+
export type { PropertyOverride, PropertyOverlayResolver };
|
|
3
5
|
/**
|
|
4
6
|
* Bridge an `IfcDataStore` (produced by `@ifc-lite/parser`) into the
|
|
5
7
|
* abstract `IFCDataAccessor` the IDS validator consumes. The single
|
|
@@ -12,6 +14,13 @@ import type { IFCDataAccessor } from '../types.js';
|
|
|
12
14
|
* non-rooted resources, length unit conversion, predefined property-set
|
|
13
15
|
* unwrapping, schema-driven attribute XSD types, USERDEFINED predicate
|
|
14
16
|
* substitution, partOf transitivity, etc.
|
|
17
|
+
*
|
|
18
|
+
* `propertyOverlay` is optional and lets a caller with in-memory,
|
|
19
|
+
* not-yet-exported property edits (e.g. an IDS correction applied through
|
|
20
|
+
* the viewer's `MutablePropertyView`) have those edits reflected in
|
|
21
|
+
* `getPropertyValue`/`getPropertySets` immediately, without re-parsing the
|
|
22
|
+
* store. Every other read (attributes, classifications, materials, partOf)
|
|
23
|
+
* is unaffected — only the two property-reading methods below consult it.
|
|
15
24
|
*/
|
|
16
|
-
export declare function createDataAccessor(store: IfcDataStore): IFCDataAccessor;
|
|
25
|
+
export declare function createDataAccessor(store: IfcDataStore, propertyOverlay?: PropertyOverlayResolver): IFCDataAccessor;
|
|
17
26
|
//# sourceMappingURL=data-accessor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-accessor.d.ts","sourceRoot":"","sources":["../../src/bridge/data-accessor.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,YAAY,EAGlB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EACV,eAAe,EAOhB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"data-accessor.d.ts","sourceRoot":"","sources":["../../src/bridge/data-accessor.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,YAAY,EAGlB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EACV,eAAe,EAOhB,MAAM,aAAa,CAAC;AAKrB,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,EAC7B,MAAM,gCAAgC,CAAC;AAOxC,YAAY,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,CAAC;AAM1D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,YAAY,EACnB,eAAe,CAAC,EAAE,uBAAuB,GACxC,eAAe,CAiPjB"}
|
|
@@ -5,33 +5,13 @@ import { extractAllEntityAttributes, extractAllMaterialsOnDemand, } from '@ifc-l
|
|
|
5
5
|
import { RelationshipType, getAttributeXsdTypes } from '@ifc-lite/data';
|
|
6
6
|
import { flattenMaterials } from './materials.js';
|
|
7
7
|
import { resolveClassifications } from './classifications.js';
|
|
8
|
-
import {
|
|
8
|
+
import { resolvePartOfAncestors } from './ancestors.js';
|
|
9
|
+
import { resolveEffectivePropertySets, } from './property-overlay-resolver.js';
|
|
9
10
|
import { resolveObjectType, resolveRawPredefinedType, } from './predefined-types.js';
|
|
10
11
|
import { narrowSchemaVersion } from './schema-version.js';
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
// "no parent" → fail-when-required, pass-when-prohibited.
|
|
15
|
-
//
|
|
16
|
-
// Each relation maps to a LIST of edge types the ancestor walk follows.
|
|
17
|
-
// All but the merged voids/fills token map to a single type; the IDS XSD
|
|
18
|
-
// merged voids + fills into one enumeration value
|
|
19
|
-
// (`IFCRELVOIDSELEMENT IFCRELFILLSELEMENT`) that links an element to its
|
|
20
|
-
// host building element through an opening — a window fills an opening
|
|
21
|
-
// (`FillsElement`) that voids a wall (`VoidsElement`). Walking both edge
|
|
22
|
-
// types inverse-direction reaches the opening and the wall in turn.
|
|
23
|
-
const PARTOF_REL_MAP = {
|
|
24
|
-
IfcRelAggregates: [RelationshipType.Aggregates],
|
|
25
|
-
IfcRelAssignsToGroup: [RelationshipType.AssignsToGroup],
|
|
26
|
-
IfcRelContainedInSpatialStructure: [RelationshipType.ContainsElements],
|
|
27
|
-
IfcRelNests: [RelationshipType.Aggregates],
|
|
28
|
-
IfcRelVoidsElement: [RelationshipType.VoidsElement],
|
|
29
|
-
IfcRelFillsElement: [RelationshipType.FillsElement],
|
|
30
|
-
'IfcRelVoidsElement IfcRelFillsElement': [
|
|
31
|
-
RelationshipType.FillsElement,
|
|
32
|
-
RelationshipType.VoidsElement,
|
|
33
|
-
],
|
|
34
|
-
};
|
|
12
|
+
// `PropertyOverride`/`PropertyOverlayResolver` are re-exported above from
|
|
13
|
+
// ./property-overlay-resolver.js; the PartOf relation map and ancestor BFS
|
|
14
|
+
// walk live in ./ancestors.js — see `resolvePartOfAncestors` below.
|
|
35
15
|
/**
|
|
36
16
|
* Bridge an `IfcDataStore` (produced by `@ifc-lite/parser`) into the
|
|
37
17
|
* abstract `IFCDataAccessor` the IDS validator consumes. The single
|
|
@@ -44,8 +24,15 @@ const PARTOF_REL_MAP = {
|
|
|
44
24
|
* non-rooted resources, length unit conversion, predefined property-set
|
|
45
25
|
* unwrapping, schema-driven attribute XSD types, USERDEFINED predicate
|
|
46
26
|
* substitution, partOf transitivity, etc.
|
|
27
|
+
*
|
|
28
|
+
* `propertyOverlay` is optional and lets a caller with in-memory,
|
|
29
|
+
* not-yet-exported property edits (e.g. an IDS correction applied through
|
|
30
|
+
* the viewer's `MutablePropertyView`) have those edits reflected in
|
|
31
|
+
* `getPropertyValue`/`getPropertySets` immediately, without re-parsing the
|
|
32
|
+
* store. Every other read (attributes, classifications, materials, partOf)
|
|
33
|
+
* is unaffected — only the two property-reading methods below consult it.
|
|
47
34
|
*/
|
|
48
|
-
export function createDataAccessor(store) {
|
|
35
|
+
export function createDataAccessor(store, propertyOverlay) {
|
|
49
36
|
// Memoize per-entity attribute extraction. extractAllEntityAttributes
|
|
50
37
|
// re-parses the entity from the raw source buffer on every call, and the
|
|
51
38
|
// validator hits Name/GlobalId/Description/getAttribute(Names) for the same
|
|
@@ -69,6 +56,15 @@ export function createDataAccessor(store) {
|
|
|
69
56
|
}
|
|
70
57
|
return undefined;
|
|
71
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Property sets for `expressId`, with any pending overlay writes applied
|
|
61
|
+
* on top of the canonical (parsed) result. See
|
|
62
|
+
* `resolveEffectivePropertySets` (./property-overlay-resolver.js) for the
|
|
63
|
+
* merge semantics.
|
|
64
|
+
*/
|
|
65
|
+
function getEffectivePropertySets(expressId) {
|
|
66
|
+
return resolveEffectivePropertySets(store, expressId, propertyOverlay);
|
|
67
|
+
}
|
|
72
68
|
const accessor = {
|
|
73
69
|
getEntityType(expressId) {
|
|
74
70
|
// The columnar entity table only summarises "interesting"
|
|
@@ -156,7 +152,7 @@ export function createDataAccessor(store) {
|
|
|
156
152
|
getPropertyValue(expressId, propertySetName, propertyName) {
|
|
157
153
|
const psetLower = propertySetName.toLowerCase();
|
|
158
154
|
const propLower = propertyName.toLowerCase();
|
|
159
|
-
const all =
|
|
155
|
+
const all = getEffectivePropertySets(expressId);
|
|
160
156
|
for (const pset of all) {
|
|
161
157
|
if (pset.name.toLowerCase() !== psetLower)
|
|
162
158
|
continue;
|
|
@@ -174,7 +170,7 @@ export function createDataAccessor(store) {
|
|
|
174
170
|
return undefined;
|
|
175
171
|
},
|
|
176
172
|
getPropertySets(expressId) {
|
|
177
|
-
return
|
|
173
|
+
return getEffectivePropertySets(expressId);
|
|
178
174
|
},
|
|
179
175
|
getClassifications(expressId) {
|
|
180
176
|
return resolveClassifications(store, expressId);
|
|
@@ -189,44 +185,7 @@ export function createDataAccessor(store) {
|
|
|
189
185
|
return all.length > 0 ? all[0] : undefined;
|
|
190
186
|
},
|
|
191
187
|
getAncestors(expressId, relationType) {
|
|
192
|
-
|
|
193
|
-
if (!relationships?.getRelated)
|
|
194
|
-
return [];
|
|
195
|
-
const relTypes = PARTOF_REL_MAP[relationType];
|
|
196
|
-
if (!relTypes || relTypes.length === 0)
|
|
197
|
-
return [];
|
|
198
|
-
// BFS up the graph — IDS partOf is transitive, so any reachable
|
|
199
|
-
// ancestor counts. The merged voids/fills relation walks two edge
|
|
200
|
-
// types per node, so the queue follows each mapped type in turn.
|
|
201
|
-
const out = [];
|
|
202
|
-
const seen = new Set([expressId]);
|
|
203
|
-
const queue = [expressId];
|
|
204
|
-
while (queue.length > 0) {
|
|
205
|
-
const id = queue.shift();
|
|
206
|
-
for (const relType of relTypes) {
|
|
207
|
-
const parents = relationships.getRelated(id, relType, 'inverse');
|
|
208
|
-
for (const parentId of parents || []) {
|
|
209
|
-
if (seen.has(parentId))
|
|
210
|
-
continue;
|
|
211
|
-
seen.add(parentId);
|
|
212
|
-
out.push({
|
|
213
|
-
expressId: parentId,
|
|
214
|
-
entityType: accessor.getEntityType(parentId) || 'Unknown',
|
|
215
|
-
// Raw enum token first (BEAM, USERDEFINED, …) — NOT
|
|
216
|
-
// getObjectType. getObjectType collapses USERDEFINED to the
|
|
217
|
-
// accompanying user-defined name, which loses the literal
|
|
218
|
-
// "USERDEFINED" token a spec may legitimately ask for (the
|
|
219
|
-
// same case entity-facet.ts's rawType branch accepts for a
|
|
220
|
-
// direct entity check). The user-defined name is carried
|
|
221
|
-
// separately in `objectType` as a fallback for partof-facet.
|
|
222
|
-
predefinedType: accessor.getPredefinedTypeRaw?.(parentId),
|
|
223
|
-
objectType: accessor.getObjectType(parentId),
|
|
224
|
-
});
|
|
225
|
-
queue.push(parentId);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
return out;
|
|
188
|
+
return resolvePartOfAncestors(store, expressId, relationType, (id) => accessor.getEntityType(id), (id) => accessor.getPredefinedTypeRaw?.(id), (id) => accessor.getObjectType(id));
|
|
230
189
|
},
|
|
231
190
|
getAttribute(expressId, attributeName) {
|
|
232
191
|
const lowerName = attributeName.toLowerCase();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-accessor.js","sourceRoot":"","sources":["../../src/bridge/data-accessor.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D,OAAO,EAEL,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAYxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"data-accessor.js","sourceRoot":"","sources":["../../src/bridge/data-accessor.ts"],"names":[],"mappings":"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"}
|
package/dist/bridge/index.d.ts
CHANGED
|
@@ -13,5 +13,8 @@
|
|
|
13
13
|
* unwrapping, schema-driven attribute XSD types, etc.
|
|
14
14
|
*/
|
|
15
15
|
export { createDataAccessor } from './data-accessor.js';
|
|
16
|
+
export type { PropertyOverride, PropertyOverlayResolver } from './data-accessor.js';
|
|
16
17
|
export { narrowSchemaVersion } from './schema-version.js';
|
|
18
|
+
export { resolveEntityMeasureScales, toRaw } from './units.js';
|
|
19
|
+
export type { EntityMeasureScales } from './units.js';
|
|
17
20
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bridge/index.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bridge/index.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,YAAY,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AACpF,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,0BAA0B,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAC/D,YAAY,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/bridge/index.js
CHANGED
package/dist/bridge/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bridge/index.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bridge/index.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,0BAA0B,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { type IfcDataStore } from '@ifc-lite/parser';
|
|
2
|
+
import type { PropertySetInfo } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* One pending, in-memory correction to a property value, applied on top
|
|
5
|
+
* of the canonical (parsed) projection without re-exporting the model.
|
|
6
|
+
* Mirrors the viewer's `MutablePropertyView` mutation shape without a
|
|
7
|
+
* dependency on `@ifc-lite/mutations` — callers (the viewer) adapt their
|
|
8
|
+
* mutation view's per-entity mutation list into this shape.
|
|
9
|
+
*/
|
|
10
|
+
export interface PropertyOverride {
|
|
11
|
+
/** Property set name, exactly as written (case-sensitive). */
|
|
12
|
+
psetName: string;
|
|
13
|
+
/** Property name, exactly as written (case-sensitive). */
|
|
14
|
+
propName: string;
|
|
15
|
+
/** The corrected value, or `null`/`deleted` to remove the property. */
|
|
16
|
+
value: string | number | boolean | null;
|
|
17
|
+
/** True when the property was deleted rather than set. */
|
|
18
|
+
deleted?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* The IFC measure dataType (e.g. `"IFCLENGTHMEASURE"`) `value` was
|
|
21
|
+
* scaled against at WRITE time. Only consulted when this override
|
|
22
|
+
* targets a property that doesn't already exist (below): the
|
|
23
|
+
* existing-entry branch always prefers the entity's OWN stored
|
|
24
|
+
* `dataType`, since that is authoritative over whatever the caller
|
|
25
|
+
* happened to pass. Absent/undefined behaves exactly as before — no
|
|
26
|
+
* scale applied, value spliced in as-is.
|
|
27
|
+
*/
|
|
28
|
+
dataType?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Resolves the pending property overrides for one entity, or `undefined`
|
|
32
|
+
* when the entity has none. Called on every property read, so it must be
|
|
33
|
+
* cheap (an O(1)/O(mutations-for-entity) map lookup, not a scan).
|
|
34
|
+
*/
|
|
35
|
+
export type PropertyOverlayResolver = (expressId: number) => PropertyOverride[] | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Property sets for `expressId`, with any pending overlay writes applied
|
|
38
|
+
* on top of the canonical (parsed) result. The canonical projection stays
|
|
39
|
+
* the single source of truth for pset unwrapping/merging — the overlay
|
|
40
|
+
* only patches the specific properties it names, so an entity with no
|
|
41
|
+
* overrides sees byte-identical output to the no-overlay path, and an
|
|
42
|
+
* entity WITH overrides keeps every other property untouched.
|
|
43
|
+
*
|
|
44
|
+
* An override's OWN value, however, does still go through unit
|
|
45
|
+
* conversion here (`toBaseSI` below, keyed off the same
|
|
46
|
+
* `resolveEntityMeasureScales` the canonical projection uses): a
|
|
47
|
+
* `PropertyOverride.value` is written in the model's raw storage frame
|
|
48
|
+
* (mirroring `MutablePropertyView.setProperty`), the same frame the
|
|
49
|
+
* canonical projection's OWN properties start in before
|
|
50
|
+
* `projectProperty` scales them — so splicing it in unconverted would
|
|
51
|
+
* leave it in the wrong unit frame relative to its neighbours.
|
|
52
|
+
*
|
|
53
|
+
* Pset/property name matching here is deliberately CASE-INSENSITIVE, to
|
|
54
|
+
* match `getPropertyValue`/`getPropertySets` in ./data-accessor.ts (both
|
|
55
|
+
* compare via `.toLowerCase()`, to tolerate real-world IFC files with
|
|
56
|
+
* inconsistent Pset/property-name casing). An exact-case `find`/`findIndex`
|
|
57
|
+
* here would silently miss a base property whose stored name differs only
|
|
58
|
+
* in case from the override's target: the override would land as a NEW,
|
|
59
|
+
* separately-cased property instead of replacing the existing one, and
|
|
60
|
+
* `getPropertyValue`'s case-insensitive scan would then return the OLD,
|
|
61
|
+
* uncorrected entry (it iterates in array order and the untouched base
|
|
62
|
+
* property comes first) — a correction that reads back as applied through
|
|
63
|
+
* this same accessor (case-insensitively) yet never becomes visible to a
|
|
64
|
+
* re-run of IDS validation through the very same accessor. Matching
|
|
65
|
+
* case-insensitively here, and preserving each existing entry's own
|
|
66
|
+
* stored casing on update, keeps this merge and the read path that
|
|
67
|
+
* consumes it in agreement.
|
|
68
|
+
*/
|
|
69
|
+
export declare function resolveEffectivePropertySets(store: IfcDataStore, expressId: number, propertyOverlay: PropertyOverlayResolver | undefined): PropertySetInfo[];
|
|
70
|
+
//# sourceMappingURL=property-overlay-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"property-overlay-resolver.d.ts","sourceRoot":"","sources":["../../src/bridge/property-overlay-resolver.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAKnD;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IACxC,0DAA0D;IAC1D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,SAAS,EAAE,MAAM,KAAK,gBAAgB,EAAE,GAAG,SAAS,CAAC;AAE5F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,uBAAuB,GAAG,SAAS,GACnD,eAAe,EAAE,CAqFnB"}
|