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
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
;
48 public Iterable
<AnnotationSpec
> generatedClass() {
49 return getAnnotationSpecs(
50 annotations
.annotateClasses(),
51 annotations
.annotationApi(),
52 annotations
.classMembers(),
53 annotations
.classComment());
57 public Iterable
<AnnotationSpec
> generatedField() {
58 return getAnnotationSpecs(
59 annotations
.annotateFields(),
60 annotations
.annotationApi(),
61 annotations
.fieldMembers(),
62 annotations
.fieldComment());
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
) {
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();
97 public Iterable
<AnnotationSpec
> generatedRepository() {
98 return annotations
.repositoryAnnotations().stream()
99 .map(DefaultAnnotations
::asAnnotationSpec
)
104 public Iterable
<AnnotationSpec
> generatedMethod(final SqlConfiguration configuration
) {
105 return Annotation
.mergeAnnotations(configuration
.annotations(), annotations
.methodAnnotations()).stream()
106 .map(DefaultAnnotations
::asAnnotationSpec
)
111 public Iterable
<AnnotationSpec
> generatedConstructor() {
112 return annotations
.constructorAnnotations().stream()
113 .map(DefaultAnnotations
::asAnnotationSpec
)
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());
134 builder
.add("$S", member
.value());
136 return builder
.build();