From 330fb581d374848e94ad247e565d7aa5b032f597 Mon Sep 17 00:00:00 2001
From: anttil <anttil>
Date: Wed, 5 Dec 2012 08:46:36 +0000
Subject: [PATCH] Add filtering by package name to class reference searching.

SVN: 27864
---
 .../api/server/json/util/ClassReferences.java |  41 ++++---
 .../server/json/ClassReferenceSearchTest.java | 102 +++++++++++-------
 .../systemtests/JsonAnnotationTest.java       | 102 +++---------------
 3 files changed, 105 insertions(+), 140 deletions(-)

diff --git a/openbis-common/source/java/ch/systemsx/cisd/openbis/common/api/server/json/util/ClassReferences.java b/openbis-common/source/java/ch/systemsx/cisd/openbis/common/api/server/json/util/ClassReferences.java
index a6cbb073b16..d68c44af19b 100644
--- a/openbis-common/source/java/ch/systemsx/cisd/openbis/common/api/server/json/util/ClassReferences.java
+++ b/openbis-common/source/java/ch/systemsx/cisd/openbis/common/api/server/json/util/ClassReferences.java
@@ -28,42 +28,51 @@ import java.util.Set;
 
 import org.reflections.Reflections;
 
+import com.google.common.base.Predicate;
+
 /**
- * A utility class that searches for classes and interfaces that are potentially converted in
- * JSON form.
+ * A utility class that searches for classes and interfaces that are potentially converted in JSON
+ * form.
  * 
  * @author anttil
  */
 public class ClassReferences
 {
 
-    private static Reflections ref = new Reflections("");
+    public static Reflections ref = new Reflections("ch");
 
     /**
      * Returns all the classes and interfaces that are referenced by the public methods declared by
-     * the given class. 
-     *
-     * A class considered to be referenced by a method if either of the following holds 
-     * 1) The class or its superclass or an interface it implements is mentioned in the signature of 
-     *    the method as an argument or as a return type either directly or as a type of an array
-     *    or a collection.
-     * 2) The class or its superclass or an interface it implements is used as a return type of a
-     *    getter method in a class referenced (note recursion here) by a method.
-     * 
-     *  However, the following kind of classes never considered to be referenced:
-     *  1) Anonymous classes
-     *  2) Classes that are not defined within package "ch."
+     * the given class. A class considered to be referenced by a method if either of the following
+     * holds 1) The class or its superclass or an interface it implements is mentioned in the
+     * signature of the method as an argument or as a return type either directly or as a type of an
+     * array or a collection. 2) The class or its superclass or an interface it implements is used
+     * as a return type of a getter method in a class referenced (note recursion here) by a method.
+     * However, the following kind of classes never considered to be referenced: 1) Anonymous
+     * classes 2) Classes that are not defined within package "ch."
      * 
      * @param clazz class whose references should be searched.
      * @returns referenced classes
      */
-    public static Collection<Class<?>> search(Class<?> clazz)
+    public static Collection<Class<?>> search(Class<?> clazz, Predicate<Class<?>> filter)
     {
         Set<Class<?>> results = new HashSet<Class<?>>();
         for (Method method : clazz.getDeclaredMethods())
         {
             searchIfMethodIsPublic(method, results);
         }
+        if (filter != null)
+        {
+            Set<Class<?>> filteredResults = new HashSet<Class<?>>();
+            for (Class<?> result : results)
+            {
+                if (filter.apply(result))
+                {
+                    filteredResults.add(result);
+                }
+            }
+            results = filteredResults;
+        }
         return results;
     }
 
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/openbis/common/api/server/json/ClassReferenceSearchTest.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/openbis/common/api/server/json/ClassReferenceSearchTest.java
index 455567ba8dc..06319cd425d 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/openbis/common/api/server/json/ClassReferenceSearchTest.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/openbis/common/api/server/json/ClassReferenceSearchTest.java
@@ -25,102 +25,126 @@ import java.util.List;
 
 import org.testng.annotations.Test;
 
+import com.google.common.base.Predicate;
+
 import ch.systemsx.cisd.openbis.common.api.server.json.util.ClassReferences;
 
 public class ClassReferenceSearchTest
 {
 
-    public class BaseClass 
+    private static Predicate<Class<?>> noFilter = new Predicate<Class<?>>()
+        {
+            @Override
+            public boolean apply(Class<?> arg0)
+            {
+                return true;
+            }
+        };
+
+    public class BaseClass
     {
     }
-    public interface BaseInterface 
+
+    public interface BaseInterface
     {
     }
-    public class SimpleClass extends BaseClass 
+
+    public class SimpleClass extends BaseClass
     {
     }
-    public class AnotherSimpleClass implements BaseInterface 
+
+    public class AnotherSimpleClass implements BaseInterface
     {
     }
-    public class NotExtendedSimpleClass 
+
+    public class NotExtendedSimpleClass
     {
     }
-    
 
-    public interface SimpleInterface 
+    public interface SimpleInterface
     {
         public AnotherSimpleClass getSimple(SimpleClass argument);
     }
+
     @Test
-    public void findsDirectSimpleReferences() 
+    public void findsDirectSimpleReferences()
     {
-        Class<?>[] expected = {SimpleClass.class, AnotherSimpleClass.class};
-        Collection<Class<?>> result = ClassReferences.search(SimpleInterface.class);
+        Class<?>[] expected =
+            { SimpleClass.class, AnotherSimpleClass.class };
+        Collection<Class<?>> result = ClassReferences.search(SimpleInterface.class, noFilter);
         assertThat(result, hasItems(expected));
         assertThat(result.size(), is(expected.length));
     }
- 
-    
-    public interface CollectionInterface 
+
+    public interface CollectionInterface
     {
         Collection<SimpleClass> getCollection(List<AnotherSimpleClass> argument);
     }
+
     @Test
-    public void findsReferencesInCollections() 
+    public void findsReferencesInCollections()
     {
-        Class<?>[] expected = {SimpleClass.class, AnotherSimpleClass.class};
-        Collection<Class<?>> result = ClassReferences.search(CollectionInterface.class);
+        Class<?>[] expected =
+            { SimpleClass.class, AnotherSimpleClass.class };
+        Collection<Class<?>> result = ClassReferences.search(CollectionInterface.class, noFilter);
         assertThat(result, hasItems(expected));
         assertThat(result.size(), is(expected.length));
     }
 
-    
-    public interface ArrayInterface 
+    public interface ArrayInterface
     {
         SimpleClass[] getArray(AnotherSimpleClass[] argument);
     }
+
     @Test
-    public void findsReferencesInArrays() 
+    public void findsReferencesInArrays()
     {
-        Class<?>[] expected = {SimpleClass.class, AnotherSimpleClass.class};
-        Collection<Class<?>> result = ClassReferences.search(ArrayInterface.class);
+        Class<?>[] expected =
+            { SimpleClass.class, AnotherSimpleClass.class };
+        Collection<Class<?>> result = ClassReferences.search(ArrayInterface.class, noFilter);
         assertThat(result, hasItems(expected));
         assertThat(result.size(), is(expected.length));
     }
-    
-    public interface SubTypeInterface 
+
+    public interface SubTypeInterface
     {
-       public BaseClass getBaseclass(BaseInterface argument); 
+        public BaseClass getBaseclass(BaseInterface argument);
     }
+
     @Test
-    public void findsSubTypesOfReferencedClassesAndInterfaces() 
-    {
-        Class<?>[] expected = {SimpleClass.class, 
-                               AnotherSimpleClass.class,
-                               BaseClass.class,
-                               BaseInterface.class};
-        Collection<Class<?>> result = ClassReferences.search(SubTypeInterface.class);
+    public void findsSubTypesOfReferencedClassesAndInterfaces()
+    {
+        Class<?>[] expected =
+            { SimpleClass.class,
+                    AnotherSimpleClass.class,
+                    BaseClass.class,
+                    BaseInterface.class };
+        Collection<Class<?>> result = ClassReferences.search(SubTypeInterface.class, noFilter);
         assertThat(result, hasItems(expected));
         assertThat(result.size(), is(expected.length));
     }
-    
-    
-    public interface GetterInterface 
+
+    public interface GetterInterface
     {
         public void method(InterfaceWithOneGetter argument);
     }
-    public interface InterfaceWithOneGetter 
+
+    public interface InterfaceWithOneGetter
     {
         public BaseClass doSomething();
+
         public BaseInterface getCalculatedValue(BaseInterface argument);
+
         public NotExtendedSimpleClass getSimpleClass();
     }
+
     @Test
-    public void searchesOnlyGettersOfReferencedClasses() 
+    public void searchesOnlyGettersOfReferencedClasses()
     {
-        Class<?>[] expected = {InterfaceWithOneGetter.class, 
-                               NotExtendedSimpleClass.class};
-        Collection<Class<?>> result = ClassReferences.search(GetterInterface.class);
+        Class<?>[] expected =
+            { InterfaceWithOneGetter.class,
+                    NotExtendedSimpleClass.class };
+        Collection<Class<?>> result = ClassReferences.search(GetterInterface.class, noFilter);
         assertThat(result, hasItems(expected));
         assertThat(result.size(), is(expected.length));
     }
diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/screening/systemtests/JsonAnnotationTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/screening/systemtests/JsonAnnotationTest.java
index 2db9fa9cbf0..3b940da0cc2 100644
--- a/screening/sourceTest/java/ch/systemsx/cisd/openbis/screening/systemtests/JsonAnnotationTest.java
+++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/screening/systemtests/JsonAnnotationTest.java
@@ -25,12 +25,10 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 
-import org.reflections.Reflections;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
-import com.fasterxml.jackson.annotation.JsonSubTypes;
-import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
+import com.google.common.base.Predicate;
 
 import ch.systemsx.cisd.base.annotation.JsonObject;
 import ch.systemsx.cisd.openbis.common.api.server.json.JsonUniqueCheckIgnore;
@@ -53,26 +51,33 @@ public class JsonAnnotationTest
 {
     private Collection<Class<?>> allJsonClasses = new HashSet<Class<?>>();
 
-    private Reflections reflections = new Reflections("");
-
     private Collection<Class<?>> empty = Collections.emptySet();
 
     private Map<String, Collection<Class<?>>> emptyMap =
             new HashMap<String, Collection<Class<?>>>();
 
     // Used by TestNG
+    @SuppressWarnings("unused")
     @BeforeClass
     private void findAllClassesUsedByJsonRpcApi()
     {
         Class<?>[] jsonRpcInterfaces =
-                    { IDssServiceRpcGeneric.class, IScreeningApiServer.class,
-                            IGeneralInformationChangingService.class,
-                            IGeneralInformationService.class, IWebInformationService.class,
-                            IQueryApiServer.class, IDssServiceRpcScreening.class };
+            { IDssServiceRpcGeneric.class, IScreeningApiServer.class,
+                    IGeneralInformationChangingService.class,
+                    IGeneralInformationService.class, IWebInformationService.class,
+                    IQueryApiServer.class, IDssServiceRpcScreening.class };
 
         for (Class<?> jsonClass : jsonRpcInterfaces)
         {
-            allJsonClasses.addAll(ClassReferences.search(jsonClass));
+            allJsonClasses.addAll(ClassReferences.search(jsonClass, new Predicate<Class<?>>()
+                {
+                    @Override
+                    public boolean apply(Class<?> clazz)
+                    {
+                        return (clazz.getPackage().getName().startsWith(
+                                "ch.systemsx.sybit.imageviewer") == false);
+                    }
+                }));
         }
     }
 
@@ -87,7 +92,7 @@ public class JsonAnnotationTest
     public void jsonTypeNamesAreUnique()
     {
         Map<String, Collection<Class<?>>> names = new HashMap<String, Collection<Class<?>>>();
-        for (Class<?> clazz : reflections.getTypesAnnotatedWith(JsonObject.class))
+        for (Class<?> clazz : ClassReferences.ref.getTypesAnnotatedWith(JsonObject.class))
         {
             if (clazz.getAnnotation(JsonUniqueCheckIgnore.class) != null)
             {
@@ -101,50 +106,11 @@ public class JsonAnnotationTest
         assertThat(duplicatedValuesIn(names), is(emptyMap));
     }
 
-    @Test(enabled = false)
-    public void jsonClassesWithSubClassesAreAnnotatedWithJsonSubTypes()
-    {
-        Collection<Class<?>> classesWithoutAnnotation = new HashSet<Class<?>>();
-        for (Class<?> clazz : allJsonClasses)
-        {
-            if (clazz.isEnum() == false && reflections.getSubTypesOf(clazz).isEmpty() == false)
-            {
-                if (clazz.getAnnotation(JsonSubTypes.class) == null)
-                {
-                    classesWithoutAnnotation.add(clazz);
-                }
-            }
-        }
-        assertThat(classesWithoutAnnotation, is(empty));
-    }
-
-    @Test(enabled = false)
-    public void jsonSubTypesAnnotationsContainAllDirectSubClasses()
-    {
-        Map<String, Collection<Class<?>>> missingSubtypeAnnotations =
-                new PrettyPrintingCollectionMap<String, Collection<Class<?>>>();
-        for (Class<?> main : reflections.getTypesAnnotatedWith(JsonSubTypes.class))
-        {
-            Collection<Class<?>> annotatedSubtypes = getAnnotatedSubTypes(main);
-
-            for (Class<?> subtype : reflections.getSubTypesOf(main))
-            {
-                if (subtypeIsMissing(main, subtype, annotatedSubtypes))
-                {
-                    addValueToCollectionMap(missingSubtypeAnnotations, main.getCanonicalName(),
-                            subtype);
-                }
-            }
-        }
-
-        assertThat(missingSubtypeAnnotations, is(emptyMap));
-    }
-
     private static class PrettyPrintingCollectionMap<K, V extends Collection<?>> extends
             HashMap<K, V>
     {
 
-        private static final long serialVersionUID = 2615134692782526120L;
+        private static final long serialVersionUID = 1L;
 
         @Override
         public String toString()
@@ -163,40 +129,6 @@ public class JsonAnnotationTest
         }
     }
 
-    private static boolean subtypeIsMissing(Class<?> main, Class<?> subtype,
-            Collection<Class<?>> classes)
-    {
-
-        if (subtype.isAnonymousClass())
-        {
-            return false;
-        }
-
-        if (classes.contains(subtype))
-        {
-            return false;
-        }
-
-        if (subtype.isInterface())
-        {
-            return true;
-        } else
-        {
-            return subtype.getSuperclass().equals(main);
-        }
-    }
-
-    private static Collection<Class<?>> getAnnotatedSubTypes(Class<?> clazz)
-    {
-        Collection<Class<?>> annotated = new HashSet<Class<?>>();
-        JsonSubTypes types = clazz.getAnnotation(JsonSubTypes.class);
-        for (Type type : types.value())
-        {
-            annotated.add(type.value());
-        }
-        return annotated;
-    }
-
     private Collection<Class<?>> getAllJsonRpcClassesWithoutJsonObject()
     {
         Collection<Class<?>> classesWithoutJsonObject = new HashSet<Class<?>>();
-- 
GitLab