diff --git a/LICENSE.txt b/LICENSE.txt index f8ccc6b..a84dc09 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,28 +1,3 @@ Copyright MapStruct Authors. MapStruct Tools Gem is licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 - ------------------------------------------------------------------------- - - MAPSTRUCT Tools Gem SUBCOMPONENTS WITH DIFFERENT COPYRIGHT OWNERS - - The Tools Gem distribution (ZIP, TAR.GZ) as well as the Tools Gem - processor library (JAR) include FreeMarker, a software developed by - Attila Szegedi, Daniel Dekany and Jonathan Revusky. FreeMarker is - licensed under the same license as Tools Gem itself - Apache License, - Version 2.0 - but the copyright owners are the aforementioned individuals. - - The Tools Gem distribution (ZIP, TAR.GZ) as well as the Tools Gem - processor library (JAR) include a number of files that are licensed by the - Apache Software Foundation under the same license as Tools Gem itself - - Apache License, Version 2.0 - but the copyright owner is the Apache - Software Foundation. These files are: - - freemarker/ext/jsp/web-app_2_2.dtd - freemarker/ext/jsp/web-app_2_3.dtd - freemarker/ext/jsp/web-app_2_4.xsd - freemarker/ext/jsp/web-app_2_5.xsd - freemarker/ext/jsp/web-jsptaglibrary_1_1.dtd - freemarker/ext/jsp/web-jsptaglibrary_1_2.dtd - freemarker/ext/jsp/web-jsptaglibrary_2_0.xsd - freemarker/ext/jsp/web-jsptaglibrary_2_1.xsd diff --git a/parent/pom.xml b/parent/pom.xml index 12fce53..1ae008a 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -27,7 +27,7 @@ 8.29 1 - 3.17.2 + 3.23.1 @@ -95,12 +95,6 @@ ${project.version} - - org.freemarker - freemarker - 2.3.29 - - org.assertj assertj-core diff --git a/processor/pom.xml b/processor/pom.xml index d204afd..44a6757 100644 --- a/processor/pom.xml +++ b/processor/pom.xml @@ -34,8 +34,9 @@ - org.freemarker - freemarker + com.squareup + javapoet + 1.13.0 @@ -119,36 +120,6 @@ - - org.apache.maven.plugins - maven-shade-plugin - - - processor-deps-shading - package - - shade - - - true - - - org.freemarker:freemarker - - META-INF/*.* - - - - - - freemarker - org.mapstruct.tools.gem.processor.shaded.freemarker - - - - - - org.codehaus.mojo flatten-maven-plugin @@ -166,29 +137,6 @@ - - org.apache.maven.plugins - maven-dependency-plugin - - - unpack-freemarker-license - prepare-package - - unpack - - - - - org.freemarker - freemarker - ${project.build.directory}/classes/META-INF/freemarker - META-INF/LICENSE.txt,META-INF/NOTICE.txt - - - - - - org.apache.maven.plugins maven-compiler-plugin diff --git a/processor/src/main/java/org/mapstruct/tools/gem/processor/GemInfo.java b/processor/src/main/java/org/mapstruct/tools/gem/processor/GemInfo.java index 6354e7a..2e416cf 100644 --- a/processor/src/main/java/org/mapstruct/tools/gem/processor/GemInfo.java +++ b/processor/src/main/java/org/mapstruct/tools/gem/processor/GemInfo.java @@ -5,7 +5,7 @@ */ package org.mapstruct.tools.gem.processor; -import java.util.Arrays; +import java.util.Collection; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -24,10 +24,10 @@ public class GemInfo { private final String builderImplName; private final List gemValueInfos; - private final Element[] originatingElements; + private final Collection originatingElements; public GemInfo(String gemPackageName, String annotationName, String annotationFqn, - List gemValueInfos, Element... originatingElements) { + List gemValueInfos, Collection originatingElements) { this.gemPackageName = gemPackageName; this.gemName = annotationName + "Gem"; this.annotationName = annotationName; @@ -35,7 +35,7 @@ public GemInfo(String gemPackageName, String annotationName, String annotationFq this.gemValueInfos = gemValueInfos; this.builderName = BUILDER_NAME + ( BUILDER_NAME.equals( annotationName ) ? "_" : "" ); this.builderImplName = BUILDER_IMPL_NAME + ( BUILDER_IMPL_NAME.equals( annotationName ) ? "_" : "" ); - this.originatingElements = Arrays.copyOf( originatingElements, originatingElements.length ); + this.originatingElements = originatingElements; } public String getGemName() { @@ -75,7 +75,7 @@ public String getBuilderImplName() { return builderImplName; } - public Element[] getOriginatingElements() { + public Collection getOriginatingElements() { return originatingElements; } diff --git a/processor/src/main/java/org/mapstruct/tools/gem/processor/GemProcessor.java b/processor/src/main/java/org/mapstruct/tools/gem/processor/GemProcessor.java index cc97c09..0ad5b16 100644 --- a/processor/src/main/java/org/mapstruct/tools/gem/processor/GemProcessor.java +++ b/processor/src/main/java/org/mapstruct/tools/gem/processor/GemProcessor.java @@ -5,15 +5,12 @@ */ package org.mapstruct.tools.gem.processor; -import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; -import java.io.Writer; import java.util.ArrayList; -import java.util.HashMap; +import java.util.Arrays; import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import javax.annotation.processing.AbstractProcessor; @@ -32,10 +29,8 @@ import javax.lang.model.util.ElementFilter; import javax.tools.Diagnostic; -import freemarker.template.Configuration; -import freemarker.template.Template; -import freemarker.template.TemplateException; -import freemarker.template.Version; +import com.squareup.javapoet.JavaFile; +import com.squareup.javapoet.TypeSpec; /** * @author sjaakd @@ -110,8 +105,7 @@ private void addGemInfo(AnnotationMirror gemDefinitionMirror, Element definingEl gemName, gemFqn, gemValueInfos, - definingElement, - gemDeclaredType.asElement() + Arrays.asList( definingElement, gemDeclaredType.asElement() ) ); gemInfos.add( gemInfo ); } @@ -191,23 +185,15 @@ else if (String.class.getName().equals( fqn ) ) { private void write( ) { for ( GemInfo gemInfo : gemInfos ) { - try (Writer writer = processingEnv.getFiler() - .createSourceFile( - gemInfo.getGemPackageName() + "." + gemInfo.getGemName(), - gemInfo.getOriginatingElements() - ) - .openWriter()) { - Configuration cfg = new Configuration( new Version( "2.3.21" ) ); - cfg.setClassForTemplateLoading( GemProcessor.class, "/" ); - cfg.setDefaultEncoding( "UTF-8" ); - - Map templateData = new HashMap<>(); - - templateData.put( "gemInfo", gemInfo ); - Template template = cfg.getTemplate( "org/mapstruct/tools/gem/processor/Gem.ftl" ); - template.process( templateData, writer ); + TypeSpec gemSpec = JavaPoetWriter.createGemSpec( gemInfo ); + JavaFile javaFile = JavaFile.builder( gemInfo.getGemPackageName(), gemSpec ) + .indent( " " ) + .skipJavaLangImports( true ) + .build(); + try { + javaFile.writeTo( processingEnv.getFiler() ); } - catch ( TemplateException | IOException ex ) { + catch ( Exception ex ) { throw new IllegalStateException( ex ); } } diff --git a/processor/src/main/java/org/mapstruct/tools/gem/processor/JavaPoetWriter.java b/processor/src/main/java/org/mapstruct/tools/gem/processor/JavaPoetWriter.java new file mode 100644 index 0000000..83a1064 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/tools/gem/processor/JavaPoetWriter.java @@ -0,0 +1,449 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.tools.gem.processor; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.util.ElementFilter; + +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterSpec; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeName; +import com.squareup.javapoet.TypeSpec; +import com.squareup.javapoet.TypeVariableName; + +/** + * @author Filip Hrisafov + */ +public class JavaPoetWriter { + + private static final ClassName GEM = ClassName.get( "org.mapstruct.tools.gem", "Gem" ); + private static final ClassName GEM_VALUE = ClassName.get( "org.mapstruct.tools.gem", "GemValue" ); + + private static final ClassName LIST = ClassName.get( List.class ); + + private JavaPoetWriter() { + // hide utility class contstructor + } + + public static TypeSpec createGemSpec(GemInfo gemInfo) { + ClassName generatedGemClassName = ClassName.get( gemInfo.getGemPackageName(), gemInfo.getGemName() ); + ClassName gemBuilder = generatedGemClassName.nestedClass( gemInfo.getBuilderName() ); + ClassName gemBuilderImpl = generatedGemClassName.nestedClass( gemInfo.getBuilderImplName() ); + + TypeSpec builder = createBuilderInterfaceSpec( gemBuilder, gemInfo ); + + TypeSpec builderImpl = createBuilderImplClassSpec( + gemBuilderImpl, + gemBuilder, + generatedGemClassName, + gemInfo + ); + + Collection getters = new ArrayList<>( gemInfo.getGemValueInfos().size() ); + Collection fields = new ArrayList<>( gemInfo.getGemValueInfos().size() ); + for ( GemValueInfo gemValueInfo : gemInfo.getGemValueInfos() ) { + + getters.add( MethodSpec.methodBuilder( gemValueInfo.getName() ) + .addModifiers( Modifier.PUBLIC ) + .returns( gemValueParameterTypeName( gemValueInfo.getValueType() ) ) + .addStatement( "return this.$N", gemValueInfo.getName() ) + .addJavadoc( "accessor\n" ) + .addJavadoc( + "\n@return the {@link $L} for {@link $L#$L}", + GEM_VALUE.simpleName(), + gemInfo.getGemName(), + gemValueInfo.getName() + ) + .build() ); + + fields.add( FieldSpec.builder( + gemValueParameterTypeName( gemValueInfo.getValueType() ), + gemValueInfo.getName(), + Modifier.PRIVATE, Modifier.FINAL + ).build() ); + } + + TypeSpec.Builder gemTypeSpecBuilder = TypeSpec.classBuilder( generatedGemClassName ); + + for ( Element originatingElement : gemInfo.getOriginatingElements() ) { + gemTypeSpecBuilder.addOriginatingElement( originatingElement ); + } + + + return gemTypeSpecBuilder + .addSuperinterface( GEM ) + .addModifiers( Modifier.PUBLIC ) + .addFields( fields ) + .addField( FieldSpec.builder( TypeName.BOOLEAN, "isValid", Modifier.PRIVATE, Modifier.FINAL ).build() ) + .addField( FieldSpec.builder( AnnotationMirror.class, "mirror", Modifier.PRIVATE, Modifier.FINAL ).build() ) + .addMethod( MethodSpec.constructorBuilder() + .addModifiers( Modifier.PRIVATE ) + .addParameter( gemBuilderImpl, "builder" ) + .addCode( constructorSetValueFields( gemInfo ) ) + .addStatement( "this.$1N = builder.$1N", "mirror" ) + .addCode( "\n" ) + .addCode( constructorValidDefinition( gemInfo ) ) + .build() ) + // getters + .addMethods( getters ) + .addMethod( MethodSpec.methodBuilder( "mirror" ) + .addAnnotation( Override.class ) + .addModifiers( Modifier.PUBLIC ) + .returns( AnnotationMirror.class ) + .addStatement( "return this.mirror" ) + .build() ) + .addMethod( MethodSpec.methodBuilder( "isValid" ) + .addAnnotation( Override.class ) + .addModifiers( Modifier.PUBLIC ) + .returns( TypeName.BOOLEAN ) + .addStatement( "return this.isValid" ) + .build() ) + // static methods + .addMethod( MethodSpec.methodBuilder( "instanceOn" ) + .addModifiers( Modifier.PUBLIC, Modifier.STATIC ) + .addParameter( Element.class, "element" ) + .returns( generatedGemClassName ) + .addStatement( "return build( element, new $T() )", gemBuilderImpl ) + .build() ) + .addMethod( MethodSpec.methodBuilder( "instanceOn" ) + .addModifiers( Modifier.PUBLIC, Modifier.STATIC ) + .addParameter( AnnotationMirror.class, "mirror" ) + .returns( generatedGemClassName ) + .addStatement( "return build( mirror, new $T() )", gemBuilderImpl ) + .build() ) + .addMethod( MethodSpec.methodBuilder( "build" ) + .addModifiers( Modifier.PUBLIC, Modifier.STATIC ) + .addTypeVariable( TypeVariableName.get( "T" ) ) + .addParameter( Element.class, "element" ) + .addParameter( ParameterizedTypeName.get( gemBuilder, TypeVariableName.get( "T" ) ), "builder" ) + .returns( TypeVariableName.get( "T" ) ) + .addStatement( "$T mirror = element.getAnnotationMirrors().stream()" + + "\n.filter( a -> $S.contentEquals( ( ( $T ) a.getAnnotationType().asElement() )" + + ".getQualifiedName() ) )" + + "\n.findAny()" + + "\n.orElse( null )", AnnotationMirror.class, gemInfo.getAnnotationFqn(), TypeElement.class ) + .addStatement( "return build( mirror, builder )" ) + .build() ) + .addMethod( gemBuildMethod( gemBuilder, gemInfo ) ) + .addType( builder ) + .addType( builderImpl ) + .build(); + } + + protected static TypeSpec createBuilderInterfaceSpec(ClassName gemBuilder, GemInfo gemInfo) { + Collection gemSetterMethods = new ArrayList<>( gemInfo.getGemValueInfos().size() ); + for ( GemValueInfo gemValueInfo : gemInfo.getGemValueInfos() ) { + gemSetterMethods.add( MethodSpec.methodBuilder( "set" + Util.capitalize( gemValueInfo.getName() ) ) + .addModifiers( Modifier.PUBLIC, Modifier.ABSTRACT ) + .addParameter( createParameterSpec( gemValueInfo ) ) + .addJavadoc( + "Sets the {@link $T} for {@link $L#$L}", + GEM_VALUE, + gemInfo.getGemName(), + gemValueInfo.getName() + ) + .addJavadoc( + "\n\n@return the {@link $T} for this gem, representing {@link $L}", + gemBuilder, + gemInfo.getGemName() + ) + .returns( gemBuilder ) + .build() ); + + } + + return TypeSpec.interfaceBuilder( gemBuilder ) + .addTypeVariable( TypeVariableName.get( "T" ) ) + .addModifiers( Modifier.PUBLIC, Modifier.STATIC ) + .addJavadoc( "A builder that can be implemented by the user to define custom logic" ) + .addJavadoc( "\ne.g. in the build method, prior to creating the annotation gem." ) + .addMethods( gemSetterMethods ) + .addMethod( MethodSpec.methodBuilder( "setMirror" ) + .addModifiers( Modifier.PUBLIC, Modifier.ABSTRACT ) + .addParameter( AnnotationMirror.class, "mirror" ) + .returns( gemBuilder ) + .addJavadoc( "Sets the annotation mirror\n" ) + .addJavadoc( "\n@param mirror the mirror which this gem represents" ) + .addJavadoc( + "\n\n@return the {@link $L} for this gem, representing {@link $L}", + gemBuilder.simpleName(), + gemInfo.getGemName() + ) + .build() ) + .addMethod( MethodSpec.methodBuilder( "build" ) + .addModifiers( Modifier.PUBLIC, Modifier.ABSTRACT ) + .returns( TypeVariableName.get( "T" ) ) + .addJavadoc( "The build method can be overridden in a custom implementation," ) + .addJavadoc( "\nwhich allows the user to define their own custom validation on the annotation." ) + .addJavadoc( "\n\n@return the representation of the annotation" ) + .build() ) + .build(); + } + + protected static TypeSpec createBuilderImplClassSpec(ClassName gemBuilderImpl, ClassName gemBuilder, + ClassName generatedGem, GemInfo gemInfo) { + Collection gemSetterMethods = new ArrayList<>( gemInfo.getGemValueInfos().size() ); + Collection fields = new ArrayList<>( gemInfo.getGemValueInfos().size() ); + for ( GemValueInfo gemValueInfo : gemInfo.getGemValueInfos() ) { + gemSetterMethods.add( MethodSpec.methodBuilder( "set" + Util.capitalize( gemValueInfo.getName() ) ) + .addAnnotation( Override.class ) + .addModifiers( Modifier.PUBLIC ) + .addParameter( createParameterSpec( gemValueInfo ) ) + .addStatement( "this.$1N = $1N", gemValueInfo.getName() ) + .addStatement( "return this" ) + .returns( gemBuilder ) + .build() ); + + fields.add( FieldSpec.builder( + gemValueParameterTypeName( gemValueInfo.getValueType() ), + gemValueInfo.getName(), + Modifier.PRIVATE + ).build() ); + + } + + return TypeSpec.classBuilder( gemBuilderImpl ) + .addSuperinterface( ParameterizedTypeName.get( gemBuilder, generatedGem ) ) + .addModifiers( Modifier.PRIVATE, Modifier.STATIC ) + .addFields( fields ) + .addField( AnnotationMirror.class, "mirror", Modifier.PRIVATE ) + .addMethods( gemSetterMethods ) + .addMethod( MethodSpec.methodBuilder( "setMirror" ) + .addModifiers( Modifier.PUBLIC ) + .addAnnotation( Override.class ) + .addParameter( AnnotationMirror.class, "mirror" ) + .addStatement( "this.$1N = $1N", "mirror" ) + .addStatement( "return this" ) + .returns( gemBuilder ) + .build() ) + .addMethod( MethodSpec.methodBuilder( "build" ) + .addModifiers( Modifier.PUBLIC ) + .addAnnotation( Override.class ) + .addStatement( "return new $T( this )", generatedGem ) + .returns( generatedGem ) + .build() ) + .build(); + } + + protected static CodeBlock constructorSetValueFields(GemInfo gemInfo) { + CodeBlock.Builder builder = CodeBlock.builder(); + for ( GemValueInfo gemValueInfo : gemInfo.getGemValueInfos() ) { + builder.addStatement( "this.$1N = builder.$1N", gemValueInfo.getName() ); + } + + return builder.build(); + } + + protected static CodeBlock constructorValidDefinition(GemInfo gemInfo) { + boolean first = true; + CodeBlock.Builder codeBuilder = CodeBlock.builder(); + for ( GemValueInfo gemValueInfo : gemInfo.getGemValueInfos() ) { + if ( first ) { + codeBuilder.addStatement( + "boolean isValid = this.$1N != null ? this.$1N.isValid() : false", + gemValueInfo.getName() + ); + first = false; + } + else { + codeBuilder.addStatement( + "isValid = isValid && this.$1N != null ? this.$1N.isValid() : false", + gemValueInfo.getName() + ); + } + } + + if ( first ) { + // If this is true then there is no intermediate variable created + codeBuilder.addStatement( "this.isValid = true" ); + } + else { + codeBuilder.addStatement( "this.isValid = isValid" ); + } + + + return codeBuilder.build(); + + } + + protected static MethodSpec gemBuildMethod(ClassName gemBuilder, GemInfo gemInfo) { + return MethodSpec.methodBuilder( "build" ) + .addModifiers( Modifier.PUBLIC, Modifier.STATIC ) + .addTypeVariable( TypeVariableName.get( "T" ) ) + .addParameter( AnnotationMirror.class, "mirror" ) + .addParameter( ParameterizedTypeName.get( gemBuilder, TypeVariableName.get( "T" ) ), "builder" ) + .returns( TypeVariableName.get( "T" ) ) + .addCode( CodeBlock.builder() + .add( "// return fast\n" ) + .beginControlFlow( "if ( mirror == null || builder == null )" ) + .addStatement( "return null" ) + .endControlFlow() + .add( getBuildMethodSetValueFromAnnotation( gemInfo ) ) + .addStatement( "builder.setMirror( mirror )" ) + .addStatement( "return builder.build()" ) + .build() ) + .build(); + } + + public static CodeBlock getBuildMethodSetValueFromAnnotation(GemInfo gemInfo) { + if ( gemInfo.getGemValueInfos().isEmpty() ) { + return CodeBlock.builder().build(); + } + CodeBlock.Builder codeBlockBuilder = CodeBlock.builder(); + codeBlockBuilder.add( "\n// fetch defaults from all defined values in the annotation type\n" ) + .addStatement( + "$T enclosed = $T.methodsIn( mirror.getAnnotationType().asElement().getEnclosedElements() )", + ParameterizedTypeName.get( List.class, ExecutableElement.class ), + ElementFilter.class + ) + .addStatement( + "$T defaultValues = new $T<>( enclosed.size() )", + ParameterizedTypeName.get( Map.class, String.class, AnnotationValue.class ), + HashMap.class + ) + .addStatement( + "enclosed.forEach( e -> defaultValues.put( e.getSimpleName().toString(), e.getDefaultValue() ) )" ) + .add( "\n// fetch all explicitly set annotation values in the annotation instance\n" ) + .addStatement( + "$T values = new $T<>( enclosed.size() )", + ParameterizedTypeName.get( Map.class, String.class, AnnotationValue.class ), + HashMap.class + ) + .addStatement( + "mirror.getElementValues().entrySet().forEach( e -> values.put( e.getKey().getSimpleName()" + + ".toString(), e.getValue() ) )" ) + .add( "\n// iterate and populate builder\n" ); + + + codeBlockBuilder.beginControlFlow( "for ( $T methodName : defaultValues.keySet() )", String.class ); + boolean first = true; + for ( GemValueInfo gemValueInfo : gemInfo.getGemValueInfos() ) { + if ( first ) { + first = false; + codeBlockBuilder.beginControlFlow( "if ( $S.equals( methodName ) )", gemValueInfo.getName() ); + } + else { + codeBlockBuilder.beginControlFlow( "else if ( $S.equals( methodName ) )", gemValueInfo.getName() ); + } + + codeBlockBuilder.add( createGemValueAndSetOnBuilderCodeBlock( gemValueInfo ) ) + .endControlFlow(); + } + + return codeBlockBuilder.endControlFlow() + .build(); + } + + protected static CodeBlock createGemValueAndSetOnBuilderCodeBlock(GemValueInfo gemValueInfo) { + GemValueType valueType = gemValueInfo.getValueType(); + String name = Util.capitalize( gemValueInfo.getName() ); + if ( valueType.isGem() ) { + ClassName gemType = ClassName.get( valueType.getPacakage(), valueType.getGemName() ); + if ( valueType.isArray() ) { + return CodeBlock.builder() + .addStatement( + "builder.set$N( $T.createArray( values.get( methodName ), defaultValues.get( methodName ), " + + "$T::instanceOn ) )", + name, + GEM_VALUE, + gemType + ) + .build(); + } + else { + return CodeBlock.builder() + .addStatement( + "builder.set$N( $T.create( values.get( methodName ), defaultValues.get( methodName ), " + + "$T::instanceOn ) )", + name, + GEM_VALUE, + gemType + ) + .build(); + } + } + else if ( valueType.isEnum() ) { + if ( valueType.isArray() ) { + return CodeBlock.builder() + .addStatement( + "builder.set$N( $T.createEnumArray( values.get( methodName ), " + + "defaultValues.get( methodName ) ) )", + name, + GEM_VALUE + ) + .build(); + } + else { + return CodeBlock.builder() + .addStatement( + "builder.set$N( $T.createEnum( values.get( methodName ), defaultValues.get( methodName ) ) )", + name, + GEM_VALUE + ) + .build(); + } + } + else { + ClassName type = ClassName.get( valueType.getPacakage(), valueType.getElementName() ); + if ( valueType.isArray() ) { + return CodeBlock.builder() + .addStatement( + "builder.set$N( $T.createArray( values.get( methodName ), defaultValues.get( methodName ), " + + "$T.class ) )", + name, + GEM_VALUE, + type + ) + .build(); + } + else { + return CodeBlock.builder() + .addStatement( + "builder.set$N( $T.create( values.get( methodName ), defaultValues.get( methodName ), " + + "$T.class ) )", + name, + GEM_VALUE, + type + ) + .build(); + } + } + } + + protected static ParameterSpec createParameterSpec(GemValueInfo gemValueInfo) { + return ParameterSpec.builder( + gemValueParameterTypeName( gemValueInfo.getValueType() ), + gemValueInfo.getName() + ).build(); + } + + protected static TypeName gemValueParameterTypeName(GemValueType type) { + TypeName base = ClassName.get( type.getPacakage(), type.getElementName() ); + TypeName finalType; + if ( type.isArray() ) { + finalType = ParameterizedTypeName.get( LIST, base ); + } + else { + finalType = base; + } + + return ParameterizedTypeName.get( GEM_VALUE, finalType ); + } +} diff --git a/processor/src/main/resources/org/mapstruct/tools/gem/processor/Gem.ftl b/processor/src/main/resources/org/mapstruct/tools/gem/processor/Gem.ftl deleted file mode 100644 index 0433d80..0000000 --- a/processor/src/main/resources/org/mapstruct/tools/gem/processor/Gem.ftl +++ /dev/null @@ -1,199 +0,0 @@ -<#-- - - Copyright MapStruct Authors. - - Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 - ---> -<#-- @ftlvariable name="gemInfo" type="org.mapstruct.tools.gem.processor.GemInfo" --> -package ${gemInfo.gemPackageName}; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.AbstractAnnotationValueVisitor8; -import javax.lang.model.util.ElementFilter; -import org.mapstruct.tools.gem.Gem; -import org.mapstruct.tools.gem.GemValue; - -<#list gemInfo.imports as importItem> -import ${importItem}; - - -public class ${gemInfo.gemName} implements Gem { - -<#list gemInfo.gemValueInfos as gemValueInfo> - private final GemValue<${gemValueInfo.valueType.name}> ${gemValueInfo.name}; - - private final boolean isValid; - private final AnnotationMirror mirror; - - private ${gemInfo.gemName}( ${gemInfo.builderImplName} builder ) { - <#list gemInfo.gemValueInfos as gemValueInfo> - this.${gemValueInfo.name} = builder.${gemValueInfo.name}; - - <#list gemInfo.gemValueInfos as gemValueInfo> - <#if gemValueInfo_index == 0>isValid = <#else> && ( this.${gemValueInfo.name} != null ? this.${gemValueInfo.name}.isValid() : false )<#if !(gemValueInfo_has_next)>; - - <#if gemInfo.gemValueInfos?size==0> - isValid = true; - - mirror = builder.mirror; - } - - <#list gemInfo.gemValueInfos as gemValueInfo> - /** - * accessor - * - * @return the {@link GemValue} for {@link ${gemInfo.gemName}#${gemValueInfo.name}} - */ - public GemValue<${gemValueInfo.valueType.name}> ${gemValueInfo.name}( ) { - return ${gemValueInfo.name}; - } - - - @Override - public AnnotationMirror mirror( ) { - return mirror; - } - - @Override - public boolean isValid( ) { - return isValid; - } - - public static ${gemInfo.gemName} instanceOn(Element element) { - return build( element, new ${gemInfo.builderImplName}() ); - } - - public static ${gemInfo.gemName} instanceOn(AnnotationMirror mirror ) { - return build( mirror, new ${gemInfo.builderImplName}() ); - } - - public static T build(Element element, ${gemInfo.builderName} builder) { - AnnotationMirror mirror = element.getAnnotationMirrors().stream() - .filter( a -> "${gemInfo.annotationFqn}".contentEquals( ( ( TypeElement )a.getAnnotationType().asElement() ).getQualifiedName() ) ) - .findAny() - .orElse( null ); - return build( mirror, builder ); - } - - public static T build(AnnotationMirror mirror, ${gemInfo.builderName} builder ) { - - // return fast - if ( mirror == null || builder == null ) { - return null; - } - <#if gemInfo.gemValueInfos?size != 0> - - // fetch defaults from all defined values in the annotation type - List enclosed = ElementFilter.methodsIn( mirror.getAnnotationType().asElement().getEnclosedElements() ); - Map defaultValues = new HashMap<>( enclosed.size() ); - enclosed.forEach( e -> defaultValues.put( e.getSimpleName().toString(), e.getDefaultValue() ) ); - - // fetch all explicitely set annotation values in the annotation instance - Map values = new HashMap<>( enclosed.size() ); - mirror.getElementValues().entrySet().forEach( e -> values.put( e.getKey().getSimpleName().toString(), e.getValue() ) ); - - // iterate and populate builder - for ( String methodName : defaultValues.keySet() ) { - - <#list gemInfo.gemValueInfos as gemValueInfo> - <#if gemValueInfo_index != 0>else if ( "${gemValueInfo.name}".equals( methodName ) ) { - <@compress single_line=true>builder.set${gemValueInfo.name?capitalize}( - <#if gemValueInfo.valueType.gem> - <#if gemValueInfo.valueType.array> - GemValue.createArray( values.get( methodName ), defaultValues.get( methodName ), ${gemValueInfo.valueType.gemName}::instanceOn ) - <#else> - GemValue.create( values.get( methodName ), defaultValues.get( methodName ), ${gemValueInfo.valueType.gemName}::instanceOn ) - - <#elseif gemValueInfo.valueType.enum> - <#if gemValueInfo.valueType.array> - GemValue.createEnumArray( values.get( methodName ), defaultValues.get( methodName ) ) - <#else> - GemValue.createEnum( values.get( methodName ), defaultValues.get( methodName ) ) - - <#else> - <#if gemValueInfo.valueType.array> - GemValue.createArray( values.get( methodName ), defaultValues.get( methodName ), ${gemValueInfo.valueType.elementName}.class ) - <#else> - GemValue.create( values.get( methodName ), defaultValues.get( methodName ), ${gemValueInfo.valueType.elementName}.class ) - - - ); - } - - } - - builder.setMirror( mirror ); - return builder.build(); - } - - /** - * A builder that can be implemented by the user to define custom logic e.g. in the - * build method, prior to creating the annotation gem. - */ - public interface ${gemInfo.builderName} { - - <#list gemInfo.gemValueInfos as gemValueInfo> - /** - * Sets the {@link GemValue} for {@link ${gemInfo.gemName}#${gemValueInfo.name}} - * - * @return the {@link ${gemInfo.builderName}} for this gem, representing {@link ${gemInfo.gemName}} - */ - ${gemInfo.builderName} set${gemValueInfo.name?capitalize}(GemValue<${gemValueInfo.valueType.name}> methodName ); - - - /** - * Sets the annotation mirror - * - * @param mirror the mirror which this gem represents - * - * @return the {@link ${gemInfo.builderName}} for this gem, representing {@link ${gemInfo.gemName}} - */ - ${gemInfo.builderName} setMirror( AnnotationMirror mirror ); - - /** - * The build method can be overriden in a custom custom implementation, which allows - * the user to define his own custom validation on the annotation. - * - * @return the representation of the annotation - */ - T build(); - } - - private static class ${gemInfo.builderImplName} implements ${gemInfo.builderName}<${gemInfo.gemName}> { - - <#list gemInfo.gemValueInfos as gemValueInfo> - private GemValue<${gemValueInfo.valueType.name}> ${gemValueInfo.name}; - - private AnnotationMirror mirror; - - <#list gemInfo.gemValueInfos as gemValueInfo> - public ${gemInfo.builderName} set${gemValueInfo.name?capitalize}(GemValue<${gemValueInfo.valueType.name}> ${gemValueInfo.name} ) { - this.${gemValueInfo.name} = ${gemValueInfo.name}; - return this; - } - - - public ${gemInfo.builderName} setMirror( AnnotationMirror mirror ) { - this.mirror = mirror; - return this; - } - - public ${gemInfo.gemName} build() { - return new ${gemInfo.gemName}( this ); - } - } - -} diff --git a/processor/src/test/resources/fixtures/org/mapstruct/tools/gem/processor/BuilderGem.java b/processor/src/test/resources/fixtures/org/mapstruct/tools/gem/processor/BuilderGem.java index a43f216..36c3219 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/tools/gem/processor/BuilderGem.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/tools/gem/processor/BuilderGem.java @@ -1,62 +1,48 @@ package org.mapstruct.tools.gem.processor; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.AbstractAnnotationValueVisitor8; -import javax.lang.model.util.ElementFilter; import org.mapstruct.tools.gem.Gem; -import org.mapstruct.tools.gem.GemValue; - public class BuilderGem implements Gem { - private final boolean isValid; + private final AnnotationMirror mirror; - private BuilderGem( BuilderImpl builder ) { - isValid = true; - mirror = builder.mirror; + private BuilderGem(BuilderImpl builder) { + this.mirror = builder.mirror; + + this.isValid = true; } @Override - public AnnotationMirror mirror( ) { - return mirror; + public AnnotationMirror mirror() { + return this.mirror; } @Override - public boolean isValid( ) { - return isValid; + public boolean isValid() { + return this.isValid; } - public static BuilderGem instanceOn(Element element) { + public static BuilderGem instanceOn(Element element) { return build( element, new BuilderImpl() ); } - public static BuilderGem instanceOn(AnnotationMirror mirror ) { + public static BuilderGem instanceOn(AnnotationMirror mirror) { return build( mirror, new BuilderImpl() ); } - public static T build(Element element, Builder_ builder) { + public static T build(Element element, Builder_ builder) { AnnotationMirror mirror = element.getAnnotationMirrors().stream() - .filter( a -> "org.mapstruct.tools.gem.test.Builder".contentEquals( ( ( TypeElement )a.getAnnotationType().asElement() ).getQualifiedName() ) ) - .findAny() - .orElse( null ); + .filter( a -> "org.mapstruct.tools.gem.test.Builder".contentEquals( ( ( TypeElement ) a.getAnnotationType().asElement() ).getQualifiedName() ) ) + .findAny() + .orElse( null ); return build( mirror, builder ); } - public static T build(AnnotationMirror mirror, Builder_ builder ) { - + public static T build(AnnotationMirror mirror, Builder_ builder) { // return fast if ( mirror == null || builder == null ) { return null; @@ -66,11 +52,10 @@ public static T build(AnnotationMirror mirror, Builder_ builder ) { } /** - * A builder that can be implemented by the user to define custom logic e.g. in the - * build method, prior to creating the annotation gem. + * A builder that can be implemented by the user to define custom logic + * e.g. in the build method, prior to creating the annotation gem. */ public interface Builder_ { - /** * Sets the annotation mirror * @@ -78,11 +63,11 @@ public interface Builder_ { * * @return the {@link Builder_} for this gem, representing {@link BuilderGem} */ - Builder_ setMirror( AnnotationMirror mirror ); + Builder_ setMirror(AnnotationMirror mirror); /** - * The build method can be overriden in a custom custom implementation, which allows - * the user to define his own custom validation on the annotation. + * The build method can be overridden in a custom implementation, + * which allows the user to define their own custom validation on the annotation. * * @return the representation of the annotation */ @@ -90,17 +75,17 @@ public interface Builder_ { } private static class BuilderImpl implements Builder_ { - private AnnotationMirror mirror; - public Builder_ setMirror( AnnotationMirror mirror ) { + @Override + public Builder_ setMirror(AnnotationMirror mirror) { this.mirror = mirror; return this; } + @Override public BuilderGem build() { return new BuilderGem( this ); } } - } diff --git a/processor/src/test/resources/fixtures/org/mapstruct/tools/gem/processor/SomeAnnotationGem.java b/processor/src/test/resources/fixtures/org/mapstruct/tools/gem/processor/SomeAnnotationGem.java index 1d030cc..a091217 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/tools/gem/processor/SomeAnnotationGem.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/tools/gem/processor/SomeAnnotationGem.java @@ -1,53 +1,68 @@ package org.mapstruct.tools.gem.processor; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; - import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.AbstractAnnotationValueVisitor8; import javax.lang.model.util.ElementFilter; import org.mapstruct.tools.gem.Gem; import org.mapstruct.tools.gem.GemValue; -import javax.lang.model.type.TypeMirror; - public class SomeAnnotationGem implements Gem { - private final GemValue myClassWithDefault; + private final GemValue myBooleanWithDefault; + private final GemValue myCharWithDefault; + private final GemValue myByteWithDefault; + private final GemValue mShortWithDefault; + private final GemValue myIntWithDefault; + private final GemValue myLongWithDefault; + private final GemValue myFloatWithDefault; + private final GemValue myDoubleWithDefault; + private final GemValue myStringWithDefault; + private final GemValue myEnumWithDefault; + private final GemValue myClass; + private final GemValue myBoolean; + private final GemValue myChar; + private final GemValue myByte; + private final GemValue myShort; + private final GemValue myInt; + private final GemValue myLong; + private final GemValue myFloat; + private final GemValue myDouble; + private final GemValue myString; + private final GemValue myEnum; + private final boolean isValid; + private final AnnotationMirror mirror; - private SomeAnnotationGem( BuilderImpl builder ) { + private SomeAnnotationGem(BuilderImpl builder) { this.myClassWithDefault = builder.myClassWithDefault; this.myBooleanWithDefault = builder.myBooleanWithDefault; this.myCharWithDefault = builder.myCharWithDefault; @@ -70,257 +85,258 @@ private SomeAnnotationGem( BuilderImpl builder ) { this.myDouble = builder.myDouble; this.myString = builder.myString; this.myEnum = builder.myEnum; - isValid = ( this.myClassWithDefault != null ? this.myClassWithDefault.isValid() : false ) - && ( this.myBooleanWithDefault != null ? this.myBooleanWithDefault.isValid() : false ) - && ( this.myCharWithDefault != null ? this.myCharWithDefault.isValid() : false ) - && ( this.myByteWithDefault != null ? this.myByteWithDefault.isValid() : false ) - && ( this.mShortWithDefault != null ? this.mShortWithDefault.isValid() : false ) - && ( this.myIntWithDefault != null ? this.myIntWithDefault.isValid() : false ) - && ( this.myLongWithDefault != null ? this.myLongWithDefault.isValid() : false ) - && ( this.myFloatWithDefault != null ? this.myFloatWithDefault.isValid() : false ) - && ( this.myDoubleWithDefault != null ? this.myDoubleWithDefault.isValid() : false ) - && ( this.myStringWithDefault != null ? this.myStringWithDefault.isValid() : false ) - && ( this.myEnumWithDefault != null ? this.myEnumWithDefault.isValid() : false ) - && ( this.myClass != null ? this.myClass.isValid() : false ) - && ( this.myBoolean != null ? this.myBoolean.isValid() : false ) - && ( this.myChar != null ? this.myChar.isValid() : false ) - && ( this.myByte != null ? this.myByte.isValid() : false ) - && ( this.myShort != null ? this.myShort.isValid() : false ) - && ( this.myInt != null ? this.myInt.isValid() : false ) - && ( this.myLong != null ? this.myLong.isValid() : false ) - && ( this.myFloat != null ? this.myFloat.isValid() : false ) - && ( this.myDouble != null ? this.myDouble.isValid() : false ) - && ( this.myString != null ? this.myString.isValid() : false ) - && ( this.myEnum != null ? this.myEnum.isValid() : false ); - mirror = builder.mirror; + this.mirror = builder.mirror; + + boolean isValid = this.myClassWithDefault != null ? this.myClassWithDefault.isValid() : false; + isValid = isValid && this.myBooleanWithDefault != null ? this.myBooleanWithDefault.isValid() : false; + isValid = isValid && this.myCharWithDefault != null ? this.myCharWithDefault.isValid() : false; + isValid = isValid && this.myByteWithDefault != null ? this.myByteWithDefault.isValid() : false; + isValid = isValid && this.mShortWithDefault != null ? this.mShortWithDefault.isValid() : false; + isValid = isValid && this.myIntWithDefault != null ? this.myIntWithDefault.isValid() : false; + isValid = isValid && this.myLongWithDefault != null ? this.myLongWithDefault.isValid() : false; + isValid = isValid && this.myFloatWithDefault != null ? this.myFloatWithDefault.isValid() : false; + isValid = isValid && this.myDoubleWithDefault != null ? this.myDoubleWithDefault.isValid() : false; + isValid = isValid && this.myStringWithDefault != null ? this.myStringWithDefault.isValid() : false; + isValid = isValid && this.myEnumWithDefault != null ? this.myEnumWithDefault.isValid() : false; + isValid = isValid && this.myClass != null ? this.myClass.isValid() : false; + isValid = isValid && this.myBoolean != null ? this.myBoolean.isValid() : false; + isValid = isValid && this.myChar != null ? this.myChar.isValid() : false; + isValid = isValid && this.myByte != null ? this.myByte.isValid() : false; + isValid = isValid && this.myShort != null ? this.myShort.isValid() : false; + isValid = isValid && this.myInt != null ? this.myInt.isValid() : false; + isValid = isValid && this.myLong != null ? this.myLong.isValid() : false; + isValid = isValid && this.myFloat != null ? this.myFloat.isValid() : false; + isValid = isValid && this.myDouble != null ? this.myDouble.isValid() : false; + isValid = isValid && this.myString != null ? this.myString.isValid() : false; + isValid = isValid && this.myEnum != null ? this.myEnum.isValid() : false; + this.isValid = isValid; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#myClassWithDefault} - */ - public GemValue myClassWithDefault( ) { - return myClassWithDefault; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#myClassWithDefault} + */ + public GemValue myClassWithDefault() { + return this.myClassWithDefault; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#myBooleanWithDefault} - */ - public GemValue myBooleanWithDefault( ) { - return myBooleanWithDefault; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#myBooleanWithDefault} + */ + public GemValue myBooleanWithDefault() { + return this.myBooleanWithDefault; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#myCharWithDefault} - */ - public GemValue myCharWithDefault( ) { - return myCharWithDefault; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#myCharWithDefault} + */ + public GemValue myCharWithDefault() { + return this.myCharWithDefault; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#myByteWithDefault} - */ - public GemValue myByteWithDefault( ) { - return myByteWithDefault; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#myByteWithDefault} + */ + public GemValue myByteWithDefault() { + return this.myByteWithDefault; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#mShortWithDefault} - */ - public GemValue mShortWithDefault( ) { - return mShortWithDefault; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#mShortWithDefault} + */ + public GemValue mShortWithDefault() { + return this.mShortWithDefault; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#myIntWithDefault} - */ - public GemValue myIntWithDefault( ) { - return myIntWithDefault; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#myIntWithDefault} + */ + public GemValue myIntWithDefault() { + return this.myIntWithDefault; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#myLongWithDefault} - */ - public GemValue myLongWithDefault( ) { - return myLongWithDefault; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#myLongWithDefault} + */ + public GemValue myLongWithDefault() { + return this.myLongWithDefault; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#myFloatWithDefault} - */ - public GemValue myFloatWithDefault( ) { - return myFloatWithDefault; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#myFloatWithDefault} + */ + public GemValue myFloatWithDefault() { + return this.myFloatWithDefault; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#myDoubleWithDefault} - */ - public GemValue myDoubleWithDefault( ) { - return myDoubleWithDefault; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#myDoubleWithDefault} + */ + public GemValue myDoubleWithDefault() { + return this.myDoubleWithDefault; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#myStringWithDefault} - */ - public GemValue myStringWithDefault( ) { - return myStringWithDefault; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#myStringWithDefault} + */ + public GemValue myStringWithDefault() { + return this.myStringWithDefault; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#myEnumWithDefault} - */ - public GemValue myEnumWithDefault( ) { - return myEnumWithDefault; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#myEnumWithDefault} + */ + public GemValue myEnumWithDefault() { + return this.myEnumWithDefault; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#myClass} - */ - public GemValue myClass( ) { - return myClass; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#myClass} + */ + public GemValue myClass() { + return this.myClass; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#myBoolean} - */ - public GemValue myBoolean( ) { - return myBoolean; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#myBoolean} + */ + public GemValue myBoolean() { + return this.myBoolean; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#myChar} - */ - public GemValue myChar( ) { - return myChar; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#myChar} + */ + public GemValue myChar() { + return this.myChar; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#myByte} - */ - public GemValue myByte( ) { - return myByte; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#myByte} + */ + public GemValue myByte() { + return this.myByte; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#myShort} - */ - public GemValue myShort( ) { - return myShort; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#myShort} + */ + public GemValue myShort() { + return this.myShort; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#myInt} - */ - public GemValue myInt( ) { - return myInt; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#myInt} + */ + public GemValue myInt() { + return this.myInt; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#myLong} - */ - public GemValue myLong( ) { - return myLong; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#myLong} + */ + public GemValue myLong() { + return this.myLong; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#myFloat} - */ - public GemValue myFloat( ) { - return myFloat; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#myFloat} + */ + public GemValue myFloat() { + return this.myFloat; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#myDouble} - */ - public GemValue myDouble( ) { - return myDouble; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#myDouble} + */ + public GemValue myDouble() { + return this.myDouble; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#myString} - */ - public GemValue myString( ) { - return myString; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#myString} + */ + public GemValue myString() { + return this.myString; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationGem#myEnum} - */ - public GemValue myEnum( ) { - return myEnum; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationGem#myEnum} + */ + public GemValue myEnum() { + return this.myEnum; } @Override - public AnnotationMirror mirror( ) { - return mirror; + public AnnotationMirror mirror() { + return this.mirror; } @Override - public boolean isValid( ) { - return isValid; + public boolean isValid() { + return this.isValid; } - public static SomeAnnotationGem instanceOn(Element element) { + public static SomeAnnotationGem instanceOn(Element element) { return build( element, new BuilderImpl() ); } - public static SomeAnnotationGem instanceOn(AnnotationMirror mirror ) { + public static SomeAnnotationGem instanceOn(AnnotationMirror mirror) { return build( mirror, new BuilderImpl() ); } - public static T build(Element element, Builder builder) { + public static T build(Element element, Builder builder) { AnnotationMirror mirror = element.getAnnotationMirrors().stream() - .filter( a -> "org.mapstruct.tools.gem.test.SomeAnnotation".contentEquals( ( ( TypeElement )a.getAnnotationType().asElement() ).getQualifiedName() ) ) - .findAny() - .orElse( null ); + .filter( a -> "org.mapstruct.tools.gem.test.SomeAnnotation".contentEquals( ( ( TypeElement ) a.getAnnotationType().asElement() ).getQualifiedName() ) ) + .findAny() + .orElse( null ); return build( mirror, builder ); } - public static T build(AnnotationMirror mirror, Builder builder ) { - + public static T build(AnnotationMirror mirror, Builder builder) { // return fast if ( mirror == null || builder == null ) { return null; @@ -331,78 +347,77 @@ public static T build(AnnotationMirror mirror, Builder builder ) { Map defaultValues = new HashMap<>( enclosed.size() ); enclosed.forEach( e -> defaultValues.put( e.getSimpleName().toString(), e.getDefaultValue() ) ); - // fetch all explicitely set annotation values in the annotation instance + // fetch all explicitly set annotation values in the annotation instance Map values = new HashMap<>( enclosed.size() ); mirror.getElementValues().entrySet().forEach( e -> values.put( e.getKey().getSimpleName().toString(), e.getValue() ) ); // iterate and populate builder for ( String methodName : defaultValues.keySet() ) { - if ( "myClassWithDefault".equals( methodName ) ) { - builder.setMyclasswithdefault( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), TypeMirror.class ) ); + builder.setMyClassWithDefault( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), TypeMirror.class ) ); } else if ( "myBooleanWithDefault".equals( methodName ) ) { - builder.setMybooleanwithdefault( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Boolean.class ) ); + builder.setMyBooleanWithDefault( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Boolean.class ) ); } else if ( "myCharWithDefault".equals( methodName ) ) { - builder.setMycharwithdefault( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Character.class ) ); + builder.setMyCharWithDefault( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Character.class ) ); } else if ( "myByteWithDefault".equals( methodName ) ) { - builder.setMybytewithdefault( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Byte.class ) ); + builder.setMyByteWithDefault( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Byte.class ) ); } else if ( "mShortWithDefault".equals( methodName ) ) { - builder.setMshortwithdefault( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Short.class ) ); + builder.setMShortWithDefault( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Short.class ) ); } else if ( "myIntWithDefault".equals( methodName ) ) { - builder.setMyintwithdefault( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Integer.class ) ); + builder.setMyIntWithDefault( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Integer.class ) ); } else if ( "myLongWithDefault".equals( methodName ) ) { - builder.setMylongwithdefault( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Integer.class ) ); + builder.setMyLongWithDefault( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Integer.class ) ); } else if ( "myFloatWithDefault".equals( methodName ) ) { - builder.setMyfloatwithdefault( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Float.class ) ); + builder.setMyFloatWithDefault( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Float.class ) ); } else if ( "myDoubleWithDefault".equals( methodName ) ) { - builder.setMydoublewithdefault( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Double.class ) ); + builder.setMyDoubleWithDefault( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Double.class ) ); } else if ( "myStringWithDefault".equals( methodName ) ) { - builder.setMystringwithdefault( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), String.class ) ); + builder.setMyStringWithDefault( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), String.class ) ); } else if ( "myEnumWithDefault".equals( methodName ) ) { - builder.setMyenumwithdefault( GemValue.createEnum( values.get( methodName ), defaultValues.get( methodName ) ) ); + builder.setMyEnumWithDefault( GemValue.createEnum( values.get( methodName ), defaultValues.get( methodName ) ) ); } else if ( "myClass".equals( methodName ) ) { - builder.setMyclass( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), TypeMirror.class ) ); + builder.setMyClass( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), TypeMirror.class ) ); } else if ( "myBoolean".equals( methodName ) ) { - builder.setMyboolean( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Boolean.class ) ); + builder.setMyBoolean( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Boolean.class ) ); } else if ( "myChar".equals( methodName ) ) { - builder.setMychar( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Character.class ) ); + builder.setMyChar( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Character.class ) ); } else if ( "myByte".equals( methodName ) ) { - builder.setMybyte( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Byte.class ) ); + builder.setMyByte( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Byte.class ) ); } else if ( "myShort".equals( methodName ) ) { - builder.setMyshort( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Short.class ) ); + builder.setMyShort( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Short.class ) ); } else if ( "myInt".equals( methodName ) ) { - builder.setMyint( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Integer.class ) ); + builder.setMyInt( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Integer.class ) ); } else if ( "myLong".equals( methodName ) ) { - builder.setMylong( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Integer.class ) ); + builder.setMyLong( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Integer.class ) ); } else if ( "myFloat".equals( methodName ) ) { - builder.setMyfloat( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Float.class ) ); + builder.setMyFloat( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Float.class ) ); } else if ( "myDouble".equals( methodName ) ) { - builder.setMydouble( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Double.class ) ); + builder.setMyDouble( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), Double.class ) ); } else if ( "myString".equals( methodName ) ) { - builder.setMystring( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), String.class ) ); + builder.setMyString( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), String.class ) ); } else if ( "myEnum".equals( methodName ) ) { - builder.setMyenum( GemValue.createEnum( values.get( methodName ), defaultValues.get( methodName ) ) ); + builder.setMyEnum( GemValue.createEnum( values.get( methodName ), defaultValues.get( methodName ) ) ); } } builder.setMirror( mirror ); @@ -410,164 +425,163 @@ else if ( "myEnum".equals( methodName ) ) { } /** - * A builder that can be implemented by the user to define custom logic e.g. in the - * build method, prior to creating the annotation gem. + * A builder that can be implemented by the user to define custom logic + * e.g. in the build method, prior to creating the annotation gem. */ public interface Builder { + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#myClassWithDefault} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMyClassWithDefault(GemValue myClassWithDefault); + + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#myBooleanWithDefault} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMyBooleanWithDefault(GemValue myBooleanWithDefault); + + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#myCharWithDefault} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMyCharWithDefault(GemValue myCharWithDefault); + + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#myByteWithDefault} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMyByteWithDefault(GemValue myByteWithDefault); + + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#mShortWithDefault} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMShortWithDefault(GemValue mShortWithDefault); - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#myClassWithDefault} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMyclasswithdefault(GemValue methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#myBooleanWithDefault} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMybooleanwithdefault(GemValue methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#myCharWithDefault} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMycharwithdefault(GemValue methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#myByteWithDefault} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMybytewithdefault(GemValue methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#mShortWithDefault} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMshortwithdefault(GemValue methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#myIntWithDefault} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMyintwithdefault(GemValue methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#myLongWithDefault} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMylongwithdefault(GemValue methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#myFloatWithDefault} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMyfloatwithdefault(GemValue methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#myDoubleWithDefault} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMydoublewithdefault(GemValue methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#myStringWithDefault} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMystringwithdefault(GemValue methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#myEnumWithDefault} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMyenumwithdefault(GemValue methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#myClass} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMyclass(GemValue methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#myBoolean} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMyboolean(GemValue methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#myChar} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMychar(GemValue methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#myByte} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMybyte(GemValue methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#myShort} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMyshort(GemValue methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#myInt} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMyint(GemValue methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#myLong} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMylong(GemValue methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#myFloat} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMyfloat(GemValue methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#myDouble} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMydouble(GemValue methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#myString} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMystring(GemValue methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationGem#myEnum} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} - */ - Builder setMyenum(GemValue methodName ); + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#myIntWithDefault} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMyIntWithDefault(GemValue myIntWithDefault); + + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#myLongWithDefault} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMyLongWithDefault(GemValue myLongWithDefault); + + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#myFloatWithDefault} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMyFloatWithDefault(GemValue myFloatWithDefault); + + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#myDoubleWithDefault} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMyDoubleWithDefault(GemValue myDoubleWithDefault); + + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#myStringWithDefault} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMyStringWithDefault(GemValue myStringWithDefault); + + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#myEnumWithDefault} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMyEnumWithDefault(GemValue myEnumWithDefault); + + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#myClass} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMyClass(GemValue myClass); + + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#myBoolean} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMyBoolean(GemValue myBoolean); + + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#myChar} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMyChar(GemValue myChar); + + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#myByte} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMyByte(GemValue myByte); + + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#myShort} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMyShort(GemValue myShort); + + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#myInt} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMyInt(GemValue myInt); + + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#myLong} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMyLong(GemValue myLong); + + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#myFloat} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMyFloat(GemValue myFloat); + + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#myDouble} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMyDouble(GemValue myDouble); + + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#myString} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMyString(GemValue myString); + + /** + * Sets the {@link GemValue} for {@link SomeAnnotationGem#myEnum} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} + */ + Builder setMyEnum(GemValue myEnum); /** * Sets the annotation mirror @@ -576,11 +590,11 @@ public interface Builder { * * @return the {@link Builder} for this gem, representing {@link SomeAnnotationGem} */ - Builder setMirror( AnnotationMirror mirror ); + Builder setMirror(AnnotationMirror mirror); /** - * The build method can be overriden in a custom custom implementation, which allows - * the user to define his own custom validation on the annotation. + * The build method can be overridden in a custom implementation, + * which allows the user to define their own custom validation on the annotation. * * @return the representation of the annotation */ @@ -588,149 +602,193 @@ public interface Builder { } private static class BuilderImpl implements Builder { - private GemValue myClassWithDefault; + private GemValue myBooleanWithDefault; + private GemValue myCharWithDefault; + private GemValue myByteWithDefault; + private GemValue mShortWithDefault; + private GemValue myIntWithDefault; + private GemValue myLongWithDefault; + private GemValue myFloatWithDefault; + private GemValue myDoubleWithDefault; + private GemValue myStringWithDefault; + private GemValue myEnumWithDefault; + private GemValue myClass; + private GemValue myBoolean; + private GemValue myChar; + private GemValue myByte; + private GemValue myShort; + private GemValue myInt; + private GemValue myLong; + private GemValue myFloat; + private GemValue myDouble; + private GemValue myString; + private GemValue myEnum; + private AnnotationMirror mirror; - public Builder setMyclasswithdefault(GemValue myClassWithDefault ) { + @Override + public Builder setMyClassWithDefault(GemValue myClassWithDefault) { this.myClassWithDefault = myClassWithDefault; return this; } - public Builder setMybooleanwithdefault(GemValue myBooleanWithDefault ) { + @Override + public Builder setMyBooleanWithDefault(GemValue myBooleanWithDefault) { this.myBooleanWithDefault = myBooleanWithDefault; return this; } - public Builder setMycharwithdefault(GemValue myCharWithDefault ) { + @Override + public Builder setMyCharWithDefault(GemValue myCharWithDefault) { this.myCharWithDefault = myCharWithDefault; return this; } - public Builder setMybytewithdefault(GemValue myByteWithDefault ) { + @Override + public Builder setMyByteWithDefault(GemValue myByteWithDefault) { this.myByteWithDefault = myByteWithDefault; return this; } - public Builder setMshortwithdefault(GemValue mShortWithDefault ) { + @Override + public Builder setMShortWithDefault(GemValue mShortWithDefault) { this.mShortWithDefault = mShortWithDefault; return this; } - public Builder setMyintwithdefault(GemValue myIntWithDefault ) { + @Override + public Builder setMyIntWithDefault(GemValue myIntWithDefault) { this.myIntWithDefault = myIntWithDefault; return this; } - public Builder setMylongwithdefault(GemValue myLongWithDefault ) { + @Override + public Builder setMyLongWithDefault(GemValue myLongWithDefault) { this.myLongWithDefault = myLongWithDefault; return this; } - public Builder setMyfloatwithdefault(GemValue myFloatWithDefault ) { + @Override + public Builder setMyFloatWithDefault(GemValue myFloatWithDefault) { this.myFloatWithDefault = myFloatWithDefault; return this; } - public Builder setMydoublewithdefault(GemValue myDoubleWithDefault ) { + @Override + public Builder setMyDoubleWithDefault(GemValue myDoubleWithDefault) { this.myDoubleWithDefault = myDoubleWithDefault; return this; } - public Builder setMystringwithdefault(GemValue myStringWithDefault ) { + @Override + public Builder setMyStringWithDefault(GemValue myStringWithDefault) { this.myStringWithDefault = myStringWithDefault; return this; } - public Builder setMyenumwithdefault(GemValue myEnumWithDefault ) { + @Override + public Builder setMyEnumWithDefault(GemValue myEnumWithDefault) { this.myEnumWithDefault = myEnumWithDefault; return this; } - public Builder setMyclass(GemValue myClass ) { + @Override + public Builder setMyClass(GemValue myClass) { this.myClass = myClass; return this; } - public Builder setMyboolean(GemValue myBoolean ) { + @Override + public Builder setMyBoolean(GemValue myBoolean) { this.myBoolean = myBoolean; return this; } - public Builder setMychar(GemValue myChar ) { + @Override + public Builder setMyChar(GemValue myChar) { this.myChar = myChar; return this; } - public Builder setMybyte(GemValue myByte ) { + @Override + public Builder setMyByte(GemValue myByte) { this.myByte = myByte; return this; } - public Builder setMyshort(GemValue myShort ) { + @Override + public Builder setMyShort(GemValue myShort) { this.myShort = myShort; return this; } - public Builder setMyint(GemValue myInt ) { + @Override + public Builder setMyInt(GemValue myInt) { this.myInt = myInt; return this; } - public Builder setMylong(GemValue myLong ) { + @Override + public Builder setMyLong(GemValue myLong) { this.myLong = myLong; return this; } - public Builder setMyfloat(GemValue myFloat ) { + @Override + public Builder setMyFloat(GemValue myFloat) { this.myFloat = myFloat; return this; } - public Builder setMydouble(GemValue myDouble ) { + @Override + public Builder setMyDouble(GemValue myDouble) { this.myDouble = myDouble; return this; } - public Builder setMystring(GemValue myString ) { + @Override + public Builder setMyString(GemValue myString) { this.myString = myString; return this; } - public Builder setMyenum(GemValue myEnum ) { + @Override + public Builder setMyEnum(GemValue myEnum) { this.myEnum = myEnum; return this; } - public Builder setMirror( AnnotationMirror mirror ) { + @Override + public Builder setMirror(AnnotationMirror mirror) { this.mirror = mirror; return this; } + @Override public SomeAnnotationGem build() { return new SomeAnnotationGem( this ); } } - } diff --git a/processor/src/test/resources/fixtures/org/mapstruct/tools/gem/processor/SomeAnnotationsGem.java b/processor/src/test/resources/fixtures/org/mapstruct/tools/gem/processor/SomeAnnotationsGem.java index 83ab83e..9a7e3fd 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/tools/gem/processor/SomeAnnotationsGem.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/tools/gem/processor/SomeAnnotationsGem.java @@ -1,73 +1,68 @@ package org.mapstruct.tools.gem.processor; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; - import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.AbstractAnnotationValueVisitor8; import javax.lang.model.util.ElementFilter; import org.mapstruct.tools.gem.Gem; import org.mapstruct.tools.gem.GemValue; - public class SomeAnnotationsGem implements Gem { - private final GemValue> value; + private final boolean isValid; + private final AnnotationMirror mirror; - private SomeAnnotationsGem( BuilderImpl builder ) { + private SomeAnnotationsGem(BuilderImpl builder) { this.value = builder.value; - isValid = ( this.value != null ? this.value.isValid() : false ); - mirror = builder.mirror; + this.mirror = builder.mirror; + + boolean isValid = this.value != null ? this.value.isValid() : false; + this.isValid = isValid; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeAnnotationsGem#value} - */ - public GemValue> value( ) { - return value; + * accessor + * + * @return the {@link GemValue} for {@link SomeAnnotationsGem#value} + */ + public GemValue> value() { + return this.value; } @Override - public AnnotationMirror mirror( ) { - return mirror; + public AnnotationMirror mirror() { + return this.mirror; } @Override - public boolean isValid( ) { - return isValid; + public boolean isValid() { + return this.isValid; } - public static SomeAnnotationsGem instanceOn(Element element) { + public static SomeAnnotationsGem instanceOn(Element element) { return build( element, new BuilderImpl() ); } - public static SomeAnnotationsGem instanceOn(AnnotationMirror mirror ) { + public static SomeAnnotationsGem instanceOn(AnnotationMirror mirror) { return build( mirror, new BuilderImpl() ); } - public static T build(Element element, Builder builder) { + public static T build(Element element, Builder builder) { AnnotationMirror mirror = element.getAnnotationMirrors().stream() - .filter( a -> "org.mapstruct.tools.gem.test.SomeAnnotations".contentEquals( ( ( TypeElement )a.getAnnotationType().asElement() ).getQualifiedName() ) ) - .findAny() - .orElse( null ); + .filter( a -> "org.mapstruct.tools.gem.test.SomeAnnotations".contentEquals( ( ( TypeElement ) a.getAnnotationType().asElement() ).getQualifiedName() ) ) + .findAny() + .orElse( null ); return build( mirror, builder ); } - public static T build(AnnotationMirror mirror, Builder builder ) { - + public static T build(AnnotationMirror mirror, Builder builder) { // return fast if ( mirror == null || builder == null ) { return null; @@ -78,13 +73,12 @@ public static T build(AnnotationMirror mirror, Builder builder ) { Map defaultValues = new HashMap<>( enclosed.size() ); enclosed.forEach( e -> defaultValues.put( e.getSimpleName().toString(), e.getDefaultValue() ) ); - // fetch all explicitely set annotation values in the annotation instance + // fetch all explicitly set annotation values in the annotation instance Map values = new HashMap<>( enclosed.size() ); mirror.getElementValues().entrySet().forEach( e -> values.put( e.getKey().getSimpleName().toString(), e.getValue() ) ); // iterate and populate builder for ( String methodName : defaultValues.keySet() ) { - if ( "value".equals( methodName ) ) { builder.setValue( GemValue.createArray( values.get( methodName ), defaultValues.get( methodName ), SomeAnnotationGem::instanceOn ) ); } @@ -94,17 +88,16 @@ public static T build(AnnotationMirror mirror, Builder builder ) { } /** - * A builder that can be implemented by the user to define custom logic e.g. in the - * build method, prior to creating the annotation gem. + * A builder that can be implemented by the user to define custom logic + * e.g. in the build method, prior to creating the annotation gem. */ public interface Builder { - - /** - * Sets the {@link GemValue} for {@link SomeAnnotationsGem#value} - * - * @return the {@link Builder} for this gem, representing {@link SomeAnnotationsGem} - */ - Builder setValue(GemValue> methodName ); + /** + * Sets the {@link GemValue} for {@link SomeAnnotationsGem#value} + * + * @return the {@link Builder} for this gem, representing {@link SomeAnnotationsGem} + */ + Builder setValue(GemValue> value); /** * Sets the annotation mirror @@ -113,11 +106,11 @@ public interface Builder { * * @return the {@link Builder} for this gem, representing {@link SomeAnnotationsGem} */ - Builder setMirror( AnnotationMirror mirror ); + Builder setMirror(AnnotationMirror mirror); /** - * The build method can be overriden in a custom custom implementation, which allows - * the user to define his own custom validation on the annotation. + * The build method can be overridden in a custom implementation, + * which allows the user to define their own custom validation on the annotation. * * @return the representation of the annotation */ @@ -125,23 +118,25 @@ public interface Builder { } private static class BuilderImpl implements Builder { - private GemValue> value; + private AnnotationMirror mirror; - public Builder setValue(GemValue> value ) { + @Override + public Builder setValue(GemValue> value) { this.value = value; return this; } - public Builder setMirror( AnnotationMirror mirror ) { + @Override + public Builder setMirror(AnnotationMirror mirror) { this.mirror = mirror; return this; } + @Override public SomeAnnotationsGem build() { return new SomeAnnotationsGem( this ); } } - } diff --git a/processor/src/test/resources/fixtures/org/mapstruct/tools/gem/processor/SomeArrayAnnotationGem.java b/processor/src/test/resources/fixtures/org/mapstruct/tools/gem/processor/SomeArrayAnnotationGem.java index dfb0a81..bbdc6f3 100644 --- a/processor/src/test/resources/fixtures/org/mapstruct/tools/gem/processor/SomeArrayAnnotationGem.java +++ b/processor/src/test/resources/fixtures/org/mapstruct/tools/gem/processor/SomeArrayAnnotationGem.java @@ -1,110 +1,108 @@ package org.mapstruct.tools.gem.processor; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; - import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.AbstractAnnotationValueVisitor8; import javax.lang.model.util.ElementFilter; import org.mapstruct.tools.gem.Gem; import org.mapstruct.tools.gem.GemValue; -import javax.lang.model.type.TypeMirror; - public class SomeArrayAnnotationGem implements Gem { - private final GemValue> myClassWithDefault; + private final GemValue> myBooleanWithDefault; + private final GemValue> myEnumWithDefault; + private final GemValue myAnnotation; + private final boolean isValid; + private final AnnotationMirror mirror; - private SomeArrayAnnotationGem( BuilderImpl builder ) { + private SomeArrayAnnotationGem(BuilderImpl builder) { this.myClassWithDefault = builder.myClassWithDefault; this.myBooleanWithDefault = builder.myBooleanWithDefault; this.myEnumWithDefault = builder.myEnumWithDefault; this.myAnnotation = builder.myAnnotation; - isValid = ( this.myClassWithDefault != null ? this.myClassWithDefault.isValid() : false ) - && ( this.myBooleanWithDefault != null ? this.myBooleanWithDefault.isValid() : false ) - && ( this.myEnumWithDefault != null ? this.myEnumWithDefault.isValid() : false ) - && ( this.myAnnotation != null ? this.myAnnotation.isValid() : false ); - mirror = builder.mirror; + this.mirror = builder.mirror; + + boolean isValid = this.myClassWithDefault != null ? this.myClassWithDefault.isValid() : false; + isValid = isValid && this.myBooleanWithDefault != null ? this.myBooleanWithDefault.isValid() : false; + isValid = isValid && this.myEnumWithDefault != null ? this.myEnumWithDefault.isValid() : false; + isValid = isValid && this.myAnnotation != null ? this.myAnnotation.isValid() : false; + this.isValid = isValid; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeArrayAnnotationGem#myClassWithDefault} - */ - public GemValue> myClassWithDefault( ) { - return myClassWithDefault; + * accessor + * + * @return the {@link GemValue} for {@link SomeArrayAnnotationGem#myClassWithDefault} + */ + public GemValue> myClassWithDefault() { + return this.myClassWithDefault; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeArrayAnnotationGem#myBooleanWithDefault} - */ - public GemValue> myBooleanWithDefault( ) { - return myBooleanWithDefault; + * accessor + * + * @return the {@link GemValue} for {@link SomeArrayAnnotationGem#myBooleanWithDefault} + */ + public GemValue> myBooleanWithDefault() { + return this.myBooleanWithDefault; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeArrayAnnotationGem#myEnumWithDefault} - */ - public GemValue> myEnumWithDefault( ) { - return myEnumWithDefault; + * accessor + * + * @return the {@link GemValue} for {@link SomeArrayAnnotationGem#myEnumWithDefault} + */ + public GemValue> myEnumWithDefault() { + return this.myEnumWithDefault; } /** - * accessor - * - * @return the {@link GemValue} for {@link SomeArrayAnnotationGem#myAnnotation} - */ - public GemValue myAnnotation( ) { - return myAnnotation; + * accessor + * + * @return the {@link GemValue} for {@link SomeArrayAnnotationGem#myAnnotation} + */ + public GemValue myAnnotation() { + return this.myAnnotation; } @Override - public AnnotationMirror mirror( ) { - return mirror; + public AnnotationMirror mirror() { + return this.mirror; } @Override - public boolean isValid( ) { - return isValid; + public boolean isValid() { + return this.isValid; } - public static SomeArrayAnnotationGem instanceOn(Element element) { + public static SomeArrayAnnotationGem instanceOn(Element element) { return build( element, new BuilderImpl() ); } - public static SomeArrayAnnotationGem instanceOn(AnnotationMirror mirror ) { + public static SomeArrayAnnotationGem instanceOn(AnnotationMirror mirror) { return build( mirror, new BuilderImpl() ); } - public static T build(Element element, Builder builder) { + public static T build(Element element, Builder builder) { AnnotationMirror mirror = element.getAnnotationMirrors().stream() - .filter( a -> "org.mapstruct.tools.gem.test.gem.SomeArrayAnnotation".contentEquals( ( ( TypeElement )a.getAnnotationType().asElement() ).getQualifiedName() ) ) - .findAny() - .orElse( null ); + .filter( a -> "org.mapstruct.tools.gem.test.gem.SomeArrayAnnotation".contentEquals( ( ( TypeElement ) a.getAnnotationType().asElement() ).getQualifiedName() ) ) + .findAny() + .orElse( null ); return build( mirror, builder ); } - public static T build(AnnotationMirror mirror, Builder builder ) { - + public static T build(AnnotationMirror mirror, Builder builder) { // return fast if ( mirror == null || builder == null ) { return null; @@ -115,24 +113,23 @@ public static T build(AnnotationMirror mirror, Builder builder ) { Map defaultValues = new HashMap<>( enclosed.size() ); enclosed.forEach( e -> defaultValues.put( e.getSimpleName().toString(), e.getDefaultValue() ) ); - // fetch all explicitely set annotation values in the annotation instance + // fetch all explicitly set annotation values in the annotation instance Map values = new HashMap<>( enclosed.size() ); mirror.getElementValues().entrySet().forEach( e -> values.put( e.getKey().getSimpleName().toString(), e.getValue() ) ); // iterate and populate builder for ( String methodName : defaultValues.keySet() ) { - if ( "myClassWithDefault".equals( methodName ) ) { - builder.setMyclasswithdefault( GemValue.createArray( values.get( methodName ), defaultValues.get( methodName ), TypeMirror.class ) ); + builder.setMyClassWithDefault( GemValue.createArray( values.get( methodName ), defaultValues.get( methodName ), TypeMirror.class ) ); } else if ( "myBooleanWithDefault".equals( methodName ) ) { - builder.setMybooleanwithdefault( GemValue.createArray( values.get( methodName ), defaultValues.get( methodName ), Boolean.class ) ); + builder.setMyBooleanWithDefault( GemValue.createArray( values.get( methodName ), defaultValues.get( methodName ), Boolean.class ) ); } else if ( "myEnumWithDefault".equals( methodName ) ) { - builder.setMyenumwithdefault( GemValue.createEnumArray( values.get( methodName ), defaultValues.get( methodName ) ) ); + builder.setMyEnumWithDefault( GemValue.createEnumArray( values.get( methodName ), defaultValues.get( methodName ) ) ); } else if ( "myAnnotation".equals( methodName ) ) { - builder.setMyannotation( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), SomeAnnotationGem::instanceOn ) ); + builder.setMyAnnotation( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), SomeAnnotationGem::instanceOn ) ); } } builder.setMirror( mirror ); @@ -140,38 +137,37 @@ else if ( "myAnnotation".equals( methodName ) ) { } /** - * A builder that can be implemented by the user to define custom logic e.g. in the - * build method, prior to creating the annotation gem. + * A builder that can be implemented by the user to define custom logic + * e.g. in the build method, prior to creating the annotation gem. */ public interface Builder { + /** + * Sets the {@link GemValue} for {@link SomeArrayAnnotationGem#myClassWithDefault} + * + * @return the {@link Builder} for this gem, representing {@link SomeArrayAnnotationGem} + */ + Builder setMyClassWithDefault(GemValue> myClassWithDefault); - /** - * Sets the {@link GemValue} for {@link SomeArrayAnnotationGem#myClassWithDefault} - * - * @return the {@link Builder} for this gem, representing {@link SomeArrayAnnotationGem} - */ - Builder setMyclasswithdefault(GemValue> methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeArrayAnnotationGem#myBooleanWithDefault} - * - * @return the {@link Builder} for this gem, representing {@link SomeArrayAnnotationGem} - */ - Builder setMybooleanwithdefault(GemValue> methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeArrayAnnotationGem#myEnumWithDefault} - * - * @return the {@link Builder} for this gem, representing {@link SomeArrayAnnotationGem} - */ - Builder setMyenumwithdefault(GemValue> methodName ); - - /** - * Sets the {@link GemValue} for {@link SomeArrayAnnotationGem#myAnnotation} - * - * @return the {@link Builder} for this gem, representing {@link SomeArrayAnnotationGem} - */ - Builder setMyannotation(GemValue methodName ); + /** + * Sets the {@link GemValue} for {@link SomeArrayAnnotationGem#myBooleanWithDefault} + * + * @return the {@link Builder} for this gem, representing {@link SomeArrayAnnotationGem} + */ + Builder setMyBooleanWithDefault(GemValue> myBooleanWithDefault); + + /** + * Sets the {@link GemValue} for {@link SomeArrayAnnotationGem#myEnumWithDefault} + * + * @return the {@link Builder} for this gem, representing {@link SomeArrayAnnotationGem} + */ + Builder setMyEnumWithDefault(GemValue> myEnumWithDefault); + + /** + * Sets the {@link GemValue} for {@link SomeArrayAnnotationGem#myAnnotation} + * + * @return the {@link Builder} for this gem, representing {@link SomeArrayAnnotationGem} + */ + Builder setMyAnnotation(GemValue myAnnotation); /** * Sets the annotation mirror @@ -180,11 +176,11 @@ public interface Builder { * * @return the {@link Builder} for this gem, representing {@link SomeArrayAnnotationGem} */ - Builder setMirror( AnnotationMirror mirror ); + Builder setMirror(AnnotationMirror mirror); /** - * The build method can be overriden in a custom custom implementation, which allows - * the user to define his own custom validation on the annotation. + * The build method can be overridden in a custom implementation, + * which allows the user to define their own custom validation on the annotation. * * @return the representation of the annotation */ @@ -192,41 +188,49 @@ public interface Builder { } private static class BuilderImpl implements Builder { - private GemValue> myClassWithDefault; + private GemValue> myBooleanWithDefault; + private GemValue> myEnumWithDefault; + private GemValue myAnnotation; + private AnnotationMirror mirror; - public Builder setMyclasswithdefault(GemValue> myClassWithDefault ) { + @Override + public Builder setMyClassWithDefault(GemValue> myClassWithDefault) { this.myClassWithDefault = myClassWithDefault; return this; } - public Builder setMybooleanwithdefault(GemValue> myBooleanWithDefault ) { + @Override + public Builder setMyBooleanWithDefault(GemValue> myBooleanWithDefault) { this.myBooleanWithDefault = myBooleanWithDefault; return this; } - public Builder setMyenumwithdefault(GemValue> myEnumWithDefault ) { + @Override + public Builder setMyEnumWithDefault(GemValue> myEnumWithDefault) { this.myEnumWithDefault = myEnumWithDefault; return this; } - public Builder setMyannotation(GemValue myAnnotation ) { + @Override + public Builder setMyAnnotation(GemValue myAnnotation) { this.myAnnotation = myAnnotation; return this; } - public Builder setMirror( AnnotationMirror mirror ) { + @Override + public Builder setMirror(AnnotationMirror mirror) { this.mirror = mirror; return this; } + @Override public SomeArrayAnnotationGem build() { return new SomeArrayAnnotationGem( this ); } } - }