You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by sk...@apache.org on 2016/11/16 18:45:56 UTC

[1/9] cayenne git commit: - MergeToken reverse method now returns collection of tokens

Repository: cayenne
Updated Branches:
  refs/heads/master 4bd2cad0c -> 74e5e2f3c


- MergeToken reverse method now returns collection of tokens


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

Branch: refs/heads/master
Commit: f2842b90ce4cf96998c81b2db04c83302eb04703
Parents: 2dc30c8
Author: Nikita Timofeev <st...@gmail.com>
Authored: Fri Nov 4 17:11:27 2016 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Fri Nov 4 17:11:27 2016 +0300

----------------------------------------------------------------------
 .../org/apache/cayenne/dbsync/merge/AddColumnToDb.java   |  5 +++--
 .../apache/cayenne/dbsync/merge/AddColumnToModel.java    |  7 +++++--
 .../apache/cayenne/dbsync/merge/AddRelationshipToDb.java |  5 +++--
 .../cayenne/dbsync/merge/AddRelationshipToModel.java     |  7 +++++--
 .../org/apache/cayenne/dbsync/merge/CreateTableToDb.java |  5 +++--
 .../apache/cayenne/dbsync/merge/CreateTableToModel.java  |  7 +++++--
 .../java/org/apache/cayenne/dbsync/merge/DbMerger.java   |  4 +++-
 .../org/apache/cayenne/dbsync/merge/DropColumnToDb.java  |  5 +++--
 .../apache/cayenne/dbsync/merge/DropColumnToModel.java   |  6 ++++--
 .../cayenne/dbsync/merge/DropRelationshipToDb.java       |  9 +++++++--
 .../cayenne/dbsync/merge/DropRelationshipToModel.java    |  7 +++++--
 .../org/apache/cayenne/dbsync/merge/DropTableToDb.java   |  6 ++++--
 .../apache/cayenne/dbsync/merge/DropTableToModel.java    |  7 +++++--
 .../apache/cayenne/dbsync/merge/DummyReverseToken.java   |  7 +++++--
 .../org/apache/cayenne/dbsync/merge/MergerToken.java     |  4 +++-
 .../apache/cayenne/dbsync/merge/SetAllowNullToDb.java    |  5 +++--
 .../apache/cayenne/dbsync/merge/SetAllowNullToModel.java |  7 +++++--
 .../apache/cayenne/dbsync/merge/SetColumnTypeToDb.java   |  5 +++--
 .../cayenne/dbsync/merge/SetColumnTypeToModel.java       |  7 +++++--
 .../org/apache/cayenne/dbsync/merge/SetNotNullToDb.java  |  5 +++--
 .../apache/cayenne/dbsync/merge/SetNotNullToModel.java   |  7 +++++--
 .../apache/cayenne/dbsync/merge/SetPrimaryKeyToDb.java   | 11 ++++-------
 .../cayenne/dbsync/merge/SetPrimaryKeyToModel.java       |  7 ++++---
 .../apache/cayenne/dbsync/merge/SetValueForNullToDb.java |  6 ++++--
 .../apache/cayenne/dbsync/merge/AddColumnToModelIT.java  |  2 +-
 .../cayenne/dbsync/merge/CreateTableToModelIT.java       |  2 +-
 .../apache/cayenne/dbsync/merge/DropColumnToModelIT.java |  6 +++---
 .../cayenne/dbsync/merge/DropRelationshipToModelIT.java  |  4 ++--
 .../apache/cayenne/dbsync/merge/DropTableToModelIT.java  |  2 +-
 .../apache/cayenne/dbsync/merge/TokensReversTest.java    |  5 ++++-
 .../cayenne/tools/dbimport/DefaultDbImportAction.java    |  2 +-
 .../modeler/dialog/db/MergerTokenSelectorController.java |  6 ++++--
 32 files changed, 116 insertions(+), 64 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToDb.java
index 2a87b98..7b32168 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToDb.java
@@ -25,6 +25,7 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -59,7 +60,7 @@ public class AddColumnToDb extends AbstractToDbToken.EntityAndColumn {
     }
 
     @Override
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return factory.createDropColumnToModel(getEntity(), getColumn());
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        return Collections.singleton(factory.createDropColumnToModel(getEntity(), getColumn()));
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToModel.java
index 823a81d..6928f6a 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToModel.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToModel.java
@@ -23,6 +23,9 @@ import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.ObjEntity;
 
+import java.util.Collection;
+import java.util.Collections;
+
 /**
  * A {@link MergerToken} to add a {@link DbAttribute} to a {@link DbEntity}. The
  * {@link EntityMergeSupport} will be used to update the mapped {@link ObjEntity}
@@ -34,8 +37,8 @@ public class AddColumnToModel extends AbstractToModelToken.EntityAndColumn {
     }
 
     @Override
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return factory.createDropColumnToDb(getEntity(), getColumn());
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        return Collections.singleton(factory.createDropColumnToDb(getEntity(), getColumn()));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToDb.java
index 150ac98..5ca3b24 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToDb.java
@@ -24,6 +24,7 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbRelationship;
 
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -59,8 +60,8 @@ public class AddRelationshipToDb extends AbstractToDbToken.Entity {
     }
 
     @Override
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return factory.createDropRelationshipToModel(getEntity(), relationship);
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        return Collections.singleton(factory.createDropRelationshipToModel(getEntity(), relationship));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToModel.java
index 5ae2d3f..bae2a20 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToModel.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToModel.java
@@ -24,6 +24,9 @@ import org.apache.cayenne.map.DbJoin;
 import org.apache.cayenne.map.DbRelationship;
 import org.apache.cayenne.map.ObjEntity;
 
+import java.util.Collection;
+import java.util.Collections;
+
 public class AddRelationshipToModel extends AbstractToModelToken.Entity {
 
     public static final String COMMA_SEPARATOR = ", ";
@@ -52,8 +55,8 @@ public class AddRelationshipToModel extends AbstractToModelToken.Entity {
     }
 
     @Override
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return factory.createDropRelationshipToDb(getEntity(), relationship);
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        return Collections.singleton(factory.createDropRelationshipToDb(getEntity(), relationship));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToDb.java
index 9584aaf..81267c6 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToDb.java
@@ -25,6 +25,7 @@ import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.validation.SimpleValidationFailure;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -59,8 +60,8 @@ public class CreateTableToDb extends AbstractToDbToken.Entity {
         }
     }
 
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return factory.createDropTableToModel(getEntity());
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        return Collections.singleton(factory.createDropTableToModel(getEntity()));
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToModel.java
index 8352a27..7ad863c 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToModel.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToModel.java
@@ -24,6 +24,9 @@ import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.ObjEntity;
 
+import java.util.Collection;
+import java.util.Collections;
+
 /**
  * A {@link MergerToken} to add a {@link DbEntity} to a {@link DataMap}
  */
@@ -91,8 +94,8 @@ public class CreateTableToModel extends AbstractToModelToken.Entity {
         context.getDelegate().objEntityAdded(objEntity);
     }
 
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return factory.createDropTableToDb(getEntity());
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        return Collections.singleton(factory.createDropTableToDb(getEntity()));
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMerger.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMerger.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMerger.java
index 319ef26..8f0adb7 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMerger.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMerger.java
@@ -280,7 +280,9 @@ public class DbMerger {
                     // default toModel as we can not do drop a toMany in the db.
                     // only
                     // toOne are represented using foreign key
-                    token = token.createReverse(tokenFactory);
+                    tokens.addAll(token.createReverse(tokenFactory));
+                } else {
+                    tokens.add(token);
                 }
                 tokens.add(token);
             }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToDb.java
index 19914f0..f2cd725 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToDb.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.dbsync.merge;
 
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -45,8 +46,8 @@ public class DropColumnToDb extends AbstractToDbToken.EntityAndColumn {
         return Collections.singletonList(sqlBuffer.toString());
     }
 
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return factory.createAddColumnToModel(getEntity(), getColumn());
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        return Collections.singleton(factory.createAddColumnToModel(getEntity(), getColumn()));
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToModel.java
index e92df93..8ca0a2a 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToModel.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToModel.java
@@ -27,6 +27,8 @@ import org.apache.cayenne.map.ObjAttribute;
 import org.apache.cayenne.map.ObjEntity;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -40,8 +42,8 @@ public class DropColumnToModel extends AbstractToModelToken.EntityAndColumn {
     }
 
     @Override
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return factory.createAddColumnToDb(getEntity(), getColumn());
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        return Collections.singleton(factory.createAddColumnToDb(getEntity(), getColumn()));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java
index 1579b25..b037cca 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java
@@ -25,6 +25,8 @@ import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbRelationship;
 import org.apache.cayenne.dbsync.reverse.db.DbRelationshipDetected;
 
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -56,8 +58,11 @@ public class DropRelationshipToDb extends AbstractToDbToken.Entity {
                 "ALTER TABLE " + context.quotedFullyQualifiedName(getEntity()) + " DROP CONSTRAINT " + fkName);
     }
 
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return factory.createAddRelationshipToModel(getEntity(), relationship);
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        Collection<MergerToken> result = new ArrayList<>();
+        result.add(factory.createAddRelationshipToModel(getEntity(), relationship));
+        result.add(factory.createAddRelationshipToModel(relationship.getTargetEntity(), relationship.createReverseRelationship()));
+        return result;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModel.java
index 3908dbd..3ef18fe 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModel.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModel.java
@@ -22,6 +22,9 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbRelationship;
 
+import java.util.Collection;
+import java.util.Collections;
+
 public class DropRelationshipToModel extends AbstractToModelToken.Entity {
 
     private final DbRelationship relationship;
@@ -32,8 +35,8 @@ public class DropRelationshipToModel extends AbstractToModelToken.Entity {
     }
 
     @Override
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return factory.createAddRelationshipToDb(getEntity(), relationship);
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        return Collections.singleton(factory.createAddRelationshipToDb(getEntity(), relationship));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToDb.java
index 3f416c7..0fe9f9f 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToDb.java
@@ -23,6 +23,8 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbEntity;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 
 public class DropTableToDb extends AbstractToDbToken.Entity {
@@ -44,8 +46,8 @@ public class DropTableToDb extends AbstractToDbToken.Entity {
     }
 
     @Override
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return factory.createCreateTableToModel(getEntity());
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        return Collections.singleton(factory.createCreateTableToModel(getEntity()));
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToModel.java
index b6eabee..020edb0 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToModel.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToModel.java
@@ -23,6 +23,9 @@ import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.ObjEntity;
 
+import java.util.Collection;
+import java.util.Collections;
+
 /**
  * A {@link MergerToken} to remove a {@link DbEntity} from a {@link DataMap}. Any
  * {@link ObjEntity} mapped to the {@link DbEntity} will also be removed.
@@ -35,8 +38,8 @@ public class DropTableToModel extends AbstractToModelToken.Entity {
     }
 
     @Override
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return factory.createCreateTableToDb(getEntity());
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        return Collections.singleton(factory.createCreateTableToDb(getEntity()));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DummyReverseToken.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DummyReverseToken.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DummyReverseToken.java
index 3f9b35c..0e6d23e 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DummyReverseToken.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DummyReverseToken.java
@@ -20,6 +20,9 @@ package org.apache.cayenne.dbsync.merge;
 
 import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 
+import java.util.Collection;
+import java.util.Collections;
+
 /**
  * The reverse of a {@link MergerToken} that can not be reversed.. This will not execute
  * any thing, but {@link #createReverse(MergerTokenFactory)} will get back the reverse that
@@ -34,8 +37,8 @@ class DummyReverseToken implements MergerToken {
     }
 
     @Override
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return reverse;
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        return Collections.singleton(reverse);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerToken.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerToken.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerToken.java
index 5088f97..943a393 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerToken.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerToken.java
@@ -20,6 +20,8 @@ package org.apache.cayenne.dbsync.merge;
 
 import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 
+import java.util.Collection;
+
 /**
  * Represents a minimal atomic synchronization operation between database and Cayenne model.
  */
@@ -41,7 +43,7 @@ public interface MergerToken {
      * <p>
      * Not all tokens are reversible.
      */
-    MergerToken createReverse(MergerTokenFactory factory);
+    Collection<MergerToken> createReverse(MergerTokenFactory factory);
 
     /**
      * Executes synchronization operation.

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToDb.java
index 68078c2..1b417ba 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToDb.java
@@ -24,6 +24,7 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -51,8 +52,8 @@ public class SetAllowNullToDb extends AbstractToDbToken.EntityAndColumn {
     }
 
     @Override
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return factory.createSetNotNullToModel(getEntity(), getColumn());
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        return Collections.singleton(factory.createSetNotNullToModel(getEntity(), getColumn()));
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToModel.java
index 463f912..30841bd 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToModel.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToModel.java
@@ -22,6 +22,9 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 
+import java.util.Collection;
+import java.util.Collections;
+
 /**
  * A {@link MergerToken} to set the mandatory field of a {@link DbAttribute} to false
  * 
@@ -33,8 +36,8 @@ public class SetAllowNullToModel extends AbstractToModelToken.EntityAndColumn {
     }
 
     @Override
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return factory.createSetNotNullToDb(getEntity(), getColumn());
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        return Collections.singleton(factory.createSetNotNullToDb(getEntity(), getColumn()));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToDb.java
index 2434dd1..a52de9d 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToDb.java
@@ -26,6 +26,7 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -105,7 +106,7 @@ public class SetColumnTypeToDb extends AbstractToDbToken.Entity {
     }
 
     @Override
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return factory.createSetColumnTypeToModel(getEntity(), columnNew, columnOriginal);
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        return Collections.singleton(factory.createSetColumnTypeToModel(getEntity(), columnNew, columnOriginal));
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToModel.java
index a960467..1e51468 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToModel.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToModel.java
@@ -23,6 +23,9 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 
+import java.util.Collection;
+import java.util.Collections;
+
 /**
  * A {@link MergerToken} that modifies one original {@link DbAttribute} to match another
  * new {@link DbAttribute}s type, maxLength and precision. The name and mandatory fields
@@ -41,8 +44,8 @@ public class SetColumnTypeToModel extends AbstractToModelToken.Entity {
     }
 
     @Override
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return factory.createSetColumnTypeToDb(getEntity(), columnNew, columnOriginal);
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        return Collections.singleton(factory.createSetColumnTypeToDb(getEntity(), columnNew, columnOriginal));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToDb.java
index 0591c2a..1b4c5f6 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToDb.java
@@ -24,6 +24,7 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -45,8 +46,8 @@ public class SetNotNullToDb extends AbstractToDbToken.EntityAndColumn {
     }
 
     @Override
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return factory.createSetAllowNullToModel(getEntity(), getColumn());
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        return Collections.singleton(factory.createSetAllowNullToModel(getEntity(), getColumn()));
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToModel.java
index dfc9b15..6aa7c63 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToModel.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToModel.java
@@ -22,6 +22,9 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 
+import java.util.Collection;
+import java.util.Collections;
+
 /**
  * A {@link MergerToken} to set the mandatory field of a {@link DbAttribute} to true
  * 
@@ -33,8 +36,8 @@ public class SetNotNullToModel extends AbstractToModelToken.EntityAndColumn {
     }
 
     @Override
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return factory.createSetAllowNullToDb(getEntity(), getColumn());
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        return Collections.singleton(factory.createSetAllowNullToDb(getEntity(), getColumn()));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToDb.java
index 077b6ef..e052e1c 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToDb.java
@@ -24,10 +24,7 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
+import java.util.*;
 
 public class SetPrimaryKeyToDb extends AbstractToDbToken.Entity {
 
@@ -80,8 +77,8 @@ public class SetPrimaryKeyToDb extends AbstractToDbToken.Entity {
     }
 
     @Override
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return factory.createSetPrimaryKeyToModel(getEntity(), primaryKeyNew, primaryKeyOriginal,
-                detectedPrimaryKeyName);
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        return Collections.singleton(factory.createSetPrimaryKeyToModel(getEntity(), primaryKeyNew, primaryKeyOriginal,
+                detectedPrimaryKeyName));
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToModel.java
index a2198ba..1048b7f 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToModel.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToModel.java
@@ -24,6 +24,7 @@ import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.event.AttributeEvent;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -49,12 +50,12 @@ public class SetPrimaryKeyToModel extends AbstractToModelToken.Entity {
     }
 
     @Override
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return factory.createSetPrimaryKeyToDb(
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        return Collections.singleton(factory.createSetPrimaryKeyToDb(
                 getEntity(),
                 primaryKeyNew,
                 primaryKeyOriginal,
-                detectedPrimaryKeyName);
+                detectedPrimaryKeyName));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetValueForNullToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetValueForNullToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetValueForNullToDb.java
index 340f2bf..ae231d1 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetValueForNullToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetValueForNullToDb.java
@@ -23,6 +23,8 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 
 
@@ -41,8 +43,8 @@ public class SetValueForNullToDb extends AbstractToDbToken.EntityAndColumn {
     }
 
     @Override
-    public MergerToken createReverse(MergerTokenFactory factory) {
-        return new DummyReverseToken(this);
+    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
+        return Collections.<MergerToken>singleton(new DummyReverseToken(this));
     }
     
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/AddColumnToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/AddColumnToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/AddColumnToModelIT.java
index 30fa47b..0e9ef89 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/AddColumnToModelIT.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/AddColumnToModelIT.java
@@ -75,7 +75,7 @@ public class AddColumnToModelIT extends MergeCase {
         assertEquals(1, tokens.size());
         MergerToken token = tokens.get(0);
         if (token.getDirection().isToDb()) {
-            token = token.createReverse(mergerFactory());
+            token = token.createReverse(mergerFactory()).iterator().next();
         }
         assertTrue(token instanceof AddColumnToModel);
         execute(token);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/CreateTableToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/CreateTableToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/CreateTableToModelIT.java
index bac6402..48a02d5 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/CreateTableToModelIT.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/CreateTableToModelIT.java
@@ -58,7 +58,7 @@ public class CreateTableToModelIT extends MergeCase {
 		assertEquals(1, tokens.size());
 		MergerToken token = tokens.get(0);
 		if (token.getDirection().isToDb()) {
-			token = token.createReverse(mergerFactory());
+			token = token.createReverse(mergerFactory()).iterator().next();
 		}
 		assertTrue(token.getClass().getName(), token instanceof CreateTableToModel);
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropColumnToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropColumnToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropColumnToModelIT.java
index f6e0675..4e1b262 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropColumnToModelIT.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropColumnToModelIT.java
@@ -78,7 +78,7 @@ public class DropColumnToModelIT extends MergeCase {
 		assertEquals(1, tokens.size());
 		token = tokens.get(0);
 		if (token.getDirection().isToDb()) {
-			token = token.createReverse(mergerFactory());
+			token = token.createReverse(mergerFactory()).iterator().next();
 		}
 		assertTrue(token instanceof DropColumnToModel);
 		execute(token);
@@ -193,8 +193,8 @@ public class DropColumnToModelIT extends MergeCase {
 		assertTokens(tokens, 2, 0);
 		// TODO: reversing the following two tokens should also reverse the
 		// order
-		MergerToken token0 = tokens.get(0).createReverse(mergerFactory());
-		MergerToken token1 = tokens.get(1).createReverse(mergerFactory());
+		MergerToken token0 = tokens.get(0).createReverse(mergerFactory()).iterator().next();
+		MergerToken token1 = tokens.get(1).createReverse(mergerFactory()).iterator().next();
 		if (!(token0 instanceof DropRelationshipToModel && token1 instanceof DropColumnToModel || token1 instanceof DropRelationshipToModel
 				&& token0 instanceof DropColumnToModel)) {
 			fail();

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModelIT.java
index cf2ec3d..2271e25 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModelIT.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModelIT.java
@@ -151,8 +151,8 @@ public class DropRelationshipToModelIT extends MergeCase {
 		assertTokens(tokens, 2, 0);
 		// TODO: reversing the following two tokens should also reverse the
 		// order
-		MergerToken token0 = tokens.get(0).createReverse(mergerFactory());
-		MergerToken token1 = tokens.get(1).createReverse(mergerFactory());
+		MergerToken token0 = tokens.get(0).createReverse(mergerFactory()).iterator().next();
+		MergerToken token1 = tokens.get(1).createReverse(mergerFactory()).iterator().next();
 		if (!(token0 instanceof DropRelationshipToModel && token1 instanceof DropColumnToModel || token1 instanceof DropRelationshipToModel
 				&& token0 instanceof DropColumnToModel)) {
 			fail();

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropTableToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropTableToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropTableToModelIT.java
index 5b1744a..1d05205 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropTableToModelIT.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropTableToModelIT.java
@@ -72,7 +72,7 @@ public class DropTableToModelIT extends MergeCase {
 		assertEquals(1, tokens.size());
 		token = tokens.get(0);
 		if (token.getDirection().isToDb()) {
-			token = token.createReverse(mergerFactory());
+			token = token.createReverse(mergerFactory()).iterator().next();
 		}
 		assertTrue(token instanceof DropTableToModel);
 		execute(token);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReversTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReversTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReversTest.java
index b23128c..411b253 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReversTest.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReversTest.java
@@ -27,6 +27,7 @@ import org.apache.cayenne.map.DbRelationship;
 import org.junit.Assert;
 import org.junit.Test;
 
+import java.util.Collection;
 import java.util.Collections;
 
 import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.dbAttr;
@@ -76,7 +77,9 @@ public class TokensReversTest {
     }
 
     private void test(MergerToken token1) {
-        MergerToken token2 = token1.createReverse(factory()).createReverse(factory());
+        MergerToken token2 = token1.createReverse(factory()).iterator().next()
+                                    .createReverse(factory()).iterator().next();
+
 
         Assert.assertEquals(token1.getTokenName(), token2.getTokenName());
         Assert.assertEquals(token1.getTokenValue(), token2.getTokenValue());

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DefaultDbImportAction.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DefaultDbImportAction.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DefaultDbImportAction.java
index 05fd502..7f05d8c 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DefaultDbImportAction.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DefaultDbImportAction.java
@@ -297,7 +297,7 @@ public class DefaultDbImportAction implements DbImportAction {
             if (token instanceof AbstractToModelToken) {
                 continue;
             }
-            tokens.add(token.createReverse(mergerTokenFactory));
+            tokens.addAll(token.createReverse(mergerTokenFactory));
         }
         return tokens;
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f2842b90/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenSelectorController.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenSelectorController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenSelectorController.java
index a5c6e96..8c36d25 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenSelectorController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenSelectorController.java
@@ -195,7 +195,8 @@ public class MergerTokenSelectorController extends CayenneController {
             return;
         }
         int i = selectableTokensList.indexOf(token);
-        MergerToken reverse = token.createReverse(mergerTokenFactory);
+        // TODO change to collection iteration
+        MergerToken reverse = token.createReverse(mergerTokenFactory).iterator().next();
         selectableTokensList.set(i, reverse);
         if (excludedTokens.remove(token)) {
             excludedTokens.add(reverse);
@@ -226,7 +227,8 @@ public class MergerTokenSelectorController extends CayenneController {
         
         for (int i = 0; i < selectableTokensList.size(); i++) {
             MergerToken token = selectableTokensList.get(i);
-            MergerToken reverse = token.createReverse(mergerTokenFactory);
+            // TODO change to collection iteration
+            MergerToken reverse = token.createReverse(mergerTokenFactory).iterator().next();
             selectableTokensList.set(i, reverse);
             if (excludedTokens.remove(token)) {
                 excludedTokens.add(reverse);


[6/9] cayenne git commit: Removed complex ModelMergeDelegate. At the end of migration the whole data map is reloaded now.

Posted by sk...@apache.org.
Removed complex ModelMergeDelegate. At the end of migration the whole data map is reloaded now.


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

Branch: refs/heads/master
Commit: 2eb2172fd0fa807b35907f06df22385474a18feb
Parents: cb41151
Author: Nikita Timofeev <st...@gmail.com>
Authored: Tue Nov 15 10:30:54 2016 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Tue Nov 15 10:30:54 2016 +0300

----------------------------------------------------------------------
 .../modeler/dialog/db/MergerOptions.java        | 192 ++-----------------
 1 file changed, 18 insertions(+), 174 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/2eb2172f/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java
index 06260b6..b19fe35 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java
@@ -20,11 +20,11 @@
 package org.apache.cayenne.modeler.dialog.db;
 
 import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.configuration.DataChannelDescriptor;
-import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.configuration.event.DataMapEvent;
 import org.apache.cayenne.dba.JdbcAdapter;
 import org.apache.cayenne.dbsync.merge.AbstractToDbToken;
 import org.apache.cayenne.dbsync.merge.DbMerger;
+import org.apache.cayenne.dbsync.merge.DefaultModelMergeDelegate;
 import org.apache.cayenne.dbsync.merge.MergeDirection;
 import org.apache.cayenne.dbsync.merge.MergerContext;
 import org.apache.cayenne.dbsync.merge.MergerToken;
@@ -40,19 +40,11 @@ import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig;
 import org.apache.cayenne.dbsync.reverse.filters.PatternFilter;
 import org.apache.cayenne.dbsync.reverse.filters.TableFilter;
 import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.ObjAttribute;
 import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.map.ObjRelationship;
-import org.apache.cayenne.map.event.EntityEvent;
 import org.apache.cayenne.map.event.MapEvent;
+import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.ProjectController;
 import org.apache.cayenne.modeler.dialog.ValidationResultBrowser;
-import org.apache.cayenne.modeler.event.AttributeDisplayEvent;
-import org.apache.cayenne.modeler.event.EntityDisplayEvent;
-import org.apache.cayenne.modeler.event.RelationshipDisplayEvent;
 import org.apache.cayenne.modeler.pref.DBConnectionInfo;
 import org.apache.cayenne.modeler.util.CayenneController;
 import org.apache.cayenne.project.Project;
@@ -64,10 +56,12 @@ import org.apache.cayenne.validation.ValidationResult;
 import org.apache.commons.logging.LogFactory;
 
 import javax.sql.DataSource;
-import javax.swing.*;
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+import javax.swing.WindowConstants;
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
-import java.awt.*;
+import java.awt.Component;
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
@@ -298,7 +292,10 @@ public class MergerOptions extends CayenneController {
 
         boolean modelChanged = applyTokens(tokensToMigrate, mergerContext);
 
-        DefaultDbImportAction.flattenManyToManyRelationships(dataMap, loadedObjEntities, mergerContext.getNameGenerator());
+        DefaultDbImportAction.flattenManyToManyRelationships(
+                dataMap,
+                loadedObjEntities,
+                mergerContext.getNameGenerator());
 
         notifyProjectModified(modelChanged);
 
@@ -306,8 +303,7 @@ public class MergerOptions extends CayenneController {
     }
 
     private ModelMergeDelegate createDelegate(final Collection<ObjEntity> loadedObjEntities) {
-        return new ProxyModelMergeDelegate(
-                new MigrateModelMergeDelegate(getProjectController(), this)) {
+        return new ProxyModelMergeDelegate(new DefaultModelMergeDelegate()) {
             @Override
             public void objEntityAdded(ObjEntity ent) {
                 loadedObjEntities.add(ent);
@@ -365,10 +361,13 @@ public class MergerOptions extends CayenneController {
         Project project = getApplication().getProject();
         project.setModified(true);
 
-        ProjectController projectController = getApplication()
-                .getFrameController()
-                .getProjectController();
+        ProjectController projectController = getProjectController();
         projectController.setDirty(true);
+
+        projectController.fireDataMapEvent(new DataMapEvent(Application.getFrame(),
+                dataMap, MapEvent.REMOVE));
+        projectController.fireDataMapEvent(new DataMapEvent(Application.getFrame(),
+                dataMap, MapEvent.ADD));
     }
 
     /**
@@ -409,159 +408,4 @@ public class MergerOptions extends CayenneController {
         view.dispose();
     }
 
-    private class MigrateModelMergeDelegate implements ModelMergeDelegate {
-
-        private final ProjectController controller;
-        private final Object src;
-        private final DataChannelDescriptor domain;
-        private final DataNodeDescriptor node;
-
-        public MigrateModelMergeDelegate(ProjectController controller, Object src) {
-            this.controller = controller;
-            this.src = src;
-            domain = (DataChannelDescriptor) getProjectController()
-                    .getProject()
-                    .getRootNode();
-            node = getProjectController().getCurrentDataNode();
-        }
-
-        public void dbAttributeAdded(DbAttribute att) {
-            if (controller.getCurrentDbEntity() == att.getEntity()) {
-                controller.fireDbAttributeDisplayEvent(new AttributeDisplayEvent(src, att, att
-                        .getEntity(), dataMap, domain));
-            }
-        }
-
-        public void dbAttributeModified(DbAttribute att) {
-            if (controller.getCurrentDbEntity() == att.getEntity()) {
-                controller.fireDbAttributeDisplayEvent(new AttributeDisplayEvent(src, att, att
-                        .getEntity(), dataMap, domain));
-            }
-        }
-
-        public void dbAttributeRemoved(DbAttribute att) {
-            if (controller.getCurrentDbEntity() == att.getEntity()) {
-                controller.fireDbAttributeDisplayEvent(new AttributeDisplayEvent(src, att, att
-                        .getEntity(), dataMap, domain));
-            }
-        }
-
-        public void dbEntityAdded(DbEntity ent) {
-            controller.fireDbEntityEvent(new EntityEvent(src, ent, MapEvent.ADD));
-            controller.fireDbEntityDisplayEvent(new EntityDisplayEvent(
-                    src,
-                    ent,
-                    dataMap,
-                    node,
-                    domain));
-        }
-
-        public void dbEntityRemoved(DbEntity ent) {
-            controller.fireDbEntityEvent(new EntityEvent(src, ent, MapEvent.REMOVE));
-            controller.fireDbEntityDisplayEvent(new EntityDisplayEvent(
-                    src,
-                    ent,
-                    dataMap,
-                    node,
-                    domain));
-        }
-
-        public void dbRelationshipAdded(DbRelationship rel) {
-            if (controller.getCurrentDbEntity() == rel.getSourceEntity()) {
-                controller.fireDbRelationshipDisplayEvent(new RelationshipDisplayEvent(
-                        src,
-                        rel,
-                        rel.getSourceEntity(),
-                        dataMap,
-                        domain));
-            }
-        }
-
-        public void dbRelationshipRemoved(DbRelationship rel) {
-            if (controller.getCurrentDbEntity() == rel.getSourceEntity()) {
-                controller.fireDbRelationshipDisplayEvent(new RelationshipDisplayEvent(
-                        src,
-                        rel,
-                        rel.getSourceEntity(),
-                        dataMap,
-                        domain));
-            }
-        }
-
-        public void objAttributeAdded(ObjAttribute att) {
-            if (controller.getCurrentObjEntity() == att.getEntity()) {
-                controller.fireObjAttributeDisplayEvent(new AttributeDisplayEvent(
-                        src,
-                        att,
-                        att.getEntity(),
-                        dataMap,
-                        domain));
-            }
-        }
-
-        public void objAttributeModified(ObjAttribute att) {
-            if (controller.getCurrentObjEntity() == att.getEntity()) {
-                controller.fireObjAttributeDisplayEvent(new AttributeDisplayEvent(
-                        src,
-                        att,
-                        att.getEntity(),
-                        dataMap,
-                        domain));
-            }
-        }
-
-        public void objAttributeRemoved(ObjAttribute att) {
-            if (controller.getCurrentObjEntity() == att.getEntity()) {
-                controller.fireObjAttributeDisplayEvent(new AttributeDisplayEvent(
-                        src,
-                        att,
-                        att.getEntity(),
-                        dataMap,
-                        domain));
-            }
-        }
-
-        public void objEntityAdded(ObjEntity ent) {
-            controller.fireObjEntityEvent(new EntityEvent(src, ent, MapEvent.ADD));
-            controller.fireObjEntityDisplayEvent(new EntityDisplayEvent(
-                    src,
-                    ent,
-                    dataMap,
-                    node,
-                    domain));
-        }
-
-        public void objEntityRemoved(ObjEntity ent) {
-            controller.fireObjEntityEvent(new EntityEvent(src, ent, MapEvent.REMOVE));
-            controller.fireObjEntityDisplayEvent(new EntityDisplayEvent(
-                    src,
-                    ent,
-                    dataMap,
-                    node,
-                    domain));
-        }
-
-        public void objRelationshipAdded(ObjRelationship rel) {
-            if (controller.getCurrentObjEntity() == rel.getSourceEntity()) {
-                controller.fireObjRelationshipDisplayEvent(new RelationshipDisplayEvent(
-                        src,
-                        rel,
-                        rel.getSourceEntity(),
-                        dataMap,
-                        domain));
-            }
-        }
-
-        public void objRelationshipRemoved(ObjRelationship rel) {
-            if (controller.getCurrentObjEntity() == rel.getSourceEntity()) {
-                controller.fireObjRelationshipDisplayEvent(new RelationshipDisplayEvent(
-                        src,
-                        rel,
-                        rel.getSourceEntity(),
-                        dataMap,
-                        domain));
-            }
-        }
-
-    }
 }


[8/9] cayenne git commit: Merge branch 'master' into modeler-reverseengineering-added-relation-fix

Posted by sk...@apache.org.
Merge branch 'master' into modeler-reverseengineering-added-relation-fix

# Conflicts:
#	modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java


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

Branch: refs/heads/master
Commit: 1462b2db3c6127615fee1dc9b0f3540462000517
Parents: 8c5985e
Author: Nikita Timofeev <st...@gmail.com>
Authored: Tue Nov 15 10:44:56 2016 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Tue Nov 15 10:44:56 2016 +0300

----------------------------------------------------------------------
 .../java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java  | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/1462b2db/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java
index 344215d..3709aae 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java
@@ -20,8 +20,7 @@
 package org.apache.cayenne.modeler.dialog.db;
 
 import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.configuration.DataChannelDescriptor;
-import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.configuration.event.DataMapEvent;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dbsync.merge.AbstractToDbToken;
 import org.apache.cayenne.dbsync.merge.DbMerger;


[4/9] cayenne git commit: Unified behavior in reverse engineering and db migration actions - Many to many relationships are flattened in db migration - All tokens are generated for forward and reverse relationships. This leads to proper token rever

Posted by sk...@apache.org.
Unified behavior in reverse engineering and db migration actions
   - Many to many relationships are flattened in db migration
   - All tokens are generated for forward and reverse relationships. This leads to proper token reverse logic.


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

Branch: refs/heads/master
Commit: 29d6439269cbe7d1c09e92a78c88093e32ae51ea
Parents: 8718ee9
Author: Nikita Timofeev <st...@gmail.com>
Authored: Mon Nov 14 20:19:27 2016 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Mon Nov 14 20:19:27 2016 +0300

----------------------------------------------------------------------
 .../cayenne/dbsync/merge/AbstractToDbToken.java |   4 +
 .../dbsync/merge/AbstractToModelToken.java      |   4 +
 .../cayenne/dbsync/merge/AddColumnToDb.java     |   5 +-
 .../cayenne/dbsync/merge/AddColumnToModel.java  |   7 +-
 .../dbsync/merge/AddRelationshipToDb.java       |  12 +-
 .../dbsync/merge/AddRelationshipToModel.java    |   7 +-
 .../cayenne/dbsync/merge/CreateTableToDb.java   |   5 +-
 .../dbsync/merge/CreateTableToModel.java        |   7 +-
 .../apache/cayenne/dbsync/merge/DbMerger.java   |  20 +-
 .../cayenne/dbsync/merge/DropColumnToDb.java    |   5 +-
 .../cayenne/dbsync/merge/DropColumnToModel.java |   6 +-
 .../dbsync/merge/DropRelationshipToDb.java      |  24 +-
 .../dbsync/merge/DropRelationshipToModel.java   |   7 +-
 .../cayenne/dbsync/merge/DropTableToDb.java     |   6 +-
 .../cayenne/dbsync/merge/DropTableToModel.java  |   7 +-
 .../cayenne/dbsync/merge/DummyReverseToken.java |  12 +-
 .../cayenne/dbsync/merge/MergerToken.java       |   4 +-
 .../cayenne/dbsync/merge/SetAllowNullToDb.java  |   5 +-
 .../dbsync/merge/SetAllowNullToModel.java       |   7 +-
 .../cayenne/dbsync/merge/SetColumnTypeToDb.java |   5 +-
 .../dbsync/merge/SetColumnTypeToModel.java      |   7 +-
 .../cayenne/dbsync/merge/SetNotNullToDb.java    |   5 +-
 .../cayenne/dbsync/merge/SetNotNullToModel.java |   7 +-
 .../cayenne/dbsync/merge/SetPrimaryKeyToDb.java |  11 +-
 .../dbsync/merge/SetPrimaryKeyToModel.java      |   7 +-
 .../dbsync/merge/SetValueForNullToDb.java       |   6 +-
 .../dbsync/merge/AddColumnToModelIT.java        |   2 +-
 .../dbsync/merge/CreateTableToModelIT.java      |   2 +-
 .../dbsync/merge/DropColumnToModelIT.java       |   6 +-
 .../dbsync/merge/DropRelationshipToModelIT.java |   6 +-
 .../dbsync/merge/DropTableToModelIT.java        |   2 +-
 .../apache/cayenne/dbsync/merge/MergeCase.java  |  13 +-
 .../cayenne/dbsync/merge/TokensReverseTest.java |  26 +-
 .../tools/dbimport/DefaultDbImportAction.java   |   4 +-
 .../modeler/dialog/db/MergerOptions.java        | 400 +++++++++++--------
 .../db/MergerTokenSelectorController.java       |   4 +-
 36 files changed, 338 insertions(+), 329 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractToDbToken.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractToDbToken.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractToDbToken.java
index 1cc3092..88e056f 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractToDbToken.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractToDbToken.java
@@ -78,6 +78,10 @@ public abstract class AbstractToDbToken implements MergerToken, Comparable<Merge
 		return getTokenName() + ' ' + getTokenValue() + ' ' + getDirection();
 	}
 
+	public boolean isEmpty() {
+		return false;
+	}
+
 	public abstract List<String> createSql(DbAdapter adapter);
 
 	abstract static class Entity extends AbstractToDbToken {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractToModelToken.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractToModelToken.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractToModelToken.java
index 424c8dc..24cee4a 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractToModelToken.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractToModelToken.java
@@ -79,6 +79,10 @@ public abstract class AbstractToModelToken implements MergerToken {
         return getTokenName() + ' ' + getTokenValue() + ' ' + getDirection();
     }
 
+    public boolean isEmpty() {
+        return false;
+    }
+
     abstract static class Entity extends AbstractToModelToken {
 
         private final DbEntity entity;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToDb.java
index 7b32168..2a87b98 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToDb.java
@@ -25,7 +25,6 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 
-import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -60,7 +59,7 @@ public class AddColumnToDb extends AbstractToDbToken.EntityAndColumn {
     }
 
     @Override
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        return Collections.singleton(factory.createDropColumnToModel(getEntity(), getColumn()));
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return factory.createDropColumnToModel(getEntity(), getColumn());
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToModel.java
index 6928f6a..823a81d 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToModel.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToModel.java
@@ -23,9 +23,6 @@ import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.ObjEntity;
 
-import java.util.Collection;
-import java.util.Collections;
-
 /**
  * A {@link MergerToken} to add a {@link DbAttribute} to a {@link DbEntity}. The
  * {@link EntityMergeSupport} will be used to update the mapped {@link ObjEntity}
@@ -37,8 +34,8 @@ public class AddColumnToModel extends AbstractToModelToken.EntityAndColumn {
     }
 
     @Override
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        return Collections.singleton(factory.createDropColumnToDb(getEntity(), getColumn()));
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return factory.createDropColumnToDb(getEntity(), getColumn());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToDb.java
index 5ca3b24..90d92b0 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToDb.java
@@ -24,7 +24,6 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbRelationship;
 
-import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -60,8 +59,8 @@ public class AddRelationshipToDb extends AbstractToDbToken.Entity {
     }
 
     @Override
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        return Collections.singleton(factory.createDropRelationshipToModel(getEntity(), relationship));
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return factory.createDropRelationshipToModel(getEntity(), relationship);
     }
 
     @Override
@@ -72,7 +71,12 @@ public class AddRelationshipToDb extends AbstractToDbToken.Entity {
             return "Skip. No sql representation.";
         }
     }
-    
+
+    @Override
+    public boolean isEmpty() {
+        return !shouldGenerateFkConstraint();
+    }
+
     @Override
     public int compareTo(MergerToken o) {
         // add all AddRelationshipToDb to the end.

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToModel.java
index 2e7dbd4..05a3d6c 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToModel.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToModel.java
@@ -24,9 +24,6 @@ import org.apache.cayenne.map.DbJoin;
 import org.apache.cayenne.map.DbRelationship;
 import org.apache.cayenne.map.ObjEntity;
 
-import java.util.Collection;
-import java.util.Collections;
-
 public class AddRelationshipToModel extends AbstractToModelToken.Entity {
 
     public static final String COMMA_SEPARATOR = ", ";
@@ -55,8 +52,8 @@ public class AddRelationshipToModel extends AbstractToModelToken.Entity {
     }
 
     @Override
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        return Collections.singleton(factory.createDropRelationshipToDb(getEntity(), relationship));
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return factory.createDropRelationshipToDb(getEntity(), relationship);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToDb.java
index 81267c6..9584aaf 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToDb.java
@@ -25,7 +25,6 @@ import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.validation.SimpleValidationFailure;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -60,8 +59,8 @@ public class CreateTableToDb extends AbstractToDbToken.Entity {
         }
     }
 
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        return Collections.singleton(factory.createDropTableToModel(getEntity()));
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return factory.createDropTableToModel(getEntity());
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToModel.java
index 7ad863c..8352a27 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToModel.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToModel.java
@@ -24,9 +24,6 @@ import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.ObjEntity;
 
-import java.util.Collection;
-import java.util.Collections;
-
 /**
  * A {@link MergerToken} to add a {@link DbEntity} to a {@link DataMap}
  */
@@ -94,8 +91,8 @@ public class CreateTableToModel extends AbstractToModelToken.Entity {
         context.getDelegate().objEntityAdded(objEntity);
     }
 
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        return Collections.singleton(factory.createDropTableToDb(getEntity()));
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return factory.createDropTableToDb(getEntity());
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMerger.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMerger.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMerger.java
index a1f7d56..e485a5e 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMerger.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMerger.java
@@ -274,13 +274,9 @@ public class DbMerger {
                     }
                 }
 
-                // There is only one FK in the database so we create
-                // DropRelationshipToDb token only for direct relationships
-                // and skip token for toMany relationships
-                if (!detected.isToMany()) {
-                    MergerToken token = tokenFactory.createDropRelationshipToDb(dbEntity, detected);
-                    tokens.add(token);
-                }
+                // Add all relationships. Tokens will decide whether or not to execute
+                MergerToken token = tokenFactory.createDropRelationshipToDb(dbEntity, detected);
+                tokens.add(token);
             }
         }
 
@@ -293,15 +289,9 @@ public class DbMerger {
 
         for (DbRelationship rel : dbEntity.getRelationships()) {
             if (findDbRelationship(detectedEntity, rel) == null) {
+                // Add all relationships. Tokens will decide whether or not to execute
                 AddRelationshipToDb token = (AddRelationshipToDb) tokenFactory.createAddRelationshipToDb(dbEntity, rel);
-
-                if (token.shouldGenerateFkConstraint()) {
-                    // TODO I guess we should add relationship always; in order
-                    // TODO to have ability generate reverse relationship.
-                    // TODO If it doesn't have anything to execute it will be
-                    // TODO passed through execution without any affect on db
-                    tokens.add(token);
-                }
+                tokens.add(token);
             }
         }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToDb.java
index f2cd725..19914f0 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToDb.java
@@ -18,7 +18,6 @@
  ****************************************************************/
 package org.apache.cayenne.dbsync.merge;
 
-import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -46,8 +45,8 @@ public class DropColumnToDb extends AbstractToDbToken.EntityAndColumn {
         return Collections.singletonList(sqlBuffer.toString());
     }
 
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        return Collections.singleton(factory.createAddColumnToModel(getEntity(), getColumn()));
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return factory.createAddColumnToModel(getEntity(), getColumn());
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToModel.java
index 8ca0a2a..e92df93 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToModel.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToModel.java
@@ -27,8 +27,6 @@ import org.apache.cayenne.map.ObjAttribute;
 import org.apache.cayenne.map.ObjEntity;
 
 import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
 
 /**
@@ -42,8 +40,8 @@ public class DropColumnToModel extends AbstractToModelToken.EntityAndColumn {
     }
 
     @Override
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        return Collections.singleton(factory.createAddColumnToDb(getEntity(), getColumn()));
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return factory.createAddColumnToDb(getEntity(), getColumn());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java
index c94236b..0bc74c6 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java
@@ -25,8 +25,6 @@ import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbRelationship;
 import org.apache.cayenne.dbsync.reverse.db.DbRelationshipDetected;
 
-import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -49,7 +47,7 @@ public class DropRelationshipToDb extends AbstractToDbToken.Entity {
     @Override
     public List<String> createSql(DbAdapter adapter) {
         String fkName = getFkName();
-        if (fkName == null) {
+        if (fkName == null || relationship.isToMany()) {
             return Collections.emptyList();
         }
 
@@ -58,20 +56,20 @@ public class DropRelationshipToDb extends AbstractToDbToken.Entity {
                 "ALTER TABLE " + context.quotedFullyQualifiedName(getEntity()) + " DROP CONSTRAINT " + fkName);
     }
 
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        Collection<MergerToken> result = new ArrayList<>();
-        result.add(factory.createAddRelationshipToModel(getEntity(), relationship));
-        DbRelationship reverse = relationship.getReverseRelationship();
-        if(reverse == null) {
-            reverse = relationship.createReverseRelationship();
-            // NB name will be set in AddRelationshipToModel.execute() call
-            result.add(factory.createAddRelationshipToModel(relationship.getTargetEntity(), reverse));
-        }
-        return result;
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return factory.createAddRelationshipToModel(getEntity(), relationship);
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return relationship.isToMany();
     }
 
     @Override
     public String getTokenValue() {
+        if(relationship.isToMany()) {
+            return "Skip. No sql representation.";
+        }
         return relationship.getSourceEntity().getName() + "->" + relationship.getTargetEntityName();
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModel.java
index 3ef18fe..3908dbd 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModel.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModel.java
@@ -22,9 +22,6 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbRelationship;
 
-import java.util.Collection;
-import java.util.Collections;
-
 public class DropRelationshipToModel extends AbstractToModelToken.Entity {
 
     private final DbRelationship relationship;
@@ -35,8 +32,8 @@ public class DropRelationshipToModel extends AbstractToModelToken.Entity {
     }
 
     @Override
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        return Collections.singleton(factory.createAddRelationshipToDb(getEntity(), relationship));
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return factory.createAddRelationshipToDb(getEntity(), relationship);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToDb.java
index 0fe9f9f..3f416c7 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToDb.java
@@ -23,8 +23,6 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbEntity;
 
 import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
 
 public class DropTableToDb extends AbstractToDbToken.Entity {
@@ -46,8 +44,8 @@ public class DropTableToDb extends AbstractToDbToken.Entity {
     }
 
     @Override
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        return Collections.singleton(factory.createCreateTableToModel(getEntity()));
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return factory.createCreateTableToModel(getEntity());
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToModel.java
index 020edb0..b6eabee 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToModel.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToModel.java
@@ -23,9 +23,6 @@ import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.ObjEntity;
 
-import java.util.Collection;
-import java.util.Collections;
-
 /**
  * A {@link MergerToken} to remove a {@link DbEntity} from a {@link DataMap}. Any
  * {@link ObjEntity} mapped to the {@link DbEntity} will also be removed.
@@ -38,8 +35,8 @@ public class DropTableToModel extends AbstractToModelToken.Entity {
     }
 
     @Override
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        return Collections.singleton(factory.createCreateTableToDb(getEntity()));
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return factory.createCreateTableToDb(getEntity());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DummyReverseToken.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DummyReverseToken.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DummyReverseToken.java
index 0e6d23e..6428b36 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DummyReverseToken.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DummyReverseToken.java
@@ -20,9 +20,6 @@ package org.apache.cayenne.dbsync.merge;
 
 import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 
-import java.util.Collection;
-import java.util.Collections;
-
 /**
  * The reverse of a {@link MergerToken} that can not be reversed.. This will not execute
  * any thing, but {@link #createReverse(MergerTokenFactory)} will get back the reverse that
@@ -37,8 +34,8 @@ class DummyReverseToken implements MergerToken {
     }
 
     @Override
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        return Collections.singleton(reverse);
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return reverse;
     }
 
     @Override
@@ -47,6 +44,11 @@ class DummyReverseToken implements MergerToken {
     }
 
     @Override
+    public boolean isEmpty() {
+        return true;
+    }
+
+    @Override
     public MergeDirection getDirection() {
         return reverse.getDirection().reverseDirection();
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerToken.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerToken.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerToken.java
index 943a393..b2e7354 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerToken.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerToken.java
@@ -43,7 +43,7 @@ public interface MergerToken {
      * <p>
      * Not all tokens are reversible.
      */
-    Collection<MergerToken> createReverse(MergerTokenFactory factory);
+    MergerToken createReverse(MergerTokenFactory factory);
 
     /**
      * Executes synchronization operation.
@@ -52,4 +52,6 @@ public interface MergerToken {
      */
     void execute(MergerContext context);
 
+    boolean isEmpty();
+
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToDb.java
index 1b417ba..68078c2 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToDb.java
@@ -24,7 +24,6 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 
-import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -52,8 +51,8 @@ public class SetAllowNullToDb extends AbstractToDbToken.EntityAndColumn {
     }
 
     @Override
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        return Collections.singleton(factory.createSetNotNullToModel(getEntity(), getColumn()));
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return factory.createSetNotNullToModel(getEntity(), getColumn());
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToModel.java
index 30841bd..463f912 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToModel.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToModel.java
@@ -22,9 +22,6 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 
-import java.util.Collection;
-import java.util.Collections;
-
 /**
  * A {@link MergerToken} to set the mandatory field of a {@link DbAttribute} to false
  * 
@@ -36,8 +33,8 @@ public class SetAllowNullToModel extends AbstractToModelToken.EntityAndColumn {
     }
 
     @Override
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        return Collections.singleton(factory.createSetNotNullToDb(getEntity(), getColumn()));
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return factory.createSetNotNullToDb(getEntity(), getColumn());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToDb.java
index a52de9d..2434dd1 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToDb.java
@@ -26,7 +26,6 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 
-import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -106,7 +105,7 @@ public class SetColumnTypeToDb extends AbstractToDbToken.Entity {
     }
 
     @Override
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        return Collections.singleton(factory.createSetColumnTypeToModel(getEntity(), columnNew, columnOriginal));
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return factory.createSetColumnTypeToModel(getEntity(), columnNew, columnOriginal);
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToModel.java
index 1e51468..a960467 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToModel.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToModel.java
@@ -23,9 +23,6 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 
-import java.util.Collection;
-import java.util.Collections;
-
 /**
  * A {@link MergerToken} that modifies one original {@link DbAttribute} to match another
  * new {@link DbAttribute}s type, maxLength and precision. The name and mandatory fields
@@ -44,8 +41,8 @@ public class SetColumnTypeToModel extends AbstractToModelToken.Entity {
     }
 
     @Override
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        return Collections.singleton(factory.createSetColumnTypeToDb(getEntity(), columnNew, columnOriginal));
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return factory.createSetColumnTypeToDb(getEntity(), columnNew, columnOriginal);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToDb.java
index 1b4c5f6..0591c2a 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToDb.java
@@ -24,7 +24,6 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 
-import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -46,8 +45,8 @@ public class SetNotNullToDb extends AbstractToDbToken.EntityAndColumn {
     }
 
     @Override
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        return Collections.singleton(factory.createSetAllowNullToModel(getEntity(), getColumn()));
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return factory.createSetAllowNullToModel(getEntity(), getColumn());
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToModel.java
index 6aa7c63..dfc9b15 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToModel.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToModel.java
@@ -22,9 +22,6 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 
-import java.util.Collection;
-import java.util.Collections;
-
 /**
  * A {@link MergerToken} to set the mandatory field of a {@link DbAttribute} to true
  * 
@@ -36,8 +33,8 @@ public class SetNotNullToModel extends AbstractToModelToken.EntityAndColumn {
     }
 
     @Override
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        return Collections.singleton(factory.createSetAllowNullToDb(getEntity(), getColumn()));
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return factory.createSetAllowNullToDb(getEntity(), getColumn());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToDb.java
index e052e1c..077b6ef 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToDb.java
@@ -24,7 +24,10 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
 
 public class SetPrimaryKeyToDb extends AbstractToDbToken.Entity {
 
@@ -77,8 +80,8 @@ public class SetPrimaryKeyToDb extends AbstractToDbToken.Entity {
     }
 
     @Override
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        return Collections.singleton(factory.createSetPrimaryKeyToModel(getEntity(), primaryKeyNew, primaryKeyOriginal,
-                detectedPrimaryKeyName));
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return factory.createSetPrimaryKeyToModel(getEntity(), primaryKeyNew, primaryKeyOriginal,
+                detectedPrimaryKeyName);
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToModel.java
index 1048b7f..a2198ba 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToModel.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToModel.java
@@ -24,7 +24,6 @@ import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.event.AttributeEvent;
 
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -50,12 +49,12 @@ public class SetPrimaryKeyToModel extends AbstractToModelToken.Entity {
     }
 
     @Override
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        return Collections.singleton(factory.createSetPrimaryKeyToDb(
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return factory.createSetPrimaryKeyToDb(
                 getEntity(),
                 primaryKeyNew,
                 primaryKeyOriginal,
-                detectedPrimaryKeyName));
+                detectedPrimaryKeyName);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetValueForNullToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetValueForNullToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetValueForNullToDb.java
index ae231d1..340f2bf 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetValueForNullToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetValueForNullToDb.java
@@ -23,8 +23,6 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 
-import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
 
 
@@ -43,8 +41,8 @@ public class SetValueForNullToDb extends AbstractToDbToken.EntityAndColumn {
     }
 
     @Override
-    public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
-        return Collections.<MergerToken>singleton(new DummyReverseToken(this));
+    public MergerToken createReverse(MergerTokenFactory factory) {
+        return new DummyReverseToken(this);
     }
     
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/AddColumnToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/AddColumnToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/AddColumnToModelIT.java
index 0e9ef89..30fa47b 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/AddColumnToModelIT.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/AddColumnToModelIT.java
@@ -75,7 +75,7 @@ public class AddColumnToModelIT extends MergeCase {
         assertEquals(1, tokens.size());
         MergerToken token = tokens.get(0);
         if (token.getDirection().isToDb()) {
-            token = token.createReverse(mergerFactory()).iterator().next();
+            token = token.createReverse(mergerFactory());
         }
         assertTrue(token instanceof AddColumnToModel);
         execute(token);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/CreateTableToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/CreateTableToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/CreateTableToModelIT.java
index 48a02d5..bac6402 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/CreateTableToModelIT.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/CreateTableToModelIT.java
@@ -58,7 +58,7 @@ public class CreateTableToModelIT extends MergeCase {
 		assertEquals(1, tokens.size());
 		MergerToken token = tokens.get(0);
 		if (token.getDirection().isToDb()) {
-			token = token.createReverse(mergerFactory()).iterator().next();
+			token = token.createReverse(mergerFactory());
 		}
 		assertTrue(token.getClass().getName(), token instanceof CreateTableToModel);
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropColumnToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropColumnToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropColumnToModelIT.java
index 4e1b262..f6e0675 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropColumnToModelIT.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropColumnToModelIT.java
@@ -78,7 +78,7 @@ public class DropColumnToModelIT extends MergeCase {
 		assertEquals(1, tokens.size());
 		token = tokens.get(0);
 		if (token.getDirection().isToDb()) {
-			token = token.createReverse(mergerFactory()).iterator().next();
+			token = token.createReverse(mergerFactory());
 		}
 		assertTrue(token instanceof DropColumnToModel);
 		execute(token);
@@ -193,8 +193,8 @@ public class DropColumnToModelIT extends MergeCase {
 		assertTokens(tokens, 2, 0);
 		// TODO: reversing the following two tokens should also reverse the
 		// order
-		MergerToken token0 = tokens.get(0).createReverse(mergerFactory()).iterator().next();
-		MergerToken token1 = tokens.get(1).createReverse(mergerFactory()).iterator().next();
+		MergerToken token0 = tokens.get(0).createReverse(mergerFactory());
+		MergerToken token1 = tokens.get(1).createReverse(mergerFactory());
 		if (!(token0 instanceof DropRelationshipToModel && token1 instanceof DropColumnToModel || token1 instanceof DropRelationshipToModel
 				&& token0 instanceof DropColumnToModel)) {
 			fail();

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModelIT.java
index 41d6dbf..4981581 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModelIT.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModelIT.java
@@ -88,7 +88,7 @@ public class DropRelationshipToModelIT extends MergeCase {
 		assertSame(rel1To2, rel2To1.getReverseRelationship());
 		assertSame(rel2To1, rel1To2.getReverseRelationship());
 
-		assertTokensAndExecute(4, 0);
+		assertTokensAndExecute(3, 0);
 		assertTokensAndExecute(0, 0);
 
 		// create ObjEntities
@@ -153,8 +153,8 @@ public class DropRelationshipToModelIT extends MergeCase {
 		assertTokens(tokens, 2, 0);
 		// TODO: reversing the following two tokens should also reverse the
 		// order
-		MergerToken token0 = tokens.get(0).createReverse(mergerFactory()).iterator().next();
-		MergerToken token1 = tokens.get(1).createReverse(mergerFactory()).iterator().next();
+		MergerToken token0 = tokens.get(0).createReverse(mergerFactory());
+		MergerToken token1 = tokens.get(1).createReverse(mergerFactory());
 		if (!(token0 instanceof DropRelationshipToModel && token1 instanceof DropColumnToModel || token1 instanceof DropRelationshipToModel
 				&& token0 instanceof DropColumnToModel)) {
 			fail();

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropTableToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropTableToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropTableToModelIT.java
index 1d05205..5b1744a 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropTableToModelIT.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropTableToModelIT.java
@@ -72,7 +72,7 @@ public class DropTableToModelIT extends MergeCase {
 		assertEquals(1, tokens.size());
 		token = tokens.get(0);
 		if (token.getDirection().isToDb()) {
-			token = token.createReverse(mergerFactory()).iterator().next();
+			token = token.createReverse(mergerFactory());
 		}
 		assertTrue(token instanceof DropTableToModel);
 		execute(token);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java
index 0f4f1b1..e764778 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java
@@ -119,7 +119,18 @@ public abstract class MergeCase extends DbSyncCase {
             throw new CayenneRuntimeException("Can't doLoad dataMap from db.", e);
         }
 
-        return merger().filters(filters).build().createMergeTokens(map, dbImport);
+        List<MergerToken> tokens = merger().filters(filters).build().createMergeTokens(map, dbImport);
+        return filterEmpty(tokens);
+    }
+
+    private List<MergerToken> filterEmpty(List<MergerToken> tokens) {
+        List<MergerToken> tokensOut = new ArrayList<>();
+        for(MergerToken token : tokens) {
+            if(!token.isEmpty()) {
+                tokensOut.add(token);
+            }
+        }
+        return tokensOut;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReverseTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReverseTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReverseTest.java
index 34cd7cb..bde6c88 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReverseTest.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReverseTest.java
@@ -52,8 +52,8 @@ public class TokensReverseTest {
         testOneToOneReverse(factory().createDropColumnToModel(entity, attr));
 
         testOneToOneReverse(factory().createAddRelationshipToDb(entity, rel));
-        testCreateAddRelationshipToModel(factory().createAddRelationshipToModel(entity, rel));
-        testCreateDropRelationshipToDb(factory().createDropRelationshipToDb(entity, rel));
+        testOneToOneReverse(factory().createAddRelationshipToModel(entity, rel));
+        testOneToOneReverse(factory().createDropRelationshipToDb(entity, rel));
         testOneToOneReverse(factory().createDropRelationshipToModel(entity, rel));
 
         testOneToOneReverse(factory().createCreateTableToDb(entity));
@@ -76,32 +76,14 @@ public class TokensReverseTest {
         testOneToOneReverse(factory().createSetValueForNullToDb(entity, attr, new DefaultValueForNullProvider()));
     }
 
-    private void testReversTokenWithCount(MergerToken token, int countFirstReverse, int countSecondReverse) {
-        Collection<MergerToken> collectionReverse1 = token.createReverse(factory());
-        Assert.assertEquals(countFirstReverse, collectionReverse1.size());
-
-        Collection<MergerToken> collectionReverse2 = collectionReverse1.iterator().next().createReverse(factory());
-        Assert.assertEquals(countSecondReverse, collectionReverse2.size());
-
-        MergerToken token2 = collectionReverse2.iterator().next();
+    private void testOneToOneReverse(MergerToken token) {
+        MergerToken token2 = token.createReverse(factory()).createReverse(factory());
 
         Assert.assertEquals(token.getTokenName(), token2.getTokenName());
         Assert.assertEquals(token.getTokenValue(), token2.getTokenValue());
         Assert.assertEquals(token.getDirection(), token2.getDirection());
     }
 
-    private void testCreateAddRelationshipToModel(MergerToken token1) {
-        testReversTokenWithCount(token1, 1, 2);
-    }
-
-    private void testCreateDropRelationshipToDb(MergerToken token1) {
-        testReversTokenWithCount(token1, 2, 1);
-    }
-
-    private void testOneToOneReverse(MergerToken token1) {
-        testReversTokenWithCount(token1, 1, 1);
-    }
-
     private MergerTokenFactory factory() {
         return new HSQLMergerTokenFactory();
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DefaultDbImportAction.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DefaultDbImportAction.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DefaultDbImportAction.java
index 7f05d8c..e5b393f 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DefaultDbImportAction.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DefaultDbImportAction.java
@@ -117,7 +117,7 @@ public class DefaultDbImportAction implements DbImportAction {
     /**
      * Flattens many-to-many relationships in the generated model.
      */
-    protected static void flattenManyToManyRelationships(DataMap map, Collection<ObjEntity> loadedObjEntities,
+    public static void flattenManyToManyRelationships(DataMap map, Collection<ObjEntity> loadedObjEntities,
                                                          ObjectNameGenerator objectNameGenerator) {
         if (loadedObjEntities.isEmpty()) {
             return;
@@ -297,7 +297,7 @@ public class DefaultDbImportAction implements DbImportAction {
             if (token instanceof AbstractToModelToken) {
                 continue;
             }
-            tokens.addAll(token.createReverse(mergerTokenFactory));
+            tokens.add(token.createReverse(mergerTokenFactory));
         }
         return tokens;
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java
index 4ee133c..06260b6 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java
@@ -29,6 +29,7 @@ import org.apache.cayenne.dbsync.merge.MergeDirection;
 import org.apache.cayenne.dbsync.merge.MergerContext;
 import org.apache.cayenne.dbsync.merge.MergerToken;
 import org.apache.cayenne.dbsync.merge.ModelMergeDelegate;
+import org.apache.cayenne.dbsync.merge.ProxyModelMergeDelegate;
 import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider;
 import org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator;
@@ -58,6 +59,7 @@ import org.apache.cayenne.project.Project;
 import org.apache.cayenne.resource.Resource;
 import org.apache.cayenne.swing.BindingBuilder;
 import org.apache.cayenne.swing.ObjectBinding;
+import org.apache.cayenne.tools.dbimport.DefaultDbImportAction;
 import org.apache.cayenne.validation.ValidationResult;
 import org.apache.commons.logging.LogFactory;
 
@@ -72,7 +74,9 @@ import java.io.IOException;
 import java.io.PrintWriter;
 import java.sql.Connection;
 import java.sql.SQLException;
+import java.util.Collection;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 
 public class MergerOptions extends CayenneController {
@@ -276,209 +280,95 @@ public class MergerOptions extends CayenneController {
             return;
         }
 
-        final ProjectController c = getProjectController();
-
-        final Object src = this;
-        final DataChannelDescriptor domain = (DataChannelDescriptor) getProjectController()
-                .getProject()
-                .getRootNode();
-        final DataNodeDescriptor node = getProjectController().getCurrentDataNode();
-
-        ModelMergeDelegate delegate = new ModelMergeDelegate() {
-
-            public void dbAttributeAdded(DbAttribute att) {
-                if (c.getCurrentDbEntity() == att.getEntity()) {
-                    c.fireDbAttributeDisplayEvent(new AttributeDisplayEvent(src, att, att
-                            .getEntity(), dataMap, domain));
-                }
-            }
-
-            public void dbAttributeModified(DbAttribute att) {
-                if (c.getCurrentDbEntity() == att.getEntity()) {
-                    c.fireDbAttributeDisplayEvent(new AttributeDisplayEvent(src, att, att
-                            .getEntity(), dataMap, domain));
-                }
-            }
-
-            public void dbAttributeRemoved(DbAttribute att) {
-                if (c.getCurrentDbEntity() == att.getEntity()) {
-                    c.fireDbAttributeDisplayEvent(new AttributeDisplayEvent(src, att, att
-                            .getEntity(), dataMap, domain));
-                }
-            }
-
-            public void dbEntityAdded(DbEntity ent) {
-                c.fireDbEntityEvent(new EntityEvent(src, ent, MapEvent.ADD));
-                c.fireDbEntityDisplayEvent(new EntityDisplayEvent(
-                        src,
-                        ent,
-                        dataMap,
-                        node,
-                        domain));
-            }
+        DataSource dataSource;
+        try {
+            dataSource = connectionInfo.makeDataSource(getApplication()
+                    .getClassLoadingService());
+        } catch (SQLException ex) {
+            reportError("Migration Error", ex);
+            return;
+        }
 
-            public void dbEntityRemoved(DbEntity ent) {
-                c.fireDbEntityEvent(new EntityEvent(src, ent, MapEvent.REMOVE));
-                c.fireDbEntityDisplayEvent(new EntityDisplayEvent(
-                        src,
-                        ent,
-                        dataMap,
-                        node,
-                        domain));
-            }
+        final Collection<ObjEntity> loadedObjEntities = new LinkedList<>();
 
-            public void dbRelationshipAdded(DbRelationship rel) {
-                if (c.getCurrentDbEntity() == rel.getSourceEntity()) {
-                    c.fireDbRelationshipDisplayEvent(new RelationshipDisplayEvent(
-                            src,
-                            rel,
-                            rel.getSourceEntity(),
-                            dataMap,
-                            domain));
-                }
-            }
+        MergerContext mergerContext = MergerContext.builder(dataMap)
+                .syntheticDataNode(dataSource, adapter)
+                .delegate(createDelegate(loadedObjEntities))
+                .build();
 
-            public void dbRelationshipRemoved(DbRelationship rel) {
-                if (c.getCurrentDbEntity() == rel.getSourceEntity()) {
-                    c.fireDbRelationshipDisplayEvent(new RelationshipDisplayEvent(
-                            src,
-                            rel,
-                            rel.getSourceEntity(),
-                            dataMap,
-                            domain));
-                }
-            }
+        boolean modelChanged = applyTokens(tokensToMigrate, mergerContext);
 
-            public void objAttributeAdded(ObjAttribute att) {
-                if (c.getCurrentObjEntity() == att.getEntity()) {
-                    c.fireObjAttributeDisplayEvent(new AttributeDisplayEvent(
-                            src,
-                            att,
-                            att.getEntity(),
-                            dataMap,
-                            domain));
-                }
-            }
+        DefaultDbImportAction.flattenManyToManyRelationships(dataMap, loadedObjEntities, mergerContext.getNameGenerator());
 
-            public void objAttributeModified(ObjAttribute att) {
-                if (c.getCurrentObjEntity() == att.getEntity()) {
-                    c.fireObjAttributeDisplayEvent(new AttributeDisplayEvent(
-                            src,
-                            att,
-                            att.getEntity(),
-                            dataMap,
-                            domain));
-                }
-            }
+        notifyProjectModified(modelChanged);
 
-            public void objAttributeRemoved(ObjAttribute att) {
-                if (c.getCurrentObjEntity() == att.getEntity()) {
-                    c.fireObjAttributeDisplayEvent(new AttributeDisplayEvent(
-                            src,
-                            att,
-                            att.getEntity(),
-                            dataMap,
-                            domain));
-                }
-            }
+        reportFailures(mergerContext);
+    }
 
+    private ModelMergeDelegate createDelegate(final Collection<ObjEntity> loadedObjEntities) {
+        return new ProxyModelMergeDelegate(
+                new MigrateModelMergeDelegate(getProjectController(), this)) {
+            @Override
             public void objEntityAdded(ObjEntity ent) {
-                c.fireObjEntityEvent(new EntityEvent(src, ent, MapEvent.ADD));
-                c.fireObjEntityDisplayEvent(new EntityDisplayEvent(
-                        src,
-                        ent,
-                        dataMap,
-                        node,
-                        domain));
+                loadedObjEntities.add(ent);
+                super.objEntityAdded(ent);
             }
-
-            public void objEntityRemoved(ObjEntity ent) {
-                c.fireObjEntityEvent(new EntityEvent(src, ent, MapEvent.REMOVE));
-                c.fireObjEntityDisplayEvent(new EntityDisplayEvent(
-                        src,
-                        ent,
-                        dataMap,
-                        node,
-                        domain));
-            }
-
-            public void objRelationshipAdded(ObjRelationship rel) {
-                if (c.getCurrentObjEntity() == rel.getSourceEntity()) {
-                    c.fireObjRelationshipDisplayEvent(new RelationshipDisplayEvent(
-                            src,
-                            rel,
-                            rel.getSourceEntity(),
-                            dataMap,
-                            domain));
-                }
-            }
-
-            public void objRelationshipRemoved(ObjRelationship rel) {
-                if (c.getCurrentObjEntity() == rel.getSourceEntity()) {
-                    c.fireObjRelationshipDisplayEvent(new RelationshipDisplayEvent(
-                            src,
-                            rel,
-                            rel.getSourceEntity(),
-                            dataMap,
-                            domain));
-                }
-            }
-
         };
+    }
 
-        try {
-            DataSource dataSource = connectionInfo.makeDataSource(getApplication()
-                    .getClassLoadingService());
-
-            MergerContext mergerContext = MergerContext.builder(dataMap)
-                    .syntheticDataNode(dataSource, adapter)
-                    .delegate(delegate)
-                    .build();
+    private boolean applyTokens(List<MergerToken> tokensToMigrate, MergerContext mergerContext) {
+        boolean modelChanged = false;
 
-            boolean modelChanged = false;
+        try {
             for (MergerToken tok : tokensToMigrate) {
-                int numOfFailuresBefore = mergerContext
-                        .getValidationResult()
-                        .getFailures()
-                        .size();
+                int numOfFailuresBefore = getFailuresCount(mergerContext);
+
                 tok.execute(mergerContext);
+
                 if (!modelChanged && tok.getDirection().equals(MergeDirection.TO_MODEL)) {
                     modelChanged = true;
                 }
-
-                if (numOfFailuresBefore == mergerContext
-                        .getValidationResult()
-                        .getFailures()
-                        .size()) {
+                if (numOfFailuresBefore == getFailuresCount(mergerContext)) {
                     // looks like the token executed without failures
                     tokens.removeToken(tok);
                 }
             }
+        } catch (Throwable th) {
+            reportError("Migration Error", th);
+        }
 
-            if (modelChanged) {
-                // mark the model as unsaved
-                Project project = getApplication().getProject();
-                project.setModified(true);
+        return modelChanged;
+    }
 
-                ProjectController projectController = getApplication()
-                        .getFrameController()
-                        .getProjectController();
-                projectController.setDirty(true);
-            }
+    private int getFailuresCount(MergerContext mergerContext) {
+        return mergerContext.getValidationResult().getFailures().size();
+    }
 
-            ValidationResult failures = mergerContext.getValidationResult();
+    private void reportFailures(MergerContext mergerContext) {
+        ValidationResult failures = mergerContext.getValidationResult();
+        if (failures == null || !failures.hasFailures()) {
+            JOptionPane.showMessageDialog(getView(), "Migration Complete.");
+        } else {
+            new ValidationResultBrowser(this).startupAction(
+                    "Migration Complete",
+                    "Migration finished. The following problem(s) were ignored.",
+                    failures);
+        }
+    }
 
-            if (failures == null || !failures.hasFailures()) {
-                JOptionPane.showMessageDialog(getView(), "Migration Complete.");
-            } else {
-                new ValidationResultBrowser(this).startupAction(
-                        "Migration Complete",
-                        "Migration finished. The following problem(s) were ignored.",
-                        failures);
-            }
-        } catch (Throwable th) {
-            reportError("Migration Error", th);
+    private void notifyProjectModified(boolean modelChanged) {
+        if(!modelChanged) {
+            return;
         }
+
+        // mark the model as unsaved
+        Project project = getApplication().getProject();
+        project.setModified(true);
+
+        ProjectController projectController = getApplication()
+                .getFrameController()
+                .getProjectController();
+        projectController.setDirty(true);
     }
 
     /**
@@ -518,4 +408,160 @@ public class MergerOptions extends CayenneController {
     public void closeAction() {
         view.dispose();
     }
+
+    private class MigrateModelMergeDelegate implements ModelMergeDelegate {
+
+        private final ProjectController controller;
+        private final Object src;
+        private final DataChannelDescriptor domain;
+        private final DataNodeDescriptor node;
+
+        public MigrateModelMergeDelegate(ProjectController controller, Object src) {
+            this.controller = controller;
+            this.src = src;
+            domain = (DataChannelDescriptor) getProjectController()
+                    .getProject()
+                    .getRootNode();
+            node = getProjectController().getCurrentDataNode();
+        }
+
+        public void dbAttributeAdded(DbAttribute att) {
+            if (controller.getCurrentDbEntity() == att.getEntity()) {
+                controller.fireDbAttributeDisplayEvent(new AttributeDisplayEvent(src, att, att
+                        .getEntity(), dataMap, domain));
+            }
+        }
+
+        public void dbAttributeModified(DbAttribute att) {
+            if (controller.getCurrentDbEntity() == att.getEntity()) {
+                controller.fireDbAttributeDisplayEvent(new AttributeDisplayEvent(src, att, att
+                        .getEntity(), dataMap, domain));
+            }
+        }
+
+        public void dbAttributeRemoved(DbAttribute att) {
+            if (controller.getCurrentDbEntity() == att.getEntity()) {
+                controller.fireDbAttributeDisplayEvent(new AttributeDisplayEvent(src, att, att
+                        .getEntity(), dataMap, domain));
+            }
+        }
+
+        public void dbEntityAdded(DbEntity ent) {
+            controller.fireDbEntityEvent(new EntityEvent(src, ent, MapEvent.ADD));
+            controller.fireDbEntityDisplayEvent(new EntityDisplayEvent(
+                    src,
+                    ent,
+                    dataMap,
+                    node,
+                    domain));
+        }
+
+        public void dbEntityRemoved(DbEntity ent) {
+            controller.fireDbEntityEvent(new EntityEvent(src, ent, MapEvent.REMOVE));
+            controller.fireDbEntityDisplayEvent(new EntityDisplayEvent(
+                    src,
+                    ent,
+                    dataMap,
+                    node,
+                    domain));
+        }
+
+        public void dbRelationshipAdded(DbRelationship rel) {
+            if (controller.getCurrentDbEntity() == rel.getSourceEntity()) {
+                controller.fireDbRelationshipDisplayEvent(new RelationshipDisplayEvent(
+                        src,
+                        rel,
+                        rel.getSourceEntity(),
+                        dataMap,
+                        domain));
+            }
+        }
+
+        public void dbRelationshipRemoved(DbRelationship rel) {
+            if (controller.getCurrentDbEntity() == rel.getSourceEntity()) {
+                controller.fireDbRelationshipDisplayEvent(new RelationshipDisplayEvent(
+                        src,
+                        rel,
+                        rel.getSourceEntity(),
+                        dataMap,
+                        domain));
+            }
+        }
+
+        public void objAttributeAdded(ObjAttribute att) {
+            if (controller.getCurrentObjEntity() == att.getEntity()) {
+                controller.fireObjAttributeDisplayEvent(new AttributeDisplayEvent(
+                        src,
+                        att,
+                        att.getEntity(),
+                        dataMap,
+                        domain));
+            }
+        }
+
+        public void objAttributeModified(ObjAttribute att) {
+            if (controller.getCurrentObjEntity() == att.getEntity()) {
+                controller.fireObjAttributeDisplayEvent(new AttributeDisplayEvent(
+                        src,
+                        att,
+                        att.getEntity(),
+                        dataMap,
+                        domain));
+            }
+        }
+
+        public void objAttributeRemoved(ObjAttribute att) {
+            if (controller.getCurrentObjEntity() == att.getEntity()) {
+                controller.fireObjAttributeDisplayEvent(new AttributeDisplayEvent(
+                        src,
+                        att,
+                        att.getEntity(),
+                        dataMap,
+                        domain));
+            }
+        }
+
+        public void objEntityAdded(ObjEntity ent) {
+            controller.fireObjEntityEvent(new EntityEvent(src, ent, MapEvent.ADD));
+            controller.fireObjEntityDisplayEvent(new EntityDisplayEvent(
+                    src,
+                    ent,
+                    dataMap,
+                    node,
+                    domain));
+        }
+
+        public void objEntityRemoved(ObjEntity ent) {
+            controller.fireObjEntityEvent(new EntityEvent(src, ent, MapEvent.REMOVE));
+            controller.fireObjEntityDisplayEvent(new EntityDisplayEvent(
+                    src,
+                    ent,
+                    dataMap,
+                    node,
+                    domain));
+        }
+
+        public void objRelationshipAdded(ObjRelationship rel) {
+            if (controller.getCurrentObjEntity() == rel.getSourceEntity()) {
+                controller.fireObjRelationshipDisplayEvent(new RelationshipDisplayEvent(
+                        src,
+                        rel,
+                        rel.getSourceEntity(),
+                        dataMap,
+                        domain));
+            }
+        }
+
+        public void objRelationshipRemoved(ObjRelationship rel) {
+            if (controller.getCurrentObjEntity() == rel.getSourceEntity()) {
+                controller.fireObjRelationshipDisplayEvent(new RelationshipDisplayEvent(
+                        src,
+                        rel,
+                        rel.getSourceEntity(),
+                        dataMap,
+                        domain));
+            }
+        }
+
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/29d64392/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenSelectorController.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenSelectorController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenSelectorController.java
index 8c36d25..e23f780 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenSelectorController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenSelectorController.java
@@ -196,7 +196,7 @@ public class MergerTokenSelectorController extends CayenneController {
         }
         int i = selectableTokensList.indexOf(token);
         // TODO change to collection iteration
-        MergerToken reverse = token.createReverse(mergerTokenFactory).iterator().next();
+        MergerToken reverse = token.createReverse(mergerTokenFactory);
         selectableTokensList.set(i, reverse);
         if (excludedTokens.remove(token)) {
             excludedTokens.add(reverse);
@@ -228,7 +228,7 @@ public class MergerTokenSelectorController extends CayenneController {
         for (int i = 0; i < selectableTokensList.size(); i++) {
             MergerToken token = selectableTokensList.get(i);
             // TODO change to collection iteration
-            MergerToken reverse = token.createReverse(mergerTokenFactory).iterator().next();
+            MergerToken reverse = token.createReverse(mergerTokenFactory);
             selectableTokensList.set(i, reverse);
             if (excludedTokens.remove(token)) {
                 excludedTokens.add(reverse);


[9/9] cayenne git commit: Merge branch '129'

Posted by sk...@apache.org.
Merge branch '129'


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

Branch: refs/heads/master
Commit: 74e5e2f3ce75217c1ddefd32cef85a8ef473059f
Parents: 4bd2cad 1462b2d
Author: Savva Kolbachev <s....@gmail.com>
Authored: Wed Nov 16 21:39:38 2016 +0300
Committer: Savva Kolbachev <s....@gmail.com>
Committed: Wed Nov 16 21:39:38 2016 +0300

----------------------------------------------------------------------
 .../cayenne/dbsync/merge/AbstractToDbToken.java |   4 +
 .../dbsync/merge/AbstractToModelToken.java      |   4 +
 .../dbsync/merge/AddRelationshipToDb.java       |  23 +-
 .../dbsync/merge/AddRelationshipToModel.java    |   7 +-
 .../apache/cayenne/dbsync/merge/DbMerger.java   |  21 +-
 .../dbsync/merge/DropRelationshipToDb.java      |  13 +-
 .../cayenne/dbsync/merge/DummyReverseToken.java |   5 +
 .../cayenne/dbsync/merge/MergerToken.java       |   4 +
 .../dbsync/merge/DropRelationshipToModelIT.java |   6 +-
 .../apache/cayenne/dbsync/merge/MergeCase.java  |  13 +-
 .../cayenne/dbsync/merge/MergerFactoryIT.java   |   8 +-
 .../cayenne/dbsync/merge/TokensReversTest.java  |  89 -------
 .../cayenne/dbsync/merge/TokensReverseTest.java |  90 +++++++
 .../tools/dbimport/DefaultDbImportAction.java   |   2 +-
 .../modeler/dialog/db/MergerOptions.java        | 264 ++++++-------------
 .../db/MergerTokenSelectorController.java       |   4 +-
 16 files changed, 236 insertions(+), 321 deletions(-)
----------------------------------------------------------------------



[2/9] cayenne git commit: Merge branch 'master' of git://git.apache.org/cayenne into modeler-reverseengineering-added-relation-fix

Posted by sk...@apache.org.
Merge branch 'master' of git://git.apache.org/cayenne into modeler-reverseengineering-added-relation-fix


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

Branch: refs/heads/master
Commit: db9a49da9dd4813bb87db3a2d41477dce2db5904
Parents: f2842b9 7293ed6
Author: Nikita Timofeev <st...@gmail.com>
Authored: Fri Nov 4 17:24:28 2016 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Fri Nov 4 17:24:28 2016 +0300

----------------------------------------------------------------------
 .../dbsync/merge/EntityMergeSupport.java        |  2 +-
 .../naming/DefaultObjectNameGenerator.java      | 69 +++++++++++----
 .../naming/LegacyObjectNameGenerator.java       | 58 -------------
 .../dbsync/naming/ObjectNameGenerator.java      | 24 +++---
 .../cayenne/dbsync/reverse/db/DbLoader.java     | 19 ++--
 .../cayenne/dbsync/reverse/db/ExportedKey.java  |  4 +-
 .../dbsync/merge/EntityMergeSupportIT.java      | 15 ++--
 .../naming/DefaultObjectNameGeneratorTest.java  | 91 +++++++++++---------
 .../naming/LegacyObjectNameGeneratorTest.java   | 55 ------------
 .../dbimport/ManyToManyCandidateEntity.java     | 12 +--
 .../dbimport/ManyToManyCandidateEntityTest.java |  4 +-
 docs/doc/src/main/resources/RELEASE-NOTES.txt   |  1 +
 docs/doc/src/main/resources/UPGRADE.txt         |  4 +
 .../InferRelationshipsControllerBase.java       | 60 +++++++------
 .../dialog/objentity/ObjRelationshipInfo.java   | 21 ++---
 .../modeler/util/NameGeneratorPreferences.java  | 10 +--
 .../tools/dbimport/testOneToOne.map.xml-result  |  4 +-
 17 files changed, 187 insertions(+), 266 deletions(-)
----------------------------------------------------------------------



[5/9] cayenne git commit: Some clean up

Posted by sk...@apache.org.
Some clean up


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

Branch: refs/heads/master
Commit: cb41151fda1fe7e4f6f0af7f548a034e53491c04
Parents: 29d6439
Author: Nikita Timofeev <st...@gmail.com>
Authored: Mon Nov 14 21:03:48 2016 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Mon Nov 14 21:03:48 2016 +0300

----------------------------------------------------------------------
 .../cayenne/dbsync/merge/AddRelationshipToDb.java | 18 ++++++++----------
 .../dbsync/merge/DropRelationshipToDb.java        |  7 +++----
 .../dialog/db/MergerTokenSelectorController.java  |  6 +-----
 3 files changed, 12 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/cb41151f/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToDb.java
index 90d92b0..8712613 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToDb.java
@@ -42,8 +42,7 @@ public class AddRelationshipToDb extends AbstractToDbToken.Entity {
     @Override
     public List<String> createSql(DbAdapter adapter) {
         // TODO: skip FK to a different DB
-
-        if (this.shouldGenerateFkConstraint()) {
+        if (!this.isEmpty()) {
             String fksql = adapter.createFkConstraint(relationship);
             if (fksql != null) {
                 return Collections.singletonList(fksql);
@@ -52,12 +51,6 @@ public class AddRelationshipToDb extends AbstractToDbToken.Entity {
         return Collections.emptyList();
     }
 
-    public boolean shouldGenerateFkConstraint() {
-        return !relationship.isToMany()
-                && relationship.isToPK() // TODO it is not necessary primary key it can be unique index
-                && !relationship.isToDependentPK();
-    }
-
     @Override
     public MergerToken createReverse(MergerTokenFactory factory) {
         return factory.createDropRelationshipToModel(getEntity(), relationship);
@@ -65,7 +58,7 @@ public class AddRelationshipToDb extends AbstractToDbToken.Entity {
 
     @Override
     public String getTokenValue() {
-        if (this.shouldGenerateFkConstraint()) {
+        if (!this.isEmpty()) {
             return relationship.getSourceEntity().getName() + "->" + relationship.getTargetEntityName();
         } else {
             return "Skip. No sql representation.";
@@ -74,7 +67,12 @@ public class AddRelationshipToDb extends AbstractToDbToken.Entity {
 
     @Override
     public boolean isEmpty() {
-        return !shouldGenerateFkConstraint();
+        // Method DbRelationship.isSourceIndependentFromTargetChange() looks same
+        return relationship.isSourceIndependentFromTargetChange();
+        /*return relationship.isToMany()
+                || relationship.isToDependentPK()
+                || !relationship.isToPK(); // TODO it is not necessary primary key it can be unique index
+        */
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/cb41151f/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java
index 0bc74c6..ec939ef 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java
@@ -46,14 +46,13 @@ public class DropRelationshipToDb extends AbstractToDbToken.Entity {
 
     @Override
     public List<String> createSql(DbAdapter adapter) {
-        String fkName = getFkName();
-        if (fkName == null || relationship.isToMany()) {
+        if (isEmpty()) {
             return Collections.emptyList();
         }
 
         QuotingStrategy context = adapter.getQuotingStrategy();
         return Collections.singletonList(
-                "ALTER TABLE " + context.quotedFullyQualifiedName(getEntity()) + " DROP CONSTRAINT " + fkName);
+                "ALTER TABLE " + context.quotedFullyQualifiedName(getEntity()) + " DROP CONSTRAINT " + getFkName());
     }
 
     public MergerToken createReverse(MergerTokenFactory factory) {
@@ -62,7 +61,7 @@ public class DropRelationshipToDb extends AbstractToDbToken.Entity {
 
     @Override
     public boolean isEmpty() {
-        return relationship.isToMany();
+        return getFkName() == null || relationship.isToMany();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/cb41151f/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenSelectorController.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenSelectorController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenSelectorController.java
index e23f780..cfb1af1 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenSelectorController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenSelectorController.java
@@ -168,9 +168,7 @@ public class MergerTokenSelectorController extends CayenneController {
         TableColumn directionColumn = columnModel.getColumn(
                 MergerTokenTableModel.COL_DIRECTION);
         directionColumn.setCellEditor(new DefaultCellEditor(directionCombo));
-        
-        // TODO: correct width for the different columns
-        //view.getTokens().setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
+
         columnModel.getColumn(MergerTokenTableModel.COL_SELECT).setPreferredWidth(50);
         columnModel.getColumn(MergerTokenTableModel.COL_DIRECTION).setPreferredWidth(100);
         columnModel.getColumn(MergerTokenTableModel.COL_SELECT).setMaxWidth(50);
@@ -195,7 +193,6 @@ public class MergerTokenSelectorController extends CayenneController {
             return;
         }
         int i = selectableTokensList.indexOf(token);
-        // TODO change to collection iteration
         MergerToken reverse = token.createReverse(mergerTokenFactory);
         selectableTokensList.set(i, reverse);
         if (excludedTokens.remove(token)) {
@@ -227,7 +224,6 @@ public class MergerTokenSelectorController extends CayenneController {
         
         for (int i = 0; i < selectableTokensList.size(); i++) {
             MergerToken token = selectableTokensList.get(i);
-            // TODO change to collection iteration
             MergerToken reverse = token.createReverse(mergerTokenFactory);
             selectableTokensList.set(i, reverse);
             if (excludedTokens.remove(token)) {


[7/9] cayenne git commit: Merge branch 'master' into modeler-reverseengineering-added-relation-fix

Posted by sk...@apache.org.
Merge branch 'master' into modeler-reverseengineering-added-relation-fix

# Conflicts:
#	modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java


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

Branch: refs/heads/master
Commit: 8c5985ee2f938d03b9ce55c5a24eec9485a7d54b
Parents: 2eb2172 56906f0
Author: Nikita Timofeev <st...@gmail.com>
Authored: Tue Nov 15 10:38:57 2016 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Tue Nov 15 10:38:57 2016 +0300

----------------------------------------------------------------------
 .../cayenne/dbsync/CayenneDbSyncModule.java     |  68 --------
 .../org/apache/cayenne/dbsync/DbSyncModule.java |  68 ++++++++
 .../dbsync/merge/EntityMergeSupport.java        |  61 ++++++-
 .../cayenne/dbsync/merge/MergerContext.java     |   3 +-
 .../factory/MergerTokenFactoryProvider.java     |   8 +-
 .../dbsync/naming/DbEntityNameStemmer.java      |  29 ++++
 .../naming/DefaultObjectNameGenerator.java      |  26 ++-
 .../cayenne/dbsync/naming/NoStemStemmer.java    |  39 +++++
 .../dbsync/naming/ObjectNameGenerator.java      |  11 +-
 .../cayenne/dbsync/naming/PatternStemmer.java   |  46 +++++
 .../cayenne/dbsync/reverse/db/DbLoader.java     |  59 +++----
 .../dbsync/merge/EntityMergeSupportIT.java      |   4 +-
 .../apache/cayenne/dbsync/merge/MergeCase.java  |   3 +-
 .../naming/DefaultObjectNameGeneratorTest.java  |   3 +-
 .../dbsync/naming/PatternStemmerTest.java       |  61 +++++++
 .../cayenne/dbsync/reverse/db/DbLoaderIT.java   |   3 +-
 .../unit/DbSyncServerRuntimeProvider.java       |   4 +-
 .../project/validation/EJBQLQueryValidator.java |   9 +-
 .../validation/EJBQLStatementValidator.java     |  34 ++--
 .../java/org/apache/cayenne/query/Ordering.java |   5 +-
 .../org/apache/cayenne/dba/firebird/types.xml   |  10 +-
 .../org/apache/cayenne/query/OrderingTest.java  |  62 +++++++
 .../apache/cayenne/tools/DbGeneratorTask.java   |   4 +-
 .../apache/cayenne/tools/DbImporterTask.java    |  23 ++-
 .../tools/dbimport/DbImportConfiguration.java   |  52 ++++--
 .../cayenne/tools/dbimport/DbImportModule.java  |   5 +-
 .../tools/dbimport/DefaultDbImportAction.java   |  54 +++++-
 .../tools/dbimport/DbImportModuleTest.java      |   4 +-
 .../dbimport/DefaultDbImportActionTest.java     |  48 +++---
 .../dbimport/ManyToManyCandidateEntityTest.java |   4 +-
 docs/doc/pom.xml                                |   6 +-
 docs/doc/src/main/resources/RELEASE-NOTES.txt   |   4 +
 modeler/cayenne-modeler-generic-ext/pom.xml     |   4 +-
 .../generic/GenericPlatformInitializer.java     |   2 +-
 modeler/cayenne-modeler-win-ext/pom.xml         |  93 ++++++++++
 .../modeler/win/WinCayenneModelerModule.java    |  30 ++++
 .../org/apache/cayenne/modeler/win/WinMain.java |  50 ++++++
 .../modeler/win/WinPlatformInitializer.java     |  43 +++++
 modeler/cayenne-modeler-win/pom.xml             |   7 +-
 modeler/cayenne-modeler/pom.xml                 |   2 +-
 .../java/org/apache/cayenne/modeler/Main.java   |   4 +-
 .../modeler/action/CreateEmbeddableAction.java  |   4 +-
 .../modeler/action/CreateObjEntityAction.java   |   6 +-
 .../modeler/action/DefaultActionManager.java    |   5 +-
 .../modeler/action/ImportDataMapAction.java     |   8 +-
 .../cayenne/modeler/action/MigrateAction.java   |   3 +-
 .../action/ReverseEngineeringAction.java        |  14 +-
 .../modeler/dialog/DbImportProjectSaver.java    |  77 +++++++++
 .../modeler/dialog/codegen/CustomModePanel.java |   1 +
 .../dialog/datamap/PackageUpdateController.java |   9 +-
 .../modeler/dialog/db/DbLoaderHelper.java       | 168 ++++++++++---------
 .../dialog/db/DbLoaderOptionsDialog.java        |  55 +++---
 .../modeler/dialog/db/MergerOptions.java        |  12 +-
 .../dialog/db/ModelerDbImportAction.java        |  95 +++--------
 .../objentity/ObjAttributeInfoDialogView.java   |   4 +-
 .../cayenne/modeler/editor/EditorView.java      |   2 +-
 .../modeler/editor/EjbqlQueryScriptsTab.java    |   5 +-
 .../modeler/editor/dbentity/DbEntityTab.java    |   2 +-
 .../cayenne/modeler/util/LongRunningTask.java   |  30 ++--
 .../modeler/util/NameGeneratorPreferences.java  |   3 +-
 .../util/PathChooserComboBoxCellEditor.java     |   3 +
 modeler/pom.xml                                 |   3 +-
 .../apache/cayenne/tools/DbGeneratorMojo.java   |   4 +-
 .../apache/cayenne/tools/DbImporterMojo.java    |  40 +++--
 .../tools/DbImporterMojoConfigurationTest.java  |   6 +-
 .../cayenne/tools/DbImporterMojoTest.java       |  29 ++--
 .../testCustomObjectLayerSettings-pom.xml       |   1 +
 ...testCustomObjectLayerSettings.map.xml-result |   6 +
 .../dbimport/testCustomObjectLayerSettings.sql  |   5 +
 .../dbimport/testForceDataMapSchema-pom.xml     |  46 +++++
 .../dbimport/testForceDataMapSchema.map.xml     |  26 +++
 .../testForceDataMapSchema.map.xml-result       |  52 ++++++
 .../tools/dbimport/testForceDataMapSchema.sql   |  40 +++++
 pom.xml                                         |  12 +-
 74 files changed, 1343 insertions(+), 488 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/8c5985ee/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cayenne/blob/8c5985ee/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DefaultDbImportAction.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cayenne/blob/8c5985ee/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java
----------------------------------------------------------------------
diff --cc modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java
index b19fe35,9c417fe..344215d
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java
@@@ -20,11 -20,11 +20,12 @@@
  package org.apache.cayenne.modeler.dialog.db;
  
  import org.apache.cayenne.CayenneRuntimeException;
- import org.apache.cayenne.configuration.event.DataMapEvent;
- import org.apache.cayenne.dba.JdbcAdapter;
+ import org.apache.cayenne.configuration.DataChannelDescriptor;
+ import org.apache.cayenne.configuration.DataNodeDescriptor;
+ import org.apache.cayenne.dba.DbAdapter;
  import org.apache.cayenne.dbsync.merge.AbstractToDbToken;
  import org.apache.cayenne.dbsync.merge.DbMerger;
 +import org.apache.cayenne.dbsync.merge.DefaultModelMergeDelegate;
  import org.apache.cayenne.dbsync.merge.MergeDirection;
  import org.apache.cayenne.dbsync.merge.MergerContext;
  import org.apache.cayenne.dbsync.merge.MergerToken;


[3/9] cayenne git commit: - Reverse Engineering Fix: toMany relationships are not created

Posted by sk...@apache.org.
- Reverse Engineering Fix: toMany relationships are not created


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

Branch: refs/heads/master
Commit: 8718ee95e320b62a271e720ca4bee57bbd5a0994
Parents: db9a49d
Author: Nikita Timofeev <st...@gmail.com>
Authored: Tue Nov 8 15:24:06 2016 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Tue Nov 8 15:24:06 2016 +0300

----------------------------------------------------------------------
 .../dbsync/merge/AddRelationshipToModel.java    |   7 +-
 .../apache/cayenne/dbsync/merge/DbMerger.java   |  23 ++--
 .../dbsync/merge/DropRelationshipToDb.java      |   7 +-
 .../dbsync/merge/DropRelationshipToModelIT.java |   4 +-
 .../cayenne/dbsync/merge/MergerFactoryIT.java   |   8 +-
 .../cayenne/dbsync/merge/TokensReversTest.java  |  92 ----------------
 .../cayenne/dbsync/merge/TokensReverseTest.java | 108 +++++++++++++++++++
 7 files changed, 134 insertions(+), 115 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/8718ee95/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToModel.java
index bae2a20..2e7dbd4 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToModel.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToModel.java
@@ -61,11 +61,12 @@ public class AddRelationshipToModel extends AbstractToModelToken.Entity {
 
     @Override
     public void execute(MergerContext context) {
+        // Set name to relationship if it was created without it, e.g. in createReverse() action
+        if(relationship.getName() == null) {
+            relationship.setName(context.getNameGenerator().relationshipName(relationship));
+        }
 
         getEntity().addRelationship(relationship);
-
-        // TODO: add reverse relationship as well if it does not exist
-
         for (ObjEntity e : getEntity().mappedObjEntities()) {
             context.getEntityMergeSupport().synchronizeOnDbRelationshipAdded(e, relationship);
         }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/8718ee95/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMerger.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMerger.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMerger.java
index 8f0adb7..a1f7d56 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMerger.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMerger.java
@@ -250,8 +250,7 @@ public class DbMerger {
         for (DbRelationship detected : detectedEntity.getRelationships()) {
             if (findDbRelationship(dbEntity, detected) == null) {
 
-                // alter detected relationship to match entity and attribute
-                // names.
+                // alter detected relationship to match entity and attribute names.
                 // (case sensitively)
 
                 DbEntity targetEntity = findDbEntity(dbEntity.getDataMap().getDbEntities(),
@@ -275,16 +274,13 @@ public class DbMerger {
                     }
                 }
 
-                MergerToken token = tokenFactory.createDropRelationshipToDb(dbEntity, detected);
-                if (detected.isToMany()) {
-                    // default toModel as we can not do drop a toMany in the db.
-                    // only
-                    // toOne are represented using foreign key
-                    tokens.addAll(token.createReverse(tokenFactory));
-                } else {
+                // There is only one FK in the database so we create
+                // DropRelationshipToDb token only for direct relationships
+                // and skip token for toMany relationships
+                if (!detected.isToMany()) {
+                    MergerToken token = tokenFactory.createDropRelationshipToDb(dbEntity, detected);
                     tokens.add(token);
                 }
-                tokens.add(token);
             }
         }
 
@@ -301,10 +297,9 @@ public class DbMerger {
 
                 if (token.shouldGenerateFkConstraint()) {
                     // TODO I guess we should add relationship always; in order
-                    // to have ability
-                    // TODO generate reverse relationship. If it doesn't have
-                    // anything to execute it will be passed
-                    // TODO through execution without any affect on db
+                    // TODO to have ability generate reverse relationship.
+                    // TODO If it doesn't have anything to execute it will be
+                    // TODO passed through execution without any affect on db
                     tokens.add(token);
                 }
             }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/8718ee95/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java
index b037cca..c94236b 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java
@@ -61,7 +61,12 @@ public class DropRelationshipToDb extends AbstractToDbToken.Entity {
     public Collection<MergerToken> createReverse(MergerTokenFactory factory) {
         Collection<MergerToken> result = new ArrayList<>();
         result.add(factory.createAddRelationshipToModel(getEntity(), relationship));
-        result.add(factory.createAddRelationshipToModel(relationship.getTargetEntity(), relationship.createReverseRelationship()));
+        DbRelationship reverse = relationship.getReverseRelationship();
+        if(reverse == null) {
+            reverse = relationship.createReverseRelationship();
+            // NB name will be set in AddRelationshipToModel.execute() call
+            result.add(factory.createAddRelationshipToModel(relationship.getTargetEntity(), reverse));
+        }
         return result;
     }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/8718ee95/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModelIT.java
index 2271e25..41d6dbf 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModelIT.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModelIT.java
@@ -130,18 +130,20 @@ public class DropRelationshipToModelIT extends MergeCase {
         dbEntity1.removeRelationship(rel1To2.getName());
         dbEntity2.removeAttribute(e2col2.getName());
         List<MergerToken> tokens = createMergeTokens();
+
         /**
          * Add Relationship NEW_TABLE->NEW_TABLE2 To Model
          * Drop Relationship NEW_TABLE2->NEW_TABLE To DB
          * Drop Column NEW_TABLE2.FK To DB
          * */
-        assertTokens(tokens, 2, 1);
+        assertTokens(tokens, 2, 0);
         for (MergerToken token : tokens) {
             if (token.getDirection().isToDb()) {
                 execute(token);
             }
         }
         assertTokensAndExecute(0, 0);
+
         dbEntity2.addRelationship(rel2To1);
         dbEntity1.addRelationship(rel1To2);
         dbEntity2.addAttribute(e2col2);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/8718ee95/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergerFactoryIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergerFactoryIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergerFactoryIT.java
index 1fe7da7..1e92c14 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergerFactoryIT.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergerFactoryIT.java
@@ -221,9 +221,9 @@ public class MergerFactoryIT extends MergeCase {
         resolver.refreshMappingCache();
         /*
          * Db -Rel 'toArtistR1' - NEW_TABLE 1 -> 1 ARTIST"
-r2 =     * Db -Rel 'toNewTableR2' - ARTIST 1 -> * NEW_TABLE"
+r2 =     * Db -Rel 'toNewTableR2' - ARTIST 1 -> * NEW_TABLE" -- Not generated any more
          * */
-        assertTokensAndExecute(1, 1);
+        assertTokensAndExecute(1, 0);
         assertTokensAndExecute(0, 0);
 
         // clear up
@@ -281,10 +281,10 @@ r2 =     * Db -Rel 'toNewTableR2' - ARTIST 1 -> * NEW_TABLE"
         artistDbEntity.removeRelationship(r2.getName());
         resolver.refreshMappingCache();
         /*
-        * Add Relationship ARTIST->NEW_TABLE To Model
+        * Add Relationship ARTIST->NEW_TABLE To Model -- Not generated any more
         * Drop Relationship NEW_TABLE->ARTIST To DB
         * */
-        assertTokensAndExecute(1, 1);
+        assertTokensAndExecute(1, 0);
         assertTokensAndExecute(0, 0);
 
         // clear up

http://git-wip-us.apache.org/repos/asf/cayenne/blob/8718ee95/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReversTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReversTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReversTest.java
deleted file mode 100644
index 411b253..0000000
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReversTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*****************************************************************
- *   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.dbsync.merge;
-
-import org.apache.cayenne.dbsync.merge.factory.HSQLMergerTokenFactory;
-import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbJoin;
-import org.apache.cayenne.map.DbRelationship;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.Collection;
-import java.util.Collections;
-
-import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.dbAttr;
-import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.dbEntity;
-
-/**
- * @since 4.0.
- */
-public class TokensReversTest {
-
-    @Test
-    public void testReverses() {
-        DbAttribute attr = dbAttr().build();
-        DbEntity entity = dbEntity().attributes(attr).build();
-        DbRelationship rel = new DbRelationship("rel");
-        rel.setSourceEntity(entity);
-        rel.addJoin(new DbJoin(rel, attr.getName(), "dontKnow"));
-
-        test(factory().createAddColumnToDb(entity, attr));
-        test(factory().createAddColumnToModel(entity, attr));
-        test(factory().createDropColumnToDb(entity, attr));
-        test(factory().createDropColumnToModel(entity, attr));
-
-        test(factory().createAddRelationshipToDb(entity, rel));
-        test(factory().createAddRelationshipToModel(entity, rel));
-        test(factory().createDropRelationshipToDb(entity, rel));
-        test(factory().createDropRelationshipToModel(entity, rel));
-
-        test(factory().createCreateTableToDb(entity));
-        test(factory().createCreateTableToModel(entity));
-        test(factory().createDropTableToDb(entity));
-        test(factory().createDropTableToModel(entity));
-
-        test(factory().createSetAllowNullToDb(entity, attr));
-        test(factory().createSetAllowNullToModel(entity, attr));
-        test(factory().createSetNotNullToDb(entity, attr));
-        test(factory().createSetNotNullToModel(entity, attr));
-
-        DbAttribute attr2 = dbAttr().build();
-        test(factory().createSetColumnTypeToDb(entity, attr, attr2));
-        test(factory().createSetColumnTypeToModel(entity, attr, attr2));
-
-        test(factory().createSetPrimaryKeyToDb(entity, Collections.singleton(attr), Collections.singleton(attr2), "PK"));
-        test(factory().createSetPrimaryKeyToModel(entity, Collections.singleton(attr), Collections.singleton(attr2), "PK"));
-
-        test(factory().createSetValueForNullToDb(entity, attr, new DefaultValueForNullProvider()));
-    }
-
-    private void test(MergerToken token1) {
-        MergerToken token2 = token1.createReverse(factory()).iterator().next()
-                                    .createReverse(factory()).iterator().next();
-
-
-        Assert.assertEquals(token1.getTokenName(), token2.getTokenName());
-        Assert.assertEquals(token1.getTokenValue(), token2.getTokenValue());
-        Assert.assertEquals(token1.getDirection(), token2.getDirection());
-    }
-
-    private MergerTokenFactory factory() {
-        return new HSQLMergerTokenFactory();
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/8718ee95/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReverseTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReverseTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReverseTest.java
new file mode 100644
index 0000000..34cd7cb
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReverseTest.java
@@ -0,0 +1,108 @@
+/*****************************************************************
+ *   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.dbsync.merge;
+
+import org.apache.cayenne.dbsync.merge.factory.HSQLMergerTokenFactory;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.dbAttr;
+import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.dbEntity;
+
+/**
+ * @since 4.0.
+ */
+public class TokensReverseTest {
+
+    @Test
+    public void testReverses() {
+        DbAttribute attr = dbAttr().build();
+        DbEntity entity = dbEntity().attributes(attr).build();
+        DbRelationship rel = new DbRelationship("rel");
+        rel.setSourceEntity(entity);
+        rel.addJoin(new DbJoin(rel, attr.getName(), "dontKnow"));
+
+        testOneToOneReverse(factory().createAddColumnToDb(entity, attr));
+        testOneToOneReverse(factory().createAddColumnToModel(entity, attr));
+        testOneToOneReverse(factory().createDropColumnToDb(entity, attr));
+        testOneToOneReverse(factory().createDropColumnToModel(entity, attr));
+
+        testOneToOneReverse(factory().createAddRelationshipToDb(entity, rel));
+        testCreateAddRelationshipToModel(factory().createAddRelationshipToModel(entity, rel));
+        testCreateDropRelationshipToDb(factory().createDropRelationshipToDb(entity, rel));
+        testOneToOneReverse(factory().createDropRelationshipToModel(entity, rel));
+
+        testOneToOneReverse(factory().createCreateTableToDb(entity));
+        testOneToOneReverse(factory().createCreateTableToModel(entity));
+        testOneToOneReverse(factory().createDropTableToDb(entity));
+        testOneToOneReverse(factory().createDropTableToModel(entity));
+
+        testOneToOneReverse(factory().createSetAllowNullToDb(entity, attr));
+        testOneToOneReverse(factory().createSetAllowNullToModel(entity, attr));
+        testOneToOneReverse(factory().createSetNotNullToDb(entity, attr));
+        testOneToOneReverse(factory().createSetNotNullToModel(entity, attr));
+
+        DbAttribute attr2 = dbAttr().build();
+        testOneToOneReverse(factory().createSetColumnTypeToDb(entity, attr, attr2));
+        testOneToOneReverse(factory().createSetColumnTypeToModel(entity, attr, attr2));
+
+        testOneToOneReverse(factory().createSetPrimaryKeyToDb(entity, Collections.singleton(attr), Collections.singleton(attr2), "PK"));
+        testOneToOneReverse(factory().createSetPrimaryKeyToModel(entity, Collections.singleton(attr), Collections.singleton(attr2), "PK"));
+
+        testOneToOneReverse(factory().createSetValueForNullToDb(entity, attr, new DefaultValueForNullProvider()));
+    }
+
+    private void testReversTokenWithCount(MergerToken token, int countFirstReverse, int countSecondReverse) {
+        Collection<MergerToken> collectionReverse1 = token.createReverse(factory());
+        Assert.assertEquals(countFirstReverse, collectionReverse1.size());
+
+        Collection<MergerToken> collectionReverse2 = collectionReverse1.iterator().next().createReverse(factory());
+        Assert.assertEquals(countSecondReverse, collectionReverse2.size());
+
+        MergerToken token2 = collectionReverse2.iterator().next();
+
+        Assert.assertEquals(token.getTokenName(), token2.getTokenName());
+        Assert.assertEquals(token.getTokenValue(), token2.getTokenValue());
+        Assert.assertEquals(token.getDirection(), token2.getDirection());
+    }
+
+    private void testCreateAddRelationshipToModel(MergerToken token1) {
+        testReversTokenWithCount(token1, 1, 2);
+    }
+
+    private void testCreateDropRelationshipToDb(MergerToken token1) {
+        testReversTokenWithCount(token1, 2, 1);
+    }
+
+    private void testOneToOneReverse(MergerToken token1) {
+        testReversTokenWithCount(token1, 1, 1);
+    }
+
+    private MergerTokenFactory factory() {
+        return new HSQLMergerTokenFactory();
+    }
+}