package net.karneim.pojobuilder.analysis;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.util.Types;
import net.karneim.pojobuilder.GeneratePojoBuilder;
public class AnnotationHierarchyUtil {
private final Types types;
public AnnotationHierarchyUtil(Types types) {
this.types = types;
}
/**
* Filters the given set of annotation elements and returns only those that are 'triggering' the generation of a pojo
* builder, including, of course, the {@link GeneratePojoBuilder} annotation and all custom made meta annotations that
* are annotated with {@link GeneratePojoBuilder} or with another meta annotation.
*
* @param aAnnotations the set of annotation elements that will be filtered
* @param generatePojoBuilderAnnotation the type element representing the {@literal @}{@link GeneratePojoBuilder}
* annotation
* @return those annotations that are triggering the generation of a pojo builder
*/
public Set<TypeElement> filterTriggeringAnnotations(Set<? extends TypeElement> aAnnotations,
TypeElement generatePojoBuilderAnnotation) {
Set<TypeElement> result = new HashSet<TypeElement>();
for (TypeElement annoEl : aAnnotations) {
Set<TypeElement> hierarchy = getAnnotationHierarchy(annoEl);
if (containsAnnotation(hierarchy, generatePojoBuilderAnnotation)) {
result.add(annoEl);
}
}
return result;
}
private Set<TypeElement> getAnnotationHierarchy(TypeElement annoTypeEl) {
Set<TypeElement> result = new HashSet<TypeElement>();
getAnnotationHierarchy(annoTypeEl, result);
return result;
}
private void getAnnotationHierarchy(TypeElement annoTypeEl, Set<TypeElement> result) {
if (result.add(annoTypeEl)) {
List<? extends AnnotationMirror> annos = annoTypeEl.getAnnotationMirrors();
for (AnnotationMirror anno : annos) {
DeclaredType annoDeclType = anno.getAnnotationType();
Element annoEl = annoDeclType.asElement();
if (annoEl.getKind() == ElementKind.ANNOTATION_TYPE) {
getAnnotationHierarchy((TypeElement) annoEl, result);
}
}
}
}
private boolean containsAnnotation(Set<TypeElement> elems, TypeElement annoEl) {
for (TypeElement el : elems) {
if (types.isSameType(annoEl.asType(), el.asType())) {
return true;
}
}
return false;
}
}