package org.restler.spring.mvc;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

public class AnnotationUtils {

    public static boolean isAnnotated(Class<?> clazz, Class<? extends Annotation> annotationClass) {
        return findAnnotation(clazz, annotationClass, new HashSet<>()) != null;
    }

    public static boolean isAnnotated(Method method, Class<? extends Annotation> annotationClass) {
        for(Annotation annotation : method.getDeclaredAnnotations()) {
            if(findAnnotation(annotation.annotationType(), annotationClass, new HashSet<>()) != null) {
                return true;
            }
        }

        return false;
    }

    public static <R extends Annotation> R getAnnotation(Class<?> clazz, Class<R> annotationClass) {
        return (R)findAnnotation(clazz, annotationClass, new HashSet<>());
    }

    public static <R extends Annotation> R getAnnotation(Method method, Class<R> annotationClass) {
        Annotation resultAnnotation;
        for(Annotation annotation : method.getDeclaredAnnotations()) {

            if(annotation.annotationType().equals(annotationClass)) {
                return (R)annotation;
            }

            if((resultAnnotation = findAnnotation(annotation.annotationType(), annotationClass, new HashSet<>())) != null) {
                return (R)resultAnnotation;
            }
        }

        return null;
    }

    private static Annotation findAnnotation(Class<?> clazz, Class<? extends Annotation> annotationClass, Set<Class<?>> set) {
        if(clazz == null || set.contains(clazz) || clazz.equals(Object.class)) {
            return null;
        }

        set.add(clazz);

        Annotation result = findAnnotation(clazz.getSuperclass(), annotationClass, set);

        if(result != null) {
            return result;
        }

        Class<?>[] interfaces = clazz.getInterfaces();

        for(Class<?> interf : interfaces) {
            if(( result = findAnnotation(interf, annotationClass, set)) != null) {
                return result;
            }
        }

        for(Annotation annotation : clazz.getDeclaredAnnotations()) {
            if(annotation.annotationType().equals(annotationClass)) {
                return annotation;
            } else if ((result = findAnnotation(annotation.annotationType(), annotationClass, set)) != null) {
                return result;
            }
        }

        return null;
    }

}

@@ -99,16 +99,41 @@
 Method;%0A
+import java.util.Arrays;%0A
 import j
@@ -505,36 +505,29 @@
     
-for(Annotation annotation : 
+return Arrays.stream(
 meth
@@ -546,35 +546,39 @@
 edAnnotations())
- %7B%0A
+.%0A     
             if(f
@@ -572,20 +572,45 @@
         
- if(
+map((Annotation annotation)-%3E
 findAnno
@@ -682,132 +682,35 @@
 %3E())
- != null) %7B%0A                return true;%0A            %7D%0A        %7D%0A%0A        return false;%0A    %7D%0A%0A    public static %3CR extends 
+).%0A                filter((
 Anno
@@ -711,32 +711,26 @@
 ((Annotation
-%3E R getA
+ a
 nnotation(Cl
@@ -730,126 +730,59 @@
 tion
-(Class%3C?%3E clazz, Class%3CR%3E annotationClass) %7B%0A        return (R)findAnnotation(clazz, annotationClass, new HashSet%3C%3E())
+)-%3Eannotation != null).%0A                count() %3E 0
 ;%0A  
@@ -847,210 +847,33 @@
 ion(
-Method method, 
 Class%3C
-R%3E annotationClass) %7B%0A        Annotation resultAnnotation;%0A        for(Annotation annotation : method.getDeclaredAnnotations()) %7B%0A%0A            if(annotation.annotationType().equals(
+?%3E clazz, Class%3CR%3E 
 anno
@@ -876,33 +876,32 @@
 annotationClass)
-)
  %7B%0A             
@@ -891,32 +891,24 @@
 ) %7B%0A        
-        
 return (R)an
@@ -909,248 +909,63 @@
  (R)
-annotation;%0A            %7D%0A%0A            if((resultAnnotation = findAnnotation(annotation.annotationType(), annotationClass, new HashSet%3C%3E())) != null) %7B%0A                return (R)resultAnnotation;%0A            %7D%0A        %7D%0A%0A        return null
+findAnnotation(clazz, annotationClass, new HashSet%3C%3E())
 ;%0A  
@@ -1407,32 +1407,46 @@
     
-Class%3C?%3E%5B%5D interfaces = 
+Annotation findResult = Arrays.stream(
 claz
@@ -1462,27 +1462,35 @@
 rfaces()
-;%0A%0A
+).%0A        
         
 for(Clas
@@ -1481,19 +1481,20 @@
         
-for
+map(
 (Class%3C?
@@ -1505,55 +1505,82 @@
 terf
- : interfaces) %7B%0A            if(( result = find
+)-%3EfindAnnotation(interf, annotationClass, set)).%0A                filter((
 Anno
@@ -1581,32 +1581,24 @@
 ((Annotation
-(interf,
  annotationC
@@ -1600,76 +1600,155 @@
 tion
-Class, set)) != null) %7B%0A                return result;%0A            %7D
+)-%3Eannotation != null).%0A                findFirst().%0A                orElse(null);%0A%0A        if(findResult != null) %7B%0A            return findResult;
 %0A   
@@ -1767,12 +1767,8 @@
     
-for(
 Anno
@@ -1778,21 +1778,44 @@
 ion 
-annotation : 
+interfaceAnnotation = Arrays.stream(
 claz
@@ -1841,18 +1841,17 @@
 tions())
- %7B
+.
 %0A       
@@ -1855,19 +1855,52 @@
         
-if(
+    filter((Annotation annotation)-%3E
 annotati
@@ -1947,79 +1947,270 @@
 ss))
- %7B%0A                return annotation;%0A            %7D else if ((result = 
+.%0A                findFirst().%0A                orElse(null);%0A%0A        if(interfaceAnnotation != null) %7B%0A            return interfaceAnnotation;%0A        %7D%0A%0A        return Arrays.stream(clazz.getDeclaredAnnotations()).%0A                map((Annotation annotation)-%3E
 find
@@ -2271,27 +2271,17 @@
 s, set))
- != null) %7B
+.
 %0A       
@@ -2293,36 +2293,89 @@
     
-return result;%0A            %7D
+filter((Annotation annotation)-%3Eannotation != null).%0A                findFirst().
 %0A   
@@ -2375,35 +2375,32 @@
 ().%0A        
-%7D%0A%0A
         
 return null;
@@ -2383,34 +2383,35 @@
             
-return 
+orElse(
 null
+)
 ;%0A    %7D%0A%0A%7D%0A

Change cycles to streams.