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