Skip to content

Commit 2b0cdee

Browse files
committed
feat(read): account for xml.serialize when infering property from tag name
1 parent 077b7d1 commit 2b0cdee

File tree

5 files changed

+131
-26
lines changed

5 files changed

+131
-26
lines changed

lib/read.js

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,44 @@ ElementHandler.prototype.createElement = function(node) {
383383
return instance;
384384
};
385385

386+
/**
387+
* Returns a property with an effective type descriptor,
388+
* in case type is defined through xml -> serialize hint.
389+
*
390+
* @param {any} node parsed
391+
* @param {PropertyDescriptor} property
392+
*
393+
* @return {PropertyDescriptor|null}
394+
*/
395+
ElementHandler.prototype.getSerializeAsTypePropertyForNode = function(node, property) {
396+
397+
const model = this.model;
398+
399+
const serializationType = getSerializationType(property);
400+
401+
if (!serializationType) {
402+
return null;
403+
}
404+
405+
const elementTypeName = node.attributes[serializationType];
406+
407+
// type is optional, if it does not exists the
408+
// default type is assumed
409+
if (elementTypeName) {
410+
411+
// convert the prefix used to the mapped form, but also
412+
// take possible type prefixes from XML
413+
// into account, i.e.: xsi:type="t{ActualType}",
414+
const normalizedTypeName = normalizeTypeName(elementTypeName, node.ns, model);
415+
416+
const elementType = model.getType(normalizedTypeName);
417+
418+
return assign({}, property, {
419+
effectiveType: getModdleDescriptor(elementType).name
420+
});
421+
}
422+
};
423+
386424
ElementHandler.prototype.getPropertyForNode = function(node) {
387425

388426
var name = node.name;
@@ -398,33 +436,10 @@ ElementHandler.prototype.getPropertyForNode = function(node) {
398436
// search for properties by name first
399437

400438
if (property && !property.isAttr) {
401-
402-
const serializationType = getSerializationType(property);
403-
404-
if (serializationType) {
405-
const elementTypeName = node.attributes[serializationType];
406-
407-
// type is optional, if it does not exists the
408-
// default type is assumed
409-
if (elementTypeName) {
410-
411-
// convert the prefix used to the mapped form, but also
412-
// take possible type prefixes from XML
413-
// into account, i.e.: xsi:type="t{ActualType}",
414-
const normalizedTypeName = normalizeTypeName(elementTypeName, node.ns, model);
415-
416-
const elementType = model.getType(normalizedTypeName);
417-
418-
return assign({}, property, {
419-
effectiveType: getModdleDescriptor(elementType).name
420-
});
421-
}
422-
}
423-
424-
// search for properties by name first
425-
return property;
439+
return this.getSerializeAsTypePropertyForNode(node, property) || property;
426440
}
427441

442+
// search by properties by type
428443
var pkg = model.getPackage(nameNs.prefix);
429444

430445
if (pkg) {
@@ -437,10 +452,11 @@ ElementHandler.prototype.getPropertyForNode = function(node) {
437452
});
438453

439454
if (property) {
440-
return assign({}, property, {
455+
return this.getSerializeAsTypePropertyForNode(node, property) || assign({}, property, {
441456
effectiveType: getModdleDescriptor(elementType).name
442457
});
443458
}
459+
444460
} else {
445461

446462
// parse unknown element (maybe extension)

test/fixtures/model/uml/uml.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "UML",
3+
"uri": "http://www.omg.org/spec/UML/20131001",
4+
"prefix": "uml",
5+
"types": [
6+
{
7+
"name": "Package",
8+
"superClass": [
9+
"xmi:Extension"
10+
]
11+
},
12+
{
13+
"name": "SpecialPackage",
14+
"superClass": [
15+
"Package"
16+
]
17+
}
18+
]
19+
}

test/fixtures/model/uml/xmi.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "XMI",
3+
"uri": "http://www.omg.org/spec/XMI/20131001",
4+
"prefix": "xmi",
5+
"types": [
6+
{
7+
"name": "XMI",
8+
"properties": [
9+
{ "name": "extensions", "type": "Extension", "isMany": true, "xml": { "serialize": "xmi:type" } }
10+
]
11+
},
12+
{
13+
"name": "Extension",
14+
"properties": [
15+
{
16+
"name": "type",
17+
"type": "String",
18+
"isAttr": true
19+
}
20+
]
21+
}
22+
]
23+
}

test/fixtures/xml/XMI.xmi

Whitespace-only changes.

test/spec/reader.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2819,4 +2819,51 @@ describe('Reader', function() {
28192819

28202820
});
28212821

2822+
2823+
describe('package owned xml -> serialize property', function() {
2824+
2825+
it('should parse without warnings', async function() {
2826+
2827+
// given
2828+
var datatypesModel = createModel([
2829+
'uml/xmi',
2830+
'uml/uml'
2831+
]);
2832+
2833+
var reader = new Reader(datatypesModel);
2834+
var rootHandler = reader.handler('xmi:XMI');
2835+
2836+
var xml = `
2837+
<xmi:XMI xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:uml="http://www.omg.org/spec/UML/20131001">
2838+
<uml:Package xmi:type="uml:Package" />
2839+
<uml:Package xmi:type="uml:SpecialPackage" />
2840+
</xmi:XMI>
2841+
`;
2842+
2843+
// when
2844+
var {
2845+
rootElement,
2846+
warnings
2847+
} = await reader.fromXML(xml, rootHandler);
2848+
2849+
// then
2850+
expect(rootElement).to.jsonEqual({
2851+
$type: 'xmi:XMI',
2852+
extensions: [
2853+
{
2854+
$type: 'uml:Package',
2855+
type: 'uml:Package'
2856+
},
2857+
{
2858+
$type: 'uml:SpecialPackage',
2859+
type: 'uml:SpecialPackage'
2860+
}
2861+
]
2862+
});
2863+
2864+
expect(warnings).to.be.empty;
2865+
});
2866+
2867+
});
2868+
28222869
});

0 commit comments

Comments
 (0)