Skip to content

Commit

Permalink
fix #123 allow to specify extra annotations on repositories/methods
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebastian Hoß committed Jun 10, 2022
1 parent 335cbd6 commit cfafba2
Show file tree
Hide file tree
Showing 84 changed files with 2,702 additions and 930 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# YoSQL [![Chat](https://img.shields.io/badge/matrix-%23yosql:matrix.org-brightgreen.svg?style=social&label=Matrix)](https://matrix.to/#yosql:matrix.org) [![Mailing List](https://img.shields.io/badge/email-yosql%40metio.groups.io%20-brightgreen.svg?style=social&label=Mail)](https://metio.groups.io/g/yosql/topics)

Take a look at the [project website](https://yosql.projects.metio.wtf/) to read the documentation. The *yosql-examples*
folder contains multiple examples that uses all available features of YoSQL.
Take a look at the [project website](https://yosql.projects.metio.wtf/) to read the documentation.

## License

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
package wtf.metio.yosql.codegen.blocks;

import com.squareup.javapoet.AnnotationSpec;
import wtf.metio.yosql.models.immutables.SqlConfiguration;

/**
* Generates annotations for classes, fields, and methods.
Expand All @@ -29,4 +30,19 @@ public interface Annotations {
*/
Iterable<AnnotationSpec> generatedMethod();

/**
* @return User specified annotations for generated repositories and their interfaces.
*/
Iterable<AnnotationSpec> generatedRepository();

/**
* @return User specified annotations for generated methods.
*/
Iterable<AnnotationSpec> generatedMethod(SqlConfiguration configuration);

/**
* @return User specified annotations for generated constructors.
*/
Iterable<AnnotationSpec> generatedConstructor();

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,73 +8,79 @@

import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ClassName;
import wtf.metio.yosql.models.configuration.AnnotationApis;
import wtf.metio.yosql.models.configuration.AnnotationMembers;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.TypeName;
import de.xn__ho_hia.javapoet.TypeGuesser;
import wtf.metio.yosql.models.configuration.Annotation;
import wtf.metio.yosql.models.configuration.AnnotationMember;
import wtf.metio.yosql.models.configuration.GeneratedAnnotationApis;
import wtf.metio.yosql.models.configuration.GeneratedAnnotationMembers;
import wtf.metio.yosql.models.immutables.AnnotationsConfiguration;
import wtf.metio.yosql.models.immutables.SqlConfiguration;

import java.time.ZonedDateTime;
import java.util.Collections;
import java.util.EnumSet;

public final class DefaultAnnotations implements Annotations {

private static final EnumSet<AnnotationMembers> OPTIONS_WITH_VALUE = EnumSet.of(
AnnotationMembers.ALL,
AnnotationMembers.VALUE,
AnnotationMembers.WITHOUT_DATE);
private static final EnumSet<GeneratedAnnotationMembers> OPTIONS_WITH_VALUE = EnumSet.of(
GeneratedAnnotationMembers.ALL,
GeneratedAnnotationMembers.VALUE,
GeneratedAnnotationMembers.WITHOUT_DATE);

private static final EnumSet<AnnotationMembers> OPTIONS_WITH_DATE = EnumSet.of(
AnnotationMembers.ALL,
AnnotationMembers.DATE);
private static final EnumSet<GeneratedAnnotationMembers> OPTIONS_WITH_DATE = EnumSet.of(
GeneratedAnnotationMembers.ALL,
GeneratedAnnotationMembers.DATE);

private static final EnumSet<AnnotationMembers> OPTIONS_WITH_COMMENT = EnumSet.of(
AnnotationMembers.ALL,
AnnotationMembers.COMMENT,
AnnotationMembers.WITHOUT_DATE);
private static final EnumSet<GeneratedAnnotationMembers> OPTIONS_WITH_COMMENT = EnumSet.of(
GeneratedAnnotationMembers.ALL,
GeneratedAnnotationMembers.COMMENT,
GeneratedAnnotationMembers.WITHOUT_DATE);

private final AnnotationsConfiguration configuration;
private final AnnotationsConfiguration annotations;

public DefaultAnnotations(final AnnotationsConfiguration configuration) {
this.configuration = configuration;
public DefaultAnnotations(final AnnotationsConfiguration annotations) {
this.annotations = annotations;
}

@Override
public Iterable<AnnotationSpec> generatedClass() {
return getAnnotationSpecs(
configuration.annotateClasses(),
configuration.annotationApi(),
configuration.classMembers(),
configuration.classComment());
annotations.annotateClasses(),
annotations.annotationApi(),
annotations.classMembers(),
annotations.classComment());
}

@Override
public Iterable<AnnotationSpec> generatedField() {
return getAnnotationSpecs(
configuration.annotateFields(),
configuration.annotationApi(),
configuration.fieldMembers(),
configuration.fieldComment());
annotations.annotateFields(),
annotations.annotationApi(),
annotations.fieldMembers(),
annotations.fieldComment());
}

@Override
public Iterable<AnnotationSpec> generatedMethod() {
return getAnnotationSpecs(
configuration.annotateMethods(),
configuration.annotationApi(),
configuration.methodMembers(),
configuration.methodComment());
annotations.annotateMethods(),
annotations.annotationApi(),
annotations.methodMembers(),
annotations.methodComment());
}

private Iterable<AnnotationSpec> getAnnotationSpecs(
final boolean shouldAnnotate,
final AnnotationApis annotationApi,
final AnnotationMembers memberOption,
final GeneratedAnnotationApis annotationApi,
final GeneratedAnnotationMembers memberOption,
final String comment) {
if (shouldAnnotate) {
final var annotationClass = ClassName.bestGuess(annotationApi.annotationClass);
final var builder = AnnotationSpec.builder(annotationClass);
if (OPTIONS_WITH_VALUE.contains(memberOption)) {
builder.addMember("value", "$S", configuration.generatorName());
builder.addMember("value", "$S", annotations.generatorName());
}
if (OPTIONS_WITH_DATE.contains(memberOption)) {
builder.addMember("date", "$S", ZonedDateTime.now().toString());
Expand All @@ -87,4 +93,47 @@ private Iterable<AnnotationSpec> getAnnotationSpecs(
return Collections.emptyList();
}

@Override
public Iterable<AnnotationSpec> generatedRepository() {
return annotations.repositoryAnnotations().stream()
.map(DefaultAnnotations::asAnnotationSpec)
.toList();
}

@Override
public Iterable<AnnotationSpec> generatedMethod(final SqlConfiguration configuration) {
return Annotation.mergeAnnotations(configuration.annotations(), annotations.methodAnnotations()).stream()
.map(DefaultAnnotations::asAnnotationSpec)
.toList();
}

@Override
public Iterable<AnnotationSpec> generatedConstructor() {
return annotations.constructorAnnotations().stream()
.map(DefaultAnnotations::asAnnotationSpec)
.toList();
}

// visible for testing
static AnnotationSpec asAnnotationSpec(final Annotation annotation) {
// TODO: catch exception thrown by bestGuess and return Optional + use ExecutionErrors?
final var type = ClassName.bestGuess(annotation.type());
final var builder = AnnotationSpec.builder(type);
annotation.members().forEach(member -> builder.addMember(member.key(), asAnnotationMemberSpec(member)));
return builder.build();
}

private static CodeBlock asAnnotationMemberSpec(final AnnotationMember member) {
final var builder = CodeBlock.builder();
final var type = TypeGuesser.guessTypeName(member.type());
if (TypeName.CHAR.equals(type)) {
builder.add("'$L'", member.value());
} else if (type.isPrimitive()) {
builder.add("$L", member.value());
} else {
builder.add("$S", member.value());
}
return builder.build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,9 @@

package wtf.metio.yosql.codegen.blocks;

import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import wtf.metio.yosql.models.configuration.ResultRowConverter;

import java.util.Objects;

public final class DefaultCodeBlocks implements CodeBlocks {

@Override
Expand Down Expand Up @@ -46,11 +43,10 @@ public CodeBlock initializeFieldToSelf(final String fieldName) {

@Override
public CodeBlock initializeConverter(final ResultRowConverter converter) {
final var type = converter.converterType();
final ClassName converterClass = ClassName.bestGuess((Objects.isNull(type) || type.isBlank()) ? "java.lang.Object" :
type);
return CodeBlock.builder()
.addStatement("this.$N = new $T()", converter.alias(), converterClass)
.addStatement("this.$N = new $T()",
converter.alias().orElseThrow(), // TODO: throw business exception
converter.converterTypeName().orElseThrow()) // TODO: throw business exception
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@
import wtf.metio.yosql.internals.jdk.Strings;
import wtf.metio.yosql.models.configuration.ResultRowConverter;
import wtf.metio.yosql.models.immutables.FilesConfiguration;
import wtf.metio.yosql.models.immutables.SqlConfiguration;
import wtf.metio.yosql.models.immutables.SqlStatement;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

import static java.util.function.Predicate.not;

Expand Down Expand Up @@ -93,10 +94,10 @@ public CodeBlock methodJavadoc(final List<SqlStatement> statements, final String
builder.add(messages.getMessage(Javadocs.DISABLE_WITH), configuration);
statements.stream()
.map(SqlStatement::getConfiguration)
.flatMap(config -> config.resultRowConverter().stream())
.filter(Objects::nonNull)
.map(SqlConfiguration::resultRowConverter)
.flatMap(Optional::stream)
.map(ResultRowConverter::resultType)
.filter(Objects::nonNull)
.flatMap(Optional::stream)
.filter(type -> !type.startsWith("java"))
.map(type -> type.substring(0, type.contains("<") ? type.indexOf("<") : type.length()))
.distinct()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import com.squareup.javapoet.MethodSpec;
import wtf.metio.yosql.models.immutables.JavaConfiguration;
import wtf.metio.yosql.models.immutables.SqlConfiguration;
import wtf.metio.yosql.models.immutables.SqlStatement;

import javax.lang.model.element.Modifier;
Expand Down Expand Up @@ -47,6 +48,7 @@ public MethodSpec.Builder publicMethod(
return MethodSpec.methodBuilder(name)
.addModifiers(modifiers)
.addAnnotations(annotations.generatedMethod())
.addAnnotations(annotations.generatedMethod(SqlConfiguration.fromStatements(statements)))
.addJavadoc(javadoc.methodJavadoc(statements, configuration));
}

Expand All @@ -58,6 +60,7 @@ public MethodSpec.Builder declaration(
return MethodSpec.methodBuilder(name)
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addAnnotations(annotations.generatedMethod())
.addAnnotations(annotations.generatedMethod(SqlConfiguration.fromStatements(statements)))
.addJavadoc(javadoc.methodJavadoc(statements, configuration));
}

Expand All @@ -76,7 +79,8 @@ public MethodSpec.Builder implementation(final String name) {
public MethodSpec.Builder constructor() {
return MethodSpec.constructorBuilder()
.addModifiers(Modifier.PUBLIC)
.addAnnotations(annotations.generatedMethod());
.addAnnotations(annotations.generatedMethod())
.addAnnotations(annotations.generatedConstructor());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.util.Map;
import java.util.function.BiFunction;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public final class DefaultCodeGenerator implements CodeGenerator {
Expand Down Expand Up @@ -46,11 +47,11 @@ private Stream<PackagedTypeSpec> generateRepositories(final List<SqlStatement> s
}

private Stream<PackagedTypeSpec> generateRepositoryClasses(final List<SqlStatement> statements) {
return generate(statements, SqlStatement.groupByRepositoryClass(), repositoryGenerator::generateRepositoryClass);
return generate(statements, Collectors.groupingBy(SqlStatement::getRepositoryClass), repositoryGenerator::generateRepositoryClass);
}

private Stream<PackagedTypeSpec> generateRepositoryInterfaces(final List<SqlStatement> statements) {
return generate(statements, SqlStatement.groupByRepositoryInterface(), repositoryGenerator::generateRepositoryInterface);
return generate(statements, Collectors.groupingBy(SqlStatement::getRepositoryInterface), repositoryGenerator::generateRepositoryInterface);
}

private static Stream<PackagedTypeSpec> generate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public MethodSpec repository(final List<SqlStatement> statements) {
final var constructor = methods.constructor().addParameter(jdbcParameters.dataSource());
resultConverters(statements).forEach(converter -> {
constructor.addParameter(jdbcParameters.converter(converter));
builder.add(blocks.initializeFieldToSelf(converter.alias()));
builder.add(blocks.initializeFieldToSelf(converter.alias().orElseThrow())); // TODO: throw business exception
});
return constructor
.addCode(blocks.initializeFieldToSelf(names.dataSource()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.FieldSpec;
import de.xn__ho_hia.javapoet.TypeGuesser;
import wtf.metio.yosql.codegen.blocks.Fields;
import wtf.metio.yosql.codegen.blocks.Javadoc;
import wtf.metio.yosql.codegen.files.SqlStatementParser;
Expand Down Expand Up @@ -76,13 +75,15 @@ private void addIndexArray(
final SqlConfiguration config) {
builder.addStatement("$N.put($S, $L)",
constantSqlStatementParameterIndexFieldName(config),
parameter.name(),
parameter.name().orElseThrow(), // TODO: throw business exception
indexArray(parameter));
}

private static String indexArray(final SqlParameter param) {
return IntStream.of(param.indices())
.boxed()
return param.indices()
.stream()
.map(IntStream::of)
.flatMap(IntStream::boxed)
.map(Object::toString)
.collect(Collectors.joining(", ", "new int[] { ", " }"));
}
Expand Down Expand Up @@ -114,10 +115,6 @@ public Iterable<FieldSpec> asFields(final List<SqlStatement> statements) {
}

private Optional<FieldSpec> loggerField(final SqlStatement sqlStatement) {
// return sqlStatement.getRepository()
// .map(ClassName::bestGuess)
// .flatMap(logging::logger);

return logging.logger(ClassName.bestGuess(sqlStatement.getRepositoryClass()));
}

Expand Down Expand Up @@ -154,8 +151,8 @@ private FieldSpec asConstantSqlParameterIndexField(final SqlStatement sqlStateme

private FieldSpec asConverterField(final ResultRowConverter converter) {
return fields.field(
TypeGuesser.guessTypeName(converter.converterType()),
converter.alias());
converter.converterTypeName().orElseThrow(), // TODO: throw business exception
converter.alias().orElseThrow()); // TODO: throw business exception
}

@Override
Expand Down
Loading

0 comments on commit cfafba2

Please sign in to comment.