You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2018/02/14 15:15:23 UTC

[isis] 07/13: ISIS-1816 refactoring Annotations + implement hierarchy search

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 <ah...@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
danhaywood@apache.org.