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

org.mapstruct.ap.spi.DefaultAccessorNamingStrategy Maven / Gradle / Ivy

/**
 *  Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
 *  and/or other contributors as indicated by the @authors tag. See the
 *  copyright.txt file in the distribution for a full listing of all
 *  contributors.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.mapstruct.ap.spi;

import java.beans.Introspector;

import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.SimpleElementVisitor6;
import javax.lang.model.util.SimpleTypeVisitor6;


/**
 * The default JavaBeans-compliant implementation of the {@link AccessorNamingStrategy} service provider interface.
 *
 * @author Christian Schuster, Sjaak Derken
 */
public class DefaultAccessorNamingStrategy implements AccessorNamingStrategy {

    @Override
    public MethodType getMethodType(ExecutableElement method) {
        if ( isGetterMethod( method ) ) {
            return MethodType.GETTER;
        }
        else if ( isSetterMethod( method ) ) {
            return MethodType.SETTER;
        }
        else if ( isAdderMethod( method ) ) {
            return MethodType.ADDER;
        }
        else if ( isPresenceCheckMethod( method ) ) {
            return MethodType.PRESENCE_CHECKER;
        }
        else {
            return MethodType.OTHER;
        }
    }

    /**
     * Returns {@code true} when the {@link ExecutableElement} is a getter method. A method is a getter when it starts
     * with 'get' and the return type is any type other than {@code void}, OR the getter starts with 'is' and the type
     * returned is a primitive or the wrapper for {@code boolean}. NOTE: the latter does strictly not comply to the bean
     * convention. The remainder of the name is supposed to reflect the property name.
     * 

* The calling MapStruct code guarantees that the given method has no arguments. * * @param method to be analyzed * * @return {@code true} when the method is a getter. */ public boolean isGetterMethod(ExecutableElement method) { String methodName = method.getSimpleName().toString(); boolean isNonBooleanGetterName = methodName.startsWith( "get" ) && methodName.length() > 3 && method.getReturnType().getKind() != TypeKind.VOID; boolean isBooleanGetterName = methodName.startsWith( "is" ) && methodName.length() > 2; boolean returnTypeIsBoolean = method.getReturnType().getKind() == TypeKind.BOOLEAN || "java.lang.Boolean".equals( getQualifiedName( method.getReturnType() ) ); return isNonBooleanGetterName || ( isBooleanGetterName && returnTypeIsBoolean ); } /** * Returns {@code true} when the {@link ExecutableElement} is a setter method. A setter starts with 'set'. The * remainder of the name is supposed to reflect the property name. *

* The calling MapStruct code guarantees that there's only one argument. * * @param method to be analyzed * @return {@code true} when the method is a setter. */ public boolean isSetterMethod(ExecutableElement method) { String methodName = method.getSimpleName().toString(); return methodName.startsWith( "set" ) && methodName.length() > 3; } /** * Returns {@code true} when the {@link ExecutableElement} is an adder method. An adder method starts with 'add'. * The remainder of the name is supposed to reflect the singular property name (as opposed to plural) of * its corresponding property. For example: property "children", but "addChild". See also * {@link #getElementName(ExecutableElement) }. *

* The calling MapStruct code guarantees there's only one argument. *

* * @param method to be analyzed * * @return {@code true} when the method is an adder method. */ public boolean isAdderMethod(ExecutableElement method) { String methodName = method.getSimpleName().toString(); return methodName.startsWith( "add" ) && methodName.length() > 3; } /** * Returns {@code true} when the {@link ExecutableElement} is a presence check method that checks if the * corresponding property is present (e.g. not null, not nil, ..). A presence check method method starts with * 'has'. The remainder of the name is supposed to reflect the property name. *

* The calling MapStruct code guarantees there's no argument and that the return type is boolean or a * {@link Boolean} * * @param method to be analyzed * @return {@code true} when the method is a presence check method. */ public boolean isPresenceCheckMethod(ExecutableElement method) { String methodName = method.getSimpleName().toString(); return methodName.startsWith( "has" ) && methodName.length() > 3; } /** * Analyzes the method (getter or setter) and derives the property name. * See {@link #isGetterMethod(ExecutableElement)} {@link #isSetterMethod(ExecutableElement)}. The first three * ('get' / 'set' scenario) characters are removed from the simple name, or the first 2 characters ('is' scenario). * From the remainder the first character is made into small case (to counter camel casing) and the result forms * the property name. * * @param getterOrSetterMethod getter or setter method. * * @return the property name. */ @Override public String getPropertyName(ExecutableElement getterOrSetterMethod) { String methodName = getterOrSetterMethod.getSimpleName().toString(); return Introspector.decapitalize( methodName.substring( methodName.startsWith( "is" ) ? 2 : 3 ) ); } /** * Adder methods are used to add elements to collections on a target bean. A typical use case is JPA. The * convention is that the element name will be equal to the remainder of the add method. Example: 'addElement' * element name will be 'element'. * * @param adderMethod getter or setter method. * * @return the property name. */ @Override public String getElementName(ExecutableElement adderMethod) { String methodName = adderMethod.getSimpleName().toString(); return Introspector.decapitalize( methodName.substring( 3 ) ); } /** * Helper method, to obtain the fully qualified name of a type. * * @param type input type * * @return fully qualified name of type when the type is a {@link DeclaredType}, null when otherwise. */ protected static String getQualifiedName(TypeMirror type) { DeclaredType declaredType = type.accept( new SimpleTypeVisitor6() { @Override public DeclaredType visitDeclared(DeclaredType t, Void p) { return t; } }, null ); if ( declaredType == null ) { return null; } TypeElement typeElement = declaredType.asElement().accept( new SimpleElementVisitor6() { @Override public TypeElement visitType(TypeElement e, Void p) { return e; } }, null ); return typeElement != null ? typeElement.getQualifiedName().toString() : null; } @Override public String getCollectionGetterName(String property) { throw new IllegalStateException( "This method is not intended to be called anymore and will be removed in " + "future versions." ); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy