@typemf/xmi 0.8.1 → 0.9.1

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/index.cjs CHANGED
@@ -38,6 +38,7 @@ __export(index_exports, {
38
38
  computeEmfFragment: () => computeEmfFragment,
39
39
  escapeAttributeValue: () => escapeAttributeValue,
40
40
  escapeText: () => escapeText,
41
+ nameSegmentAmong: () => nameSegmentAmong,
41
42
  parseXmlDocument: () => parseXmlDocument,
42
43
  registerXmiFormat: () => registerXmiFormat,
43
44
  resolveEmfFragment: () => resolveEmfFragment
@@ -45,6 +46,7 @@ __export(index_exports, {
45
46
  module.exports = __toCommonJS(index_exports);
46
47
 
47
48
  // src/emf-fragment.ts
49
+ var import_core = require("@typemf/core");
48
50
  function allStructuralFeaturesOf(eClass) {
49
51
  const seen = /* @__PURE__ */ new Set();
50
52
  const result = [];
@@ -73,6 +75,13 @@ function computeEmfFragment(target, roots) {
73
75
  if (!feature) {
74
76
  throw new Error("Object has a container but no containing feature - inconsistent containment state.");
75
77
  }
78
+ const named = nameSegment(current, container);
79
+ if (named !== void 0) {
80
+ segments.unshift(named);
81
+ current = container;
82
+ container = current.eContainer();
83
+ continue;
84
+ }
76
85
  let segment = `@${feature.getName()}`;
77
86
  if (feature.isMany()) {
78
87
  const siblings = [...container.eGet(feature)];
@@ -96,17 +105,27 @@ function computeEmfFragment(target, roots) {
96
105
  }
97
106
  return path === "" ? `/${rootIndex}` : `/${rootIndex}/${path}`;
98
107
  }
108
+ function nameSegment(target, container) {
109
+ if (!(0, import_core.isENamedElement)(target) || !(0, import_core.isEModelElement)(container)) return void 0;
110
+ return nameSegmentAmong(target, container.eContents());
111
+ }
112
+ function nameSegmentAmong(target, siblings) {
113
+ const name = nameOf(target);
114
+ if (typeof name !== "string" || name === "" || /^[@%]|[\s/#]/.test(name)) return void 0;
115
+ let count = 0;
116
+ for (const sibling of siblings) {
117
+ if (sibling === target) return count > 0 ? `${name}.${count}` : name;
118
+ if (nameOf(sibling) === name) count++;
119
+ }
120
+ return void 0;
121
+ }
99
122
  function resolveEmfFragment(fragment, roots) {
100
123
  if (fragment === "/") {
101
124
  return roots.length === 1 ? roots[0] : void 0;
102
125
  }
103
126
  if (fragment.startsWith("//")) {
104
- const rest = fragment.slice(2);
105
127
  if (roots.length !== 1) return void 0;
106
- if (rest.startsWith("@")) {
107
- return walkSegments(rest, roots[0]);
108
- }
109
- return walkNamedSegments(rest, roots[0]);
128
+ return walkSegments(fragment.slice(2), roots[0]);
110
129
  }
111
130
  if (fragment.startsWith("/")) {
112
131
  const rest = fragment.slice(1);
@@ -120,54 +139,40 @@ function resolveEmfFragment(fragment, roots) {
120
139
  }
121
140
  return findByIdValue(fragment, roots);
122
141
  }
123
- function walkNamedSegments(path, start) {
124
- const segments = path.split("/");
142
+ function walkSegments(path, start) {
125
143
  let current = start;
126
- for (const name of segments) {
144
+ for (const segment of path.split("/")) {
127
145
  if (!current) return void 0;
128
- const currentClass = current.eClass();
129
- const eClassifiersFeature = allStructuralFeaturesOf(currentClass).filter((feature) => feature.getName() === "eClassifiers").at(0);
130
- if (eClassifiersFeature) {
131
- current = findNamedChild(current, eClassifiersFeature, name);
132
- continue;
133
- }
134
- const eStructuralFeaturesFeature = allStructuralFeaturesOf(currentClass).filter((feature) => feature.getName() === "eStructuralFeatures").at(0);
135
- if (eStructuralFeaturesFeature) {
136
- current = findNamedChild(current, eStructuralFeaturesFeature, name);
137
- continue;
138
- }
139
- return void 0;
146
+ current = segment.startsWith("@") ? containmentStep(current, segment) : namedChild(current, segment);
140
147
  }
141
148
  return current;
142
149
  }
143
- function findNamedChild(container, listFeature, name) {
144
- const children = [...container.eGet(listFeature)];
145
- return children.find((child) => {
146
- const nameFeature = allStructuralFeaturesOf(child.eClass()).filter((feature) => feature.getName() === "name").at(0);
147
- return nameFeature !== void 0 && child.eGet(nameFeature) === name;
148
- });
149
- }
150
- function walkSegments(path, start) {
151
- let current = start;
152
- for (const segment of path.split("/")) {
153
- if (!segment.startsWith("@")) return void 0;
154
- const dotIndex = segment.indexOf(".");
155
- const featureName = dotIndex === -1 ? segment.slice(1) : segment.slice(1, dotIndex);
156
- const feature = allStructuralFeaturesOf(current.eClass()).filter((feature2) => feature2.getName() === featureName).at(0);
157
- if (!feature) return void 0;
158
- if (feature.isMany()) {
159
- const indexToken = dotIndex === -1 ? void 0 : segment.slice(dotIndex + 1);
160
- const index = Number(indexToken);
161
- if (indexToken === void 0 || !Number.isInteger(index)) return void 0;
162
- const list = [...current.eGet(feature)];
163
- const next = list[index];
164
- if (!next) return void 0;
165
- current = next;
166
- } else {
167
- current = current.eGet(feature);
168
- }
150
+ function containmentStep(current, segment) {
151
+ const dotIndex = segment.indexOf(".");
152
+ const featureName = dotIndex === -1 ? segment.slice(1) : segment.slice(1, dotIndex);
153
+ const feature = allStructuralFeaturesOf(current.eClass()).find((f) => f.getName() === featureName);
154
+ if (!feature) return void 0;
155
+ if (!feature.isMany()) return current.eGet(feature);
156
+ const index = Number(dotIndex === -1 ? void 0 : segment.slice(dotIndex + 1));
157
+ if (!Number.isInteger(index)) return void 0;
158
+ return [...current.eGet(feature)][index];
159
+ }
160
+ function namedChild(container, segment) {
161
+ const counted = /^(.*)\.(\d+)$/.exec(segment);
162
+ return counted && nthNamedChild(container, counted[1], Number(counted[2])) || nthNamedChild(container, segment, 0);
163
+ }
164
+ function nthNamedChild(container, name, n) {
165
+ let remaining = n;
166
+ for (const child of container.eContents()) {
167
+ if (nameOf(child) !== name) continue;
168
+ if (remaining === 0) return child;
169
+ remaining--;
169
170
  }
170
- return current;
171
+ return void 0;
172
+ }
173
+ function nameOf(obj) {
174
+ const nameFeature = allStructuralFeaturesOf(obj.eClass()).find((f) => f.getName() === "name");
175
+ return nameFeature ? obj.eGet(nameFeature) : void 0;
171
176
  }
172
177
  function findByIdValue(idValue, roots) {
173
178
  for (const root of roots) {
@@ -216,10 +221,10 @@ var NamespaceCollector = class {
216
221
  };
217
222
 
218
223
  // src/xmi-resource-factory.ts
219
- var import_core2 = require("@typemf/core");
224
+ var import_core3 = require("@typemf/core");
220
225
 
221
226
  // src/xmi-serializer.ts
222
- var import_core = require("@typemf/core");
227
+ var import_core2 = require("@typemf/core");
223
228
 
224
229
  // src/xml-text.ts
225
230
  function escapeAttributeValue(value) {
@@ -382,11 +387,7 @@ function writeObjectParts(obj, tagName, roots, sourceResource, namespaces) {
382
387
  childrenXml += renderElement({ tagName: feature.getName(), attributes: attrs, childrenXml: "" });
383
388
  }
384
389
  } else {
385
- const anyPolymorphic = encoded.some((e) => e.xsiType);
386
- const tokens = encoded.map(
387
- (e) => anyPolymorphic ? `${e.xsiType ?? sameTypeToken(refFeature, namespaces)} ${e.value}` : e.value
388
- );
389
- attributes.push([feature.getName(), tokens.join(" ")]);
390
+ attributes.push([feature.getName(), encoded.map((e) => `#${e.value}`).join(" ")]);
390
391
  }
391
392
  }
392
393
  return { tagName, attributes, childrenXml };
@@ -402,17 +403,12 @@ function childElementTag(child, feature, namespaces) {
402
403
  const prefix = namespaces.prefixFor(requirePackage(actual));
403
404
  return { xsiType: `${prefix}:${actual.getName()}` };
404
405
  }
405
- function sameTypeToken(feature, namespaces) {
406
- const declared = feature.getEType();
407
- const prefix = namespaces.prefixFor(requirePackage(declared));
408
- return `${prefix}:${declared.getName()}`;
409
- }
410
406
  function encodeReferenceValue(target, feature, roots, sourceResource, namespaces) {
411
407
  const declared = feature.getEType();
412
408
  if (target.eIsProxy()) {
413
409
  const actual2 = target.eClass();
414
410
  const xsiType2 = declared !== actual2 ? `${namespaces.prefixFor(requirePackage(actual2))}:${actual2.getName()}` : void 0;
415
- const proxyURI = (0, import_core.getProxyURI)(target);
411
+ const proxyURI = (0, import_core2.getProxyURI)(target);
416
412
  if (!proxyURI) {
417
413
  throw new Error(`eIsProxy() is true but no proxy URI is on record for this ${actual2.getName()}.`);
418
414
  }
@@ -426,7 +422,7 @@ function encodeReferenceValue(target, feature, roots, sourceResource, namespaces
426
422
  }
427
423
  const ecoreOwnPath = ecoreOwnFragmentPath(target);
428
424
  if (ecoreOwnPath !== void 0) {
429
- return { value: `${import_core.EcorePackageImpl.eINSTANCE.getNsURI()}#${ecoreOwnPath}`, crossDocument: true, xsiType };
425
+ return { value: `${import_core2.EcorePackageImpl.eINSTANCE.getNsURI()}#${ecoreOwnPath}`, crossDocument: true, xsiType };
430
426
  }
431
427
  if (targetResource) {
432
428
  const targetDocumentURI = targetResource.getURI().deresolve(sourceResource.getURI());
@@ -449,27 +445,25 @@ function isReachableFromRoots(target, roots) {
449
445
  return false;
450
446
  }
451
447
  function ecoreOwnFragmentPath(target) {
452
- const ecore = import_core.EcorePackageImpl.eINSTANCE;
453
- if ((0, import_core.isEClassifier)(target)) {
448
+ const ecore = import_core2.EcorePackageImpl.eINSTANCE;
449
+ if ((0, import_core2.isEClassifier)(target)) {
454
450
  return target.getEPackage() === ecore ? `//${target.getName() ?? ""}` : void 0;
455
451
  }
456
452
  const containingClass = hasContainingClass(target) ? target.getEContainingClass() : void 0;
457
- if (containingClass && containingClass.getEPackage() === ecore && isNamed(target)) {
458
- return `//${containingClass.getName() ?? ""}/${target.getName() ?? ""}`;
453
+ if (containingClass && containingClass.getEPackage() === ecore) {
454
+ const segment = nameSegmentAmong(target, containingClass.eContents());
455
+ return segment === void 0 ? void 0 : `//${containingClass.getName() ?? ""}/${segment}`;
459
456
  }
460
457
  return void 0;
461
458
  }
462
459
  function hasContainingClass(obj) {
463
460
  return typeof obj.getEContainingClass === "function";
464
461
  }
465
- function isNamed(obj) {
466
- return typeof obj.getName === "function";
467
- }
468
462
  function fragmentForTarget(target, owningResource, fallbackRoots) {
469
463
  if (!owningResource) return computeEmfFragment(target, fallbackRoots);
470
464
  const roots = owningResource.getContents().toArray();
471
465
  const serializer = owningResource.getSerializer();
472
- return serializer.computeFragment ? serializer.computeFragment(target, roots) : (0, import_core.computeFragment)(target, roots);
466
+ return serializer.computeFragment ? serializer.computeFragment(target, roots) : (0, import_core2.computeFragment)(target, roots);
473
467
  }
474
468
  function isReferenceFeature(feature) {
475
469
  return "isContainment" in feature;
@@ -481,7 +475,7 @@ function requirePackage(eClass) {
481
475
  }
482
476
  function encodeAttributeValue(value, feature) {
483
477
  const eType = feature.getEType();
484
- const text = eType && (0, import_core.isEDataType)(eType) ? (0, import_core.convertToString)(eType, value) : void 0;
478
+ const text = eType && (0, import_core2.isEDataType)(eType) ? (0, import_core2.convertToString)(eType, value) : void 0;
485
479
  return text ?? String(value);
486
480
  }
487
481
  function resolveElementEClass(element, packageRegistry) {
@@ -631,7 +625,7 @@ function completeObject(element, obj, ctx, elementToObj, roots) {
631
625
  const xsiType = child.getAttributeNS(XSI_NS, "type");
632
626
  const declared = refFeature.getEType();
633
627
  const proxyEClass = xsiType ? resolvePrefixedName(xsiType, child, ctx.packageRegistry) : declared;
634
- const proxy = (0, import_core.createProxy)(proxyEClass, import_core.URI.parse(href).resolve(ctx.resourceURI));
628
+ const proxy = (0, import_core2.createProxy)(proxyEClass, import_core2.URI.parse(href).resolve(ctx.resourceURI));
635
629
  if (feature.isMany()) {
636
630
  const list = obj.eGet(feature);
637
631
  list.add(proxy);
@@ -650,7 +644,7 @@ function decodeAttributeFormReference(rawValue, feature, contextElement, roots,
650
644
  if (isAbsoluteUri(fragment) || isRelativeCrossDocument) {
651
645
  const declared = feature.getEType();
652
646
  const proxyEClass = typeToken ? resolvePrefixedName(typeToken, contextElement, ctx.packageRegistry) : declared;
653
- return [(0, import_core.createProxy)(proxyEClass, import_core.URI.parse(fragment).resolve(ctx.resourceURI))];
647
+ return [(0, import_core2.createProxy)(proxyEClass, import_core2.URI.parse(fragment).resolve(ctx.resourceURI))];
654
648
  }
655
649
  const normalized = fragment.startsWith("#") ? fragment.slice(1) : fragment;
656
650
  const resolved = resolveEmfFragment(normalized, roots);
@@ -671,9 +665,9 @@ function isAbsoluteUri(token) {
671
665
  }
672
666
  function decodeAttributeValue(text, feature, element, ctx) {
673
667
  const eType = feature.getEType();
674
- if (!eType || !(0, import_core.isEDataType)(eType)) return { value: text };
668
+ if (!eType || !(0, import_core2.isEDataType)(eType)) return { value: text };
675
669
  try {
676
- return { value: (0, import_core.createFromString)(eType, text) };
670
+ return { value: (0, import_core2.createFromString)(eType, text) };
677
671
  } catch (err) {
678
672
  ctx.resource.getErrors().push({
679
673
  message: `Invalid value for '${feature.getName()}' on <${element.tagName}>: ${err.message}`
@@ -685,7 +679,7 @@ function decodeAttributeValue(text, feature, element, ctx) {
685
679
  // src/xmi-resource-factory.ts
686
680
  var XmiResourceFactory = class {
687
681
  createResource(uri) {
688
- return new import_core2.ResourceImpl(uri, new XmiSerializer());
682
+ return new import_core3.ResourceImpl(uri, new XmiSerializer());
689
683
  }
690
684
  };
691
685
  function registerXmiFormat(registry) {
@@ -702,6 +696,7 @@ function registerXmiFormat(registry) {
702
696
  computeEmfFragment,
703
697
  escapeAttributeValue,
704
698
  escapeText,
699
+ nameSegmentAmong,
705
700
  parseXmlDocument,
706
701
  registerXmiFormat,
707
702
  resolveEmfFragment