Reputation: 157
So, my problem is the following, I'm using annotations to tag the methods of a class.
My main annotation is @Action
and I need a stronger annotation for specific methods that is @SpecificAction
.
All the methods annotated with @SpecificAction
must be annotated as @Action
.
My idea is to have @SpecificAction
annotated with @Action
.
@Action
[other irrelevant annotations]
public @interface SpecificAction{}
with
@SpecificAction
public void specificMethod(){}
I would expect specificMethod.isAnnotationPresent(Action.class)
to be true, but it isn't.
How could I make it so that the @Action
annotation is "inherited"?
Upvotes: 3
Views: 1293
Reputation: 5048
As @assylias's link says, the annotations can't be inherited, but you can use the composition, and search recursively your target annotation like this:
public static class AnnotationUtil {
private static <T extends Annotation> boolean containsAnnotation(Class<? extends Annotation> annotation, Class<T> annotationTypeTarget, Set<Class<? extends Annotation>> revised) {
boolean result = !revised.contains(annotation);
if (result && annotationTypeTarget != annotation) {
Set<Class<? extends Annotation>> nextRevised = new HashSet<>(revised);
nextRevised.add(annotation);
result = Arrays.stream(annotation.getAnnotations()).anyMatch(a -> containsAnnotation(a.annotationType(), annotationTypeTarget, nextRevised));
}
return result;
}
public static <T extends Annotation> boolean containsAnnotation(Class<? extends Annotation> annotation, Class<T> annotationTypeTarget) {
return containsAnnotation(annotation, annotationTypeTarget, Collections.emptySet());
}
public static <T extends Annotation> Map<Class<? extends Annotation>, ? extends Annotation> getAnnotations(Method method, Class<T> annotationTypeTarget) {
return Arrays.stream(method.getAnnotations()).filter(a -> containsAnnotation(a.annotationType(), annotationTypeTarget)).collect(Collectors.toMap(a -> a.annotationType(), Function.identity()));
}
}
If you have:
@Retention(RetentionPolicy.RUNTIME)
@interface Action {
}
@Action
@Retention(RetentionPolicy.RUNTIME)
@interface SpecificAction {
}
@Action
@Retention(RetentionPolicy.RUNTIME)
@interface ParticularAction {
}
public class Foo{
@SpecificAction
@ParticularAction
public void specificMethod() {
// ...
}
}
You can use like this: AnnotationUtil.getAnnotations(specificMethod, Action.class);
And this'll return a Map: {interface [email protected](), interface [email protected]()}
Upvotes: 3