private static void getFlattenedSuperTypeHierarchyRecursive( JClassType type, Set<JClassType> typesSeen) { if (typesSeen.contains(type)) { return; } typesSeen.add(type); // Check the interfaces JClassType[] intfs = type.getImplementedInterfaces(); for (JClassType intf : intfs) { typesSeen.addAll(getFlattenedSuperTypeHierarchy(intf)); } // Superclass JClassType superclass = type.getSuperclass(); if (superclass != null) { typesSeen.addAll(getFlattenedSuperTypeHierarchy(superclass)); } }
/** * Find an annotation on a type or on one of its superclasses or superinterfaces. * * <p>This provides semantics similar to that of {@link java.lang.annotation.Inherited} except * that it checks all types to which this type is assignable. {@code @Inherited} only works on * superclasses, not superinterfaces. * * <p>Annotations present on the superclass chain will be returned preferentially over those found * in the superinterface hierarchy. Note that the annotation does not need to be tagged with * {@code @Inherited} in order to be returned from the superclass chain. * * @param annotationType the type of the annotation to look for * @return the desired annotation or <code>null</code> if the annotation is not present in the * type's type hierarchy */ @Override public <T extends Annotation> T findAnnotationInTypeHierarchy(Class<T> annotationType) { // Remember what we've seen to avoid loops Set<JClassType> seen = new HashSet<JClassType>(); // Work queue List<JClassType> searchTypes = new LinkedList<JClassType>(); searchTypes.add(this); T toReturn = null; while (!searchTypes.isEmpty()) { JClassType current = searchTypes.remove(0); if (!seen.add(current)) { continue; } toReturn = current.getAnnotation(annotationType); if (toReturn != null) { /* * First one wins. It might be desirable at some point to have a * variation that can return more than one instance of the annotation if * it is present on multiple supertypes. */ break; } if (current.getSuperclass() != null) { // Add the superclass at the front of the list searchTypes.add(0, current.getSuperclass()); } // Superinterfaces Collections.addAll(searchTypes, current.getImplementedInterfaces()); } return toReturn; }