Skip to content

Commit 41c659a

Browse files
committed
Allow generation a report class
1 parent 837930f commit 41c659a

File tree

6 files changed

+92
-17
lines changed

6 files changed

+92
-17
lines changed

api/src/main/java/com/cosium/json_schema_to_java_record_api/GenerateRecordsFromJsonSchemas.java

+5
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,9 @@
1212
JsonSchemaFileLocation[] schemaRootFileLocations();
1313

1414
JsonSchemaConfiguration[] schemaConfigurations() default {};
15+
16+
/**
17+
* @return A non-empty string to generate a report class. Empty otherwise.
18+
*/
19+
String reportClassQualifiedName() default "";
1520
}

core/src/main/java/com/cosium/json_schema_to_java_record/AnnotationProcessor.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.util.concurrent.CopyOnWriteArraySet;
88
import java.util.function.Predicate;
99
import java.util.stream.Collectors;
10+
import javax.annotation.processing.Filer;
1011
import javax.annotation.processing.ProcessingEnvironment;
1112
import javax.annotation.processing.Processor;
1213
import javax.annotation.processing.RoundEnvironment;
@@ -28,13 +29,13 @@ public class AnnotationProcessor extends AbstractLoggingProcessor {
2829

2930
private final Set<Command> processedCommands = new CopyOnWriteArraySet<>();
3031

31-
@Nullable private JavaTypes javaTypes;
32+
@Nullable private Filer filer;
3233
@Nullable private JsonSchemas jsonSchemas;
3334

3435
@Override
3536
public synchronized void init(ProcessingEnvironment processingEnv) {
3637
super.init(processingEnv);
37-
this.javaTypes = new JavaTypes(processingEnv.getFiler());
38+
this.filer = processingEnv.getFiler();
3839
jsonSchemas = new JsonSchemas(new ReadonlyClassPathResources(processingEnv.getFiler()));
3940
}
4041

@@ -55,7 +56,7 @@ protected boolean doProcess(Set<? extends TypeElement> annotations, RoundEnviron
5556

5657
commands.stream()
5758
.peek(command -> LOGGER.debug("Executing {}", command))
58-
.forEach(command -> command.execute(javaTypes, jsonSchemas));
59+
.forEach(command -> command.execute(filer, jsonSchemas));
5960

6061
processedCommands.addAll(commands);
6162

core/src/main/java/com/cosium/json_schema_to_java_record/Command.java

+7-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import com.cosium.json_schema_to_java_record_api.GenerateRecordsFromJsonSchemas;
66
import java.util.Arrays;
7+
import javax.annotation.processing.Filer;
78
import javax.lang.model.element.Element;
89
import javax.lang.model.element.PackageElement;
910

@@ -17,12 +18,14 @@ record Command(Element annotatedElement, GenerateRecordsFromJsonSchemas annotati
1718
requireNonNull(annotation);
1819
}
1920

20-
public void execute(JavaTypes javaTypes, JsonSchemas jsonSchemas) {
21+
public void execute(Filer filer, JsonSchemas jsonSchemas) {
2122
Configuration configuration = new Configuration(annotatedElementPackageName(), annotation);
2223

23-
Arrays.stream(annotation.schemaRootFileLocations())
24-
.map(jsonSchemas::parse)
25-
.forEach(jsonSchema -> jsonSchema.writeJavaType(javaTypes, configuration));
24+
try (JavaTypes javaTypes = new JavaTypes(filer, annotation)) {
25+
Arrays.stream(annotation.schemaRootFileLocations())
26+
.map(jsonSchemas::parse)
27+
.forEach(jsonSchema -> jsonSchema.writeJavaType(javaTypes, configuration));
28+
}
2629
}
2730

2831
private String annotatedElementPackageName() {

core/src/main/java/com/cosium/json_schema_to_java_record/JavaTypes.java

+73-8
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,45 @@
55
import com.cosium.json_schema_to_java_record_api.GenerateRecordsFromJsonSchemas;
66
import com.palantir.javapoet.AnnotationSpec;
77
import com.palantir.javapoet.ClassName;
8+
import com.palantir.javapoet.CodeBlock;
9+
import com.palantir.javapoet.FieldSpec;
810
import com.palantir.javapoet.JavaFile;
11+
import com.palantir.javapoet.MethodSpec;
12+
import com.palantir.javapoet.ParameterizedTypeName;
913
import com.palantir.javapoet.TypeSpec;
1014
import java.io.IOException;
1115
import java.io.UncheckedIOException;
16+
import java.util.HashMap;
17+
import java.util.Map;
18+
import java.util.Optional;
19+
import java.util.function.Predicate;
1220
import javax.annotation.processing.Filer;
1321
import javax.annotation.processing.FilerException;
1422
import javax.annotation.processing.Generated;
23+
import javax.lang.model.element.Modifier;
1524
import javax.tools.StandardLocation;
25+
import org.jspecify.annotations.Nullable;
1626
import org.slf4j.Logger;
1727
import org.slf4j.LoggerFactory;
1828

1929
/**
2030
* @author Réda Housni Alaoui
2131
*/
22-
class JavaTypes {
32+
class JavaTypes implements AutoCloseable {
2333

2434
private static final Logger LOGGER = LoggerFactory.getLogger(JavaTypes.class);
2535

2636
private final Filer filer;
37+
@Nullable private final ClassName reportClassName;
38+
private final Map<String, ClassName> classNameBySchemaId = new HashMap<>();
2739

28-
JavaTypes(Filer filer) {
40+
JavaTypes(Filer filer, GenerateRecordsFromJsonSchemas annotation) {
2941
this.filer = requireNonNull(filer);
42+
reportClassName =
43+
Optional.of(annotation.reportClassQualifiedName())
44+
.filter(Predicate.not(String::isBlank))
45+
.map(ClassName::bestGuess)
46+
.orElse(null);
3047
}
3148

3249
public boolean existsOnClassPath(ClassName className) {
@@ -39,12 +56,16 @@ public boolean existsOnClassPath(ClassName className) {
3956
}
4057
}
4158

42-
public void write(String packageName, TypeSpec.Builder typeSpecBuilder) {
43-
typeSpecBuilder.addAnnotation(
44-
AnnotationSpec.builder(Generated.class)
45-
.addMember("value", "$S", GenerateRecordsFromJsonSchemas.class.getName())
46-
.build());
47-
write(JavaFile.builder(packageName, typeSpecBuilder.build()).build());
59+
public void write(
60+
@Nullable String schemaId, String packageName, TypeSpec.Builder typeSpecBuilder) {
61+
62+
TypeSpec typeSpec = markAsGenerated(typeSpecBuilder).build();
63+
64+
if (schemaId != null) {
65+
classNameBySchemaId.put(schemaId, ClassName.get(packageName, typeSpec.name()));
66+
}
67+
68+
write(JavaFile.builder(packageName, typeSpec).build());
4869
}
4970

5071
private void write(JavaFile javaFile) {
@@ -61,4 +82,48 @@ private void write(JavaFile javaFile) {
6182
throw new UncheckedIOException(e);
6283
}
6384
}
85+
86+
@Override
87+
public void close() {
88+
if (reportClassName == null) {
89+
return;
90+
}
91+
92+
TypeSpec.Builder reportBuilder =
93+
markAsGenerated(TypeSpec.classBuilder(reportClassName))
94+
.addModifiers(Modifier.PUBLIC)
95+
.addModifiers(Modifier.FINAL)
96+
.addMethod(MethodSpec.constructorBuilder().addModifiers(Modifier.PRIVATE).build());
97+
98+
CodeBlock classBySchemaIdFieldEntries =
99+
classNameBySchemaId.entrySet().stream()
100+
.map(
101+
schemaIdToClassName ->
102+
CodeBlock.of(
103+
"$T.entry($S,$T.class)",
104+
Map.class,
105+
schemaIdToClassName.getKey(),
106+
schemaIdToClassName.getValue()))
107+
.collect(CodeBlock.joining(","));
108+
109+
FieldSpec classBySchemaIdField =
110+
FieldSpec.builder(
111+
ParameterizedTypeName.get(Map.class, String.class, Class.class), "classBySchemaId")
112+
.addModifiers(Modifier.PUBLIC)
113+
.addModifiers(Modifier.STATIC)
114+
.addModifiers(Modifier.FINAL)
115+
.initializer("$T.ofEntries($L)", Map.class, classBySchemaIdFieldEntries)
116+
.build();
117+
118+
reportBuilder.addField(classBySchemaIdField);
119+
120+
write(JavaFile.builder(reportClassName.packageName(), reportBuilder.build()).build());
121+
}
122+
123+
private TypeSpec.Builder markAsGenerated(TypeSpec.Builder typeBuilder) {
124+
return typeBuilder.addAnnotation(
125+
AnnotationSpec.builder(Generated.class)
126+
.addMember("value", "$S", GenerateRecordsFromJsonSchemas.class.getName())
127+
.build());
128+
}
64129
}

core/src/main/java/com/cosium/json_schema_to_java_record/JsonSchemaContent.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ public TypeName writeJavaType(
167167
.map(ClassName::bestGuess)
168168
.forEach(typeBuilder::addSuperinterface);
169169

170-
javaTypes.write(className.packageName(), typeBuilder);
170+
javaTypes.write($id, className.packageName(), typeBuilder);
171171

172172
return className;
173173
}

tests/src/test/java/com/cosium/json_schema_to_java_record_tests/case1/package-info.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
javaTypeQualifiedName = "com.cosium.json_schema_to_java_record_tests.case1.Country",
1919
javaInterfaceQualifiedNames =
2020
"com.cosium.json_schema_to_java_record_tests.case1.Location"),
21-
})
21+
},
22+
reportClassQualifiedName = "com.cosium.json_schema_to_java_record_tests.case1.Report")
2223
package com.cosium.json_schema_to_java_record_tests.case1;
2324

2425
import com.cosium.json_schema_to_java_record_api.GenerateRecordsFromJsonSchemas;

0 commit comments

Comments
 (0)