org.mapstruct.ap.internal.gem.ElementGem Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mapstruct-processor Show documentation
Show all versions of mapstruct-processor Show documentation
An annotation processor for generating type-safe bean mappers
package org.mapstruct.ap.internal.gem;
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 ElementGem implements Gem {
private final GemValue name;
private final GemValue> shorts;
private final GemValue> bytes;
private final GemValue> ints;
private final GemValue> longs;
private final GemValue> floats;
private final GemValue> doubles;
private final GemValue> chars;
private final GemValue> booleans;
private final GemValue> strings;
private final GemValue> classes;
private final GemValue enumClass;
private final GemValue> enums;
private final boolean isValid;
private final AnnotationMirror mirror;
private ElementGem( BuilderImpl builder ) {
this.name = builder.name;
this.shorts = builder.shorts;
this.bytes = builder.bytes;
this.ints = builder.ints;
this.longs = builder.longs;
this.floats = builder.floats;
this.doubles = builder.doubles;
this.chars = builder.chars;
this.booleans = builder.booleans;
this.strings = builder.strings;
this.classes = builder.classes;
this.enumClass = builder.enumClass;
this.enums = builder.enums;
isValid = ( this.name != null ? this.name.isValid() : false )
&& ( this.shorts != null ? this.shorts.isValid() : false )
&& ( this.bytes != null ? this.bytes.isValid() : false )
&& ( this.ints != null ? this.ints.isValid() : false )
&& ( this.longs != null ? this.longs.isValid() : false )
&& ( this.floats != null ? this.floats.isValid() : false )
&& ( this.doubles != null ? this.doubles.isValid() : false )
&& ( this.chars != null ? this.chars.isValid() : false )
&& ( this.booleans != null ? this.booleans.isValid() : false )
&& ( this.strings != null ? this.strings.isValid() : false )
&& ( this.classes != null ? this.classes.isValid() : false )
&& ( this.enumClass != null ? this.enumClass.isValid() : false )
&& ( this.enums != null ? this.enums.isValid() : false );
mirror = builder.mirror;
}
/**
* accessor
*
* @return the {@link GemValue} for {@link ElementGem#name}
*/
public GemValue name( ) {
return name;
}
/**
* accessor
*
* @return the {@link GemValue} for {@link ElementGem#shorts}
*/
public GemValue> shorts( ) {
return shorts;
}
/**
* accessor
*
* @return the {@link GemValue} for {@link ElementGem#bytes}
*/
public GemValue> bytes( ) {
return bytes;
}
/**
* accessor
*
* @return the {@link GemValue} for {@link ElementGem#ints}
*/
public GemValue> ints( ) {
return ints;
}
/**
* accessor
*
* @return the {@link GemValue} for {@link ElementGem#longs}
*/
public GemValue> longs( ) {
return longs;
}
/**
* accessor
*
* @return the {@link GemValue} for {@link ElementGem#floats}
*/
public GemValue> floats( ) {
return floats;
}
/**
* accessor
*
* @return the {@link GemValue} for {@link ElementGem#doubles}
*/
public GemValue> doubles( ) {
return doubles;
}
/**
* accessor
*
* @return the {@link GemValue} for {@link ElementGem#chars}
*/
public GemValue> chars( ) {
return chars;
}
/**
* accessor
*
* @return the {@link GemValue} for {@link ElementGem#booleans}
*/
public GemValue> booleans( ) {
return booleans;
}
/**
* accessor
*
* @return the {@link GemValue} for {@link ElementGem#strings}
*/
public GemValue> strings( ) {
return strings;
}
/**
* accessor
*
* @return the {@link GemValue} for {@link ElementGem#classes}
*/
public GemValue> classes( ) {
return classes;
}
/**
* accessor
*
* @return the {@link GemValue} for {@link ElementGem#enumClass}
*/
public GemValue enumClass( ) {
return enumClass;
}
/**
* accessor
*
* @return the {@link GemValue} for {@link ElementGem#enums}
*/
public GemValue> enums( ) {
return enums;
}
@Override
public AnnotationMirror mirror( ) {
return mirror;
}
@Override
public boolean isValid( ) {
return isValid;
}
public static ElementGem instanceOn(Element element) {
return build( element, new BuilderImpl() );
}
public static ElementGem instanceOn(AnnotationMirror mirror ) {
return build( mirror, new BuilderImpl() );
}
public static T build(Element element, Builder builder) {
AnnotationMirror mirror = element.getAnnotationMirrors().stream()
.filter( a -> "org.mapstruct.AnnotateWith.Element".contentEquals( ( ( TypeElement )a.getAnnotationType().asElement() ).getQualifiedName() ) )
.findAny()
.orElse( null );
return build( mirror, builder );
}
public static T build(AnnotationMirror mirror, Builder builder ) {
// return fast
if ( mirror == null || builder == null ) {
return null;
}
// 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() ) {
if ( "name".equals( methodName ) ) {
builder.setName( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), String.class ) );
}
else if ( "shorts".equals( methodName ) ) {
builder.setShorts( GemValue.createArray( values.get( methodName ), defaultValues.get( methodName ), Short.class ) );
}
else if ( "bytes".equals( methodName ) ) {
builder.setBytes( GemValue.createArray( values.get( methodName ), defaultValues.get( methodName ), Byte.class ) );
}
else if ( "ints".equals( methodName ) ) {
builder.setInts( GemValue.createArray( values.get( methodName ), defaultValues.get( methodName ), Integer.class ) );
}
else if ( "longs".equals( methodName ) ) {
builder.setLongs( GemValue.createArray( values.get( methodName ), defaultValues.get( methodName ), Long.class ) );
}
else if ( "floats".equals( methodName ) ) {
builder.setFloats( GemValue.createArray( values.get( methodName ), defaultValues.get( methodName ), Float.class ) );
}
else if ( "doubles".equals( methodName ) ) {
builder.setDoubles( GemValue.createArray( values.get( methodName ), defaultValues.get( methodName ), Double.class ) );
}
else if ( "chars".equals( methodName ) ) {
builder.setChars( GemValue.createArray( values.get( methodName ), defaultValues.get( methodName ), Character.class ) );
}
else if ( "booleans".equals( methodName ) ) {
builder.setBooleans( GemValue.createArray( values.get( methodName ), defaultValues.get( methodName ), Boolean.class ) );
}
else if ( "strings".equals( methodName ) ) {
builder.setStrings( GemValue.createArray( values.get( methodName ), defaultValues.get( methodName ), String.class ) );
}
else if ( "classes".equals( methodName ) ) {
builder.setClasses( GemValue.createArray( values.get( methodName ), defaultValues.get( methodName ), TypeMirror.class ) );
}
else if ( "enumClass".equals( methodName ) ) {
builder.setEnumclass( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), TypeMirror.class ) );
}
else if ( "enums".equals( methodName ) ) {
builder.setEnums( GemValue.createArray( values.get( methodName ), defaultValues.get( methodName ), String.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 Builder {
/**
* Sets the {@link GemValue} for {@link ElementGem#name}
*
* @return the {@link Builder} for this gem, representing {@link ElementGem}
*/
Builder setName(GemValue methodName );
/**
* Sets the {@link GemValue} for {@link ElementGem#shorts}
*
* @return the {@link Builder} for this gem, representing {@link ElementGem}
*/
Builder setShorts(GemValue> methodName );
/**
* Sets the {@link GemValue} for {@link ElementGem#bytes}
*
* @return the {@link Builder} for this gem, representing {@link ElementGem}
*/
Builder setBytes(GemValue> methodName );
/**
* Sets the {@link GemValue} for {@link ElementGem#ints}
*
* @return the {@link Builder} for this gem, representing {@link ElementGem}
*/
Builder setInts(GemValue> methodName );
/**
* Sets the {@link GemValue} for {@link ElementGem#longs}
*
* @return the {@link Builder} for this gem, representing {@link ElementGem}
*/
Builder setLongs(GemValue> methodName );
/**
* Sets the {@link GemValue} for {@link ElementGem#floats}
*
* @return the {@link Builder} for this gem, representing {@link ElementGem}
*/
Builder setFloats(GemValue> methodName );
/**
* Sets the {@link GemValue} for {@link ElementGem#doubles}
*
* @return the {@link Builder} for this gem, representing {@link ElementGem}
*/
Builder setDoubles(GemValue> methodName );
/**
* Sets the {@link GemValue} for {@link ElementGem#chars}
*
* @return the {@link Builder} for this gem, representing {@link ElementGem}
*/
Builder setChars(GemValue> methodName );
/**
* Sets the {@link GemValue} for {@link ElementGem#booleans}
*
* @return the {@link Builder} for this gem, representing {@link ElementGem}
*/
Builder setBooleans(GemValue> methodName );
/**
* Sets the {@link GemValue} for {@link ElementGem#strings}
*
* @return the {@link Builder} for this gem, representing {@link ElementGem}
*/
Builder setStrings(GemValue> methodName );
/**
* Sets the {@link GemValue} for {@link ElementGem#classes}
*
* @return the {@link Builder} for this gem, representing {@link ElementGem}
*/
Builder setClasses(GemValue> methodName );
/**
* Sets the {@link GemValue} for {@link ElementGem#enumClass}
*
* @return the {@link Builder} for this gem, representing {@link ElementGem}
*/
Builder setEnumclass(GemValue methodName );
/**
* Sets the {@link GemValue} for {@link ElementGem#enums}
*
* @return the {@link Builder} for this gem, representing {@link ElementGem}
*/
Builder setEnums(GemValue> methodName );
/**
* Sets the annotation mirror
*
* @param mirror the mirror which this gem represents
*
* @return the {@link Builder} for this gem, representing {@link ElementGem}
*/
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.
*
* @return the representation of the annotation
*/
T build();
}
private static class BuilderImpl implements Builder {
private GemValue name;
private GemValue> shorts;
private GemValue> bytes;
private GemValue> ints;
private GemValue> longs;
private GemValue> floats;
private GemValue> doubles;
private GemValue> chars;
private GemValue> booleans;
private GemValue> strings;
private GemValue> classes;
private GemValue enumClass;
private GemValue> enums;
private AnnotationMirror mirror;
public Builder setName(GemValue name ) {
this.name = name;
return this;
}
public Builder setShorts(GemValue> shorts ) {
this.shorts = shorts;
return this;
}
public Builder setBytes(GemValue> bytes ) {
this.bytes = bytes;
return this;
}
public Builder setInts(GemValue> ints ) {
this.ints = ints;
return this;
}
public Builder setLongs(GemValue> longs ) {
this.longs = longs;
return this;
}
public Builder setFloats(GemValue> floats ) {
this.floats = floats;
return this;
}
public Builder setDoubles(GemValue> doubles ) {
this.doubles = doubles;
return this;
}
public Builder setChars(GemValue> chars ) {
this.chars = chars;
return this;
}
public Builder setBooleans(GemValue> booleans ) {
this.booleans = booleans;
return this;
}
public Builder setStrings(GemValue> strings ) {
this.strings = strings;
return this;
}
public Builder setClasses(GemValue> classes ) {
this.classes = classes;
return this;
}
public Builder setEnumclass(GemValue enumClass ) {
this.enumClass = enumClass;
return this;
}
public Builder setEnums(GemValue> enums ) {
this.enums = enums;
return this;
}
public Builder setMirror( AnnotationMirror mirror ) {
this.mirror = mirror;
return this;
}
public ElementGem build() {
return new ElementGem( this );
}
}
}