Author: simoneg
Date: Thu Nov  3 17:19:21 2011
New Revision: 1197229

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

Added:
    
labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/BeanMemberInfo.java
    
labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/MethodInfo.java
    
labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/ParameterInfo.java

Added: 
labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/BeanMemberInfo.java
URL: 
http://svn.apache.org/viewvc/labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/BeanMemberInfo.java?rev=1197229&view=auto
==============================================================================
--- 
labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/BeanMemberInfo.java
 (added)
+++ 
labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/BeanMemberInfo.java
 Thu Nov  3 17:19:21 2011
@@ -0,0 +1,303 @@
+package org.apache.magma.beans;
+
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.magma.basics.utils.GenericClass;
+import org.apache.magma.basics.utils.GenericClass.MethodDef;
+
+
+/**
+ * Holds informations about a member of a bean.
+ * 
+ * Members are either public fields, properties (exposed by getters and 
setters), instance methods and static methods.
+ * 
+ * Each kind of member is represented by the proper subclassm like {@link 
PropertyInfo} for properties.
+ * 
+ * Bean is inspected inside {@link BeanData} constructor. Many aspects will 
enhance either this class
+ * or subclasses adding specific fields and specific parsing of bean classes.
+ * 
+ * @author Simone Gianni <[email protected]>
+ *
+ */
+public abstract class BeanMemberInfo {
+
+       /**
+        * Name of the member, could be field name, property name or method 
name.
+        */
+       protected String name;
+       
+       /**
+        * Type of the member, in case of fields is a real type, in case of 
properties is usually the return type of the getter,
+        * in case of methods is the return type of the method, and in this 
case could be {@link Void}.
+        */
+       @SuppressWarnings("rawtypes")
+       protected Class type;
+       
+       /**
+        * Class of the bean this member is found on
+        */
+       @SuppressWarnings("rawtypes")
+       protected Class beanClass;
+       
+       /**
+        * Whether the {@link #type} represents a collection (this includes 
{@link List}, {@link Set} and arrays, but not maps or tables).
+        */
+       protected boolean isCollection;
+       
+       /**
+        * The type of elements contained in the collection (could be Object if 
it's not possible to deduce it) if {@link #isCollection} is true.
+        */
+       @SuppressWarnings("rawtypes")
+       protected Class collectionClass;
+       
+       /**
+        * Whether the {@link #type} represents a map (this includes {@link 
Map} and tables).
+        */
+       protected boolean isMap;
+       
+       /**
+        * The type of keys in the map (could be Object if it's not possible to 
deduce it)
+        */
+       @SuppressWarnings("rawtypes")
+       protected Class mapKeyClass;
+       
+       /**
+        * The type of values in the map (could be Object if it's not possible 
to deduce it)
+        */
+       @SuppressWarnings("rawtypes")
+       protected Class mapValueClass;
+       
+       /**
+        * If the type is a basic type, that is a primitive type, a wrapper, 
one of java.math numbers, or Date.
+        */
+       protected boolean isBasicType;
+       
+       /**
+        * If the type is an enum.
+        */
+       protected boolean isEnum;
+       
+       /**
+        * If the type is itself another bean
+        */
+       protected boolean isBean;
+       
+       /**
+        * Initializes this instance
+        * @param beanClass The class this member is found in
+        */
+       public BeanMemberInfo(@SuppressWarnings("rawtypes") Class beanClass) {
+               this.beanClass = beanClass;
+       }
+
+       /**
+        * @return the name of the member, could be field name, property name 
or method name.
+        */
+       public String getName() {
+               return name;
+       }
+
+       /**
+        * @return the type of the member, in case of fields is a real type, in 
case of properties is usually the return type of the getter,
+        * in case of methods is the return type of the method, and in this 
case could be {@link Void}.
+        */
+       @SuppressWarnings("rawtypes")
+       public Class getType() {
+               return type;
+       }
+       
+       /**
+        * Initializes {@link #type} the the given type (if provided), if a 
method is provided tries to determine generics based on that method return type.
+        * @param type The type of this member, see {@link #type}. May be null 
if a method is provided, in that case return type of the method is used.
+        * @param method A method (the getter in case of properties, the method 
itself for method members, null for fields) to use to try determine 
+        * generics informations if needed
+        */
+       @SuppressWarnings("rawtypes")
+       protected void initType(Class type, GenericClass generic) {
+               if (type == null) {
+                       type = generic.getBaseClass();
+               }
+               this.type = type;
+               
+               if (this.type != null) {
+                       this.isCollection = 
Collection.class.isAssignableFrom(this.type);
+                       this.isMap = Map.class.isAssignableFrom(this.type);
+                       if (this.isCollection) {
+                               if (generic != null) {
+                                       if 
(!generic.getBaseClass().equals(this.type)) 
+                                               generic = 
GenericClass.forClass(this.type);
+                                       // It must have an add method
+                                       List<MethodDef> methods = 
generic.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 (generic != null) {
+                                       if 
(!generic.getBaseClass().equals(this.type)) 
+                                               generic = 
GenericClass.forClass(this.type);
+                                       // It must have a put method
+                                       List<MethodDef> methods = 
generic.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 = isBasicType(this.type); 
+                               this.isEnum = isEnum(this.type);
+                               this.isBean = isBean(this.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;
+       }
+       
+       /**
+        * Static access to determination of basic types.
+        * @param c The class to check
+        * @return true if it can be considered a basic type
+        */
+       public static boolean isBasicType(Class c) {
+               return c.isPrimitive() ||
+                       (Number.class.isAssignableFrom(c) && 
(c.getName().startsWith("java.lang") || c.getName().startsWith("java.math"))) ||
+                       String.class.equals(c) || 
+                       Date.class.isAssignableFrom(c);
+       }
+       
+       /**
+        * Static access to determination of enum type
+        * @param c The class to check
+        * @return true if it can be considered an enum type
+        */
+       public static boolean isEnum(Class c) {
+               return Enum.class.isAssignableFrom(c);
+       }
+
+       /**
+        * @return true if type is itself a bean
+        */
+       public boolean isBean() {
+               return isBean;
+       }
+       
+       /**
+        * Static access to determination of bean type
+        * @param c The class to check
+        * @return true is the given class is itself a bean (in the Magma sense)
+        */
+       public static boolean isBean(Class c) {
+               return MagmaBeanSupport.class.isAssignableFrom(c);
+       }
+       
+       /**
+        * @return Whether the type returned by {@link #getType()} 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 {@link #type} 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("rawtypes")
+       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("rawtypes")
+       public void setCollectionClass(Class collectionClass) {
+               this.collectionClass = collectionClass;
+       }
+
+       /**
+        * @return Class of the bean this member is found on
+        */
+       @SuppressWarnings("rawtypes")
+       public Class getBeanClass() {
+               return beanClass;
+       }
+
+       /**
+        * @param beanClass Class of the bean this member is found on
+        */
+       @SuppressWarnings("rawtypes")
+       public void setBeanClass(Class beanClass) {
+               this.beanClass = beanClass;
+       }
+
+       /**
+        * @return Whether the type returned by {@link #getType()} represents a 
map (this includes {@link Map} and tables).
+        */
+       public boolean isMap() {
+               return isMap;
+       }
+
+       /**
+        * @return the Class of the keys in the map if {@link #isMap} and if 
it's possible to determine its generics.
+        */
+       @SuppressWarnings("rawtypes")
+       public Class getMapKeyClass() {
+               return mapKeyClass;
+       }
+
+       /**
+        * @return the Class of the values in the map if {@link #isMap} and if 
it's possible to determine its generics.
+        */
+       @SuppressWarnings("rawtypes")
+       public Class getMapValueClass() {
+               return mapValueClass;
+       }
+       
+       /**
+        * Checks if the given {@link Class} is a good fit for the type of this 
member.
+        * 
+        * The basic check relies on {@link Class#isAssignableFrom(Class)}.
+        * 
+        * @param clazz The class of the argument we are planning to assign to 
this member
+        * @return true if a value of the given type will fit in the type of 
this member
+        */
+       public boolean matchesType(Class clazz) {
+               return this.type.isAssignableFrom(clazz);
+       }
+       
+       
+       public boolean isVoid() {
+               return this.type.equals(Void.TYPE);
+       }
+       
+       
+       @Override
+       public String toString() {
+               return this.getClass().getSimpleName() + " " + this.getType() + 
" " + this.getName();
+       }
+
+}

Added: 
labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/MethodInfo.java
URL: 
http://svn.apache.org/viewvc/labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/MethodInfo.java?rev=1197229&view=auto
==============================================================================
--- 
labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/MethodInfo.java
 (added)
+++ 
labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/MethodInfo.java
 Thu Nov  3 17:19:21 2011
@@ -0,0 +1,74 @@
+package org.apache.magma.beans;
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.magma.basics.MagmaException;
+import org.apache.magma.basics.utils.GenericClass;
+
+public class MethodInfo extends BeanMemberInfo {
+
+       private Method method;
+       private ParameterInfo[] parameters = new ParameterInfo[0];
+       private Class[] exceptions = new Class[0];
+       private boolean isStatic = false;
+       
+       @SuppressWarnings("rawtypes")
+       public MethodInfo(Class beanClass) {
+               super(beanClass);
+       }
+
+       public void init(Method method, Class beanClass) {
+               super.initType(null, GenericClass.forReturnType(method));
+               
+               this.name = method.getName();
+               this.method = method;
+               this.isStatic = Modifier.isStatic(method.getModifiers());
+               
+               Class<?>[] params = method.getParameterTypes();
+               if (params.length > 0) {
+                       List<ParameterInfo> paramInfos = new 
ArrayList<ParameterInfo>(params.length);
+                       for (int i = 0; i < params.length; i++) {
+                               paramInfos.add(new 
ParameterInfo(this.beanClass, method, i));
+                       }
+                       this.parameters = paramInfos.toArray(this.parameters);
+               }
+       
+               this.exceptions = method.getExceptionTypes();
+       }       
+       
+       public ParameterInfo[] getParameters() {
+               return parameters;
+       }
+       
+       public Class[] getExceptions() {
+               return exceptions;
+       }
+       
+       public boolean isStatic() {
+               return isStatic;
+       }
+       
+       public Object invoke(Object target, Object... parameters) {
+               try {
+                       return method.invoke(target, parameters);
+               } catch (Exception e) {
+                       throw new MagmaException(e, "Error invoking method 
({0}) {1}.{2}({3})", target, this.getBeanClass(), this.name, parameters);
+               }
+       }
+
+       public boolean matchesParameters(Class[] paramTypes) {
+               if (this.parameters.length != paramTypes.length) return false;
+               for (int i = 0; i < this.parameters.length; i++) {
+                       if (paramTypes[i] == null) continue;
+                       if (!this.parameters[i].matchesType(paramTypes[i])) 
return false;
+               }
+               return true;
+       }
+       
+}

Added: 
labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/ParameterInfo.java
URL: 
http://svn.apache.org/viewvc/labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/ParameterInfo.java?rev=1197229&view=auto
==============================================================================
--- 
labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/ParameterInfo.java
 (added)
+++ 
labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans/ParameterInfo.java
 Thu Nov  3 17:19:21 2011
@@ -0,0 +1,22 @@
+package org.apache.magma.beans;
+
+import java.lang.reflect.Method;
+
+import org.apache.magma.basics.utils.GenericClass;
+
+public class ParameterInfo extends BeanMemberInfo {
+
+       public ParameterInfo(Class beanClass, Method method, int i) {
+               super(beanClass);
+               
+               GenericClass gc = GenericClass.forParameter(method, i);
+               super.initType(null, gc);
+               
+               String simpleName = super.getType().getSimpleName();
+               if (simpleName.endsWith("[]")) {
+                       simpleName = simpleName.substring(0, 
simpleName.length() - 2) + "Arr";
+               }
+               this.name = "p" + i + "_" + simpleName;
+       }
+
+}



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

Reply via email to