Skip to content

Commit 9fdd1fd

Browse files
Merge pull request #383 from fjtirado/Fix_#380
[Fix #380] Change item API
2 parents e5828d5 + 9a91a05 commit 9fdd1fd

16 files changed

+257
-23
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class CallTaskDeserializer extends JsonDeserializer<CallTask> {
3030

3131
@Override
3232
public CallTask deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
33-
return DeserializeHelper.deserialize(
33+
return DeserializeHelper.deserializeOneOf(
3434
p,
3535
CallTask.class,
3636
List.of(CallHTTP.class, CallAsyncAPI.class, CallOpenAPI.class, CallGRPC.class));

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,6 @@ class CallTaskSerializer extends JsonSerializer<CallTask> {
2525
@Override
2626
public void serialize(CallTask value, JsonGenerator gen, SerializerProvider serializers)
2727
throws IOException {
28-
SerializeHelper.serialize(gen, value);
28+
SerializeHelper.serializeOneOf(gen, value);
2929
}
3030
}

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

+14-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
public class DeserializeHelper {
2626

27-
public static <T> T deserialize(
27+
public static <T> T deserializeOneOf(
2828
JsonParser p, Class<T> targetClass, Collection<Class<?>> unionTypes) throws IOException {
2929
TreeNode node = p.readValueAsTree();
3030
JsonProcessingException ex = new JsonMappingException("Problem deserializing " + targetClass);
@@ -38,4 +38,17 @@ public static <T> T deserialize(
3838
}
3939
throw ex;
4040
}
41+
42+
public static <T> T deserializeItem(JsonParser p, Class<T> targetClass, Class<?> valueClass)
43+
throws IOException {
44+
TreeNode node = p.readValueAsTree();
45+
String fieldName = node.fieldNames().next();
46+
try {
47+
return targetClass
48+
.getConstructor(String.class, valueClass)
49+
.newInstance(fieldName, p.getCodec().treeToValue(node.get(fieldName), valueClass));
50+
} catch (ReflectiveOperationException e) {
51+
throw new IOException(e);
52+
}
53+
}
4154
}

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

+7
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
2222
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature;
2323
import io.serverlessworkflow.api.types.CallTask;
24+
import io.serverlessworkflow.api.types.SwitchItem;
2425
import io.serverlessworkflow.api.types.Task;
26+
import io.serverlessworkflow.api.types.TaskItem;
2527

2628
class ObjectMapperFactory {
2729

@@ -44,6 +46,11 @@ private static ObjectMapper configure(ObjectMapper mapper) {
4446
simpleModule.addSerializer(Task.class, new TaskSerializer());
4547
simpleModule.addDeserializer(CallTask.class, new CallTaskDeserializer());
4648
simpleModule.addSerializer(CallTask.class, new CallTaskSerializer());
49+
simpleModule.addDeserializer(TaskItem.class, new TaskItemDeserializer());
50+
simpleModule.addSerializer(TaskItem.class, new TaskItemSerializer());
51+
simpleModule.addSerializer(SwitchItem.class, new SwitchItemSerializer());
52+
simpleModule.addDeserializer(SwitchItem.class, new SwitchItemDeserializer());
53+
4754
return mapper
4855
.configure(SerializationFeature.INDENT_OUTPUT, true)
4956
.configure(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, false)

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import java.lang.reflect.Method;
2121

2222
public class SerializeHelper {
23-
public static void serialize(JsonGenerator jgen, Object item) throws IOException {
23+
public static void serializeOneOf(JsonGenerator jgen, Object item) throws IOException {
2424
try {
2525
for (Method m : item.getClass().getDeclaredMethods()) {
2626
Object value = m.invoke(item);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.api;
17+
18+
import com.fasterxml.jackson.core.JsonParser;
19+
import com.fasterxml.jackson.databind.DeserializationContext;
20+
import com.fasterxml.jackson.databind.JsonDeserializer;
21+
import io.serverlessworkflow.api.types.SwitchCase;
22+
import io.serverlessworkflow.api.types.SwitchItem;
23+
import java.io.IOException;
24+
25+
class SwitchItemDeserializer extends JsonDeserializer<SwitchItem> {
26+
27+
@Override
28+
public SwitchItem deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
29+
return DeserializeHelper.deserializeItem(p, SwitchItem.class, SwitchCase.class);
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.api;
17+
18+
import com.fasterxml.jackson.core.JsonGenerator;
19+
import com.fasterxml.jackson.databind.JsonSerializer;
20+
import com.fasterxml.jackson.databind.SerializerProvider;
21+
import io.serverlessworkflow.api.types.SwitchItem;
22+
import java.io.IOException;
23+
24+
class SwitchItemSerializer extends JsonSerializer<SwitchItem> {
25+
26+
@Override
27+
public void serialize(SwitchItem value, JsonGenerator gen, SerializerProvider serializers)
28+
throws IOException {
29+
gen.writeStartObject();
30+
gen.writeObjectField(value.getName(), value.getSwitchCase());
31+
gen.writeEndObject();
32+
}
33+
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class TaskDeserializer extends JsonDeserializer<Task> {
3838

3939
@Override
4040
public Task deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
41-
return DeserializeHelper.deserialize(
41+
return DeserializeHelper.deserializeOneOf(
4242
p,
4343
Task.class,
4444
List.of(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.api;
17+
18+
import com.fasterxml.jackson.core.JsonParser;
19+
import com.fasterxml.jackson.databind.DeserializationContext;
20+
import com.fasterxml.jackson.databind.JsonDeserializer;
21+
import io.serverlessworkflow.api.types.Task;
22+
import io.serverlessworkflow.api.types.TaskItem;
23+
import java.io.IOException;
24+
25+
class TaskItemDeserializer extends JsonDeserializer<TaskItem> {
26+
27+
@Override
28+
public TaskItem deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
29+
return DeserializeHelper.deserializeItem(p, TaskItem.class, Task.class);
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.api;
17+
18+
import com.fasterxml.jackson.core.JsonGenerator;
19+
import com.fasterxml.jackson.databind.JsonSerializer;
20+
import com.fasterxml.jackson.databind.SerializerProvider;
21+
import io.serverlessworkflow.api.types.TaskItem;
22+
import java.io.IOException;
23+
24+
class TaskItemSerializer extends JsonSerializer<TaskItem> {
25+
26+
@Override
27+
public void serialize(TaskItem value, JsonGenerator gen, SerializerProvider serializers)
28+
throws IOException {
29+
gen.writeStartObject();
30+
gen.writeObjectField(value.getName(), value.getTask());
31+
gen.writeEndObject();
32+
}
33+
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ class TaskSerializer extends JsonSerializer<Task> {
2626
@Override
2727
public void serialize(Task value, JsonGenerator gen, SerializerProvider serializers)
2828
throws IOException {
29-
SerializeHelper.serialize(gen, value);
29+
SerializeHelper.serializeOneOf(gen, value);
3030
}
3131
}

api/src/main/resources/schema/workflow.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -571,8 +571,10 @@ $defs:
571571
type: object
572572
minProperties: 1
573573
maxProperties: 1
574+
title: SwitchItem
574575
additionalProperties:
575576
type: object
577+
title: SwitchCase
576578
properties:
577579
name:
578580
type: string

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ public class ApiTest {
3131
void testCallHTTPAPI() throws IOException {
3232
Workflow workflow = readWorkflowFromClasspath("features/callHttp.yaml");
3333
assertThat(workflow.getDo()).isNotEmpty();
34-
assertThat(workflow.getDo().get(0).getAdditionalProperties()).isNotEmpty();
35-
assertThat(workflow.getDo().get(0).getAdditionalProperties().values()).isNotEmpty();
36-
Task task = workflow.getDo().get(0).getAdditionalProperties().values().iterator().next();
34+
assertThat(workflow.getDo().get(0).getName()).isNotNull();
35+
assertThat(workflow.getDo().get(0).getTask()).isNotNull();
36+
Task task = workflow.getDo().get(0).getTask();
3737
CallTask callTask = task.getCallTask();
3838
assertThat(callTask).isNotNull();
3939
assertThat(task.getDoTask()).isNull();

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

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

18-
import static org.apache.commons.lang3.StringUtils.*;
19-
2018
import com.fasterxml.jackson.databind.JsonNode;
2119
import com.fasterxml.jackson.databind.node.ArrayNode;
2220
import com.sun.codemodel.JClass;
@@ -127,16 +125,8 @@ private JDefinedClass createUnionClass(
127125

128126
private void wrapIt(JDefinedClass definedClass, JType unionType) {
129127
JFieldVar instanceField =
130-
definedClass.field(
131-
JMod.PRIVATE,
132-
unionType,
133-
ruleFactory.getNameHelper().getPropertyName(unionType.name(), null));
134-
JMethod method =
135-
definedClass.method(
136-
JMod.PUBLIC,
137-
unionType,
138-
ruleFactory.getNameHelper().getGetterName(unionType.name(), unionType, null));
139-
method.body()._return(instanceField);
128+
GeneratorUtils.addGetter(
129+
definedClass, unionType, ruleFactory.getNameHelper(), unionType.name());
140130
JMethod constructor = definedClass.constructor(JMod.PUBLIC);
141131
constructor
142132
.body()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.generator;
17+
18+
import com.sun.codemodel.JDefinedClass;
19+
import com.sun.codemodel.JFieldVar;
20+
import com.sun.codemodel.JMethod;
21+
import com.sun.codemodel.JMod;
22+
import com.sun.codemodel.JType;
23+
import org.jsonschema2pojo.util.NameHelper;
24+
25+
public class GeneratorUtils {
26+
27+
public static JFieldVar addGetter(
28+
JDefinedClass definedClass, JType type, NameHelper nameHelper, String name) {
29+
JFieldVar instanceField =
30+
definedClass.field(JMod.PRIVATE, type, nameHelper.getPropertyName(name, null));
31+
JMethod method =
32+
definedClass.method(JMod.PUBLIC, type, nameHelper.getGetterName(name, type, null));
33+
method.body()._return(instanceField);
34+
return instanceField;
35+
}
36+
37+
private GeneratorUtils() {}
38+
}

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

+58-2
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,25 @@
1717

1818
import com.fasterxml.jackson.databind.JsonNode;
1919
import com.sun.codemodel.JDefinedClass;
20+
import com.sun.codemodel.JExpr;
21+
import com.sun.codemodel.JFieldVar;
22+
import com.sun.codemodel.JMethod;
23+
import com.sun.codemodel.JMod;
24+
import com.sun.codemodel.JType;
2025
import org.jsonschema2pojo.Schema;
2126
import org.jsonschema2pojo.rules.AdditionalPropertiesRule;
2227
import org.jsonschema2pojo.rules.Rule;
28+
import org.jsonschema2pojo.rules.RuleFactory;
29+
import org.jsonschema2pojo.util.NameHelper;
2330

2431
public class UnevaluatedPropertiesRule extends AdditionalPropertiesRule
2532
implements Rule<JDefinedClass, JDefinedClass> {
2633

27-
public UnevaluatedPropertiesRule(UnreferencedFactory unreferencedFactory) {
28-
super(unreferencedFactory);
34+
private RuleFactory ruleFactory;
35+
36+
public UnevaluatedPropertiesRule(RuleFactory ruleFactory) {
37+
super(ruleFactory);
38+
this.ruleFactory = ruleFactory;
2939
}
3040

3141
public JDefinedClass apply(
@@ -35,8 +45,54 @@ public JDefinedClass apply(
3545
|| (node == null && parent.has("properties"))) {
3646
// no additional properties allowed
3747
return jclass;
48+
} else if (node != null
49+
&& checkIntValue(parent, "maxProperties", 1)
50+
&& checkIntValue(parent, "minProperties", 1)) {
51+
return addKeyValueFields(jclass, node, parent, nodeName, schema);
3852
} else {
3953
return super.apply(nodeName, node, parent, jclass, schema);
4054
}
4155
}
56+
57+
private JDefinedClass addKeyValueFields(
58+
JDefinedClass jclass, JsonNode node, JsonNode parent, String nodeName, Schema schema) {
59+
NameHelper nameHelper = ruleFactory.getNameHelper();
60+
JType stringClass = jclass.owner()._ref(String.class);
61+
JFieldVar nameField = GeneratorUtils.addGetter(jclass, stringClass, nameHelper, "name");
62+
JType propertyType;
63+
if (node != null && node.size() != 0) {
64+
String pathToAdditionalProperties;
65+
if (schema.getId().getFragment() == null) {
66+
pathToAdditionalProperties = "#/additionalProperties";
67+
} else {
68+
pathToAdditionalProperties = "#" + schema.getId().getFragment() + "/additionalProperties";
69+
}
70+
Schema additionalPropertiesSchema =
71+
ruleFactory
72+
.getSchemaStore()
73+
.create(
74+
schema,
75+
pathToAdditionalProperties,
76+
ruleFactory.getGenerationConfig().getRefFragmentPathDelimiters());
77+
propertyType =
78+
ruleFactory
79+
.getSchemaRule()
80+
.apply(nodeName + "Property", node, parent, jclass, additionalPropertiesSchema);
81+
additionalPropertiesSchema.setJavaTypeIfEmpty(propertyType);
82+
} else {
83+
propertyType = jclass.owner().ref(Object.class);
84+
}
85+
JFieldVar valueField =
86+
GeneratorUtils.addGetter(jclass, propertyType, nameHelper, propertyType.name());
87+
JMethod constructor = jclass.constructor(JMod.PUBLIC);
88+
constructor
89+
.body()
90+
.assign(JExpr._this().ref(nameField), constructor.param(stringClass, nameField.name()))
91+
.assign(JExpr._this().ref(valueField), constructor.param(propertyType, valueField.name()));
92+
return jclass;
93+
}
94+
95+
private boolean checkIntValue(JsonNode node, String propName, int value) {
96+
return node.has(propName) && node.get(propName).asInt() == value;
97+
}
4298
}

0 commit comments

Comments
 (0)