Skip to content

Commit 739fb09

Browse files
rjalanderlapentad
andauthored
Generate events using jsonschema2pojo and mustache template (#58)
Initial changes to generate events using jsonschema2pojo and mustache template, /src/main/resources/template/event-template.mustache pom.xml has the plugin to generate jsonschema2pojo and plugin to run the main class from CDEventsGenerator to create events using mustache template. Running ./mvnw verify Generates models using jsonschema2pojo for each event under - dev.cdevents.models.generated.subject.predicate Generates events from mustache template and placed under - dev.cdevents.events.generated Note: Generating only 3 events for an initial review and schema files for the same are placed under - /src/main/resources/schema (This will essentially point to spec repo to generate all the events once reviewed) Removed current Events(dev.cdevents.events) and Models(dev.cdevents.models) that are manually created earlier. --------- Signed-off-by: Jalander Ramagiri <jalander.ramagiri@est.tech> Co-authored-by: Lapenta Francesco Davide <37077655+lapentad@users.noreply.github.com>
1 parent d6e4167 commit 739fb09

File tree

109 files changed

+3492
-10066
lines changed

Some content is hidden

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

109 files changed

+3492
-10066
lines changed

.github/linters/sun_checks.xml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,9 @@
114114

115115
<!-- Checks for imports -->
116116
<!-- See https://checkstyle.org/config_imports.html -->
117-
<module name="AvoidStarImport"/>
117+
<module name="AvoidStarImport">
118+
<property name="allowClassImports" value="true"/>
119+
</module>
118120
<module name="IllegalImport"/>
119121
<!-- defaults to sun.* packages -->
120122
<module name="RedundantImport"/>
@@ -171,7 +173,9 @@
171173
</module>
172174
<module name="IllegalInstantiation"/>
173175
<module name="InnerAssignment"/>
174-
<module name="MagicNumber"/>
176+
<module name="MagicNumber">
177+
<property name="ignoreFieldDeclaration" value="true"/>
178+
</module>
175179
<module name="MissingSwitchDefault"/>
176180
<module name="MultipleVariableDeclarations"/>
177181
<module name="SimplifyBooleanExpression"/>

.github/workflows/linter.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ jobs:
1515
- name: Lint Code Base
1616
uses: github/super-linter/slim@v4
1717
env:
18-
FILTER_REGEX_INCLUDE: .*src/main/.*
18+
FILTER_REGEX_INCLUDE: .*sdk/src/main/.*|.*generator/src/main/.*
1919
VALIDATE_ALL_CODEBASE: false
2020
DEFAULT_BRANCH: main
2121
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2222
# mvnw is provided as is from the Maven Wrapper project. Can't change it
23-
FILTER_REGEX_EXCLUDE: .*mvnw
23+
FILTER_REGEX_EXCLUDE: .*mvnw|.*sdk/src/main/java/dev/cdevents/models/.*

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050
5151
- name: Release
5252
run: |
53-
./mvnw -ntp -B --file pom.xml -Prelease
53+
./mvnw -ntp -B --file pom.xml -Prelease -pl :cdevents-sdk-java-parent
5454
env:
5555
JRELEASER_GITHUB_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
5656
JRELEASER_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}

generator/pom.xml

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<parent>
8+
<groupId>dev.cdevents</groupId>
9+
<artifactId>cdevents-sdk-java-parent</artifactId>
10+
<version>0.1.3-SNAPSHOT</version>
11+
</parent>
12+
13+
<artifactId>cdevents-sdk-java-generator</artifactId>
14+
15+
<name>cdevents-sdk-java-generator</name>
16+
<description>Source code generator for CDEvents Java SDK</description>
17+
<url>https://github.com/cdevents</url>
18+
19+
<properties>
20+
<maven.javadoc.skip>true</maven.javadoc.skip>
21+
<maven.source.skip>true</maven.source.skip>
22+
<maven.deploy.skip>true</maven.deploy.skip>
23+
<maven.compiler.source>11</maven.compiler.source>
24+
<maven.compiler.target>11</maven.compiler.target>
25+
<sdk.project.dir>${project.basedir}/../sdk</sdk.project.dir>
26+
</properties>
27+
28+
<dependencies>
29+
<dependency>
30+
<groupId>com.fasterxml.jackson.core</groupId>
31+
<artifactId>jackson-databind</artifactId>
32+
</dependency>
33+
34+
<dependency>
35+
<groupId>com.fasterxml.jackson.datatype</groupId>
36+
<artifactId>jackson-datatype-jsr310</artifactId>
37+
</dependency>
38+
39+
<dependency>
40+
<groupId>org.slf4j</groupId>
41+
<artifactId>slf4j-api</artifactId>
42+
<version>${slf4j.version}</version>
43+
</dependency>
44+
45+
<dependency>
46+
<groupId>org.apache.commons</groupId>
47+
<artifactId>commons-lang3</artifactId>
48+
<version>3.12.0</version>
49+
</dependency>
50+
51+
<dependency>
52+
<groupId>com.github.spullara.mustache.java</groupId>
53+
<artifactId>compiler</artifactId>
54+
<version>0.9.6</version>
55+
</dependency>
56+
57+
<dependency>
58+
<groupId>org.slf4j</groupId>
59+
<artifactId>slf4j-simple</artifactId>
60+
<version>${slf4j.version}</version>
61+
<scope>runtime</scope>
62+
</dependency>
63+
64+
</dependencies>
65+
66+
<build>
67+
<plugins>
68+
<plugin>
69+
<groupId>org.jsonschema2pojo</groupId>
70+
<artifactId>jsonschema2pojo-maven-plugin</artifactId>
71+
<version>1.2.1</version>
72+
<configuration>
73+
<outputDirectory>${sdk.project.dir}/src/main/java</outputDirectory>
74+
<includeHashcodeAndEquals>false</includeHashcodeAndEquals>
75+
<includeToString>false</includeToString>
76+
<addCompileSourceRoot>false</addCompileSourceRoot>
77+
</configuration>
78+
<executions>
79+
<execution>
80+
<id>generate-artifact-packaged-from-schema</id>
81+
<phase>generate-sources</phase>
82+
<goals>
83+
<goal>generate</goal>
84+
</goals>
85+
<configuration>
86+
<sourcePaths>
87+
<sourcePath>${sdk.project.dir}/src/main/resources/schema/artifact-packaged-event.json
88+
</sourcePath>
89+
</sourcePaths>
90+
<targetPackage>dev.cdevents.models.artifact.packaged</targetPackage>
91+
</configuration>
92+
</execution>
93+
<execution>
94+
<id>generate-artifact-published-from-schema</id>
95+
<phase>generate-sources</phase>
96+
<goals>
97+
<goal>generate</goal>
98+
</goals>
99+
<configuration>
100+
<sourcePaths>
101+
<sourcePath>${sdk.project.dir}/src/main/resources/schema/artifact-published-event.json
102+
</sourcePath>
103+
</sourcePaths>
104+
<targetPackage>dev.cdevents.models.artifact.published</targetPackage>
105+
</configuration>
106+
</execution>
107+
<execution>
108+
<id>generate-pipeline-run-finished-from-schema</id>
109+
<phase>generate-sources</phase>
110+
<goals>
111+
<goal>generate</goal>
112+
</goals>
113+
<configuration>
114+
<sourcePaths>
115+
<sourcePath>
116+
${sdk.project.dir}/src/main/resources/schema/pipeline-run-finished-event.json
117+
</sourcePath>
118+
</sourcePaths>
119+
<targetPackage>dev.cdevents.models.pipelinerun.finished</targetPackage>
120+
</configuration>
121+
</execution>
122+
</executions>
123+
</plugin>
124+
<plugin>
125+
<groupId>org.codehaus.mojo</groupId>
126+
<artifactId>exec-maven-plugin</artifactId>
127+
<version>3.1.0</version>
128+
<executions>
129+
<execution>
130+
<id>run-CDEventsGenerator-main-class</id>
131+
<phase>process-classes</phase>
132+
<goals>
133+
<goal>java</goal>
134+
</goals>
135+
<configuration>
136+
<mainClass>dev.cdevents.generator.CDEventsGenerator</mainClass>
137+
<arguments>
138+
<argument>${project.basedir}</argument>
139+
<argument>${sdk.project.dir}</argument>
140+
</arguments>
141+
</configuration>
142+
</execution>
143+
</executions>
144+
</plugin>
145+
</plugins>
146+
</build>
147+
</project>
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
package dev.cdevents.generator;
2+
3+
import com.fasterxml.jackson.databind.JsonNode;
4+
import com.fasterxml.jackson.databind.ObjectMapper;
5+
import com.github.mustachejava.DefaultMustacheFactory;
6+
import com.github.mustachejava.Mustache;
7+
import com.github.mustachejava.MustacheFactory;
8+
import org.apache.commons.lang3.StringUtils;
9+
import org.slf4j.Logger;
10+
import org.slf4j.LoggerFactory;
11+
import java.io.BufferedWriter;
12+
import java.io.File;
13+
import java.io.FileWriter;
14+
import java.io.IOException;
15+
import java.util.ArrayList;
16+
import java.util.Iterator;
17+
import java.util.List;
18+
import java.util.Map;
19+
20+
public final class CDEventsGenerator {
21+
22+
private CDEventsGenerator() {
23+
}
24+
25+
private static ObjectMapper objectMapper = new ObjectMapper();
26+
private static Logger log = LoggerFactory.getLogger(CDEventsGenerator.class);
27+
28+
private static final int SUBJECT_INDEX = 2;
29+
private static final int PREDICATE_INDEX = 3;
30+
private static final int VERSION_INDEX = 4;
31+
private static final int SUBSTRING_PIPELINE_INDEX = 8;
32+
33+
private static final String TARGET_PACKAGE = "src/main/java/dev/cdevents/events";
34+
35+
/**
36+
* Event JsonSchema files location.
37+
*/
38+
private static final String RESOURCES_DIR = "src/main/resources/";
39+
/**
40+
* Mustache generic event template file.
41+
*/
42+
private static final String EVENT_TEMPLATE_MUSTACHE = RESOURCES_DIR + "template/event-template.mustache";
43+
44+
/**
45+
* Main method to generate CDEvents from Json schema files.
46+
* @param args [0] - base directory for the cdevents-java-sdk-generator module
47+
* [1] - base directory for the cdevents-java-sdk module
48+
*/
49+
public static void main(String[] args) {
50+
if (args == null || args.length < 2) {
51+
throw new IllegalArgumentException("Insufficient arguments passed to CDEventsGenerator");
52+
}
53+
String generatorBaseDir = args[0];
54+
String sdkBaseDir = args[1];
55+
String targetPackageDir = sdkBaseDir + File.separator + "src/main/java/dev/cdevents/events";
56+
File folder = new File(sdkBaseDir + File.separator + RESOURCES_DIR + "schema");
57+
System.out.println(folder.toPath().toAbsolutePath());
58+
if (folder.isDirectory()) {
59+
File[] files = folder.listFiles((dir, name) -> name.toLowerCase().endsWith(".json"));
60+
if (files != null) {
61+
//Create Mustache factory and compile event-template.mustache template
62+
MustacheFactory mf = new DefaultMustacheFactory();
63+
Mustache mustache = mf.compile(generatorBaseDir + File.separator + EVENT_TEMPLATE_MUSTACHE);
64+
65+
//Generate a class file for each Json schema file using a mustache template
66+
67+
for (File file : files) {
68+
SchemaData schemaData = buildCDEventDataFromJsonSchema(file);
69+
generateClassFileFromSchemaData(mustache, schemaData, targetPackageDir);
70+
}
71+
}
72+
}
73+
}
74+
75+
private static void generateClassFileFromSchemaData(Mustache mustache, SchemaData schemaData, String targetPackageDir) {
76+
String classFileName = StringUtils.join(new String[]{schemaData.getCapitalizedSubject(), schemaData.getCapitalizedPredicate(), "CDEvent", ".java"});
77+
File classFile = new File(targetPackageDir, classFileName);
78+
try {
79+
FileWriter fileWriter = new FileWriter(classFile);
80+
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
81+
mustache.execute(bufferedWriter, schemaData).flush();
82+
fileWriter.close();
83+
} catch (IOException e) {
84+
log.error("Exception occurred while generating class file from Json schema {}", e.getMessage());
85+
throw new IllegalStateException("Exception occurred while generating class file from Json schema ", e);
86+
}
87+
log.info("Rendered event-template has been written to file - {}", classFile.getAbsolutePath());
88+
}
89+
90+
private static SchemaData buildCDEventDataFromJsonSchema(File file) {
91+
SchemaData schemaData = new SchemaData();
92+
93+
log.info("Processing event JsonSchema file: {}", file.getAbsolutePath());
94+
try {
95+
JsonNode rootNode = objectMapper.readTree(file);
96+
JsonNode contextNode = rootNode.get("properties").get("context").get("properties");
97+
98+
String eventType = contextNode.get("type").get("enum").get(0).asText();
99+
log.info("eventType: {}", eventType);
100+
String[] type = eventType.split("\\.");
101+
String subject = type[SUBJECT_INDEX];
102+
String predicate = type[PREDICATE_INDEX];
103+
String capitalizedSubject = StringUtils.capitalize(subject);
104+
if (subject.equals("pipelinerun")) {
105+
capitalizedSubject = capitalizedSubject.substring(0, SUBSTRING_PIPELINE_INDEX)
106+
+ StringUtils.capitalize(subject.substring(SUBSTRING_PIPELINE_INDEX));
107+
}
108+
String capitalizedPredicate = StringUtils.capitalize(predicate);
109+
String version = type[VERSION_INDEX];
110+
111+
//set the Schema JsonNode required values to schemaData
112+
schemaData.setSubject(subject);
113+
schemaData.setPredicate(predicate);
114+
schemaData.setCapitalizedSubject(capitalizedSubject);
115+
schemaData.setCapitalizedPredicate(capitalizedPredicate);
116+
schemaData.setSchemaFileName(file.getName());
117+
schemaData.setUpperCaseSubject(subject.toUpperCase());
118+
schemaData.setVersion(version);
119+
120+
JsonNode subjectNode = rootNode.get("properties").get("subject").get("properties");
121+
JsonNode subjectContentNode = subjectNode.get("content").get("properties");
122+
updateSubjectContentProperties(schemaData, subjectContentNode);
123+
} catch (IOException e) {
124+
log.error("Exception occurred while building schema data from Json schema {}", e.getMessage());
125+
throw new IllegalStateException("Exception occurred while building schema data from Json schema ", e);
126+
}
127+
return schemaData;
128+
}
129+
130+
private static void updateSubjectContentProperties(SchemaData schemaData, JsonNode subjectContentNode) {
131+
Iterator<Map.Entry<String, JsonNode>> contentProps = subjectContentNode.fields();
132+
List<SchemaData.ContentField> contentFields = new ArrayList<>();
133+
List<SchemaData.ContentObjectField> contentObjectFields = new ArrayList<>();
134+
while (contentProps.hasNext()) {
135+
Map.Entry<String, JsonNode> contentMap = contentProps.next();
136+
String contentField = contentMap.getKey();
137+
String capitalizedContentField = StringUtils.capitalize(contentField);
138+
JsonNode contentNode = contentMap.getValue();
139+
if (!contentNode.get("type").asText().equals("object")) {
140+
contentFields.add(new SchemaData.ContentField(contentField, capitalizedContentField, "String"));
141+
} else {
142+
schemaData.setObjectName(contentField);
143+
schemaData.setCapitalizedObjectName(capitalizedContentField);
144+
JsonNode contentObjectNode = contentNode.get("properties");
145+
Iterator<String> contentObjectProps = contentObjectNode.fieldNames();
146+
while (contentObjectProps.hasNext()) {
147+
String contentObjField = contentObjectProps.next();
148+
String capitalizedContentObjField = StringUtils.capitalize(contentObjField);
149+
contentObjectFields.add(new SchemaData.ContentObjectField(contentObjField,
150+
capitalizedContentObjField, contentField, capitalizedContentField, "String"));
151+
}
152+
}
153+
}
154+
schemaData.setContentFields(contentFields);
155+
schemaData.setContentObjectFields(contentObjectFields);
156+
}
157+
158+
private static String getFieldsDataType(String fieldName) {
159+
if (fieldName.equalsIgnoreCase("url")) {
160+
return "URI";
161+
} else {
162+
return "String";
163+
}
164+
}
165+
}

0 commit comments

Comments
 (0)