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 2007/09/24 14:53:46 UTC

svn commit: r578793 - in /cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src: main/java/org/apache/cayenne/ main/java/org/apache/cayenne/access/ main/java/org/apache/cayenne/map/ main/java/org/apache/cayenne/reflect/ main/java/org/apache/cayen...

Author: aadamchik
Date: Mon Sep 24 05:53:44 2007
New Revision: 578793

URL: http://svn.apache.org/viewvc?rev=578793&view=rev
Log:
CAY-848 Support for mapping to-many as Maps and Sets and Collections
changed map key reading algorithm to support default objectid keys

Added:
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/MultiColumnIdMapKeyAccessor.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/PropertyAccessor.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/SingleColumnIdMapKeyAccessor.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/IdMapToMany.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/IdMapToManyTarget.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/auto/
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/auto/_IdMapToMany.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/auto/_IdMapToManyTarget.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/testdo/relationship/IdMapToMany.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/testdo/relationship/IdMapToManyTarget.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/testdo/relationship/auto/_IdMapToMany.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/testdo/relationship/auto/_IdMapToManyTarget.java
Modified:
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/CayenneDataObject.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/DataDomainSyncBucket.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/ToManyMapFault.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/reflect/FaultFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/PersistentDescriptorFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/SingletonFaultFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/ToManyMapProperty.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/generic/DataObjectDescriptorFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/generic/DataObjectToManyMapProperty.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/pojo/EnhancedPojoDescriptorFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/pojo/EnhancedPojoMapProperty.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/util/PersistentObjectMap.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/CDOMapRelationshipTest.java
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/resources/dml/CDOMapRelationshipTest.xml
    cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/resources/relationships.map.xml

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/CayenneDataObject.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/CayenneDataObject.java?rev=578793&r1=578792&r2=578793&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/CayenneDataObject.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/CayenneDataObject.java Mon Sep 24 05:53:44 2007
@@ -39,7 +39,10 @@
 import org.apache.cayenne.map.ObjAttribute;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.ObjRelationship;
+import org.apache.cayenne.reflect.ClassDescriptor;
+import org.apache.cayenne.reflect.Property;
 import org.apache.cayenne.reflect.PropertyUtils;
+import org.apache.cayenne.reflect.ToManyMapProperty;
 import org.apache.cayenne.validation.BeanValidationFailure;
 import org.apache.cayenne.validation.ValidationFailure;
 import org.apache.cayenne.validation.ValidationResult;
@@ -363,18 +366,25 @@
      * 
      * @since 3.0
      */
-    protected Object getMapKey(String relationshipName, Object value) {
+    private Object getMapKey(String relationshipName, Object value) {
 
         EntityResolver resolver = objectContext.getEntityResolver();
-        ObjEntity entity = resolver.getObjEntity(objectId.getEntityName());
+        ClassDescriptor descriptor = resolver
+                .getClassDescriptor(objectId.getEntityName());
 
-        if (entity == null) {
+        if (descriptor == null) {
             throw new IllegalStateException("DataObject's entity is unmapped, objectId: "
                     + objectId);
         }
 
-        ObjRelationship rel = (ObjRelationship) entity.getRelationship(relationshipName);
-        return rel.getMapKeyExpression().evaluate(value);
+        Property property = descriptor.getProperty(relationshipName);
+        if (property instanceof ToManyMapProperty) {
+            return ((ToManyMapProperty) property).getMapKey(value);
+        }
+
+        throw new IllegalArgumentException("Relationship '"
+                + relationshipName
+                + "' is not a to-many Map");
     }
 
     /**

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/DataDomainSyncBucket.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/DataDomainSyncBucket.java?rev=578793&r1=578792&r2=578793&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/DataDomainSyncBucket.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/DataDomainSyncBucket.java Mon Sep 24 05:53:44 2007
@@ -26,7 +26,6 @@
 import java.util.List;
 import java.util.Map;
 
-import org.apache.commons.collections.Factory;
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.DataObject;
 import org.apache.cayenne.DataRow;
@@ -40,7 +39,9 @@
 import org.apache.cayenne.reflect.ArcProperty;
 import org.apache.cayenne.reflect.AttributeProperty;
 import org.apache.cayenne.reflect.ClassDescriptor;
+import org.apache.cayenne.reflect.PropertyException;
 import org.apache.cayenne.reflect.ToManyMapProperty;
+import org.apache.commons.collections.Factory;
 
 /**
  * A superclass of batch query wrappers.
@@ -243,12 +244,43 @@
 
                         Object source = arc.readPropertyDirectly(object);
                         if (source != null && !reverseArc.isFault(source)) {
-                            reverseArc.remapTarget(source, object);
+                            remapTarget(reverseArc, source, object);
                         }
                     }
                 }
             }
         }
+    }
+
+    private final void remapTarget(
+            ToManyMapProperty property,
+            Object source,
+            Object target) throws PropertyException {
+
+        Map map = (Map) property.readProperty(source);
+        Object newKey = property.getMapKey(target);
+        Object currentValue = map.get(newKey);
+
+        if (currentValue == target) {
+            // nothing to do
+            return;
+        }
+        // else - do not check for conflicts here (i.e. another object mapped for the same
+        // key), as we have no control of the order in which this method is called, so
+        // another object may be remapped later by the caller
+
+        // must do a slow map scan to ensure the object is not mapped under a different
+        // key...
+        Iterator it = map.entrySet().iterator();
+        while (it.hasNext()) {
+            Map.Entry e = (Map.Entry) it.next();
+            if (e.getValue() == target) {
+                it.remove();
+                break;
+            }
+        }
+
+        map.put(newKey, target);
     }
 
     // a factory for extracting PKs generated on commit.

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/ToManyMapFault.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/ToManyMapFault.java?rev=578793&r1=578792&r2=578793&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/ToManyMapFault.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/access/ToManyMapFault.java Mon Sep 24 05:53:44 2007
@@ -20,7 +20,7 @@
 
 import org.apache.cayenne.Fault;
 import org.apache.cayenne.Persistent;
-import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.reflect.Accessor;
 import org.apache.cayenne.util.PersistentObjectMap;
 
 /**
@@ -29,13 +29,13 @@
  */
 public class ToManyMapFault extends Fault {
 
-    protected Expression mapKeyExpression;
+    protected Accessor mapKeyAccessor;
 
-    public ToManyMapFault(Expression mapKeyExpression) {
-        this.mapKeyExpression = mapKeyExpression;
+    public ToManyMapFault(Accessor mapKeyAccessor) {
+        this.mapKeyAccessor = mapKeyAccessor;
     }
 
     public Object resolveFault(Persistent sourceObject, String relationshipName) {
-        return new PersistentObjectMap(sourceObject, relationshipName, mapKeyExpression);
+        return new PersistentObjectMap(sourceObject, relationshipName, mapKeyAccessor);
     }
 }

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?rev=578793&r1=578792&r2=578793&view=diff
==============================================================================
--- 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 Mon Sep 24 05:53:44 2007
@@ -26,15 +26,14 @@
 import java.util.List;
 import java.util.ListIterator;
 
-import org.apache.commons.lang.builder.ToStringBuilder;
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.event.EventManager;
-import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.exp.ExpressionException;
 import org.apache.cayenne.exp.parser.ASTDbPath;
 import org.apache.cayenne.map.event.RelationshipEvent;
 import org.apache.cayenne.util.Util;
 import org.apache.cayenne.util.XMLEncoder;
+import org.apache.commons.lang.builder.ToStringBuilder;
 
 /**
  * Describes navigational association between two Java classes, represented as source and
@@ -76,8 +75,6 @@
      */
     protected String mapKey;
 
-    protected transient Expression mapKeyExpression;
-
     public ObjRelationship() {
         this(null);
     }
@@ -761,20 +758,5 @@
      */
     public void setMapKey(String mapKey) {
         this.mapKey = mapKey;
-
-        // reset
-        this.mapKeyExpression = null;
-    }
-
-    public Expression getMapKeyExpression() {
-        if (mapKey == null) {
-            return null;
-        }
-
-        if (mapKeyExpression == null) {
-            mapKeyExpression = Expression.fromString(mapKey);
-        }
-
-        return mapKeyExpression;
     }
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/FaultFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/FaultFactory.java?rev=578793&r1=578792&r2=578793&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/FaultFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/FaultFactory.java Mon Sep 24 05:53:44 2007
@@ -19,7 +19,6 @@
 package org.apache.cayenne.reflect;
 
 import org.apache.cayenne.Fault;
-import org.apache.cayenne.exp.Expression;
 
 /**
  * @since 3.0
@@ -32,8 +31,8 @@
     Fault getListFault();
 
     Fault getCollectionFault();
-    
+
     Fault getSetFault();
-    
-    Fault getMapFault(Expression mapKeyExpression);
+
+    Fault getMapFault(Accessor mapKeyAccessor);
 }

Added: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/MultiColumnIdMapKeyAccessor.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/MultiColumnIdMapKeyAccessor.java?rev=578793&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/MultiColumnIdMapKeyAccessor.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/MultiColumnIdMapKeyAccessor.java Mon Sep 24 05:53:44 2007
@@ -0,0 +1,50 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.reflect;
+
+import org.apache.cayenne.Persistent;
+
+/**
+ * A stateless read-only accessor of the map key value that is based on the Persistent
+ * object multi-column id.
+ * 
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+public final class MultiColumnIdMapKeyAccessor implements Accessor {
+
+    public static final Accessor SHARED_ACCESSOR = new MultiColumnIdMapKeyAccessor();
+
+    public String getName() {
+        return "MultiColumnIdMapKeyAccessor";
+    }
+
+    public Object getValue(Object object) throws PropertyException {
+        if (object instanceof Persistent) {
+            return ((Persistent) object).getObjectId();
+        }
+        else {
+            throw new IllegalArgumentException("Object must be Persistent: " + object);
+        }
+    }
+
+    public void setValue(Object object, Object newValue) throws PropertyException {
+        throw new UnsupportedOperationException("Setting map key is not supported");
+    }
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/PersistentDescriptorFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/PersistentDescriptorFactory.java?rev=578793&r1=578792&r2=578793&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/PersistentDescriptorFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/PersistentDescriptorFactory.java Mon Sep 24 05:53:44 2007
@@ -222,6 +222,29 @@
     }
 
     /**
+     * Creates an accessor to read a map key for a given relationship.
+     */
+    protected Accessor createMapKeyAccessor(
+            ObjRelationship relationship,
+            ClassDescriptor targetDescriptor) {
+
+        String mapKey = relationship.getMapKey();
+        if (mapKey != null) {
+            return new PropertyAccessor(targetDescriptor.getProperty(mapKey));
+        }
+
+        // do not use 'targetDescriptor' to resolve target entity, as it leads to an
+        // endless loop during the phase when descriptos are not fully initialized
+        ObjEntity targetEntity = (ObjEntity) relationship.getTargetEntity();
+        if (targetEntity.getDbEntity().getPrimaryKey().size() > 1) {
+            return MultiColumnIdMapKeyAccessor.SHARED_ACCESSOR;
+        }
+        else {
+            return SingleColumnIdMapKeyAccessor.SHARED_ACCESSOR;
+        }
+    }
+
+    /**
      * Creates an accessor for the property of the embeddable class.
      */
     protected Accessor createEmbeddableAccessor(

Added: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/PropertyAccessor.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/PropertyAccessor.java?rev=578793&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/PropertyAccessor.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/PropertyAccessor.java Mon Sep 24 05:53:44 2007
@@ -0,0 +1,49 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.reflect;
+
+/**
+ * A utility accessor class that wraps a simple property.
+ * 
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+public class PropertyAccessor implements Accessor {
+
+    protected Property property;
+
+    public PropertyAccessor(Property property) {
+        if (property == null) {
+            throw new NullPointerException("Null property");
+        }
+        this.property = property;
+    }
+
+    public String getName() {
+        return property.getName();
+    }
+
+    public Object getValue(Object object) throws PropertyException {
+        return property.readProperty(object);
+    }
+
+    public void setValue(Object object, Object newValue) throws PropertyException {
+        property.writeProperty(object, null, newValue);
+    }
+}

Added: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/SingleColumnIdMapKeyAccessor.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/SingleColumnIdMapKeyAccessor.java?rev=578793&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/SingleColumnIdMapKeyAccessor.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/SingleColumnIdMapKeyAccessor.java Mon Sep 24 05:53:44 2007
@@ -0,0 +1,51 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.reflect;
+
+import org.apache.cayenne.DataObjectUtils;
+import org.apache.cayenne.Persistent;
+
+/**
+ * A stateless read-only accessor of the map key value that is based on the Persistent
+ * object single-column id.
+ * 
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+public final class SingleColumnIdMapKeyAccessor implements Accessor {
+
+    public static final Accessor SHARED_ACCESSOR = new SingleColumnIdMapKeyAccessor();
+
+    public String getName() {
+        return "SingleColumnIdMapKeyAccessor";
+    }
+
+    public Object getValue(Object object) throws PropertyException {
+        if (object instanceof Persistent) {
+            return DataObjectUtils.pkForObject((Persistent) object);
+        }
+        else {
+            throw new IllegalArgumentException("Object must be Persistent: " + object);
+        }
+    }
+
+    public void setValue(Object object, Object newValue) throws PropertyException {
+        throw new UnsupportedOperationException("Setting map key is not supported");
+    }
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/SingletonFaultFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/SingletonFaultFactory.java?rev=578793&r1=578792&r2=578793&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/SingletonFaultFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/SingletonFaultFactory.java Mon Sep 24 05:53:44 2007
@@ -26,7 +26,6 @@
 import org.apache.cayenne.access.ToManyMapFault;
 import org.apache.cayenne.access.ToManySetFault;
 import org.apache.cayenne.access.ToOneFault;
-import org.apache.cayenne.exp.Expression;
 
 /**
  * @since 3.0
@@ -46,14 +45,14 @@
     public Fault getListFault() {
         return listFault;
     }
-
-    public Fault getMapFault(Expression mapKeyExpression) {
+    
+    public Fault getMapFault(Accessor mapKeyAccessor) {
         synchronized (mapFaults) {
-            Fault fault = (Fault) mapFaults.get(mapKeyExpression.toString());
+            Fault fault = (Fault) mapFaults.get(mapKeyAccessor);
 
             if (fault == null) {
-                fault = new ToManyMapFault(mapKeyExpression);
-                mapFaults.put(mapKeyExpression, fault);
+                fault = new ToManyMapFault(mapKeyAccessor);
+                mapFaults.put(mapKeyAccessor, fault);
             }
 
             return fault;

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/ToManyMapProperty.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/ToManyMapProperty.java?rev=578793&r1=578792&r2=578793&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/ToManyMapProperty.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/ToManyMapProperty.java Mon Sep 24 05:53:44 2007
@@ -27,8 +27,7 @@
 public interface ToManyMapProperty extends ToManyProperty {
 
     /**
-     * Updates target map key in the source relationship map to match the "map" property
-     * of the object.
+     * Extracts the map key of the target object.
      */
-    void remapTarget(Object source, Object target) throws PropertyException;
+    Object getMapKey(Object target) throws PropertyException;
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/generic/DataObjectDescriptorFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/generic/DataObjectDescriptorFactory.java?rev=578793&r1=578792&r2=578793&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/generic/DataObjectDescriptorFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/generic/DataObjectDescriptorFactory.java Mon Sep 24 05:53:44 2007
@@ -18,9 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.reflect.generic;
 
-import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.DataObject;
-import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.map.ObjAttribute;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.ObjRelationship;
@@ -85,16 +83,13 @@
             ObjRelationship relationship) {
         ClassDescriptor targetDescriptor = descriptorMap.getDescriptor(relationship
                 .getTargetEntityName());
-        Expression mapKey = relationship.getMapKeyExpression();
-        if (mapKey == null) {
-            throw new CayenneRuntimeException("Null map key for map relationship: "
-                    + relationship.getName());
-        }
+
+        Accessor mapKeyAccessor = createMapKeyAccessor(relationship, targetDescriptor);
         descriptor.addDeclaredProperty(new DataObjectToManyMapProperty(
                 relationship,
                 targetDescriptor,
-                faultFactory.getMapFault(mapKey),
-                mapKey));
+                faultFactory.getMapFault(mapKeyAccessor),
+                mapKeyAccessor));
     }
 
     protected void createToManySetProperty(

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/generic/DataObjectToManyMapProperty.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/generic/DataObjectToManyMapProperty.java?rev=578793&r1=578792&r2=578793&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/generic/DataObjectToManyMapProperty.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/generic/DataObjectToManyMapProperty.java Mon Sep 24 05:53:44 2007
@@ -18,12 +18,9 @@
  ****************************************************************/
 package org.apache.cayenne.reflect.generic;
 
-import java.util.Iterator;
-import java.util.Map;
-
 import org.apache.cayenne.Fault;
-import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.map.ObjRelationship;
+import org.apache.cayenne.reflect.Accessor;
 import org.apache.cayenne.reflect.ClassDescriptor;
 import org.apache.cayenne.reflect.PropertyException;
 import org.apache.cayenne.reflect.ToManyMapProperty;
@@ -35,44 +32,15 @@
 class DataObjectToManyMapProperty extends DataObjectToManyProperty implements
         ToManyMapProperty {
 
-    private Expression mapKey;
+    private Accessor mapKeyAccessor;
 
     DataObjectToManyMapProperty(ObjRelationship relationship,
-            ClassDescriptor targetDescriptor, Fault fault, Expression mapKey) {
+            ClassDescriptor targetDescriptor, Fault fault, Accessor mapKeyAccessor) {
         super(relationship, targetDescriptor, fault);
-        this.mapKey = mapKey;
+        this.mapKeyAccessor = mapKeyAccessor;
     }
 
-    public void remapTarget(Object source, Object target) throws PropertyException {
-
-        if (target == null) {
-            throw new NullPointerException("Null target");
-        }
-
-        Map map = (Map) readProperty(source);
-
-        Object newKey = mapKey.evaluate(target);
-        Object currentValue = map.get(newKey);
-
-        if (currentValue == target) {
-            // nothing to do
-            return;
-        }
-        // else - do not check for conflicts here (i.e. another object mapped for the same
-        // key), as we have no control of the order in which this method is called, so
-        // another object may be remapped later by the caller
-
-        // must do a slow map scan to ensure the object is not mapped under a different
-        // key...
-        Iterator it = map.entrySet().iterator();
-        while (it.hasNext()) {
-            Map.Entry e = (Map.Entry) it.next();
-            if (e.getValue() == target) {
-                it.remove();
-                break;
-            }
-        }
-
-        map.put(newKey, target);
+    public Object getMapKey(Object target) throws PropertyException {
+        return mapKeyAccessor.getValue(target);
     }
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/pojo/EnhancedPojoDescriptorFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/pojo/EnhancedPojoDescriptorFactory.java?rev=578793&r1=578792&r2=578793&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/pojo/EnhancedPojoDescriptorFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/pojo/EnhancedPojoDescriptorFactory.java Mon Sep 24 05:53:44 2007
@@ -90,11 +90,13 @@
                 .getTargetEntityName());
         String reverseName = relationship.getReverseRelationshipName();
         Accessor accessor = createAccessor(descriptor, relationship.getName(), Map.class);
+        Accessor mapKeyAccessor = createMapKeyAccessor(relationship, targetDescriptor);
         Property property = new EnhancedPojoMapProperty(
                 descriptor,
                 targetDescriptor,
                 accessor,
-                reverseName);
+                reverseName,
+                mapKeyAccessor);
 
         descriptor.addDeclaredProperty(property);
     }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/pojo/EnhancedPojoMapProperty.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/pojo/EnhancedPojoMapProperty.java?rev=578793&r1=578792&r2=578793&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/pojo/EnhancedPojoMapProperty.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/reflect/pojo/EnhancedPojoMapProperty.java Mon Sep 24 05:53:44 2007
@@ -18,12 +18,8 @@
  ****************************************************************/
 package org.apache.cayenne.reflect.pojo;
 
-import java.util.Iterator;
-import java.util.Map;
-
 import org.apache.cayenne.Persistent;
 import org.apache.cayenne.ValueHolder;
-import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.reflect.Accessor;
 import org.apache.cayenne.reflect.ClassDescriptor;
 import org.apache.cayenne.reflect.PropertyException;
@@ -37,52 +33,19 @@
 class EnhancedPojoMapProperty extends EnhancedPojoToManyProperty implements
         ToManyMapProperty {
 
-    private Expression mapKey;
+    private Accessor mapKeyAccessor;
 
     EnhancedPojoMapProperty(ClassDescriptor owner, ClassDescriptor targetDescriptor,
-            Accessor accessor, String reverseName) {
+            Accessor accessor, String reverseName, Accessor mapKeyAccessor) {
         super(owner, targetDescriptor, accessor, reverseName);
-
-        this.mapKey = getRelationship().getMapKeyExpression();
+        this.mapKeyAccessor = mapKeyAccessor;
     }
 
     protected ValueHolder createValueHolder(Persistent relationshipOwner) {
-        return new PersistentObjectMap(relationshipOwner, getName(), mapKey);
+        return new PersistentObjectMap(relationshipOwner, getName(), mapKeyAccessor);
     }
 
-    public void remapTarget(Object source, Object target) throws PropertyException {
-        // TODO: andrus, 9/24/2007 - this is an clone of the remapTarget method in
-        // DataObjectToManyMapProperty that is a part of a different inheritance
-        // hierarchy... need to reconcile that somehow...
-
-        if (target == null) {
-            throw new NullPointerException("Null target");
-        }
-
-        Map map = (Map) readProperty(source);
-
-        Object newKey = mapKey.evaluate(target);
-        Object currentValue = map.get(newKey);
-
-        if (currentValue == target) {
-            // nothing to do
-            return;
-        }
-        // else - do not check for conflicts here (i.e. another object mapped for the same
-        // key), as we have no control of the order in which this method is called, so
-        // another object may be remapped later by the caller
-
-        // must do a slow map scan to ensure the object is not mapped under a different
-        // key...
-        Iterator it = map.entrySet().iterator();
-        while (it.hasNext()) {
-            Map.Entry e = (Map.Entry) it.next();
-            if (e.getValue() == target) {
-                it.remove();
-                break;
-            }
-        }
-
-        map.put(newKey, target);
+    public Object getMapKey(Object target) throws PropertyException {
+        return mapKeyAccessor.getValue(target);
     }
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/util/PersistentObjectMap.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/util/PersistentObjectMap.java?rev=578793&r1=578792&r2=578793&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/util/PersistentObjectMap.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/main/java/org/apache/cayenne/util/PersistentObjectMap.java Mon Sep 24 05:53:44 2007
@@ -28,7 +28,7 @@
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.Persistent;
 import org.apache.cayenne.ValueHolder;
-import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.reflect.Accessor;
 
 /**
  * @since 3.0
@@ -37,25 +37,24 @@
 public class PersistentObjectMap extends RelationshipFault implements Map, ValueHolder {
 
     protected Map objectMap;
-    protected Expression mapKeyExpression;
+    protected Accessor mapKeyAccessor;
 
     // exists for the benefit of manual serialization schemes such as the one in Hessian.
     private PersistentObjectMap() {
     }
-    
+
     /**
      * Creates PersistentObjectList initializing it with list owner persistent object and
      * relationship name that this list maps to.
      * 
      * @param relationshipOwner persistent object that owns this list.
      * @param relationshipName a query used to resolve the list
-     * @param mapKeyExpression a Cayenne expression that resolves to a map key for the
-     *            target entity.
+     * @param mapKeyAccessor an accessor that can read a map key from an object.
      */
     public PersistentObjectMap(Persistent relationshipOwner, String relationshipName,
-            Expression mapKeyExpression) {
+            Accessor mapKeyAccessor) {
         super(relationshipOwner, relationshipName);
-        this.mapKeyExpression = mapKeyExpression;
+        this.mapKeyAccessor = mapKeyAccessor;
     }
 
     public Object getValue() throws CayenneRuntimeException {
@@ -162,7 +161,7 @@
             Iterator it = collection.iterator();
             while (it.hasNext()) {
                 Object next = it.next();
-                Object key = mapKeyExpression.evaluate(next);
+                Object key = mapKeyAccessor.getValue(next);
                 Object previous = map.put(key, next);
                 if (previous != null && previous != next) {
                     throw new CayenneRuntimeException("Duplicate key '"

Added: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/IdMapToMany.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/IdMapToMany.java?rev=578793&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/IdMapToMany.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/IdMapToMany.java Mon Sep 24 05:53:44 2007
@@ -0,0 +1,10 @@
+package org.apache.cayenne.testdo.relationship;
+
+import org.apache.cayenne.testdo.relationship.auto._IdMapToMany;
+
+public class IdMapToMany extends _IdMapToMany {
+
+}
+
+
+

Added: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/IdMapToManyTarget.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/IdMapToManyTarget.java?rev=578793&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/IdMapToManyTarget.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/IdMapToManyTarget.java Mon Sep 24 05:53:44 2007
@@ -0,0 +1,10 @@
+package org.apache.cayenne.testdo.relationship;
+
+import org.apache.cayenne.testdo.relationship.auto._IdMapToManyTarget;
+
+public class IdMapToManyTarget extends _IdMapToManyTarget {
+
+}
+
+
+

Added: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/auto/_IdMapToMany.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/auto/_IdMapToMany.java?rev=578793&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/auto/_IdMapToMany.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/auto/_IdMapToMany.java Mon Sep 24 05:53:44 2007
@@ -0,0 +1,25 @@
+package org.apache.cayenne.testdo.relationship.auto;
+
+/** Class _IdMapToMany was generated by Cayenne.
+  * It is probably a good idea to avoid changing this class manually, 
+  * since it may be overwritten next time code is regenerated. 
+  * If you need to make any customizations, please use subclass. 
+  */
+public abstract class _IdMapToMany extends org.apache.cayenne.CayenneDataObject {
+
+    public static final String TARGETS_PROPERTY = "targets";
+
+    public static final String ID_PK_COLUMN = "ID";
+
+    public void addToTargets(org.apache.cayenne.testdo.relationship.IdMapToManyTarget obj) {
+        addToManyTarget("targets", obj, true);
+    }
+    public void removeFromTargets(org.apache.cayenne.testdo.relationship.IdMapToManyTarget obj) {
+        removeToManyTarget("targets", obj, true);
+    }
+    public java.util.Map getTargets() {
+        return (java.util.Map)readProperty("targets");
+    }
+    
+    
+}

Added: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/auto/_IdMapToManyTarget.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/auto/_IdMapToManyTarget.java?rev=578793&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/auto/_IdMapToManyTarget.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/classes/org/apache/cayenne/testdo/relationship/auto/_IdMapToManyTarget.java Mon Sep 24 05:53:44 2007
@@ -0,0 +1,23 @@
+package org.apache.cayenne.testdo.relationship.auto;
+
+/** Class _IdMapToManyTarget was generated by Cayenne.
+  * It is probably a good idea to avoid changing this class manually, 
+  * since it may be overwritten next time code is regenerated. 
+  * If you need to make any customizations, please use subclass. 
+  */
+public abstract class _IdMapToManyTarget extends org.apache.cayenne.CayenneDataObject {
+
+    public static final String MAP_TO_MANY_PROPERTY = "mapToMany";
+
+    public static final String ID_PK_COLUMN = "ID";
+
+    public void setMapToMany(org.apache.cayenne.testdo.relationship.IdMapToMany mapToMany) {
+        setToOneTarget("mapToMany", mapToMany, true);
+    }
+
+    public org.apache.cayenne.testdo.relationship.IdMapToMany getMapToMany() {
+        return (org.apache.cayenne.testdo.relationship.IdMapToMany)readProperty("mapToMany");
+    } 
+    
+    
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/CDOMapRelationshipTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/CDOMapRelationshipTest.java?rev=578793&r1=578792&r2=578793&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/CDOMapRelationshipTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/CDOMapRelationshipTest.java Mon Sep 24 05:53:44 2007
@@ -23,6 +23,7 @@
 import org.apache.cayenne.exp.ExpressionFactory;
 import org.apache.cayenne.query.RefreshQuery;
 import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.testdo.relationship.IdMapToMany;
 import org.apache.cayenne.testdo.relationship.MapToMany;
 import org.apache.cayenne.testdo.relationship.MapToManyTarget;
 import org.apache.cayenne.unit.RelationshipCase;
@@ -54,6 +55,29 @@
         assertEquals(1, DataObjectUtils.intPKForObject((Persistent) targets.get("A")));
         assertEquals(2, DataObjectUtils.intPKForObject((Persistent) targets.get("B")));
         assertEquals(3, DataObjectUtils.intPKForObject((Persistent) targets.get("C")));
+    }
+    
+    public void testReadToManyId() throws Exception {
+        createTestData("prepare-id");
+
+        IdMapToMany o1 = (IdMapToMany) DataObjectUtils.objectForPK(
+                createDataContext(),
+                IdMapToMany.class,
+                1);
+
+        Map targets = o1.getTargets();
+
+        assertTrue(((ValueHolder) targets).isFault());
+
+        assertNotNull(targets);
+        assertEquals(3, targets.size());
+        assertNotNull(targets.get(new Integer(1)));
+        assertNotNull(targets.get(new Integer(2)));
+        assertNotNull(targets.get(new Integer(3)));
+
+        assertEquals(1, DataObjectUtils.intPKForObject((Persistent) targets.get(new Integer(1))));
+        assertEquals(2, DataObjectUtils.intPKForObject((Persistent) targets.get(new Integer(2))));
+        assertEquals(3, DataObjectUtils.intPKForObject((Persistent) targets.get(new Integer(3))));
     }
 
     public void testReadToManyPrefetching() throws Exception {

Added: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/testdo/relationship/IdMapToMany.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/testdo/relationship/IdMapToMany.java?rev=578793&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/testdo/relationship/IdMapToMany.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/testdo/relationship/IdMapToMany.java Mon Sep 24 05:53:44 2007
@@ -0,0 +1,10 @@
+package org.apache.cayenne.testdo.relationship;
+
+import org.apache.cayenne.testdo.relationship.auto._IdMapToMany;
+
+public class IdMapToMany extends _IdMapToMany {
+
+}
+
+
+

Added: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/testdo/relationship/IdMapToManyTarget.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/testdo/relationship/IdMapToManyTarget.java?rev=578793&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/testdo/relationship/IdMapToManyTarget.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/testdo/relationship/IdMapToManyTarget.java Mon Sep 24 05:53:44 2007
@@ -0,0 +1,10 @@
+package org.apache.cayenne.testdo.relationship;
+
+import org.apache.cayenne.testdo.relationship.auto._IdMapToManyTarget;
+
+public class IdMapToManyTarget extends _IdMapToManyTarget {
+
+}
+
+
+

Added: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/testdo/relationship/auto/_IdMapToMany.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/testdo/relationship/auto/_IdMapToMany.java?rev=578793&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/testdo/relationship/auto/_IdMapToMany.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/testdo/relationship/auto/_IdMapToMany.java Mon Sep 24 05:53:44 2007
@@ -0,0 +1,25 @@
+package org.apache.cayenne.testdo.relationship.auto;
+
+/** Class _IdMapToMany was generated by Cayenne.
+  * It is probably a good idea to avoid changing this class manually, 
+  * since it may be overwritten next time code is regenerated. 
+  * If you need to make any customizations, please use subclass. 
+  */
+public abstract class _IdMapToMany extends org.apache.cayenne.CayenneDataObject {
+
+    public static final String TARGETS_PROPERTY = "targets";
+
+    public static final String ID_PK_COLUMN = "ID";
+
+    public void addToTargets(org.apache.cayenne.testdo.relationship.IdMapToManyTarget obj) {
+        addToManyTarget("targets", obj, true);
+    }
+    public void removeFromTargets(org.apache.cayenne.testdo.relationship.IdMapToManyTarget obj) {
+        removeToManyTarget("targets", obj, true);
+    }
+    public java.util.Map getTargets() {
+        return (java.util.Map)readProperty("targets");
+    }
+    
+    
+}

Added: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/testdo/relationship/auto/_IdMapToManyTarget.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/testdo/relationship/auto/_IdMapToManyTarget.java?rev=578793&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/testdo/relationship/auto/_IdMapToManyTarget.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/java/org/apache/cayenne/testdo/relationship/auto/_IdMapToManyTarget.java Mon Sep 24 05:53:44 2007
@@ -0,0 +1,23 @@
+package org.apache.cayenne.testdo.relationship.auto;
+
+/** Class _IdMapToManyTarget was generated by Cayenne.
+  * It is probably a good idea to avoid changing this class manually, 
+  * since it may be overwritten next time code is regenerated. 
+  * If you need to make any customizations, please use subclass. 
+  */
+public abstract class _IdMapToManyTarget extends org.apache.cayenne.CayenneDataObject {
+
+    public static final String MAP_TO_MANY_PROPERTY = "mapToMany";
+
+    public static final String ID_PK_COLUMN = "ID";
+
+    public void setMapToMany(org.apache.cayenne.testdo.relationship.IdMapToMany mapToMany) {
+        setToOneTarget("mapToMany", mapToMany, true);
+    }
+
+    public org.apache.cayenne.testdo.relationship.IdMapToMany getMapToMany() {
+        return (org.apache.cayenne.testdo.relationship.IdMapToMany)readProperty("mapToMany");
+    } 
+    
+    
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/resources/dml/CDOMapRelationshipTest.xml
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/resources/dml/CDOMapRelationshipTest.xml?rev=578793&r1=578792&r2=578793&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/resources/dml/CDOMapRelationshipTest.xml (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/resources/dml/CDOMapRelationshipTest.xml Mon Sep 24 05:53:44 2007
@@ -74,6 +74,81 @@
 			</value>
 		</constructor-arg>
 	</bean>
+	
+	
+	
+	
+	<bean id="OI1" class="org.apache.cayenne.unit.util.UpdatingSQLTemplate">
+		<constructor-arg type="java.lang.Class">
+			<value>org.apache.cayenne.testdo.relationship.IdMapToMany</value>
+		</constructor-arg>
+		<constructor-arg>
+			<value>
+				INSERT INTO ID_MAP_TO_MANY (ID)
+				VALUES (1)
+			</value>
+		</constructor-arg>
+	</bean>
+	
+	<bean id="OI2" class="org.apache.cayenne.unit.util.UpdatingSQLTemplate">
+		<constructor-arg type="java.lang.Class">
+			<value>org.apache.cayenne.testdo.relationship.IdMapToMany</value>
+		</constructor-arg>
+		<constructor-arg>
+			<value>
+				INSERT INTO ID_MAP_TO_MANY (ID)
+				VALUES (2)
+			</value>
+		</constructor-arg>
+	</bean>
+	
+	<bean id="OI1C1" class="org.apache.cayenne.unit.util.UpdatingSQLTemplate">
+		<constructor-arg type="java.lang.Class">
+			<value>org.apache.cayenne.testdo.relationship.IdMapToManyTarget</value>
+		</constructor-arg>
+		<constructor-arg>
+			<value>
+				INSERT INTO ID_MAP_TO_MANY_TARGET (ID, MAP_TO_MANY_ID)
+				VALUES (1, 1)
+			</value>
+		</constructor-arg>
+	</bean>
+	
+	<bean id="OI1C2" class="org.apache.cayenne.unit.util.UpdatingSQLTemplate">
+		<constructor-arg type="java.lang.Class">
+			<value>org.apache.cayenne.testdo.relationship.IdMapToManyTarget</value>
+		</constructor-arg>
+		<constructor-arg>
+			<value>
+				INSERT INTO ID_MAP_TO_MANY_TARGET (ID, MAP_TO_MANY_ID)
+				VALUES (2, 1)
+			</value>
+		</constructor-arg>
+	</bean>
+
+	<bean id="OI1C3" class="org.apache.cayenne.unit.util.UpdatingSQLTemplate">
+		<constructor-arg type="java.lang.Class">
+			<value>org.apache.cayenne.testdo.relationship.IdMapToManyTarget</value>
+		</constructor-arg>
+		<constructor-arg>
+			<value>
+				INSERT INTO ID_MAP_TO_MANY_TARGET (ID, MAP_TO_MANY_ID)
+				VALUES (3, 1)
+			</value>
+		</constructor-arg>
+	</bean>
+	
+	<bean id="OI2C1" class="org.apache.cayenne.unit.util.UpdatingSQLTemplate">
+		<constructor-arg type="java.lang.Class">
+			<value>org.apache.cayenne.testdo.relationship.IdMapToManyTarget</value>
+		</constructor-arg>
+		<constructor-arg>
+			<value>
+				INSERT INTO ID_MAP_TO_MANY_TARGET (ID, MAP_TO_MANY_ID)
+				VALUES (4, 2)
+			</value>
+		</constructor-arg>
+	</bean>
 
 	<!-- ======================================= -->
 	<!-- Data Sets -->
@@ -88,6 +163,19 @@
 				<ref bean="O1C2" />
 				<ref bean="O1C3" />
 				<ref bean="O2C1" />
+			</list>
+		</constructor-arg>
+	</bean>
+	
+	<bean id="prepare-id" class="java.util.ArrayList">
+		<constructor-arg>
+			<list>
+				<ref bean="OI1" />
+				<ref bean="OI2" />
+				<ref bean="OI1C1" />
+				<ref bean="OI1C2" />
+				<ref bean="OI1C3" />
+				<ref bean="OI2C1" />
 			</list>
 		</constructor-arg>
 	</bean>

Modified: cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/resources/relationships.map.xml
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/resources/relationships.map.xml?rev=578793&r1=578792&r2=578793&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/resources/relationships.map.xml (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.4-unpublished/src/test/resources/relationships.map.xml Mon Sep 24 05:53:44 2007
@@ -63,6 +63,13 @@
 		<db-attribute name="FT3_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
 		<db-attribute name="NAME" type="VARCHAR" isMandatory="true" length="100"/>
 	</db-entity>
+	<db-entity name="ID_MAP_TO_MANY">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
+	<db-entity name="ID_MAP_TO_MANY_TARGET">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="MAP_TO_MANY_ID" type="INTEGER"/>
+	</db-entity>
 	<db-entity name="MAP_TO_MANY">
 		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
 	</db-entity>
@@ -145,6 +152,10 @@
 	<obj-entity name="FlattenedTest3" className="org.apache.cayenne.testdo.relationship.FlattenedTest3" dbEntityName="FLATTENED_TEST_3">
 		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
 	</obj-entity>
+	<obj-entity name="IdMapToMany" className="org.apache.cayenne.testdo.relationship.IdMapToMany" dbEntityName="ID_MAP_TO_MANY">
+	</obj-entity>
+	<obj-entity name="IdMapToManyTarget" className="org.apache.cayenne.testdo.relationship.IdMapToManyTarget" dbEntityName="ID_MAP_TO_MANY_TARGET">
+	</obj-entity>
 	<obj-entity name="MapToMany" className="org.apache.cayenne.testdo.relationship.MapToMany" dbEntityName="MAP_TO_MANY">
 	</obj-entity>
 	<obj-entity name="MapToManyTarget" className="org.apache.cayenne.testdo.relationship.MapToManyTarget" dbEntityName="MAP_TO_MANY_TARGET">
@@ -244,6 +255,12 @@
 	<db-relationship name="toFT2" source="FLATTENED_TEST_3" target="FLATTENED_TEST_2" toMany="false">
 		<db-attribute-pair source="FT2_ID" target="FT2_ID"/>
 	</db-relationship>
+	<db-relationship name="targets" source="ID_MAP_TO_MANY" target="ID_MAP_TO_MANY_TARGET" toMany="true">
+		<db-attribute-pair source="ID" target="MAP_TO_MANY_ID"/>
+	</db-relationship>
+	<db-relationship name="mapToMany" source="ID_MAP_TO_MANY_TARGET" target="ID_MAP_TO_MANY" toMany="false">
+		<db-attribute-pair source="MAP_TO_MANY_ID" target="ID"/>
+	</db-relationship>
 	<db-relationship name="targets" source="MAP_TO_MANY" target="MAP_TO_MANY_TARGET" toMany="true">
 		<db-attribute-pair source="ID" target="MAP_TO_MANY_ID"/>
 	</db-relationship>
@@ -313,6 +330,8 @@
 	<obj-relationship name="toFT1" source="FlattenedTest2" target="FlattenedTest1" db-relationship-path="toFT1"/>
 	<obj-relationship name="toFT1" source="FlattenedTest3" target="FlattenedTest1" db-relationship-path="toFT2.toFT1"/>
 	<obj-relationship name="toFT2" source="FlattenedTest3" target="FlattenedTest2" db-relationship-path="toFT2"/>
+	<obj-relationship name="targets" source="IdMapToMany" target="IdMapToManyTarget" collection-type="java.util.Map" db-relationship-path="targets"/>
+	<obj-relationship name="mapToMany" source="IdMapToManyTarget" target="IdMapToMany" db-relationship-path="mapToMany"/>
 	<obj-relationship name="targets" source="MapToMany" target="MapToManyTarget" collection-type="java.util.Map" map-key="name" db-relationship-path="targets"/>
 	<obj-relationship name="mapToMany" source="MapToManyTarget" target="MapToMany" db-relationship-path="mapToMany"/>
 	<obj-relationship name="toRelationshipHelper" source="MeaningfulFK" target="RelationshipHelper" db-relationship-path="toRelationshipHelper"/>