package org.robobinding.codegen.apt.element; import java.util.Collections; import java.util.List; 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.TypeMirror; import javax.lang.model.util.ElementFilter; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; import org.robobinding.codegen.apt.MessagerLoggerFactory; import org.robobinding.codegen.apt.MethodElementFilter; import org.robobinding.codegen.apt.SetterElementFilter; import org.robobinding.codegen.apt.type.TypeMirrorWrapper; import org.robobinding.codegen.apt.type.WrappedDeclaredType; import org.robobinding.util.Lists; /** * @since 1.0 * @author Cheng Wei * */ public class WrappedTypeElement extends AbstractWrappedElement { private final TypeElement element; private final WrappedDeclaredType type; private final ElementWrapper wrapper; private final Types types; private final TypeMirrorWrapper typeWrapper; private final Elements elements; private final MessagerLoggerFactory loggerFactory; public WrappedTypeElement(TypeElement element, WrappedDeclaredType type, TypeMirrorWrapper typeWrapper, MessagerLoggerFactory loggerFactory, Elements elements, ElementWrapper wrapper, Types types) { super(element, typeWrapper, loggerFactory, elements); this.element = element; this.type = type; this.wrapper = wrapper; this.types = types; this.elements = elements; this.typeWrapper = typeWrapper; this.loggerFactory = loggerFactory; } public List<MethodElement> methodsRecursively(MethodElementFilter filter) { return methodsRecursively(filter, this); } private List<MethodElement> methodsRecursively(MethodElementFilter filter, WrappedTypeElement fromTypeElement) { if(fromTypeElement.isOfType(Object.class)) { return Collections.emptyList(); } List<ExecutableElement> methods = ElementFilter.methodsIn(fromTypeElement.element.getEnclosedElements()); List<MethodElement> result = Lists.newArrayList(); for (ExecutableElement method : methods) { MethodElement methodElement = wrapper.wrap(method); if(filter.include(methodElement)) { result.add(methodElement); } } result.addAll(methodsRecursively(filter, fromTypeElement.superclass())); return result; } public List<SetterElement> looseSetters(SetterElementFilter filter) { List<ExecutableElement> methods = ElementFilter.methodsIn(element.getEnclosedElements()); List<SetterElement> result = Lists.newArrayList(); for (ExecutableElement method : methods) { MethodElement methodElement = wrapper.wrap(method); if(!methodElement.isLooseSetter()) { continue; } SetterElement looseSetter = methodElement.asLooseSetter(); if(filter.include(looseSetter)) { result.add(looseSetter); } } return result; } private WrappedTypeElement superclass() { return typeElementOf((DeclaredType)element.getSuperclass()); } private WrappedTypeElement typeElementOf(DeclaredType declaredType) { WrappedDeclaredType type = typeWrapper.wrap(declaredType); TypeElement element = (TypeElement)types.asElement(declaredType); return new WrappedTypeElement(element, type, typeWrapper, loggerFactory, elements, wrapper, types); } public WrappedTypeElement findDirectSuperclassOf(Class<?> type) { WrappedTypeElement superclass = superclass(); if(superclass.isOfType(type)) { return superclass; } else { return null; } } public String qName() { return element.getQualifiedName().toString(); } public String binaryName() { return this.type.binaryName(); } public boolean isAssignableTo(Class<?> type) { return this.type.isAssignableTo(type); } public boolean isOfType(Class<?> type) { return this.type.isOfType(type); } @Override public boolean equals(Object other) { if (this == other) return true; if (!(other instanceof WrappedTypeElement)) return false; WrappedTypeElement that = (WrappedTypeElement)other; return type.equals(that.type); } @Override public int hashCode() { return type.hashCode(); } public boolean isNotConcreteClass() { return !isConcreteClass(); } public boolean isConcreteClass() { return element.getKind().isClass() && (!element.getModifiers().contains(Modifier.ABSTRACT)); } public WrappedTypeElement firstTypeArgument() { List<? extends TypeMirror> typeArguments = type.getTypeArguments(); DeclaredType firstTypeArgument = (DeclaredType)typeArguments.get(0); return typeElementOf(firstTypeArgument); } }