You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2007/12/18 11:56:07 UTC
svn commit: r605178 - in
/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src:
main/java/org/apache/cayenne/reflect/ test/java/org/apache/cayenne/reflect/
Author: aadamchik
Date: Tue Dec 18 02:56:04 2007
New Revision: 605178
URL: http://svn.apache.org/viewvc?rev=605178&view=rev
Log:
CAY-945 PropertyUtils support for "compiled" property access
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/BeanAccessor.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/PropertyUtils.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/reflect/PropertyUtilsTest.java
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/BeanAccessor.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/BeanAccessor.java?rev=605178&r1=605177&r2=605178&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/BeanAccessor.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/BeanAccessor.java Tue Dec 18 02:56:04 2007
@@ -36,7 +36,7 @@
protected Method writeMethod;
protected Object nullValue;
- public BeanAccessor(Class objectClass, String propertyName, Class propertyType) {
+ public BeanAccessor(Class<?> objectClass, String propertyName, Class<?> propertyType) {
if (objectClass == null) {
throw new IllegalArgumentException("Null objectClass");
}
@@ -57,10 +57,7 @@
this.writeMethod = descriptor.getWriteMethod();
}
catch (IntrospectionException e) {
- throw new PropertyException(
- "Invalid bean property: " + propertyName,
- this,
- e);
+ throw new PropertyException("Invalid bean property: " + propertyName, this, e);
}
}
@@ -73,13 +70,14 @@
*/
public Object getValue(Object object) throws PropertyException {
if (readMethod == null) {
- throw new PropertyException("Property '"
- + propertyName
- + "' is not readable", this, object);
+ throw new PropertyException(
+ "Property '" + propertyName + "' is not readable",
+ this,
+ object);
}
try {
- return readMethod.invoke(object, null);
+ return readMethod.invoke(object, (Object[]) null);
}
catch (Throwable th) {
throw new PropertyException(
@@ -96,9 +94,10 @@
public void setValue(Object object, Object newValue) throws PropertyException {
if (writeMethod == null) {
- throw new PropertyException("Property '"
- + propertyName
- + "' is not writable", this, object);
+ throw new PropertyException(
+ "Property '" + propertyName + "' is not writable",
+ this,
+ object);
}
// this will take care of primitives.
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/PropertyUtils.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/PropertyUtils.java?rev=605178&r1=605177&r2=605178&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/PropertyUtils.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/reflect/PropertyUtils.java Tue Dec 18 02:56:04 2007
@@ -25,6 +25,9 @@
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
@@ -44,6 +47,38 @@
public class PropertyUtils {
/**
+ * Compiles an accessor that can be used for fast access for the nested property of
+ * the objects of a given class.
+ *
+ * @since 3.0
+ */
+ public static Accessor createAccessor(Class<?> objectClass, String nestedPropertyName) {
+ if (objectClass == null) {
+ throw new IllegalArgumentException("Null class.");
+ }
+
+ if (Util.isEmptyString(nestedPropertyName)) {
+ throw new IllegalArgumentException("Null or empty property name.");
+ }
+
+ StringTokenizer path = new StringTokenizer(
+ nestedPropertyName,
+ Entity.PATH_SEPARATOR);
+
+ if (path.countTokens() == 1) {
+ return new BeanAccessor(objectClass, nestedPropertyName, null);
+ }
+
+ NestedBeanAccessor accessor = new NestedBeanAccessor(nestedPropertyName);
+ while (path.hasMoreTokens()) {
+ String token = path.nextToken();
+ accessor.addAccessor(new BeanAccessor(objectClass, token, null));
+ }
+
+ return accessor;
+ }
+
+ /**
* Returns object property using JavaBean-compatible introspection with one addition -
* a property can be a dot-separated property name path.
*/
@@ -269,7 +304,7 @@
* is returned. For primitive types a default such as zero or false is returned.
*/
static Object defaultNullValueForType(Class<?> type) {
- if (type.isPrimitive()) {
+ if (type != null && type.isPrimitive()) {
String className = type.getName();
if ("byte".equals(className)) {
@@ -300,5 +335,56 @@
private PropertyUtils() {
super();
+ }
+
+ static final class NestedBeanAccessor implements Accessor {
+
+ private Collection<Accessor> accessors;
+ private String name;
+
+ NestedBeanAccessor(String name) {
+ accessors = new ArrayList<Accessor>();
+ this.name = name;
+ }
+
+ void addAccessor(Accessor accessor) {
+ accessors.add(accessor);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Object getValue(Object object) throws PropertyException {
+
+ Object value = object;
+ for (Accessor accessor : accessors) {
+ if (value == null) {
+ throw new IllegalArgumentException(
+ "Null object at the end of the segment '"
+ + accessor.getName()
+ + "'");
+ }
+
+ value = accessor.getValue(value);
+ }
+
+ return value;
+ }
+
+ public void setValue(Object object, Object newValue) throws PropertyException {
+ Object value = object;
+ Iterator<Accessor> accessors = this.accessors.iterator();
+ while (accessors.hasNext()) {
+ Accessor accessor = accessors.next();
+
+ if (accessors.hasNext()) {
+ value = accessor.getValue(value);
+ }
+ else {
+ accessor.setValue(value, newValue);
+ }
+ }
+ }
}
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/reflect/PropertyUtilsTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/reflect/PropertyUtilsTest.java?rev=605178&r1=605177&r2=605178&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/reflect/PropertyUtilsTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/reflect/PropertyUtilsTest.java Tue Dec 18 02:56:04 2007
@@ -31,6 +31,23 @@
public class PropertyUtilsTest extends TestCase {
+ public void testCreateAccessor() {
+
+ Accessor accessor = PropertyUtils.createAccessor(
+ TestJavaBean.class,
+ "byteArrayField");
+ assertNotNull(accessor);
+
+ TestJavaBean o1 = createBean();
+ assertSame(o1.getByteArrayField(), accessor.getValue(o1));
+
+ TestJavaBean o2 = new TestJavaBean();
+ assertNull(o2.getByteArrayField());
+ accessor.setValue(o2, o1.getByteArrayField());
+ assertNotNull(o2.getByteArrayField());
+ assertSame(o1.getByteArrayField(), o2.getByteArrayField());
+ }
+
public void testGetProperty() {
TestJavaBean o1 = createBean();
@@ -64,15 +81,18 @@
public void testGetPropertyMap() {
Map o1 = createMap();
- assertSame(o1.get("byteArrayField"), PropertyUtils.getProperty(o1, "byteArrayField"));
+ assertSame(o1.get("byteArrayField"), PropertyUtils.getProperty(
+ o1,
+ "byteArrayField"));
assertSame(o1.get("integerField"), PropertyUtils.getProperty(o1, "integerField"));
assertEquals(o1.get("intField"), PropertyUtils.getProperty(o1, "intField"));
assertSame(o1.get("numberField"), PropertyUtils.getProperty(o1, "numberField"));
assertSame(o1.get("objectField"), PropertyUtils.getProperty(o1, "objectField"));
assertSame(o1.get("stringField"), PropertyUtils.getProperty(o1, "stringField"));
- assertEquals(o1.get("booleanField"), PropertyUtils.getProperty(o1, "booleanField"));
+ assertEquals(o1.get("booleanField"), PropertyUtils
+ .getProperty(o1, "booleanField"));
}
-
+
public void testSetPropertyMap() {
Map o1 = createMap();
Map o2 = new HashMap();
@@ -84,11 +104,10 @@
PropertyUtils.setProperty(o2, "objectField", o1.get("objectField"));
PropertyUtils.setProperty(o2, "stringField", o1.get("stringField"));
PropertyUtils.setProperty(o2, "booleanField", o1.get("booleanField"));
-
+
assertEquals(o1, o2);
}
-
public void testSetConverted() {
TestJavaBean o1 = new TestJavaBean();
@@ -105,8 +124,6 @@
PropertyUtils.setProperty(o1, "intField", "28");
assertEquals(28, o1.getIntField());
}
-
-
public void testSetNull() {
TestJavaBean o1 = new TestJavaBean();
@@ -119,20 +136,18 @@
PropertyUtils.setProperty(o1, "intField", null);
assertEquals(0, o1.getIntField());
}
-
-
+
public void testSetConvertedEnum() {
MockEnumHolder o1 = new MockEnumHolder();
// String to Enum
PropertyUtils.setProperty(o1, "mockEnum", "b");
assertSame(MockEnum.b, o1.getMockEnum());
-
+
// check that regular converters still work
PropertyUtils.setProperty(o1, "number", "445");
assertEquals(445, o1.getNumber());
}
-
protected TestJavaBean createBean() {
TestJavaBean o1 = new TestJavaBean();