Skip to content

Commit da43998

Browse files
authored
Merge pull request #95 from ZenWave360/feature/v2.3.0
Feature/v2.3.0
2 parents 464e05f + 57e6254 commit da43998

File tree

50 files changed

+805
-179
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+805
-179
lines changed

jbang-catalog.json

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,23 @@
3131
]
3232
},
3333
"snapshots": {
34-
"script-ref": "io.zenwave360.sdk:zenwave-sdk-cli:2.3.0-SNAPSHOT",
34+
"script-ref": "io.zenwave360.sdk:zenwave-sdk-cli:2.4.0-SNAPSHOT",
3535
"dependencies": [
3636
"org.slf4j:slf4j-simple:1.7.36",
37-
"io.zenwave360.sdk.plugins:asyncapi-spring-cloud-streams3:2.3.0-SNAPSHOT",
38-
"io.zenwave360.sdk.plugins:asyncapi-jsonschema2pojo:2.3.0-SNAPSHOT",
39-
"io.zenwave360.sdk.plugins:avro-schema-compiler:2.3.0-SNAPSHOT",
37+
"io.zenwave360.sdk.plugins:asyncapi-spring-cloud-streams3:2.4.0-SNAPSHOT",
38+
"io.zenwave360.sdk.plugins:asyncapi-jsonschema2pojo:2.4.0-SNAPSHOT",
39+
"io.zenwave360.sdk.plugins:avro-schema-compiler:2.4.0-SNAPSHOT",
4040
"org.apache.avro:avro-compiler:1.12.0",
41-
"io.zenwave360.sdk.plugins:asyncapi-generator:2.3.0-SNAPSHOT",
42-
"io.zenwave360.sdk.plugins:openapi-spring-webtestclient:2.3.0-SNAPSHOT",
43-
"io.zenwave360.sdk.plugins:openapi-karate:2.3.0-SNAPSHOT",
44-
"io.zenwave360.sdk.plugins:backend-application-default:2.3.0-SNAPSHOT",
45-
"io.zenwave360.sdk.plugins.customizations:kotlin-backend-application:2.3.0-SNAPSHOT",
46-
"io.zenwave360.sdk.plugins:zdl-to-openapi:2.3.0-SNAPSHOT",
47-
"io.zenwave360.sdk.plugins:zdl-to-asyncapi:2.3.0-SNAPSHOT",
48-
"io.zenwave360.sdk.plugins:jdl-to-asyncapi:2.3.0-SNAPSHOT",
49-
"io.zenwave360.sdk.plugins:zdl-to-markdown:2.3.0-SNAPSHOT",
50-
"io.zenwave360.sdk.plugins:openapi-controllers:2.3.0-SNAPSHOT"
41+
"io.zenwave360.sdk.plugins:asyncapi-generator:2.4.0-SNAPSHOT",
42+
"io.zenwave360.sdk.plugins:openapi-spring-webtestclient:2.4.0-SNAPSHOT",
43+
"io.zenwave360.sdk.plugins:openapi-karate:2.4.0-SNAPSHOT",
44+
"io.zenwave360.sdk.plugins:backend-application-default:2.4.0-SNAPSHOT",
45+
"io.zenwave360.sdk.plugins.customizations:kotlin-backend-application:2.4.0-SNAPSHOT",
46+
"io.zenwave360.sdk.plugins:zdl-to-openapi:2.4.0-SNAPSHOT",
47+
"io.zenwave360.sdk.plugins:zdl-to-asyncapi:2.4.0-SNAPSHOT",
48+
"io.zenwave360.sdk.plugins:jdl-to-asyncapi:2.4.0-SNAPSHOT",
49+
"io.zenwave360.sdk.plugins:zdl-to-markdown:2.4.0-SNAPSHOT",
50+
"io.zenwave360.sdk.plugins:openapi-controllers:2.4.0-SNAPSHOT"
5151
],
5252
"repositories": [
5353
"mavencentral",

plugins/asyncapi-jsonschema2pojo/src/main/java/io/zenwave360/sdk/plugins/AsyncApiJsonSchema2PojoGenerator.java

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,17 @@
1414
import java.util.regex.Matcher;
1515
import java.util.regex.Pattern;
1616

17+
import com.fasterxml.jackson.annotation.JsonInclude;
1718
import io.zenwave360.sdk.utils.AsyncAPIUtils;
19+
import io.zenwave360.sdk.utils.Maps;
1820
import io.zenwave360.sdk.zdl.GeneratedProjectFiles;
1921
import org.apache.commons.lang3.ObjectUtils;
20-
import org.apache.commons.lang3.RegExUtils;
21-
import org.apache.commons.lang3.StringUtils;
2222
import org.jsonschema2pojo.*;
2323
import org.jsonschema2pojo.exception.ClassAlreadyExistsException;
2424
import org.jsonschema2pojo.rules.RuleFactory;
2525
import org.slf4j.Logger;
2626
import org.slf4j.LoggerFactory;
2727

28-
import com.fasterxml.jackson.annotation.JsonInclude;
2928
import com.fasterxml.jackson.core.JsonProcessingException;
3029
import com.fasterxml.jackson.databind.ObjectMapper;
3130
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
@@ -151,33 +150,42 @@ public void generateFromNativeFormat(JsonSchema2PojoConfiguration config, Map<St
151150
codeModel.build(sourcesWriter, resourcesWriter);
152151
}
153152

154-
private final ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory());
155153
private final ObjectMapper jsonMapper = new ObjectMapper();
156154

157155
protected String convertToJson(final Map<String, Object> payload, final String packageName) throws JsonProcessingException {
158-
this.yamlMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
159-
String yml = this.yamlMapper.writerWithDefaultPrettyPrinter().writeValueAsString(payload);
160-
161-
List<String> regexPatterns = List.of(
162-
originalRefProperty + ": \".*#/components/schemas/([^\"]+)\"",
163-
"ref: \".*#/components/schemas/([^\"]+)\""
164-
);
165-
166-
for (String regex : regexPatterns) {
167-
Pattern pattern = Pattern.compile(regex);
168-
Matcher matcher = pattern.matcher(yml);
169-
StringBuilder result = new StringBuilder();
170-
171-
while (matcher.find()) {
172-
String matchedGroup = matcher.group(1);
173-
String className = NamingUtils.asJavaTypeName(matchedGroup);
174-
matcher.appendReplacement(result, "javaType: \"" + packageName + "." + className + "\"");
156+
populateJavaTypeFromRefsRecursively(payload, packageName);
157+
return this.jsonMapper.writeValueAsString(payload);
158+
}
159+
160+
private void populateJavaTypeFromRefsRecursively(Object obj, String packageName) {
161+
if (obj instanceof Map) {
162+
Map<String, Object> map = (Map<String, Object>) obj;
163+
164+
// Replace $ref and original ref with javaType (if not already present)
165+
if (!map.containsKey("javaType")) {
166+
String refValue = JSONPath.getFirst(map, "$['" + originalRefProperty + "']", "$['$ref']");
167+
168+
if (refValue != null && refValue.contains("#/components/schemas/")) {
169+
String schemaName = refValue.substring(refValue.lastIndexOf("/") + 1);
170+
String className = NamingUtils.asJavaTypeName(schemaName);
171+
map.put("javaType", packageName + "." + className);
172+
}
173+
}
174+
map.remove("x--original-$ref");
175+
map.remove("$ref");
176+
177+
178+
// Recursively process all values in the map
179+
for (Object value : map.values()) {
180+
populateJavaTypeFromRefsRecursively(value, packageName);
175181
}
176-
yml = matcher.appendTail(result).toString();
177-
}
178182

179-
Object jsonObject = this.yamlMapper.readTree(yml);
180-
return this.jsonMapper.writeValueAsString(jsonObject);
183+
} else if (obj instanceof List) {
184+
List<Object> list = (List<Object>) obj;
185+
for (Object item : list) {
186+
populateJavaTypeFromRefsRecursively(item, packageName);
187+
}
188+
}
181189
}
182190

183191
private Annotator instantiate(Class<? extends Annotator> annotatorClass, GenerationConfig config) {

plugins/asyncapi-jsonschema2pojo/src/test/java/io/zenwave360/sdk/plugins/AsyncApiJsonSchema2PojoGeneratorTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public void test_generator_for_asyncapi_v3() throws Exception {
3030
new MainGenerator().generate(plugin);
3131

3232
Assertions.assertTrue(new File("target/zenwave630/src/main/java/io/example/v3/domain/events/CustomerInput.java").exists());
33+
Assertions.assertTrue(new File("target/zenwave630/src/main/java/mypackage/CustomerCreated.java").exists());
34+
Assertions.assertFalse(new File("target/zenwave630/src/main/java/io/example/v3/domain/events/CustomerCreated.java").exists());
3335
}
3436

3537
@Test

plugins/asyncapi-jsonschema2pojo/src/test/resources/asyncapi-v3.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ components:
137137
CustomerCreated:
138138
type: "object"
139139
x-business-entity: "CustomerCreated"
140+
javaType: "mypackage.CustomerCreated"
140141
properties:
141142
id:
142143
type: "string"

plugins/asyncapi-spring-cloud-streams3/src/test/resources/scs3-pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<spring-cloud.version>2021.0.3</spring-cloud.version>
2323
<avro.version>1.11.1</avro.version>
2424
<testcontainers.version>1.17.2</testcontainers.version>
25-
<commons-lang3.version>3.12.0</commons-lang3.version>
25+
<commons-lang3.version>3.20.0</commons-lang3.version>
2626

2727
<!-- Plugin versions -->
2828
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>

plugins/backend-application-default/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Visit https://www.zenwave360.io/docs/zenwave-sdk/backend-application for complet
4141
| `style` | Programming Style | ProgrammingStyle | imperative | imperative, reactive |
4242
| `useLombok` | Use @Getter and @Setter annotations from Lombok | boolean | false | |
4343
| `useSpringModulith` | Whether to use Spring Modulith annotations and features | boolean | false | |
44+
| `useJSpecify` | Whether to use JSpecify for nullability annotations | boolean | false | |
4445
| `addRelationshipsById` | Controls whether to add a read/write relationship by id when mapping relationships between aggregate (not recommended) keeping the relationship by object readonly. | boolean | false | |
4546
| `idJavaType` | Specifies the Java data type for the ID fields of entities. Defaults to Long for JPA and String for MongoDB if not explicitly set. | String | | |
4647
| `includeEmitEventsImplementation` | Whether to add AsyncAPI/ApplicationEventPublisher as service dependencies. Depends on the naming convention of zenwave-asyncapi plugin to work. | boolean | true | |

plugins/backend-application-default/src/main/java/io/zenwave360/sdk/plugins/BackendApplicationDefaultHelpers.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,6 @@ public Map findAggregateCommandsForMethod(Map method, Options options) {
6666
}
6767
return Map.of("templateFile", "aggregates-commands-methodBody", "aggregatesCommandsForMethod", aggregatesCommandsForMethod);
6868
}
69-
public boolean isWriteMethod(Map method, Options options) {
70-
var methodName = (String) method.get("name");
71-
var hasId = method.get("paramId") != null;
72-
return hasId || methodName.startsWith("create") || methodName.startsWith("update") || methodName.startsWith("delete");
73-
}
7469

7570
@Deprecated
7671
public boolean isCrudMethod(String crudMethodPrefix, Options options) {

plugins/backend-application-default/src/main/java/io/zenwave360/sdk/plugins/BackendApplicationProjectTemplates.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
import io.zenwave360.sdk.doc.DocumentedOption;
44
import io.zenwave360.sdk.generators.Generator;
55
import io.zenwave360.sdk.options.PersistenceType;
6+
import io.zenwave360.sdk.plugins.annotators.AnnotationHelper;
7+
import io.zenwave360.sdk.plugins.annotators.JSpecifyAnnotator;
68
import io.zenwave360.sdk.utils.JSONPath;
79
import io.zenwave360.sdk.zdl.ProjectTemplates;
810
import io.zenwave360.sdk.zdl.layouts.CleanArchitectureProjectLayout;
911
import io.zenwave360.sdk.zdl.layouts.CleanHexagonalProjectLayout;
1012
import io.zenwave360.sdk.zdl.layouts.ProjectLayout;
13+
import io.zenwave360.sdk.zdl.utils.ZDLAnnotator;
1114
import io.zenwave360.sdk.zdl.utils.ZDLFindUtils;
1215

1316
import java.util.ArrayList;
@@ -24,6 +27,9 @@ public class BackendApplicationProjectTemplates extends ProjectTemplates {
2427
@DocumentedOption(description = "Whether to use Spring Modulith annotations and features")
2528
public boolean useSpringModulith = false;
2629

30+
@DocumentedOption(description = "Whether to use JSpecify for nullability annotations")
31+
public boolean useJSpecify = false;
32+
2733
public PersistenceType persistence = PersistenceType.mongodb;
2834

2935
public boolean includeEmitEventsImplementation = true;
@@ -54,9 +60,19 @@ public List<Object> getTemplateHelpers(Generator generator) {
5460
var helpers = new ArrayList<>(super.getTemplateHelpers(generator));
5561
helpers.add(new BackendApplicationDefaultHelpers((BackendApplicationDefaultGenerator) generator));
5662
helpers.add(new BackendApplicationDefaultJpaHelpers((BackendApplicationDefaultGenerator) generator));
63+
helpers.add(AnnotationHelper.class);
5764
return helpers;
5865
}
5966

67+
@Override
68+
public List<ZDLAnnotator> getZDLAnnotators() {
69+
var annotators = new ArrayList<>(super.getZDLAnnotators());
70+
if(useJSpecify) {
71+
annotators.add(new JSpecifyAnnotator());
72+
}
73+
return annotators;
74+
}
75+
6076
public BackendApplicationProjectTemplates() {
6177
setTemplatesFolder("io/zenwave360/sdk/plugins/BackendApplicationDefaultGenerator");
6278

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package io.zenwave360.sdk.plugins.annotators;
2+
3+
import com.github.jknack.handlebars.Options;
4+
import io.zenwave360.sdk.zdl.model.JavaZdlModel;
5+
6+
import java.util.Map;
7+
import java.util.stream.Collectors;
8+
9+
public class AnnotationHelper {
10+
public static String annotate(Object javaModel, Options options) {
11+
var zdl = (Map) options.get("zdl");
12+
var model = options.param(0);
13+
if(javaModel instanceof JavaZdlModel.Service) {
14+
return annotate((JavaZdlModel.Service) javaModel, (Map) model, zdl);
15+
}
16+
if(javaModel instanceof JavaZdlModel.ServiceMethod) {
17+
return annotate((JavaZdlModel.ServiceMethod) javaModel, (Map) model, zdl);
18+
}
19+
return "";
20+
}
21+
22+
public static String addImports(Object javaModel, Options options) {
23+
var zdl = (Map) options.get("zdl");
24+
var model = options.param(0);
25+
if(javaModel instanceof JavaZdlModel.Service) {
26+
return addImports((JavaZdlModel.Service) javaModel, (Map) model, zdl);
27+
}
28+
return "";
29+
}
30+
31+
private static String addImports(JavaZdlModel.Service service, Map<String, Object> zdlService, Map<String, Object> zdl) {
32+
return service.annotations().stream().map(a -> "import " + a.name()).collect(Collectors.joining(";\n"));
33+
}
34+
35+
36+
private static String annotate(JavaZdlModel.Service service, Map<String, Object> zdlService, Map<String, Object> zdl) {
37+
return service.annotations().stream().map(a -> "@" + a.name()).collect(Collectors.joining("\n"));
38+
}
39+
40+
private static String annotate(JavaZdlModel.ServiceMethod serviceMethod, Map<String, Object> zdlMethod, Map<String, Object> zdl) {
41+
return "// todo";
42+
}
43+
44+
private static String annotate(JavaZdlModel.MethodParameter methodParameter, Map<String, Object> zdlService, Map<String, Object> zdl) {
45+
return methodParameter.annotations().stream().map(a -> "@" + a.name()).collect(Collectors.joining("\n"));
46+
}
47+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package io.zenwave360.sdk.plugins.annotators;
2+
3+
import io.zenwave360.sdk.zdl.model.JavaZdlModel;
4+
import io.zenwave360.sdk.zdl.utils.ZDLAnnotator;
5+
6+
import java.util.Map;
7+
8+
public class JSpecifyAnnotator implements ZDLAnnotator {
9+
10+
@Override
11+
public void annotate(JavaZdlModel.Service service, Map<String, Object> zdlService, Map<String, Object> zdl) {
12+
service.annotations().add(new JavaZdlModel.Annotation("org.jspecify.annotations.NullMarked", null, null));
13+
}
14+
15+
@Override
16+
public void annotate(JavaZdlModel.MethodParameter methodParameter, Map<String, Object> method, Map<String, Object> zdl) {
17+
if(methodParameter.isOptional()) {
18+
methodParameter.annotations().add(new JavaZdlModel.Annotation("org.jspecify.annotations.Nullable", null, null));
19+
}
20+
}
21+
}

0 commit comments

Comments
 (0)