All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mapstruct.ap.internal.gem.ElementGem Maven / Gradle / Ivy

There is a newer version: 1.6.3
Show newest version
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 );
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy