You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@labs.apache.org by si...@apache.org on 2011/11/03 18:19:21 UTC

svn commit: r1197229 - in /labs/magma/trunk/foundation-beans/src/main/java/org/apache/magma/beans: BeanMemberInfo.java MethodInfo.java ParameterInfo.java

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 <si...@apache.org>
+ *
+ */
+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: commits-unsubscribe@labs.apache.org
For additional commands, e-mail: commits-help@labs.apache.org