Skip to content

Commit a1b5551

Browse files
authored
Merge pull request #25 from KavinduZoysa/dm-sub-mapping
Add sub mappings to the model
2 parents 39a8101 + 2a7f18c commit a1b5551

File tree

3 files changed

+196
-19
lines changed

3 files changed

+196
-19
lines changed

flow-model-generator/modules/flow-model-generator-core/src/main/java/io/ballerina/flowmodelgenerator/core/DataMapManager.java

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
import io.ballerina.compiler.syntax.tree.FunctionCallExpressionNode;
4848
import io.ballerina.compiler.syntax.tree.ImplicitNewExpressionNode;
4949
import io.ballerina.compiler.syntax.tree.IntermediateClauseNode;
50+
import io.ballerina.compiler.syntax.tree.LetExpressionNode;
51+
import io.ballerina.compiler.syntax.tree.LetVariableDeclarationNode;
5052
import io.ballerina.compiler.syntax.tree.ListConstructorExpressionNode;
5153
import io.ballerina.compiler.syntax.tree.MappingConstructorExpressionNode;
5254
import io.ballerina.compiler.syntax.tree.MappingFieldNode;
@@ -193,10 +195,17 @@ public JsonElement getMappings(JsonElement node, LinePosition position, String p
193195
return null;
194196
}
195197

196-
Type type;
198+
Type type = Type.fromSemanticSymbol(targetNode.typeSymbol());
199+
String name = targetNode.name();
200+
MappingPort outputPort = getMappingPort(name, name, type);
197201
ExpressionNode expressionNode = targetNode.expressionNode();
202+
if (expressionNode == null) {
203+
return gson.toJsonTree(new Model(inputPorts, outputPort, new ArrayList<>(), null));
204+
}
205+
198206
Query query = null;
199-
if (expressionNode != null && targetNode.expressionNode().kind() == SyntaxKind.QUERY_EXPRESSION) {
207+
List<MappingPort> subMappingPorts = null;
208+
if (expressionNode.kind() == SyntaxKind.QUERY_EXPRESSION) {
200209
QueryExpressionNode queryExpressionNode = (QueryExpressionNode) targetNode.expressionNode();
201210
FromClauseNode fromClauseNode = queryExpressionNode.queryPipeline().fromClause();
202211
List<String> inputs = new ArrayList<>();
@@ -221,20 +230,29 @@ public JsonElement getMappings(JsonElement node, LinePosition position, String p
221230
}
222231
query = new Query(targetField, inputs, fromClause,
223232
getQueryIntermediateClause(queryExpressionNode.queryPipeline()), resultClause);
233+
} else if (expressionNode.kind() == SyntaxKind.LET_EXPRESSION) {
234+
LetExpressionNode letExpressionNode = (LetExpressionNode) expressionNode;
235+
subMappingPorts = new ArrayList<>();
236+
for (LetVariableDeclarationNode letVarDeclaration : letExpressionNode.letVarDeclarations()) {
237+
Optional<Symbol> optSymbol = newSemanticModel.symbol(letVarDeclaration);
238+
if (optSymbol.isEmpty()) {
239+
continue;
240+
}
241+
Symbol symbol = optSymbol.get();
242+
String letVarName = symbol.getName().orElseThrow();
243+
subMappingPorts.add(getMappingPort(letVarName, letVarName, Type.fromSemanticSymbol(symbol)));
244+
}
224245
}
225-
type = Type.fromSemanticSymbol(targetNode.typeSymbol());
226-
String name = targetNode.name();
227-
MappingPort outputPort = getMappingPort(name, name, type);
246+
228247
List<Mapping> mappings = new ArrayList<>();
229-
if (expressionNode != null) {
230-
TypeDescKind typeDescKind = CommonUtils.getRawType(targetNode.typeSymbol()).typeKind();
231-
if (typeDescKind == TypeDescKind.RECORD) {
232-
generateRecordVariableDataMapping(expressionNode, mappings, name, newSemanticModel);
233-
} else if (typeDescKind == TypeDescKind.ARRAY) {
234-
generateArrayVariableDataMapping(expressionNode, mappings, name, newSemanticModel);
235-
}
248+
TypeDescKind typeDescKind = CommonUtils.getRawType(targetNode.typeSymbol()).typeKind();
249+
if (typeDescKind == TypeDescKind.RECORD) {
250+
generateRecordVariableDataMapping(expressionNode, mappings, name, newSemanticModel);
251+
} else if (typeDescKind == TypeDescKind.ARRAY) {
252+
generateArrayVariableDataMapping(expressionNode, mappings, name, newSemanticModel);
236253
}
237-
return gson.toJsonTree(new Model(inputPorts, outputPort, mappings, query));
254+
255+
return gson.toJsonTree(new Model(inputPorts, outputPort, subMappingPorts, mappings, query));
238256
}
239257

240258
private TargetNode getTargetNode(Node parentNode, String targetField, NodeKind nodeKind, String propertyKey,
@@ -1275,14 +1293,19 @@ private List<IntermediateClause> getQueryIntermediateClause(QueryPipelineNode qu
12751293
return intermediateClauses;
12761294
}
12771295

1278-
private record Model(List<MappingPort> inputs, MappingPort output, List<Mapping> mappings, Query query) {
1296+
private record Model(List<MappingPort> inputs, MappingPort output, List<MappingPort> subMappings,
1297+
List<Mapping> mappings, Query query) {
12791298

12801299
private Model(List<MappingPort> inputs, MappingPort output, List<Mapping> mappings) {
1281-
this(inputs, output, mappings, null);
1300+
this(inputs, output, null, mappings, null);
12821301
}
12831302

12841303
private Model(List<MappingPort> inputs, MappingPort output, Query query) {
1285-
this(inputs, output, new ArrayList<>(), query);
1304+
this(inputs, output, null, new ArrayList<>(), query);
1305+
}
1306+
1307+
private Model(List<MappingPort> inputs, MappingPort output, List<Mapping> mappings, Query query) {
1308+
this(inputs, output, null, mappings, query);
12861309
}
12871310
}
12881311

flow-model-generator/modules/flow-model-generator-ls-extension/src/test/java/io/ballerina/flowmodelgenerator/extension/DataMappingModelTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ protected Object[] getConfigsList() {
9191
{Path.of("function_call1.json")},
9292
{Path.of("function_call2.json")},
9393
{Path.of("new_connection1.json")},
94+
{Path.of("sub_mapping1.json")},
9495
};
9596
}
9697

@@ -112,9 +113,7 @@ public void test(Path config) throws IOException {
112113
TestConfig updateConfig = new TestConfig(testConfig.source(), testConfig.description(),
113114
testConfig.diagram(), testConfig.propertyKey(), testConfig.position(), model,
114115
testConfig.targetField());
115-
116-
117-
// updateConfig(configJsonPath, updateConfig);
116+
// updateConfig(configJsonPath, updateConfig);
118117
compareJsonElements(model, testConfig.model());
119118
Assert.fail(String.format("Failed test: '%s' (%s)", testConfig.description(), configJsonPath));
120119
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
{
2+
"source": "variable2.bal",
3+
"description": "Sample diagram node",
4+
"diagram": {
5+
"id": "32874",
6+
"metadata": {
7+
"label": "Variable",
8+
"description": "Assign a value to a variable"
9+
},
10+
"codedata": {
11+
"node": "VARIABLE",
12+
"lineRange": {
13+
"fileName": "variable2.bal",
14+
"startLine": {
15+
"line": 0,
16+
"offset": 0
17+
},
18+
"endLine": {
19+
"line": 0,
20+
"offset": 0
21+
}
22+
},
23+
"sourceCode": ""
24+
},
25+
"returning": false,
26+
"properties": {
27+
"expression": {
28+
"metadata": {
29+
"label": "Expression",
30+
"description": "Expression"
31+
},
32+
"valueType": "EXPRESSION",
33+
"value": "let Student s = {username: \"U\", password: \"PWD\"}, let int x = 2 in {username: userInfo.username}",
34+
"optional": false,
35+
"editable": true
36+
},
37+
"variable": {
38+
"metadata": {
39+
"label": "Variable",
40+
"description": "Name of the variable"
41+
},
42+
"valueType": "IDENTIFIER",
43+
"value": "student",
44+
"optional": false,
45+
"editable": true
46+
},
47+
"type": {
48+
"metadata": {
49+
"label": "Type",
50+
"description": "Type of the variable"
51+
},
52+
"valueType": "TYPE",
53+
"value": "Student",
54+
"optional": false,
55+
"editable": true
56+
}
57+
},
58+
"flags": 0
59+
},
60+
"propertyKey": "expression",
61+
"position": {
62+
"line": 18,
63+
"offset": 65
64+
},
65+
"model": {
66+
"inputs": [
67+
{
68+
"id": "CONST",
69+
"typeName": "CONST",
70+
"kind": "CONST",
71+
"category": "constant"
72+
},
73+
{
74+
"fields": [
75+
{
76+
"id": "userInfo.username",
77+
"variableName": "username",
78+
"typeName": "string",
79+
"kind": "string"
80+
},
81+
{
82+
"id": "userInfo.password",
83+
"variableName": "password",
84+
"typeName": "string",
85+
"kind": "string"
86+
}
87+
],
88+
"id": "userInfo",
89+
"variableName": "userInfo",
90+
"typeName": "UserInfo",
91+
"kind": "record",
92+
"category": "variable"
93+
}
94+
],
95+
"output": {
96+
"fields": [
97+
{
98+
"id": "student.username",
99+
"variableName": "username",
100+
"typeName": "string",
101+
"kind": "string"
102+
},
103+
{
104+
"id": "student.password",
105+
"variableName": "password",
106+
"typeName": "string",
107+
"kind": "string"
108+
}
109+
],
110+
"id": "student",
111+
"variableName": "student",
112+
"typeName": "Student",
113+
"kind": "record"
114+
},
115+
"subMappings": [
116+
{
117+
"fields": [
118+
{
119+
"id": "s.username",
120+
"variableName": "username",
121+
"typeName": "string",
122+
"kind": "string"
123+
},
124+
{
125+
"id": "s.password",
126+
"variableName": "password",
127+
"typeName": "string",
128+
"kind": "string"
129+
}
130+
],
131+
"id": "s",
132+
"variableName": "s",
133+
"typeName": "Student",
134+
"kind": "record"
135+
},
136+
{
137+
"id": "x",
138+
"typeName": "int",
139+
"kind": "int"
140+
}
141+
],
142+
"mappings": [
143+
{
144+
"output": "student",
145+
"inputs": [],
146+
"expression": "let Student s = {username: \"U\", password: \"PWD\"}, let int x = 2 in {username: userInfo.username}",
147+
"diagnostics": [
148+
"invalid token 'let'",
149+
"missing non-defaultable required record field 'password'"
150+
],
151+
"elements": []
152+
}
153+
]
154+
}
155+
}

0 commit comments

Comments
 (0)