This is an automated email from the ASF dual-hosted git repository.
tiagobento pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-tools.git
The following commit(s) were added to refs/heads/main by this push:
new f829ef2e5fe kie-issues#1051: `@kie-tools/dmn-marshaller` not
respecting `xsd:sequence` declaration order when an XSD Element extends another
Element (#2222)
f829ef2e5fe is described below
commit f829ef2e5fec417f3239094daafce2bf30fcf44c
Author: Tiago Bento <[email protected]>
AuthorDate: Mon Apr 1 16:50:43 2024 -0400
kie-issues#1051: `@kie-tools/dmn-marshaller` not respecting `xsd:sequence`
declaration order when an XSD Element extends another Element (#2222)
---
packages/dmn-marshaller/tests/xsdSequence.test.ts | 65 ++++++++++++++++++++---
packages/xml-parser-ts-codegen/src/codegen.ts | 32 ++++++-----
2 files changed, 79 insertions(+), 18 deletions(-)
diff --git a/packages/dmn-marshaller/tests/xsdSequence.test.ts
b/packages/dmn-marshaller/tests/xsdSequence.test.ts
index ca831d5ffad..c2aefe113b9 100644
--- a/packages/dmn-marshaller/tests/xsdSequence.test.ts
+++ b/packages/dmn-marshaller/tests/xsdSequence.test.ts
@@ -19,15 +19,68 @@
import * as fs from "fs";
import * as path from "path";
-import { getMarshaller } from "@kie-tools/dmn-marshaller";
+import { DmnLatestModel, getMarshaller } from "@kie-tools/dmn-marshaller";
-const files = [
- { path: "../tests-data--manual/other/decisionAndInput.dmn" },
- { path:
"../tests-data--manual/other/decisionAndInput_wrongSequenceOrder.dmn" },
-];
+describe("build produces elements respecting the hierarchy of the element
type", () => {
+ test("businessKnowledgeSource element", () => {
+ const json: DmnLatestModel = {
+ definitions: {
+ "@_name": "myDmn",
+ "@_namespace": "myDmnNamespace",
+ drgElement: [
+ {
+ __$$element: "businessKnowledgeModel",
+ authorityRequirement: [],
+ "@_name": "myBkm",
+ encapsulatedLogic: {
+ expression: {
+ __$$element: "literalExpression",
+ text: { __$$text: "myBkm literal expression" },
+ extensionElements: {},
+ },
+ },
+ variable: {
+ "@_name": "myBkm var",
+ extensionElements: {},
+ description: { __$$text: "myBkm var description" },
+ },
+ extensionElements: {},
+ description: { __$$text: "myBkm description" },
+ },
+ ],
+ },
+ };
+ expect(
+ getMarshaller(
+ `<?xml version="1.0" encoding="UTF-8" ?><definitions name=""
namespace="" xmlns="https://www.omg.org/spec/DMN/20230324/MODEL/"/>`,
+ { upgradeTo: "latest" }
+ ).builder.build(json)
+ ).toStrictEqual(`<?xml version="1.0" encoding="UTF-8" ?>
+<definitions name="myDmn" namespace="myDmnNamespace"
xmlns="https://www.omg.org/spec/DMN/20230324/MODEL/"
xmlns:dmndi="https://www.omg.org/spec/DMN/20230324/DMNDI/"
xmlns:dc="http://www.omg.org/spec/DMN/20180521/DC/"
xmlns:di="http://www.omg.org/spec/DMN/20180521/DI/"
xmlns:kie="https://kie.org/dmn/extensions/1.0">
+ <businessKnowledgeModel name="myBkm">
+ <description>myBkm description</description>
+ <extensionElements />
+ <variable name="myBkm var">
+ <description>myBkm var description</description>
+ <extensionElements />
+ </variable>
+ <encapsulatedLogic>
+ <literalExpression>
+ <extensionElements />
+ <text>myBkm literal expression</text>
+ </literalExpression>
+ </encapsulatedLogic>
+ </businessKnowledgeModel>
+</definitions>
+`);
+ });
+});
describe("build always produces elements in the same order", () => {
- for (const file of files) {
+ for (const file of [
+ { path: "../tests-data--manual/other/decisionAndInput.dmn" },
+ { path:
"../tests-data--manual/other/decisionAndInput_wrongSequenceOrder.dmn" },
+ ]) {
test(path.basename(file.path), () => {
const xml = fs.readFileSync(path.join(__dirname, file.path), "utf-8");
const marshaller = getMarshaller(xml, { upgradeTo: "1.5" });
diff --git a/packages/xml-parser-ts-codegen/src/codegen.ts
b/packages/xml-parser-ts-codegen/src/codegen.ts
index eb349425f85..c5054aebc12 100644
--- a/packages/xml-parser-ts-codegen/src/codegen.ts
+++ b/packages/xml-parser-ts-codegen/src/codegen.ts
@@ -575,7 +575,10 @@ function getMetaProperties(
ct: XptcComplexType,
metaTypeName: string
): { anonymousTypes: XptcMetaType[]; needsExtensionType: boolean;
metaProperties: XptcMetaTypeProperty[] } {
- const metaProperties: XptcMetaTypeProperty[] = [];
+ /** Accumulates all properties of this complex type (ct). Attributes and
elements. */
+ let ctMetaProperties: XptcMetaTypeProperty[] = [];
+
+ /** Accumulates all anonymous types instantiated on this complex type's
hierarchy */
const anonymousTypes: XptcMetaType[] = [];
const immediateParentType = ct.childOf
@@ -587,6 +590,7 @@ function getMetaProperties(
let needsExtensionType = ct.needsExtensionType;
while (curParentCt) {
+ const curParentCtMetaProperties: XptcMetaTypeProperty[] = [];
if (curParentCt?.type === "complex") {
const curParentCtMetaTypeName = getTsNameFromNamedType(
curParentCt.declaredAtRelativeLocation,
@@ -608,7 +612,7 @@ function getMetaProperties(
throw new Error(`Can't resolve local type ref ${a.localTypeRef}`);
}
- metaProperties.push({
+ curParentCtMetaProperties.push({
declaredAt: curParentCt.declaredAtRelativeLocation,
fromType: curParentCtMetaTypeName,
elem: undefined,
@@ -638,7 +642,7 @@ function getMetaProperties(
name: anonymousTypeName,
properties: mp.metaProperties,
});
- metaProperties.push({
+ curParentCtMetaProperties.push({
elem: undefined, // REALLY?
declaredAt: curParentCt.declaredAtRelativeLocation,
fromType: curParentCtMetaTypeName,
@@ -655,7 +659,7 @@ function getMetaProperties(
e.typeName
);
- metaProperties.push({
+ curParentCtMetaProperties.push({
declaredAt: curParentCt.declaredAtRelativeLocation,
fromType: curParentCtMetaTypeName,
elem: undefined, // REALLY?
@@ -692,7 +696,7 @@ function getMetaProperties(
annotation: "Anonymous type from element " +
referencedElement.name,
};
- metaProperties.push({
+ curParentCtMetaProperties.push({
declaredAt: referencedElement?.declaredAtRelativeLocation,
fromType: ct.isAnonymous ? "" : curParentCtMetaTypeName,
name: referencedElement.name,
@@ -725,6 +729,10 @@ function getMetaProperties(
curParentCt.childOf
)
: undefined;
+
+ // Make sure the inheritance order is respected. Elements should be
listed always from the most generic to the most specific type.
+ // Since we're iterating upwards in the hierarchy, we need to invert
prepend the array with the props we find on each step of the hierarchy.
+ ctMetaProperties = [...curParentCtMetaProperties, ...ctMetaProperties];
curParentCt = nextParentType ?
__NAMED_TYPES_BY_TS_NAME.get(nextParentType.name) : undefined;
} else if (curParentCt?.type === "simple") {
throw new Error("Can't have a non-complex type as parent of another.");
@@ -743,7 +751,7 @@ function getMetaProperties(
a.localTypeRef
);
- metaProperties.push({
+ ctMetaProperties.push({
declaredAt: ct.declaredAtRelativeLocation,
fromType: metaTypeName,
name: `@_${a.name}`,
@@ -777,7 +785,7 @@ function getMetaProperties(
annotation: "Anonymous type from element " +
referencedElement.name,
};
- metaProperties.push({
+ ctMetaProperties.push({
declaredAt: referencedElement?.declaredAtRelativeLocation,
fromType: ct.isAnonymous ? "" : metaTypeName,
name: referencedElement.name,
@@ -799,7 +807,7 @@ function getMetaProperties(
});
} else if (e.kind === "ofNamedType") {
const tsType = getTsTypeFromLocalRef(__XSDS, __NAMED_TYPES_BY_TS_NAME,
ct.declaredAtRelativeLocation, e.typeName);
- metaProperties.push({
+ ctMetaProperties.push({
declaredAt: ct.declaredAtRelativeLocation,
fromType: metaTypeName,
name: e.name,
@@ -827,7 +835,7 @@ function getMetaProperties(
name: anonymousTypeName,
properties: mp.metaProperties,
});
- metaProperties.push({
+ ctMetaProperties.push({
declaredAt: ct.declaredAtRelativeLocation,
fromType: metaTypeName,
name: e.name,
@@ -843,7 +851,7 @@ function getMetaProperties(
if (ct.isSimpleContent && ct.childOf) {
const t = getTsTypeFromLocalRef(__XSDS, __NAMED_TYPES_BY_TS_NAME,
ct.declaredAtRelativeLocation, ct.childOf);
- metaProperties.push({
+ ctMetaProperties.push({
declaredAt: ct.declaredAtRelativeLocation,
fromType: metaTypeName,
name: `__$$text`,
@@ -860,11 +868,11 @@ function getMetaProperties(
if (!(ct.type === "complex" && !ct.isAnonymous && ct.isAbstract)) {
__META_TYPE_MAPPING.set(metaTypeName, {
name: metaTypeName,
- properties: [...metaProperties.reduce((acc, p) => acc.set(p.name, p),
new Map()).values()], // Removing duplicates.
+ properties: [...ctMetaProperties.reduce((acc, p) => acc.set(p.name, p),
new Map()).values()], // Removing duplicates.
});
}
- return { metaProperties, needsExtensionType, anonymousTypes };
+ return { metaProperties: ctMetaProperties, needsExtensionType,
anonymousTypes };
}
function getAnonymousMetaTypeName(elementName: string, metaTypeName: string) {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]