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();