This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 0645ecde12e94d416bf858387eeca960cb0bc60a
Author: Andi Huber <ahu...@apache.org>
AuthorDate: Mon Jan 15 11:15:35 2018 +0100

    ISIS-1816 refactoring Annotations + implement hierarchy search
---
 .../isis/core/metamodel/facets/Annotations.java    | 103 ++++++++++++++++-----
 1 file changed, 80 insertions(+), 23 deletions(-)

diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/Annotations.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/Annotations.java
index 5a4a45e..3d24c77 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/Annotations.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/Annotations.java
@@ -26,13 +26,13 @@ import java.lang.reflect.Method;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
 import javax.validation.constraints.Pattern;
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 
-import com.google.common.collect.Lists;
-
 import org.apache.isis.applib.annotation.Collection;
 import org.apache.isis.applib.annotation.CollectionLayout;
 import org.apache.isis.applib.annotation.MemberOrder;
@@ -43,6 +43,8 @@ import org.apache.isis.core.commons.lang.ThrowableExtensions;
 import org.apache.isis.core.metamodel.exceptions.MetaModelException;
 import org.apache.isis.core.metamodel.methodutils.MethodScope;
 
+import com.google.common.collect.Lists;
+
 public final class Annotations  {
     
     private Annotations() {}
@@ -352,48 +354,103 @@ public final class Annotations  {
 
     /**
      * Searches for all no-arg methods or fields with a specified title, 
returning an
-     * {@link Evaluator} object that wraps either.  Will search up hierarchy 
also.
+     * {@link Evaluator} object that wraps either. Will search up hierarchy 
also, 
+     * including implemented interfaces.
      */
     public static <T extends Annotation> List<Evaluator<T>> getEvaluators(
             final Class<?> cls,
             final Class<T> annotationClass) {
-        List<Evaluator<T>> evaluators = Lists.newArrayList();
-        appendEvaluators(cls, annotationClass, evaluators);
+        final List<Evaluator<T>> evaluators = Lists.newArrayList();
+        visitEvaluators(cls, annotationClass, evaluators::add);
+        
+        // search implemented interfaces
+        final Class<?>[] interfaces = cls.getInterfaces();
+        for (final Class<?> iface : interfaces) {
+               visitEvaluators(iface, annotationClass, evaluators::add);
+        }
+        
         return evaluators;
     }
+    
+    /**
+     * Starting from the current class {@code cls}, we search down the 
inheritance 
+     * hierarchy (super class, super super class, ...), until we find 
+     * the first class that has at least a field or no-arg method with {@code 
annotationClass} annotation.
+     * <br/>
+     * In this hierarchy traversal, implemented interfaces are not processed.  
    
+     * @param cls
+     * @param annotationClass
+     * @return list of {@link Evaluator} that wraps each annotated member 
found on the class where 
+     * the search stopped, null otherwise
+     * 
+     * @since 2.0.0
+     */
+    public static <T extends Annotation> List<Evaluator<T>> 
findFirstInHierarchyHaving(
+            final Class<?> cls,
+            final Class<T> annotationClass) {
+       
+        final List<Evaluator<T>> evaluators = Lists.newArrayList();
+        visitEvaluatorsWhile(cls, annotationClass, __->evaluators.isEmpty(), 
evaluators::add);
+         
+         return evaluators;
+    }
 
-    private static <T extends Annotation> void appendEvaluators(
+    private static <T extends Annotation> void visitEvaluators(
+               final Class<?> cls,
+            final Class<T> annotationClass,
+            final Consumer<Evaluator<T>> visitor) {
+       visitEvaluatorsWhile(cls, annotationClass, __->true, visitor);
+    }
+    
+    private static <T extends Annotation> void visitEvaluatorsWhile(
             final Class<?> cls,
             final Class<T> annotationClass,
-            final List<Evaluator<T>> evaluators) {
+            Predicate<Class<?>> filter,
+            final Consumer<Evaluator<T>> visitor) {
+       
+       if(!filter.test(cls))
+               return; // stop visitation
+       
+       collectMethodEvaluators(cls, annotationClass, visitor);
+       collectFieldEvaluators(cls, annotationClass, visitor);
+        
+        // search super-classes
+        final Class<?> superclass = cls.getSuperclass();
+        if (superclass != null) {
+               visitEvaluatorsWhile(superclass, annotationClass, filter, 
visitor);
+        }
 
-        for (Method method : cls.getDeclaredMethods()) {
+    }
+    
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+       private static <T extends Annotation> void collectMethodEvaluators(
+            final Class<?> cls,
+            final Class<T> annotationClass,
+            final Consumer<Evaluator<T>> action) {
+       
+       for (Method method : cls.getDeclaredMethods()) {
             if(MethodScope.OBJECT.matchesScopeOf(method) &&
                     method.getParameterTypes().length == 0) {
                 final Annotation annotation = 
method.getAnnotation(annotationClass);
                 if(annotation != null) {
-                    evaluators.add(new MethodEvaluator(method, annotation));
+                       action.accept(new MethodEvaluator(method, annotation));
                 }
             }
         }
-        for (final Field field: cls.getDeclaredFields()) {
+    }
+    
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+       private static <T extends Annotation> void collectFieldEvaluators(
+            final Class<?> cls,
+            final Class<T> annotationClass,
+            final Consumer<Evaluator<T>> action) {
+       
+       for (final Field field: cls.getDeclaredFields()) {
             final Annotation annotation = field.getAnnotation(annotationClass);
             if(annotation != null) {
-                evaluators.add(new FieldEvaluator(field, annotation));
+               action.accept(new FieldEvaluator(field, annotation));
             }
         }
-
-        // search superclasses
-        final Class<?> superclass = cls.getSuperclass();
-        if (superclass != null) {
-            appendEvaluators(superclass, annotationClass, evaluators);
-        }
-
-        // search implemented interfaces
-        final Class<?>[] interfaces = cls.getInterfaces();
-        for (final Class<?> iface : interfaces) {
-            appendEvaluators(iface, annotationClass, evaluators);
-        }
     }
 
     public static abstract class Evaluator<T extends Annotation> {

-- 
To stop receiving notification emails like this one, please contact
danhayw...@apache.org.

Reply via email to