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:18:22 UTC
svn commit: r1197228 - in /labs/magma/trunk/foundation-beans/src:
main/java/org/apache/magma/beans/ test/java/org/apache/magma/beans/
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 <si...@apache.org>
*/
-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: commits-unsubscribe@labs.apache.org
For additional commands, e-mail: commits-help@labs.apache.org