/**
* Copyright 2011-2015 John Ericksen
*
* 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.androidtransfuse.adapter;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableSet;
import java.util.List;
/**
* Utility singleton for AST classes.
*
* @author John Ericksen
*/
public final class ASTUtils {
private static final ASTType OBJECT_TYPE = new ASTStringType(Object.class.getCanonicalName());
private static final ASTUtils INSTANCE = new ASTUtils();
private ASTUtils() {
//private singleton constructor
}
public static ASTUtils getInstance() {
return INSTANCE;
}
/**
* Determines if the given ASTType inherits or extends from the given inheritable ASTType
*
* @param astType target
* @param inheritable inheritance target
* @return true if the given astType target inherits from the inheritable type with the given rules.
*/
public boolean inherits(ASTType astType, ASTType inheritable) {
if (astType == null) {
return false;
}
if(inheritable == null || inheritable.equals(OBJECT_TYPE)){
return true;
}
if (astType.equals(inheritable)) {
return true;
}
for (ASTType typeInterfaces : astType.getInterfaces()) {
if (inherits(typeInterfaces, inheritable)) {
return true;
}
}
return inherits(astType.getSuperClass(), inheritable);
}
public boolean isAnnotated(ASTType annotatationType, ImmutableSet<ASTAnnotation> annotations) {
return getAnnotation(annotatationType, annotations) != null;
}
public ASTAnnotation getAnnotation(ASTType annotationType, ImmutableSet<ASTAnnotation> annotations) {
return getAnnotation(annotationType.getName(), annotations);
}
public ASTAnnotation getAnnotation(Class annotationClass, ImmutableSet<ASTAnnotation> annotations) {
return getAnnotation(annotationClass.getCanonicalName(), annotations);
}
public ASTAnnotation getAnnotation(String annotationClassName, ImmutableSet<ASTAnnotation> annotations){
for (ASTAnnotation astAnnotation : annotations) {
if (astAnnotation.getASTType().getName().equals(annotationClassName)) {
return astAnnotation;
}
}
return null;
}
public boolean isAnnotated(ASTType type, Class annotationClass){
return isAnnotated(type, annotationClass.getCanonicalName());
}
public boolean isAnnotated(ASTType type, String annotationClassName){
return getAnnotation(annotationClassName, type.getAnnotations()) != null;
}
public ASTConstructor findConstructor(ASTType type, ASTType... parameters){
ASTConstructor foundConstructor = null;
for (ASTConstructor astConstructor : type.getConstructors()) {
if (parameterTypesMatch(astConstructor.getParameters(), parameters)) {
foundConstructor = astConstructor;
}
}
return foundConstructor;
}
public boolean constructorExists(ASTType type, final ASTType... parameters){
return FluentIterable.from(type.getConstructors()).anyMatch(new Predicate<ASTConstructor>() {
@Override
public boolean apply(ASTConstructor constructor) {
return parameterTypesMatch(constructor.getParameters(), parameters);
}
});
}
public ASTMethod findMethod(ASTType containingType, String methodName, ASTType... methodParameters) {
MethodSignature matchingSignature = new MethodSignature(methodName, methodParameters);
for (ASTMethod astMethod : containingType.getMethods()) {
if(new MethodSignature(astMethod).equals(matchingSignature)){
return astMethod;
}
}
return null;
}
public boolean methodExists(ASTType containingType, String methodName, ASTType... methodParameters) {
final MethodSignature matchingSignature = new MethodSignature(methodName, methodParameters);
return FluentIterable.from(containingType.getMethods())
.transform(new Function<ASTMethod, MethodSignature>() {
public MethodSignature apply(ASTMethod astMethod) {
return new MethodSignature(astMethod);
}
})
.anyMatch(new Predicate<MethodSignature>() {
public boolean apply(MethodSignature methodSignature) {
return methodSignature.equals(matchingSignature);
}
});
}
public ASTField findField(ASTType containingType, final String fieldName) {
for (ASTField astField : containingType.getFields()) {
if(astField.getName().equals(fieldName)) {
return astField;
}
}
return null;
}
public boolean fieldExists(ASTType containingType, final String fieldName) {
return FluentIterable.from(containingType.getFields())
.anyMatch(new Predicate<ASTField>() {
public boolean apply(ASTField astField) {
return astField.getName().equals(fieldName);
}
});
}
public boolean parameterTypesMatch(List<ASTParameter> parameters, ASTType... types){
boolean matches = true;
if(parameters.size() == types.length) {
for (int i = 0; i < parameters.size(); i++) {
if (!parameters.get(i).getASTType().equals(types[i])) {
matches = false;
}
}
}
else{
matches = false;
}
return matches;
}
}