Author: aadamchik
Date: Wed Aug 8 06:51:45 2007
New Revision: 563882
URL: http://svn.apache.org/viewvc?view=rev&rev=563882
Log:
CAY-843 Remove arbitrary reverse relationship mapping limitations
(runtime done - untested)
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/conf/RuntimeLoadDelegate.java
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/map/ObjRelationship.java
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/map/Relationship.java
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/project/ApplicationProject.java
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/project/ApplicationProjectUpgradeTest.java
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/conf/RuntimeLoadDelegate.java
URL:
http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/conf/RuntimeLoadDelegate.java?view=diff&rev=563882&r1=563881&r2=563882
==============================================================================
---
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/conf/RuntimeLoadDelegate.java
(original)
+++
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/conf/RuntimeLoadDelegate.java
Wed Aug 8 06:51:45 2007
@@ -26,13 +26,19 @@
import javax.sql.DataSource;
+import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.ConfigurationException;
import org.apache.cayenne.access.DataDomain;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.dba.AutoAdapter;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.Entity;
import org.apache.cayenne.map.MapLoader;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.InputSource;
@@ -458,10 +464,12 @@
}
}
- // update configuration object
+ // load missing relationships and update configuration object
Iterator it = getDomains().values().iterator();
while (it.hasNext()) {
- config.addDomain((DataDomain) it.next());
+ DataDomain domain = (DataDomain) it.next();
+ updateDefaults(domain);
+ config.addDomain(domain);
}
config.setDataViewLocations(views);
@@ -469,6 +477,81 @@
logger.info("finished configuration loading in "
+ (System.currentTimeMillis() - startTime)
+ " ms.");
+ }
+
+ /**
+ * Updates missing mapping artefacts that can be guessed from other mapping
+ * information. This implementation creates missing reverse relationships,
marking
+ * newly created relationships as "runtime".
+ *
+ * @since 3.0
+ */
+ protected void updateDefaults(DataDomain domain) {
+
+ // connect DB layer
+ Iterator maps = domain.getDataMaps().iterator();
+ while (maps.hasNext()) {
+ DataMap map = (DataMap) maps.next();
+
+ Iterator entities = map.getDbEntities().iterator();
+ while (entities.hasNext()) {
+ DbEntity entity = (DbEntity) entities.next();
+
+ // iterate by copy to avoid concurrency modification errors on
reflexive
+ // relationships
+ Object[] relationships = entity.getRelationships().toArray();
+ for (int i = 0; i < relationships.length; i++) {
+ DbRelationship relationship = (DbRelationship)
relationships[i];
+ if (relationship.getReverseRelationship() == null) {
+ DbRelationship reverse =
relationship.createReverseRelationship();
+
+ Entity targetEntity = reverse.getSourceEntity();
+
reverse.setName(makeUniqueRelationshipName(targetEntity));
+ reverse.setRuntime(true);
+ targetEntity.addRelationship(reverse);
+ }
+ }
+ }
+ }
+
+ // connect object layer
+ maps = domain.getDataMaps().iterator();
+ while (maps.hasNext()) {
+ DataMap map = (DataMap) maps.next();
+
+ Iterator entities = map.getObjEntities().iterator();
+ while (entities.hasNext()) {
+ ObjEntity entity = (ObjEntity) entities.next();
+
+ // iterate by copy to avoid concurrency modification errors on
reflexive
+ // relationships
+ Object[] relationships = entity.getRelationships().toArray();
+ for (int i = 0; i < relationships.length; i++) {
+ ObjRelationship relationship = (ObjRelationship)
relationships[i];
+ if (relationship.getReverseRelationship() == null) {
+ ObjRelationship reverse = relationship
+ .createReverseRelationship();
+
+ Entity targetEntity = reverse.getSourceEntity();
+
reverse.setName(makeUniqueRelationshipName(targetEntity));
+ reverse.setRuntime(true);
+ targetEntity.addRelationship(reverse);
+ }
+ }
+ }
+ }
+ }
+
+ private String makeUniqueRelationshipName(Entity entity) {
+ for (int i = 0; i < 1000; i++) {
+ String name = "runtimeRelationship" + i;
+ if(entity.getRelationship(name) == null) {
+ return name;
+ }
+ }
+
+ throw new CayenneRuntimeException(
+ "Could not come up with a unique relationship name");
}
/**
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/map/ObjRelationship.java
URL:
http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/map/ObjRelationship.java?view=diff&rev=563882&r1=563881&r2=563882
==============================================================================
---
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/map/ObjRelationship.java
(original)
+++
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/map/ObjRelationship.java
Wed Aug 8 06:51:45 2007
@@ -173,6 +173,22 @@
}
/**
+ * Creates a complimentary reverse relationship from target entity to the
source
+ * entity. A new relationship is created regardless of whether one already
exists.
+ * Returned relationship is not attached to the source entity and has no
name. Throws
+ * a [EMAIL PROTECTED] CayenneRuntimeException} if reverse DbRelationship
is not mapped.
+ *
+ * @since 3.0
+ */
+ public ObjRelationship createReverseRelationship() {
+ ObjRelationship reverse = new ObjRelationship();
+ reverse.setSourceEntity(getTargetEntity());
+ reverse.setTargetEntityName(getSourceEntity().getName());
+ reverse.setDbRelationshipPath(getReverseDbRelationshipPath());
+ return reverse;
+ }
+
+ /**
* Returns an immutable list of underlying DbRelationships.
*/
public List getDbRelationships() {
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/map/Relationship.java
URL:
http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/map/Relationship.java?view=diff&rev=563882&r1=563881&r2=563882
==============================================================================
---
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/map/Relationship.java
(original)
+++
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/map/Relationship.java
Wed Aug 8 06:51:45 2007
@@ -163,10 +163,16 @@
isToMany()).toString();
}
+ /**
+ * @since 3.0
+ */
public boolean isRuntime() {
return runtime;
}
+ /**
+ * @since 3.0
+ */
public void setRuntime(boolean synthetic) {
this.runtime = synthetic;
}
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/project/ApplicationProject.java
URL:
http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/project/ApplicationProject.java?view=diff&rev=563882&r1=563881&r2=563882
==============================================================================
---
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/project/ApplicationProject.java
(original)
+++
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/project/ApplicationProject.java
Wed Aug 8 06:51:45 2007
@@ -213,6 +213,10 @@
public ProjectLoader(Configuration config) {
super(config, config.getLoadStatus());
}
+
+ protected void updateDefaults(DataDomain domain) {
+ // do nothing...
+ }
public void shouldLoadDataDomain(String domainName) {
super.shouldLoadDataDomain(domainName);
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/project/ApplicationProjectUpgradeTest.java
URL:
http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/project/ApplicationProjectUpgradeTest.java?view=diff&rev=563882&r1=563881&r2=563882
==============================================================================
---
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/project/ApplicationProjectUpgradeTest.java
(original)
+++
cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/project/ApplicationProjectUpgradeTest.java
Wed Aug 8 06:51:45 2007
@@ -124,7 +124,7 @@
assertNotNull(dn.getAdapter());
assertEquals(MySQLAdapter.class.getName(),
dn.getAdapter().getClass().getName());
assertEquals(DriverDataSourceFactory.class.getName(),
dn.getDataSourceFactory());
-
+
DataMap testmap = dd.getMap("testmap");
assertNotNull(testmap);
SQLTemplate query = (SQLTemplate)
testmap.getQuery("NonSelectingQuery");
@@ -137,6 +137,10 @@
protected Configuration buildProjectConfiguration(File projectFile) {
ProjectConfiguration config = new ProjectConfiguration(projectFile);
config.setLoaderDelegate(new RuntimeLoadDelegate(config, new
ConfigStatus()) {
+
+ protected void updateDefaults(DataDomain domain) {
+ // do nothing...
+ }
protected DataNode createDataNode(String nodeName) {
return new DataNode(nodeName) {