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 2008/05/05 15:26:14 UTC

svn commit: r653475 - in /cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src: main/java/org/apache/cayenne/access/trans/ main/java/org/apache/cayenne/map/ main/java/org/apache/cayenne/wocompat/ test/java/org/apache/cayenne/map/

Author: aadamchik
Date: Mon May  5 06:26:13 2008
New Revision: 653475

URL: http://svn.apache.org/viewvc?rev=653475&view=rev
Log:
CAY-802  Split Expressions
(switching to the new path iterator)

Modified:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/QueryAssemblerHelper.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/AliasPathComponent.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DbEntity.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/Entity.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/PathComponentIterator.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/wocompat/EOQuery.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/map/ObjEntityTest.java

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/QueryAssemblerHelper.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/QueryAssemblerHelper.java?rev=653475&r1=653474&r2=653475&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/QueryAssemblerHelper.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/QueryAssemblerHelper.java Mon May  5 06:26:13 2008
@@ -33,7 +33,6 @@
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbJoin;
 import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.EmbeddableAttribute;
 import org.apache.cayenne.map.JoinType;
 import org.apache.cayenne.map.ObjAttribute;
 import org.apache.cayenne.map.ObjEntity;
@@ -84,8 +83,8 @@
         return getQueryAssembler().getRootDbEntity();
     }
 
-    /** 
-     * Processes parts of the OBJ_PATH expression. 
+    /**
+     * Processes parts of the OBJ_PATH expression.
      */
     protected void appendObjPath(StringBuffer buf, Expression pathExp) {
 
@@ -319,18 +318,22 @@
             if (op instanceof Expression) {
                 Expression expression = (Expression) op;
                 if (expression.getType() == Expression.OBJ_PATH) {
-                    Object last = getObjEntity().lastPathComponent(expression);
+                    PathComponent<ObjAttribute, ObjRelationship> last = getObjEntity()
+                            .lastPathComponent(
+                                    expression,
+                                    queryAssembler.getJoinAliases());
+
                     // TODO: handle EmbeddableAttribute
-                    if (last instanceof EmbeddableAttribute)
-                        break;
+                    // if (last instanceof EmbeddableAttribute)
+                    // break;
 
-                    if (last instanceof ObjAttribute) {
-                        attribute = ((ObjAttribute) last).getDbAttribute();
+                    if (last.getAttribute() != null) {
+                        attribute = last.getAttribute().getDbAttribute();
                         break;
                     }
-                    else if (last instanceof ObjRelationship) {
-                        ObjRelationship objRelationship = (ObjRelationship) last;
-                        List<DbRelationship> dbPath = objRelationship
+                    else if (last.getRelationship() != null) {
+                        List<DbRelationship> dbPath = last
+                                .getRelationship()
                                 .getDbRelationships();
                         if (dbPath.size() > 0) {
                             relationship = dbPath.get(dbPath.size() - 1);
@@ -339,13 +342,16 @@
                     }
                 }
                 else if (expression.getType() == Expression.DB_PATH) {
-                    Object last = getDbEntity().lastPathComponent(expression);
-                    if (last instanceof DbAttribute) {
-                        attribute = (DbAttribute) last;
+                    PathComponent<DbAttribute, DbRelationship> last = getDbEntity()
+                            .lastPathComponent(
+                                    expression,
+                                    queryAssembler.getJoinAliases());
+                    if (last.getAttribute() != null) {
+                        attribute = last.getAttribute();
                         break;
                     }
-                    else if (last instanceof DbRelationship) {
-                        relationship = (DbRelationship) last;
+                    else if (last.getRelationship() != null) {
+                        relationship = last.getRelationship();
                         break;
                     }
                 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/AliasPathComponent.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/AliasPathComponent.java?rev=653475&r1=653474&r2=653475&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/AliasPathComponent.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/AliasPathComponent.java Mon May  5 06:26:13 2008
@@ -18,8 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.map;
 
-import java.util.Collections;
-import java.util.Iterator;
+import java.util.Collection;
 
 /**
  * Represents an alias for the relationship path.
@@ -30,29 +29,18 @@
 class AliasPathComponent<T extends Attribute, U extends Relationship> implements
         PathComponent<T, U> {
 
-    private Entity root;
     private String alias;
-    private String path;
+    private Collection<PathComponent<T, U>> path;
     private boolean last;
 
-    AliasPathComponent(Entity root, String alias, String path, boolean last) {
-        this.root = root;
+    AliasPathComponent(String alias, Collection<PathComponent<T, U>> path, boolean last) {
         this.alias = alias;
         this.path = path;
         this.last = last;
     }
 
     public Iterable<PathComponent<T, U>> getAliasedPath() {
-        return new Iterable<PathComponent<T, U>>() {
-
-            // suppress warning until we parameterize Entity as Entity<T extends
-            // Attribute, U extends Relationship>
-            @SuppressWarnings("unchecked")
-            public Iterator iterator() {
-                return new PathComponentIterator(root, path, Collections
-                        .<String, String> emptyMap());
-            }
-        };
+        return path;
     }
 
     public T getAttribute() {

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DbEntity.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DbEntity.java?rev=653475&r1=653474&r2=653475&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DbEntity.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DbEntity.java Mon May  5 06:26:13 2008
@@ -268,6 +268,17 @@
     public SortedMap<String, DbRelationship> getRelationshipMap() {
         return (SortedMap<String, DbRelationship>) super.getRelationshipMap();
     }
+    
+    /**
+     * @since 3.0
+     */
+    @Override
+    @SuppressWarnings("unchecked")
+    public PathComponent<DbAttribute, DbRelationship> lastPathComponent(
+            Expression path,
+            Map aliasMap) {
+        return super.lastPathComponent(path, aliasMap);
+    }
 
     /**
      * Returns an Iterable instance over expression path components based on this entity.

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/Entity.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/Entity.java?rev=653475&r1=653474&r2=653475&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/Entity.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/Entity.java Mon May  5 06:26:13 2008
@@ -288,23 +288,62 @@
      * {@link ObjAttribute} or an {@link ObjRelationship}.
      * 
      * @since 1.1
+     * @deprecated since 3.0 use {@link #lastPathComponent(Expression, Map)} method that
+     *             supports aliases.
      */
-    // TODO: andrus 2008/05/03 - support aliases?
-    public Object lastPathComponent(Expression pathExp) {
+    public Object lastPathComponent(Expression path) {
 
-        for (PathComponent<Attribute, Relationship> component : resolvePath(
-                pathExp,
-                Collections.EMPTY_MAP)) {
+        PathComponent<Attribute, Relationship> last = lastPathComponent(
+                path,
+                Collections.EMPTY_MAP);
+        if (last != null) {
+            return last.getAttribute() != null ? last.getAttribute() : last
+                    .getRelationship();
+        }
+
+        return null;
+    }
+
+    /**
+     * Convenience method returning the last component in the path iterator. If the last
+     * component is an alias, it is fully resolved down to the last ObjRelationship.
+     * 
+     * @since 3.0
+     */
+    @SuppressWarnings("unchecked")
+    public <T extends Attribute, U extends Relationship> PathComponent<T, U> lastPathComponent(
+            Expression path,
+            Map aliasMap) {
+
+        for (PathComponent component : resolvePath(path, aliasMap)) {
             if (component.isLast()) {
-                return component.getAttribute() != null
-                        ? component.getAttribute()
-                        : component.getRelationship();
+
+                // resolve aliases if needed
+                return lastPathComponent(component);
             }
         }
 
         return null;
     }
 
+    @SuppressWarnings("unchecked")
+    private PathComponent lastPathComponent(
+            PathComponent<Attribute, Relationship> component) {
+        
+        if (!component.isAlias()) {
+            return component;
+        }
+
+        for (PathComponent subcomponent : component.getAliasedPath()) {
+            if (subcomponent.isLast()) {
+                return lastPathComponent(subcomponent);
+            }
+        }
+
+        throw new IllegalStateException("Invalid last path component: "
+                + component.getName());
+    }
+
     /**
      * Returns an Iterable over the path components with elements represented as
      * {@link PathComponent} instances, encapsulating a relationship, an attribute or a

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java?rev=653475&r1=653474&r2=653475&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java Mon May  5 06:26:13 2008
@@ -829,6 +829,17 @@
 
         return (superEntity != null) ? superEntity.isSubentityOf(entity) : false;
     }
+    
+    /**
+     * @since 3.0
+     */
+    @Override
+    @SuppressWarnings("unchecked")
+    public PathComponent<ObjAttribute, ObjRelationship> lastPathComponent(
+            Expression path,
+            Map aliasMap) {
+        return super.lastPathComponent(path, aliasMap);
+    }
 
     /**
      * Returns an Iterable instance over expression path components based on this entity.

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/PathComponentIterator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/PathComponentIterator.java?rev=653475&r1=653474&r2=653475&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/PathComponentIterator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/PathComponentIterator.java Mon May  5 06:26:13 2008
@@ -18,6 +18,9 @@
  ****************************************************************/
 package org.apache.cayenne.map;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.StringTokenizer;
@@ -84,23 +87,63 @@
 
         String aliasedPath = (aliasMap != null) ? aliasMap.get(pathComp) : null;
         if (aliasedPath != null) {
-            // TODO: andrus 5/3/2008 - reset current entity to skip the aliased path
-            return new AliasPathComponent<Attribute, Relationship>(
+
+            // a few fairly arbitrary assumptions.... if we find that they restrict valid
+            // and useful cases, we can change this behavior:
+            // 
+            // 1. No nested aliases. Aliased path must contain only unaliased component
+            // names.
+            // 2. Subpath must be relationship-only. Aliasing attributes doesn't seem
+            // useful, so we don't handle this case for simplicity...
+
+            // fully resolve subpath here... since we need to know the target entity of
+            // the subpath, we have to fully traverse it, hence instead of lazy iterator
+            // we might as well reuse obtained information in the AliasPathComponent
+
+            Iterator<PathComponent<Attribute, Relationship>> subpathIt = new PathComponentIterator(
                     currentEntity,
-                    pathComp,
                     aliasedPath,
+                    Collections.EMPTY_MAP);
+
+            Collection<PathComponent<Attribute, Relationship>> parsedSubpath = new ArrayList<PathComponent<Attribute, Relationship>>(
+                    4);
+
+            while (subpathIt.hasNext()) {
+                PathComponent<Attribute, Relationship> subpathComponent = subpathIt
+                        .next();
+
+                Relationship subpathRelationship = subpathComponent.getRelationship();
+                if (subpathRelationship == null) {
+                    throw invalidPathException(
+                            "Expected a relationship in the aliased subpath. Alias ["
+                                    + pathComp
+                                    + "]",
+                            subpathComponent.getName());
+                }
+
+                currentEntity = subpathRelationship.getTargetEntity();
+                parsedSubpath.add(subpathComponent);
+            }
+
+            return new AliasPathComponent<Attribute, Relationship>(
+                    pathComp,
+                    parsedSubpath,
                     !hasNext());
         }
 
-        // build error message
-        StringBuilder buf = new StringBuilder();
-        buf
-                .append("Can't resolve path component: [")
+        throw invalidPathException("Can't resolve path component", pathComp);
+    }
+
+    private ExpressionException invalidPathException(String message, String pathComponent) {
+        StringBuilder buffer = new StringBuilder();
+        buffer
+                .append(message)
+                .append(": [")
                 .append(currentEntity.getName())
                 .append('.')
-                .append(pathComp)
+                .append(pathComponent)
                 .append("].");
-        throw new ExpressionException(buf.toString(), path, null);
+        return new ExpressionException(buffer.toString(), path, null);
     }
 
     public void remove() {

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/wocompat/EOQuery.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/wocompat/EOQuery.java?rev=653475&r1=653474&r2=653475&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/wocompat/EOQuery.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/wocompat/EOQuery.java Mon May  5 06:26:13 2008
@@ -21,6 +21,7 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -468,7 +469,7 @@
 
             Expression keyExp = Expression.fromString(key);
             try {
-                entity.lastPathComponent(keyExp);
+                entity.lastPathComponent(keyExp, Collections.emptyMap());
             }
             catch (ExpressionException e) {
                 keyExp = entity.translateToDbPath(keyExp);

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/map/ObjEntityTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/map/ObjEntityTest.java?rev=653475&r1=653474&r2=653475&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/map/ObjEntityTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/map/ObjEntityTest.java Mon May  5 06:26:13 2008
@@ -19,6 +19,9 @@
 
 package org.apache.cayenne.map;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import org.apache.art.Artist;
 import org.apache.cayenne.CayenneDataObject;
 import org.apache.cayenne.CayenneRuntimeException;
@@ -29,7 +32,10 @@
 
 public class ObjEntityTest extends CayenneCase {
 
-    public void testLastPathComponent() {
+    /**
+     * @deprecated since 3.0 as the method being tested is deprecated.
+     */
+    public void testLastPathComponentLegacy() {
         ObjEntity artistE = getObjEntity("Artist");
 
         Object lastAttribute = artistE.lastPathComponent(Expression
@@ -48,6 +54,37 @@
         assertEquals("toGallery", ((ObjRelationship) lastLeftJoinRelationship).getName());
     }
 
+    public void testLastPathComponent() {
+        ObjEntity artistE = getObjEntity("Artist");
+
+        Map<String, String> aliases = new HashMap<String, String>();
+        aliases.put("a", "paintingArray.toGallery");
+
+        PathComponent<ObjAttribute, ObjRelationship> lastAttribute = artistE
+                .lastPathComponent(
+                        Expression.fromString("paintingArray.paintingTitle"),
+                        aliases);
+        assertTrue(lastAttribute.getAttribute() != null);
+        assertEquals("paintingTitle", lastAttribute.getAttribute().getName());
+
+        PathComponent<ObjAttribute, ObjRelationship> lastRelationship = artistE
+                .lastPathComponent(
+                        Expression.fromString("paintingArray.toGallery"),
+                        aliases);
+        assertTrue(lastRelationship.getRelationship() != null);
+        assertEquals("toGallery", lastRelationship.getRelationship().getName());
+
+        PathComponent<ObjAttribute, ObjRelationship> lastLeftJoinRelationship = artistE
+                .lastPathComponent(new ASTObjPath("paintingArray+.toGallery+"), aliases);
+        assertTrue(lastLeftJoinRelationship.getRelationship() != null);
+        assertEquals("toGallery", lastLeftJoinRelationship.getRelationship().getName());
+
+        PathComponent<ObjAttribute, ObjRelationship> lastAliasedRelationship = artistE
+                .lastPathComponent(new ASTObjPath("a"), aliases);
+        assertTrue(lastAliasedRelationship.getRelationship() != null);
+        assertEquals("toGallery", lastAliasedRelationship.getRelationship().getName());
+    }
+
     public void testGeneric() {
         ObjEntity e1 = new ObjEntity("e1");
         assertTrue(e1.isGeneric());