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

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

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 XmlElementDeclGem implements Gem {

    private final GemValue scope;
    private final GemValue namespace;
    private final GemValue name;
    private final GemValue substitutionHeadNamespace;
    private final GemValue substitutionHeadName;
    private final GemValue defaultValue;
    private final boolean isValid;
    private final AnnotationMirror mirror;

    private XmlElementDeclGem( BuilderImpl builder ) {
        this.scope = builder.scope;
        this.namespace = builder.namespace;
        this.name = builder.name;
        this.substitutionHeadNamespace = builder.substitutionHeadNamespace;
        this.substitutionHeadName = builder.substitutionHeadName;
        this.defaultValue = builder.defaultValue;
        isValid = ( this.scope != null ? this.scope.isValid() : false )
               && ( this.namespace != null ? this.namespace.isValid() : false )
               && ( this.name != null ? this.name.isValid() : false )
               && ( this.substitutionHeadNamespace != null ? this.substitutionHeadNamespace.isValid() : false )
               && ( this.substitutionHeadName != null ? this.substitutionHeadName.isValid() : false )
               && ( this.defaultValue != null ? this.defaultValue.isValid() : false );
        mirror = builder.mirror;
    }

    /**
    * accessor
    *
    * @return the {@link GemValue} for {@link XmlElementDeclGem#scope}
    */
    public GemValue scope( ) {
        return scope;
    }

    /**
    * accessor
    *
    * @return the {@link GemValue} for {@link XmlElementDeclGem#namespace}
    */
    public GemValue namespace( ) {
        return namespace;
    }

    /**
    * accessor
    *
    * @return the {@link GemValue} for {@link XmlElementDeclGem#name}
    */
    public GemValue name( ) {
        return name;
    }

    /**
    * accessor
    *
    * @return the {@link GemValue} for {@link XmlElementDeclGem#substitutionHeadNamespace}
    */
    public GemValue substitutionHeadNamespace( ) {
        return substitutionHeadNamespace;
    }

    /**
    * accessor
    *
    * @return the {@link GemValue} for {@link XmlElementDeclGem#substitutionHeadName}
    */
    public GemValue substitutionHeadName( ) {
        return substitutionHeadName;
    }

    /**
    * accessor
    *
    * @return the {@link GemValue} for {@link XmlElementDeclGem#defaultValue}
    */
    public GemValue defaultValue( ) {
        return defaultValue;
    }

    @Override
    public AnnotationMirror mirror( ) {
        return mirror;
    }

    @Override
    public boolean isValid( ) {
        return isValid;
    }

    public static XmlElementDeclGem  instanceOn(Element element) {
        return build( element, new BuilderImpl() );
    }

    public static XmlElementDeclGem instanceOn(AnnotationMirror mirror ) {
        return build( mirror, new BuilderImpl() );
    }

    public static   T  build(Element element, Builder builder) {
        AnnotationMirror mirror = element.getAnnotationMirrors().stream()
            .filter( a ->  "javax.xml.bind.annotation.XmlElementDecl".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 ( "scope".equals( methodName ) ) {
                builder.setScope( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), TypeMirror.class ) );
            }
            else if ( "namespace".equals( methodName ) ) {
                builder.setNamespace( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), String.class ) );
            }
            else if ( "name".equals( methodName ) ) {
                builder.setName( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), String.class ) );
            }
            else if ( "substitutionHeadNamespace".equals( methodName ) ) {
                builder.setSubstitutionheadnamespace( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), String.class ) );
            }
            else if ( "substitutionHeadName".equals( methodName ) ) {
                builder.setSubstitutionheadname( GemValue.create( values.get( methodName ), defaultValues.get( methodName ), String.class ) );
            }
            else if ( "defaultValue".equals( methodName ) ) {
                builder.setDefaultvalue( GemValue.create( 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 XmlElementDeclGem#scope}
        *
        * @return the {@link Builder} for this gem, representing {@link XmlElementDeclGem}
        */
        Builder setScope(GemValue methodName );

       /**
        * Sets the {@link GemValue} for {@link XmlElementDeclGem#namespace}
        *
        * @return the {@link Builder} for this gem, representing {@link XmlElementDeclGem}
        */
        Builder setNamespace(GemValue methodName );

       /**
        * Sets the {@link GemValue} for {@link XmlElementDeclGem#name}
        *
        * @return the {@link Builder} for this gem, representing {@link XmlElementDeclGem}
        */
        Builder setName(GemValue methodName );

       /**
        * Sets the {@link GemValue} for {@link XmlElementDeclGem#substitutionHeadNamespace}
        *
        * @return the {@link Builder} for this gem, representing {@link XmlElementDeclGem}
        */
        Builder setSubstitutionheadnamespace(GemValue methodName );

       /**
        * Sets the {@link GemValue} for {@link XmlElementDeclGem#substitutionHeadName}
        *
        * @return the {@link Builder} for this gem, representing {@link XmlElementDeclGem}
        */
        Builder setSubstitutionheadname(GemValue methodName );

       /**
        * Sets the {@link GemValue} for {@link XmlElementDeclGem#defaultValue}
        *
        * @return the {@link Builder} for this gem, representing {@link XmlElementDeclGem}
        */
        Builder setDefaultvalue(GemValue methodName );

        /**
         * Sets the annotation mirror
         *
         * @param mirror the mirror which this gem represents
         *
         * @return the {@link Builder} for this gem, representing {@link XmlElementDeclGem}
         */
          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 scope;
        private GemValue namespace;
        private GemValue name;
        private GemValue substitutionHeadNamespace;
        private GemValue substitutionHeadName;
        private GemValue defaultValue;
        private AnnotationMirror mirror;

        public Builder setScope(GemValue scope ) {
            this.scope = scope;
            return this;
        }

        public Builder setNamespace(GemValue namespace ) {
            this.namespace = namespace;
            return this;
        }

        public Builder setName(GemValue name ) {
            this.name = name;
            return this;
        }

        public Builder setSubstitutionheadnamespace(GemValue substitutionHeadNamespace ) {
            this.substitutionHeadNamespace = substitutionHeadNamespace;
            return this;
        }

        public Builder setSubstitutionheadname(GemValue substitutionHeadName ) {
            this.substitutionHeadName = substitutionHeadName;
            return this;
        }

        public Builder setDefaultvalue(GemValue defaultValue ) {
            this.defaultValue = defaultValue;
            return this;
        }

        public Builder  setMirror( AnnotationMirror mirror ) {
            this.mirror = mirror;
            return this;
        }

        public XmlElementDeclGem build() {
            return new XmlElementDeclGem( this );
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy