Author: simoneg
Date: Thu Nov  3 17:18:21 2011
New Revision: 1197228

URL: http://svn.apache.org/viewvc?rev=1197228&view=rev
Log:
Support for inspection of methods

Modified:
    
labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/BeanData.java
    
labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/PropertyInfo.java
    
labs/magma/trunk/foundation-beans/src/test/java/org/apache/magma/beans/BeanDataTest.java
    
labs/magma/trunk/foundation-beans/src/test/java/org/apache/magma/beans/DummyBean.java

Modified: 
labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/BeanData.java
URL: 
http://svn.apache.org/viewvc/labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/BeanData.java?rev=1197228&r1=1197227&r2=1197228&view=diff
==============================================================================
--- 
labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/BeanData.java
 (original)
+++ 
labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/BeanData.java
 Thu Nov  3 17:18:21 2011
@@ -21,8 +21,12 @@ import java.beans.IntrospectionException
 import java.beans.Introspector;
 import java.beans.PropertyDescriptor;
 import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -69,6 +73,8 @@ public class BeanData {
         * Properties of the class.
         */
        private Map<String, PropertyInfo> properties = new HashMap<String, 
PropertyInfo>();
+       private Map<String, List<MethodInfo>> instanceMethods = new 
HashMap<String, List<MethodInfo>>();
+       private Map<String, List<MethodInfo>> staticMethods = new 
HashMap<String, List<MethodInfo>>();
 
        /**
         * Builds a new {@link BeanData} for the given class, performing 
inspection.
@@ -85,13 +91,38 @@ public class BeanData {
                        } catch (IntrospectionException e) {
                                throw new IllegalStateException("Error 
analyzing bean " + clazz, e);
                        }
+                       Set<Method> doneMethods = new HashSet<Method>();
                        PropertyDescriptor[] descriptors = 
beanInfo.getPropertyDescriptors();
                        for (PropertyDescriptor desc : descriptors) {
                                RunningContext.get().push(desc.getName());
                                try {
-                                       PropertyInfo info = new PropertyInfo();
-                                       info.init(desc, clazz);
+                                       PropertyInfo info = new 
PropertyInfo(clazz);
+                                       info.init(desc,clazz);
                                        properties.put(info.getName(), info);
+                                       doneMethods.add(desc.getReadMethod());
+                                       doneMethods.add(desc.getWriteMethod());
+                               } finally {
+                                       RunningContext.get().popString();       
                        
+                               }
+                       }
+                       
+                       Method[] methods = clazz.getMethods();
+                       for (Method method : methods) {
+                               if (doneMethods.contains(method)) continue;
+                               if (method.isBridge() || method.isSynthetic()) 
continue;
+                               if 
(method.getDeclaringClass().equals(Object.class)) continue;
+                               RunningContext.get().push(method.getName());
+                               try {
+                                       MethodInfo info = new MethodInfo(clazz);
+                                       info.init(method, clazz);
+                                       Map<String, List<MethodInfo>> tgt = 
info.isStatic() ? staticMethods : instanceMethods;
+                                       List<MethodInfo> list = 
tgt.get(info.getName());
+                                       if (list == null) {
+                                               list = new 
ArrayList<MethodInfo>();
+                                               tgt.put(info.getName(), list);
+                                       }
+                                       list.add(info);
+                                       doneMethods.add(method);
                                } finally {
                                        RunningContext.get().popString();       
                        
                                }
@@ -110,6 +141,14 @@ public class BeanData {
        }
        
        /**
+        * Fetches all properties,.
+        * @return a set of properties
+        */
+       public Collection<PropertyInfo> getProperties() {
+               return Collections.unmodifiableCollection(properties.values());
+       }
+       
+       /**
         * Fetches a single property.
         * @param name the name of the property to fetch.
         * @return a {@link PropertyInfo} describing the required property, or 
null if not found.
@@ -145,5 +184,69 @@ public class BeanData {
                return this.getProperty(name);
        }
 
+       /**
+        * @return All the names of instance methods
+        */
+       public Set<String> getInstanceMethodNames() {
+               return Collections.unmodifiableSet(instanceMethods.keySet());
+       }
+       
+       /**
+        * @return All the names of static methods
+        */
+       public Set<String> getStaticMethodNames() {
+               return Collections.unmodifiableSet(staticMethods.keySet());
+       }
+       
+       /**
+        * Fetches an instance method
+        * @param name The name of the method
+        * @return One or more (if method is overloaded) {@link MethodInfo}s 
describing the method.
+        */
+       public List<MethodInfo> getInstanceMethod(String name) {
+               List<MethodInfo> list = instanceMethods.get(name);
+               if (list == null) return null;
+               return Collections.unmodifiableList(list);
+       }
+       
+       /**
+        * Fetches a static method
+        * @param name The name of the method
+        * @return One or more (if method is overloaded) {@link MethodInfo}s 
describing the method.
+        */
+       public List<MethodInfo> getStaticMethod(String name) {
+               List<MethodInfo> list = staticMethods.get(name);
+               if (list == null) return null;
+               return Collections.unmodifiableList(list);
+       }
+       
+       
+       public MethodInfo findInstanceMethod(String name, Class... parameters) {
+               return findMethod(false, name, parameters);
+       }
+       
+       public MethodInfo findStaticMethod(String name, Class... parameters) {
+               return findMethod(true, name, parameters);
+       }
+
+       public MethodInfo findMethod(boolean stat, String name, Class... 
parameters) {
+               Map<String, List<MethodInfo>> tgt = stat ? staticMethods : 
instanceMethods;
+               List<MethodInfo> list = stat ? getStaticMethod(name) : 
getInstanceMethod(name);
+               if (list == null || list.size() == 0) return null;
+               for (MethodInfo methodInfo : list) {
+                       if (methodInfo.matchesParameters(parameters)) return 
methodInfo;
+               }
+               return null;
+       }
+       
+       public MethodInfo findMethodWithParameters(boolean stat, String name, 
Object... parameters) {
+               Class[] classes = new Class[parameters.length];
+               for (int i = 0; i < parameters.length; i++) {
+                       if (parameters[i] != null) {
+                               classes[i] = parameters[i].getClass();
+                       } 
+               }
+               return findMethod(stat, name, classes);
+       }
        
 }

Modified: 
labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/PropertyInfo.java
URL: 
http://svn.apache.org/viewvc/labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/PropertyInfo.java?rev=1197228&r1=1197227&r2=1197228&view=diff
==============================================================================
--- 
labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/PropertyInfo.java
 (original)
+++ 
labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/PropertyInfo.java
 Thu Nov  3 17:18:21 2011
@@ -23,7 +23,6 @@ import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 import org.apache.commons.beanutils.PropertyUtils;
 import org.apache.magma.basics.MagmaException;
@@ -42,19 +41,13 @@ import org.apache.magma.conversion.Prope
  *
  * @author Simone Gianni <[email protected]>
  */
-public class PropertyInfo implements Cloneable {
+public class PropertyInfo extends BeanMemberInfo implements Cloneable {
+
+       @SuppressWarnings("rawtypes")
+       public PropertyInfo(Class beanClass) {
+               super(beanClass);
+       }
 
-       /**
-        * Name of the property.
-        */
-       private String name;
-       
-       /**
-        * Type of the property
-        */
-       @SuppressWarnings("unchecked")
-       private Class type;
-       
        /**
         * When {@link Consider} is used, this is the underlying type
         */
@@ -68,12 +61,6 @@ public class PropertyInfo implements Clo
        private GenericConverter underlyingConverter;
        
        /**
-        * Class of the bean this property is found on
-        */
-       @SuppressWarnings("unchecked")
-       private Class beanClass;
-       
-       /**
         * Whether the property is readable
         */
        private boolean readable;
@@ -89,48 +76,11 @@ public class PropertyInfo implements Clo
        private boolean underlyingWriteable;
        
        /**
-        * Whether the property represents a collection (this includes {@link 
List}, {@link Set} and arrays, but not maps or tables).
-        */
-       private boolean isCollection;
-
-       /**
-        * The type of elements contained in the collection (could be Object if 
it's not possible to deduce it)
-        */
-       @SuppressWarnings("unchecked")
-       private Class collectionClass;
-
-       
-       /**
-        * Whether the property represents a map (this includes {@link Map} and 
tables).
-        */
-       private boolean isMap;
-       
-
-       /**
-        * The type of keys in the map (could be Object if it's not possible to 
deduce it)
-        */
-       private Class mapKeyClass;
-       /**
-        * The type of values in the map (could be Object if it's not possible 
to deduce it)
-        */     
-       private Class mapValueClass;
-       
-       /**
         * If content of this property is rendered as a string, the maximum 
size of this string.
         */
        private int maxStringSize = -1;
 
        /**
-        * If the type is a basic type, that is a primitive type, a wrapper, 
one of java.math numbers, or Date.
-        */
-       private boolean isBasicType;
-
-       /**
-        * If the type is an enum.
-        */
-       private boolean isEnum;
-       
-       /**
         * Another PropertyInfo representing the underlying property, without 
conversion or hiding. Could be the same instance
         * if there is no conversion nor hiding to handle.
         */
@@ -170,48 +120,22 @@ public class PropertyInfo implements Clo
        public void setWriteable(boolean writeable) {
                this.writeable = writeable;
        }
-
-       /**
-        * @return the name of the property.
-        */             
-       public String getName() {
-               return name;
-       }
-       
-       /**
-        * @return the type of the property.
-        */
-       @SuppressWarnings("unchecked")
-       public Class getType() {
-               return type;
-       }
        
        /**
-        * @return true if the type is a basic type, that is a primitive type, 
a wrapper, one of java.math numbers or Date.
-        */
-       public boolean isBasicType() {
-               return this.isBasicType;
-       }
-
-       /**
-        * @return true if the type is an {@link Enum}.
-        */
-       public boolean isEnum() {
-               return this.isEnum;
-       }
-
-       /**
         * Initializes this class, parsing the {@link PropertyDescriptor} and 
eventually annotations found on the getter or setter methods.
         * 
         * This is the method to hook to when implementing additional parsing, 
like validation and conversion does.
         * 
+        * NOTE: the beanClass parameter is currently ignored. It is here only 
because a lot of aspects matches that signature. It will
+        * be removed when all aspects hooking here can be safely refactored.
+        * 
         * @param descriptor the {@link PropertyDescriptor} of the property.
-        * @param beanClass the class of the bean containing the property.
+        * @param beanClass IGNORED the class of the bean containing the 
property.
         */
+       // TODO remove beanClass parameter when a way to force aspect matching 
is found
        @SuppressWarnings("unchecked")
        public void init(PropertyDescriptor descriptor, Class beanClass) {
                this.descriptor = descriptor;
-               this.beanClass = beanClass;
                this.name = descriptor.getName();
                readMethod = descriptor.getReadMethod();
                writeMethod = descriptor.getWriteMethod();
@@ -262,40 +186,11 @@ public class PropertyInfo implements Clo
                }
                
                if (this.type != null) {
-                       this.isCollection = 
Collection.class.isAssignableFrom(this.type);
-                       this.isMap = Map.class.isAssignableFrom(this.type);
-                       if (this.isCollection) {
-                               if (readable) {
-                                       GenericClass returnType = 
GenericClass.forReturnType(readMethod);
-                                       if 
(!returnType.getBaseClass().equals(this.type)) 
-                                               returnType = 
GenericClass.forClass(this.type);
-                                       // It must have an add method
-                                       List<MethodDef> methods = 
returnType.findMethods("add", new Class<?>[] {null});
-                                       // It must have a single parameter of 
the type of the collection
-                                       this.collectionClass = 
methods.get(0).getParameterTypes()[0].getBaseClass();
-                               }                               
-                       } else if (this.isMap) {
-                               if (readable) {
-                                       GenericClass returnType = 
GenericClass.forReturnType(readMethod);
-                                       if 
(!returnType.getBaseClass().equals(this.type)) 
-                                               returnType = 
GenericClass.forClass(this.type);
-                                       // It must have a put method
-                                       List<MethodDef> methods = 
returnType.findMethods("put", new Class<?>[] {null, null});
-                                       // It must have a single parameter of 
the type of the collection
-                                       MethodDef putmethod = methods.get(0);
-                                       GenericClass[] parameterTypes = 
putmethod.getParameterTypes();
-                                       this.mapKeyClass = 
parameterTypes[0].getBaseClass();
-                                       this.mapValueClass = 
parameterTypes[1].getBaseClass();
-                               }                                               
                
-                       } else {
-                               this.isBasicType = 
-                                       this.type.isPrimitive() ||
-                                       
this.type.getName().startsWith("java.lang") ||
-                                       
this.type.getName().startsWith("java.math") ||
-                                       Date.class.isAssignableFrom(this.type);
-                               this.isEnum = 
Enum.class.isAssignableFrom(this.type);
-                       } 
-               }               
+                       GenericClass gc = null;
+                       if (readable) gc = 
GenericClass.forReturnType(readMethod);
+                       super.initType(this.type, gc);
+               }
+               
        }
        
        protected void initAsUnderlying(PropertyInfo sup) {
@@ -316,52 +211,6 @@ public class PropertyInfo implements Clo
     }
     
     /**
-     * @return Whether the property represents a collection (this includes 
{@link List}, {@link Set} and arrays, but not maps or tables).
-     */
-       public boolean isCollection() {
-               return isCollection;
-       }
-       
-       /**
-        * @param isCollection Whether the property represents a collection.
-        */
-       public void setCollection(boolean isCollection) {
-               this.isCollection = isCollection;
-       }
-       
-       /**
-        * @return The type of elements contained in the collection (could be 
Object if it's not possible to deduce it)
-        */
-       @SuppressWarnings("unchecked")
-       public Class getCollectionClass() {
-               return collectionClass;
-       }
-       
-       /**
-        * @param collectionClass The type of elements contained in the 
collection (could be Object if it's not possible to deduce it)
-        */     
-       @SuppressWarnings("unchecked")
-       public void setCollectionClass(Class collectionClass) {
-               this.collectionClass = collectionClass;
-       }
-       
-       /**
-        * @return Class of the bean this property is found on
-        */
-       @SuppressWarnings("unchecked")
-       public Class getBeanClass() {
-               return beanClass;
-       }
-       
-       /**
-        * @param beanClass Class of the bean this property is found on
-        */
-       @SuppressWarnings("unchecked")
-       public void setBeanClass(Class beanClass) {
-               this.beanClass = beanClass;
-       }
-       
-       /**
         * @return If content of this property is rendered as a string, the 
maximum size of this string.
         */
        public int getMaximumStringSize() {
@@ -439,27 +288,6 @@ public class PropertyInfo implements Clo
        }
        
        /**
-     * @return Whether the property represents a map (this includes {@link 
Map} and tables).
-        */
-       public boolean isMap() {
-               return isMap;
-       }
-       
-       /**
-        * @return the Class of the keys in the map if this property {@link 
#isMap} and if it's possible to determine its generics.
-        */
-       public Class getMapKeyClass() {
-               return mapKeyClass;
-       }
-       
-       /**
-        * @return the Class of the values in the map if this property {@link 
#isMap} and if it's possible to determine its generics.
-        */     
-       public Class getMapValueClass() {
-               return mapValueClass;
-       }
-       
-       /**
         * Set the given value for this property on the given bean. Value will 
be converted to underlying if applicable.
         * @param bean The bean to set the property to
         * @param val The value to set, it will be converted to the underlying 
type.
@@ -501,7 +329,7 @@ public class PropertyInfo implements Clo
                        if (this.underlyingType == null && 
this.underlyingWriteable == this.writeable) {
                                this.underlyingProperty = this;
                        } else {
-                               PropertyInfo np = new PropertyInfo();
+                               PropertyInfo np = new 
PropertyInfo(this.beanClass);
                                np.initAsUnderlying(this);
                                this.underlyingProperty = np;
                        }

Modified: 
labs/magma/trunk/foundation-beans/src/test/java/org/apache/magma/beans/BeanDataTest.java
URL: 
http://svn.apache.org/viewvc/labs/magma/trunk/foundation-beans/src/test/java/org/apache/magma/beans/BeanDataTest.java?rev=1197228&r1=1197227&r2=1197228&view=diff
==============================================================================
--- 
labs/magma/trunk/foundation-beans/src/test/java/org/apache/magma/beans/BeanDataTest.java
 (original)
+++ 
labs/magma/trunk/foundation-beans/src/test/java/org/apache/magma/beans/BeanDataTest.java
 Thu Nov  3 17:18:21 2011
@@ -20,6 +20,7 @@ import static org.junit.Assert.*;
 import static org.hamcrest.CoreMatchers.*;
 
 import java.util.Date;
+import java.util.List;
 import java.util.Set;
 
 import org.junit.Before;
@@ -118,4 +119,72 @@ public class BeanDataTest {
                assertEquals(String.class, property.getType());
        }
        
+       @Test
+       public void methodsInBean() throws Exception {
+               DummyBean dummy = new DummyBean();
+               BeanData bd = dummy.beanData();
+               
+               Set<String> instanceMethodNames = bd.getInstanceMethodNames();
+               System.out.println(instanceMethodNames);
+               assertEquals(4, instanceMethodNames.size());
+               
+               List<MethodInfo> methods = bd.getInstanceMethod("computeA");
+               assertEquals(1, methods.size());
+               MethodInfo methodInfo = methods.get(0);
+               assertEquals(0,methodInfo.getParameters().length);
+               assertEquals(String.class,methodInfo.getType());
+               
+               methods = bd.getInstanceMethod("alterPrivString");
+               assertEquals(3, methods.size());
+       }
+       
+       @Test
+       public void staticMethodsInBean() throws Exception {
+               DummyBean dummy = new DummyBean();
+               BeanData bd = dummy.beanData();
+
+               Set<String> staticMethodNames = bd.getStaticMethodNames();
+               assertEquals(1, staticMethodNames.size());
+               
+               List<MethodInfo> staticMethod = 
bd.getStaticMethod("computeMyName");
+               assertEquals(2,staticMethod.size());
+               
+               assertEquals(String.class, staticMethod.get(0).getType());
+       }
+       
+       @Test
+       public void findMethods() throws Exception {
+               DummyBean dummy = new DummyBean();
+               BeanData bd = dummy.beanData();
+               
+               MethodInfo methodInfo = 
bd.findInstanceMethod("alterPrivString", Integer.TYPE);
+               assertNotNull(methodInfo);
+               assertEquals("alterPrivString", methodInfo.getName());
+               assertEquals(Void.TYPE, methodInfo.getType());
+               
+               MethodInfo methodInfo2 = 
bd.findInstanceMethod("alterPrivString", String.class);
+               assertNotSame(methodInfo, methodInfo2);
+               
+               methodInfo2 = bd.findInstanceMethod("alterPrivString");
+               assertNotSame(methodInfo, methodInfo2);
+               assertEquals(1, methodInfo2.getExceptions().length);
+               
+       }
+       
+       @Test
+       public void invokeMethods() throws Exception {
+               DummyBean dummy = new DummyBean();
+               BeanData bd = dummy.beanData();
+               
+               MethodInfo methodInfo2 = 
bd.findInstanceMethod("alterPrivString", String.class);
+               methodInfo2.invoke(dummy, "TestInvoke");
+               
+               assertEquals("TestInvoke", dummy.getPrivString());
+               
+               
+               methodInfo2 = bd.findInstanceMethod("computeA");
+               Object ret = methodInfo2.invoke(dummy);
+               assertEquals("a", ret);
+       }
+       
 }

Modified: 
labs/magma/trunk/foundation-beans/src/test/java/org/apache/magma/beans/DummyBean.java
URL: 
http://svn.apache.org/viewvc/labs/magma/trunk/foundation-beans/src/test/java/org/apache/magma/beans/DummyBean.java?rev=1197228&r1=1197227&r2=1197228&view=diff
==============================================================================
--- 
labs/magma/trunk/foundation-beans/src/test/java/org/apache/magma/beans/DummyBean.java
 (original)
+++ 
labs/magma/trunk/foundation-beans/src/test/java/org/apache/magma/beans/DummyBean.java
 Thu Nov  3 17:18:21 2011
@@ -16,6 +16,7 @@
  */
 package org.apache.magma.beans;
 
+import java.io.IOException;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
@@ -75,4 +76,30 @@ public class DummyBean {
                this.aMap = aMap;
        }
        
+       
+       /* Testing methods */
+       
+       public String computeA() {
+               return "a";
+       }
+       
+       public void alterPrivString() throws IOException {
+               this.setPrivString("altered");
+       }
+       
+       public void alterPrivString(String val) {
+               this.setPrivString(val);                
+       }
+       
+       public void alterPrivString(int val) {
+               this.setPrivString(Integer.toString(val));
+       }
+       
+       public static String computeMyName() {
+               return "MyName";
+       }
+       
+       public static String computeMyName(int val) {
+               return "MyName" + val;
+       }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to