fix #123 allow to specify extra annotations on repositories/methods
[yosql.git] / yosql-codegen / src / main / java / wtf / metio / yosql / codegen / blocks / DefaultAnnotations.java
blobbf85fd4cfb908b3cda8b099a699ee4fd4de7fab7
1 /*
2 * This file is part of yosql. It is subject to the license terms in the LICENSE file found in the top-level
3 * directory of this distribution and at https://creativecommons.org/publicdomain/zero/1.0/. No part of yosql,
4 * including this file, may be copied, modified, propagated, or distributed except according to the terms contained
5 * in the LICENSE file.
6 */
7 package wtf.metio.yosql.codegen.blocks;
9 import com.squareup.javapoet.AnnotationSpec;
10 import com.squareup.javapoet.ClassName;
11 import com.squareup.javapoet.CodeBlock;
12 import com.squareup.javapoet.TypeName;
13 import de.xn__ho_hia.javapoet.TypeGuesser;
14 import wtf.metio.yosql.models.configuration.Annotation;
15 import wtf.metio.yosql.models.configuration.AnnotationMember;
16 import wtf.metio.yosql.models.configuration.GeneratedAnnotationApis;
17 import wtf.metio.yosql.models.configuration.GeneratedAnnotationMembers;
18 import wtf.metio.yosql.models.immutables.AnnotationsConfiguration;
19 import wtf.metio.yosql.models.immutables.SqlConfiguration;
21 import java.time.ZonedDateTime;
22 import java.util.Collections;
23 import java.util.EnumSet;
25 public final class DefaultAnnotations implements Annotations {
27 private static final EnumSet<GeneratedAnnotationMembers> OPTIONS_WITH_VALUE = EnumSet.of(
28 GeneratedAnnotationMembers.ALL,
29 GeneratedAnnotationMembers.VALUE,
30 GeneratedAnnotationMembers.WITHOUT_DATE);
32 private static final EnumSet<GeneratedAnnotationMembers> OPTIONS_WITH_DATE = EnumSet.of(
33 GeneratedAnnotationMembers.ALL,
34 GeneratedAnnotationMembers.DATE);
36 private static final EnumSet<GeneratedAnnotationMembers> OPTIONS_WITH_COMMENT = EnumSet.of(
37 GeneratedAnnotationMembers.ALL,
38 GeneratedAnnotationMembers.COMMENT,
39 GeneratedAnnotationMembers.WITHOUT_DATE);
41 private final AnnotationsConfiguration annotations;
43 public DefaultAnnotations(final AnnotationsConfiguration annotations) {
44 this.annotations = annotations;
47 @Override
48 public Iterable<AnnotationSpec> generatedClass() {
49 return getAnnotationSpecs(
50 annotations.annotateClasses(),
51 annotations.annotationApi(),
52 annotations.classMembers(),
53 annotations.classComment());
56 @Override
57 public Iterable<AnnotationSpec> generatedField() {
58 return getAnnotationSpecs(
59 annotations.annotateFields(),
60 annotations.annotationApi(),
61 annotations.fieldMembers(),
62 annotations.fieldComment());
65 @Override
66 public Iterable<AnnotationSpec> generatedMethod() {
67 return getAnnotationSpecs(
68 annotations.annotateMethods(),
69 annotations.annotationApi(),
70 annotations.methodMembers(),
71 annotations.methodComment());
74 private Iterable<AnnotationSpec> getAnnotationSpecs(
75 final boolean shouldAnnotate,
76 final GeneratedAnnotationApis annotationApi,
77 final GeneratedAnnotationMembers memberOption,
78 final String comment) {
79 if (shouldAnnotate) {
80 final var annotationClass = ClassName.bestGuess(annotationApi.annotationClass);
81 final var builder = AnnotationSpec.builder(annotationClass);
82 if (OPTIONS_WITH_VALUE.contains(memberOption)) {
83 builder.addMember("value", "$S", annotations.generatorName());
85 if (OPTIONS_WITH_DATE.contains(memberOption)) {
86 builder.addMember("date", "$S", ZonedDateTime.now().toString());
88 if (OPTIONS_WITH_COMMENT.contains(memberOption)) {
89 builder.addMember("comments", "$S", comment);
91 return Collections.singletonList(builder.build());
93 return Collections.emptyList();
96 @Override
97 public Iterable<AnnotationSpec> generatedRepository() {
98 return annotations.repositoryAnnotations().stream()
99 .map(DefaultAnnotations::asAnnotationSpec)
100 .toList();
103 @Override
104 public Iterable<AnnotationSpec> generatedMethod(final SqlConfiguration configuration) {
105 return Annotation.mergeAnnotations(configuration.annotations(), annotations.methodAnnotations()).stream()
106 .map(DefaultAnnotations::asAnnotationSpec)
107 .toList();
110 @Override
111 public Iterable<AnnotationSpec> generatedConstructor() {
112 return annotations.constructorAnnotations().stream()
113 .map(DefaultAnnotations::asAnnotationSpec)
114 .toList();
117 // visible for testing
118 static AnnotationSpec asAnnotationSpec(final Annotation annotation) {
119 // TODO: catch exception thrown by bestGuess and return Optional + use ExecutionErrors?
120 final var type = ClassName.bestGuess(annotation.type());
121 final var builder = AnnotationSpec.builder(type);
122 annotation.members().forEach(member -> builder.addMember(member.key(), asAnnotationMemberSpec(member)));
123 return builder.build();
126 private static CodeBlock asAnnotationMemberSpec(final AnnotationMember member) {
127 final var builder = CodeBlock.builder();
128 final var type = TypeGuesser.guessTypeName(member.type());
129 if (TypeName.CHAR.equals(type)) {
130 builder.add("'$L'", member.value());
131 } else if (type.isPrimitive()) {
132 builder.add("$L", member.value());
133 } else {
134 builder.add("$S", member.value());
136 return builder.build();