/**
* Copyright 2012-2014 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.util;
import java.beans.Introspector;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
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;
/**
* Provides functionality around {@link ExecutableElement}s.
*
* @author Gunnar Morling
*/
public class Executables {
private Executables() {
}
public static boolean isGetterMethod(ExecutableElement method) {
return isPublic( method ) && ( isNonBooleanGetterMethod( method ) || isBooleanGetterMethod( method ) );
}
private static boolean isNonBooleanGetterMethod(ExecutableElement method) {
String name = method.getSimpleName().toString();
return method.getParameters().isEmpty() &&
name.startsWith( "get" ) &&
name.length() > 3 &&
method.getReturnType().getKind() != TypeKind.VOID;
}
private static boolean isBooleanGetterMethod(ExecutableElement method) {
String name = method.getSimpleName().toString();
boolean returnTypeIsBoolean = method.getReturnType().getKind() == TypeKind.BOOLEAN ||
"java.lang.Boolean".equals( getQualifiedName( method.getReturnType() ) );
return method.getParameters().isEmpty() &&
name.startsWith( "is" ) &&
name.length() > 2 &&
returnTypeIsBoolean;
}
public static boolean isSetterMethod(ExecutableElement method) {
String name = method.getSimpleName().toString();
if ( isPublic( method ) && name.startsWith( "set" ) && name.length() > 3 && method.getParameters()
.size() == 1 && method.getReturnType().getKind() == TypeKind.VOID ) {
return true;
}
return false;
}
public static boolean isAdderMethod(ExecutableElement method) {
String name = method.getSimpleName().toString();
return isPublic( method ) &&
name.startsWith( "add" ) && name.length() > 3 &&
method.getParameters().size() == 1;
}
private static boolean isPublic(ExecutableElement method) {
return method.getModifiers().contains( Modifier.PUBLIC );
}
public static String getPropertyName(ExecutableElement getterOrSetterMethod) {
if ( isNonBooleanGetterMethod( getterOrSetterMethod ) ) {
return Introspector.decapitalize(
getterOrSetterMethod.getSimpleName().toString().substring( 3 )
);
}
else if ( isBooleanGetterMethod( getterOrSetterMethod ) ) {
return Introspector.decapitalize(
getterOrSetterMethod.getSimpleName().toString().substring( 2 )
);
}
else if ( isSetterMethod( getterOrSetterMethod ) ) {
return Introspector.decapitalize(
getterOrSetterMethod.getSimpleName().toString().substring( 3 )
);
}
throw new IllegalArgumentException( "Executable " + getterOrSetterMethod + " is not getter or setter method." );
}
/**
* Returns the 'element name' to which an adder method applies. If. e.g. an adder method is named
* {@code addChild(Child v)}, the element name would be 'Child'.
*/
public static String getElementNameForAdder(ExecutableElement adderMethod) {
if ( isAdderMethod( adderMethod ) ) {
return Introspector.decapitalize(
adderMethod.getSimpleName().toString().substring( 3 )
);
}
throw new IllegalArgumentException( "Executable " + adderMethod + " is not an adder method." );
}
public static Set<String> getPropertyNames(List<ExecutableElement> propertyAccessors) {
Set<String> propertyNames = new HashSet<String>();
for ( ExecutableElement executableElement : propertyAccessors ) {
propertyNames.add( getPropertyName( executableElement ) );
}
return propertyNames;
}
private static String getQualifiedName(TypeMirror type) {
DeclaredType declaredType = type.accept(
new SimpleTypeVisitor6<DeclaredType, Void>() {
@Override
public DeclaredType visitDeclared(DeclaredType t, Void p) {
return t;
}
},
null
);
if ( declaredType == null ) {
return null;
}
TypeElement typeElement = declaredType.asElement().accept(
new SimpleElementVisitor6<TypeElement, Void>() {
@Override
public TypeElement visitType(TypeElement e, Void p) {
return e;
}
},
null
);
return typeElement != null ? typeElement.getQualifiedName().toString() : null;
}
}