This is an automated email from the ASF dual-hosted git repository.

ntimofeev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git

commit 05bb9ce1b22711d2e0c1ce31bc4c3de769452660
Author: Nikita Timofeev <[email protected]>
AuthorDate: Thu Mar 21 14:09:52 2019 +0300

    CAY-2555 Use explicit ArcId in GraphChangeHandler methods
---
 .../org/apache/cayenne/NestedCayenneContextIT.java | 25 +++++--
 .../cayenne/NestedCayenneContextTooneIT.java       | 16 ++--
 .../cayenne/remote/ClientChannelServerDiffsIT.java | 11 ++-
 .../cayenne/commitlog/DeletedDiffProcessor.java    |  5 +-
 .../org/apache/cayenne/commitlog/DiffFilter.java   |  5 +-
 .../apache/cayenne/commitlog/DiffProcessor.java    |  5 +-
 .../cayenne/CayenneContextChildDiffLoader.java     |  9 ++-
 .../apache/cayenne/CayenneContextGraphManager.java | 15 +++-
 .../apache/cayenne/CayenneContextMergeHandler.java | 14 +++-
 .../cayenne/DataChannelSyncCallbackAction.java     | 11 ++-
 .../apache/cayenne/ObjectContextDeleteAction.java  |  6 +-
 .../org/apache/cayenne/ObjectContextStateLog.java  | 12 ++-
 .../cayenne/access/ClientReturnDiffFilter.java     | 11 ++-
 .../org/apache/cayenne/access/DataContext.java     | 15 ++--
 .../cayenne/access/DataContextMergeHandler.java    | 14 +++-
 .../cayenne/access/DataDomainDBDiffBuilder.java    | 15 +++-
 .../access/DataDomainIndirectDiffBuilder.java      |  5 +-
 .../java/org/apache/cayenne/access/ObjectDiff.java | 23 +++---
 .../org/apache/cayenne/access/ObjectStore.java     | 13 ++--
 .../apache/cayenne/graph/ArcCreateOperation.java   |  6 +-
 .../apache/cayenne/graph/ArcDeleteOperation.java   |  6 +-
 .../main/java/org/apache/cayenne/graph/ArcId.java  | 87 ++++++++++++++++++++++
 .../org/apache/cayenne/graph/ChildDiffLoader.java  | 10 ++-
 .../apache/cayenne/graph/GraphChangeHandler.java   |  4 +-
 .../apache/cayenne/graph/GraphDiffCompressor.java  | 24 +++---
 .../java/org/apache/cayenne/graph/GraphMap.java    | 16 +++-
 .../cayenne/util/ObjectContextGraphAction.java     |  5 +-
 .../main/java/org/apache/cayenne/util/Util.java    |  5 +-
 .../org/apache/cayenne/access/DeleteRulesIT.java   | 18 ++---
 .../cayenne/unit/di/DataChannelSyncStats.java      | 11 ++-
 30 files changed, 310 insertions(+), 112 deletions(-)

diff --git 
a/cayenne-client/src/test/java/org/apache/cayenne/NestedCayenneContextIT.java 
b/cayenne-client/src/test/java/org/apache/cayenne/NestedCayenneContextIT.java
index 83fad72..8f40904 100644
--- 
a/cayenne-client/src/test/java/org/apache/cayenne/NestedCayenneContextIT.java
+++ 
b/cayenne-client/src/test/java/org/apache/cayenne/NestedCayenneContextIT.java
@@ -20,6 +20,7 @@ package org.apache.cayenne;
 
 import org.apache.cayenne.configuration.rop.client.ClientRuntime;
 import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.graph.GraphChangeHandler;
 import org.apache.cayenne.graph.GraphDiff;
 import org.apache.cayenne.query.SelectById;
@@ -261,24 +262,30 @@ public class NestedCayenneContextIT extends 
RemoteCayenneCase {
                        final int[] arcDiffs = new int[1];
 
                        diffs.apply(new GraphChangeHandler() {
-                               public void arcCreated(Object nodeId, Object 
targetNodeId, Object arcId) {
+                               @Override
+                               public void arcCreated(Object nodeId, Object 
targetNodeId, ArcId arcId) {
                                        arcDiffs[0]++;
                                }
 
-                               public void arcDeleted(Object nodeId, Object 
targetNodeId, Object arcId) {
+                               @Override
+                               public void arcDeleted(Object nodeId, Object 
targetNodeId, ArcId arcId) {
                                        arcDiffs[0]--;
                                }
 
+                               @Override
                                public void nodeCreated(Object nodeId) {
                                }
 
+                               @Override
                                public void nodeIdChanged(Object nodeId, Object 
newId) {
                                }
 
+                               @Override
                                public void nodePropertyChanged(Object nodeId,
                                                String property, Object 
oldValue, Object newValue) {
                                }
 
+                               @Override
                                public void nodeRemoved(Object nodeId) {
                                }
                        });
@@ -356,11 +363,11 @@ public class NestedCayenneContextIT extends 
RemoteCayenneCase {
                        diffs.apply(new GraphChangeHandler() {
 
                                @Override
-                               public void arcCreated(Object nodeId, Object 
targetNodeId, Object arcId) {
+                               public void arcCreated(Object nodeId, Object 
targetNodeId, ArcId arcId) {
                                }
 
                                @Override
-                               public void arcDeleted(Object nodeId, Object 
targetNodeId, Object arcId) {
+                               public void arcDeleted(Object nodeId, Object 
targetNodeId, ArcId arcId) {
                                }
 
                                @Override
@@ -644,24 +651,30 @@ public class NestedCayenneContextIT extends 
RemoteCayenneCase {
                final int[] newNodes = new int[1];
 
                diffs.apply(new GraphChangeHandler() {
-                       public void arcCreated(Object nodeId, Object 
targetNodeId, Object arcId) {
+                       @Override
+                       public void arcCreated(Object nodeId, Object 
targetNodeId, ArcId arcId) {
                                arcDiffs[0]++;
                        }
 
-                       public void arcDeleted(Object nodeId, Object 
targetNodeId, Object arcId) {
+                       @Override
+                       public void arcDeleted(Object nodeId, Object 
targetNodeId, ArcId arcId) {
                                arcDiffs[0]--;
                        }
 
+                       @Override
                        public void nodeCreated(Object nodeId) {
                                newNodes[0]++;
                        }
 
+                       @Override
                        public void nodeIdChanged(Object nodeId, Object newId) {
                        }
 
+                       @Override
                        public void nodePropertyChanged(Object nodeId, String 
property, Object oldValue, Object newValue) {
                        }
 
+                       @Override
                        public void nodeRemoved(Object nodeId) {
                                newNodes[0]--;
                        }
diff --git 
a/cayenne-client/src/test/java/org/apache/cayenne/NestedCayenneContextTooneIT.java
 
b/cayenne-client/src/test/java/org/apache/cayenne/NestedCayenneContextTooneIT.java
index 28f9875..862a50f 100644
--- 
a/cayenne-client/src/test/java/org/apache/cayenne/NestedCayenneContextTooneIT.java
+++ 
b/cayenne-client/src/test/java/org/apache/cayenne/NestedCayenneContextTooneIT.java
@@ -21,6 +21,7 @@ package org.apache.cayenne;
 
 import org.apache.cayenne.configuration.rop.client.ClientRuntime;
 import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.graph.GraphChangeHandler;
 import org.apache.cayenne.graph.GraphDiff;
 import org.apache.cayenne.query.SelectQuery;
@@ -190,27 +191,30 @@ public class NestedCayenneContextTooneIT extends 
RemoteCayenneCase {
 
         diffs.apply(new GraphChangeHandler() {
 
-            public void arcCreated(Object nodeId, Object targetNodeId,
-                                   Object arcId) {
+            @Override
+            public void arcCreated(Object nodeId, Object targetNodeId, ArcId 
arcId) {
                 arcDiffs[0]++;
             }
 
-            public void arcDeleted(Object nodeId, Object targetNodeId,
-                                   Object arcId) {
+            @Override
+            public void arcDeleted(Object nodeId, Object targetNodeId, ArcId 
arcId) {
                 arcDiffs[0]--;
             }
 
+            @Override
             public void nodeCreated(Object nodeId) {
                 newNodes[0]++;
             }
 
+            @Override
             public void nodeIdChanged(Object nodeId, Object newId) {
             }
 
-            public void nodePropertyChanged(Object nodeId, String property,
-                                            Object oldValue, Object newValue) {
+            @Override
+            public void nodePropertyChanged(Object nodeId, String property, 
Object oldValue, Object newValue) {
             }
 
+            @Override
             public void nodeRemoved(Object nodeId) {
                 newNodes[0]--;
             }
diff --git 
a/cayenne-client/src/test/java/org/apache/cayenne/remote/ClientChannelServerDiffsIT.java
 
b/cayenne-client/src/test/java/org/apache/cayenne/remote/ClientChannelServerDiffsIT.java
index 1bfdb24..6f747ff 100644
--- 
a/cayenne-client/src/test/java/org/apache/cayenne/remote/ClientChannelServerDiffsIT.java
+++ 
b/cayenne-client/src/test/java/org/apache/cayenne/remote/ClientChannelServerDiffsIT.java
@@ -24,6 +24,7 @@ import org.apache.cayenne.ObjectId;
 import org.apache.cayenne.access.ClientServerChannel;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.event.MockEventManager;
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.graph.GraphChangeHandler;
 import org.apache.cayenne.graph.GraphDiff;
 import org.apache.cayenne.map.LifecycleEvent;
@@ -227,6 +228,7 @@ public class ClientChannelServerDiffsIT extends ClientCase {
             size = 0;
         }
 
+        @Override
         public void nodePropertyChanged(
                 Object nodeId,
                 String property,
@@ -236,22 +238,27 @@ public class ClientChannelServerDiffsIT extends 
ClientCase {
             size++;
         }
 
-        public void arcCreated(Object nodeId, Object targetNodeId, Object 
arcId) {
+        @Override
+        public void arcCreated(Object nodeId, Object targetNodeId, ArcId 
arcId) {
             size++;
         }
 
-        public void arcDeleted(Object nodeId, Object targetNodeId, Object 
arcId) {
+        @Override
+        public void arcDeleted(Object nodeId, Object targetNodeId, ArcId 
arcId) {
             size++;
         }
 
+        @Override
         public void nodeCreated(Object nodeId) {
             size++;
         }
 
+        @Override
         public void nodeIdChanged(Object nodeId, Object newId) {
             size++;
         }
 
+        @Override
         public void nodeRemoved(Object nodeId) {
             size++;
         }
diff --git 
a/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/DeletedDiffProcessor.java
 
b/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/DeletedDiffProcessor.java
index a2f706f..c631cad 100644
--- 
a/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/DeletedDiffProcessor.java
+++ 
b/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/DeletedDiffProcessor.java
@@ -24,6 +24,7 @@ import org.apache.cayenne.DataChannel;
 import org.apache.cayenne.DataRow;
 import org.apache.cayenne.ObjectId;
 import org.apache.cayenne.QueryResponse;
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.graph.GraphChangeHandler;
 import org.apache.cayenne.commitlog.model.MutableChangeMap;
 import org.apache.cayenne.commitlog.model.MutableObjectChange;
@@ -129,12 +130,12 @@ class DeletedDiffProcessor implements GraphChangeHandler {
        }
 
        @Override
-       public void arcCreated(Object nodeId, Object targetNodeId, Object 
arcId) {
+       public void arcCreated(Object nodeId, Object targetNodeId, ArcId arcId) 
{
                // do nothing
        }
 
        @Override
-       public void arcDeleted(Object nodeId, Object targetNodeId, Object 
arcId) {
+       public void arcDeleted(Object nodeId, Object targetNodeId, ArcId arcId) 
{
                // do nothing
        }
 }
diff --git 
a/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/DiffFilter.java 
b/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/DiffFilter.java
index d524387..9b64208 100644
--- 
a/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/DiffFilter.java
+++ 
b/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/DiffFilter.java
@@ -19,6 +19,7 @@
 package org.apache.cayenne.commitlog;
 
 import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.graph.GraphChangeHandler;
 import org.apache.cayenne.commitlog.meta.CommitLogEntity;
 import org.apache.cayenne.commitlog.meta.CommitLogEntityFactory;
@@ -73,14 +74,14 @@ class DiffFilter implements GraphChangeHandler {
        }
 
        @Override
-       public void arcCreated(Object nodeId, Object targetNodeId, Object 
arcId) {
+       public void arcCreated(Object nodeId, Object targetNodeId, ArcId arcId) 
{
                if (entityFactory.getEntity((ObjectId) 
nodeId).isIncluded(arcId.toString())) {
                        delegate.arcCreated(nodeId, targetNodeId, arcId);
                }
        }
 
        @Override
-       public void arcDeleted(Object nodeId, Object targetNodeId, Object 
arcId) {
+       public void arcDeleted(Object nodeId, Object targetNodeId, ArcId arcId) 
{
                if (entityFactory.getEntity((ObjectId) 
nodeId).isIncluded(arcId.toString())) {
                        delegate.arcDeleted(nodeId, targetNodeId, arcId);
                }
diff --git 
a/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/DiffProcessor.java
 
b/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/DiffProcessor.java
index 849aa3a..f8518f4 100644
--- 
a/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/DiffProcessor.java
+++ 
b/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/DiffProcessor.java
@@ -19,6 +19,7 @@
 package org.apache.cayenne.commitlog;
 
 import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.graph.GraphChangeHandler;
 import org.apache.cayenne.commitlog.model.MutableChangeMap;
 import org.apache.cayenne.commitlog.model.MutableObjectChange;
@@ -64,7 +65,7 @@ class DiffProcessor implements GraphChangeHandler {
        }
 
        @Override
-       public void arcDeleted(Object nodeId, Object targetNodeId, Object 
arcId) {
+       public void arcDeleted(Object nodeId, Object targetNodeId, ArcId arcId) 
{
                ObjectId id = (ObjectId) nodeId;
                String relationshipName = arcId.toString();
 
@@ -83,7 +84,7 @@ class DiffProcessor implements GraphChangeHandler {
        }
 
        @Override
-       public void arcCreated(Object nodeId, Object targetNodeId, Object 
arcId) {
+       public void arcCreated(Object nodeId, Object targetNodeId, ArcId arcId) 
{
 
                ObjectId id = (ObjectId) nodeId;
                String relationshipName = arcId.toString();
diff --git 
a/cayenne-rop-server/src/main/java/org/apache/cayenne/CayenneContextChildDiffLoader.java
 
b/cayenne-rop-server/src/main/java/org/apache/cayenne/CayenneContextChildDiffLoader.java
index 94d30f2..6402d72 100644
--- 
a/cayenne-rop-server/src/main/java/org/apache/cayenne/CayenneContextChildDiffLoader.java
+++ 
b/cayenne-rop-server/src/main/java/org/apache/cayenne/CayenneContextChildDiffLoader.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne;
 
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.graph.ChildDiffLoader;
 import org.apache.cayenne.reflect.ArcProperty;
 import org.apache.cayenne.reflect.AttributeProperty;
@@ -52,7 +53,7 @@ class CayenneContextChildDiffLoader extends ChildDiffLoader {
     }
 
     @Override
-    public void arcCreated(Object nodeId, Object targetNodeId, Object arcId) {
+    public void arcCreated(Object nodeId, Object targetNodeId, ArcId arcId) {
 
         final Persistent source = findObject(nodeId);
         final Persistent target = findObject(targetNodeId);
@@ -83,11 +84,11 @@ class CayenneContextChildDiffLoader extends ChildDiffLoader 
{
                 return false;
             }
         });
-        context.propertyChanged(source, (String) arcId, null, target);
+        context.propertyChanged(source, arcId.toString(), null, target);
     }
 
     @Override
-    public void arcDeleted(Object nodeId, final Object targetNodeId, Object 
arcId) {
+    public void arcDeleted(Object nodeId, final Object targetNodeId, ArcId 
arcId) {
         final Persistent source = findObject(nodeId);
 
         // needed as sometime temporary objects are evoked from the context 
before
@@ -133,7 +134,7 @@ class CayenneContextChildDiffLoader extends ChildDiffLoader 
{
             }
         });
 
-        context.propertyChanged(source, (String) arcId, target[0], null);
+        context.propertyChanged(source, arcId.toString(), target[0], null);
     }
 
 }
\ No newline at end of file
diff --git 
a/cayenne-rop-server/src/main/java/org/apache/cayenne/CayenneContextGraphManager.java
 
b/cayenne-rop-server/src/main/java/org/apache/cayenne/CayenneContextGraphManager.java
index f4865c0..cfc0be6 100644
--- 
a/cayenne-rop-server/src/main/java/org/apache/cayenne/CayenneContextGraphManager.java
+++ 
b/cayenne-rop-server/src/main/java/org/apache/cayenne/CayenneContextGraphManager.java
@@ -23,6 +23,7 @@ import org.apache.cayenne.event.EventManager;
 import org.apache.cayenne.event.EventSubject;
 import org.apache.cayenne.graph.ArcCreateOperation;
 import org.apache.cayenne.graph.ArcDeleteOperation;
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.graph.GraphChangeHandler;
 import org.apache.cayenne.graph.GraphDiff;
 import org.apache.cayenne.graph.GraphEvent;
@@ -274,13 +275,13 @@ final class CayenneContextGraphManager extends GraphMap {
     }
 
     @Override
-    public synchronized void arcCreated(Object nodeId, Object targetNodeId, 
Object arcId) {
+    public synchronized void arcCreated(Object nodeId, Object targetNodeId, 
ArcId arcId) {
         stateLog.arcCreated(nodeId, targetNodeId, arcId);
         processChange(new ArcCreateOperation(nodeId, targetNodeId, arcId));
     }
 
     @Override
-    public synchronized void arcDeleted(Object nodeId, Object targetNodeId, 
Object arcId) {
+    public synchronized void arcDeleted(Object nodeId, Object targetNodeId, 
ArcId arcId) {
         stateLog.arcDeleted(nodeId, targetNodeId, arcId);
         processChange(new ArcDeleteOperation(nodeId, targetNodeId, arcId));
     }
@@ -337,20 +338,24 @@ final class CayenneContextGraphManager extends GraphMap {
      */
     class RollbackChangeHandler implements GraphChangeHandler {
 
-        public void arcCreated(Object nodeId, Object targetNodeId, Object 
arcId) {
+        @Override
+        public void arcCreated(Object nodeId, Object targetNodeId, ArcId 
arcId) {
             context.mergeHandler.arcCreated(nodeId, targetNodeId, arcId);
             CayenneContextGraphManager.this.arcCreated(nodeId, targetNodeId, 
arcId);
         }
 
-        public void arcDeleted(Object nodeId, Object targetNodeId, Object 
arcId) {
+        @Override
+        public void arcDeleted(Object nodeId, Object targetNodeId, ArcId 
arcId) {
             context.mergeHandler.arcDeleted(nodeId, targetNodeId, arcId);
             CayenneContextGraphManager.this.arcDeleted(nodeId, targetNodeId, 
arcId);
         }
 
+        @Override
         public void nodeCreated(Object nodeId) {
             CayenneContextGraphManager.this.nodeCreated(nodeId);
         }
 
+        @Override
         public void nodeIdChanged(Object nodeId, Object newId) {
             CayenneContextGraphManager.this.nodeIdChanged(nodeId, newId);
         }
@@ -358,6 +363,7 @@ final class CayenneContextGraphManager extends GraphMap {
         /**
          * Need to write property directly to this context
          */
+        @Override
         public void nodePropertyChanged(
                 Object nodeId,
                 String property,
@@ -372,6 +378,7 @@ final class CayenneContextGraphManager extends GraphMap {
                     newValue);
         }
 
+        @Override
         public void nodeRemoved(Object nodeId) {
             CayenneContextGraphManager.this.nodeRemoved(nodeId);
         }
diff --git 
a/cayenne-rop-server/src/main/java/org/apache/cayenne/CayenneContextMergeHandler.java
 
b/cayenne-rop-server/src/main/java/org/apache/cayenne/CayenneContextMergeHandler.java
index e3217a8..5ede370 100644
--- 
a/cayenne-rop-server/src/main/java/org/apache/cayenne/CayenneContextMergeHandler.java
+++ 
b/cayenne-rop-server/src/main/java/org/apache/cayenne/CayenneContextMergeHandler.java
@@ -19,6 +19,7 @@
 
 package org.apache.cayenne;
 
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.graph.GraphChangeHandler;
 import org.apache.cayenne.graph.GraphDiff;
 import org.apache.cayenne.graph.GraphEvent;
@@ -47,6 +48,7 @@ class CayenneContextMergeHandler implements 
GraphChangeHandler, DataChannelListe
 
     // ******* DataChannelListener methods *******
 
+    @Override
     public void graphChanged(final GraphEvent e) {
         // process flush
         if (shouldProcessEvent(e) && e.getDiff() != null) {
@@ -63,6 +65,7 @@ class CayenneContextMergeHandler implements 
GraphChangeHandler, DataChannelListe
         }
     }
 
+    @Override
     public void graphFlushed(final GraphEvent e) {
         // TODO (Andrus, 10/17/2005) - there are a few problems with commit 
processing:
 
@@ -92,6 +95,7 @@ class CayenneContextMergeHandler implements 
GraphChangeHandler, DataChannelListe
         }
     }
 
+    @Override
     public void graphRolledback(final GraphEvent e) {
 
         // TODO: andrus, 3/29/2007: per CAY-771, if a LOCAL peer context 
posted the event,
@@ -122,6 +126,7 @@ class CayenneContextMergeHandler implements 
GraphChangeHandler, DataChannelListe
 
     // ******* GraphChangeHandler methods *********
 
+    @Override
     public void nodeIdChanged(Object nodeId, Object newId) {
         // do not unregister the node just yet... only put replaced id in 
deadIds to
         // remove it later. Otherwise stored operations will not work
@@ -138,14 +143,17 @@ class CayenneContextMergeHandler implements 
GraphChangeHandler, DataChannelListe
         }
     }
 
+    @Override
     public void nodeCreated(Object nodeId) {
         // ignore
     }
 
+    @Override
     public void nodeRemoved(Object nodeId) {
         context.getGraphManager().unregisterNode(nodeId);
     }
 
+    @Override
     public void nodePropertyChanged(
             Object nodeId,
             String property,
@@ -164,7 +172,8 @@ class CayenneContextMergeHandler implements 
GraphChangeHandler, DataChannelListe
         }
     }
 
-    public void arcCreated(Object nodeId, Object targetNodeId, Object arcId) {
+    @Override
+    public void arcCreated(Object nodeId, Object targetNodeId, ArcId arcId) {
         // null source or target likely means the object is not faulted yet... 
Faults
         // shouldn't get disturbed by adding/removing arcs
 
@@ -194,7 +203,8 @@ class CayenneContextMergeHandler implements 
GraphChangeHandler, DataChannelListe
         }
     }
 
-    public void arcDeleted(Object nodeId, Object targetNodeId, Object arcId) {
+    @Override
+    public void arcDeleted(Object nodeId, Object targetNodeId, ArcId arcId) {
 
         // null source or target likely means the object is not faulted yet... 
Faults
         // shouldn't get disturbed by adding/removing arcs
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/DataChannelSyncCallbackAction.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/DataChannelSyncCallbackAction.java
index 4e954f3..e4608ab 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/DataChannelSyncCallbackAction.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/DataChannelSyncCallbackAction.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne;
 
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.graph.GraphChangeHandler;
 import org.apache.cayenne.graph.GraphDiff;
 import org.apache.cayenne.graph.GraphManager;
@@ -87,6 +88,7 @@ public abstract class DataChannelSyncCallbackAction 
implements GraphChangeHandle
         }
     }
 
+    @Override
     public void nodeCreated(Object nodeId) {
         Op op = seenIds.put(nodeId, Op.INSERT);
         if (op == null) {
@@ -103,6 +105,7 @@ public abstract class DataChannelSyncCallbackAction 
implements GraphChangeHandle
         }
     }
 
+    @Override
     public void nodeRemoved(Object nodeId) {
         Op op = seenIds.put(nodeId, Op.DELETE);
         
@@ -128,19 +131,23 @@ public abstract class DataChannelSyncCallbackAction 
implements GraphChangeHandle
         }
     }
 
-    public void arcCreated(Object nodeId, Object targetNodeId, Object arcId) {
+    @Override
+    public void arcCreated(Object nodeId, Object targetNodeId, ArcId arcId) {
         // TODO: andrus, 9/21/2006 - should we register to-many relationship 
updates?
         nodeUpdated(nodeId);
     }
 
-    public void arcDeleted(Object nodeId, Object targetNodeId, Object arcId) {
+    @Override
+    public void arcDeleted(Object nodeId, Object targetNodeId, ArcId arcId) {
         // TODO: andrus, 9/21/2006 - should we register to-many relationship 
updates?
         nodeUpdated(nodeId);
     }
 
+    @Override
     public void nodeIdChanged(Object nodeId, Object newId) {
     }
 
+    @Override
     public void nodePropertyChanged(
             Object nodeId,
             String property,
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/ObjectContextDeleteAction.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/ObjectContextDeleteAction.java
index e38868c..4d0f431 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/ObjectContextDeleteAction.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/ObjectContextDeleteAction.java
@@ -24,6 +24,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Map;
 
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.map.DeleteRule;
 import org.apache.cayenne.map.LifecycleEvent;
 import org.apache.cayenne.map.ObjRelationship;
@@ -161,9 +162,10 @@ class ObjectContextDeleteAction {
             // joins must be removed even if they are non-existent or ignored 
in the
             // object graph
             if (processFlattened) {
+                ArcId arcId = new ArcId(property);
                 for (Persistent relatedObject : relatedObjects) {
-                    context.getGraphManager().arcDeleted(object.getObjectId()
-                            , relatedObject.getObjectId(), 
relationship.getName());
+                    context.getGraphManager()
+                            .arcDeleted(object.getObjectId(), 
relatedObject.getObjectId(), arcId);
                 }
             }
 
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/ObjectContextStateLog.java 
b/cayenne-server/src/main/java/org/apache/cayenne/ObjectContextStateLog.java
index 25a970b..7847d8b 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/ObjectContextStateLog.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/ObjectContextStateLog.java
@@ -19,6 +19,7 @@
 
 package org.apache.cayenne;
 
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.graph.GraphChangeHandler;
 import org.apache.cayenne.graph.GraphManager;
 
@@ -28,7 +29,6 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
-import java.util.Vector;
 
 /**
  * Tracks dirty Persistent objects.
@@ -150,20 +150,24 @@ class ObjectContextStateLog implements GraphChangeHandler 
{
 
     // *** GraphChangeHandler methods
 
+    @Override
     public void nodeIdChanged(Object nodeId, Object newId) {
         if (dirtyIds.remove(nodeId)) {
             dirtyIds.add(newId);
         }
     }
 
+    @Override
     public void nodeCreated(Object nodeId) {
         dirtyIds.add(nodeId);
     }
 
+    @Override
     public void nodeRemoved(Object nodeId) {
         dirtyIds.add(nodeId);
     }
 
+    @Override
     public void nodePropertyChanged(
             Object nodeId,
             String property,
@@ -172,11 +176,13 @@ class ObjectContextStateLog implements GraphChangeHandler 
{
         dirtyIds.add(nodeId);
     }
 
-    public void arcCreated(Object nodeId, Object targetNodeId, Object arcId) {
+    @Override
+    public void arcCreated(Object nodeId, Object targetNodeId, ArcId arcId) {
         dirtyIds.add(nodeId);
     }
 
-    public void arcDeleted(Object nodeId, Object targetNodeId, Object arcId) {
+    @Override
+    public void arcDeleted(Object nodeId, Object targetNodeId, ArcId arcId) {
         dirtyIds.add(nodeId);
     }
 
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/access/ClientReturnDiffFilter.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/access/ClientReturnDiffFilter.java
index aae41da..c18e332 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/access/ClientReturnDiffFilter.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/access/ClientReturnDiffFilter.java
@@ -21,6 +21,7 @@ package org.apache.cayenne.access;
 import org.apache.cayenne.ObjectId;
 import org.apache.cayenne.graph.ArcCreateOperation;
 import org.apache.cayenne.graph.ArcDeleteOperation;
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.graph.CompoundDiff;
 import org.apache.cayenne.graph.GraphChangeHandler;
 import org.apache.cayenne.graph.GraphDiff;
@@ -57,30 +58,35 @@ class ClientReturnDiffFilter implements GraphChangeHandler {
         return new CompoundDiff(diffs);
     }
 
-    public void arcCreated(Object nodeId, Object targetNodeId, Object arcId) {
+    @Override
+    public void arcCreated(Object nodeId, Object targetNodeId, ArcId arcId) {
         if (isClientArc(nodeId, targetNodeId, arcId)) {
             diffs.add(new ArcCreateOperation(nodeId, targetNodeId, arcId));
         }
     }
 
-    public void arcDeleted(Object nodeId, Object targetNodeId, Object arcId) {
+    @Override
+    public void arcDeleted(Object nodeId, Object targetNodeId, ArcId arcId) {
         if (isClientArc(nodeId, targetNodeId, arcId)) {
             diffs.add(new ArcDeleteOperation(nodeId, targetNodeId, arcId));
         }
     }
 
+    @Override
     public void nodeCreated(Object nodeId) {
         if (isClientNode(nodeId)) {
             diffs.add(new NodeCreateOperation(nodeId));
         }
     }
 
+    @Override
     public void nodeIdChanged(Object nodeId, Object newId) {
         if (isClientNode(nodeId)) {
             diffs.add(new NodeIdChangeOperation(nodeId, newId));
         }
     }
 
+    @Override
     public void nodePropertyChanged(
             Object nodeId,
             String property,
@@ -96,6 +102,7 @@ class ClientReturnDiffFilter implements GraphChangeHandler {
         }
     }
 
+    @Override
     public void nodeRemoved(Object nodeId) {
         if (isClientNode(nodeId)) {
             diffs.add(new NodeDeleteOperation(nodeId));
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/access/DataContext.java 
b/cayenne-server/src/main/java/org/apache/cayenne/access/DataContext.java
index 57993f4..fc2f585 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DataContext.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DataContext.java
@@ -44,6 +44,7 @@ import org.apache.cayenne.ResultIterator;
 import org.apache.cayenne.access.util.IteratedSelectObserver;
 import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.event.EventManager;
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.graph.ChildDiffLoader;
 import org.apache.cayenne.graph.CompoundDiff;
 import org.apache.cayenne.graph.GraphDiff;
@@ -566,20 +567,18 @@ public class DataContext extends BaseContext {
                 if (!property.isFault(persistent)) {
 
                     Object value = property.readProperty(persistent);
-                    Collection<Map.Entry> collection = (value instanceof Map) 
? ((Map) value).entrySet()
+                    @SuppressWarnings("unchecked")
+                    Collection<Map.Entry> collection = (value instanceof Map)
+                            ? ((Map) value).entrySet()
                             : (Collection) value;
 
-                    Iterator<Map.Entry> it = collection.iterator();
-                    while (it.hasNext()) {
-                        Object target = it.next();
-
+                    for (Object target : collection) {
                         if (target instanceof Persistent) {
                             Persistent targetDO = (Persistent) target;
 
                             // make sure it is registered
                             registerNewObject(targetDO);
-                            
getObjectStore().arcCreated(persistent.getObjectId(), targetDO.getObjectId(),
-                                    property.getName());
+                            
getObjectStore().arcCreated(persistent.getObjectId(), targetDO.getObjectId(), 
new ArcId(property));
                         }
                     }
                 }
@@ -595,7 +594,7 @@ public class DataContext extends BaseContext {
 
                     // make sure it is registered
                     registerNewObject(targetDO);
-                    getObjectStore().arcCreated(persistent.getObjectId(), 
targetDO.getObjectId(), property.getName());
+                    getObjectStore().arcCreated(persistent.getObjectId(), 
targetDO.getObjectId(), new ArcId(property));
                 }
                 return true;
             }
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/access/DataContextMergeHandler.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/access/DataContextMergeHandler.java
index 6b422ea..3dcda4b 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/access/DataContextMergeHandler.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/access/DataContextMergeHandler.java
@@ -25,6 +25,7 @@ import org.apache.cayenne.PersistenceState;
 import org.apache.cayenne.Persistent;
 import org.apache.cayenne.access.ObjectStore.SnapshotEventDecorator;
 import org.apache.cayenne.access.event.SnapshotEvent;
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.graph.GraphChangeHandler;
 import org.apache.cayenne.graph.GraphDiff;
 import org.apache.cayenne.graph.GraphEvent;
@@ -87,6 +88,7 @@ class DataContextMergeHandler implements GraphChangeHandler, 
DataChannelListener
 
     // *** GraphEventListener methods
 
+    @Override
     public void graphChanged(GraphEvent event) {
         // parent received external change
         if (shouldProcessEvent(event)) {
@@ -107,6 +109,7 @@ class DataContextMergeHandler implements 
GraphChangeHandler, DataChannelListener
         }
     }
 
+    @Override
     public void graphFlushed(GraphEvent event) {
 
         // peer is committed
@@ -130,6 +133,7 @@ class DataContextMergeHandler implements 
GraphChangeHandler, DataChannelListener
         }
     }
 
+    @Override
     public void graphRolledback(GraphEvent event) {
         // TODO: andrus, 3/26/2006 - enable this once all ObjectStore diffs 
implement
         // working undo operation
@@ -141,14 +145,17 @@ class DataContextMergeHandler implements 
GraphChangeHandler, DataChannelListener
 
     // *** GraphChangeHandler methods
 
+    @Override
     public void nodeIdChanged(Object nodeId, Object newId) {
         context.getObjectStore().processIdChange(nodeId, newId);
     }
 
+    @Override
     public void nodeCreated(Object nodeId) {
         // noop
     }
 
+    @Override
     public void nodeRemoved(Object nodeId) {
         ObjectStore os = context.getObjectStore();
         synchronized (os) {
@@ -156,6 +163,7 @@ class DataContextMergeHandler implements 
GraphChangeHandler, DataChannelListener
         }
     }
 
+    @Override
     public void nodePropertyChanged(
             Object nodeId,
             String property,
@@ -173,11 +181,13 @@ class DataContextMergeHandler implements 
GraphChangeHandler, DataChannelListener
         }
     }
 
-    public void arcCreated(Object nodeId, Object targetNodeId, Object arcId) {
+    @Override
+    public void arcCreated(Object nodeId, Object targetNodeId, ArcId arcId) {
         arcChanged(nodeId, targetNodeId, arcId);
     }
 
-    public void arcDeleted(Object nodeId, Object targetNodeId, Object arcId) {
+    @Override
+    public void arcDeleted(Object nodeId, Object targetNodeId, ArcId arcId) {
         arcChanged(nodeId, targetNodeId, arcId);
     }
 
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainDBDiffBuilder.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainDBDiffBuilder.java
index 80db9c5..ea6964d 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainDBDiffBuilder.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainDBDiffBuilder.java
@@ -22,6 +22,7 @@ package org.apache.cayenne.access;
 import org.apache.cayenne.ObjectId;
 import org.apache.cayenne.access.DataDomainSyncBucket.PropagatedValueFactory;
 import org.apache.cayenne.exp.parser.ASTDbPath;
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.graph.GraphChangeHandler;
 import org.apache.cayenne.graph.GraphDiff;
 import org.apache.cayenne.map.DbAttribute;
@@ -150,6 +151,7 @@ class DataDomainDBDiffBuilder implements GraphChangeHandler 
{
     // GraphChangeHandler methods.
     // ==================================================
 
+    @Override
     public void nodePropertyChanged(Object nodeId, String property, Object 
oldValue, Object newValue) {
         // note - no checking for phantom mod... assuming there is no phantom
         // diffs
@@ -161,7 +163,8 @@ class DataDomainDBDiffBuilder implements GraphChangeHandler 
{
         currentPropertyDiff.put(property, newValue);
     }
 
-    public void arcCreated(Object nodeId, Object targetNodeId, Object arcId) {
+    @Override
+    public void arcCreated(Object nodeId, Object targetNodeId, ArcId arcId) {
         String arcIdString = arcId.toString();
         ObjRelationship relationship = objEntity.getRelationship(arcIdString);
 
@@ -184,14 +187,15 @@ class DataDomainDBDiffBuilder implements 
GraphChangeHandler {
         }
     }
 
-    private void doArcCreated(Object targetNodeId, Object arcId) {
+    private void doArcCreated(Object targetNodeId, ArcId arcId) {
         if (currentArcDiff == null) {
             currentArcDiff = new HashMap<>();
         }
         currentArcDiff.put(arcId, targetNodeId);
     }
 
-    public void arcDeleted(Object nodeId, Object targetNodeId, Object arcId) {
+    @Override
+    public void arcDeleted(Object nodeId, Object targetNodeId, ArcId arcId) {
 
         String arcIdString = arcId.toString();
         ObjRelationship relationship = objEntity.getRelationship(arcIdString);
@@ -214,7 +218,7 @@ class DataDomainDBDiffBuilder implements GraphChangeHandler 
{
         }
     }
 
-    private void doArcDeleted(Object targetNodeId, Object arcId) {
+    private void doArcDeleted(Object targetNodeId, ArcId arcId) {
         if (currentArcDiff == null) {
             currentArcDiff = new HashMap<>();
             currentArcDiff.put(arcId, null);
@@ -228,15 +232,18 @@ class DataDomainDBDiffBuilder implements 
GraphChangeHandler {
         }
     }
 
+    @Override
     public void nodeCreated(Object nodeId) {
         // need to append PK columns
         this.currentId = nodeId;
     }
 
+    @Override
     public void nodeRemoved(Object nodeId) {
         // noop
     }
 
+    @Override
     public void nodeIdChanged(Object nodeId, Object newId) {
         // noop
     }
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainIndirectDiffBuilder.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainIndirectDiffBuilder.java
index c824d6e..b7aeaf2 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainIndirectDiffBuilder.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainIndirectDiffBuilder.java
@@ -24,6 +24,7 @@ import java.util.HashSet;
 
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.graph.GraphChangeHandler;
 import org.apache.cayenne.graph.GraphDiff;
 import org.apache.cayenne.map.DbEntity;
@@ -74,7 +75,7 @@ final class DataDomainIndirectDiffBuilder implements 
GraphChangeHandler {
     }
 
     @Override
-    public void arcCreated(Object nodeId, Object targetNodeId, Object arcId) {
+    public void arcCreated(Object nodeId, Object targetNodeId, ArcId arcId) {
         ObjEntity entity = resolver.getObjEntity(((ObjectId) 
nodeId).getEntityName());
         ObjRelationship relationship = 
entity.getRelationship(arcId.toString());
 
@@ -114,7 +115,7 @@ final class DataDomainIndirectDiffBuilder implements 
GraphChangeHandler {
     }
 
     @Override
-    public void arcDeleted(Object nodeId, Object targetNodeId, Object arcId) {
+    public void arcDeleted(Object nodeId, Object targetNodeId, ArcId arcId) {
 
         ObjEntity entity = resolver.getObjEntity(((ObjectId) 
nodeId).getEntityName());
         ObjRelationship relationship = 
entity.getRelationship(arcId.toString());
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/access/ObjectDiff.java 
b/cayenne-server/src/main/java/org/apache/cayenne/access/ObjectDiff.java
index d711bcf..97080eb 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/ObjectDiff.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/ObjectDiff.java
@@ -25,6 +25,7 @@ import org.apache.cayenne.ObjectId;
 import org.apache.cayenne.PersistenceState;
 import org.apache.cayenne.Persistent;
 import org.apache.cayenne.exp.parser.ASTDbPath;
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.graph.GraphChangeHandler;
 import org.apache.cayenne.graph.GraphDiff;
 import org.apache.cayenne.graph.NodeDiff;
@@ -195,16 +196,16 @@ class ObjectDiff extends NodeDiff {
 
             ArcOperation arcDiff = (ArcOperation) diff;
             Object targetId = arcDiff.getTargetNodeId();
-            String arcId = arcDiff.getArcId().toString();
+            ArcId arcId = arcDiff.getArcId();
 
-            ArcProperty property = (ArcProperty) 
getClassDescriptor().getProperty(arcId);
+            ArcProperty property = (ArcProperty) 
getClassDescriptor().getProperty(arcId.getForwardArc());
 
             // note that some collection properties implement
             // 'SingleObjectArcProperty',
             // so we cant't do 'instanceof SingleObjectArcProperty'
             // TODO: andrus, 3.22.2006 - should we consider this a bug?
 
-            if (property == null && arcId.startsWith(ASTDbPath.DB_PREFIX)) {
+            if (property == null && 
arcId.getForwardArc().startsWith(ASTDbPath.DB_PREFIX)) {
                 addPhantomFkDiff(arcDiff);
                 addDiff = false;
             } else if (property instanceof ToManyProperty) {
@@ -232,10 +233,10 @@ class ObjectDiff extends NodeDiff {
                 } else if (property.getComplimentaryReverseArc() == null) {
 
                     // register complimentary arc diff
-                    String arc = ASTDbPath.DB_PREFIX + 
property.getComplimentaryReverseDbRelationshipPath();
-                    ArcOperation complimentartyOp = new ArcOperation(targetId, 
arcDiff.getNodeId(), arc,
-                            arcDiff.isDelete());
-                    parent.registerDiff(targetId, complimentartyOp);
+                    ArcId arc = arcId.getReverseId();
+                    //new ArcId(ASTDbPath.DB_PREFIX + 
property.getComplimentaryReverseDbRelationshipPath(), property.getName());
+                    ArcOperation complimentaryOp = new ArcOperation(targetId, 
arcDiff.getNodeId(), arc, arcDiff.isDelete());
+                    parent.registerDiff(targetId, complimentaryOp);
                 }
 
             } else if (property instanceof ToOneProperty) {
@@ -244,7 +245,7 @@ class ObjectDiff extends NodeDiff {
                     currentArcSnapshot = new HashMap<>();
                 }
 
-                currentArcSnapshot.put(arcId, targetId);
+                currentArcSnapshot.put(arcId.getForwardArc(), targetId);
             } else {
                 String message = (property == null) ? "No property for arcId " 
+ arcId
                         : "Unrecognized property for arcId " + arcId + ": " + 
property;
@@ -443,10 +444,10 @@ class ObjectDiff extends NodeDiff {
     static final class ArcOperation extends NodeDiff {
 
         private Object targetNodeId;
-        private Object arcId;
+        private ArcId arcId;
         private boolean delete;
 
-        public ArcOperation(Object nodeId, Object targetNodeId, Object arcId, 
boolean delete) {
+        ArcOperation(Object nodeId, Object targetNodeId, ArcId arcId, boolean 
delete) {
 
             super(nodeId);
             this.targetNodeId = targetNodeId;
@@ -498,7 +499,7 @@ class ObjectDiff extends NodeDiff {
             throw new UnsupportedOperationException();
         }
 
-        public Object getArcId() {
+        public ArcId getArcId() {
             return arcId;
         }
 
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/access/ObjectStore.java 
b/cayenne-server/src/main/java/org/apache/cayenne/access/ObjectStore.java
index 4bb72c2..8a821c4 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/ObjectStore.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/ObjectStore.java
@@ -29,6 +29,7 @@ import org.apache.cayenne.Persistent;
 import org.apache.cayenne.access.ObjectDiff.ArcOperation;
 import org.apache.cayenne.access.event.SnapshotEvent;
 import org.apache.cayenne.access.event.SnapshotEventListener;
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.graph.ChildDiffLoader;
 import org.apache.cayenne.graph.GraphChangeHandler;
 import org.apache.cayenne.graph.GraphDiff;
@@ -430,11 +431,11 @@ public class ObjectStore implements Serializable, 
SnapshotEventListener, GraphMa
             parentChanges.apply(new GraphChangeHandler() {
 
                 @Override
-                public void arcCreated(Object nodeId, Object targetNodeId, 
Object arcId) {
+                public void arcCreated(Object nodeId, Object targetNodeId, 
ArcId arcId) {
                 }
 
                 @Override
-                public void arcDeleted(Object nodeId, Object targetNodeId, 
Object arcId) {
+                public void arcDeleted(Object nodeId, Object targetNodeId, 
ArcId arcId) {
                 }
 
                 @Override
@@ -963,8 +964,8 @@ public class ObjectStore implements Serializable, 
SnapshotEventListener, GraphMa
      * @since 1.2
      */
     @Override
-    public void arcCreated(Object nodeId, Object targetNodeId, Object arcId) {
-        NodeDiff diff = new ArcOperation(nodeId, targetNodeId, 
arcId.toString(), false);
+    public void arcCreated(Object nodeId, Object targetNodeId, ArcId arcId) {
+        NodeDiff diff = new ArcOperation(nodeId, targetNodeId, arcId, false);
 
         if (lifecycleEventInducedChanges != null) {
             registerLifecycleEventInducedChange(diff);
@@ -977,8 +978,8 @@ public class ObjectStore implements Serializable, 
SnapshotEventListener, GraphMa
      * @since 1.2
      */
     @Override
-    public void arcDeleted(Object nodeId, Object targetNodeId, Object arcId) {
-        NodeDiff diff = new ArcOperation(nodeId, targetNodeId, 
arcId.toString(), true);
+    public void arcDeleted(Object nodeId, Object targetNodeId, ArcId arcId) {
+        NodeDiff diff = new ArcOperation(nodeId, targetNodeId, arcId, true);
 
         if (lifecycleEventInducedChanges != null) {
             registerLifecycleEventInducedChange(diff);
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/graph/ArcCreateOperation.java 
b/cayenne-server/src/main/java/org/apache/cayenne/graph/ArcCreateOperation.java
index 8182756..f36c89a 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/graph/ArcCreateOperation.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/graph/ArcCreateOperation.java
@@ -27,15 +27,15 @@ public class ArcCreateOperation extends NodeDiff {
        private static final long serialVersionUID = 2497511574121718987L;
        
        protected Object targetNodeId;
-       protected Object arcId;
+       protected ArcId arcId;
 
-       public ArcCreateOperation(Object nodeId, Object targetNodeId, Object 
arcId) {
+       public ArcCreateOperation(Object nodeId, Object targetNodeId, ArcId 
arcId) {
                super(nodeId);
                this.targetNodeId = targetNodeId;
                this.arcId = arcId;
        }
 
-       public ArcCreateOperation(Object nodeId, Object targetNodeId, Object 
arcId, int diffId) {
+       public ArcCreateOperation(Object nodeId, Object targetNodeId, ArcId 
arcId, int diffId) {
                super(nodeId, diffId);
                this.targetNodeId = targetNodeId;
                this.arcId = arcId;
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/graph/ArcDeleteOperation.java 
b/cayenne-server/src/main/java/org/apache/cayenne/graph/ArcDeleteOperation.java
index aaada17..e59507b 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/graph/ArcDeleteOperation.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/graph/ArcDeleteOperation.java
@@ -27,15 +27,15 @@ public class ArcDeleteOperation extends NodeDiff {
        private static final long serialVersionUID = 3614253207710845385L;
        
        protected Object targetNodeId;
-       protected Object arcId;
+       protected ArcId arcId;
 
-       public ArcDeleteOperation(Object nodeId, Object targetNodeId, Object 
arcId) {
+       public ArcDeleteOperation(Object nodeId, Object targetNodeId, ArcId 
arcId) {
                super(nodeId);
                this.targetNodeId = targetNodeId;
                this.arcId = arcId;
        }
 
-       public ArcDeleteOperation(Object nodeId, Object targetNodeId, Object 
arcId, int diffId) {
+       public ArcDeleteOperation(Object nodeId, Object targetNodeId, ArcId 
arcId, int diffId) {
                super(nodeId, diffId);
                this.targetNodeId = targetNodeId;
                this.arcId = arcId;
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/graph/ArcId.java 
b/cayenne-server/src/main/java/org/apache/cayenne/graph/ArcId.java
new file mode 100644
index 0000000..2a66a60
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/graph/ArcId.java
@@ -0,0 +1,87 @@
+/*****************************************************************
+ *   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.graph;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+import org.apache.cayenne.exp.parser.ASTDbPath;
+import org.apache.cayenne.reflect.ArcProperty;
+
+/**
+ * Object that represents Arc identifier.
+ * Used in graph change operations.
+ *
+ * @since 4.2
+ */
+public class ArcId implements Serializable {
+
+    private static final long serialVersionUID = -3712846298213425259L;
+
+    private final String forwardArc;
+    private final String reverseArc;
+
+    public ArcId(ArcProperty property) {
+        this.forwardArc = property.getName();
+        this.reverseArc = property.getComplimentaryReverseArc() == null
+                ? ASTDbPath.DB_PREFIX + 
property.getComplimentaryReverseDbRelationshipPath()
+                : property.getComplimentaryReverseArc().getName();
+    }
+
+    public ArcId(String forwardArc, String reverseArc) {
+        this.forwardArc = Objects.requireNonNull(forwardArc);
+        this.reverseArc = Objects.requireNonNull(reverseArc);
+    }
+
+    public String getForwardArc() {
+        return forwardArc;
+    }
+
+    public String getReverseArc() {
+        return reverseArc;
+    }
+
+    public ArcId getReverseId() {
+        return new ArcId(reverseArc, forwardArc);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ArcId arcId = (ArcId) o;
+
+        if (!forwardArc.equals(arcId.forwardArc)) return false;
+        return reverseArc.equals(arcId.reverseArc);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = forwardArc.hashCode();
+        result = 31 * result + reverseArc.hashCode();
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return forwardArc;
+    }
+}
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/graph/ChildDiffLoader.java 
b/cayenne-server/src/main/java/org/apache/cayenne/graph/ChildDiffLoader.java
index 03a9268..03d86fa 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/graph/ChildDiffLoader.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/graph/ChildDiffLoader.java
@@ -75,10 +75,12 @@ public class ChildDiffLoader implements GraphChangeHandler {
                this.context = context;
        }
 
+       @Override
        public void nodeIdChanged(Object nodeId, Object newId) {
                throw new CayenneRuntimeException("Not supported");
        }
 
+       @Override
        public void nodeCreated(Object nodeId) {
 
                setExternalChange(Boolean.TRUE);
@@ -108,6 +110,7 @@ public class ChildDiffLoader implements GraphChangeHandler {
                }
        }
 
+       @Override
        public void nodeRemoved(Object nodeId) {
                setExternalChange(Boolean.TRUE);
                Persistent object = findObject(nodeId);
@@ -122,6 +125,7 @@ public class ChildDiffLoader implements GraphChangeHandler {
                }
        }
 
+       @Override
        public void nodePropertyChanged(Object nodeId, String property, Object 
oldValue, Object newValue) {
 
                // this change is for simple property, so no need to convert 
targets to
@@ -141,7 +145,8 @@ public class ChildDiffLoader implements GraphChangeHandler {
                }
        }
 
-       public void arcCreated(Object nodeId, Object targetNodeId, Object 
arcId) {
+       @Override
+       public void arcCreated(Object nodeId, Object targetNodeId, ArcId arcId) 
{
 
                final Persistent source = findObject(nodeId);
                final Persistent target = findObject(targetNodeId);
@@ -185,7 +190,8 @@ public class ChildDiffLoader implements GraphChangeHandler {
                }
        }
 
-       public void arcDeleted(Object nodeId, final Object targetNodeId, Object 
arcId) {
+       @Override
+       public void arcDeleted(Object nodeId, final Object targetNodeId, ArcId 
arcId) {
                final Persistent source = findObject(nodeId);
 
                // needed as sometime temporary objects are evoked from the 
context
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/graph/GraphChangeHandler.java 
b/cayenne-server/src/main/java/org/apache/cayenne/graph/GraphChangeHandler.java
index 3c92520..3d40d23 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/graph/GraphChangeHandler.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/graph/GraphChangeHandler.java
@@ -56,10 +56,10 @@ public interface GraphChangeHandler {
     /**
      * Notifies implementing object that a new arc was created between two 
nodes.
      */
-    void arcCreated(Object nodeId, Object targetNodeId, Object arcId);
+    void arcCreated(Object nodeId, Object targetNodeId, ArcId arcId);
 
     /**
      * Notifies implementing object that an arc between two nodes was deleted.
      */
-    void arcDeleted(Object nodeId, Object targetNodeId, Object arcId);
+    void arcDeleted(Object nodeId, Object targetNodeId, ArcId arcId);
 }
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/graph/GraphDiffCompressor.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/graph/GraphDiffCompressor.java
index 9bf1dc4..31849a8 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/graph/GraphDiffCompressor.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/graph/GraphDiffCompressor.java
@@ -93,7 +93,8 @@ public class GraphDiffCompressor {
             return new CompoundDiff(compressed);
         }
 
-        public void arcCreated(Object nodeId, Object targetNodeId, Object 
arcId) {
+        @Override
+        public void arcCreated(Object nodeId, Object targetNodeId, ArcId 
arcId) {
 
             if (targetNodeId != null) {
                 List<NodeDiff> diffs = diffsByNode.get(nodeId);
@@ -116,7 +117,8 @@ public class GraphDiffCompressor {
             registerDiff(new ArcCreateOperation(nodeId, targetNodeId, arcId));
         }
 
-        public void arcDeleted(Object nodeId, Object targetNodeId, Object 
arcId) {
+        @Override
+        public void arcDeleted(Object nodeId, Object targetNodeId, ArcId 
arcId) {
 
             if (targetNodeId != null) {
                 List<NodeDiff> diffs = diffsByNode.get(nodeId);
@@ -139,31 +141,35 @@ public class GraphDiffCompressor {
             registerDiff(new ArcDeleteOperation(nodeId, targetNodeId, arcId));
         }
 
+        @Override
         public void nodeCreated(Object nodeId) {
             registerDiff(new NodeCreateOperation(nodeId));
 
             if (createdNodes == null) {
-                createdNodes = new HashSet<Object>();
+                createdNodes = new HashSet<>();
             }
 
             createdNodes.add(nodeId);
         }
 
+        @Override
         public void nodeIdChanged(Object nodeId, Object newId) {
             registerDiff(new NodeIdChangeOperation(nodeId, newId));
         }
 
+        @Override
         public void nodeRemoved(Object nodeId) {
 
             registerDiff(new NodeDeleteOperation(nodeId));
 
             if (deletedNodes == null) {
-                deletedNodes = new HashSet<Object>();
+                deletedNodes = new HashSet<>();
             }
 
             deletedNodes.add(nodeId);
         }
 
+        @Override
         public void nodePropertyChanged(
                 Object nodeId,
                 String property,
@@ -195,13 +201,9 @@ public class GraphDiffCompressor {
         private void registerDiff(NodeDiff diff) {
 
             compressed.add(diff);
-            List<NodeDiff> diffs = diffsByNode.get(diff.getNodeId());
-            if (diffs == null) {
-                diffs = new ArrayList<>();
-                diffsByNode.put(diff.getNodeId(), diffs);
-            }
-
-            diffs.add(diff);
+            diffsByNode
+                    .computeIfAbsent(diff.getNodeId(), k -> new ArrayList<>())
+                    .add(diff);
         }
     }
 }
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/graph/GraphMap.java 
b/cayenne-server/src/main/java/org/apache/cayenne/graph/GraphMap.java
index cd4c1f6..f65934e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/graph/GraphMap.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/graph/GraphMap.java
@@ -51,44 +51,54 @@ public class GraphMap implements GraphManager {
     /**
      * Returns an immutable collection of registered nodes.
      */
+    @Override
     public Collection<Object> registeredNodes() {
         return Collections.unmodifiableCollection(nodes.values());
     }
 
+    @Override
     public synchronized Object getNode(Object nodeId) {
         return nodes.get(nodeId);
     }
 
+    @Override
     public synchronized void registerNode(Object nodeId, Object nodeObject) {
         nodes.put(nodeId, nodeObject);
     }
 
+    @Override
     public synchronized Object unregisterNode(Object nodeId) {
         return nodes.remove(nodeId);
     }
 
     // *** methods for tracking local changes declared in GraphChangeHandler 
interface
-    
-    public void arcCreated(Object nodeId, Object targetNodeId, Object arcId) {
+
+    @Override
+    public void arcCreated(Object nodeId, Object targetNodeId, ArcId arcId) {
         // noop
     }
 
-    public void arcDeleted(Object nodeId, Object targetNodeId, Object arcId) {
+    @Override
+    public void arcDeleted(Object nodeId, Object targetNodeId, ArcId arcId) {
         // noop
     }
 
+    @Override
     public void nodeCreated(Object nodeId) {
         // noop
     }
 
+    @Override
     public void nodeRemoved(Object nodeId) {
         // noop
     }
 
+    @Override
     public void nodeIdChanged(Object nodeId, Object newId) {
         // noop
     }
 
+    @Override
     public void nodePropertyChanged(
             Object nodeId,
             String property,
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/util/ObjectContextGraphAction.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/util/ObjectContextGraphAction.java
index 7944c1b..01868df 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/util/ObjectContextGraphAction.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/util/ObjectContextGraphAction.java
@@ -23,6 +23,7 @@ import java.io.Serializable;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.PersistenceState;
 import org.apache.cayenne.Persistent;
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.reflect.ArcProperty;
 import org.apache.cayenne.reflect.ClassDescriptor;
 import org.apache.cayenne.reflect.PropertyDescriptor;
@@ -81,14 +82,14 @@ public class ObjectContextGraphAction implements 
Serializable {
                 context.getGraphManager().arcDeleted(
                         object.getObjectId(),
                         ((Persistent) oldValue).getObjectId(),
-                        property.getName());
+                        new ArcId(property));
             }
 
             if (newValue instanceof Persistent) {
                 context.getGraphManager().arcCreated(
                         object.getObjectId(),
                         ((Persistent) newValue).getObjectId(),
-                        property.getName());
+                        new ArcId(property));
             }
         }
     }
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/util/Util.java 
b/cayenne-server/src/main/java/org/apache/cayenne/util/Util.java
index 08941b8..99c0c3e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/util/Util.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/util/Util.java
@@ -26,6 +26,7 @@ import org.apache.cayenne.Persistent;
 import org.apache.cayenne.di.AdhocObjectFactory;
 import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory;
 import org.apache.cayenne.di.spi.DefaultClassLoaderManager;
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.reflect.ArcProperty;
 import org.apache.cayenne.reflect.AttributeProperty;
 import org.apache.cayenne.reflect.PropertyVisitor;
@@ -741,7 +742,7 @@ public class Util {
                        });
 
                        sourceObject.getObjectContext().getGraphManager()
-                                       .arcCreated(targetObject.getObjectId(), 
sourceObject.getObjectId(), reverseArc.getName());
+                                       .arcCreated(targetObject.getObjectId(), 
sourceObject.getObjectId(), new ArcId(reverseArc));
 
                        markAsDirty(targetObject);
                }
@@ -771,7 +772,7 @@ public class Util {
                        });
 
                        sourceObject.getObjectContext().getGraphManager()
-                                       .arcDeleted(targetObject.getObjectId(), 
sourceObject.getObjectId(), reverseArc.getName());
+                                       .arcDeleted(targetObject.getObjectId(), 
sourceObject.getObjectId(), new ArcId(reverseArc));
 
                        markAsDirty(targetObject);
                }
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/access/DeleteRulesIT.java 
b/cayenne-server/src/test/java/org/apache/cayenne/access/DeleteRulesIT.java
index 430c28d..6e7d821 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DeleteRulesIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DeleteRulesIT.java
@@ -338,16 +338,15 @@ public class DeleteRulesIT extends ServerCase {
         ObjectDiff changes = 
context.getObjectStore().changes.get(a.getObjectId());
 
         assertNotNull(changes);
-        Collection<NodeDiff> diffs = new ArrayList<NodeDiff>();
+        Collection<NodeDiff> diffs = new ArrayList<>();
         changes.appendDiffs(diffs);
-        Iterator<?> it = diffs.iterator();
-        while (it.hasNext()) {
-            Object diff = it.next();
+        for (Object diff : diffs) {
             if (diff instanceof ArcOperation) {
                 ArcOperation arcDelete = (ArcOperation) diff;
                 if (arcDelete.getNodeId().equals(a.getObjectId())
                         && arcDelete.getTargetNodeId().equals(b.getObjectId())
-                        && 
arcDelete.getArcId().equals(DeleteRuleFlatA.FLAT_B.getName()) && 
arcDelete.isDelete()) {
+                        && 
arcDelete.getArcId().getForwardArc().equals(DeleteRuleFlatA.FLAT_B.getName())
+                        && arcDelete.isDelete()) {
                     return;
                 }
             }
@@ -360,16 +359,15 @@ public class DeleteRulesIT extends ServerCase {
         ObjectDiff changes = 
context.getObjectStore().changes.get(a.getObjectId());
 
         if (changes != null) {
-            Collection<NodeDiff> diffs = new ArrayList<NodeDiff>();
+            Collection<NodeDiff> diffs = new ArrayList<>();
             changes.appendDiffs(diffs);
-            Iterator<?> it = diffs.iterator();
-            while (it.hasNext()) {
-                Object diff = it.next();
+            for (Object diff : diffs) {
                 if (diff instanceof ArcOperation) {
                     ArcOperation arcDelete = (ArcOperation) diff;
                     if (arcDelete.getNodeId().equals(a.getObjectId())
                             && 
arcDelete.getTargetNodeId().equals(b.getObjectId())
-                            && 
arcDelete.getArcId().equals(DeleteRuleFlatA.FLAT_B.getName()) && 
!arcDelete.isDelete()) {
+                            && 
arcDelete.getArcId().getForwardArc().equals(DeleteRuleFlatA.FLAT_B.getName())
+                            && !arcDelete.isDelete()) {
                         fail("Join was  deleted for flattened relationship");
                     }
                 }
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/DataChannelSyncStats.java
 
b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/DataChannelSyncStats.java
index 4b2e49c..cbbf48b 100644
--- 
a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/DataChannelSyncStats.java
+++ 
b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/DataChannelSyncStats.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.unit.di;
 
+import org.apache.cayenne.graph.ArcId;
 import org.apache.cayenne.graph.GraphChangeHandler;
 
 public class DataChannelSyncStats implements GraphChangeHandler {
@@ -29,22 +30,27 @@ public class DataChannelSyncStats implements 
GraphChangeHandler {
     public int nodePropertiesChanged;
     public int nodesRemoved;
 
-    public void arcCreated(Object nodeId, Object targetNodeId, Object arcId) {
+    @Override
+    public void arcCreated(Object nodeId, Object targetNodeId, ArcId arcId) {
         arcsCreated++;
     }
 
-    public void arcDeleted(Object nodeId, Object targetNodeId, Object arcId) {
+    @Override
+    public void arcDeleted(Object nodeId, Object targetNodeId, ArcId arcId) {
         arcsDeleted++;
     }
 
+    @Override
     public void nodeCreated(Object nodeId) {
         nodesCreated++;
     }
 
+    @Override
     public void nodeIdChanged(Object nodeId, Object newId) {
         nodeIdsChanged++;
     }
 
+    @Override
     public void nodePropertyChanged(
             Object nodeId,
             String property,
@@ -53,6 +59,7 @@ public class DataChannelSyncStats implements 
GraphChangeHandler {
         nodePropertiesChanged++;
     }
 
+    @Override
     public void nodeRemoved(Object nodeId) {
         nodesRemoved++;
     }

Reply via email to