Skip to content

Commit 1cb65b4

Browse files
authoredJul 26, 2024··
Merge pull request #390 from fjtirado/Fix_#379
2 parents 6a02d21 + 9ebcdbe commit 1cb65b4

15 files changed

+292
-394
lines changed
 

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

-38
This file was deleted.

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

-30
This file was deleted.

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

+1-17
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,8 @@
1717

1818
import com.fasterxml.jackson.databind.ObjectMapper;
1919
import com.fasterxml.jackson.databind.SerializationFeature;
20-
import com.fasterxml.jackson.databind.module.SimpleModule;
2120
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
2221
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature;
23-
import io.serverlessworkflow.api.types.CallTask;
24-
import io.serverlessworkflow.api.types.SwitchItem;
25-
import io.serverlessworkflow.api.types.Task;
26-
import io.serverlessworkflow.api.types.TaskItem;
2722

2823
class ObjectMapperFactory {
2924

@@ -41,21 +36,10 @@ public static final ObjectMapper yamlMapper() {
4136
}
4237

4338
private static ObjectMapper configure(ObjectMapper mapper) {
44-
SimpleModule simpleModule = new SimpleModule();
45-
simpleModule.addDeserializer(Task.class, new TaskDeserializer());
46-
simpleModule.addSerializer(Task.class, new TaskSerializer());
47-
simpleModule.addDeserializer(CallTask.class, new CallTaskDeserializer());
48-
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-
5439
return mapper
5540
.configure(SerializationFeature.INDENT_OUTPUT, true)
5641
.configure(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, false)
57-
.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false)
58-
.registerModule(simpleModule);
42+
.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
5943
}
6044

6145
private ObjectMapperFactory() {}

‎api/src/main/java/io/serverlessworkflow/api/SwitchItemDeserializer.java

-31
This file was deleted.

‎api/src/main/java/io/serverlessworkflow/api/SwitchItemSerializer.java

-33
This file was deleted.

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

-58
This file was deleted.

‎api/src/main/java/io/serverlessworkflow/api/TaskItemDeserializer.java

-31
This file was deleted.

‎api/src/main/java/io/serverlessworkflow/api/TaskItemSerializer.java

-33
This file was deleted.

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

-31
This file was deleted.

‎api/src/main/java/io/serverlessworkflow/api/DeserializeHelper.java renamed to ‎api/src/main/java/io/serverlessworkflow/serialization/DeserializeHelper.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package io.serverlessworkflow.api;
16+
package io.serverlessworkflow.serialization;
1717

1818
import com.fasterxml.jackson.core.JsonParser;
1919
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -27,7 +27,8 @@ public class DeserializeHelper {
2727
public static <T> T deserializeOneOf(
2828
JsonParser p, Class<T> targetClass, Collection<Class<?>> unionTypes) throws IOException {
2929
TreeNode node = p.readValueAsTree();
30-
JsonProcessingException ex = new JsonMappingException("Problem deserializing " + targetClass);
30+
JsonProcessingException ex =
31+
new JsonMappingException(p, "Problem deserializing " + targetClass);
3132
for (Class<?> unionType : unionTypes) {
3233
try {
3334
Object object = p.getCodec().treeToValue(node, unionType);

‎api/src/main/java/io/serverlessworkflow/api/SerializeHelper.java renamed to ‎api/src/main/java/io/serverlessworkflow/serialization/SerializeHelper.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package io.serverlessworkflow.api;
16+
package io.serverlessworkflow.serialization;
1717

1818
import com.fasterxml.jackson.core.JsonGenerator;
1919
import java.io.IOException;

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

+107-76
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ properties:
103103
description: Schedules the workflow
104104
$defs:
105105
taskList:
106+
title: TaskList
106107
type: array
107108
items:
108109
type: object
@@ -181,10 +182,8 @@ $defs:
181182
type: object
182183
description: The payload to call the AsyncAPI operation with, if any.
183184
authentication:
185+
$ref: '#/$defs/referenceableAuthenticationPolicy'
184186
description: The authentication policy, if any, to use when calling the AsyncAPI operation.
185-
oneOf:
186-
- $ref: '#/$defs/authenticationPolicy'
187-
- type: string
188187
required: [ document, operationRef ]
189188
additionalProperties: false
190189
description: Defines the AsyncAPI call to perform.
@@ -216,14 +215,12 @@ $defs:
216215
description: The hostname of the GRPC service to call.
217216
port:
218217
type: integer
219-
min: 0
220-
max: 65535
218+
minimum: 0
219+
maximum: 65535
221220
description: The port number of the GRPC service to call.
222221
authentication:
222+
$ref: '#/$defs/referenceableAuthenticationPolicy'
223223
description: The endpoint's authentication policy, if any.
224-
oneOf:
225-
- $ref: '#/$defs/authenticationPolicy'
226-
- type: string
227224
required: [ name, host ]
228225
method:
229226
type: string
@@ -293,10 +290,8 @@ $defs:
293290
additionalProperties: true
294291
description: A name/value mapping of the parameters of the OpenAPI operation to call.
295292
authentication:
293+
$ref: '#/$defs/referenceableAuthenticationPolicy'
296294
description: The authentication policy, if any, to use when calling the OpenAPI operation.
297-
oneOf:
298-
- $ref: '#/$defs/authenticationPolicy'
299-
- type: string
300295
output:
301296
type: string
302297
enum: [ raw, content, response ]
@@ -320,6 +315,7 @@ $defs:
320315
additionalProperties: true
321316
description: A name/value mapping of the parameters, if any, to call the function with.
322317
forkTask:
318+
title: ForkTask
323319
description: Allows workflows to execute multiple tasks concurrently and optionally race them against each other, with a single possible winner, which sets the task's output.
324320
$ref: '#/$defs/taskBase'
325321
type: object
@@ -337,6 +333,7 @@ $defs:
337333
type: boolean
338334
default: false
339335
doTask:
336+
title: DoTask
340337
description: Allows to execute a list of tasks in sequence
341338
$ref: '#/$defs/taskBase'
342339
type: object
@@ -346,6 +343,7 @@ $defs:
346343
do:
347344
$ref: '#/$defs/taskList'
348345
emitTask:
346+
title: EmitTask
349347
description: Allows workflows to publish events to event brokers or messaging systems, facilitating communication and coordination between different components and services.
350348
$ref: '#/$defs/taskBase'
351349
type: object
@@ -383,6 +381,7 @@ $defs:
383381
additionalProperties: true
384382
required: [ event ]
385383
forTask:
384+
title: ForTask
386385
description: Allows workflows to iterate over a collection of items, executing a defined set of subtasks for each item in the collection. This task type is instrumental in handling scenarios such as batch processing, data transformation, and repetitive operations across datasets.
387386
$ref: '#/$defs/taskBase'
388387
type: object
@@ -410,6 +409,7 @@ $defs:
410409
do:
411410
$ref: '#/$defs/taskList'
412411
listenTask:
412+
title: ListenTask
413413
description: Provides a mechanism for workflows to await and react to external events, enabling event-driven behavior within workflow systems.
414414
$ref: '#/$defs/taskBase'
415415
type: object
@@ -424,6 +424,7 @@ $defs:
424424
description: Defines the event(s) to listen to.
425425
required: [ to ]
426426
raiseTask:
427+
title: RaiseTask
427428
description: Intentionally triggers and propagates errors.
428429
$ref: '#/$defs/taskBase'
429430
type: object
@@ -438,6 +439,7 @@ $defs:
438439
description: Defines the error to raise.
439440
required: [ error ]
440441
runTask:
442+
title: RunTask
441443
description: Provides the capability to execute external containers, shell commands, scripts, or workflows.
442444
$ref: '#/$defs/taskBase'
443445
type: object
@@ -546,6 +548,7 @@ $defs:
546548
required: [ workflow ]
547549
description: Enables the invocation and execution of nested workflows within a parent workflow, facilitating modularization, reusability, and abstraction of complex logic or business processes by encapsulating them into standalone workflow units.
548550
setTask:
551+
title: SetTask
549552
description: A task used to set data
550553
$ref: '#/$defs/taskBase'
551554
type: object
@@ -558,6 +561,7 @@ $defs:
558561
additionalProperties: true
559562
description: The data to set
560563
switchTask:
564+
title: SwitchTask
561565
description: Enables conditional branching within workflows, allowing them to dynamically select different paths based on specified conditions or criteria
562566
$ref: '#/$defs/taskBase'
563567
type: object
@@ -575,17 +579,17 @@ $defs:
575579
additionalProperties:
576580
type: object
577581
title: SwitchCase
582+
required:
583+
- then
578584
properties:
579-
name:
580-
type: string
581-
description: The case's name.
582585
when:
583586
type: string
584587
description: A runtime expression used to determine whether or not the case matches.
585588
then:
586589
$ref: '#/$defs/flowDirective'
587590
description: The flow directive to execute when the case matches.
588591
tryTask:
592+
title: TryTask
589593
description: Serves as a mechanism within workflows to handle errors gracefully, potentially retrying failed tasks before proceeding with alternate ones.
590594
$ref: '#/$defs/taskBase'
591595
type: object
@@ -617,6 +621,7 @@ $defs:
617621
description: The definition of the task(s) to run when catching an error.
618622
$ref: '#/$defs/taskList'
619623
waitTask:
624+
title: WaitTask
620625
description: Allows workflows to pause or delay their execution for a specified period of time.
621626
$ref: '#/$defs/taskBase'
622627
type: object
@@ -627,85 +632,109 @@ $defs:
627632
description: The amount of time to wait.
628633
$ref: '#/$defs/duration'
629634
flowDirective:
630-
additionalProperties: false
631635
anyOf:
632636
- type: string
633637
enum: [ continue, exit, end ]
634638
default: continue
635639
- type: string
640+
referenceableAuthenticationPolicy:
641+
type: object
642+
oneOf:
643+
- title: AuthenticationPolicyReference
644+
properties:
645+
use:
646+
type: string
647+
minLength: 1
648+
description: The name of the authentication policy to use
649+
required: [use]
650+
- $ref: '#/$defs/authenticationPolicy'
651+
secretBasedAuthenticationPolicy:
652+
type: object
653+
properties:
654+
use:
655+
type: string
656+
minLength: 1
657+
description: The name of the authentication policy to use
658+
required: [use]
636659
authenticationPolicy:
637660
type: object
638661
oneOf:
639662
- title: BasicAuthenticationPolicy
640663
properties:
641664
basic:
642665
type: object
643-
properties:
644-
username:
645-
type: string
646-
description: The username to use.
647-
password:
648-
type: string
649-
description: The password to use.
650-
required: [ username, password ]
666+
oneOf:
667+
- properties:
668+
username:
669+
type: string
670+
description: The username to use.
671+
password:
672+
type: string
673+
description: The password to use.
674+
required: [ username, password ]
675+
- $ref: '#/$defs/secretBasedAuthenticationPolicy'
651676
required: [ basic ]
652677
description: Use basic authentication.
653678
- title: BearerAuthenticationPolicy
654679
properties:
655680
bearer:
656681
type: object
657-
properties:
658-
token:
659-
type: string
660-
description: The bearer token to use.
661-
required: [ token ]
682+
oneOf:
683+
- properties:
684+
token:
685+
type: string
686+
description: The bearer token to use.
687+
required: [ token ]
688+
- $ref: '#/$defs/secretBasedAuthenticationPolicy'
662689
required: [ bearer ]
663690
description: Use bearer authentication.
664691
- title: OAuth2AuthenticationPolicy
665692
properties:
666693
oauth2:
667694
type: object
668-
properties:
669-
authority:
670-
type: string
671-
format: uri
672-
description: The URI that references the OAuth2 authority to use.
673-
grant:
674-
type: string
675-
description: The grant type to use.
676-
client:
677-
type: object
678-
properties:
679-
id:
695+
oneOf:
696+
- properties:
697+
authority:
680698
type: string
681-
description: The client id to use.
682-
secret:
699+
format: uri
700+
description: The URI that references the OAuth2 authority to use.
701+
grant:
683702
type: string
684-
description: The client secret to use, if any.
685-
required: [ id ]
686-
scopes:
687-
type: array
688-
items:
689-
type: string
690-
description: The scopes, if any, to request the token for.
691-
audiences:
692-
type: array
693-
items:
694-
type: string
695-
description: The audiences, if any, to request the token for.
696-
username:
697-
type: string
698-
description: The username to use. Used only if the grant type is Password.
699-
password:
700-
type: string
701-
description: The password to use. Used only if the grant type is Password.
702-
subject:
703-
$ref: '#/$defs/oauth2Token'
704-
description: The security token that represents the identity of the party on behalf of whom the request is being made.
705-
actor:
706-
$ref: '#/$defs/oauth2Token'
707-
description: The security token that represents the identity of the acting party.
708-
required: [ authority, grant, client ]
703+
description: The grant type to use.
704+
client:
705+
type: object
706+
properties:
707+
id:
708+
type: string
709+
description: The client id to use.
710+
secret:
711+
type: string
712+
description: The client secret to use, if any.
713+
required: [ id ]
714+
scopes:
715+
type: array
716+
items:
717+
type: string
718+
description: The scopes, if any, to request the token for.
719+
audiences:
720+
type: array
721+
items:
722+
type: string
723+
description: The audiences, if any, to request the token for.
724+
username:
725+
type: string
726+
description: The username to use. Used only if the grant type is Password.
727+
password:
728+
type: string
729+
description: The password to use. Used only if the grant type is Password.
730+
subject:
731+
$ref: '#/$defs/oauth2Token'
732+
description: The security token that represents the identity of the party on behalf of whom the request is being made.
733+
actor:
734+
$ref: '#/$defs/oauth2Token'
735+
description: The security token that represents the identity of the acting party.
736+
required: [ authority, grant, client ]
737+
- $ref: '#/$defs/secretBasedAuthenticationPolicy'
709738
required: [ oauth2 ]
710739
description: Use OAUTH2 authentication.
711740
description: Defines an authentication policy.
@@ -768,10 +797,8 @@ $defs:
768797
format: uri-template
769798
description: The endpoint's URI.
770799
authentication:
800+
$ref: '#/$defs/referenceableAuthenticationPolicy'
771801
description: The authentication policy to use.
772-
oneOf:
773-
- $ref: '#/$defs/authenticationPolicy'
774-
- type: string
775802
required: [ uri ]
776803
eventConsumptionStrategy:
777804
type: object
@@ -871,10 +898,8 @@ $defs:
871898
format: uri
872899
description: The endpoint's URI.
873900
authentication:
901+
$ref: '#/$defs/referenceableAuthenticationPolicy'
874902
description: The authentication policy to use.
875-
oneOf:
876-
- $ref: '#/$defs/authenticationPolicy'
877-
- type: string
878903
name:
879904
type: string
880905
description: The external resource's name, if any.
@@ -886,7 +911,9 @@ $defs:
886911
$ref: '#/$defs/schema'
887912
description: The schema used to describe and validate the input of the workflow or task.
888913
from:
889-
type: string
914+
oneOf:
915+
- type: string
916+
- type: object
890917
description: A runtime expression, if any, used to mutate and/or filter the input of the workflow or task.
891918
description: Configures the input of a workflow or task.
892919
output:
@@ -896,7 +923,9 @@ $defs:
896923
$ref: '#/$defs/schema'
897924
description: The schema used to describe and validate the output of the workflow or task.
898925
as:
899-
type: string
926+
oneOf:
927+
- type: string
928+
- type: object
900929
description: A runtime expression, if any, used to mutate and/or filter the output of the workflow or task.
901930
description: Configures the output of a workflow or task.
902931
export:
@@ -906,7 +935,9 @@ $defs:
906935
$ref: '#/$defs/schema'
907936
description: The schema used to describe and validate the workflow context.
908937
as:
909-
type: string
938+
oneOf:
939+
- type: string
940+
- type: object
910941
description: A runtime expression, if any, used to export the output data to the context.
911942
description: Set the content of the context.
912943
retryPolicy:

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

+55-4
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,17 @@
1616
package io.serverlessworkflow.generator;
1717

1818
import com.fasterxml.jackson.databind.JsonNode;
19+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
20+
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
1921
import com.fasterxml.jackson.databind.node.ArrayNode;
22+
import com.sun.codemodel.JBlock;
2023
import com.sun.codemodel.JClass;
2124
import com.sun.codemodel.JClassAlreadyExistsException;
2225
import com.sun.codemodel.JClassContainer;
2326
import com.sun.codemodel.JDefinedClass;
2427
import com.sun.codemodel.JExpr;
2528
import com.sun.codemodel.JFieldVar;
29+
import com.sun.codemodel.JInvocation;
2630
import com.sun.codemodel.JMethod;
2731
import com.sun.codemodel.JMod;
2832
import com.sun.codemodel.JPackage;
@@ -32,6 +36,7 @@
3236
import java.net.URLDecoder;
3337
import java.util.Collection;
3438
import java.util.HashSet;
39+
import java.util.List;
3540
import java.util.Optional;
3641
import org.jsonschema2pojo.Jsonschema2Pojo;
3742
import org.jsonschema2pojo.Schema;
@@ -113,20 +118,66 @@ private JDefinedClass populateClass(
113118
return definedClass;
114119
}
115120

121+
private JDefinedClass generateSerializer(JDefinedClass relatedClass) {
122+
JDefinedClass definedClass = GeneratorUtils.serializerClass(relatedClass);
123+
GeneratorUtils.fillSerializer(
124+
definedClass,
125+
relatedClass,
126+
(method, valueParam, genParam) ->
127+
method
128+
.body()
129+
.staticInvoke(
130+
definedClass.owner().ref(GeneratorUtils.SERIALIZE_HELPER_NAME),
131+
"serializeOneOf")
132+
.arg(genParam)
133+
.arg(valueParam));
134+
return definedClass;
135+
}
136+
137+
private JDefinedClass generateDeserializer(
138+
JDefinedClass relatedClass, Collection<JType> unionTypes) {
139+
JDefinedClass definedClass = GeneratorUtils.deserializerClass(relatedClass);
140+
GeneratorUtils.fillDeserializer(
141+
definedClass,
142+
relatedClass,
143+
(method, parserParam) -> {
144+
JBlock body = method.body();
145+
JInvocation list = definedClass.owner().ref(List.class).staticInvoke("of");
146+
unionTypes.forEach(c -> list.arg(((JClass) c).dotclass()));
147+
body._return(
148+
definedClass
149+
.owner()
150+
.ref(GeneratorUtils.DESERIALIZE_HELPER_NAME)
151+
.staticInvoke("deserializeOneOf")
152+
.arg(parserParam)
153+
.arg(relatedClass.dotclass())
154+
.arg(list));
155+
});
156+
return definedClass;
157+
}
158+
116159
private JDefinedClass createUnionClass(
117160
String nodeName, JPackage container, Optional<JType> refType, Collection<JType> unionTypes) {
118-
String className = ruleFactory.getNameHelper().getUniqueClassName(nodeName, null, container);
161+
final String className =
162+
ruleFactory.getNameHelper().getUniqueClassName(nodeName, null, container);
119163
try {
120-
return populateClass(container._class(className), refType, unionTypes);
164+
JDefinedClass definedClass = container._class(className);
165+
definedClass.annotate(JsonSerialize.class).param("using", generateSerializer(definedClass));
166+
definedClass
167+
.annotate(JsonDeserialize.class)
168+
.param("using", generateDeserializer(definedClass, unionTypes));
169+
return populateClass(definedClass, refType, unionTypes);
121170
} catch (JClassAlreadyExistsException e) {
122171
throw new IllegalArgumentException(e);
123172
}
124173
}
125174

126175
private void wrapIt(JDefinedClass definedClass, JType unionType) {
176+
final String name = unionType.name();
127177
JFieldVar instanceField =
128-
GeneratorUtils.addGetter(
129-
definedClass, unionType, ruleFactory.getNameHelper(), unionType.name());
178+
definedClass.field(
179+
JMod.PRIVATE, unionType, ruleFactory.getNameHelper().getPropertyName(name, null));
180+
GeneratorUtils.buildMethod(definedClass, instanceField, ruleFactory.getNameHelper(), name);
130181
JMethod constructor = definedClass.constructor(JMod.PUBLIC);
131182
constructor
132183
.body()

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

+72-7
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,88 @@
1515
*/
1616
package io.serverlessworkflow.generator;
1717

18+
import com.fasterxml.jackson.core.JsonGenerator;
19+
import com.fasterxml.jackson.core.JsonParser;
20+
import com.fasterxml.jackson.databind.DeserializationContext;
21+
import com.fasterxml.jackson.databind.JsonDeserializer;
22+
import com.fasterxml.jackson.databind.JsonSerializer;
23+
import com.fasterxml.jackson.databind.SerializerProvider;
24+
import com.sun.codemodel.JClassAlreadyExistsException;
1825
import com.sun.codemodel.JDefinedClass;
1926
import com.sun.codemodel.JFieldVar;
2027
import com.sun.codemodel.JMethod;
2128
import com.sun.codemodel.JMod;
22-
import com.sun.codemodel.JType;
29+
import com.sun.codemodel.JVar;
30+
import java.io.IOException;
2331
import org.jsonschema2pojo.util.NameHelper;
2432

2533
public class GeneratorUtils {
2634

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));
35+
public static final String SERIALIZE_HELPER_NAME =
36+
"io.serverlessworkflow.serialization.SerializeHelper";
37+
public static final String DESERIALIZE_HELPER_NAME =
38+
"io.serverlessworkflow.serialization.DeserializeHelper";
39+
40+
@FunctionalInterface
41+
public interface SerializerFiller {
42+
void accept(JMethod method, JVar valueParam, JVar genParam);
43+
}
44+
45+
@FunctionalInterface
46+
public interface DeserializerFiller {
47+
void accept(JMethod method, JVar parserParam);
48+
}
49+
50+
public static JDefinedClass serializerClass(JDefinedClass relatedClass) {
51+
return createClass(relatedClass, JsonSerializer.class, "Serializer");
52+
}
53+
54+
public static JDefinedClass deserializerClass(JDefinedClass relatedClass) {
55+
return createClass(relatedClass, JsonDeserializer.class, "Deserializer");
56+
}
57+
58+
public static JMethod buildMethod(
59+
JDefinedClass definedClass, JFieldVar instanceField, NameHelper nameHelper, String name) {
3160
JMethod method =
32-
definedClass.method(JMod.PUBLIC, type, nameHelper.getGetterName(name, type, null));
61+
definedClass.method(
62+
JMod.PUBLIC,
63+
instanceField.type(),
64+
nameHelper.getGetterName(name, instanceField.type(), null));
3365
method.body()._return(instanceField);
34-
return instanceField;
66+
return method;
67+
}
68+
69+
public static void fillSerializer(
70+
JDefinedClass definedClass, JDefinedClass relatedClass, SerializerFiller filler) {
71+
JMethod method = definedClass.method(JMod.PUBLIC, void.class, "serialize");
72+
method.annotate(Override.class);
73+
method._throws(IOException.class);
74+
JVar valueParam = method.param(relatedClass, "value");
75+
JVar genParam = method.param(JsonGenerator.class, "gen");
76+
method.param(SerializerProvider.class, "serializers");
77+
filler.accept(method, valueParam, genParam);
78+
}
79+
80+
public static void fillDeserializer(
81+
JDefinedClass definedClass, JDefinedClass relatedClass, DeserializerFiller filler) {
82+
JMethod method = definedClass.method(JMod.PUBLIC, relatedClass, "deserialize");
83+
method.annotate(Override.class);
84+
method._throws(IOException.class);
85+
JVar parserParam = method.param(JsonParser.class, "parser");
86+
method.param(DeserializationContext.class, "dctx");
87+
filler.accept(method, parserParam);
88+
}
89+
90+
private static JDefinedClass createClass(
91+
JDefinedClass relatedClass, Class<?> serializerClass, String suffix) {
92+
try {
93+
JDefinedClass definedClass =
94+
relatedClass._package()._class(JMod.NONE, relatedClass.name() + suffix);
95+
definedClass._extends(definedClass.owner().ref(serializerClass).narrow(relatedClass));
96+
return definedClass;
97+
} catch (JClassAlreadyExistsException ex) {
98+
throw new IllegalArgumentException(ex);
99+
}
35100
}
36101

37102
private GeneratorUtils() {}

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

+53-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
package io.serverlessworkflow.generator;
1717

1818
import com.fasterxml.jackson.databind.JsonNode;
19+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
20+
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
21+
import com.sun.codemodel.JBlock;
22+
import com.sun.codemodel.JClass;
1923
import com.sun.codemodel.JDefinedClass;
2024
import com.sun.codemodel.JExpr;
2125
import com.sun.codemodel.JFieldVar;
@@ -58,7 +62,9 @@ private JDefinedClass addKeyValueFields(
5862
JDefinedClass jclass, JsonNode node, JsonNode parent, String nodeName, Schema schema) {
5963
NameHelper nameHelper = ruleFactory.getNameHelper();
6064
JType stringClass = jclass.owner()._ref(String.class);
61-
JFieldVar nameField = GeneratorUtils.addGetter(jclass, stringClass, nameHelper, "name");
65+
JFieldVar nameField =
66+
jclass.field(JMod.PRIVATE, stringClass, nameHelper.getPropertyName("name", null));
67+
JMethod nameMethod = GeneratorUtils.buildMethod(jclass, nameField, nameHelper, "name");
6268
JType propertyType;
6369
if (node != null && node.size() != 0) {
6470
String pathToAdditionalProperties;
@@ -83,7 +89,16 @@ private JDefinedClass addKeyValueFields(
8389
propertyType = jclass.owner().ref(Object.class);
8490
}
8591
JFieldVar valueField =
86-
GeneratorUtils.addGetter(jclass, propertyType, nameHelper, propertyType.name());
92+
jclass.field(
93+
JMod.PRIVATE, propertyType, nameHelper.getPropertyName(propertyType.name(), null));
94+
JMethod valueMethod =
95+
GeneratorUtils.buildMethod(jclass, valueField, nameHelper, propertyType.name());
96+
jclass
97+
.annotate(JsonSerialize.class)
98+
.param("using", generateSerializer(jclass, nameMethod, valueMethod));
99+
jclass
100+
.annotate(JsonDeserialize.class)
101+
.param("using", generateDeserializer(jclass, propertyType));
87102
JMethod constructor = jclass.constructor(JMod.PUBLIC);
88103
constructor
89104
.body()
@@ -92,6 +107,42 @@ private JDefinedClass addKeyValueFields(
92107
return jclass;
93108
}
94109

110+
private JDefinedClass generateDeserializer(JDefinedClass relatedClass, JType propertyType) {
111+
JDefinedClass definedClass = GeneratorUtils.deserializerClass(relatedClass);
112+
GeneratorUtils.fillDeserializer(
113+
definedClass,
114+
relatedClass,
115+
(method, parserParam) ->
116+
method
117+
.body()
118+
._return(
119+
definedClass
120+
.owner()
121+
.ref(GeneratorUtils.DESERIALIZE_HELPER_NAME)
122+
.staticInvoke("deserializeItem")
123+
.arg(parserParam)
124+
.arg(relatedClass.dotclass())
125+
.arg(((JClass) propertyType).dotclass())));
126+
return definedClass;
127+
}
128+
129+
private JDefinedClass generateSerializer(
130+
JDefinedClass relatedClass, JMethod nameMethod, JMethod valueMethod) {
131+
JDefinedClass definedClass = GeneratorUtils.serializerClass(relatedClass);
132+
GeneratorUtils.fillSerializer(
133+
definedClass,
134+
relatedClass,
135+
(method, valueParam, genParam) -> {
136+
JBlock body = method.body();
137+
body.invoke(genParam, "writeStartObject");
138+
body.invoke(genParam, "writeObjectField")
139+
.arg(valueParam.invoke(nameMethod))
140+
.arg(valueParam.invoke(valueMethod));
141+
body.invoke(genParam, "writeEndObject");
142+
});
143+
return definedClass;
144+
}
145+
95146
private boolean checkIntValue(JsonNode node, String propName, int value) {
96147
return node.has(propName) && node.get(propName).asInt() == value;
97148
}

0 commit comments

Comments
 (0)
Please sign in to comment.