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 2015/05/23 14:34:16 UTC

cayenne git commit: CAY-1902 Implement resolving Db paths for DataObjects

Repository: cayenne
Updated Branches:
  refs/heads/master 81e879e12 -> 47428da03


CAY-1902 Implement resolving Db paths for DataObjects

* adapted 04/30/2015 patch by John Huss


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/47428da0
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/47428da0
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/47428da0

Branch: refs/heads/master
Commit: 47428da03e4ad08d431a37cf0447cb90a5093167
Parents: 81e879e
Author: aadamchik <aa...@apache.org>
Authored: Sat May 23 15:01:36 2015 +0300
Committer: aadamchik <aa...@apache.org>
Committed: Sat May 23 15:33:04 2015 +0300

----------------------------------------------------------------------
 .../apache/cayenne/exp/parser/ASTDbPath.java    | 66 +++++++++++++++++++-
 .../apache/cayenne/exp/parser/ASTDbPathIT.java  | 43 +++++++++++++
 .../apache/cayenne/exp/parser/ASTEqualIT.java   |  2 +-
 docs/doc/src/main/resources/RELEASE-NOTES.txt   |  1 +
 4 files changed, 110 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/47428da0/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTDbPath.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTDbPath.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTDbPath.java
index ade49ee..7de3d75 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTDbPath.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTDbPath.java
@@ -20,15 +20,25 @@
 package org.apache.cayenne.exp.parser;
 
 import java.io.IOException;
+import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.cayenne.Cayenne;
+import org.apache.cayenne.DataRow;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.ObjectId;
 import org.apache.cayenne.Persistent;
 import org.apache.cayenne.access.DataContext;
 import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
 import org.apache.cayenne.map.Entity;
+import org.apache.cayenne.query.SelectById;
+import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.util.CayenneMapEntry;
 
 /**
  * Path expression traversing DB relationships and attributes.
@@ -62,7 +72,10 @@ public class ASTDbPath extends ASTPath {
 		}
 
 		Map<?, ?> map = toMap(o);
-		return (map != null) ? map.get(path) : null;
+		int finalDotIndex = path.lastIndexOf('.');
+		String finalPathComponent = finalDotIndex == -1 ? path : path.substring(finalDotIndex + 1);
+
+		return (map != null) ? map.get(finalPathComponent) : null;
 	}
 
 	protected Map<?, ?> toMap(Object o) {
@@ -71,6 +84,7 @@ public class ASTDbPath extends ASTPath {
 		} else if (o instanceof ObjectId) {
 			return ((ObjectId) o).getIdSnapshot();
 		} else if (o instanceof Persistent) {
+
 			Persistent persistent = (Persistent) o;
 
 			// before reading full snapshot, check if we can use smaller ID
@@ -83,12 +97,62 @@ public class ASTDbPath extends ASTPath {
 	}
 
 	private Map<?, ?> toMap_AttachedObject(ObjectContext context, Persistent persistent) {
+		return path.indexOf('.') >= 0 ? toMap_AttchedObject_MultiStepPath(context, persistent)
+				: toMap_AttchedObject_SingleStepPath(context, persistent);
+	}
+
+	private Map<?, ?> toMap_AttchedObject_MultiStepPath(ObjectContext context, Persistent persistent) {
+		Iterator<CayenneMapEntry> pathComponents = Cayenne.getObjEntity(persistent).getDbEntity()
+				.resolvePathComponents(this);
+		LinkedList<DbRelationship> reversedPathComponents = new LinkedList<DbRelationship>();
+
+		while (pathComponents.hasNext()) {
+			CayenneMapEntry component = pathComponents.next();
+			if (component instanceof DbRelationship) {
+				DbRelationship rel = (DbRelationship) component;
+				DbRelationship reverseRelationship = rel.getReverseRelationship();
+				if (reverseRelationship == null) {
+					reverseRelationship = rel.createReverseRelationship();
+				}
+				reversedPathComponents.addFirst(reverseRelationship);
+			} else {
+				break; // an attribute can only occur at the end of the path
+			}
+		}
+
+		DbEntity finalEntity = reversedPathComponents.get(0).getSourceEntity();
+
+		StringBuilder reversedPathStr = new StringBuilder();
+		for (int i = 0; i < reversedPathComponents.size(); i++) {
+			reversedPathStr.append(reversedPathComponents.get(i).getName());
+			if (i < reversedPathComponents.size() - 1) {
+				reversedPathStr.append('.');
+			}
+		}
+
+		SelectQuery<DataRow> query = new SelectQuery<DataRow>(finalEntity, ExpressionFactory.matchDbExp(
+				reversedPathStr.toString(), persistent));
+
+		// TODO: DbEntity root option for ObjectSelect?
+		query.setFetchingDataRows(true);
+		DataRow result = persistent.getObjectContext().selectOne(query);
+		return result;
+	}
+
+	private Map<?, ?> toMap_AttchedObject_SingleStepPath(ObjectContext context, Persistent persistent) {
+		ObjectId oid = persistent.getObjectId();
 
 		// TODO: snapshotting API should not be limited to DataContext...
 		if (context instanceof DataContext) {
 			return ((DataContext) context).currentSnapshot(persistent);
 		}
 
+		if (oid != null) {
+
+			return SelectById.dataRowQuery(persistent.getObjectId()).selectOne(context);
+		}
+
+		// fallback to ID snapshot as a last resort
 		return toMap_DetachedObject(persistent);
 	}
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/47428da0/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTDbPathIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTDbPathIT.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTDbPathIT.java
index 8f5e69f..4ea0b6f 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTDbPathIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTDbPathIT.java
@@ -19,6 +19,7 @@
 package org.apache.cayenne.exp.parser;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import org.apache.cayenne.Cayenne;
@@ -30,6 +31,7 @@ import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.testdo.testmap.Artist;
+import org.apache.cayenne.testdo.testmap.Painting;
 import org.apache.cayenne.unit.di.server.CayenneProjects;
 import org.apache.cayenne.unit.di.server.ServerCase;
 import org.apache.cayenne.unit.di.server.UseServerRuntime;
@@ -69,4 +71,45 @@ public class ASTDbPathIT extends ServerCase {
 		assertTrue(dbTarget instanceof DbAttribute);
 	}
 
+	@Test
+	public void testEvaluate_Related_DataObject() {
+
+		Artist a1 = context.newObject(Artist.class);
+		Artist a2 = context.newObject(Artist.class);
+		Painting p1 = context.newObject(Painting.class);
+		Painting p2 = context.newObject(Painting.class);
+		Painting p3 = context.newObject(Painting.class);
+
+		a1.setArtistName("a1");
+		a2.setArtistName("a2");
+		p1.setPaintingTitle("p1");
+		p2.setPaintingTitle("p2");
+		p3.setPaintingTitle("p3");
+
+		p1.setToArtist(a1);
+		p2.setToArtist(a2);
+
+		context.commitChanges();
+
+		Expression attributeOnlyPath = new ASTDbPath("PAINTING_TITLE");
+		Expression singleStepPath = new ASTDbPath("toArtist.ARTIST_NAME");
+		Expression multiStepPath = new ASTDbPath("toArtist.paintingArray.PAINTING_TITLE");
+
+		// attribute only path
+		assertEquals(p1.getPaintingTitle(), attributeOnlyPath.evaluate(p1));
+		assertEquals(p2.getPaintingTitle(), attributeOnlyPath.evaluate(p2));
+
+		// attribute only path - not in cache
+		p1.getObjectContext().invalidateObjects(p1, p2);
+		assertEquals(p1.getPaintingTitle(), attributeOnlyPath.evaluate(p1));
+		assertEquals(p2.getPaintingTitle(), attributeOnlyPath.evaluate(p2));
+
+		// single step relationship path
+		assertEquals(a1.getArtistName(), singleStepPath.evaluate(p1));
+		assertEquals(a2.getArtistName(), singleStepPath.evaluate(p2));
+		assertNull(singleStepPath.evaluate(p3));
+
+		assertEquals(p1.getPaintingTitle(), multiStepPath.evaluate(p1));
+		assertEquals(p2.getPaintingTitle(), multiStepPath.evaluate(p2));
+	}
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/47428da0/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTEqualIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTEqualIT.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTEqualIT.java
index 5b056f2..deec1a9 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTEqualIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTEqualIT.java
@@ -90,7 +90,7 @@ public class ASTEqualIT extends ServerCase {
 		Painting p1 = context.newObject(Painting.class);
 		Painting p2 = context.newObject(Painting.class);
 		Painting p3 = context.newObject(Painting.class);
-		
+
 		a1.setArtistName("a1");
 		a2.setArtistName("a2");
 		p1.setPaintingTitle("p1");

http://git-wip-us.apache.org/repos/asf/cayenne/blob/47428da0/docs/doc/src/main/resources/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --git a/docs/doc/src/main/resources/RELEASE-NOTES.txt b/docs/doc/src/main/resources/RELEASE-NOTES.txt
index 3b827e8..0ab98b0 100644
--- a/docs/doc/src/main/resources/RELEASE-NOTES.txt
+++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt
@@ -15,6 +15,7 @@ Date:
 Changes/New Features:
 
 CAY-1626 Add JodaTime DateTime support
+CAY-1902 Implement resolving Db paths for DataObjects
 CAY-1991 More control over generated String property names
 CAY-1992 Allow to exclude DataMap java class from Modeler class generation
 CAY-1995 Add support for iterators to Select