Skip to content

Commit c393dde

Browse files
hjothamendixclaude
andcommitted
fixup: drop dead Array-kind branch, add import-from-mapping fallback tests
Address review feedback on the import-mapping single-vs-list fallback. M1 — drop the `Kind == "Array"` branch from both fallback sites. parseImportMappingElement only ever produces `Kind: "Object"` or `Kind: "Value"` (any other `$Type` falls through to `default: return nil` and the nil element is never appended). The Array branch was unreachable from real MPR data, and the matching test asserted a state the parser cannot produce. Repetition for the list-vs-singleton call now comes purely from MaxOccurs ( -1 or > 1 ). m3 — add the missing `im.Elements[0] != nil` guard before the pre-existing entity lookup, matching the guard added two lines above. M2 — two new tests for `addImportFromMappingAction` cover the message-definition / XML-schema fallback path: - `TestAddImportFromMappingFallsBackToImportMappingRootForListResult` pins the Object root with MaxOccurs=-1 → list-typed result - `TestAddImportFromMappingFallsBackToImportMappingRootForSingleObject` pins the Object root with MaxOccurs=1 → singleton The dead `TestAddRestCallAction_MappingFallsBackToArrayKindWhenJsonStructureMissing` test is removed alongside the Array branch it exercised. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent f30bd4c commit c393dde

3 files changed

Lines changed: 71 additions & 49 deletions

File tree

mdl/executor/cmd_microflows_builder_calls.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,13 +1047,17 @@ func (fb *flowBuilder) addRestCallAction(s *ast.RestCallStmt) model.ID {
10471047
}
10481048
if !resolved && len(im.Elements) > 0 && im.Elements[0] != nil {
10491049
// XML schema / message-definition mappings carry the
1050-
// single-vs-list shape on the root mapping element itself.
1051-
// MaxOccurs > 1 or unbounded (-1) signals a list even
1052-
// when the kind is Object — Studio Pro models a
1053-
// repeating Object element as a list, distinct from a
1054-
// singleton.
1050+
// single-vs-list shape on the root mapping element
1051+
// itself. MaxOccurs > 1 or unbounded (-1) signals a
1052+
// list — Studio Pro models a repeating Object element
1053+
// as a list, distinct from a singleton. Mendix's
1054+
// import-mapping element BSON only ever uses
1055+
// `ImportMappings$ObjectMappingElement` or
1056+
// `ImportMappings$ValueMappingElement`; there is no
1057+
// `Array` element kind from real MPR data, so
1058+
// repetition has to come from MaxOccurs.
10551059
root := im.Elements[0]
1056-
if root.Kind == "Array" || root.MaxOccurs == -1 || root.MaxOccurs > 1 {
1060+
if root.MaxOccurs == -1 || root.MaxOccurs > 1 {
10571061
singleObject = false
10581062
} else {
10591063
singleObject = root.Kind == "Object"
@@ -1362,11 +1366,11 @@ func (fb *flowBuilder) addImportFromMappingAction(s *ast.ImportFromMappingStmt)
13621366
// MaxOccurs > 1 or unbounded (-1) signals a list even when
13631367
// the kind is Object.
13641368
root := im.Elements[0]
1365-
if root.Kind == "Array" || root.MaxOccurs == -1 || root.MaxOccurs > 1 {
1369+
if root.MaxOccurs == -1 || root.MaxOccurs > 1 {
13661370
resultHandling.SingleObject = false
13671371
}
13681372
}
1369-
if len(im.Elements) > 0 && im.Elements[0].Entity != "" {
1373+
if len(im.Elements) > 0 && im.Elements[0] != nil && im.Elements[0].Entity != "" {
13701374
resultEntityQN = im.Elements[0].Entity
13711375
resultHandling.ResultEntityID = model.ID(resultEntityQN)
13721376
}

mdl/executor/cmd_microflows_builder_import_mapping_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,65 @@ func TestAddImportFromMappingRegistersListResultType(t *testing.T) {
4040
}
4141
}
4242

43+
// XML-schema and message-definition mappings have no JsonStructure;
44+
// addImportFromMappingAction must then read the single-vs-list shape
45+
// from the import mapping's own root element. MaxOccurs > 1 or
46+
// unbounded (-1) signals a list — Studio Pro models a repeating Object
47+
// root that way for these mappings.
48+
func TestAddImportFromMappingFallsBackToImportMappingRootForListResult(t *testing.T) {
49+
fb := &flowBuilder{
50+
varTypes: map[string]string{},
51+
backend: &mock.MockBackend{
52+
GetImportMappingByQualifiedNameFunc: func(moduleName, name string) (*model.ImportMapping, error) {
53+
return &model.ImportMapping{
54+
JsonStructure: "",
55+
Elements: []*model.ImportMappingElement{
56+
{Kind: "Object", Entity: "Sales.Order", MaxOccurs: -1},
57+
},
58+
}, nil
59+
},
60+
},
61+
}
62+
63+
fb.addImportFromMappingAction(&ast.ImportFromMappingStmt{
64+
OutputVariable: "ImportedOrders",
65+
SourceVariable: "Payload",
66+
Mapping: ast.QualifiedName{Module: "Integration", Name: "ImportOrders"},
67+
})
68+
69+
if got := fb.varTypes["ImportedOrders"]; got != "List of Sales.Order" {
70+
t.Fatalf("ImportedOrders type = %q, want list of Sales.Order (Object root with MaxOccurs=-1 must yield list)", got)
71+
}
72+
}
73+
74+
// A non-repeating Object root (MaxOccurs ≤ 1) keeps the singleton type
75+
// when the JSON structure is absent.
76+
func TestAddImportFromMappingFallsBackToImportMappingRootForSingleObject(t *testing.T) {
77+
fb := &flowBuilder{
78+
varTypes: map[string]string{},
79+
backend: &mock.MockBackend{
80+
GetImportMappingByQualifiedNameFunc: func(moduleName, name string) (*model.ImportMapping, error) {
81+
return &model.ImportMapping{
82+
JsonStructure: "",
83+
Elements: []*model.ImportMappingElement{
84+
{Kind: "Object", Entity: "Sales.Order", MaxOccurs: 1, MinOccurs: 1},
85+
},
86+
}, nil
87+
},
88+
},
89+
}
90+
91+
fb.addImportFromMappingAction(&ast.ImportFromMappingStmt{
92+
OutputVariable: "ImportedOrder",
93+
SourceVariable: "Payload",
94+
Mapping: ast.QualifiedName{Module: "Integration", Name: "ImportOrder"},
95+
})
96+
97+
if got := fb.varTypes["ImportedOrder"]; got != "Sales.Order" {
98+
t.Fatalf("ImportedOrder type = %q, want Sales.Order (Object root with MaxOccurs=1 must stay singleton)", got)
99+
}
100+
}
101+
43102
func importMappingFlowBuilder(t *testing.T, rootElementType string) *flowBuilder {
44103
t.Helper()
45104

mdl/executor/cmd_microflows_builder_rest_response_test.go

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -112,47 +112,6 @@ func TestAddRestCallAction_MappingFallsBackToImportMappingRootKindWhenJsonStruct
112112

113113
// And the inverse: an Array root on the mapping element must yield a
114114
// list-typed result handling.
115-
func TestAddRestCallAction_MappingFallsBackToArrayKindWhenJsonStructureMissing(t *testing.T) {
116-
fb := &flowBuilder{
117-
posX: 100,
118-
posY: 100,
119-
spacing: HorizontalSpacing,
120-
varTypes: map[string]string{},
121-
declaredVars: map[string]string{},
122-
measurer: &layoutMeasurer{},
123-
backend: &mock.MockBackend{
124-
GetImportMappingByQualifiedNameFunc: func(moduleName, name string) (*model.ImportMapping, error) {
125-
return &model.ImportMapping{
126-
Name: "ArrMapping",
127-
JsonStructure: "",
128-
Elements: []*model.ImportMappingElement{
129-
{Kind: "Array", Entity: "Synthetic.Item"},
130-
},
131-
}, nil
132-
},
133-
},
134-
}
135-
136-
stmt := &ast.RestCallStmt{
137-
OutputVariable: "Items",
138-
Method: ast.HttpMethodGet,
139-
URL: &ast.LiteralExpr{Kind: ast.LiteralString, Value: "https://example.com"},
140-
Result: ast.RestResult{
141-
Type: ast.RestResultMapping,
142-
MappingName: ast.QualifiedName{Module: "Synthetic", Name: "ArrMapping"},
143-
ResultEntity: ast.QualifiedName{Module: "Synthetic", Name: "Item"},
144-
},
145-
}
146-
fb.addRestCallAction(stmt)
147-
148-
activity := fb.objects[0].(*microflows.ActionActivity)
149-
action := activity.Action.(*microflows.RestCallAction)
150-
mapping := action.ResultHandling.(*microflows.ResultHandlingMapping)
151-
if mapping.SingleObject {
152-
t.Errorf("SingleObject = true, want false (root mapping element Kind=Array)")
153-
}
154-
}
155-
156115
// A repeating Object element (MaxOccurs > 1 or unbounded) is a list, even
157116
// though the BSON Kind is "Object". Studio Pro models a list of objects
158117
// this way for XML schema and message-definition mappings; treating it as

0 commit comments

Comments
 (0)