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 2010/11/09 04:07:19 UTC

svn commit: r1032831 - in /cayenne/main/branches/STABLE-3.0: docs/doc/src/main/resources/RELEASE-NOTES.txt framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/CayenneDataObject.java

Author: aadamchik
Date: Tue Nov  9 03:07:19 2010
New Revision: 1032831

URL: http://svn.apache.org/viewvc?rev=1032831&view=rev
Log:
CAY-1403 Method "readNestedProperty" Should Resolve Through Iterative Invocations onto DataObject and Not Complete Within Cayenne.readNestedProperty

* patch by Andrew Lindesay with minimal edits by aadamchik

Modified:
    cayenne/main/branches/STABLE-3.0/docs/doc/src/main/resources/RELEASE-NOTES.txt
    cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/CayenneDataObject.java

Modified: cayenne/main/branches/STABLE-3.0/docs/doc/src/main/resources/RELEASE-NOTES.txt
URL: http://svn.apache.org/viewvc/cayenne/main/branches/STABLE-3.0/docs/doc/src/main/resources/RELEASE-NOTES.txt?rev=1032831&r1=1032830&r2=1032831&view=diff
==============================================================================
--- cayenne/main/branches/STABLE-3.0/docs/doc/src/main/resources/RELEASE-NOTES.txt (original)
+++ cayenne/main/branches/STABLE-3.0/docs/doc/src/main/resources/RELEASE-NOTES.txt Tue Nov  9 03:07:19 2010
@@ -18,6 +18,7 @@ CAY-1500 MySQL JDBC Batching
 
 Bug Fixes Since 3.0.1:
 
+CAY-1403 Method "readNestedProperty" Should Resolve Through Iterative Invocations onto DataObject and Not Complete Within Cayenne.readNestedProperty
 CAY-1484 Flattened attribute queries are incorrectly generated
 CAY-1485 Memory information for about dialog
 CAY-1488 OutOfMemory when selecting "Remove Foreign Keys Mapped as Object Attributes"

Modified: cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/CayenneDataObject.java
URL: http://svn.apache.org/viewvc/cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/CayenneDataObject.java?rev=1032831&r1=1032830&r2=1032831&view=diff
==============================================================================
--- cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/CayenneDataObject.java (original)
+++ cayenne/main/branches/STABLE-3.0/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/CayenneDataObject.java Tue Nov  9 03:07:19 2010
@@ -30,7 +30,6 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.StringTokenizer;
 
 import org.apache.cayenne.access.DataContext;
 import org.apache.cayenne.conf.Configuration;
@@ -111,57 +110,77 @@ public class CayenneDataObject extends P
     }
 
     public Object readNestedProperty(String path) {
-        return readNestedProperty(this, path, tokenizePath(path), 0, 0);
-    }
-    
-    /**
-     * Recursively resolves nested property path 
-     */
-    private static Object readNestedProperty(CayenneDataObject dataObject, 
-        String path, String[] tokenizedPath, int tokenIndex, int pathIndex) {
         
-        Object property = dataObject.readSimpleProperty(tokenizedPath[tokenIndex]);
+        if ((null == path) || (0 == path.length())) {
+            throw new IllegalArgumentException(
+                    "the path must be supplied in order to lookup a nested property");
+        }
 
-        if (tokenIndex == tokenizedPath.length - 1) { //last component
-            return property;
+        int dotIndex = path.indexOf('.');
+
+        if (0 == dotIndex) {
+            throw new IllegalArgumentException(
+                    "the path is invalid because it starts with a period character");
         }
-        
-        pathIndex += tokenizedPath[tokenIndex].length() + 1;
+
+        if (dotIndex == path.length() - 1) {
+            throw new IllegalArgumentException(
+                    "the path is invalid because it ends with a period character");
+        }
+
+        if (-1 == dotIndex) {
+            return readSimpleProperty(path);
+        }
+
+        String path0 = path.substring(0, dotIndex);
+        String pathRemainder = path.substring(dotIndex + 1);
+
+        // this is copied from the old code where the placement of a plus
+        // character at the end of a segment of a property path would
+        // simply strip out the plus. I am not entirely sure why this is
+        // done. See unit test 'testReadNestedPropertyToManyInMiddle1'.
+
+        if ('+' == path0.charAt(path0.length() - 1)) {
+            path0 = path0.substring(0, path0.length() - 1);
+        }
+
+        Object property = readSimpleProperty(path0);
+
         if (property == null) {
             return null;
         }
-        else if (property instanceof CayenneDataObject) {
-            return readNestedProperty((CayenneDataObject) property, path, tokenizedPath, tokenIndex + 1,
-                tokenIndex);
+        else if (property instanceof DataObject) {
+            DataObject cdo = (DataObject) property;
+            return cdo.readNestedProperty(pathRemainder);
         }
         else if (property instanceof Collection) {
-        
-        	// CAY-1402
-        	// This is back-ported from 3.1's trunk and from the Cayenne utility
-        	// object.  This will allow people to put @size at the end of a property
-        	// path and be able to find out the size of a relationship.
-        
+
+            // CAY-1402
+            // This is back-ported from 3.1's trunk and from the Cayenne utility
+            // object. This will allow people to put @size at the end of a property
+            // path and be able to find out the size of a relationship.
+
             Collection<?> collection = (Collection) property;
-            
-            if (tokenIndex < tokenizedPath.length - 1) {
-                if (tokenizedPath[tokenIndex + 1].equals(PROPERTY_COLLECTION_SIZE)) {
-                    return collection.size();
-                }
-            }
-        
+
+            if (pathRemainder.equals(PROPERTY_COLLECTION_SIZE))
+                return new Integer(collection.size());
+
             /**
              * Support for collection property in the middle of the path
              */
-            Collection<Object> result = property instanceof List ?
-                    new ArrayList<Object>() : new HashSet<Object>() ;
+            Collection<Object> result = property instanceof List
+                    ? new ArrayList<Object>()
+                    : new HashSet<Object>();
             for (Object obj : (Collection<?>) property) {
                 if (obj instanceof CayenneDataObject) {
-                    Object rest = readNestedProperty((CayenneDataObject) obj, path, tokenizedPath, 
-                            tokenIndex + 1, tokenIndex);
+                    CayenneDataObject cdo = (CayenneDataObject) obj;
+                    Object rest = cdo.readNestedProperty(pathRemainder);
+
                     if (rest instanceof Collection) {
                         /**
-                         * We don't want nested collections.
-                         * E.g. readNestedProperty("paintingArray.paintingTitle") should return List<String>
+                         * We don't want nested collections. E.g.
+                         * readNestedProperty("paintingArray.paintingTitle") should return
+                         * List<String>
                          */
                         result.addAll((Collection<?>) rest);
                     }
@@ -174,42 +193,12 @@ public class CayenneDataObject extends P
         }
         else {
             // read the rest of the path via introspection
-            return PropertyUtils.getProperty(property, path.substring(pathIndex));
-        }
-    }
-
-    private static final String[] tokenizePath(String path) {
-        if (path == null) {
-            throw new NullPointerException("Null property path.");
-        }
-
-        if (path.length() == 0) {
-            throw new IllegalArgumentException("Empty property path.");
-        }
-
-        // take a shortcut for simple properties
-        if (!path.contains(".")) {
-            return new String[] {
-                path
-            };
-        }
-
-        StringTokenizer tokens = new StringTokenizer(path, ".");
-        int length = tokens.countTokens();
-        String[] tokenized = new String[length];
-        for (int i = 0; i < length; i++) {
-            String temp = tokens.nextToken();
-            if(temp.endsWith("+")){
-                tokenized[i] = temp.substring(0, temp.length() - 1);
-            }
-            else{
-                tokenized[i] = temp;
-            }
+            return PropertyUtils.getProperty(property, pathRemainder);
         }
-        return tokenized;
     }
 
     private final Object readSimpleProperty(String property) {
+                
         // side effect - resolves HOLLOW object
         Object object = readProperty(property);