Skip to content

Commit c72cfe5

Browse files
committed
[Fix #461] oneOf options must inherit union class common part
Signed-off-by: Francisco Javier Tirado Sarti <[email protected]>
1 parent 46961c6 commit c72cfe5

File tree

5 files changed

+108
-69
lines changed

5 files changed

+108
-69
lines changed

api/src/main/java/io/serverlessworkflow/api/OneOfValueProvider.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@
1515
*/
1616
package io.serverlessworkflow.api;
1717

18-
public interface OneOfValueProvider {
19-
Object get();
18+
public interface OneOfValueProvider<T> {
19+
T get();
2020
}

api/src/test/java/io/serverlessworkflow/api/FeaturesTest.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ public class FeaturesTest {
4545
"features/try.yaml",
4646
"features/listen.yaml",
4747
"features/callFunction.yaml",
48-
"features/callCustomFunction.yaml"
48+
"features/callCustomFunction.yaml",
49+
"features/call-http-query-parameters.yaml"
4950
})
5051
public void testSpecFeaturesParsing(String workflowLocation) throws IOException {
5152
Workflow workflow = readWorkflowFromClasspath(workflowLocation);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
document:
2+
dsl: 1.0.0-alpha2
3+
namespace: examples
4+
name: http-query-params
5+
version: 1.0.0-alpha2
6+
input:
7+
schema:
8+
format: json
9+
document:
10+
type: object
11+
required:
12+
- searchQuery
13+
properties:
14+
searchQuery:
15+
type: string
16+
do:
17+
- searchStarWarsCharacters:
18+
call: http
19+
with:
20+
method: get
21+
endpoint: https://swapi.dev/api/people/
22+
query:
23+
search: ${.searchQuery}
24+

custom-generator/src/main/java/io/serverlessworkflow/generator/AllAnyOneOfSchemaRule.java

+79-65
Original file line numberDiff line numberDiff line change
@@ -150,82 +150,115 @@ public JType apply(
150150
ruleFactory.getEnumRule().apply(nodeName, schemaNode, parent, generatableType, schema);
151151
} else if (!schemaNode.has("properties") && unionTypes.isEmpty() && refType.isPresent()) {
152152
javaType = refType.get();
153+
} else if (!unionTypes.isEmpty()) {
154+
JPackage container = generatableType.getPackage();
155+
JType generatedType =
156+
ruleFactory.getTypeRule().apply(nodeName, schemaNode, parent, container, schema);
157+
try {
158+
JDefinedClass unionClass;
159+
Optional<JType> commonType;
160+
if (generatedType instanceof JDefinedClass) {
161+
JDefinedClass clazz = (JDefinedClass) generatedType;
162+
if (clazz.methods().isEmpty()) {
163+
unionClass = clazz;
164+
commonType = Optional.empty();
165+
} else {
166+
unionClass = container._class(clazz.name() + "Union");
167+
commonType = Optional.of(clazz);
168+
}
153169

170+
} else {
171+
unionClass =
172+
container._class(
173+
ruleFactory.getNameHelper().getUniqueClassName(nodeName, schemaNode, container));
174+
commonType = Optional.empty();
175+
}
176+
javaType =
177+
populateRef(populateClass(schema, unionClass, commonType, unionTypes), refType, schema);
178+
schema.setJavaTypeIfEmpty(javaType);
179+
} catch (JClassAlreadyExistsException ex) {
180+
throw new IllegalStateException(ex);
181+
}
154182
} else {
155183
javaType =
156184
ruleFactory
157185
.getTypeRule()
158186
.apply(nodeName, schemaNode, parent, generatableType.getPackage(), schema);
159187
if (javaType instanceof JDefinedClass) {
160-
populateClass(schema, (JDefinedClass) javaType, refType, unionTypes);
161-
} else if (!unionTypes.isEmpty()) {
162-
javaType =
163-
createUnionClass(
164-
schema, nodeName, schemaNode, generatableType.getPackage(), refType, unionTypes);
188+
populateRef((JDefinedClass) javaType, refType, schema);
165189
}
166190
schema.setJavaTypeIfEmpty(javaType);
167191
}
192+
168193
return javaType;
169194
}
170195

171196
private JDefinedClass populateClass(
172197
Schema parentSchema,
173198
JDefinedClass definedClass,
174-
Optional<JType> refType,
199+
Optional<JType> commonType,
175200
Collection<JTypeWrapper> unionTypes) {
176-
JType clazzClass = definedClass.owner()._ref(Object.class);
201+
JFieldVar valueField =
202+
definedClass.field(
203+
JMod.PRIVATE,
204+
commonType.orElse(definedClass.owner().ref(Object.class)),
205+
ruleFactory.getNameHelper().getPropertyName("value", null),
206+
null);
177207

178-
Optional<JFieldVar> valueField;
179-
if (!unionTypes.isEmpty()) {
180-
valueField =
181-
Optional.of(
182-
definedClass.field(
183-
JMod.PRIVATE,
184-
clazzClass,
185-
ruleFactory.getNameHelper().getPropertyName("value", null),
186-
null));
208+
definedClass._implements(
209+
definedClass
210+
.owner()
211+
.ref(GeneratorUtils.ONE_OF_VALUE_PROVIDER_INTERFACE_NAME)
212+
.narrow(valueField.type()));
187213

188-
definedClass._implements(
189-
definedClass.owner().ref(GeneratorUtils.ONE_OF_VALUE_PROVIDER_INTERFACE_NAME));
214+
GeneratorUtils.implementInterface(definedClass, valueField);
190215

191-
GeneratorUtils.implementInterface(definedClass, valueField.orElseThrow());
216+
try {
217+
JDefinedClass serializer = generateSerializer(definedClass);
218+
definedClass.annotate(JsonSerialize.class).param("using", serializer);
219+
} catch (JClassAlreadyExistsException ex) {
220+
// already serialized aware
221+
}
192222

193-
try {
194-
JDefinedClass serializer = generateSerializer(definedClass);
195-
definedClass.annotate(JsonSerialize.class).param("using", serializer);
196-
} catch (JClassAlreadyExistsException ex) {
197-
// already serialized aware
198-
}
223+
try {
224+
JDefinedClass deserializer = generateDeserializer(definedClass, unionTypes);
225+
definedClass.annotate(JsonDeserialize.class).param("using", deserializer);
226+
} catch (JClassAlreadyExistsException ex) {
227+
// already deserialized aware
228+
}
199229

200-
try {
201-
JDefinedClass deserializer = generateDeserializer(definedClass, unionTypes);
202-
definedClass.annotate(JsonDeserialize.class).param("using", deserializer);
203-
} catch (JClassAlreadyExistsException ex) {
204-
// already deserialized aware
205-
}
230+
Collection<JTypeWrapper> stringTypes = new ArrayList<>();
231+
for (JTypeWrapper unionType : unionTypes) {
232+
if (isStringType(unionType.getType())) {
233+
stringTypes.add(unionType);
234+
} else {
206235

207-
Collection<JTypeWrapper> stringTypes = new ArrayList<>();
208-
for (JTypeWrapper unionType : unionTypes) {
209-
if (isStringType(unionType.getType())) {
210-
stringTypes.add(unionType);
211-
} else {
212-
wrapIt(parentSchema, definedClass, valueField, unionType.getType(), unionType.getNode());
236+
if (unionType.getType() instanceof JDefinedClass) {
237+
commonType.ifPresent(
238+
c -> ((JDefinedClass) unionType.getType())._extends((JDefinedClass) c));
213239
}
240+
wrapIt(
241+
parentSchema,
242+
definedClass,
243+
Optional.of(valueField),
244+
unionType.getType(),
245+
unionType.getNode());
214246
}
215-
if (!stringTypes.isEmpty()) {
216-
wrapStrings(parentSchema, definedClass, valueField, stringTypes);
217-
}
218-
219-
} else {
220-
valueField = Optional.empty();
221247
}
248+
if (!stringTypes.isEmpty()) {
249+
wrapStrings(parentSchema, definedClass, valueField, stringTypes);
250+
}
251+
return definedClass;
252+
}
222253

254+
private JDefinedClass populateRef(
255+
JDefinedClass definedClass, Optional<JType> refType, Schema parentSchema) {
223256
refType.ifPresent(
224257
type -> {
225258
if (type instanceof JClass) {
226259
definedClass._extends((JClass) type);
227260
} else {
228-
wrapIt(parentSchema, definedClass, valueField, type, null);
261+
wrapIt(parentSchema, definedClass, Optional.empty(), type, null);
229262
}
230263
});
231264

@@ -280,25 +313,6 @@ private JDefinedClass generateDeserializer(
280313
return definedClass;
281314
}
282315

283-
private JDefinedClass createUnionClass(
284-
Schema parentSchema,
285-
String nodeName,
286-
JsonNode schemaNode,
287-
JPackage container,
288-
Optional<JType> refType,
289-
Collection<JTypeWrapper> unionTypes) {
290-
try {
291-
return populateClass(
292-
parentSchema,
293-
container._class(
294-
ruleFactory.getNameHelper().getUniqueClassName(nodeName, schemaNode, container)),
295-
refType,
296-
unionTypes);
297-
} catch (JClassAlreadyExistsException e) {
298-
throw new IllegalArgumentException(e);
299-
}
300-
}
301-
302316
private void wrapIt(
303317
Schema parentSchema,
304318
JDefinedClass definedClass,
@@ -316,7 +330,7 @@ private void wrapIt(
316330
private void wrapStrings(
317331
Schema parentSchema,
318332
JDefinedClass definedClass,
319-
Optional<JFieldVar> valueField,
333+
JFieldVar valueField,
320334
Collection<JTypeWrapper> stringTypes) {
321335
Iterator<JTypeWrapper> iter = stringTypes.iterator();
322336
JTypeWrapper first = iter.next();
@@ -330,7 +344,7 @@ private void wrapStrings(
330344
JFieldVar instanceField =
331345
getInstanceField(parentSchema, definedClass, first.getType(), first.getNode());
332346
JVar instanceParam = constructor.param(first.type, instanceField.name());
333-
valueField.ifPresent(v -> body.assign(JExpr._this().ref(v), instanceParam));
347+
body.assign(JExpr._this().ref(valueField), instanceParam);
334348
if (pattern != null) {
335349
JConditional condition =
336350
body._if(getPatternCondition(pattern, body, instanceField, instanceParam, definedClass));

custom-generator/src/main/java/io/serverlessworkflow/generator/GeneratorUtils.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public static JDefinedClass deserializerClass(JDefinedClass relatedClass)
6060
}
6161

6262
public static JMethod implementInterface(JDefinedClass definedClass, JFieldVar valueField) {
63-
JMethod method = definedClass.method(JMod.PUBLIC, Object.class, "get");
63+
JMethod method = definedClass.method(JMod.PUBLIC, valueField.type(), "get");
6464
method.annotate(Override.class);
6565
method.body()._return(valueField);
6666
return method;

0 commit comments

Comments
 (0)