You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2016/10/02 18:31:30 UTC

[1/3] cayenne git commit: CAY-2116 Split schema synchronization code in a separate module

Repository: cayenne
Updated Branches:
  refs/heads/master 827056e81 -> 38e4e7fda


http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ReverseEngineeringAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ReverseEngineeringAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ReverseEngineeringAction.java
index 08c0c1f..b531171 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ReverseEngineeringAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ReverseEngineeringAction.java
@@ -19,35 +19,33 @@
 
 package org.apache.cayenne.modeler.action;
 
-import java.awt.event.ActionEvent;
-
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.configuration.event.DataMapEvent;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.event.MapEvent;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.CayenneModelerController;
 import org.apache.cayenne.modeler.ProjectController;
 import org.apache.cayenne.modeler.util.CayenneAction;
 
+import java.awt.event.ActionEvent;
+
 /**
  * Action that imports database structure into a DataMap.
  */
 public class ReverseEngineeringAction extends CayenneAction {
 
-    public static String getActionName() {
-        return "Reengineer Database Schema";
-    }
-
     public ReverseEngineeringAction(Application application) {
         super(getActionName(), application);
     }
 
+    public static String getActionName() {
+        return "Reengineer Database Schema";
+    }
+
     /**
-     * Connects to DB and delegates processing to DbLoaderController, starting it
-     * asynchronously.
+     * Connects to DB and delegates processing to DbLoaderController, starting it asynchronously.
      */
     @Override
     public void performAction(ActionEvent event) {
@@ -55,8 +53,10 @@ public class ReverseEngineeringAction extends CayenneAction {
         DataMap dataMap = projectController.getCurrentDataMap();
         DataChannelDescriptor dataChannelDescriptor = projectController.getCurrentDataChanel();
         if (dataMap == null) {
-            dataMap = new DataMap(DuplicateNameResolver.resolve(NameCheckers.dataMap));
-            dataMap.setName(DuplicateNameResolver.resolve(NameCheckers.dataMap, projectController.getProject().getRootNode()));
+            dataMap = new DataMap();
+            dataMap.setName(NameBuilder
+                    .builder(dataMap, dataChannelDescriptor)
+                    .name());
             dataChannelDescriptor.getDataMaps().add(dataMap);
             getProjectController().fireDataMapEvent(new DataMapEvent(this, dataMap, MapEvent.ADD));
         }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/ResolveDbRelationshipDialog.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/ResolveDbRelationshipDialog.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/ResolveDbRelationshipDialog.java
index 9284881..885c4c2 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/ResolveDbRelationshipDialog.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/ResolveDbRelationshipDialog.java
@@ -19,35 +19,16 @@
 
 package org.apache.cayenne.modeler.dialog;
 
-import java.awt.BorderLayout;
-import java.awt.Dimension;
-import java.awt.FlowLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import javax.swing.JButton;
-import javax.swing.JComboBox;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTextField;
-import javax.swing.ListSelectionModel;
-import javax.swing.table.TableColumn;
-
+import com.jgoodies.forms.builder.PanelBuilder;
+import com.jgoodies.forms.layout.CellConstraints;
+import com.jgoodies.forms.layout.FormLayout;
 import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbJoin;
 import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.Entity;
-import org.apache.cayenne.map.Relationship;
 import org.apache.cayenne.map.event.MapEvent;
 import org.apache.cayenne.map.event.RelationshipEvent;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.pref.TableColumnPreferences;
 import org.apache.cayenne.modeler.undo.RelationshipUndoableEdit;
@@ -58,9 +39,15 @@ import org.apache.cayenne.modeler.util.PanelFactory;
 import org.apache.cayenne.modeler.util.combo.AutoCompletion;
 import org.apache.cayenne.util.Util;
 
-import com.jgoodies.forms.builder.PanelBuilder;
-import com.jgoodies.forms.layout.CellConstraints;
-import com.jgoodies.forms.layout.FormLayout;
+import javax.swing.*;
+import javax.swing.table.TableColumn;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * Editor of DbRelationship joins.
@@ -156,7 +143,7 @@ public class ResolveDbRelationshipDialog extends CayenneDialog {
         builder.add(buttons, cc.xywh(5, 9, 1, 3));
 
         getContentPane().add(builder.getPanel(), BorderLayout.CENTER);
-        getContentPane().add(PanelFactory.createButtonPanel(new JButton[] {
+        getContentPane().add(PanelFactory.createButtonPanel(new JButton[]{
                 saveButton, cancelButton
         }), BorderLayout.SOUTH);
     }
@@ -286,44 +273,19 @@ public class ResolveDbRelationshipDialog extends CayenneDialog {
         stopEditing();
 
         // extract names...
-        String sourceEntityName = name.getText();
-        if (sourceEntityName.length() == 0) {
-            sourceEntityName = null;
-        }
-
-        if (sourceEntityName == null) {
-            sourceEntityName = DuplicateNameResolver.resolve(NameCheckers.dbRelationship, relationship.getSourceEntity());
-        }
-
-        if (!validateName(relationship.getSourceEntity(), relationship, sourceEntityName)) {
-            return;
-        }
-
-        String targetEntityName = reverseName.getText().trim();
-        if (targetEntityName.length() == 0) {
-            targetEntityName = null;
-        }
-
-        if (targetEntityName == null) {
-            targetEntityName = DuplicateNameResolver.resolve(NameCheckers.dbRelationship, relationship.getTargetEntity());
-        }
+        String sourceEntityName = NameBuilder
+                .builder(relationship, relationship.getSourceEntity())
+                .baseName(name.getText().trim())
+                .name();
 
         // check if reverse name is valid
         DbJoinTableModel model = (DbJoinTableModel) table.getModel();
         boolean updatingReverse = model.getObjectList().size() > 0;
 
-        if (updatingReverse
-                && !validateName(
-                        relationship.getTargetEntity(),
-                        reverseRelationship,
-                        targetEntityName)) {
-            return;
-        }
-
         // handle name update
         if (!Util.nullSafeEquals(sourceEntityName, relationship.getName())) {
             String oldName = relationship.getName();
-            
+
             relationship.setName(sourceEntityName);
 
             undo.addNameUndo(relationship, oldName, sourceEntityName);
@@ -347,7 +309,12 @@ public class ResolveDbRelationshipDialog extends CayenneDialog {
 
             // If didn't find anything, create reverseDbRel
             if (reverseRelationship == null) {
-                reverseRelationship = new DbRelationship(targetEntityName);
+                reverseRelationship = new DbRelationship();
+                reverseRelationship.setName(NameBuilder
+                        .builder(reverseRelationship, relationship.getTargetEntity())
+                        .baseName(reverseName.getText().trim())
+                        .name());
+
                 reverseRelationship.setSourceEntity(relationship.getTargetEntity());
                 reverseRelationship.setTargetEntityName(relationship.getSourceEntity());
                 reverseRelationship.setToMany(!relationship.isToMany());
@@ -363,22 +330,26 @@ public class ResolveDbRelationshipDialog extends CayenneDialog {
                                     reverseRelationship.getSourceEntity(),
                                     MapEvent.ADD));
                 }
-            }
-            else if (!Util
-                    .nullSafeEquals(targetEntityName, reverseRelationship.getName())) {
+            } else {
 
-                String oldName = reverseRelationship.getName();
-                
-                reverseRelationship.setName(targetEntityName);
+                String targetEntityName = NameBuilder
+                        .builder(reverseRelationship, relationship.getTargetEntity())
+                        .baseName(reverseName.getText().trim())
+                        .name();
 
-                undo.addNameUndo(reverseRelationship, oldName, targetEntityName);
+                if (!Util.nullSafeEquals(targetEntityName, reverseRelationship.getName())) {
 
-                getMediator().fireDbRelationshipEvent(
-                        new RelationshipEvent(
-                                this,
-                                reverseRelationship,
-                                reverseRelationship.getSourceEntity(),
-                                oldName));
+                    String oldName = reverseRelationship.getName();
+                    reverseRelationship.setName(targetEntityName);
+                    undo.addNameUndo(reverseRelationship, oldName, targetEntityName);
+
+                    getMediator().fireDbRelationshipEvent(
+                            new RelationshipEvent(
+                                    this,
+                                    reverseRelationship,
+                                    reverseRelationship.getSourceEntity(),
+                                    oldName));
+                }
             }
 
             Collection reverseJoins = getReverseJoins();
@@ -398,20 +369,6 @@ public class ResolveDbRelationshipDialog extends CayenneDialog {
                                 .getSourceEntity()));
     }
 
-    private boolean validateName(Entity entity, Relationship aRelationship, String newName) {
-        Relationship existing = entity.getRelationship(newName);
-        if (existing != null && (aRelationship == null || aRelationship != existing)) {
-            JOptionPane.showMessageDialog(
-                    this,
-                    "There is an existing relationship named \""
-                            + newName
-                            + "\". Select a different name.");
-            return false;
-        }
-
-        return true;
-    }
-
     private Collection getReverseJoins() {
         Collection<DbJoin> joins = relationship.getJoins();
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbLoaderHelper.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbLoaderHelper.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbLoaderHelper.java
index acaafdf..7ee114c 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbLoaderHelper.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbLoaderHelper.java
@@ -20,13 +20,15 @@
 package org.apache.cayenne.modeler.dialog.db;
 
 import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dbimport.ReverseEngineering;
 import org.apache.cayenne.dbsync.CayenneDbSyncModule;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
+import org.apache.cayenne.dbsync.reverse.FiltersConfigBuilder;
 import org.apache.cayenne.dbsync.reverse.db.DbLoader;
 import org.apache.cayenne.dbsync.reverse.db.DefaultDbLoaderDelegate;
-import org.apache.cayenne.dbsync.reverse.FiltersConfigBuilder;
 import org.apache.cayenne.di.DIBootstrap;
 import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.map.DataMap;
@@ -35,8 +37,6 @@ import org.apache.cayenne.map.DbRelationship;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.event.EntityEvent;
 import org.apache.cayenne.map.event.MapEvent;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.ProjectController;
 import org.apache.cayenne.modeler.pref.DBConnectionInfo;
@@ -61,13 +61,11 @@ import java.util.List;
  */
 public class DbLoaderHelper {
 
-    private static Log logObj = LogFactory.getLog(DbLoaderHelper.class);
-
     // TODO: this is a temp hack... need to delegate to DbAdapter, or
     // configurable in
     // preferences...
     private static final Collection<String> EXCLUDED_TABLES = Arrays.asList("AUTO_PK_SUPPORT", "auto_pk_support");
-
+    private static Log logObj = LogFactory.getLog(DbLoaderHelper.class);
     protected boolean stoppingReverseEngineering;
     protected boolean existingMap;
 
@@ -116,14 +114,14 @@ public class DbLoaderHelper {
         }
     }
 
-    public void setStoppingReverseEngineering(boolean stopReverseEngineering) {
-        this.stoppingReverseEngineering = stopReverseEngineering;
-    }
-
     public boolean isStoppingReverseEngineering() {
         return stoppingReverseEngineering;
     }
 
+    public void setStoppingReverseEngineering(boolean stopReverseEngineering) {
+        this.stoppingReverseEngineering = stopReverseEngineering;
+    }
+
     public DataMap getDataMap() {
         return dataMap;
     }
@@ -172,6 +170,13 @@ public class DbLoaderHelper {
         });
     }
 
+    protected ProjectController getMediator() {
+        return mediator;
+    }
+
+    protected DbLoader getLoader() {
+        return loader;
+    }
 
     private final class LoaderDelegate extends DefaultDbLoaderDelegate {
 
@@ -319,7 +324,6 @@ public class DbLoaderHelper {
         }
     }
 
-
     public final class LoadDataMapTask extends DbLoaderTask {
 
         public LoadDataMapTask(JFrame frame, String title) {
@@ -335,8 +339,11 @@ public class DbLoaderHelper {
             DbLoaderHelper.this.existingMap = dataMap != null;
 
             if (!existingMap) {
-                dataMap = new DataMap(DuplicateNameResolver.resolve(NameCheckers.dataMap));
-                dataMap.setName(DuplicateNameResolver.resolve(NameCheckers.dataMap, mediator.getProject().getRootNode()));
+
+                ConfigurationNode root = mediator.getProject().getRootNode();
+
+                dataMap = new DataMap();
+                dataMap.setName(NameBuilder.builder(dataMap, root).name());
             }
 
             if (isCanceled()) {
@@ -351,7 +358,7 @@ public class DbLoaderHelper {
                     reverseEngineering.setConfigurationSource(dataMap.getReverseEngineering().getConfigurationSource());
                 }
             } else {
-                reverseEngineering.setName(DuplicateNameResolver.resolve(NameCheckers.reverseEngineering, dataChannelDescriptor));
+                reverseEngineering.setName(NameBuilder.builder(reverseEngineering, dataChannelDescriptor).name());
             }
 
             if (dataMap.getConfigurationSource() != null) {
@@ -377,12 +384,4 @@ public class DbLoaderHelper {
         }
     }
 
-    protected ProjectController getMediator() {
-        return mediator;
-    }
-
-    protected DbLoader getLoader() {
-        return loader;
-    }
-	
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/query/QueryType.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/query/QueryType.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/query/QueryType.java
index 8b0dd85..33bff77 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/query/QueryType.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/query/QueryType.java
@@ -18,24 +18,22 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.dialog.query;
 
-import java.awt.Component;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-
-import javax.swing.WindowConstants;
-
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.configuration.event.QueryEvent;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.QueryDescriptor;
 import org.apache.cayenne.map.event.MapEvent;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
 import org.apache.cayenne.modeler.ProjectController;
 import org.apache.cayenne.modeler.event.QueryDisplayEvent;
 import org.apache.cayenne.modeler.undo.CreateQueryUndoableEdit;
 import org.apache.cayenne.modeler.util.CayenneController;
 
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
 
 public class QueryType extends CayenneController{
 
@@ -119,11 +117,8 @@ public class QueryType extends CayenneController{
         String queryType = getSelectedQuery();
 
         // update query...
-        String queryName = DuplicateNameResolver.resolve(NameCheckers.query, dataMap);
-
         QueryDescriptor query = QueryDescriptor.descriptor(queryType);
-
-        query.setName(queryName);
+        query.setName(NameBuilder.builder(query, dataMap).name());
         query.setDataMap(dataMap);
         
         dataMap.addQueryDescriptor(query);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/modeler/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOModelProcessor.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOModelProcessor.java b/modeler/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOModelProcessor.java
index fac6202..f3d858d 100644
--- a/modeler/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOModelProcessor.java
+++ b/modeler/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOModelProcessor.java
@@ -20,8 +20,7 @@
 package org.apache.cayenne.wocompat;
 
 import org.apache.cayenne.dba.TypesMapping;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.exp.ExpressionException;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbEntity;
@@ -726,10 +725,10 @@ public class EOModelProcessor {
 
 			if (relationship.getReverseRelationship() == null) {
 				DbRelationship reverse = relationship.createReverseRelationship();
-
-				String name = DuplicateNameResolver.resolve(NameCheckers.dbRelationship,
-						reverse.getSourceEntity(), relationship.getName() + "Reverse");
-				reverse.setName(name);
+				reverse.setName(NameBuilder.builder(reverse, reverse.getSourceEntity())
+						// TODO: we can do better with ObjectNameGenerator
+						.baseName(relationship.getName() + "Reverse")
+						.name());
 				relationship.getTargetEntity().addRelationship(reverse);
 			}
 		}


[3/3] cayenne git commit: CAY-2116 Split schema synchronization code in a separate module

Posted by aa...@apache.org.
CAY-2116 Split schema synchronization code in a separate module

Refactoring: Sane name builder API


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

Branch: refs/heads/master
Commit: 38e4e7fda64c3793f3fd4fe6c0ca8dc29211e1f5
Parents: 827056e
Author: Andrus Adamchik <an...@objectstyle.com>
Authored: Sun Oct 2 16:04:12 2016 +0300
Committer: Andrus Adamchik <an...@objectstyle.com>
Committed: Sun Oct 2 21:27:04 2016 +0300

----------------------------------------------------------------------
 .../dbsync/merge/CreateTableToModel.java        |  22 +-
 .../dbsync/merge/DropRelationshipToDb.java      |   2 +-
 .../dbsync/merge/EntityMergeSupport.java        |  20 +-
 .../dbsync/naming/CallbackNameBuilder.java      |  74 +++++
 .../dbsync/naming/DeduplicationVisitor.java     | 277 +++++++++++++++++++
 .../dbsync/naming/DefaultBaseNameVisitor.java   | 122 ++++++++
 .../dbsync/naming/DuplicateNameResolver.java    |  68 -----
 .../cayenne/dbsync/naming/NameBuilder.java      |  84 ++++++
 .../cayenne/dbsync/naming/NameChecker.java      |  36 ---
 .../cayenne/dbsync/naming/NameCheckers.java     | 223 ---------------
 .../apache/cayenne/dbsync/naming/NameUtil.java  |  65 +++++
 .../dbsync/naming/NormalizationVisitor.java     | 123 ++++++++
 .../cayenne/dbsync/reverse/db/DbLoader.java     |  47 ++--
 .../reverse/db/DbRelationshipDetected.java      |  53 ++++
 .../reverse/db/ManyToManyCandidateEntity.java   |  11 +-
 .../cayenne/dbsync/naming/NameBuilderTest.java  | 272 ++++++++++++++++++
 .../cayenne/dbsync/naming/NameCheckersTest.java | 204 --------------
 .../apache/cayenne/map/CallbackDescriptor.java  |   2 +-
 .../cayenne/map/DbRelationshipDetected.java     |  48 ----
 .../modeler/action/CreateAttributeAction.java   | 106 +++----
 .../action/CreateCallbackMethodAction.java      |  47 ++--
 .../modeler/action/CreateDataMapAction.java     |  13 +-
 .../modeler/action/CreateDbEntityAction.java    | 116 ++++----
 .../modeler/action/CreateEmbeddableAction.java  |  13 +-
 .../modeler/action/CreateNodeAction.java        | 148 +++++-----
 .../modeler/action/CreateObjEntityAction.java   |  65 ++---
 .../modeler/action/CreateProcedureAction.java   |  89 +++---
 .../action/CreateProcedureParameterAction.java  | 102 +++----
 .../action/CreateRelationshipAction.java        | 217 ++++++++-------
 .../modeler/action/ImportDataMapAction.java     | 139 +++++-----
 .../modeler/action/ImportEOModelAction.java     |  38 +--
 .../modeler/action/NewProjectAction.java        |  27 +-
 .../cayenne/modeler/action/PasteAction.java     | 189 ++++++++-----
 .../action/ReverseEngineeringAction.java        |  24 +-
 .../dialog/ResolveDbRelationshipDialog.java     | 127 +++------
 .../modeler/dialog/db/DbLoaderHelper.java       |  43 ++-
 .../cayenne/modeler/dialog/query/QueryType.java |  19 +-
 .../cayenne/wocompat/EOModelProcessor.java      |  11 +-
 38 files changed, 1887 insertions(+), 1399 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/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 a8483b9..ba93d2c 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
@@ -19,8 +19,7 @@
 package org.apache.cayenne.dbsync.merge;
 
 import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.dbsync.reverse.naming.DefaultObjectNameGenerator;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbEntity;
@@ -62,26 +61,21 @@ public class CreateTableToModel extends AbstractToModelToken.Entity {
 
         // create a ObjEntity
 
-        // TODO: proper name generator must be injected
+        // TODO: name generator must be injected...
+        // TODO: should we use DbEntity name as a basis instead of generic name like "ObjEntity1"?
+        String baseName = new DefaultObjectNameGenerator().createObjEntityName(dbEntity);
 
-        String objEntityName = new DefaultObjectNameGenerator().createObjEntityName(dbEntity);
-        objEntityName = DuplicateNameResolver.resolve(NameCheckers.objEntity, dbEntity.getDataMap(), objEntityName);
+        ObjEntity objEntity = new ObjEntity();
 
-        // this loop will terminate even if no valid name is found
-        // to prevent loader from looping forever (though such case is very unlikely)
-        String baseName = objEntityName;
-        for (int i = 1; i < 1000 && map.getObjEntity(objEntityName) != null; i++) {
-            objEntityName = baseName + i;
-        }
-
-        ObjEntity objEntity = new ObjEntity(objEntityName);
+        String name = NameBuilder.builder(objEntity, dbEntity.getDataMap()).baseName(baseName).name();
+        objEntity.setName(name);
         objEntity.setDbEntity(getEntity());
 
         // try to find a class name for the ObjEntity
         String className = objEntityClassName;
         if (className == null) {
             // we should generate a className based on the objEntityName
-            className = map.getNameWithDefaultPackage(objEntityName);
+            className = map.getNameWithDefaultPackage(name);
         }
 
         objEntity.setClassName(className);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/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 3c7dd82..1579b25 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
@@ -23,7 +23,7 @@ import org.apache.cayenne.dba.QuotingStrategy;
 import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.DbRelationshipDetected;
+import org.apache.cayenne.dbsync.reverse.db.DbRelationshipDetected;
 
 import java.util.Collections;
 import java.util.List;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EntityMergeSupport.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EntityMergeSupport.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EntityMergeSupport.java
index c7fc8de..e3692b0 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EntityMergeSupport.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EntityMergeSupport.java
@@ -20,8 +20,7 @@
 package org.apache.cayenne.dbsync.merge;
 
 import org.apache.cayenne.dba.TypesMapping;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.dbsync.reverse.naming.ObjectNameGenerator;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbAttribute;
@@ -199,10 +198,11 @@ public class EntityMergeSupport {
     }
 
     private boolean createObjRelationship(ObjEntity entity, DbRelationship dr, String targetEntityName) {
-        String relationshipName = nameGenerator.createObjRelationshipName(dr);
-        relationshipName = DuplicateNameResolver.resolve(NameCheckers.objRelationship, entity, relationshipName);
+        ObjRelationship or = new ObjRelationship();
+        or.setName(NameBuilder.builder(or, entity)
+                .baseName(nameGenerator.createObjRelationshipName(dr))
+                .name());
 
-        ObjRelationship or = new ObjRelationship(relationshipName);
         or.addDbRelationship(dr);
         Map<String, ObjEntity> objEntities = entity.getDataMap().getSubclassesForObjEntity(entity);
 
@@ -274,8 +274,11 @@ public class EntityMergeSupport {
     }
 
     private void addMissingAttribute(ObjEntity entity, DbAttribute da) {
-        String attrName = DuplicateNameResolver.resolve(NameCheckers.objAttribute, entity,
-                nameGenerator.createObjAttributeName(da));
+        ObjAttribute oa = new ObjAttribute();
+        oa.setName(NameBuilder.builder(oa, entity)
+                .baseName(nameGenerator.createObjAttributeName(da))
+                .name());
+        oa.setEntity(entity);
 
         String type = TypesMapping.getJavaBySqlType(da.getType());
         if (usePrimitives) {
@@ -284,8 +287,7 @@ public class EntityMergeSupport {
                 type = primitive;
             }
         }
-
-        ObjAttribute oa = new ObjAttribute(attrName, type, entity);
+        oa.setType(type);
         oa.setDbAttributePath(da.getName());
         entity.addAttribute(oa);
         fireAttributeAdded(oa);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/CallbackNameBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/CallbackNameBuilder.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/CallbackNameBuilder.java
new file mode 100644
index 0000000..655841c
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/CallbackNameBuilder.java
@@ -0,0 +1,74 @@
+/*
+ *    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.naming;
+
+import org.apache.cayenne.configuration.ConfigurationNode;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.map.ObjEntity;
+
+/**
+ * @since 4.0
+ */
+// TODO: fold CallbackMethod to org.apache.cayenne.map package and make it a ConfigurationNode
+// then we can get rid off this fork...
+class CallbackNameBuilder extends NameBuilder {
+
+    public CallbackNameBuilder() {
+        super(new CallbackNode());
+    }
+
+    @Override
+    public String name() {
+        String baseName = this.baseName != null
+                ? this.baseName
+                : "onEvent";
+
+        return new DeduplicationVisitor(namingContext, baseName, dupesPattern).resolve(new DeduplicationVisitor.Predicate() {
+            @Override
+            public boolean isNameInUse(String name) {
+
+                ObjEntity entity = (ObjEntity) namingContext;
+
+                if (entity.getCallbackMethods().contains(name)) {
+                    return true;
+                }
+
+                if (name.startsWith("get")) {
+                    String conflictingProperty = NameUtil.uncapitalize(name.substring(3));
+
+                    // check if either attribute or relationship name matches...
+                    if (entity.getAttribute(conflictingProperty) != null
+                            || entity.getRelationship(conflictingProperty) != null) {
+                        return true;
+                    }
+                }
+
+                return false;
+            }
+        });
+    }
+
+    static class CallbackNode implements ConfigurationNode {
+
+        @Override
+        public <T> T acceptVisitor(ConfigurationNodeVisitor<T> visitor) {
+            return null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/DeduplicationVisitor.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/DeduplicationVisitor.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/DeduplicationVisitor.java
new file mode 100644
index 0000000..f809fd3
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/DeduplicationVisitor.java
@@ -0,0 +1,277 @@
+/*
+ *    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.naming;
+
+import org.apache.cayenne.configuration.ConfigurationNode;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.dbimport.ReverseEngineering;
+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.Embeddable;
+import org.apache.cayenne.map.EmbeddableAttribute;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.map.ProcedureParameter;
+import org.apache.cayenne.map.QueryDescriptor;
+
+import java.util.Objects;
+
+/**
+ * @since 4.0
+ */
+// TODO: swap inner classes for lambdas when we are on java 8
+class DeduplicationVisitor implements ConfigurationNodeVisitor<String> {
+
+    private ConfigurationNode namingContext;
+    private String baseName;
+    private String dupesPattern;
+
+    DeduplicationVisitor(ConfigurationNode context, String baseName, String dupesPattern) {
+        this.namingContext = context;
+        this.baseName = Objects.requireNonNull(baseName);
+        this.dupesPattern = Objects.requireNonNull(dupesPattern);
+    }
+
+    @Override
+    public String visitDataChannelDescriptor(DataChannelDescriptor channelDescriptor) {
+        // DataChannelDescriptor is top-level. No context or naming conflicts are expected...
+        return baseName;
+    }
+
+    @Override
+    public String visitDataNodeDescriptor(DataNodeDescriptor nodeDescriptor) {
+        return resolve(new Predicate() {
+            @Override
+            public boolean isNameInUse(String name) {
+
+                DataChannelDescriptor dataChannelDescriptor = (DataChannelDescriptor) namingContext;
+                for (DataNodeDescriptor dataNodeDescriptor : dataChannelDescriptor.getNodeDescriptors()) {
+                    if (dataNodeDescriptor.getName().equals(name)) {
+                        return true;
+                    }
+                }
+
+                return false;
+            }
+        });
+    }
+
+    @Override
+    public String visitDataMap(DataMap dataMap) {
+        return resolve(new Predicate() {
+            @Override
+            public boolean isNameInUse(String name) {
+
+                // null context is a situation when DataMap is a
+                // top level object of the project
+                if (namingContext == null) {
+                    return false;
+                }
+
+                if (namingContext instanceof DataChannelDescriptor) {
+                    DataChannelDescriptor domain = (DataChannelDescriptor) namingContext;
+                    return domain.getDataMap(name) != null;
+                }
+                return false;
+            }
+        });
+    }
+
+    @Override
+    public String visitObjEntity(ObjEntity entity) {
+        return resolve(new Predicate() {
+            @Override
+            public boolean isNameInUse(String name) {
+                DataMap map = (DataMap) namingContext;
+                return map.getObjEntity(name) != null;
+            }
+        });
+    }
+
+    @Override
+    public String visitDbEntity(DbEntity entity) {
+        return resolve(new Predicate() {
+            @Override
+            public boolean isNameInUse(String name) {
+                DataMap map = (DataMap) namingContext;
+                return map.getDbEntity(name) != null;
+            }
+        });
+    }
+
+    @Override
+    public String visitEmbeddable(Embeddable embeddable) {
+        return resolve(new Predicate() {
+            @Override
+            public boolean isNameInUse(String name) {
+                DataMap map = (DataMap) namingContext;
+                return map.getEmbeddable(map.getNameWithDefaultPackage(name)) != null;
+            }
+        });
+    }
+
+    @Override
+    public String visitEmbeddableAttribute(EmbeddableAttribute attribute) {
+        return resolve(new Predicate() {
+            @Override
+            public boolean isNameInUse(String name) {
+                Embeddable emb = (Embeddable) namingContext;
+                return emb.getAttribute(name) != null;
+            }
+        });
+    }
+
+    @Override
+    public String visitObjAttribute(ObjAttribute attribute) {
+        return resolveObjEntityProperty();
+    }
+
+    @Override
+    public String visitDbAttribute(DbAttribute attribute) {
+        return resolveDbEntityProperty();
+    }
+
+    @Override
+    public String visitObjRelationship(ObjRelationship relationship) {
+        return resolveObjEntityProperty();
+    }
+
+    @Override
+    public String visitDbRelationship(DbRelationship relationship) {
+        return resolveDbEntityProperty();
+    }
+
+    @Override
+    public String visitProcedure(Procedure procedure) {
+        return resolve(new Predicate() {
+            @Override
+            public boolean isNameInUse(String name) {
+                DataMap map = (DataMap) namingContext;
+                return map.getProcedure(name) != null;
+            }
+        });
+    }
+
+    @Override
+    public String visitProcedureParameter(ProcedureParameter parameter) {
+        return resolve(new Predicate() {
+            @Override
+            public boolean isNameInUse(String name) {
+
+                // it doesn't matter if we create a parameter with a duplicate name.. parameters are positional anyway..
+                // still try to use unique names for visual consistency
+
+                Procedure procedure = (Procedure) namingContext;
+                for (ProcedureParameter parameter : procedure.getCallParameters()) {
+                    if (name.equals(parameter.getName())) {
+                        return true;
+                    }
+                }
+
+                return false;
+            }
+        });
+    }
+
+    @Override
+    public String visitQuery(QueryDescriptor query) {
+        return resolve(new Predicate() {
+            @Override
+            public boolean isNameInUse(String name) {
+                DataMap map = (DataMap) namingContext;
+                return map.getQueryDescriptor(name) != null;
+            }
+        });
+    }
+
+    @Override
+    public String visitReverseEngineering(ReverseEngineering reverseEngineering) {
+        return resolve(new Predicate() {
+            @Override
+            public boolean isNameInUse(String name) {
+
+                if (namingContext == null) {
+                    return false;
+                }
+
+                DataChannelDescriptor dataChannelDescriptor = (DataChannelDescriptor) namingContext;
+                for (DataMap dataMap : dataChannelDescriptor.getDataMaps()) {
+                    if (dataMap != null && dataMap.getReverseEngineering() != null &&
+                            dataMap.getReverseEngineering().getName() != null
+                            && dataMap.getReverseEngineering().getName().equals(name)) {
+                        return true;
+                    }
+                }
+                return false;
+            }
+        });
+    }
+
+    String resolve(Predicate nameChecker) {
+        int c = 1;
+        String name = baseName;
+        while (nameChecker.isNameInUse(name)) {
+            name = String.format(dupesPattern, baseName, c++);
+        }
+
+        return name;
+    }
+
+    private String resolveDbEntityProperty() {
+        return resolve(new Predicate() {
+            @Override
+            public boolean isNameInUse(String name) {
+
+                DbEntity entity = (DbEntity) namingContext;
+
+                // check if either attribute or relationship name matches...
+                return entity.getAttribute(name) != null || entity.getRelationship(name) != null;
+            }
+        });
+    }
+
+    private String resolveObjEntityProperty() {
+        return resolve(new Predicate() {
+            @Override
+            public boolean isNameInUse(String name) {
+
+                ObjEntity entity = (ObjEntity) namingContext;
+
+                // check if either attribute or relationship name matches...
+                if (entity.getAttribute(name) != null || entity.getRelationship(name) != null) {
+                    return true;
+                }
+
+                //  check if there's a callback method that shadows attribute getter (unlikely, but still)
+                String conflictingCallback = "get" + NameUtil.capitalize(name);
+                return entity.getCallbackMethods().contains(conflictingCallback);
+            }
+        });
+    }
+
+    interface Predicate {
+        boolean isNameInUse(String name);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/DefaultBaseNameVisitor.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/DefaultBaseNameVisitor.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/DefaultBaseNameVisitor.java
new file mode 100644
index 0000000..ecc17f0
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/DefaultBaseNameVisitor.java
@@ -0,0 +1,122 @@
+/*
+ *    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.naming;
+
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.dbimport.ReverseEngineering;
+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.Embeddable;
+import org.apache.cayenne.map.EmbeddableAttribute;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.map.ProcedureParameter;
+import org.apache.cayenne.map.QueryDescriptor;
+
+/**
+ * @since 4.0
+ */
+class DefaultBaseNameVisitor implements ConfigurationNodeVisitor<String> {
+
+    static final DefaultBaseNameVisitor INSTANCE = new DefaultBaseNameVisitor();
+
+    private DefaultBaseNameVisitor() {
+    }
+
+    @Override
+    public String visitDataChannelDescriptor(DataChannelDescriptor channelDescriptor) {
+        return "project";
+    }
+
+    @Override
+    public String visitDataNodeDescriptor(DataNodeDescriptor nodeDescriptor) {
+        return "datanode";
+    }
+
+    @Override
+    public String visitDataMap(DataMap dataMap) {
+        return "datamap";
+    }
+
+    @Override
+    public String visitObjEntity(ObjEntity entity) {
+        return "ObjEntity";
+    }
+
+    @Override
+    public String visitDbEntity(DbEntity entity) {
+        return "db_entity";
+    }
+
+    @Override
+    public String visitEmbeddable(Embeddable embeddable) {
+        return "Embeddable";
+    }
+
+    @Override
+    public String visitEmbeddableAttribute(EmbeddableAttribute attribute) {
+        return "untitledAttr";
+    }
+
+    @Override
+    public String visitObjAttribute(ObjAttribute attribute) {
+        return "untitledAttr";
+    }
+
+    @Override
+    public String visitDbAttribute(DbAttribute attribute) {
+        return "untitledAttr";
+    }
+
+    @Override
+    public String visitObjRelationship(ObjRelationship relationship) {
+        return "untitledRel";
+    }
+
+    @Override
+    public String visitDbRelationship(DbRelationship relationship) {
+        return "untitledRel";
+    }
+
+    @Override
+    public String visitProcedure(Procedure procedure) {
+        return "procedure";
+    }
+
+    @Override
+    public String visitProcedureParameter(ProcedureParameter parameter) {
+        return "UntitledProcedureParameter";
+    }
+
+    @Override
+    public String visitQuery(QueryDescriptor query) {
+        return "query";
+    }
+
+    @Override
+    public String visitReverseEngineering(ReverseEngineering reverseEngineering) {
+        return "reverseEngineering";
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/DuplicateNameResolver.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/DuplicateNameResolver.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/DuplicateNameResolver.java
deleted file mode 100644
index 3f55d8f..0000000
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/DuplicateNameResolver.java
+++ /dev/null
@@ -1,68 +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.naming;
-
-import org.apache.cayenne.map.DataMap;
-
-/**
- * A generator of unique names for the various model objects.
- *
- * @since 4.0
- */
-public class DuplicateNameResolver {
-
-    private static final String DEFAULT_PATTERN = "%s%d";
-
-    public static String resolve(NameChecker checker) {
-        return resolve(checker, DEFAULT_PATTERN, null, null);
-    }
-
-    public static String resolve(NameChecker checker, Object context) {
-        return resolve(checker, DEFAULT_PATTERN, context, null);
-    }
-
-    public static String resolve(NameChecker checker, Object context, String baseName) {
-        return resolve(checker, DEFAULT_PATTERN, context, baseName);
-    }
-
-    public static String resolve(NameChecker nameChecker, String pattern, Object context, String baseName) {
-
-        if (baseName == null) {
-            baseName = nameChecker.baseName();
-        }
-
-        String resolved = doResolve(nameChecker, pattern, context, baseName);
-
-        // TODO ugly hack with cast... something more OO is in order
-        return (nameChecker == NameCheckers.embeddable)
-                ? ((DataMap) context).getNameWithDefaultPackage(resolved) : resolved;
-    }
-
-
-    private static String doResolve(NameChecker nameChecker, String pattern, Object namingContext, String baseName) {
-        int c = 1;
-        String name = baseName;
-        while (nameChecker.isNameInUse(namingContext, name)) {
-            name = String.format(pattern, baseName, c++);
-        }
-
-        return name;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/NameBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/NameBuilder.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/NameBuilder.java
new file mode 100644
index 0000000..c791cbc
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/NameBuilder.java
@@ -0,0 +1,84 @@
+/*
+ *    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.naming;
+
+import org.apache.cayenne.configuration.ConfigurationNode;
+import org.apache.cayenne.map.ObjEntity;
+
+import java.util.Objects;
+
+/**
+ * A
+ *
+ * @since 4.0
+ */
+public class NameBuilder {
+
+    protected ConfigurationNode nodeToName;
+    protected ConfigurationNode namingContext;
+    protected String dupesPattern;
+    protected String baseName;
+
+    protected NameBuilder(ConfigurationNode nodeToName) {
+        this.nodeToName = Objects.requireNonNull(nodeToName);
+        this.dupesPattern = "%s%d";
+    }
+
+    public static NameBuilder builder(ConfigurationNode node) {
+        return new NameBuilder(node);
+    }
+
+    public static NameBuilder builder(ConfigurationNode node, ConfigurationNode namingContext) {
+        return new NameBuilder(node).in(namingContext);
+    }
+
+    /**
+     * A special builder starter for callback methods. Eventually callback methods will be made into ConfigurationNodes,
+     * and we can use regular {@link #builder(ConfigurationNode)} methods to name them.
+     */
+    // TODO: fold CallbackMethod to org.apache.cayenne.map package and make it a ConfigurationNode
+    // then we can use normal API for it... for now have to keep a special one-off method...
+    public static NameBuilder builderForCallbackMethod(ObjEntity namingContext) {
+        return new CallbackNameBuilder().in(namingContext);
+    }
+
+    public NameBuilder in(ConfigurationNode namingContext) {
+        this.namingContext = Objects.requireNonNull(namingContext);
+        return this;
+    }
+
+    public NameBuilder dupesPattern(String dupesPattern) {
+        this.dupesPattern = Objects.requireNonNull(dupesPattern);
+        return this;
+    }
+
+    public NameBuilder baseName(String baseName) {
+        this.baseName = baseName;
+        return this;
+    }
+
+    public String name() {
+        String baseName = this.baseName != null && this.baseName.length() > 0
+                ? this.baseName
+                : nodeToName.acceptVisitor(DefaultBaseNameVisitor.INSTANCE);
+
+        String normalizedBaseName = nodeToName.acceptVisitor(new NormalizationVisitor(baseName));
+        return nodeToName.acceptVisitor(new DeduplicationVisitor(namingContext, normalizedBaseName, dupesPattern));
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/NameChecker.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/NameChecker.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/NameChecker.java
deleted file mode 100644
index ade1ec5..0000000
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/NameChecker.java
+++ /dev/null
@@ -1,36 +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.naming;
-
-/**
- * @since 4.0
- */
-public interface NameChecker {
-
-	/**
-	 * Returns a base default name, like "UntitledEntity", etc.
-	 */
-	String baseName();
-
-	/**
-	 * Checks if the name is already taken by another sibling in the same
-	 * context.
-	 */
-	boolean isNameInUse(Object namingContext, String name);
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/NameCheckers.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/NameCheckers.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/NameCheckers.java
deleted file mode 100644
index fca1734..0000000
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/NameCheckers.java
+++ /dev/null
@@ -1,223 +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.naming;
-
-import org.apache.cayenne.access.DataDomain;
-import org.apache.cayenne.configuration.DataChannelDescriptor;
-import org.apache.cayenne.configuration.DataNodeDescriptor;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.Embeddable;
-import org.apache.cayenne.map.Entity;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.map.Procedure;
-import org.apache.cayenne.map.ProcedureParameter;
-import org.apache.commons.lang.StringUtils;
-
-/**
- * A set of default {@link NameChecker} objects for the known model objects.
- *
- * @since 4.0
- */
-public enum NameCheckers implements NameChecker {
-
-    dataChannelDescriptor("project") {
-        @Override
-        public boolean isNameInUse(Object namingContext, String name) {
-            return false;
-        }
-    },
-
-    dataMap("datamap") {
-        @Override
-        public boolean isNameInUse(Object namingContext, String name) {
-            // null context is a situation when DataMap is a
-            // top level object of the project
-            if (namingContext == null) {
-                return false;
-            }
-
-            if (namingContext instanceof DataDomain) {
-                DataDomain domain = (DataDomain) namingContext;
-                return domain.getDataMap(name) != null;
-            }
-
-            if (namingContext instanceof DataChannelDescriptor) {
-                DataChannelDescriptor domain = (DataChannelDescriptor) namingContext;
-                return domain.getDataMap(name) != null;
-            }
-            return false;
-        }
-    },
-
-    reverseEngineering("reverseEngineering") {
-        @Override
-        public boolean isNameInUse(Object namingContext, String name) {
-            if (namingContext == null) {
-                return false;
-            }
-
-            for (DataMap dataMap : ((DataChannelDescriptor) namingContext).getDataMaps()) {
-                if (dataMap != null && dataMap.getReverseEngineering() != null &&
-                        dataMap.getReverseEngineering().getName() != null && dataMap.getReverseEngineering().getName().equals(name)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-    },
-
-    objEntity("ObjEntity") {
-        @Override
-        public boolean isNameInUse(Object namingContext, String name) {
-            DataMap map = (DataMap) namingContext;
-            return map.getObjEntity(name) != null;
-        }
-    },
-
-    embeddable("Embeddable") {
-        @Override
-        public boolean isNameInUse(Object namingContext, String name) {
-            DataMap map = (DataMap) namingContext;
-            return map.getEmbeddable(map.getNameWithDefaultPackage(name)) != null;
-        }
-    },
-
-    embeddableAttribute("untitledAttr") {
-        @Override
-        public boolean isNameInUse(Object namingContext, String name) {
-            Embeddable emb = (Embeddable) namingContext;
-            return emb.getAttribute(name) != null;
-        }
-    },
-
-    dbEntity("db_entity") {
-        @Override
-        public boolean isNameInUse(Object namingContext, String name) {
-            DataMap map = (DataMap) namingContext;
-            return map.getDbEntity(name) != null;
-        }
-    },
-
-    procedureParameter("UntitledProcedureParameter") {
-        @Override
-        public boolean isNameInUse(Object namingContext, String name) {
-
-            // it doesn't matter if we create a parameter with
-            // a duplicate name.. parameters are positional anyway..
-            // still try to use unique names for visual consistency
-            Procedure procedure = (Procedure) namingContext;
-            for (final ProcedureParameter parameter : procedure
-                    .getCallParameters()) {
-                if (name.equals(parameter.getName())) {
-                    return true;
-                }
-            }
-
-            return false;
-        }
-    },
-
-    procedure("procedure") {
-        @Override
-        public boolean isNameInUse(Object namingContext, String name) {
-            DataMap map = (DataMap) namingContext;
-            return map.getProcedure(name) != null;
-        }
-    },
-
-    query("query") {
-        @Override
-        public boolean isNameInUse(Object namingContext, String name) {
-            DataMap map = (DataMap) namingContext;
-            return map.getQueryDescriptor(name) != null;
-        }
-    },
-
-    objAttribute("untitledAttr") {
-        @Override
-        public boolean isNameInUse(Object namingContext, String name) {
-            return objRelationship.isNameInUse(namingContext, name);
-        }
-    },
-
-    dbAttribute("untitledAttr") {
-        @Override
-        public boolean isNameInUse(Object namingContext, String name) {
-            Entity ent = (Entity) namingContext;
-            return ent.getAttribute(name) != null
-                    || ent.getRelationship(name) != null;
-        }
-    },
-
-    dataNodeDescriptor("datanode") {
-        @Override
-        public boolean isNameInUse(Object namingContext, String name) {
-            DataChannelDescriptor domain = (DataChannelDescriptor) namingContext;
-            for (DataNodeDescriptor dataNodeDescriptor : domain
-                    .getNodeDescriptors()) {
-                if (dataNodeDescriptor.getName().equals(name)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-    },
-
-    objRelationship("untitledRel") {
-        @Override
-        public boolean isNameInUse(Object namingContext, String name) {
-            ObjEntity ent = (ObjEntity) namingContext;
-            return dbAttribute.isNameInUse(namingContext, name)
-                    || ent.getCallbackMethods().contains(
-                    "get" + StringUtils.capitalize(name));
-        }
-    },
-
-    dbRelationship("untitledRel") {
-        @Override
-        public boolean isNameInUse(Object namingContext, String name) {
-            return dbAttribute.isNameInUse(namingContext, name);
-        }
-    },
-
-    objCallbackMethod("ObjCallbackMethod") {
-        @Override
-        public boolean isNameInUse(Object namingContext, String name) {
-            ObjEntity ent = (ObjEntity) namingContext;
-
-            return name.startsWith("get")
-                    && dbAttribute.isNameInUse(namingContext,
-                    StringUtils.uncapitalize(name.substring(3)))
-                    || ent.getCallbackMethods().contains(name);
-        }
-    };
-
-    private final String baseName;
-
-    NameCheckers(String baseName) {
-        this.baseName = baseName;
-    }
-
-    @Override
-    public String baseName() {
-        return baseName;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/NameUtil.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/NameUtil.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/NameUtil.java
new file mode 100644
index 0000000..fb47bcb
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/NameUtil.java
@@ -0,0 +1,65 @@
+/*
+ *    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.naming;
+
+/**
+ * @since 4.0
+ */
+final class NameUtil {
+    static String uncapitalize(String string) {
+        int len;
+        if (string == null || (len = string.length()) == 0) {
+            return string;
+        }
+
+        final char firstChar = string.charAt(0);
+        final char newChar = Character.toLowerCase(firstChar);
+        if (firstChar == newChar) {
+            // already capitalized
+            return string;
+        }
+
+        char[] newChars = new char[len];
+        newChars[0] = newChar;
+        string.getChars(1, len, newChars, 1);
+
+        return String.valueOf(newChars);
+    }
+
+    static String capitalize(String string) {
+        int len;
+        if (string == null || (len = string.length()) == 0) {
+            return string;
+        }
+
+        final char firstChar = string.charAt(0);
+        final char newChar = Character.toTitleCase(firstChar);
+        if (firstChar == newChar) {
+            // already capitalized
+            return string;
+        }
+
+        char[] newChars = new char[len];
+        newChars[0] = newChar;
+        string.getChars(1, len, newChars, 1);
+
+        return String.valueOf(newChars);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/NormalizationVisitor.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/NormalizationVisitor.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/NormalizationVisitor.java
new file mode 100644
index 0000000..75d941d
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/NormalizationVisitor.java
@@ -0,0 +1,123 @@
+/*
+ *    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.naming;
+
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.dbimport.ReverseEngineering;
+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.Embeddable;
+import org.apache.cayenne.map.EmbeddableAttribute;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.map.ProcedureParameter;
+import org.apache.cayenne.map.QueryDescriptor;
+
+/**
+ * @since 4.0
+ */
+class NormalizationVisitor implements ConfigurationNodeVisitor<String> {
+
+    private String baseName;
+
+    public NormalizationVisitor(String baseName) {
+        this.baseName = baseName;
+    }
+
+    @Override
+    public String visitDataChannelDescriptor(DataChannelDescriptor channelDescriptor) {
+        return baseName;
+    }
+
+    @Override
+    public String visitDataNodeDescriptor(DataNodeDescriptor nodeDescriptor) {
+        return baseName;
+    }
+
+    @Override
+    public String visitDataMap(DataMap dataMap) {
+        return baseName;
+    }
+
+    @Override
+    public String visitObjEntity(ObjEntity entity) {
+        return NameUtil.capitalize(baseName);
+    }
+
+    @Override
+    public String visitDbEntity(DbEntity entity) {
+        return baseName;
+    }
+
+    @Override
+    public String visitEmbeddable(Embeddable embeddable) {
+        return NameUtil.capitalize(baseName);
+    }
+
+    @Override
+    public String visitEmbeddableAttribute(EmbeddableAttribute attribute) {
+        return NameUtil.uncapitalize(baseName);
+    }
+
+    @Override
+    public String visitObjAttribute(ObjAttribute attribute) {
+        return NameUtil.uncapitalize(baseName);
+    }
+
+    @Override
+    public String visitDbAttribute(DbAttribute attribute) {
+        return baseName;
+    }
+
+    @Override
+    public String visitObjRelationship(ObjRelationship relationship) {
+        return NameUtil.uncapitalize(baseName);
+    }
+
+    @Override
+    public String visitDbRelationship(DbRelationship relationship) {
+        return NameUtil.uncapitalize(baseName);
+    }
+
+    @Override
+    public String visitProcedure(Procedure procedure) {
+        return baseName;
+    }
+
+    @Override
+    public String visitProcedureParameter(ProcedureParameter parameter) {
+        return baseName;
+    }
+
+    @Override
+    public String visitQuery(QueryDescriptor query) {
+        return baseName;
+    }
+
+    @Override
+    public String visitReverseEngineering(ReverseEngineering reverseEngineering) {
+        return baseName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/DbLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/DbLoader.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/DbLoader.java
index 44b9fb3..ecdfa70 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/DbLoader.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/DbLoader.java
@@ -21,23 +21,21 @@ package org.apache.cayenne.dbsync.reverse.db;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.TypesMapping;
 import org.apache.cayenne.dbsync.merge.EntityMergeSupport;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.dbsync.reverse.filters.CatalogFilter;
 import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig;
 import org.apache.cayenne.dbsync.reverse.filters.SchemaFilter;
 import org.apache.cayenne.dbsync.reverse.filters.TableFilter;
+import org.apache.cayenne.dbsync.reverse.naming.LegacyObjectNameGenerator;
+import org.apache.cayenne.dbsync.reverse.naming.ObjectNameGenerator;
 import org.apache.cayenne.map.DataMap;
 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.apache.cayenne.map.DbRelationshipDetected;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.Procedure;
 import org.apache.cayenne.map.ProcedureParameter;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.reverse.naming.LegacyObjectNameGenerator;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
-import org.apache.cayenne.dbsync.reverse.naming.ObjectNameGenerator;
 import org.apache.cayenne.util.EqualsBuilder;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -133,10 +131,12 @@ public class DbLoader {
                 continue;
             }
 
-            String objEntityName = DuplicateNameResolver.resolve(NameCheckers.objEntity, map,
-                    nameGenerator.createObjEntityName(dbEntity));
+            ObjEntity objEntity = new ObjEntity();
+            objEntity.setName(NameBuilder
+                    .builder(objEntity, map)
+                    .baseName(nameGenerator.createObjEntityName(dbEntity))
+                    .name());
 
-            ObjEntity objEntity = new ObjEntity(objEntityName);
             objEntity.setDbEntity(dbEntity);
             objEntity.setClassName(config.getGenericClassName() != null ? config.getGenericClassName() : map
                     .getNameWithDefaultPackage(objEntity.getName()));
@@ -315,13 +315,26 @@ public class DbLoader {
             }
 
             // forwardRelationship is a reference from table with primary key
-            DbRelationship forwardRelationship = new DbRelationship(generateName(pkEntity, key, true));
+            DbRelationship forwardRelationship = new DbRelationship();
+            forwardRelationship.setName(NameBuilder
+                    .builder(forwardRelationship, pkEntity)
+                    .baseName(nameGenerator.createDbRelationshipName(key, true))
+                    .name());
+
             forwardRelationship.setSourceEntity(pkEntity);
             forwardRelationship.setTargetEntityName(fkEntity);
 
             // forwardRelationship is a reference from table with foreign key,
             // it is what exactly we load from db
-            DbRelationshipDetected reverseRelationship = new DbRelationshipDetected(generateName(fkEntity, key, false));
+
+            // TODO: dirty and non-transparent... using DbRelationshipDetected for the benefit of the merge package.
+            // This info is available from joins....
+            DbRelationshipDetected reverseRelationship = new DbRelationshipDetected();
+            reverseRelationship.setName(NameBuilder
+                    .builder(reverseRelationship, fkEntity)
+                    .baseName(nameGenerator.createDbRelationshipName(key, false))
+                    .name());
+
             reverseRelationship.setFkName(key.getFKName());
             reverseRelationship.setSourceEntity(fkEntity);
             reverseRelationship.setTargetEntityName(pkEntity);
@@ -336,7 +349,12 @@ public class DbLoader {
                     && fkEntity.getPrimaryKeys().size() == forwardRelationship.getJoins().size();
 
             forwardRelationship.setToMany(!isOneToOne);
-            forwardRelationship.setName(generateName(pkEntity, key, !isOneToOne));
+
+            // TODO: can we avoid resetting the name twice? Do we need a placeholder name above?
+            forwardRelationship.setName(NameBuilder
+                            .builder(forwardRelationship, pkEntity)
+                            .baseName(nameGenerator.createDbRelationshipName(key, !isOneToOne))
+                            .name());
 
             if (delegate.dbRelationshipLoaded(fkEntity, reverseRelationship)) {
                 fkEntity.addRelationship(reverseRelationship);
@@ -358,7 +376,7 @@ public class DbLoader {
     }
 
     private void createAndAppendJoins(Set<ExportedKey> exportedKeys, DbEntity pkEntity, DbEntity fkEntity,
-                                      DbRelationship forwardRelationship, DbRelationshipDetected reverseRelationship) {
+                                      DbRelationship forwardRelationship, DbRelationship reverseRelationship) {
         for (ExportedKey exportedKey : exportedKeys) {
             // Create and append joins
             String pkName = exportedKey.getPKColumnName();
@@ -437,11 +455,6 @@ public class DbLoader {
         LOGGER.info("Skip relation: '" + key + "' because table '" + tableName + "' not found");
     }
 
-    private String generateName(DbEntity entity, ExportedKey key, boolean toMany) {
-        String forwardPreferredName = nameGenerator.createDbRelationshipName(key, toMany);
-        return DuplicateNameResolver.resolve(NameCheckers.dbRelationship, entity, forwardPreferredName);
-    }
-
     private void fireObjEntitiesAddedEvents(Collection<ObjEntity> loadedObjEntities) {
         for (ObjEntity curEntity : loadedObjEntities) {
             // notify delegate

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/DbRelationshipDetected.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/DbRelationshipDetected.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/DbRelationshipDetected.java
new file mode 100644
index 0000000..dfad14f
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/DbRelationshipDetected.java
@@ -0,0 +1,53 @@
+/*****************************************************************
+ *   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.reverse.db;
+
+
+import org.apache.cayenne.map.DbRelationship;
+
+/**
+ * A subclass of {@link DbRelationship} to hold some extra runtime information.
+ */
+// TODO: dirty ... can we lookup fkName via joins?
+public class DbRelationshipDetected extends DbRelationship {
+
+    private String fkName;
+
+    public DbRelationshipDetected(String uniqueRelName) {
+        super(uniqueRelName);
+    }
+
+    public DbRelationshipDetected() {
+    }
+
+    /**
+     * Get the name of the underlying foreign key. Typically FK_NAME from jdbc metadata.
+     */
+    public String getFkName() {
+        return fkName;
+    }
+
+    /**
+     * Set the name of the underlying foreign key. Typically FK_NAME from jdbc metadata.
+     */
+    public void setFkName(String fkName) {
+        this.fkName = fkName;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/ManyToManyCandidateEntity.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/ManyToManyCandidateEntity.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/ManyToManyCandidateEntity.java
index 85af6a4..7f2f815 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/ManyToManyCandidateEntity.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/ManyToManyCandidateEntity.java
@@ -18,12 +18,11 @@
  ****************************************************************/
 package org.apache.cayenne.dbsync.reverse.db;
 
+import org.apache.cayenne.dbsync.naming.NameBuilder;
+import org.apache.cayenne.dbsync.reverse.naming.ObjectNameGenerator;
 import org.apache.cayenne.map.DbRelationship;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.ObjRelationship;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
-import org.apache.cayenne.dbsync.reverse.naming.ObjectNameGenerator;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -113,8 +112,10 @@ class ManyToManyCandidateEntity {
                 (short) 1);
 
         ObjRelationship newRelationship = new ObjRelationship();
-        newRelationship.setName(DuplicateNameResolver.resolve(NameCheckers.objRelationship, srcEntity,
-                nameGenerator.createDbRelationshipName(key, true)));
+        newRelationship.setName(NameBuilder
+                .builder(newRelationship, srcEntity)
+                .baseName(nameGenerator.createDbRelationshipName(key, true))
+                .name());
 
         newRelationship.setSourceEntity(srcEntity);
         newRelationship.setTargetEntityName(dstEntity);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/NameBuilderTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/NameBuilderTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/NameBuilderTest.java
new file mode 100644
index 0000000..8aa21c3
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/NameBuilderTest.java
@@ -0,0 +1,272 @@
+/*****************************************************************
+ *   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.naming;
+
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.configuration.DataNodeDescriptor;
+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.Embeddable;
+import org.apache.cayenne.map.EmbeddableAttribute;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.map.ProcedureParameter;
+import org.apache.cayenne.map.QueryDescriptor;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class NameBuilderTest {
+
+    @Test
+    public void testName_Root() {
+        assertEquals("project", NameBuilder.builder(new DataChannelDescriptor()).name());
+    }
+
+    @Test
+    public void testName_DataChannelDescriptorContext() throws Exception {
+        DataChannelDescriptor descriptor = new DataChannelDescriptor();
+
+        DataMap m0 = new DataMap();
+        m0.setName(NameBuilder.builder(m0).in(descriptor).name());
+        assertEquals("datamap", m0.getName());
+        descriptor.getDataMaps().add(m0);
+
+        DataMap m1 = new DataMap();
+        m1.setName(NameBuilder.builder(m1).in(descriptor).name());
+        assertEquals("datamap1", m1.getName());
+        descriptor.getDataMaps().add(m1);
+
+        DataNodeDescriptor nd0 = new DataNodeDescriptor();
+        nd0.setName(NameBuilder.builder(nd0).in(descriptor).name());
+        assertEquals("datanode", nd0.getName());
+        descriptor.getNodeDescriptors().add(nd0);
+
+        DataNodeDescriptor nd1 = new DataNodeDescriptor();
+        nd1.setName(NameBuilder.builder(nd1).in(descriptor).name());
+        assertEquals("datanode1", nd1.getName());
+        descriptor.getNodeDescriptors().add(nd1);
+    }
+
+
+    @Test
+    public void testName_DataMapContext() {
+        DataMap map = new DataMap();
+        map.setDefaultPackage("com.foo");
+
+        DbEntity de0 = new DbEntity();
+        de0.setName(NameBuilder.builder(de0).in(map).name());
+        assertEquals("db_entity", de0.getName());
+        map.addDbEntity(de0);
+
+        DbEntity de1 = new DbEntity();
+        de1.setName(NameBuilder.builder(de1).in(map).name());
+        assertEquals("db_entity1", de1.getName());
+        map.addDbEntity(de1);
+
+        ObjEntity oe0 = new ObjEntity();
+        oe0.setName(NameBuilder.builder(oe0).in(map).name());
+        assertEquals("ObjEntity", oe0.getName());
+        map.addObjEntity(oe0);
+
+        ObjEntity oe1 = new ObjEntity();
+        oe1.setName(NameBuilder.builder(oe1).in(map).name());
+        assertEquals("ObjEntity1", oe1.getName());
+        map.addObjEntity(oe1);
+
+        ObjEntity oe2 = new ObjEntity();
+        oe2.setName(NameBuilder.builder(oe0).in(map).baseName("db_entity").name());
+        assertEquals("Should not conflict with similarly named DbEntity", "Db_entity", oe2.getName());
+        map.addObjEntity(oe2);
+
+        Procedure p0 = new Procedure();
+        p0.setName(NameBuilder.builder(p0).in(map).name());
+        assertEquals("procedure", p0.getName());
+        map.addProcedure(p0);
+
+        Procedure p1 = new Procedure();
+        p1.setName(NameBuilder.builder(p1).in(map).name());
+        assertEquals("procedure1", p1.getName());
+        map.addProcedure(p1);
+
+        Procedure p2 = new Procedure();
+        p2.setName(NameBuilder.builder(p1).in(map).baseName("db_enity").name());
+        assertEquals("Should not conflict with similarly named DbEntity", "db_enity", p2.getName());
+        map.addProcedure(p2);
+
+        QueryDescriptor q0 = QueryDescriptor.selectQueryDescriptor();
+        q0.setName(NameBuilder.builder(q0).in(map).name());
+        assertEquals("query", q0.getName());
+        map.addQueryDescriptor(q0);
+
+        QueryDescriptor q1 = QueryDescriptor.ejbqlQueryDescriptor();
+        q1.setName(NameBuilder.builder(q1).in(map).name());
+        assertEquals("query1", q1.getName());
+        map.addQueryDescriptor(q1);
+
+        Embeddable e0 = new Embeddable();
+        e0.setClassName("com.foo." + NameBuilder.builder(e0).in(map).name());
+        assertEquals("com.foo.Embeddable", e0.getClassName());
+        map.addEmbeddable(e0);
+
+        Embeddable e1 = new Embeddable();
+        e1.setClassName("com.foo." + NameBuilder.builder(e1).in(map).name());
+        assertEquals("com.foo.Embeddable1", e1.getClassName());
+        map.addEmbeddable(e1);
+    }
+
+    @Test
+    public void testName_ObjEntityContext() {
+
+        ObjEntity entity = new ObjEntity();
+
+        entity.getCallbackMap().getPostAdd().addCallbackMethod("getMe");
+
+        ObjAttribute a0 = new ObjAttribute();
+        String na0 = NameBuilder.builder(a0).in(entity).name();
+        assertEquals("untitledAttr", na0);
+        a0.setName(na0);
+        entity.addAttribute(a0);
+
+        ObjAttribute a1 = new ObjAttribute();
+        String na1 = NameBuilder.builder(a1).in(entity).name();
+        assertEquals("untitledAttr1", na1);
+        a1.setName(na1);
+        entity.addAttribute(a1);
+
+        ObjAttribute a2 = new ObjAttribute();
+        String na2 = NameBuilder.builder(a2).in(entity).baseName("me").name();
+        assertEquals("Conflict with callback method was not detected", "me1", na2);
+        a2.setName(na2);
+        entity.addAttribute(a2);
+
+        ObjRelationship r0 = new ObjRelationship();
+        String nr0 = NameBuilder.builder(r0).in(entity).name();
+        assertEquals("untitledRel", nr0);
+        r0.setName(nr0);
+        entity.addRelationship(r0);
+
+        ObjRelationship r1 = new ObjRelationship();
+        String nr1 = NameBuilder.builder(r1).in(entity).name();
+        assertEquals("untitledRel1", nr1);
+        r1.setName(nr1);
+        entity.addRelationship(r1);
+    }
+
+    @Test
+    public void testName_DbEntityContext() {
+        DbEntity entity = new DbEntity();
+
+        DbAttribute a0 = new DbAttribute();
+        String na0 = NameBuilder.builder(a0).in(entity).name();
+        assertEquals("untitledAttr", na0);
+        a0.setName(na0);
+        entity.addAttribute(a0);
+
+        DbAttribute a1 = new DbAttribute();
+        String na1 = NameBuilder.builder(a1).in(entity).name();
+        assertEquals("untitledAttr1", na1);
+        a1.setName(na1);
+        entity.addAttribute(a1);
+
+        DbRelationship r0 = new DbRelationship();
+        String nr0 = NameBuilder.builder(r0).in(entity).name();
+        assertEquals("untitledRel", nr0);
+        r0.setName(nr0);
+        entity.addRelationship(r0);
+
+        DbRelationship r1 = new DbRelationship();
+        String nr1 = NameBuilder.builder(r1).in(entity).name();
+        assertEquals("untitledRel1", nr1);
+        r1.setName(nr1);
+        entity.addRelationship(r1);
+    }
+
+    @Test
+    public void testName_ProcedureContext() {
+        Procedure procedure = new Procedure();
+
+        ProcedureParameter p0 = new ProcedureParameter();
+        p0.setName(NameBuilder.builder(p0).in(procedure).name());
+        assertEquals("UntitledProcedureParameter", p0.getName());
+        procedure.addCallParameter(p0);
+
+        ProcedureParameter p1 = new ProcedureParameter();
+        p1.setName(NameBuilder.builder(p1).in(procedure).name());
+        assertEquals("UntitledProcedureParameter1", p1.getName());
+        procedure.addCallParameter(p1);
+    }
+
+    @Test
+    public void testName_EmbeddableContext() {
+        Embeddable embeddable = new Embeddable();
+
+        EmbeddableAttribute ea0 = new EmbeddableAttribute();
+        ea0.setName(NameBuilder.builder(ea0).in(embeddable).name());
+        assertEquals("untitledAttr", ea0.getName());
+        embeddable.addAttribute(ea0);
+
+        EmbeddableAttribute ea1 = new EmbeddableAttribute();
+        ea1.setName(NameBuilder.builder(ea1).in(embeddable).name());
+        assertEquals("untitledAttr1", ea1.getName());
+        embeddable.addAttribute(ea1);
+    }
+
+    @Test
+    public void testName_UncapitalizeAttributeNames() throws Exception {
+
+        ObjEntity entity = new ObjEntity();
+
+        ObjAttribute a0 = new ObjAttribute();
+        String na0 = NameBuilder.builder(a0).in(entity).baseName("myName").name();
+        assertEquals("myName", na0);
+        a0.setName(na0);
+        entity.addAttribute(a0);
+
+        ObjAttribute a1 = new ObjAttribute();
+        String na1 = NameBuilder.builder(a1).in(entity).baseName("MyName").name();
+        assertEquals("myName1", na1);
+        a1.setName(na1);
+        entity.addAttribute(a1);
+    }
+
+    @Test
+    public void testName_Callbacks_ObjEntityContext() {
+
+        ObjEntity entity = new ObjEntity();
+
+        String c0 = NameBuilder.builderForCallbackMethod(entity).name();
+        assertEquals("onEvent", c0);
+        entity.getCallbackMap().getPostAdd().addCallbackMethod(c0);
+
+        String c1 = NameBuilder.builderForCallbackMethod(entity).name();
+        assertEquals("onEvent1", c1);
+        entity.getCallbackMap().getPostAdd().addCallbackMethod(c1);
+
+        entity.addAttribute(new ObjAttribute("untitledAttr"));
+
+        String c3 = NameBuilder.builderForCallbackMethod(entity).baseName("getUntitledAttr").name();
+        assertEquals("getUntitledAttr1", c3);
+        entity.getCallbackMap().getPostAdd().addCallbackMethod(c3);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/NameCheckersTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/NameCheckersTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/NameCheckersTest.java
deleted file mode 100644
index 8131160..0000000
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/NameCheckersTest.java
+++ /dev/null
@@ -1,204 +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.naming;
-
-import org.apache.cayenne.access.DataDomain;
-import org.apache.cayenne.configuration.DataChannelDescriptor;
-import org.apache.cayenne.configuration.DataNodeDescriptor;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.Embeddable;
-import org.apache.cayenne.map.EmbeddableAttribute;
-import org.apache.cayenne.map.ObjAttribute;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.map.ObjRelationship;
-import org.apache.cayenne.map.Procedure;
-import org.apache.cayenne.map.ProcedureParameter;
-import org.apache.cayenne.map.QueryDescriptor;
-import org.junit.Assert;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class NameCheckersTest {
-
-    @Test
-    public void testObjEntityAttributes() throws Exception {
-        NameCheckers maker = NameCheckers.objAttribute;
-        ObjEntity namingContainer = new ObjEntity();
-
-        String baseName = maker.baseName();
-        String name = DuplicateNameResolver.resolve(maker, namingContainer);
-        assertEquals(baseName, name);
-        namingContainer.addAttribute(new ObjAttribute(name));
-
-        name = DuplicateNameResolver.resolve(maker, namingContainer);
-        assertEquals(baseName + "1", name);
-        namingContainer.addAttribute(new ObjAttribute(name));
-
-        name = DuplicateNameResolver.resolve(maker, namingContainer);
-        assertEquals(baseName + "2", name);
-        namingContainer.addAttribute(new ObjAttribute(name));
-
-        name = DuplicateNameResolver.resolve(maker, namingContainer);
-        assertEquals(baseName + "3", name);
-        namingContainer.addAttribute(new ObjAttribute(name));
-
-        maker = NameCheckers.objRelationship;
-        baseName = maker.baseName();
-        name = DuplicateNameResolver.resolve(maker, namingContainer);
-        assertEquals(baseName, name);
-        namingContainer.addRelationship(new ObjRelationship(name));
-
-        name = DuplicateNameResolver.resolve(maker, namingContainer);
-        assertEquals(baseName + "1", name);
-        namingContainer.addRelationship(new ObjRelationship(name));
-
-        maker = NameCheckers.objCallbackMethod;
-        baseName = maker.baseName();
-        name = DuplicateNameResolver.resolve(maker, namingContainer);
-        assertEquals(baseName, name);
-        namingContainer.addRelationship(new ObjRelationship(name));
-    }
-
-    @Test
-    public void testEntity () {
-        DataMap map = new DataMap();
-
-        map.addDbEntity(new DbEntity("name"));
-        checkNameAndOther(map, NameCheckers.dbEntity, "name");
-
-        map.addObjEntity(new ObjEntity("name"));
-        checkNameAndOther(map, NameCheckers.objEntity, "name");
-
-        map.addProcedure(new Procedure("name"));
-        checkNameAndOther(map, NameCheckers.procedure, "name");
-
-        QueryDescriptor query = QueryDescriptor.selectQueryDescriptor();
-        query.setName("name");
-        map.addQueryDescriptor(query);
-        checkNameAndOther(map, NameCheckers.query, "name");
-    }
-
-    @Test
-    public void testProject() throws Exception {
-        assertFalse(NameCheckers.dataChannelDescriptor.isNameInUse(null, null));
-    }
-
-    @Test
-    public void testDbEntity() throws Exception {
-        DbEntity dbEntity = new DbEntity();
-
-        dbEntity.addRelationship(new DbRelationship("name"));
-        checkNameAndOther(dbEntity, NameCheckers.dbRelationship, "name");
-    }
-
-    @Test
-    public void testProcedureAttr() throws Exception {
-        Procedure procedure = new Procedure();
-
-        procedure.addCallParameter(new ProcedureParameter("name"));
-        checkNameAndOther(procedure, NameCheckers.procedureParameter, "name");
-    }
-
-    @Test
-    public void testEmbeddableAttr() throws Exception {
-        Embeddable embeddable = new Embeddable();
-
-        embeddable.addAttribute(new EmbeddableAttribute("name"));
-        checkNameAndOther(embeddable, NameCheckers.embeddableAttribute, "name");
-    }
-
-    @Test
-    public void testDatanode() throws Exception {
-        DataChannelDescriptor descriptor = new DataChannelDescriptor();
-
-        descriptor.getDataMaps().add(new DataMap("name"));
-        checkNameAndOther(descriptor, NameCheckers.dataMap, "name");
-
-        descriptor.getNodeDescriptors().add(new DataNodeDescriptor("name"));
-        checkNameAndOther(descriptor, NameCheckers.dataNodeDescriptor, "name");
-    }
-
-    @Test
-    public void testDataMap() throws Exception {
-        DataDomain dataDomain = new DataDomain("name");
-
-        dataDomain.addDataMap(new DataMap("name"));
-        checkNameAndOther(dataDomain, NameCheckers.dataMap, "name");
-
-        assertFalse(NameCheckers.dataMap.isNameInUse(null, "name"));
-        assertFalse(NameCheckers.dataMap.isNameInUse(1, "name"));
-    }
-
-    private void checkNameAndOther(Object namingContainer, NameCheckers maker, String newName) {
-        assertTrue(maker.isNameInUse(namingContainer, newName));
-        assertEquals(newName + "1", DuplicateNameResolver.resolve(maker,namingContainer, newName));
-        assertEquals("other" + newName, DuplicateNameResolver.resolve(maker,namingContainer, "other" + newName));
-    }
-
-    @Test
-    public void testOverlappingAttributeAndCallbackNames() throws Exception {
-        ObjEntity namingContainer = new ObjEntity();
-
-        namingContainer.addAttribute(new ObjAttribute("myName"));
-        assertEquals("getMyName1", DuplicateNameResolver.resolve(NameCheckers.objCallbackMethod, namingContainer, "getMyName"));
-
-        namingContainer.getCallbackMap().getPostAdd().addCallbackMethod("getSecondName");
-        assertEquals("SecondName1", DuplicateNameResolver.resolve(NameCheckers.objAttribute, namingContainer, "SecondName"));
-        assertEquals("secondName1", DuplicateNameResolver.resolve(NameCheckers.objAttribute, namingContainer, "secondName"));
-        assertEquals("SecondName1", DuplicateNameResolver.resolve(NameCheckers.objRelationship, namingContainer, "SecondName"));
-        assertEquals("secondName1", DuplicateNameResolver.resolve(NameCheckers.objRelationship, namingContainer, "secondName"));
-    }
-
-    @Test
-    public void testAttributeDifferentInFirstLetterCases() throws Exception {
-        ObjEntity namingContainer = new ObjEntity();
-
-        namingContainer.addAttribute(new ObjAttribute("myName"));
-        Assert.assertTrue(NameCheckers.objAttribute.isNameInUse(namingContainer, "myName"));
-        Assert.assertFalse(NameCheckers.objAttribute.isNameInUse(namingContainer, "MyName"));
-
-        namingContainer.getCallbackMap().getPostAdd().addCallbackMethod("getSecondName");
-        assertEquals("SecondName1", DuplicateNameResolver.resolve(NameCheckers.objAttribute, namingContainer, "SecondName"));
-        assertEquals("secondName1", DuplicateNameResolver.resolve(NameCheckers.objAttribute, namingContainer, "secondName"));
-    }
-
-    @Test
-    public void testEmbeddable() {
-        DataMap map = new DataMap();
-
-        map.addEmbeddable(new Embeddable("name"));
-        Assert.assertTrue(NameCheckers.embeddable.isNameInUse(map, "name"));
-        assertEquals("name1", DuplicateNameResolver.resolve(NameCheckers.embeddable, map, "name"));
-        Assert.assertFalse(NameCheckers.embeddable.isNameInUse(map, "other-name"));
-
-        map.setDefaultPackage("package");
-        Assert.assertFalse(NameCheckers.embeddable.isNameInUse(map, "name"));
-        assertEquals("package.name", DuplicateNameResolver.resolve(NameCheckers.embeddable, map, "name"));
-        map.addEmbeddable(new Embeddable("package.name"));
-
-        Assert.assertTrue(NameCheckers.embeddable.isNameInUse(map, "name"));
-        assertEquals("package.name1", DuplicateNameResolver.resolve(NameCheckers.embeddable, map, "name"));
-        Assert.assertFalse(NameCheckers.embeddable.isNameInUse(map, "other-name"));
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/cayenne-server/src/main/java/org/apache/cayenne/map/CallbackDescriptor.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/CallbackDescriptor.java b/cayenne-server/src/main/java/org/apache/cayenne/map/CallbackDescriptor.java
index d76f38c..c1a75f1 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/CallbackDescriptor.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/CallbackDescriptor.java
@@ -74,7 +74,7 @@ public class CallbackDescriptor implements Serializable {
     }
 
     /**
-     * moves specified callback method to the specified position
+     * Moves specified callback method to the specified position
      * 
      * @param callbackMethod callbacm method name (should exist)
      * @param destinationIndex destinationi index (should be valid)

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationshipDetected.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationshipDetected.java b/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationshipDetected.java
deleted file mode 100644
index 8a610e3..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationshipDetected.java
+++ /dev/null
@@ -1,48 +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.map;
-
-
-/**
- * A subclass of {@link DbRelationship} to hold some extra runtime information.
- * 
- */
-public class DbRelationshipDetected extends DbRelationship {
-
-    private String fkName;
-
-    public DbRelationshipDetected(String uniqueRelName) {
-        super(uniqueRelName);
-    }
-
-    /**
-     * Set the name of the underlying foreign key. Typically FK_NAME from jdbc metadata.
-     */
-    public void setFkName(String fkName) {
-        this.fkName = fkName;
-    }
-
-    /**
-     * Get the name of the underlying foreign key. Typically FK_NAME from jdbc metadata.
-     */
-    public String getFkName() {
-        return fkName;
-    }
-
-}


[2/3] cayenne git commit: CAY-2116 Split schema synchronization code in a separate module

Posted by aa...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateAttributeAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateAttributeAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateAttributeAction.java
index 5ee3c0e..5b1841d 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateAttributeAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateAttributeAction.java
@@ -19,11 +19,10 @@
 
 package org.apache.cayenne.modeler.action;
 
-import java.awt.event.ActionEvent;
-
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.dba.TypesMapping;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.map.Attribute;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbAttribute;
@@ -36,8 +35,6 @@ import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.event.AttributeEvent;
 import org.apache.cayenne.map.event.EmbeddableAttributeEvent;
 import org.apache.cayenne.map.event.MapEvent;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.ProjectController;
 import org.apache.cayenne.modeler.event.AttributeDisplayEvent;
@@ -46,19 +43,60 @@ import org.apache.cayenne.modeler.undo.CreateAttributeUndoableEdit;
 import org.apache.cayenne.modeler.undo.CreateEmbAttributeUndoableEdit;
 import org.apache.cayenne.modeler.util.CayenneAction;
 
+import java.awt.event.ActionEvent;
+
 /**
  */
 public class CreateAttributeAction extends CayenneAction {
 
+    /**
+     * Constructor for CreateAttributeAction.
+     */
+    public CreateAttributeAction(Application application) {
+        super(getActionName(), application);
+    }
+
     public static String getActionName() {
         return "Create Attribute";
     }
 
+    static void fireEmbeddableAttributeEvent(Object src, ProjectController mediator, Embeddable embeddable,
+                                             EmbeddableAttribute attr) {
+
+        mediator.fireEmbeddableAttributeEvent(new EmbeddableAttributeEvent(src, attr, embeddable, MapEvent.ADD));
+
+        EmbeddableAttributeDisplayEvent e = new EmbeddableAttributeDisplayEvent(src, embeddable, attr,
+                mediator.getCurrentDataMap(), (DataChannelDescriptor) mediator.getProject().getRootNode());
+
+        mediator.fireEmbeddableAttributeDisplayEvent(e);
+    }
+
     /**
-     * Constructor for CreateAttributeAction.
+     * Fires events when an obj attribute was added
      */
-    public CreateAttributeAction(Application application) {
-        super(getActionName(), application);
+    static void fireObjAttributeEvent(Object src, ProjectController mediator, DataMap map, ObjEntity objEntity,
+                                      ObjAttribute attr) {
+
+        mediator.fireObjAttributeEvent(new AttributeEvent(src, attr, objEntity, MapEvent.ADD));
+
+        DataChannelDescriptor domain = (DataChannelDescriptor) mediator.getProject().getRootNode();
+
+        AttributeDisplayEvent ade = new AttributeDisplayEvent(src, attr, objEntity, map, domain);
+
+        mediator.fireObjAttributeDisplayEvent(ade);
+    }
+
+    /**
+     * Fires events when a db attribute was added
+     */
+    static void fireDbAttributeEvent(Object src, ProjectController mediator, DataMap map, DbEntity dbEntity,
+                                     DbAttribute attr) {
+        mediator.fireDbAttributeEvent(new AttributeEvent(src, attr, dbEntity, MapEvent.ADD));
+
+        AttributeDisplayEvent ade = new AttributeDisplayEvent(src, attr, dbEntity, map,
+                (DataChannelDescriptor) mediator.getProject().getRootNode());
+
+        mediator.fireDbAttributeDisplayEvent(ade);
     }
 
     @Override
@@ -77,19 +115,22 @@ public class CreateAttributeAction extends CayenneAction {
             Embeddable embeddable = mediator.getCurrentEmbeddable();
 
             EmbeddableAttribute attr = new EmbeddableAttribute();
-            attr.setName(DuplicateNameResolver.resolve(NameCheckers.embeddableAttribute, embeddable));
+            attr.setName(NameBuilder
+                    .builder(attr, embeddable)
+                    .name());
 
             createEmbAttribute(embeddable, attr);
 
             application.getUndoManager().addEdit(
-                    new CreateEmbAttributeUndoableEdit(embeddable, new EmbeddableAttribute[] { attr }));
+                    new CreateEmbAttributeUndoableEdit(embeddable, new EmbeddableAttribute[]{attr}));
         }
 
         if (getProjectController().getCurrentObjEntity() != null) {
 
             ObjEntity objEntity = mediator.getCurrentObjEntity();
 
-            ObjAttribute attr = new ObjAttribute(DuplicateNameResolver.resolve(NameCheckers.objAttribute, objEntity), null, objEntity);
+            ObjAttribute attr = new ObjAttribute();
+            attr.setName(NameBuilder.builder(attr, objEntity).name());
 
             createObjAttribute(mediator.getCurrentDataMap(), objEntity, attr);
 
@@ -99,8 +140,10 @@ public class CreateAttributeAction extends CayenneAction {
         } else if (getProjectController().getCurrentDbEntity() != null) {
             DbEntity dbEntity = getProjectController().getCurrentDbEntity();
 
-            DbAttribute attr = new DbAttribute(DuplicateNameResolver.resolve(NameCheckers.dbAttribute, dbEntity),
-                    TypesMapping.NOT_DEFINED, dbEntity);
+            DbAttribute attr = new DbAttribute();
+            attr.setName(NameBuilder.builder(attr, dbEntity).name());
+            attr.setType(TypesMapping.NOT_DEFINED);
+            attr.setEntity(dbEntity);
 
             createDbAttribute(mediator.getCurrentDataMap(), dbEntity, attr);
 
@@ -116,17 +159,6 @@ public class CreateAttributeAction extends CayenneAction {
         fireEmbeddableAttributeEvent(this, mediator, embeddable, attr);
     }
 
-    static void fireEmbeddableAttributeEvent(Object src, ProjectController mediator, Embeddable embeddable,
-            EmbeddableAttribute attr) {
-
-        mediator.fireEmbeddableAttributeEvent(new EmbeddableAttributeEvent(src, attr, embeddable, MapEvent.ADD));
-
-        EmbeddableAttributeDisplayEvent e = new EmbeddableAttributeDisplayEvent(src, embeddable, attr,
-                mediator.getCurrentDataMap(), (DataChannelDescriptor) mediator.getProject().getRootNode());
-
-        mediator.fireEmbeddableAttributeDisplayEvent(e);
-    }
-
     public void createObjAttribute(DataMap map, ObjEntity objEntity, ObjAttribute attr) {
 
         ProjectController mediator = getProjectController();
@@ -134,21 +166,6 @@ public class CreateAttributeAction extends CayenneAction {
         fireObjAttributeEvent(this, mediator, map, objEntity, attr);
     }
 
-    /**
-     * Fires events when an obj attribute was added
-     */
-    static void fireObjAttributeEvent(Object src, ProjectController mediator, DataMap map, ObjEntity objEntity,
-            ObjAttribute attr) {
-
-        mediator.fireObjAttributeEvent(new AttributeEvent(src, attr, objEntity, MapEvent.ADD));
-
-        DataChannelDescriptor domain = (DataChannelDescriptor) mediator.getProject().getRootNode();
-
-        AttributeDisplayEvent ade = new AttributeDisplayEvent(src, attr, objEntity, map, domain);
-
-        mediator.fireObjAttributeDisplayEvent(ade);
-    }
-
     public void createDbAttribute(DataMap map, DbEntity dbEntity, DbAttribute attr) {
         dbEntity.addAttribute(attr);
         ProjectController mediator = getProjectController();
@@ -156,19 +173,6 @@ public class CreateAttributeAction extends CayenneAction {
     }
 
     /**
-     * Fires events when a db attribute was added
-     */
-    static void fireDbAttributeEvent(Object src, ProjectController mediator, DataMap map, DbEntity dbEntity,
-            DbAttribute attr) {
-        mediator.fireDbAttributeEvent(new AttributeEvent(src, attr, dbEntity, MapEvent.ADD));
-
-        AttributeDisplayEvent ade = new AttributeDisplayEvent(src, attr, dbEntity, map,
-                (DataChannelDescriptor) mediator.getProject().getRootNode());
-
-        mediator.fireDbAttributeDisplayEvent(ade);
-    }
-
-    /**
      * Returns <code>true</code> if path contains an Entity object.
      */
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateCallbackMethodAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateCallbackMethodAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateCallbackMethodAction.java
index cc37948..a3b5507 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateCallbackMethodAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateCallbackMethodAction.java
@@ -18,8 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.action;
 
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.map.CallbackMap;
 import org.apache.cayenne.map.LifecycleEvent;
 import org.apache.cayenne.map.event.MapEvent;
@@ -34,11 +33,9 @@ import java.awt.event.ActionEvent;
 
 /**
  * Action class for creating callback methods on ObjEntity
- *
- * @version 1.0 Oct 30, 2007
  */
 public class CreateCallbackMethodAction extends CayenneAction {
-    
+
     /**
      * unique action name
      */
@@ -46,8 +43,8 @@ public class CreateCallbackMethodAction extends CayenneAction {
 
     /**
      * Constructor.
-     * 
-     * @param actionName unique action name
+     *
+     * @param actionName  unique action name
      * @param application Application instance
      */
     public CreateCallbackMethodAction(String actionName, Application application) {
@@ -55,12 +52,25 @@ public class CreateCallbackMethodAction extends CayenneAction {
     }
 
     /**
+     * Constructor.
+     *
+     * @param application Application instance
+     */
+    public CreateCallbackMethodAction(Application application) {
+        super(ACTION_NAME, application);
+    }
+
+    public static String getActionName() {
+        return ACTION_NAME;
+    }
+
+    /**
      * @return CallbackMap instance where to create a method
      */
     public CallbackMap getCallbackMap() {
         return getProjectController().getCurrentObjEntity().getCallbackMap();
     }
-    
+
     /**
      * @return icon file name for button
      */
@@ -70,14 +80,16 @@ public class CreateCallbackMethodAction extends CayenneAction {
 
     /**
      * performs adding new callback method
-     * 
+     *
      * @param e event
      */
     public final void performAction(ActionEvent e) {
         CallbackType callbackType = getProjectController().getCurrentCallbackType();
 
-        String methodNamePrefix = toMethodName(callbackType.getType());
-        String methodName = DuplicateNameResolver.resolve(NameCheckers.objCallbackMethod, getProjectController().getCurrentObjEntity(), methodNamePrefix);
+        String methodName = NameBuilder
+                .builderForCallbackMethod(getProjectController().getCurrentObjEntity())
+                .baseName(toMethodName(callbackType.getType()))
+                .name();
 
         createCallbackMethod(callbackType, methodName);
         application.getUndoManager().addEdit(
@@ -103,18 +115,5 @@ public class CreateCallbackMethodAction extends CayenneAction {
     private String toMethodName(LifecycleEvent event) {
         return "on" + Util.underscoredToJava(event.name(), true);
     }
-    
-    public static String getActionName() {
-        return ACTION_NAME;
-    }
-    
-    /**
-     * Constructor.
-     *
-     * @param application Application instance
-     */
-    public CreateCallbackMethodAction(Application application) {
-        super(ACTION_NAME, application);
-    }
 }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateDataMapAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateDataMapAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateDataMapAction.java
index 8403cb7..66dbae7 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateDataMapAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateDataMapAction.java
@@ -22,9 +22,8 @@ package org.apache.cayenne.modeler.action;
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.ProjectController;
 import org.apache.cayenne.modeler.undo.CreateDataMapUndoableEdit;
@@ -34,7 +33,6 @@ import java.awt.event.ActionEvent;
 
 /**
  * Action that creates new DataMap in the project.
- * 
  */
 public class CreateDataMapAction extends CayenneAction {
 
@@ -59,16 +57,15 @@ public class CreateDataMapAction extends CayenneAction {
     public void performAction(ActionEvent e) {
         ProjectController mediator = getProjectController();
 
-        DataChannelDescriptor currentDomain = (DataChannelDescriptor) mediator
+        DataChannelDescriptor dataChannelDescriptor = (DataChannelDescriptor) mediator
                 .getProject()
                 .getRootNode();
 
-        DataMap map = new DataMap(DuplicateNameResolver.resolve(NameCheckers.dataMap, currentDomain));
-
+        DataMap map = new DataMap();
+        map.setName(NameBuilder.builder(map, dataChannelDescriptor).name());
         createDataMap(map);
 
-        application.getUndoManager().addEdit(
-                new CreateDataMapUndoableEdit(currentDomain, map));
+        application.getUndoManager().addEdit(new CreateDataMapUndoableEdit(dataChannelDescriptor, map));
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateDbEntityAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateDbEntityAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateDbEntityAction.java
index abeaee3..1117bf1 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateDbEntityAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateDbEntityAction.java
@@ -19,88 +19,84 @@
 
 package org.apache.cayenne.modeler.action;
 
-import java.awt.event.ActionEvent;
-
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.Entity;
 import org.apache.cayenne.map.event.EntityEvent;
 import org.apache.cayenne.map.event.MapEvent;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.ProjectController;
 import org.apache.cayenne.modeler.event.EntityDisplayEvent;
 import org.apache.cayenne.modeler.undo.CreateDbEntityUndoableEdit;
 import org.apache.cayenne.modeler.util.CayenneAction;
 
-public class CreateDbEntityAction extends CayenneAction {
+import java.awt.event.ActionEvent;
 
-	public static String getActionName() {
-		return "Create DbEntity";
-	}
+public class CreateDbEntityAction extends CayenneAction {
 
-	/**
-	 * Constructor for CreateDbEntityAction.
-	 */
-	public CreateDbEntityAction(Application application) {
-		super(getActionName(), application);
-	}
+    /**
+     * Constructor for CreateDbEntityAction.
+     */
+    public CreateDbEntityAction(Application application) {
+        super(getActionName(), application);
+    }
 
-	public String getIconName() {
-		return "icon-dbentity.gif";
-	}
+    public static String getActionName() {
+        return "Create DbEntity";
+    }
 
-	/**
-	 * Creates new DbEntity, adds it to the current DataMap, fires DbEntityEvent
-	 * and DbEntityDisplayEvent.
-	 * 
-	 * @see org.apache.cayenne.modeler.util.CayenneAction#performAction(ActionEvent)
-	 */
-	public void performAction(ActionEvent e) {
-		ProjectController mediator = getProjectController();
+    /**
+     * Fires events when a db entity was added
+     */
+    static void fireDbEntityEvent(Object src, ProjectController mediator, DbEntity entity) {
+        mediator.fireDbEntityEvent(new EntityEvent(src, entity, MapEvent.ADD));
+        EntityDisplayEvent displayEvent = new EntityDisplayEvent(src, entity, mediator.getCurrentDataMap(),
+                mediator.getCurrentDataNode(), (DataChannelDescriptor) mediator.getProject().getRootNode());
+        displayEvent.setMainTabFocus(true);
+        mediator.fireDbEntityDisplayEvent(displayEvent);
+    }
 
-		DataMap map = mediator.getCurrentDataMap();
-		DbEntity entity = new DbEntity(DuplicateNameResolver.resolve(NameCheckers.dbEntity, map));
+    public String getIconName() {
+        return "icon-dbentity.gif";
+    }
 
-		createEntity(map, entity);
+    /**
+     * Creates new DbEntity, adds it to the current DataMap, fires DbEntityEvent and DbEntityDisplayEvent.
+     */
+    public void performAction(ActionEvent e) {
+        ProjectController mediator = getProjectController();
 
-		application.getUndoManager().addEdit(new CreateDbEntityUndoableEdit(map, entity));
-	}
+        DataMap map = mediator.getCurrentDataMap();
+        DbEntity entity = new DbEntity();
+        entity.setName(NameBuilder.builder(entity, map).name());
+        createEntity(map, entity);
 
-	/**
-	 * Fires events when a db entity was added
-	 */
-	static void fireDbEntityEvent(Object src, ProjectController mediator, DbEntity entity) {
-		mediator.fireDbEntityEvent(new EntityEvent(src, entity, MapEvent.ADD));
-		EntityDisplayEvent displayEvent = new EntityDisplayEvent(src, entity, mediator.getCurrentDataMap(),
-				mediator.getCurrentDataNode(), (DataChannelDescriptor) mediator.getProject().getRootNode());
-		displayEvent.setMainTabFocus(true);
-		mediator.fireDbEntityDisplayEvent(displayEvent);
-	}
+        application.getUndoManager().addEdit(new CreateDbEntityUndoableEdit(map, entity));
+    }
 
-	/**
-	 * Constructs and returns a new DbEntity. Entity returned is added to the
-	 * DataMap.
-	 */
-	public void createEntity(DataMap map, DbEntity entity) {
-		ProjectController mediator = getProjectController();
-		entity.setCatalog(map.getDefaultCatalog());
-		entity.setSchema(map.getDefaultSchema());
-		map.addDbEntity(entity);
-		fireDbEntityEvent(this, mediator, entity);
-	}
+    /**
+     * Constructs and returns a new DbEntity. Entity returned is added to the
+     * DataMap.
+     */
+    public void createEntity(DataMap map, DbEntity entity) {
+        ProjectController mediator = getProjectController();
+        entity.setCatalog(map.getDefaultCatalog());
+        entity.setSchema(map.getDefaultSchema());
+        map.addDbEntity(entity);
+        fireDbEntityEvent(this, mediator, entity);
+    }
 
-	/**
-	 * Returns <code>true</code> if path contains a DataMap object.
-	 */
-	public boolean enableForPath(ConfigurationNode object) {
-		if (object == null) {
-			return false;
-		}
+    /**
+     * Returns <code>true</code> if path contains a DataMap object.
+     */
+    public boolean enableForPath(ConfigurationNode object) {
+        if (object == null) {
+            return false;
+        }
 
-		return ((Entity) object).getDataMap() != null;
-	}
+        return ((Entity) object).getDataMap() != null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateEmbeddableAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateEmbeddableAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateEmbeddableAction.java
index 7fea640..fe073ec 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateEmbeddableAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateEmbeddableAction.java
@@ -18,23 +18,22 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.action;
 
-import java.awt.event.ActionEvent;
-
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.Embeddable;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.event.EmbeddableEvent;
 import org.apache.cayenne.map.event.MapEvent;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.ProjectController;
 import org.apache.cayenne.modeler.event.EmbeddableDisplayEvent;
 import org.apache.cayenne.modeler.undo.CreateEmbeddableUndoableEdit;
 import org.apache.cayenne.modeler.util.CayenneAction;
 
+import java.awt.event.ActionEvent;
+
 public class CreateEmbeddableAction extends CayenneAction {
 
     public static String getActionName() {
@@ -56,11 +55,11 @@ public class CreateEmbeddableAction extends CayenneAction {
 
         DataMap dataMap = mediator.getCurrentDataMap();
 
-        Embeddable embeddable = new Embeddable(DuplicateNameResolver.resolve(NameCheckers.embeddable, mediator.getCurrentDataMap()));
+        Embeddable embeddable = new Embeddable();
+        embeddable.setClassName(NameBuilder.builder(embeddable, dataMap).name());
         createEmbeddable(dataMap, embeddable);
 
-        application.getUndoManager().addEdit(
-                new CreateEmbeddableUndoableEdit(dataMap, embeddable));
+        application.getUndoManager().addEdit(new CreateEmbeddableUndoableEdit(dataMap, embeddable));
     }
 
     public void createEmbeddable(DataMap dataMap, Embeddable embeddable) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateNodeAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateNodeAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateNodeAction.java
index eb0fbf9..56a0437 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateNodeAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateNodeAction.java
@@ -19,8 +19,6 @@
 
 package org.apache.cayenne.modeler.action;
 
-import java.awt.event.ActionEvent;
-
 import org.apache.cayenne.access.dbsync.SkipSchemaUpdateStrategy;
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
@@ -28,86 +26,86 @@ import org.apache.cayenne.configuration.DataNodeDescriptor;
 import org.apache.cayenne.configuration.event.DataNodeEvent;
 import org.apache.cayenne.configuration.server.XMLPoolingDataSourceFactory;
 import org.apache.cayenne.conn.DataSourceInfo;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.map.event.MapEvent;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.ProjectController;
 import org.apache.cayenne.modeler.event.DataNodeDisplayEvent;
 import org.apache.cayenne.modeler.undo.CreateNodeUndoableEdit;
 import org.apache.cayenne.modeler.util.CayenneAction;
 
+import java.awt.event.ActionEvent;
+
 public class CreateNodeAction extends CayenneAction {
 
-	public static String getActionName() {
-		return "Create DataNode";
-	}
-
-	/**
-	 * Constructor for CreateNodeAction.
-	 * 
-	 * @param application
-	 */
-	public CreateNodeAction(Application application) {
-		super(getActionName(), application);
-	}
-
-	public String getIconName() {
-		return "icon-node.gif";
-	}
-
-	/**
-	 * @see org.apache.cayenne.modeler.util.CayenneAction#performAction(ActionEvent)
-	 */
-	public void performAction(ActionEvent e) {
-		DataNodeDescriptor node = buildDataNode();
-		createDataNode(node);
-		application.getUndoManager().addEdit(new CreateNodeUndoableEdit(application, node));
-	}
-
-	public void createDataNode(DataNodeDescriptor node) {
-		DataChannelDescriptor domain = (DataChannelDescriptor) getProjectController().getProject().getRootNode();
-		domain.getNodeDescriptors().add(node);
-		getProjectController().fireDataNodeEvent(new DataNodeEvent(this, node, MapEvent.ADD));
-		getProjectController().fireDataNodeDisplayEvent(new DataNodeDisplayEvent(this, domain, node));
-	}
-
-	/**
-	 * Returns <code>true</code> if path contains a DataDomain object.
-	 */
-	public boolean enableForPath(ConfigurationNode object) {
-		return object != null && ((DataNodeDescriptor) object).getDataChannelDescriptor() != null;
-
-	}
-
-	/**
-	 * Creates a new DataNode, adding to the current domain, but doesn't send
-	 * any events.
-	 */
-	public DataNodeDescriptor buildDataNode() {
-		ProjectController mediator = getProjectController();
-		DataChannelDescriptor domain = (DataChannelDescriptor) mediator.getProject().getRootNode();
-
-		DataNodeDescriptor node = buildDataNode(domain);
-
-		DataSourceInfo src = new DataSourceInfo();
-		node.setDataSourceDescriptor(src);
-
-		// by default create JDBC Node
-		node.setDataSourceFactoryType(XMLPoolingDataSourceFactory.class.getName());
-		node.setSchemaUpdateStrategyType(SkipSchemaUpdateStrategy.class.getName());
-
-		return node;
-	}
-
-	/**
-	 * A factory method that makes a new DataNode.
-	 */
-	DataNodeDescriptor buildDataNode(DataChannelDescriptor domain) {
-		DataNodeDescriptor node = new DataNodeDescriptor(DuplicateNameResolver.resolve(
-				NameCheckers.dataNodeDescriptor, domain));
-		node.setDataChannelDescriptor(domain);
-
-		return node;
-	}
+    /**
+     * Constructor for CreateNodeAction.
+     *
+     * @param application
+     */
+    public CreateNodeAction(Application application) {
+        super(getActionName(), application);
+    }
+
+    public static String getActionName() {
+        return "Create DataNode";
+    }
+
+    @Override
+    public String getIconName() {
+        return "icon-node.gif";
+    }
+
+    @Override
+    public void performAction(ActionEvent e) {
+        DataNodeDescriptor node = buildDataNode();
+        createDataNode(node);
+        application.getUndoManager().addEdit(new CreateNodeUndoableEdit(application, node));
+    }
+
+    public void createDataNode(DataNodeDescriptor node) {
+        DataChannelDescriptor domain = (DataChannelDescriptor) getProjectController().getProject().getRootNode();
+        domain.getNodeDescriptors().add(node);
+        getProjectController().fireDataNodeEvent(new DataNodeEvent(this, node, MapEvent.ADD));
+        getProjectController().fireDataNodeDisplayEvent(new DataNodeDisplayEvent(this, domain, node));
+    }
+
+    /**
+     * Returns <code>true</code> if path contains a DataDomain object.
+     */
+    public boolean enableForPath(ConfigurationNode object) {
+        return object != null && ((DataNodeDescriptor) object).getDataChannelDescriptor() != null;
+
+    }
+
+    /**
+     * Creates a new DataNode, adding to the current domain, but doesn't send
+     * any events.
+     */
+    public DataNodeDescriptor buildDataNode() {
+        ProjectController mediator = getProjectController();
+        DataChannelDescriptor domain = (DataChannelDescriptor) mediator.getProject().getRootNode();
+
+        DataNodeDescriptor node = buildDataNode(domain);
+
+        DataSourceInfo src = new DataSourceInfo();
+        node.setDataSourceDescriptor(src);
+
+        // by default create JDBC Node
+        node.setDataSourceFactoryType(XMLPoolingDataSourceFactory.class.getName());
+        node.setSchemaUpdateStrategyType(SkipSchemaUpdateStrategy.class.getName());
+
+        return node;
+    }
+
+    /**
+     * A factory method that makes a new DataNode.
+     */
+    DataNodeDescriptor buildDataNode(DataChannelDescriptor dataChannelDescriptor) {
+        DataNodeDescriptor node = new DataNodeDescriptor();
+        node.setName(NameBuilder.builder(node, dataChannelDescriptor).name());
+        node.setDataChannelDescriptor(dataChannelDescriptor);
+
+        return node;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateObjEntityAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateObjEntityAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateObjEntityAction.java
index 8a2bd4b..8569697 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateObjEntityAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateObjEntityAction.java
@@ -22,8 +22,7 @@ package org.apache.cayenne.modeler.action;
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.dbsync.merge.EntityMergeSupport;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.dbsync.reverse.naming.DefaultObjectNameGenerator;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbEntity;
@@ -36,16 +35,11 @@ import org.apache.cayenne.modeler.event.EntityDisplayEvent;
 import org.apache.cayenne.modeler.undo.CreateObjEntityUndoableEdit;
 import org.apache.cayenne.modeler.util.CayenneAction;
 import org.apache.cayenne.util.DeleteRuleUpdater;
-import org.apache.cayenne.util.Util;
 
 import java.awt.event.ActionEvent;
 
 public class CreateObjEntityAction extends CayenneAction {
 
-    public static String getActionName() {
-        return "Create ObjEntity";
-    }
-
     /**
      * Constructor for CreateObjEntityAction.
      */
@@ -53,14 +47,32 @@ public class CreateObjEntityAction extends CayenneAction {
         super(getActionName(), application);
     }
 
+    public static String getActionName() {
+        return "Create ObjEntity";
+    }
+
+
+    static void fireObjEntityEvent(
+            Object src,
+            ProjectController mediator,
+            DataMap dataMap,
+            ObjEntity entity) {
+        mediator.fireObjEntityEvent(new EntityEvent(src, entity, MapEvent.ADD));
+        EntityDisplayEvent displayEvent = new EntityDisplayEvent(
+                src,
+                entity,
+                dataMap,
+                mediator.getCurrentDataNode(),
+                (DataChannelDescriptor) mediator.getProject().getRootNode());
+        displayEvent.setMainTabFocus(true);
+        mediator.fireObjEntityDisplayEvent(displayEvent);
+    }
+
     @Override
     public String getIconName() {
         return "icon-new_objentity.gif";
     }
 
-    /**
-     * @see org.apache.cayenne.modeler.util.CayenneAction#performAction(ActionEvent)
-     */
     @Override
     public void performAction(ActionEvent e) {
         createObjEntity();
@@ -70,7 +82,10 @@ public class CreateObjEntityAction extends CayenneAction {
         ProjectController mediator = getProjectController();
 
         DataMap dataMap = mediator.getCurrentDataMap();
-        ObjEntity entity = new ObjEntity(DuplicateNameResolver.resolve(NameCheckers.objEntity, dataMap));
+        ObjEntity entity = new ObjEntity();
+        entity.setName(NameBuilder
+                .builder(entity, dataMap)
+                .name());
 
         // init defaults
         entity.setSuperClassName(dataMap.getDefaultSuperclass());
@@ -79,8 +94,13 @@ public class CreateObjEntityAction extends CayenneAction {
         DbEntity dbEntity = mediator.getCurrentDbEntity();
         if (dbEntity != null) {
             entity.setDbEntity(dbEntity);
-            String baseName = Util.underscoredToJava(dbEntity.getName(), true);
-            entity.setName(DuplicateNameResolver.resolve(NameCheckers.objEntity, dbEntity.getDataMap(), baseName));
+
+            // TODO: use injectable name generator
+            String baseName = new DefaultObjectNameGenerator().createObjEntityName(dbEntity);
+            entity.setName(NameBuilder
+                    .builder(entity, dbEntity.getDataMap())
+                    .baseName(baseName)
+                    .name());
         }
 
         entity.setClassName(dataMap.getNameWithDefaultPackage(entity.getName()));
@@ -110,25 +130,6 @@ public class CreateObjEntityAction extends CayenneAction {
     }
 
     /**
-     * Fires events when a obj entity was added
-     */
-    static void fireObjEntityEvent(
-            Object src,
-            ProjectController mediator,
-            DataMap dataMap,
-            ObjEntity entity) {
-        mediator.fireObjEntityEvent(new EntityEvent(src, entity, MapEvent.ADD));
-        EntityDisplayEvent displayEvent = new EntityDisplayEvent(
-                src,
-                entity,
-                dataMap,
-                mediator.getCurrentDataNode(),
-                (DataChannelDescriptor) mediator.getProject().getRootNode());
-        displayEvent.setMainTabFocus(true);
-        mediator.fireObjEntityDisplayEvent(displayEvent);
-    }
-
-    /**
      * Returns <code>true</code> if path contains a DataMap object.
      */
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateProcedureAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateProcedureAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateProcedureAction.java
index 7787abc..3dbdaa4 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateProcedureAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateProcedureAction.java
@@ -19,75 +19,74 @@
 
 package org.apache.cayenne.modeler.action;
 
-import java.awt.event.ActionEvent;
-
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.configuration.event.ProcedureEvent;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.Procedure;
 import org.apache.cayenne.map.event.MapEvent;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.ProjectController;
 import org.apache.cayenne.modeler.event.ProcedureDisplayEvent;
 import org.apache.cayenne.modeler.undo.CreateProcedureUndoableEdit;
 import org.apache.cayenne.modeler.util.CayenneAction;
 
+import java.awt.event.ActionEvent;
+
 /**
  * Action class to create a new stored procedure mapping.
  */
 public class CreateProcedureAction extends CayenneAction {
 
-	public static String getActionName() {
-		return "Create Stored Procedure";
-	}
-
-	public CreateProcedureAction(Application application) {
-		super(getActionName(), application);
-	}
+    public CreateProcedureAction(Application application) {
+        super(getActionName(), application);
+    }
 
-	public void performAction(ActionEvent e) {
-		ProjectController mediator = getProjectController();
-		DataMap map = mediator.getCurrentDataMap();
+    public static String getActionName() {
+        return "Create Stored Procedure";
+    }
 
-		Procedure procedure = new Procedure(DuplicateNameResolver.resolve(NameCheckers.procedure, map));
+    /**
+     * Fires events when a procedure was added
+     */
+    static void fireProcedureEvent(Object src, ProjectController mediator, DataMap dataMap, Procedure procedure) {
+        mediator.fireProcedureEvent(new ProcedureEvent(src, procedure, MapEvent.ADD));
+        mediator.fireProcedureDisplayEvent(new ProcedureDisplayEvent(src, procedure, mediator.getCurrentDataMap(),
+                (DataChannelDescriptor) mediator.getProject().getRootNode()));
+    }
 
-		createProcedure(map, procedure);
+    public void performAction(ActionEvent e) {
+        ProjectController mediator = getProjectController();
+        DataMap map = mediator.getCurrentDataMap();
 
-		application.getUndoManager().addEdit(new CreateProcedureUndoableEdit(map, procedure));
-	}
+        Procedure procedure = new Procedure();
+        procedure.setName(NameBuilder.builder(procedure, map).name());
+        createProcedure(map, procedure);
 
-	/**
-	 * Fires events when a procedure was added
-	 */
-	static void fireProcedureEvent(Object src, ProjectController mediator, DataMap dataMap, Procedure procedure) {
-		mediator.fireProcedureEvent(new ProcedureEvent(src, procedure, MapEvent.ADD));
-		mediator.fireProcedureDisplayEvent(new ProcedureDisplayEvent(src, procedure, mediator.getCurrentDataMap(),
-				(DataChannelDescriptor) mediator.getProject().getRootNode()));
-	}
+        application.getUndoManager().addEdit(new CreateProcedureUndoableEdit(map, procedure));
+    }
 
-	public void createProcedure(DataMap map, Procedure procedure) {
-		ProjectController mediator = getProjectController();
-		procedure.setSchema(map.getDefaultSchema());
-		procedure.setCatalog(map.getDefaultCatalog());
-		map.addProcedure(procedure);
-		fireProcedureEvent(this, mediator, map, procedure);
-	}
+    public void createProcedure(DataMap map, Procedure procedure) {
+        ProjectController mediator = getProjectController();
+        procedure.setSchema(map.getDefaultSchema());
+        procedure.setCatalog(map.getDefaultCatalog());
+        map.addProcedure(procedure);
+        fireProcedureEvent(this, mediator, map, procedure);
+    }
 
-	/**
-	 * Returns <code>true</code> if path contains a DataMap object.
-	 */
-	public boolean enableForPath(ConfigurationNode object) {
-		if (object == null) {
-			return false;
-		}
+    /**
+     * Returns <code>true</code> if path contains a DataMap object.
+     */
+    public boolean enableForPath(ConfigurationNode object) {
+        if (object == null) {
+            return false;
+        }
 
-		return ((Procedure) object).getDataMap() != null;
-	}
+        return ((Procedure) object).getDataMap() != null;
+    }
 
-	public String getIconName() {
-		return "icon-stored-procedure.gif";
-	}
+    public String getIconName() {
+        return "icon-stored-procedure.gif";
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateProcedureParameterAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateProcedureParameterAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateProcedureParameterAction.java
index e939f86..67c19c5 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateProcedureParameterAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateProcedureParameterAction.java
@@ -19,78 +19,78 @@
 
 package org.apache.cayenne.modeler.action;
 
-import java.awt.event.ActionEvent;
-
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.configuration.event.ProcedureParameterEvent;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.map.Procedure;
 import org.apache.cayenne.map.ProcedureParameter;
 import org.apache.cayenne.map.event.MapEvent;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.ProjectController;
 import org.apache.cayenne.modeler.event.ProcedureParameterDisplayEvent;
 import org.apache.cayenne.modeler.util.CayenneAction;
 
+import java.awt.event.ActionEvent;
+
 public class CreateProcedureParameterAction extends CayenneAction {
 
-	public static String getActionName() {
-		return "Create Parameter";
-	}
+    /**
+     * Constructor for CreateProcedureParameterAction.
+     */
+    public CreateProcedureParameterAction(Application application) {
+        super(getActionName(), application);
+    }
 
-	/**
-	 * Constructor for CreateProcedureParameterAction.
-	 * 
-	 */
-	public CreateProcedureParameterAction(Application application) {
-		super(getActionName(), application);
-	}
+    public static String getActionName() {
+        return "Create Parameter";
+    }
 
-	public String getIconName() {
-		return "icon-plus.gif";
-	}
+    /**
+     * Fires events when an proc parameter was added
+     */
+    static void fireProcedureParameterEvent(Object src, ProjectController mediator, Procedure procedure,
+                                            ProcedureParameter parameter) {
+        mediator.fireProcedureParameterEvent(new ProcedureParameterEvent(src, parameter, MapEvent.ADD));
 
-	/**
-	 * Creates ProcedureParameter depending on context.
-	 */
-	public void performAction(ActionEvent e) {
-		if (getProjectController().getCurrentProcedure() != null) {
-			createProcedureParameter();
-		}
-	}
+        mediator.fireProcedureParameterDisplayEvent(new ProcedureParameterDisplayEvent(src, parameter, procedure,
+                mediator.getCurrentDataMap(), (DataChannelDescriptor) mediator.getProject().getRootNode()));
+    }
 
-	public void createProcedureParameter() {
-		Procedure procedure = getProjectController().getCurrentProcedure();
+    @Override
+    public String getIconName() {
+        return "icon-plus.gif";
+    }
 
-		ProcedureParameter parameter = new ProcedureParameter(DuplicateNameResolver.resolve(
-				NameCheckers.procedureParameter, procedure));
-		procedure.addCallParameter(parameter);
+    /**
+     * Creates ProcedureParameter depending on context.
+     */
+    @Override
+    public void performAction(ActionEvent e) {
+        if (getProjectController().getCurrentProcedure() != null) {
+            createProcedureParameter();
+        }
+    }
 
-		ProjectController mediator = getProjectController();
-		fireProcedureParameterEvent(this, mediator, procedure, parameter);
-	}
+    public void createProcedureParameter() {
+        Procedure procedure = getProjectController().getCurrentProcedure();
 
-	/**
-	 * Fires events when an proc parameter was added
-	 */
-	static void fireProcedureParameterEvent(Object src, ProjectController mediator, Procedure procedure,
-			ProcedureParameter parameter) {
-		mediator.fireProcedureParameterEvent(new ProcedureParameterEvent(src, parameter, MapEvent.ADD));
+        ProcedureParameter parameter = new ProcedureParameter();
+        parameter.setName(NameBuilder.builder(parameter, procedure).name());
+        procedure.addCallParameter(parameter);
 
-		mediator.fireProcedureParameterDisplayEvent(new ProcedureParameterDisplayEvent(src, parameter, procedure,
-				mediator.getCurrentDataMap(), (DataChannelDescriptor) mediator.getProject().getRootNode()));
-	}
+        ProjectController mediator = getProjectController();
+        fireProcedureParameterEvent(this, mediator, procedure, parameter);
+    }
 
-	/**
-	 * Returns <code>true</code> if path contains a Procedure object.
-	 */
-	public boolean enableForPath(ConfigurationNode object) {
-		if (object == null) {
-			return false;
-		}
+    /**
+     * Returns <code>true</code> if path contains a Procedure object.
+     */
+    public boolean enableForPath(ConfigurationNode object) {
+        if (object == null) {
+            return false;
+        }
 
-		return ((ProcedureParameter) object).getProcedure() != null;
-	}
+        return ((ProcedureParameter) object).getProcedure() != null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateRelationshipAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateRelationshipAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateRelationshipAction.java
index 8abec0c..ec3a42d 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateRelationshipAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateRelationshipAction.java
@@ -19,10 +19,9 @@
 
 package org.apache.cayenne.modeler.action;
 
-import java.awt.event.ActionEvent;
-
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbRelationship;
 import org.apache.cayenne.map.Entity;
@@ -31,8 +30,6 @@ import org.apache.cayenne.map.ObjRelationship;
 import org.apache.cayenne.map.Relationship;
 import org.apache.cayenne.map.event.MapEvent;
 import org.apache.cayenne.map.event.RelationshipEvent;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.ProjectController;
 import org.apache.cayenne.modeler.event.RelationshipDisplayEvent;
@@ -40,111 +37,113 @@ import org.apache.cayenne.modeler.undo.CreateRelationshipUndoableEdit;
 import org.apache.cayenne.modeler.util.CayenneAction;
 import org.apache.cayenne.util.DeleteRuleUpdater;
 
+import java.awt.event.ActionEvent;
+
 public class CreateRelationshipAction extends CayenneAction {
 
-	public static String getActionName() {
-		return "Create Relationship";
-	}
-
-	/**
-	 * Constructor for CreateRelationshipAction.
-	 */
-	public CreateRelationshipAction(Application application) {
-		super(getActionName(), application);
-	}
-
-	@Override
-	public String getIconName() {
-		return "icon-relationship.gif";
-	}
-
-	/**
-	 * @see org.apache.cayenne.modeler.util.CayenneAction#performAction(ActionEvent)
-	 */
-	@Override
-	public void performAction(ActionEvent e) {
-		ObjEntity objEnt = getProjectController().getCurrentObjEntity();
-		if (objEnt != null) {
-
-			ObjRelationship rel = new ObjRelationship(DuplicateNameResolver.resolve(NameCheckers.objRelationship,
-					objEnt));
-			createObjRelationship(objEnt, rel);
-
-			application.getUndoManager().addEdit(
-					new CreateRelationshipUndoableEdit(objEnt, new ObjRelationship[] { rel }));
-		} else {
-			DbEntity dbEnt = getProjectController().getCurrentDbEntity();
-			if (dbEnt != null) {
-
-				DbRelationship rel = new DbRelationship(DuplicateNameResolver.resolve(
-						NameCheckers.dbRelationship, dbEnt));
-				createDbRelationship(dbEnt, rel);
-
-				application.getUndoManager().addEdit(
-						new CreateRelationshipUndoableEdit(dbEnt, new DbRelationship[] { rel }));
-			}
-		}
-	}
-
-	public void createObjRelationship(ObjEntity objEntity, ObjRelationship rel) {
-		ProjectController mediator = getProjectController();
-
-		rel.setSourceEntity(objEntity);
-		DeleteRuleUpdater.updateObjRelationship(rel);
-
-		objEntity.addRelationship(rel);
-		fireObjRelationshipEvent(this, mediator, objEntity, rel);
-	}
-
-	/**
-	 * Fires events when a obj rel was added
-	 */
-	static void fireObjRelationshipEvent(Object src, ProjectController mediator, ObjEntity objEntity,
-			ObjRelationship rel) {
-
-		mediator.fireObjRelationshipEvent(new RelationshipEvent(src, rel, objEntity, MapEvent.ADD));
-
-		RelationshipDisplayEvent rde = new RelationshipDisplayEvent(src, rel, objEntity, mediator.getCurrentDataMap(),
-				(DataChannelDescriptor) mediator.getProject().getRootNode());
-
-		mediator.fireObjRelationshipDisplayEvent(rde);
-	}
-
-	public void createDbRelationship(DbEntity dbEntity, DbRelationship rel) {
-		ProjectController mediator = getProjectController();
-
-		rel.setSourceEntity(dbEntity);
-		dbEntity.addRelationship(rel);
-
-		fireDbRelationshipEvent(this, mediator, dbEntity, rel);
-	}
-
-	/**
-	 * Fires events when a db rel was added
-	 */
-	static void fireDbRelationshipEvent(Object src, ProjectController mediator, DbEntity dbEntity, DbRelationship rel) {
-
-		mediator.fireDbRelationshipEvent(new RelationshipEvent(src, rel, dbEntity, MapEvent.ADD));
-
-		RelationshipDisplayEvent rde = new RelationshipDisplayEvent(src, rel, dbEntity, mediator.getCurrentDataMap(),
-				(DataChannelDescriptor) mediator.getProject().getRootNode());
-
-		mediator.fireDbRelationshipDisplayEvent(rde);
-	}
-
-	/**
-	 * Returns <code>true</code> if path contains an Entity object.
-	 */
-	@Override
-	public boolean enableForPath(ConfigurationNode object) {
-		if (object == null) {
-			return false;
-		}
-
-		if (object instanceof Relationship) {
-			return ((Relationship) object).getParent() != null && ((Relationship) object).getParent() instanceof Entity;
-		}
-
-		return false;
-	}
+    /**
+     * Constructor for CreateRelationshipAction.
+     */
+    public CreateRelationshipAction(Application application) {
+        super(getActionName(), application);
+    }
+
+    public static String getActionName() {
+        return "Create Relationship";
+    }
+
+    /**
+     * Fires events when a obj rel was added
+     */
+    static void fireObjRelationshipEvent(Object src, ProjectController mediator, ObjEntity objEntity,
+                                         ObjRelationship rel) {
+
+        mediator.fireObjRelationshipEvent(new RelationshipEvent(src, rel, objEntity, MapEvent.ADD));
+
+        RelationshipDisplayEvent rde = new RelationshipDisplayEvent(src, rel, objEntity, mediator.getCurrentDataMap(),
+                (DataChannelDescriptor) mediator.getProject().getRootNode());
+
+        mediator.fireObjRelationshipDisplayEvent(rde);
+    }
+
+    /**
+     * Fires events when a db rel was added
+     */
+    static void fireDbRelationshipEvent(Object src, ProjectController mediator, DbEntity dbEntity, DbRelationship rel) {
+
+        mediator.fireDbRelationshipEvent(new RelationshipEvent(src, rel, dbEntity, MapEvent.ADD));
+
+        RelationshipDisplayEvent rde = new RelationshipDisplayEvent(src, rel, dbEntity, mediator.getCurrentDataMap(),
+                (DataChannelDescriptor) mediator.getProject().getRootNode());
+
+        mediator.fireDbRelationshipDisplayEvent(rde);
+    }
+
+    @Override
+    public String getIconName() {
+        return "icon-relationship.gif";
+    }
+
+    /**
+     * @see org.apache.cayenne.modeler.util.CayenneAction#performAction(ActionEvent)
+     */
+    @Override
+    public void performAction(ActionEvent e) {
+        ObjEntity objEnt = getProjectController().getCurrentObjEntity();
+        if (objEnt != null) {
+
+            ObjRelationship rel = new ObjRelationship();
+            rel.setName(NameBuilder.builder(rel, objEnt).name());
+            createObjRelationship(objEnt, rel);
+
+            application.getUndoManager().addEdit(
+                    new CreateRelationshipUndoableEdit(objEnt, new ObjRelationship[]{rel}));
+        } else {
+            DbEntity dbEnt = getProjectController().getCurrentDbEntity();
+            if (dbEnt != null) {
+
+                DbRelationship rel = new DbRelationship();
+                rel.setName(NameBuilder.builder(rel, dbEnt).name());
+                createDbRelationship(dbEnt, rel);
+
+                application.getUndoManager().addEdit(
+                        new CreateRelationshipUndoableEdit(dbEnt, new DbRelationship[]{rel}));
+            }
+        }
+    }
+
+    public void createObjRelationship(ObjEntity objEntity, ObjRelationship rel) {
+        ProjectController mediator = getProjectController();
+
+        rel.setSourceEntity(objEntity);
+        DeleteRuleUpdater.updateObjRelationship(rel);
+
+        objEntity.addRelationship(rel);
+        fireObjRelationshipEvent(this, mediator, objEntity, rel);
+    }
+
+    public void createDbRelationship(DbEntity dbEntity, DbRelationship rel) {
+        ProjectController mediator = getProjectController();
+
+        rel.setSourceEntity(dbEntity);
+        dbEntity.addRelationship(rel);
+
+        fireDbRelationshipEvent(this, mediator, dbEntity, rel);
+    }
+
+    /**
+     * Returns <code>true</code> if path contains an Entity object.
+     */
+    @Override
+    public boolean enableForPath(ConfigurationNode object) {
+        if (object == null) {
+            return false;
+        }
+
+        if (object instanceof Relationship) {
+            return ((Relationship) object).getParent() != null && ((Relationship) object).getParent() instanceof Entity;
+        }
+
+        return false;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportDataMapAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportDataMapAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportDataMapAction.java
index 3158e90..732963d 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportDataMapAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportDataMapAction.java
@@ -19,20 +19,11 @@
 
 package org.apache.cayenne.modeler.action;
 
-import java.awt.Frame;
-import java.awt.event.ActionEvent;
-import java.io.File;
-import java.io.InputStream;
-import java.net.URL;
-
-import javax.swing.JFileChooser;
-import javax.swing.JOptionPane;
-
+import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.MapLoader;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.pref.FSPath;
 import org.apache.cayenne.modeler.util.CayenneAction;
@@ -42,91 +33,95 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.xml.sax.InputSource;
 
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+
 /**
  * Modeler action that imports a DataMap into a project from an arbitrary
  * location.
- * 
+ *
  * @since 1.1
  */
 public class ImportDataMapAction extends CayenneAction {
 
-	private static Log logObj = LogFactory.getLog(ImportDataMapAction.class);
-
-	public static String getActionName() {
-		return "Import DataMap";
-	}
-
-	public ImportDataMapAction(Application application) {
-		super(getActionName(), application);
-	}
+    private static Log logObj = LogFactory.getLog(ImportDataMapAction.class);
 
-	public void performAction(ActionEvent e) {
-		importDataMap();
-	}
+    public ImportDataMapAction(Application application) {
+        super(getActionName(), application);
+    }
 
-	protected void importDataMap() {
-		File dataMapFile = selectDataMap(Application.getFrame());
-		if (dataMapFile == null) {
-			return;
-		}
+    public static String getActionName() {
+        return "Import DataMap";
+    }
 
-		DataMap newMap;
+    public void performAction(ActionEvent e) {
+        importDataMap();
+    }
 
-		try {
+    protected void importDataMap() {
+        File dataMapFile = selectDataMap(Application.getFrame());
+        if (dataMapFile == null) {
+            return;
+        }
 
-			URL url = dataMapFile.toURI().toURL();
+        DataMap newMap;
 
-			try (InputStream in = url.openStream();) {
-				InputSource inSrc = new InputSource(in);
-				inSrc.setSystemId(dataMapFile.getAbsolutePath());
-				newMap = new MapLoader().loadDataMap(inSrc);
-			}
+        try {
+            URL url = dataMapFile.toURI().toURL();
 
-			DataChannelDescriptor domain = (DataChannelDescriptor) getProjectController().getProject().getRootNode();
+            try (InputStream in = url.openStream();) {
+                InputSource inSrc = new InputSource(in);
+                inSrc.setSystemId(dataMapFile.getAbsolutePath());
+                newMap = new MapLoader().loadDataMap(inSrc);
+            }
 
-			if (newMap.getName() != null) {
-				newMap.setName(DuplicateNameResolver.resolve(NameCheckers.dataMap, domain, newMap.getName()));
-			} else {
-				newMap.setName(DuplicateNameResolver.resolve(NameCheckers.dataMap, domain));
-			}
+            ConfigurationNode root = getProjectController().getProject().getRootNode();
+            newMap.setName(NameBuilder
+                    .builder(newMap, root)
+                    .baseName(newMap.getName())
+                    .name());
 
-			Resource baseResource = domain.getConfigurationSource();
+            Resource baseResource = ((DataChannelDescriptor) root).getConfigurationSource();
 
-			if (baseResource != null) {
-				Resource dataMapResource = baseResource.getRelativeResource(newMap.getName());
-				newMap.setConfigurationSource(dataMapResource);
-			}
+            if (baseResource != null) {
+                Resource dataMapResource = baseResource.getRelativeResource(newMap.getName());
+                newMap.setConfigurationSource(dataMapResource);
+            }
 
-			getProjectController().addDataMap(this, newMap);
-		} catch (Exception ex) {
-			logObj.info("Error importing DataMap.", ex);
-			JOptionPane.showMessageDialog(Application.getFrame(), "Error reading DataMap: " + ex.getMessage(),
-					"Can't Open DataMap", JOptionPane.OK_OPTION);
-		}
-	}
+            getProjectController().addDataMap(this, newMap);
+        } catch (Exception ex) {
+            logObj.info("Error importing DataMap.", ex);
+            JOptionPane.showMessageDialog(Application.getFrame(), "Error reading DataMap: " + ex.getMessage(),
+                    "Can't Open DataMap", JOptionPane.OK_OPTION);
+        }
+    }
 
-	protected File selectDataMap(Frame f) {
+    protected File selectDataMap(Frame f) {
 
-		// find start directory in preferences
-		FSPath lastDir = getApplication().getFrameController().getLastDirectory();
+        // find start directory in preferences
+        FSPath lastDir = getApplication().getFrameController().getLastDirectory();
 
-		// configure dialog
-		JFileChooser chooser = new JFileChooser();
-		chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
-		lastDir.updateChooser(chooser);
+        // configure dialog
+        JFileChooser chooser = new JFileChooser();
+        chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
+        lastDir.updateChooser(chooser);
 
-		chooser.addChoosableFileFilter(FileFilters.getDataMapFilter());
+        chooser.addChoosableFileFilter(FileFilters.getDataMapFilter());
 
-		int status = chooser.showDialog(f, "Select DataMap");
-		if (status == JFileChooser.APPROVE_OPTION) {
-			File file = chooser.getSelectedFile();
+        int status = chooser.showDialog(f, "Select DataMap");
+        if (status == JFileChooser.APPROVE_OPTION) {
+            File file = chooser.getSelectedFile();
 
-			// save to preferences...
-			lastDir.updateFromChooser(chooser);
+            // save to preferences...
+            lastDir.updateFromChooser(chooser);
 
-			return file;
-		}
+            return file;
+        }
 
-		return null;
-	}
+        return null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportEOModelAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportEOModelAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportEOModelAction.java
index 8c5f1c6..75290c6 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportEOModelAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportEOModelAction.java
@@ -19,20 +19,7 @@
 
 package org.apache.cayenne.modeler.action;
 
-import java.awt.Component;
-import java.awt.HeadlessException;
-import java.awt.event.ActionEvent;
-import java.io.File;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Map;
-
-import javax.swing.JDialog;
-import javax.swing.JFileChooser;
-import javax.swing.filechooser.FileFilter;
-
+import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
 import org.apache.cayenne.configuration.event.DataNodeEvent;
@@ -41,12 +28,12 @@ import org.apache.cayenne.configuration.server.JNDIDataSourceFactory;
 import org.apache.cayenne.configuration.server.XMLPoolingDataSourceFactory;
 import org.apache.cayenne.conn.DataSourceInfo;
 import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.Entity;
+import org.apache.cayenne.map.QueryDescriptor;
 import org.apache.cayenne.map.event.EntityEvent;
 import org.apache.cayenne.map.event.MapEvent;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.ProjectController;
 import org.apache.cayenne.modeler.dialog.ErrorDebugDialog;
@@ -56,12 +43,22 @@ import org.apache.cayenne.modeler.pref.FSPath;
 import org.apache.cayenne.modeler.util.AdapterMapping;
 import org.apache.cayenne.modeler.util.CayenneAction;
 import org.apache.cayenne.modeler.util.FileFilters;
-import org.apache.cayenne.map.QueryDescriptor;
 import org.apache.cayenne.wocompat.EOModelProcessor;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import javax.swing.*;
+import javax.swing.filechooser.FileFilter;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
 /**
  * Action handler for WebObjects EOModel import function.
  * 
@@ -301,8 +298,11 @@ public class ImportEOModelAction extends CayenneAction {
         }
         else {
             // fix DataMap name, as there maybe a map with the same name already
-            DataChannelDescriptor domain = (DataChannelDescriptor) mediator.getProject().getRootNode();
-            map.setName(DuplicateNameResolver.resolve(NameCheckers.dataMap, domain, map.getName()));
+            ConfigurationNode root = (DataChannelDescriptor) mediator.getProject().getRootNode();
+            map.setName(NameBuilder
+                    .builder(map, root)
+                    .baseName(map.getName())
+                    .name());
 
             // side effect of this operation is that if a node was created, this DataMap
             // will be linked with it...

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/NewProjectAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/NewProjectAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/NewProjectAction.java
index 468ff1d..b5bbbc5 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/NewProjectAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/NewProjectAction.java
@@ -19,23 +19,19 @@
 
 package org.apache.cayenne.modeler.action;
 
-import java.awt.Toolkit;
-import java.awt.event.ActionEvent;
-import java.awt.event.KeyEvent;
-
-import javax.swing.KeyStroke;
-
 import org.apache.cayenne.configuration.ConfigurationTree;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.CayenneModelerController;
 import org.apache.cayenne.modeler.event.DomainDisplayEvent;
 import org.apache.cayenne.project.Project;
 
-/**
- */
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+
 public class NewProjectAction extends ProjectAction {
 
     public static String getActionName() {
@@ -66,17 +62,18 @@ public class NewProjectAction extends ProjectAction {
             return;
         }
 
-        DataChannelDescriptor domain = new DataChannelDescriptor();
+        DataChannelDescriptor dataChannelDescriptor = new DataChannelDescriptor();
 
-        domain.setName(DuplicateNameResolver.resolve(NameCheckers.dataChannelDescriptor, domain));
+        dataChannelDescriptor.setName(NameBuilder
+                .builder(dataChannelDescriptor)
+                .name());
 
         Project project = new Project(
-                new ConfigurationTree<DataChannelDescriptor>(domain));
+                new ConfigurationTree<DataChannelDescriptor>(dataChannelDescriptor));
 
         controller.projectOpenedAction(project);
 
         // select default domain
-        getProjectController().fireDomainDisplayEvent(
-                new DomainDisplayEvent(this, domain));
+        getProjectController().fireDomainDisplayEvent(new DomainDisplayEvent(this, dataChannelDescriptor));
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/38e4e7fd/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/PasteAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/PasteAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/PasteAction.java
index a146307..cf835ef 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/PasteAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/PasteAction.java
@@ -21,6 +21,7 @@ package org.apache.cayenne.modeler.action;
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
@@ -34,9 +35,8 @@ import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.ObjRelationship;
 import org.apache.cayenne.map.Procedure;
 import org.apache.cayenne.map.ProcedureParameter;
+import org.apache.cayenne.map.QueryDescriptor;
 import org.apache.cayenne.map.event.MapEvent;
-import org.apache.cayenne.dbsync.naming.DuplicateNameResolver;
-import org.apache.cayenne.dbsync.naming.NameCheckers;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.ProjectController;
 import org.apache.cayenne.modeler.dialog.ErrorDebugDialog;
@@ -48,11 +48,10 @@ import org.apache.cayenne.modeler.undo.PasteUndoableEdit;
 import org.apache.cayenne.modeler.util.CayenneAction;
 import org.apache.cayenne.modeler.util.CayenneTransferable;
 import org.apache.cayenne.query.Query;
-import org.apache.cayenne.map.QueryDescriptor;
 
-import javax.swing.KeyStroke;
+import javax.swing.*;
 import javax.swing.undo.UndoableEdit;
-import java.awt.Toolkit;
+import java.awt.*;
 import java.awt.datatransfer.FlavorEvent;
 import java.awt.datatransfer.FlavorListener;
 import java.awt.datatransfer.UnsupportedFlavorException;
@@ -69,10 +68,6 @@ public class PasteAction extends CayenneAction implements FlavorListener {
 
     private static final String COPY_PATTERN = "Copy of %s (%d)";
 
-    public static String getActionName() {
-        return "Paste";
-    }
-
     /**
      * Constructor for PasteAction
      */
@@ -84,6 +79,10 @@ public class PasteAction extends CayenneAction implements FlavorListener {
         Toolkit.getDefaultToolkit().getSystemClipboard().addFlavorListener(this);
     }
 
+    public static String getActionName() {
+        return "Paste";
+    }
+
     @Override
     public String getIconName() {
         return "icon-paste.gif";
@@ -125,19 +124,16 @@ public class PasteAction extends CayenneAction implements FlavorListener {
                                 currentObject,
                                 o));
                     }
-                }
-                else {
+                } else {
                     paste(currentObject, content);
                     undoableEdit = new PasteUndoableEdit(domain, map, currentObject, content);
                 }
 
                 application.getUndoManager().addEdit(undoableEdit);
             }
-        }
-        catch (UnsupportedFlavorException ufe) {
+        } catch (UnsupportedFlavorException ufe) {
             // do nothing
-        }
-        catch (Exception ex) {
+        } catch (Exception ex) {
             ErrorDebugDialog.guiException(ex);
         }
     }
@@ -154,7 +150,7 @@ public class PasteAction extends CayenneAction implements FlavorListener {
     public void paste(
             Object where,
             Object content,
-            DataChannelDescriptor domain,
+            DataChannelDescriptor dataChannelDescriptor,
             DataMap map) {
         final ProjectController mediator = getProjectController();
 
@@ -171,7 +167,11 @@ public class PasteAction extends CayenneAction implements FlavorListener {
             // paste DataMap to DataDomain or DataNode
             DataMap dataMap = ((DataMap) content);
 
-            dataMap.setName(DuplicateNameResolver.resolve(NameCheckers.dataMap, COPY_PATTERN, domain, dataMap.getName()));
+            dataMap.setName(NameBuilder
+                    .builder(dataMap, dataChannelDescriptor)
+                    .baseName(dataMap.getName())
+                    .dupesPattern(COPY_PATTERN)
+                    .name());
 
             /**
              * Update all names in the new DataMap, so that they would not conflict with
@@ -182,20 +182,28 @@ public class PasteAction extends CayenneAction implements FlavorListener {
             // to it as well
             Map<String, String> renamedDbEntities = new HashMap<>();
             Map<String, String> renamedObjEntities = new HashMap<>();
-
             Map<String, String> renamedEmbeddables = new HashMap<>();
 
             for (DbEntity dbEntity : dataMap.getDbEntities()) {
                 String oldName = dbEntity.getName();
-                dbEntity.setName(DuplicateNameResolver.resolve(NameCheckers.dbEntity, COPY_PATTERN, dataMap, dbEntity.getName()));
+                dbEntity.setName(NameBuilder
+                        .builder(dbEntity, dataMap)
+                        .baseName(dbEntity.getName())
+                        .dupesPattern(COPY_PATTERN)
+                        .name());
 
                 if (!oldName.equals(dbEntity.getName())) {
                     renamedDbEntities.put(oldName, dbEntity.getName());
                 }
             }
+
             for (ObjEntity objEntity : dataMap.getObjEntities()) {
                 String oldName = objEntity.getName();
-                objEntity.setName(DuplicateNameResolver.resolve(NameCheckers.objEntity, COPY_PATTERN, dataMap, objEntity.getName()));
+                objEntity.setName(NameBuilder
+                        .builder(objEntity, dataMap)
+                        .baseName(objEntity.getName())
+                        .dupesPattern(COPY_PATTERN)
+                        .name());
 
                 if (!oldName.equals(objEntity.getName())) {
                     renamedObjEntities.put(oldName, objEntity.getName());
@@ -204,7 +212,11 @@ public class PasteAction extends CayenneAction implements FlavorListener {
 
             for (Embeddable embeddable : dataMap.getEmbeddables()) {
                 String oldName = embeddable.getClassName();
-                embeddable.setClassName(DuplicateNameResolver.resolve(NameCheckers.embeddable, COPY_PATTERN, dataMap, embeddable.getClassName()));
+                embeddable.setClassName(NameBuilder
+                        .builder(embeddable, dataMap)
+                        .baseName(embeddable.getClassName())
+                        .dupesPattern(COPY_PATTERN)
+                        .name());
 
                 if (!oldName.equals(embeddable.getClassName())) {
                     renamedEmbeddables.put(oldName, embeddable.getClassName());
@@ -212,10 +224,18 @@ public class PasteAction extends CayenneAction implements FlavorListener {
             }
 
             for (Procedure procedure : dataMap.getProcedures()) {
-                procedure.setName(DuplicateNameResolver.resolve(NameCheckers.procedure, COPY_PATTERN, dataMap, procedure.getName()));
+                procedure.setName(NameBuilder
+                        .builder(procedure, dataMap)
+                        .baseName(procedure.getName())
+                        .dupesPattern(COPY_PATTERN)
+                        .name());
             }
+
             for (QueryDescriptor query : dataMap.getQueryDescriptors()) {
-                query.setName(DuplicateNameResolver.resolve(NameCheckers.query, COPY_PATTERN, dataMap, query.getName()));
+                query.setName(NameBuilder.builder(query, dataMap)
+                        .baseName(query.getName())
+                        .dupesPattern(COPY_PATTERN)
+                        .name());
             }
 
             // if an entity was renamed, we rename all links to it too
@@ -247,8 +267,7 @@ public class PasteAction extends CayenneAction implements FlavorListener {
             }
 
             mediator.addDataMap(this, dataMap);
-        }
-        else if (where instanceof DataMap) {
+        } else if (where instanceof DataMap) {
             // paste DbEntity to DataMap
             final DataMap dataMap = ((DataMap) where);
 
@@ -257,15 +276,21 @@ public class PasteAction extends CayenneAction implements FlavorListener {
 
             if (content instanceof DbEntity) {
                 DbEntity dbEntity = (DbEntity) content;
-                dbEntity.setName(DuplicateNameResolver.resolve(NameCheckers.dbEntity, COPY_PATTERN, dataMap, dbEntity.getName()));
+                dbEntity.setName(NameBuilder
+                        .builder(dbEntity, dataMap)
+                        .baseName(dbEntity.getName())
+                        .dupesPattern(COPY_PATTERN)
+                        .name());
 
                 dataMap.addDbEntity(dbEntity);
                 CreateDbEntityAction.fireDbEntityEvent(this, mediator, dbEntity);
-            }
-            else if (content instanceof ObjEntity) {
+            } else if (content instanceof ObjEntity) {
                 // paste ObjEntity to DataMap
                 ObjEntity objEntity = (ObjEntity) content;
-                objEntity.setName(DuplicateNameResolver.resolve(NameCheckers.objEntity, COPY_PATTERN, dataMap, objEntity.getName()));
+                objEntity.setName(NameBuilder.builder(objEntity, dataMap)
+                        .baseName(objEntity.getName())
+                        .dupesPattern(COPY_PATTERN)
+                        .name());
 
                 dataMap.addObjEntity(objEntity);
                 CreateObjEntityAction.fireObjEntityEvent(
@@ -273,11 +298,14 @@ public class PasteAction extends CayenneAction implements FlavorListener {
                         mediator,
                         dataMap,
                         objEntity);
-            }
-            else if (content instanceof Embeddable) {
+            } else if (content instanceof Embeddable) {
                 // paste Embeddable to DataMap
                 Embeddable embeddable = (Embeddable) content;
-                embeddable.setClassName(DuplicateNameResolver.resolve(NameCheckers.embeddable, COPY_PATTERN, dataMap, embeddable.getClassName()));
+                embeddable.setClassName(NameBuilder
+                        .builder(embeddable, dataMap)
+                        .baseName(embeddable.getClassName())
+                        .dupesPattern(COPY_PATTERN)
+                        .name());
 
                 dataMap.addEmbeddable(embeddable);
                 CreateEmbeddableAction.fireEmbeddableEvent(
@@ -285,20 +313,26 @@ public class PasteAction extends CayenneAction implements FlavorListener {
                         mediator,
                         dataMap,
                         embeddable);
-            }
-            else if (content instanceof QueryDescriptor) {
+            } else if (content instanceof QueryDescriptor) {
                 QueryDescriptor query = (QueryDescriptor) content;
 
-                query.setName(DuplicateNameResolver.resolve(NameCheckers.query, COPY_PATTERN, dataMap, query.getName()));
+                query.setName(NameBuilder
+                        .builder(query, dataMap)
+                        .dupesPattern(COPY_PATTERN)
+                        .baseName(query.getName())
+                        .name());
                 query.setDataMap(dataMap);
 
                 dataMap.addQueryDescriptor(query);
                 QueryType.fireQueryEvent(this, mediator, dataMap, query);
-            }
-            else if (content instanceof Procedure) {
+            } else if (content instanceof Procedure) {
                 // paste Procedure to DataMap
                 Procedure procedure = (Procedure) content;
-                procedure.setName(DuplicateNameResolver.resolve(NameCheckers.procedure, COPY_PATTERN, dataMap, procedure.getName()));
+                procedure.setName(NameBuilder
+                        .builder(procedure, dataMap)
+                        .dupesPattern(COPY_PATTERN)
+                        .baseName(procedure.getName())
+                        .name());
 
                 dataMap.addProcedure(procedure);
                 CreateProcedureAction.fireProcedureEvent(
@@ -307,21 +341,27 @@ public class PasteAction extends CayenneAction implements FlavorListener {
                         dataMap,
                         procedure);
             }
-        }
-        else if (where instanceof DbEntity) {
+        } else if (where instanceof DbEntity) {
             final DbEntity dbEntity = (DbEntity) where;
 
             if (content instanceof DbAttribute) {
                 DbAttribute attr = (DbAttribute) content;
-                attr.setName(DuplicateNameResolver.resolve(NameCheckers.dbAttribute, COPY_PATTERN, dbEntity, attr.getName()));
+                attr.setName(NameBuilder
+                        .builder(attr, dbEntity)
+                        .dupesPattern(COPY_PATTERN)
+                        .baseName(attr.getName())
+                        .name());
 
                 dbEntity.addAttribute(attr);
                 CreateAttributeAction.fireDbAttributeEvent(this, mediator, mediator
                         .getCurrentDataMap(), dbEntity, attr);
-            }
-            else if (content instanceof DbRelationship) {
+            } else if (content instanceof DbRelationship) {
                 DbRelationship rel = (DbRelationship) content;
-                rel.setName(DuplicateNameResolver.resolve(NameCheckers.dbRelationship, COPY_PATTERN, dbEntity, rel.getName()));
+                rel.setName(NameBuilder
+                        .builder(rel, dbEntity)
+                        .baseName(rel.getName())
+                        .dupesPattern(COPY_PATTERN)
+                        .name());
 
                 dbEntity.addRelationship(rel);
                 CreateRelationshipAction.fireDbRelationshipEvent(
@@ -330,22 +370,27 @@ public class PasteAction extends CayenneAction implements FlavorListener {
                         dbEntity,
                         rel);
             }
-        }
-        else if (where instanceof ObjEntity) {
-            final ObjEntity objEntity = (ObjEntity) where;
-
+        } else if (where instanceof ObjEntity) {
+            ObjEntity objEntity = (ObjEntity) where;
 
             if (content instanceof ObjAttribute) {
                 ObjAttribute attr = (ObjAttribute) content;
-                attr.setName(DuplicateNameResolver.resolve(NameCheckers.objAttribute, COPY_PATTERN, objEntity, attr.getName()));
+                attr.setName(NameBuilder
+                        .builder(attr, objEntity)
+                        .baseName(attr.getName())
+                        .dupesPattern(COPY_PATTERN)
+                        .name());
 
                 objEntity.addAttribute(attr);
                 CreateAttributeAction.fireObjAttributeEvent(this, mediator, mediator
                         .getCurrentDataMap(), objEntity, attr);
-            }
-            else if (content instanceof ObjRelationship) {
+            } else if (content instanceof ObjRelationship) {
                 ObjRelationship rel = (ObjRelationship) content;
-                rel.setName(DuplicateNameResolver.resolve(NameCheckers.objRelationship, COPY_PATTERN, objEntity, rel.getName()));
+                rel.setName(NameBuilder
+                        .builder(rel, objEntity)
+                        .baseName(rel.getName())
+                        .dupesPattern(COPY_PATTERN)
+                        .name());
 
                 objEntity.addRelationship(rel);
                 CreateRelationshipAction.fireObjRelationshipEvent(
@@ -353,13 +398,18 @@ public class PasteAction extends CayenneAction implements FlavorListener {
                         mediator,
                         objEntity,
                         rel);
-            }
-            else if(content instanceof ObjCallbackMethod) {
+            } else if (content instanceof ObjCallbackMethod) {
                 ObjCallbackMethod method = (ObjCallbackMethod) content;
 
-                method.setName(DuplicateNameResolver.resolve(NameCheckers.objCallbackMethod, COPY_PATTERN, objEntity, method.getName()));
-                
-                objEntity.getCallbackMap().getCallbackDescriptor(mediator.getCurrentCallbackType().getType()).addCallbackMethod(method.getName());
+                method.setName(NameBuilder
+                        .builderForCallbackMethod(objEntity)
+                        .baseName(method.getName())
+                        .dupesPattern(COPY_PATTERN)
+                        .name());
+
+                objEntity.getCallbackMap()
+                        .getCallbackDescriptor(mediator.getCurrentCallbackType().getType())
+                        .addCallbackMethod(method.getName());
 
                 CallbackMethodEvent ce = new CallbackMethodEvent(
                         this,
@@ -369,14 +419,16 @@ public class PasteAction extends CayenneAction implements FlavorListener {
 
                 getProjectController().fireCallbackMethodEvent(ce);
             }
-        }
-
-        else if (where instanceof Embeddable) {
+        } else if (where instanceof Embeddable) {
             final Embeddable embeddable = (Embeddable) where;
 
             if (content instanceof EmbeddableAttribute) {
                 EmbeddableAttribute attr = (EmbeddableAttribute) content;
-                attr.setName(DuplicateNameResolver.resolve(NameCheckers.embeddableAttribute, COPY_PATTERN, embeddable, attr.getName()));
+                attr.setName(NameBuilder
+                        .builder(attr, embeddable)
+                        .baseName(attr.getName())
+                        .dupesPattern(COPY_PATTERN)
+                        .name());
 
                 embeddable.addAttribute(attr);
                 CreateAttributeAction.fireEmbeddableAttributeEvent(
@@ -386,16 +438,18 @@ public class PasteAction extends CayenneAction implements FlavorListener {
                         attr);
             }
 
-        }
-
-        else if (where instanceof Procedure) {
+        } else if (where instanceof Procedure) {
             // paste param to procedure
             final Procedure procedure = (Procedure) where;
 
             if (content instanceof ProcedureParameter) {
                 ProcedureParameter param = (ProcedureParameter) content;
 
-                param.setName(DuplicateNameResolver.resolve(NameCheckers.procedureParameter, COPY_PATTERN, procedure, param.getName()));
+                param.setName(NameBuilder
+                        .builder(param, procedure)
+                        .baseName(param.getName())
+                        .dupesPattern(COPY_PATTERN)
+                        .name());
 
                 procedure.addCallParameter(param);
                 CreateProcedureParameterAction.fireProcedureParameterEvent(
@@ -476,9 +530,8 @@ public class PasteAction extends CayenneAction implements FlavorListener {
                     (currentObject instanceof Procedure
                             && (content instanceof ProcedureParameter || isTreeLeaf(content)) ||
 
-                    (currentObject instanceof Query && isTreeLeaf(content)));
-        }
-        catch (Exception ex) {
+                            (currentObject instanceof Query && isTreeLeaf(content)));
+        } catch (Exception ex) {
             return false;
         }
     }