Skip to content

Commit 37f7063

Browse files
committed
[Fix serverlessworkflow#490] Fixing schema generation
1 parent 33726c6 commit 37f7063

21 files changed

+621
-159
lines changed

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

+19-41
Original file line numberDiff line numberDiff line change
@@ -1325,47 +1325,25 @@ $defs:
13251325
$ref: '#/$defs/eventFilter'
13261326
required: [ all ]
13271327
- title: AnyEventConsumptionStrategy
1328-
oneOf:
1329-
- properties:
1330-
any:
1331-
type: array
1332-
title: AnyEventConsumptionStrategyConfiguration
1333-
description: A list containing any of the events to consume.
1334-
items:
1335-
$ref: '#/$defs/eventFilter'
1336-
minItems: 1
1337-
until:
1338-
oneOf:
1339-
- type: string
1340-
title: AnyEventUntilCondition
1341-
description: A runtime expression condition evaluated after consuming an event and which determines whether or not to continue listening.
1342-
- allOf:
1343-
- $ref: '#/$defs/eventConsumptionStrategy'
1344-
title: AnyEventUntilConsumed
1345-
description: The strategy that defines the event(s) to consume to stop listening.
1346-
- properties:
1347-
until: false
1348-
required: [ any ]
1349-
- properties:
1350-
any:
1351-
type: array
1352-
title: AnyEventConsumptionStrategyConfiguration
1353-
description: A list containing any of the events to consume.
1354-
items:
1355-
$ref: '#/$defs/eventFilter'
1356-
maxItems: 0
1357-
until:
1358-
oneOf:
1359-
- type: string
1360-
title: AnyEventUntilCondition
1361-
description: A runtime expression condition evaluated after consuming an event and which determines whether or not to continue listening.
1362-
- allOf:
1363-
- $ref: '#/$defs/eventConsumptionStrategy'
1364-
title: AnyEventUntilConsumed
1365-
description: The strategy that defines the event(s) to consume to stop listening.
1366-
- properties:
1367-
until: false
1368-
required: [ any, until ]
1328+
properties:
1329+
any:
1330+
type: array
1331+
title: AnyEventConsumptionStrategyConfiguration
1332+
description: A list containing any of the events to consume.
1333+
items:
1334+
$ref: '#/$defs/eventFilter'
1335+
until:
1336+
oneOf:
1337+
- type: string
1338+
title: AnyEventUntilCondition
1339+
description: A runtime expression condition evaluated after consuming an event and which determines whether or not to continue listening.
1340+
- allOf:
1341+
- $ref: '#/$defs/eventConsumptionStrategy'
1342+
description: The strategy that defines the event(s) to consume to stop listening.
1343+
- properties:
1344+
until: false
1345+
title: AnyEventUntilConsumed
1346+
required: [ any ]
13691347
- title: OneEventConsumptionStrategy
13701348
properties:
13711349
one:

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

+36-2
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class AllAnyOneOfSchemaRule extends SchemaRule {
6060
}
6161

6262
private static final String REF = "$ref";
63+
private static final String TITLE = "title";
6364
private static final String PATTERN = "pattern";
6465

6566
private enum Format {
@@ -154,6 +155,16 @@ public JType apply(
154155
&& allOfTypes.isEmpty()
155156
&& refType.isPresent()) {
156157
javaType = refType.get();
158+
} else if (!schemaNode.has("properties")
159+
&& oneOfTypes.isEmpty()
160+
&& allOfTypes.size() == 1
161+
&& refType.isEmpty()) {
162+
javaType = allOfTypes.get(0).getType();
163+
} else if (!schemaNode.has("properties")
164+
&& oneOfTypes.size() == 1
165+
&& allOfTypes.isEmpty()
166+
&& refType.isEmpty()) {
167+
javaType = oneOfTypes.get(0).getType();
157168
} else {
158169
JPackage container = generatableType.getPackage();
159170
javaType = ruleFactory.getTypeRule().apply(nodeName, schemaNode, parent, container, schema);
@@ -469,6 +480,9 @@ private void unionType(
469480
Collection<JTypeWrapper> types) {
470481
if (schemaNode.has(prefix)) {
471482
ArrayNode array = (ArrayNode) schemaNode.get(prefix);
483+
if (schemaNode.has(TITLE)) {
484+
nodeName = schemaNode.get(TITLE).asText();
485+
}
472486
int i = 0;
473487
for (JsonNode oneOf : array) {
474488
if (!ignoreNode(oneOf)) {
@@ -491,6 +505,23 @@ private void unionType(
491505
}
492506

493507
private static boolean ignoreNode(JsonNode node) {
508+
return allRequired(node) || allRemoveProperties(node);
509+
}
510+
511+
private static boolean allRemoveProperties(JsonNode node) {
512+
if (node.size() == 1 && node.has("properties")) {
513+
JsonNode propsNode = node.get("properties");
514+
for (JsonNode propNode : propsNode) {
515+
if (!propNode.isBoolean() || propNode.asBoolean()) {
516+
return false;
517+
}
518+
}
519+
return true;
520+
}
521+
return false;
522+
}
523+
524+
private static boolean allRequired(JsonNode node) {
494525
return node.size() == 1 && node.has("required");
495526
}
496527

@@ -514,7 +545,7 @@ private Optional<JType> refType(
514545
schema.isGenerated()
515546
? schema.getJavaType()
516547
: apply(
517-
nameFromRef(ref, nodeName),
548+
nameFromRef(ref, nodeName, schemaNode),
518549
schema.getContent(),
519550
parent,
520551
generatableType,
@@ -556,7 +587,10 @@ private String pattern(JsonNode node) {
556587
return format != null ? format.pattern() : getFromNode(node, PATTERN);
557588
}
558589

559-
private String nameFromRef(String ref, String nodeName) {
590+
private String nameFromRef(String ref, String nodeName, JsonNode schemaNode) {
591+
if (schemaNode.has(TITLE)) {
592+
return schemaNode.get(TITLE).asText();
593+
}
560594
if ("#".equals(ref)) {
561595
return nodeName;
562596
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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.fasterxml.jackson.databind.JsonNode;
19+
import com.sun.codemodel.JClassAlreadyExistsException;
20+
import com.sun.codemodel.JDefinedClass;
21+
import com.sun.codemodel.JPackage;
22+
import org.jsonschema2pojo.GenerationConfig;
23+
import org.jsonschema2pojo.util.NameHelper;
24+
25+
public class RefNameHelper extends NameHelper {
26+
27+
public RefNameHelper(GenerationConfig generationConfig) {
28+
super(generationConfig);
29+
}
30+
31+
@Override
32+
public String getUniqueClassName(String nodeName, JsonNode node, JPackage _package) {
33+
String className = getClassName(nodeName, node, _package);
34+
try {
35+
JDefinedClass _class = _package._class(className);
36+
_package.remove(_class);
37+
return className;
38+
} catch (JClassAlreadyExistsException ex) {
39+
return super.getUniqueClassName(nodeName, null, _package);
40+
}
41+
}
42+
}

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

+20
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,25 @@
1818
import com.sun.codemodel.JClassContainer;
1919
import com.sun.codemodel.JDefinedClass;
2020
import com.sun.codemodel.JType;
21+
import org.jsonschema2pojo.GenerationConfig;
2122
import org.jsonschema2pojo.rules.Rule;
2223
import org.jsonschema2pojo.rules.RuleFactory;
24+
import org.jsonschema2pojo.util.NameHelper;
2325

2426
public class UnreferencedFactory extends RuleFactory {
27+
28+
private NameHelper refNameHelper;
29+
30+
public UnreferencedFactory() {
31+
this.refNameHelper = new RefNameHelper(getGenerationConfig());
32+
}
33+
34+
@Override
35+
public void setGenerationConfig(final GenerationConfig generationConfig) {
36+
super.setGenerationConfig(generationConfig);
37+
this.refNameHelper = new RefNameHelper(generationConfig);
38+
}
39+
2540
@Override
2641
public Rule<JClassContainer, JType> getSchemaRule() {
2742
return new AllAnyOneOfSchemaRule(this);
@@ -36,4 +51,9 @@ public Rule<JClassContainer, JType> getTypeRule() {
3651
public Rule<JDefinedClass, JDefinedClass> getAdditionalPropertiesRule() {
3752
return new UnevaluatedPropertiesRule(this);
3853
}
54+
55+
@Override
56+
public NameHelper getNameHelper() {
57+
return refNameHelper;
58+
}
3959
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package io.serverlessworkflow.impl;
2+
3+
import java.util.function.BiFunction;
4+
5+
public interface ExpressionHolder<T> extends BiFunction<WorkflowContext, TaskContext, T> {}

impl/core/src/main/java/io/serverlessworkflow/impl/LongFilter.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,5 @@
1515
*/
1616
package io.serverlessworkflow.impl;
1717

18-
import java.util.function.BiFunction;
19-
2018
@FunctionalInterface
21-
public interface LongFilter extends BiFunction<WorkflowContext, TaskContext, Long> {}
19+
public interface LongFilter extends ExpressionHolder<Long> {}

impl/core/src/main/java/io/serverlessworkflow/impl/StringFilter.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,5 @@
1515
*/
1616
package io.serverlessworkflow.impl;
1717

18-
import java.util.function.BiFunction;
19-
2018
@FunctionalInterface
21-
public interface StringFilter extends BiFunction<WorkflowContext, TaskContext, String> {}
19+
public interface StringFilter extends ExpressionHolder<String> {}

impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowApplication.java

+5-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import com.github.f4b6a3.ulid.UlidCreator;
1919
import io.serverlessworkflow.api.types.Document;
2020
import io.serverlessworkflow.api.types.Workflow;
21+
import io.serverlessworkflow.impl.events.DefaultEventConsumer;
22+
import io.serverlessworkflow.impl.events.EventConsumer;
2123
import io.serverlessworkflow.impl.executors.DefaultTaskExecutorFactory;
2224
import io.serverlessworkflow.impl.executors.TaskExecutorFactory;
2325
import io.serverlessworkflow.impl.expressions.ExpressionFactory;
@@ -47,7 +49,7 @@ public class WorkflowApplication implements AutoCloseable {
4749
private final WorkflowPositionFactory positionFactory;
4850
private final ExecutorServiceFactory executorFactory;
4951
private final RuntimeDescriptorFactory runtimeDescriptorFactory;
50-
private final EventConsumer<?> eventConsumer;
52+
private final EventConsumer<?, ?> eventConsumer;
5153

5254
private ExecutorService executorService;
5355

@@ -102,7 +104,7 @@ public static class Builder {
102104
private WorkflowPositionFactory positionFactory = () -> new QueueWorkflowPosition();
103105
private WorkflowIdFactory idFactory = () -> UlidCreator.getMonotonicUlid().toString();
104106
private ExecutorServiceFactory executorFactory = () -> Executors.newCachedThreadPool();
105-
private EventConsumer<?> eventConsumer = DefaultEventConsumer.get();
107+
private EventConsumer<?, ?> eventConsumer = DefaultEventConsumer.get();
106108
private RuntimeDescriptorFactory descriptorFactory =
107109
() -> new RuntimeDescriptor("reference impl", "1.0.0_alpha", Collections.emptyMap());
108110

@@ -156,7 +158,7 @@ public Builder withDescriptorFactory(RuntimeDescriptorFactory factory) {
156158
return this;
157159
}
158160

159-
public Builder withEventConsumer(EventConsumer<?> eventConsumer) {
161+
public Builder withEventConsumer(EventConsumer<?, ?> eventConsumer) {
160162
this.eventConsumer = eventConsumer;
161163
return this;
162164
}

impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowUtils.java

+28-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import io.serverlessworkflow.api.types.SchemaExternal;
2525
import io.serverlessworkflow.api.types.SchemaInline;
2626
import io.serverlessworkflow.api.types.SchemaUnion;
27+
import io.serverlessworkflow.api.types.UriTemplate;
2728
import io.serverlessworkflow.impl.expressions.Expression;
2829
import io.serverlessworkflow.impl.expressions.ExpressionFactory;
2930
import io.serverlessworkflow.impl.expressions.ExpressionUtils;
@@ -35,8 +36,10 @@
3536
import java.io.IOException;
3637
import java.io.InputStream;
3738
import java.io.UncheckedIOException;
39+
import java.net.URI;
3840
import java.util.Map;
3941
import java.util.Optional;
42+
import java.util.function.Function;
4043

4144
public class WorkflowUtils {
4245

@@ -81,6 +84,25 @@ public static Optional<WorkflowFilter> buildWorkflowFilter(
8184
: Optional.empty();
8285
}
8386

87+
public static <T> ExpressionHolder<T> buildExpressionHolder(
88+
ExpressionFactory exprFactory,
89+
String expression,
90+
T literal,
91+
Function<JsonNode, T> converter) {
92+
return expression != null
93+
? buildExpressionHolder(buildWorkflowFilter(exprFactory, expression), converter)
94+
: buildExpressionHolder(literal);
95+
}
96+
97+
private static <T> ExpressionHolder<T> buildExpressionHolder(
98+
WorkflowFilter filter, Function<JsonNode, T> converter) {
99+
return (w, t) -> converter.apply(filter.apply(w, t, t.input()));
100+
}
101+
102+
private static <T> ExpressionHolder<T> buildExpressionHolder(T literal) {
103+
return (w, t) -> literal;
104+
}
105+
84106
public static Optional<WorkflowFilter> buildWorkflowFilter(
85107
ExpressionFactory exprFactory, ExportAs as) {
86108
return as != null
@@ -109,7 +131,7 @@ private static StringFilter toString(String literal) {
109131
return (w, t) -> literal;
110132
}
111133

112-
private static WorkflowFilter buildWorkflowFilter(
134+
public static WorkflowFilter buildWorkflowFilter(
113135
ExpressionFactory exprFactory, String str, Object object) {
114136
if (str != null) {
115137
return buildWorkflowFilter(exprFactory, str);
@@ -148,4 +170,9 @@ public static WorkflowFilter buildWorkflowFilter(ExpressionFactory exprFactory,
148170
public static Optional<WorkflowFilter> optionalFilter(ExpressionFactory exprFactory, String str) {
149171
return str != null ? Optional.of(buildWorkflowFilter(exprFactory, str)) : Optional.empty();
150172
}
173+
174+
public static String toString(UriTemplate template) {
175+
URI uri = template.getLiteralUri();
176+
return uri != null ? uri.toString() : template.getLiteralUriTemplate();
177+
}
151178
}

0 commit comments

Comments
 (0)