You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2017/07/25 12:25:31 UTC

[16/16] cayenne git commit: CAY-2335: New XML loading/saving mechanics with support of plugable handlers - Cleanup and fix - Update Modeler

CAY-2335: New XML loading/saving mechanics with support of plugable handlers
  - Cleanup and fix
  - Update Modeler


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

Branch: refs/heads/master
Commit: d608777a919f3807267c16dc3db0f70fcd24328b
Parents: 70ca356
Author: Nikita Timofeev <st...@gmail.com>
Authored: Tue Jul 25 15:00:13 2017 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Tue Jul 25 15:00:13 2017 +0300

----------------------------------------------------------------------
 .../cayenne/gen/ClassGenerationAction.java      |  2 +-
 .../gen/ClientClassGenerationAction.java        | 10 +-
 .../reverse/configuration/ToolsModule.java      |  3 +
 .../dbsync/reverse/dbimport/DbImportModule.java | 15 ++-
 .../reverse/dbimport/DefaultDbImportAction.java | 12 +--
 .../dbimport/DefaultDbImportActionTest.java     | 29 +++---
 .../dbimport/ManyToManyCandidateEntityTest.java | 10 +-
 .../apache/cayenne/project/ProjectModule.java   |  4 +-
 .../project/extension/ProjectExtension.java     |  3 +-
 .../project/upgrade/v7/ProjectUpgrader_V7.java  | 42 ---------
 .../project/upgrade/v9/ProjectUpgrader_V9.java  | 44 ---------
 .../org/apache/cayenne/modeler/Application.java |  8 ++
 .../modeler/ProjectFileChangeTracker.java       |  5 +-
 .../cayenne/modeler/action/CopyAction.java      |  3 +-
 .../modeler/action/ImportDataMapAction.java     | 13 +--
 .../modeler/action/OpenProjectAction.java       | 96 ++++++++++----------
 .../dialog/codegen/CustomModeController.java    |  4 +-
 .../dialog/codegen/GeneratorController.java     |  4 +-
 .../dialog/codegen/StandardModeController.java  |  4 +-
 .../dialog/db/load/ModelerDbImportAction.java   |  4 +-
 .../modeler/editor/ObjCallbackMethod.java       |  3 +-
 .../cayenne/modeler/graph/BaseGraphBuilder.java |  4 +-
 .../cayenne/modeler/graph/GraphBuilder.java     | 16 ++--
 .../apache/cayenne/modeler/graph/GraphMap.java  |  6 +-
 .../modeler/init/CayenneModelerModule.java      |  6 ++
 .../modeler/util/CayenneTransferable.java       | 14 +--
 26 files changed, 159 insertions(+), 205 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java
----------------------------------------------------------------------
diff --git a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java
index 8d08c52..e86bcba 100644
--- a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java
+++ b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java
@@ -522,7 +522,7 @@ public class ClassGenerationAction {
 	 *
 	 * @since 4.0 throws exception
 	 */
-	public void addEntities(Collection<ObjEntity> entities) throws CayenneException {
+	public void addEntities(Collection<ObjEntity> entities) throws CayenneRuntimeException {
 		if (artifactsGenerationMode == ArtifactsGenerationMode.ENTITY
 				|| artifactsGenerationMode == ArtifactsGenerationMode.ALL) {
 			if (entities != null) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClientClassGenerationAction.java
----------------------------------------------------------------------
diff --git a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClientClassGenerationAction.java b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClientClassGenerationAction.java
index bca02a2..c944f40 100644
--- a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClientClassGenerationAction.java
+++ b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClientClassGenerationAction.java
@@ -21,7 +21,7 @@ package org.apache.cayenne.gen;
 
 import java.util.Collection;
 
-import org.apache.cayenne.CayenneException;
+import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.QueryDescriptor;
 
@@ -70,16 +70,12 @@ public class ClientClassGenerationAction extends ClassGenerationAction {
     }
 
     /**
-     *
-     * @param entities
-     * @throws CayenneException
-     *
      * @since 4.0 throws exception
      */
     @Override
-    public void addEntities(Collection<ObjEntity> entities) throws CayenneException {
+    public void addEntities(Collection<ObjEntity> entities) throws CayenneRuntimeException {
         if (!dataMap.isClientSupported()) {
-            throw new CayenneException("Can't create client classes. Check client supported option on DataMap configuration.");
+            throw new CayenneRuntimeException("Can't create client classes. Check client supported option on DataMap configuration.");
         }
         if (entities != null) {
             for (ObjEntity entity : entities) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
index dc057dc..bd6ae66 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
@@ -58,6 +58,7 @@ import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory;
 import org.apache.cayenne.di.spi.DefaultClassLoaderManager;
 import org.apache.cayenne.log.Slf4jJdbcEventLogger;
 import org.apache.cayenne.log.JdbcEventLogger;
+import org.apache.cayenne.project.ProjectModule;
 import org.apache.cayenne.project.extension.ExtensionAwareHandlerFactory;
 import org.apache.cayenne.resource.ClassLoaderResourceLocator;
 import org.apache.cayenne.resource.ResourceLocator;
@@ -116,6 +117,8 @@ public class ToolsModule implements Module {
         binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
         binder.bind(HandlerFactory.class).to(ExtensionAwareHandlerFactory.class);
         binder.bind(DataChannelMetaData.class).to(DefaultDataChannelMetaData.class);
+
+        ProjectModule.contributeExtensions(binder);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportModule.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportModule.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportModule.java
index f709886..7cb227c 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportModule.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportModule.java
@@ -20,12 +20,19 @@
 package org.apache.cayenne.dbsync.reverse.dbimport;
 
 import org.apache.cayenne.configuration.ConfigurationNameMapper;
+import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.DefaultConfigurationNameMapper;
+import org.apache.cayenne.configuration.xml.DataChannelMetaData;
+import org.apache.cayenne.configuration.xml.DefaultDataChannelMetaData;
+import org.apache.cayenne.configuration.xml.DefaultHandlerFactory;
+import org.apache.cayenne.configuration.xml.HandlerFactory;
+import org.apache.cayenne.configuration.xml.XMLDataMapLoader;
 import org.apache.cayenne.di.Binder;
 import org.apache.cayenne.di.Module;
-import org.apache.cayenne.map.MapLoader;
 import org.apache.cayenne.project.FileProjectSaver;
+import org.apache.cayenne.project.ProjectModule;
 import org.apache.cayenne.project.ProjectSaver;
+import org.apache.cayenne.project.extension.ExtensionAwareHandlerFactory;
 
 /**
  * A DI module that bootstraps {@link DbImportAction}.
@@ -40,7 +47,11 @@ public class DbImportModule implements Module {
         binder.bind(DbImportAction.class).to(DefaultDbImportAction.class);
         binder.bind(ProjectSaver.class).to(FileProjectSaver.class);
         binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
-        binder.bind(MapLoader.class).to(MapLoader.class);
+        binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
+        binder.bind(HandlerFactory.class).to(DefaultHandlerFactory.class);
+        binder.bind(DataChannelMetaData.class).to(DefaultDataChannelMetaData.class);
+        binder.bind(HandlerFactory.class).to(ExtensionAwareHandlerFactory.class);
+        ProjectModule.contributeExtensions(binder);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
index 3ada4bd..c31aaab 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
@@ -19,6 +19,7 @@
 package org.apache.cayenne.dbsync.reverse.dbimport;
 
 import org.apache.cayenne.configuration.ConfigurationTree;
+import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
 import org.apache.cayenne.configuration.server.DataSourceFactory;
 import org.apache.cayenne.configuration.server.DbAdapterFactory;
@@ -41,7 +42,6 @@ import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.map.MapLoader;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.ObjRelationship;
 import org.apache.cayenne.map.Procedure;
@@ -52,7 +52,6 @@ import org.apache.cayenne.validation.SimpleValidationFailure;
 import org.apache.cayenne.validation.ValidationFailure;
 import org.apache.cayenne.validation.ValidationResult;
 import org.slf4j.Logger;
-import org.xml.sax.InputSource;
 
 import javax.sql.DataSource;
 import java.io.File;
@@ -76,14 +75,14 @@ public class DefaultDbImportAction implements DbImportAction {
     private final Logger logger;
     private final DataSourceFactory dataSourceFactory;
     private final DbAdapterFactory adapterFactory;
-    private final MapLoader mapLoader;
+    private final DataMapLoader mapLoader;
     private final MergerTokenFactoryProvider mergerTokenFactoryProvider;
 
     public DefaultDbImportAction(@Inject Logger logger,
                                  @Inject ProjectSaver projectSaver,
                                  @Inject DataSourceFactory dataSourceFactory,
                                  @Inject DbAdapterFactory adapterFactory,
-                                 @Inject MapLoader mapLoader,
+                                 @Inject DataMapLoader mapLoader,
                                  @Inject MergerTokenFactoryProvider mergerTokenFactoryProvider) {
         this.logger = logger;
         this.projectSaver = projectSaver;
@@ -240,9 +239,10 @@ public class DefaultDbImportAction implements DbImportAction {
 
         File file = configuration.getTargetDataMap();
         if (file != null && file.exists() && file.canRead()) {
-            DataMap dataMap = mapLoader.loadDataMap(new InputSource(file.getCanonicalPath()));
+            URLResource configurationResource = new URLResource(file.toURI().toURL());
+            DataMap dataMap = mapLoader.load(configurationResource);
             dataMap.setNamespace(new EntityResolver(Collections.singleton(dataMap)));
-            dataMap.setConfigurationSource(new URLResource(file.toURI().toURL()));
+            dataMap.setConfigurationSource(configurationResource);
 
             return dataMap;
         }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java
index 9224519..df8f8b1 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java
@@ -19,9 +19,11 @@
 package org.apache.cayenne.dbsync.reverse.dbimport;
 
 import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
 import org.apache.cayenne.configuration.server.DataSourceFactory;
 import org.apache.cayenne.configuration.server.DbAdapterFactory;
+import org.apache.cayenne.configuration.xml.DataChannelMetaData;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dbsync.DbSyncModule;
 import org.apache.cayenne.dbsync.filter.NamePatternMatcher;
@@ -45,21 +47,22 @@ import org.apache.cayenne.di.DIBootstrap;
 import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.MapLoader;
 import org.apache.cayenne.project.FileProjectSaver;
 import org.apache.cayenne.project.Project;
+import org.apache.cayenne.project.extension.ProjectExtension;
+import org.apache.cayenne.resource.Resource;
 import org.apache.cayenne.resource.URLResource;
 import org.apache.cayenne.util.Util;
 import org.slf4j.Logger;
 import org.junit.Before;
 import org.junit.Test;
-import org.xml.sax.InputSource;
 
 import javax.sql.DataSource;
 import java.io.File;
 import java.net.URL;
 import java.sql.Connection;
 import java.sql.SQLException;
+import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -129,7 +132,7 @@ public class DefaultDbImportActionTest {
         };
 
         final boolean[] haveWeTriedToSave = {false};
-        DefaultDbImportAction action = buildDbImportAction(new FileProjectSaver() {
+        DefaultDbImportAction action = buildDbImportAction(new FileProjectSaver(Collections.<ProjectExtension>emptyList()) {
             @Override
             public void save(Project project) {
                 haveWeTriedToSave[0] = true;
@@ -175,7 +178,7 @@ public class DefaultDbImportActionTest {
 
         final boolean[] haveWeTriedToSave = {false};
         DefaultDbImportAction action = buildDbImportAction(
-            new FileProjectSaver() {
+            new FileProjectSaver(Collections.<ProjectExtension>emptyList()) {
                 @Override
                 public void save(Project project) {
                     haveWeTriedToSave[0] = true;
@@ -192,9 +195,9 @@ public class DefaultDbImportActionTest {
                 }
             },
 
-            new MapLoader() {
+            new DataMapLoader() {
                 @Override
-                public synchronized DataMap loadDataMap(InputSource src) throws CayenneRuntimeException {
+                public DataMap load(Resource configurationResource) throws CayenneRuntimeException {
                     return new DataMapBuilder().with(
                             dbEntity("ARTGROUP").attributes(
                                     dbAttr("GROUP_ID").typeInt().primaryKey(),
@@ -236,8 +239,8 @@ public class DefaultDbImportActionTest {
         FileProjectSaver projectSaver = mock(FileProjectSaver.class);
         doNothing().when(projectSaver).save(any(Project.class));
 
-        MapLoader mapLoader = mock(MapLoader.class);
-        when(mapLoader.loadDataMap(any(InputSource.class))).thenReturn(new DataMapBuilder().with(
+        DataMapLoader mapLoader = mock(DataMapLoader.class);
+        when(mapLoader.load(any(Resource.class))).thenReturn(new DataMapBuilder().with(
                 dbEntity("ARTGROUP").attributes(
                         dbAttr("NAME").typeVarchar(100).mandatory()
                 )).build());
@@ -248,7 +251,7 @@ public class DefaultDbImportActionTest {
 
         // no changes - we still
         verify(projectSaver, never()).save(any(Project.class));
-        verify(mapLoader, times(1)).loadDataMap(any(InputSource.class));
+        verify(mapLoader, times(1)).load(any(Resource.class));
     }
 
     @Test
@@ -261,8 +264,8 @@ public class DefaultDbImportActionTest {
         FileProjectSaver projectSaver = mock(FileProjectSaver.class);
         doNothing().when(projectSaver).save(any(Project.class));
 
-        MapLoader mapLoader = mock(MapLoader.class);
-        when(mapLoader.loadDataMap(any(InputSource.class))).thenReturn(null);
+        DataMapLoader mapLoader = mock(DataMapLoader.class);
+        when(mapLoader.load(any(Resource.class))).thenReturn(null);
 
         DefaultDbImportAction action = buildDbImportAction(projectSaver, mapLoader, dbLoader);
 
@@ -274,10 +277,10 @@ public class DefaultDbImportActionTest {
         }
 
         verify(projectSaver, never()).save(any(Project.class));
-        verify(mapLoader, never()).loadDataMap(any(InputSource.class));
+        verify(mapLoader, never()).load(any(Resource.class));
     }
 
-    private DefaultDbImportAction buildDbImportAction(FileProjectSaver projectSaver, MapLoader mapLoader, final DbLoader dbLoader)
+    private DefaultDbImportAction buildDbImportAction(FileProjectSaver projectSaver, DataMapLoader mapLoader, final DbLoader dbLoader)
             throws Exception {
 
         Logger log = mock(Logger.class);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/ManyToManyCandidateEntityTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/ManyToManyCandidateEntityTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/ManyToManyCandidateEntityTest.java
index ca255ff..3d064e5 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/ManyToManyCandidateEntityTest.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/ManyToManyCandidateEntityTest.java
@@ -24,8 +24,12 @@ import org.apache.cayenne.configuration.ConfigurationTree;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.DefaultConfigurationNameMapper;
-import org.apache.cayenne.configuration.XMLDataChannelDescriptorLoader;
-import org.apache.cayenne.configuration.XMLDataMapLoader;
+import org.apache.cayenne.configuration.xml.DataChannelMetaData;
+import org.apache.cayenne.configuration.xml.DefaultHandlerFactory;
+import org.apache.cayenne.configuration.xml.HandlerFactory;
+import org.apache.cayenne.configuration.xml.NoopDataChannelMetaData;
+import org.apache.cayenne.configuration.xml.XMLDataChannelDescriptorLoader;
+import org.apache.cayenne.configuration.xml.XMLDataMapLoader;
 import org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator;
 import org.apache.cayenne.dbsync.naming.NoStemStemmer;
 import org.apache.cayenne.di.AdhocObjectFactory;
@@ -63,6 +67,8 @@ public class ManyToManyCandidateEntityTest {
                 binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
                 binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
                 binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
+                binder.bind(HandlerFactory.class).to(DefaultHandlerFactory.class);
+                binder.bind(DataChannelMetaData.class).to(NoopDataChannelMetaData.class);
             }
         };
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java b/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java
index 8f5d011..614d4ed 100644
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java
@@ -43,7 +43,7 @@ public class ProjectModule implements Module {
     /**
      * @since 4.1
      */
-    public static ListBuilder<ProjectExtension> contributeExtension(Binder binder) {
+    public static ListBuilder<ProjectExtension> contributeExtensions(Binder binder) {
         return binder.bindList(ProjectExtension.class);
     }
 
@@ -68,6 +68,6 @@ public class ProjectModule implements Module {
                 .add(UpgradeHandler_V9.class)
                 .add(UpgradeHandler_V10.class);
 
-        contributeExtension(binder);
+        contributeExtensions(binder);
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-project/src/main/java/org/apache/cayenne/project/extension/ProjectExtension.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/extension/ProjectExtension.java b/cayenne-project/src/main/java/org/apache/cayenne/project/extension/ProjectExtension.java
index 1bfa33e..cf0a182 100644
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/extension/ProjectExtension.java
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/extension/ProjectExtension.java
@@ -27,11 +27,10 @@ package org.apache.cayenne.project.extension;
  *     ClientRuntime so they can safely store big chunks of data.
  * </p>
  * <p>
- *     Extensions can be contributed by {@link org.apache.cayenne.project.ProjectModule#contributeExtension(org.apache.cayenne.di.Binder)}.
+ *     Extensions can be contributed by {@link org.apache.cayenne.project.ProjectModule#contributeExtensions(org.apache.cayenne.di.Binder)}.
  *     {@link org.apache.cayenne.project.ProjectModule} currently used by Modeler and cli tools, e.g. cdbimport and cgen.
  * </p>
  *
- * @see org.apache.cayenne.project.extension.info.InfoExtension as reference implementation
  * @since 4.1
  */
 public interface ProjectExtension {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v7/ProjectUpgrader_V7.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v7/ProjectUpgrader_V7.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v7/ProjectUpgrader_V7.java
deleted file mode 100644
index c107fce..0000000
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v7/ProjectUpgrader_V7.java
+++ /dev/null
@@ -1,42 +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.project.upgrade.v7;
-
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.project.upgrade.ProjectUpgrader;
-import org.apache.cayenne.project.upgrade.UpgradeHandler;
-import org.apache.cayenne.resource.Resource;
-
-/**
- * A ProjectUpgrader that handles project upgrades from version 3.0.0.1 and 6
- * to version 7
- */
-public class ProjectUpgrader_V7 implements ProjectUpgrader {
-
-    @Inject
-    protected Injector injector;
-
-    public UpgradeHandler getUpgradeHandler(Resource projectSource) {
-        UpgradeHandler_V7 handler = new UpgradeHandler_V7(projectSource);
-        injector.injectMembers(handler);
-        return handler;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v9/ProjectUpgrader_V9.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v9/ProjectUpgrader_V9.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v9/ProjectUpgrader_V9.java
deleted file mode 100644
index 2f585b2..0000000
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/v9/ProjectUpgrader_V9.java
+++ /dev/null
@@ -1,44 +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.project.upgrade.v9;
-
-
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.project.upgrade.ProjectUpgrader;
-import org.apache.cayenne.project.upgrade.UpgradeHandler;
-import org.apache.cayenne.resource.Resource;
-
-/**
- * A ProjectUpgrader that handles project upgrades from version 4.0.M4 and 8
- * to version 9.
- */
-public class ProjectUpgrader_V9 implements ProjectUpgrader {
-
-    @Inject
-    protected Injector injector;
-
-    @Override
-    public UpgradeHandler getUpgradeHandler(Resource projectSource) {
-        UpgradeHandler_V9 handler = new UpgradeHandler_V9(projectSource);
-        injector.injectMembers(handler);
-        return handler;
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java
index 10dd3aa..3625df2 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java
@@ -20,6 +20,7 @@
 package org.apache.cayenne.modeler;
 
 import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.configuration.xml.DataChannelMetaData;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.modeler.action.ActionManager;
@@ -80,6 +81,9 @@ public class Application {
     @Inject
     protected Injector injector;
 
+    @Inject
+    protected DataChannelMetaData metaData;
+
     private String newProjectTemporaryName;
 
     public static Application getInstance() {
@@ -280,6 +284,10 @@ public class Application {
         }
     }
 
+    public DataChannelMetaData getMetaData() {
+        return metaData;
+    }
+
     protected void initPreferences() {
         this.cayenneProjectPreferences = new CayenneProjectPreferences();
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectFileChangeTracker.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectFileChangeTracker.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectFileChangeTracker.java
index 99866d2..b5b61a6 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectFileChangeTracker.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectFileChangeTracker.java
@@ -84,7 +84,10 @@ public class ProjectFileChangeTracker extends Thread {
             Iterator<DataMap> it = ((DataChannelDescriptor) project.getRootNode()).getDataMaps().iterator();
             while (it.hasNext()) {
                 DataMap dm = it.next();
-                addFile(dm.getConfigurationSource().getURL().getPath());
+                if(dm.getConfigurationSource() != null) {
+                    // if DataMap is in separate file, monitor it
+                    addFile(dm.getConfigurationSource().getURL().getPath());
+                }
             }
 
         }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CopyAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CopyAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CopyAction.java
index b813ed8..8c9499d 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CopyAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CopyAction.java
@@ -26,6 +26,7 @@ import java.awt.event.KeyEvent;
 import javax.swing.KeyStroke;
 
 import org.apache.cayenne.configuration.ConfigurationNode;
+import org.apache.cayenne.configuration.EmptyConfigurationNodeVisitor;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
@@ -111,7 +112,7 @@ public class CopyAction extends CayenneAction {
      * Prints an object in XML format to an output stream
      */
     protected void print(XMLEncoder encoder, XMLSerializable object) {
-        object.encodeAsXML(encoder);
+        object.encodeAsXML(encoder, new EmptyConfigurationNodeVisitor());
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/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 de8d57d..1e80798 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
@@ -22,23 +22,22 @@ package org.apache.cayenne.modeler.action;
 import org.apache.cayenne.configuration.ConfigurationNameMapper;
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.dbsync.naming.NameBuilder;
 import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.MapLoader;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.pref.FSPath;
 import org.apache.cayenne.modeler.util.CayenneAction;
 import org.apache.cayenne.modeler.util.FileFilters;
 import org.apache.cayenne.resource.Resource;
+import org.apache.cayenne.resource.URLResource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-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;
 
 /**
@@ -76,12 +75,8 @@ public class ImportDataMapAction extends CayenneAction {
 
         try {
             URL url = dataMapFile.toURI().toURL();
-
-            try (InputStream in = url.openStream();) {
-                InputSource inSrc = new InputSource(in);
-                inSrc.setSystemId(dataMapFile.getAbsolutePath());
-                newMap = new MapLoader().loadDataMap(inSrc);
-            }
+            DataMapLoader loader = application.getInjector().getInstance(DataMapLoader.class);
+            newMap = loader.load(new URLResource(url));
 
             ConfigurationNode root = getProjectController().getProject().getRootNode();
             newMap.setName(NameBuilder

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/OpenProjectAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/OpenProjectAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/OpenProjectAction.java
index e7fcb56..c8465d6 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/OpenProjectAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/OpenProjectAction.java
@@ -24,6 +24,9 @@ import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
 import java.io.File;
 import java.net.URL;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 
 import javax.swing.JOptionPane;
 import javax.swing.KeyStroke;
@@ -33,10 +36,8 @@ import org.apache.cayenne.modeler.CayenneModelerController;
 import org.apache.cayenne.modeler.dialog.ErrorDebugDialog;
 import org.apache.cayenne.project.Project;
 import org.apache.cayenne.project.ProjectLoader;
-import org.apache.cayenne.project.upgrade.ProjectUpgrader;
-import org.apache.cayenne.project.upgrade.UpgradeHandler;
 import org.apache.cayenne.project.upgrade.UpgradeMetaData;
-import org.apache.cayenne.project.upgrade.UpgradeType;
+import org.apache.cayenne.project.upgrade.UpgradeService;
 import org.apache.cayenne.resource.Resource;
 import org.apache.cayenne.resource.URLResource;
 import org.apache.cayenne.swing.control.FileMenuItem;
@@ -47,6 +48,19 @@ public class OpenProjectAction extends ProjectAction {
 
     private static Logger logObj = LoggerFactory.getLogger(OpenProjectAction.class);
 
+    private static final Map<String, String> PROJECT_TO_MODELER_VERSION;
+    static {
+        // Correspondence between project version and latest Modeler version that can upgrade it.
+        // Modeler v4.1 can handle versions from 3.1 and 4.0 (including intermediate versions) modeler.
+        Map<String, String> map = new HashMap<>();
+        map.put("1.0",      "v3.0");
+        map.put("1.1",      "v3.0");
+        map.put("1.2",      "v3.0");
+        map.put("2.0",      "v3.0");
+        map.put("3.0.0.1",  "v3.1");
+        PROJECT_TO_MODELER_VERSION = Collections.unmodifiableMap(map);
+    }
+
     private ProjectOpener fileChooser;
 
     public static String getActionName() {
@@ -113,7 +127,7 @@ public class OpenProjectAction extends ProjectAction {
                         Application.getFrame(),
                         "Can't open project - file \"" + file.getPath() + "\" does not exist",
                         "Can't Open Project",
-                        JOptionPane.OK_OPTION);
+                        JOptionPane.ERROR_MESSAGE);
                 return;
             }
 
@@ -123,55 +137,39 @@ public class OpenProjectAction extends ProjectAction {
             URL url = file.toURI().toURL();
             Resource rootSource = new URLResource(url);
 
-            ProjectUpgrader upgrader = getApplication().getInjector().getInstance(ProjectUpgrader.class);
-            UpgradeHandler handler = upgrader.getUpgradeHandler(rootSource);
-            UpgradeMetaData md = handler.getUpgradeMetaData();
-
-            if (UpgradeType.DOWNGRADE_NEEDED == md.getUpgradeType()) {
-                JOptionPane
-                        .showMessageDialog(
-                                Application.getFrame(),
-                                "Can't open project - it was created using a newer version of the Modeler",
-                                "Can't Open Project",
-                                JOptionPane.OK_OPTION);
-                closeProject(false);
-            } else if (UpgradeType.INTERMEDIATE_UPGRADE_NEEDED == md.getUpgradeType()) {
-                JOptionPane
-                        .showMessageDialog(Application.getFrame(),
-                        // TODO: andrus 05/02/2010 - this message shows intermediate
-                                // version of the project XML, not the Modeler code
-                                // version that
-                                // can be used for upgrade
-                                "Can't upgrade project. Open the project in the Modeler v."
-                                        + md.getIntermediateUpgradeVersion()
-                                        + " to do an intermediate upgrade before you can upgrade to v."
-                                        + md.getSupportedVersion(),
-                                "Can't Upgrade Project",
-                                JOptionPane.OK_OPTION);
-                closeProject(false);
-            } else if (UpgradeType.UPGRADE_NEEDED == md.getUpgradeType()) {
-                if (processUpgrades()) {
-                    // perform upgrade
-                    logObj.info("Will upgrade project " + url.getPath());
-                    Resource upgraded = handler.performUpgrade();
-                    if (upgraded != null) {
-                        Project project = openProjectResourse(upgraded, controller);
-
-                        getProjectController().getFileChangeTracker().pauseWatching();
-                        getProjectController().getFileChangeTracker().reconfigure();
-
-                        // need to update project file name if it has changed
-                        if (!file.getAbsolutePath().equals(project.getConfigurationResource().getURL().getPath())) {
-                            File projectFile = new File(project.getConfigurationResource().getURL().toURI());
-                            controller.changePathInLastProjListAction(file, projectFile);
-                        }
+            UpgradeService upgradeService = getApplication().getInjector().getInstance(UpgradeService.class);
+            UpgradeMetaData metaData = upgradeService.getUpgradeType(rootSource);
+            switch (metaData.getUpgradeType()) {
+                case INTERMEDIATE_UPGRADE_NEEDED:
+                    String modelerVersion = PROJECT_TO_MODELER_VERSION.get(metaData.getProjectVersion());
+                    if(modelerVersion == null) {
+                        modelerVersion = "";
+                    }
+                    JOptionPane.showMessageDialog(Application.getFrame(),
+                                    "Open the project in the older Modeler " + modelerVersion
+                                            + " to do an intermediate upgrade\nbefore you can upgrade to latest version.",
+                                    "Can't Upgrade Project", JOptionPane.ERROR_MESSAGE);
+                    closeProject(false);
+                    return;
+
+                case DOWNGRADE_NEEDED:
+                    JOptionPane.showMessageDialog(Application.getFrame(),
+                                    "Can't open project - it was created using a newer version of the Modeler",
+                                    "Can't Open Project", JOptionPane.ERROR_MESSAGE);
+                    closeProject(false);
+                    return;
+
+                case UPGRADE_NEEDED:
+                    if (processUpgrades()) {
+                        rootSource = upgradeService.upgradeProject(rootSource);
                     } else {
                         closeProject(false);
+                        return;
                     }
-                }
-            } else {
-                openProjectResourse(rootSource, controller);
+                    break;
             }
+
+            openProjectResourse(rootSource, controller);
         } catch (Exception ex) {
             logObj.warn("Error loading project file.", ex);
             ErrorDebugDialog.guiWarning(ex, "Error loading project");

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/CustomModeController.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/CustomModeController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/CustomModeController.java
index 0250f9c..8d66407 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/CustomModeController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/CustomModeController.java
@@ -244,6 +244,8 @@ public class CustomModeController extends GeneratorController {
 
 	@Override
 	protected ClassGenerationAction newGenerator() {
-		return new ClassGenerationAction();
+		ClassGenerationAction action = new ClassGenerationAction();
+		getApplication().getInjector().injectMembers(action);
+		return action;
 	}
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/GeneratorController.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/GeneratorController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/GeneratorController.java
index 6d3452b..962601d 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/GeneratorController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/GeneratorController.java
@@ -19,7 +19,7 @@
 
 package org.apache.cayenne.modeler.dialog.codegen;
 
-import org.apache.cayenne.CayenneException;
+import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.gen.ArtifactsGenerationMode;
 import org.apache.cayenne.gen.ClassGenerationAction;
 import org.apache.cayenne.map.DataMap;
@@ -203,7 +203,7 @@ public abstract class GeneratorController extends CayenneController {
                 }
 
                 generators.add(generator);
-            } catch (CayenneException exception) {
+            } catch (CayenneRuntimeException exception) {
                 JOptionPane.showMessageDialog(this.getView(), exception.getUnlabeledMessage());
                 return null;
             }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/StandardModeController.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/StandardModeController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/StandardModeController.java
index e700779..8443956 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/StandardModeController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/codegen/StandardModeController.java
@@ -93,7 +93,9 @@ public class StandardModeController extends GeneratorController {
 
     @Override
     protected ClassGenerationAction newGenerator() {
-        return new ClassGenerationAction();
+        ClassGenerationAction action = new ClassGenerationAction();
+        getApplication().getInjector().injectMembers(action);
+        return action;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerDbImportAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerDbImportAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerDbImportAction.java
index c74df88..5e60bc4 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerDbImportAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerDbImportAction.java
@@ -18,12 +18,12 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.dialog.db.load;
 
+import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.server.DataSourceFactory;
 import org.apache.cayenne.configuration.server.DbAdapterFactory;
 import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.MapLoader;
 import org.apache.cayenne.project.ProjectSaver;
 import org.apache.cayenne.dbsync.reverse.dbimport.DbImportConfiguration;
 import org.apache.cayenne.dbsync.reverse.dbimport.DefaultDbImportAction;
@@ -40,7 +40,7 @@ public class ModelerDbImportAction extends DefaultDbImportAction {
                                  @Inject ProjectSaver projectSaver,
                                  @Inject DataSourceFactory dataSourceFactory,
                                  @Inject DbAdapterFactory adapterFactory,
-                                 @Inject MapLoader mapLoader,
+                                 @Inject DataMapLoader mapLoader,
                                  @Inject MergerTokenFactoryProvider mergerTokenFactoryProvider) {
         super(logger, projectSaver, dataSourceFactory, adapterFactory, mapLoader, mergerTokenFactoryProvider);
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjCallbackMethod.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjCallbackMethod.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjCallbackMethod.java
index 204a975..ddac69d 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjCallbackMethod.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjCallbackMethod.java
@@ -20,6 +20,7 @@ package org.apache.cayenne.modeler.editor;
 
 import java.io.Serializable;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.util.XMLEncoder;
 import org.apache.cayenne.util.XMLSerializable;
 
@@ -35,7 +36,7 @@ public class ObjCallbackMethod implements XMLSerializable,
 	}
 
 	@Override
-	public void encodeAsXML(XMLEncoder encoder) {
+	public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
 
         encoder.print("<" + encodeCallbackTypeForXML(callbackType));
         encoder.print(" name=\"" + getName());

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/BaseGraphBuilder.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/BaseGraphBuilder.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/BaseGraphBuilder.java
index 1b74906..ce89df2 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/BaseGraphBuilder.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/BaseGraphBuilder.java
@@ -39,6 +39,7 @@ import javax.swing.JPopupMenu;
 import javax.swing.border.LineBorder;
 import javax.swing.event.UndoableEditEvent;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.configuration.event.DataMapEvent;
 import org.apache.cayenne.configuration.event.DataMapListener;
@@ -547,7 +548,8 @@ abstract class BaseGraphBuilder implements GraphBuilder, DataMapListener {
         return rel.getSourceEntity().getName() + "." + rel.getName();
     }
 
-    public void encodeAsXML(XMLEncoder encoder) {
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
         encoder.print("<graph type=\"");
         encoder.print(getType().toString());
         encoder.print("\" scale=\"");

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/GraphBuilder.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/GraphBuilder.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/GraphBuilder.java
index 9b86e0b..665ed86 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/GraphBuilder.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/GraphBuilder.java
@@ -33,40 +33,40 @@ import org.jgraph.graph.DefaultGraphCell;
  * Interface for building graphs which represent some prespective of a domain
  */
 public interface GraphBuilder extends Serializable, XMLSerializable, UndoableEditListener {
-    public static final double ZOOM_FACTOR = 1.3;
+    double ZOOM_FACTOR = 1.3;
     
     /**
      * Builds graph
      */
-    public void buildGraph(ProjectController mediator, DataChannelDescriptor domain, boolean layout);
+    void buildGraph(ProjectController mediator, DataChannelDescriptor domain, boolean layout);
     
     /**
      * Invoked at destroying of the builder
      */
-    public void destroy();
+    void destroy();
     
     /**
      * Returns built graph for this builder
      */
-    public JGraph getGraph();
+    JGraph getGraph();
     
     /**
      * Returns domain.
      */
-    public DataChannelDescriptor getDataDomain();
+    DataChannelDescriptor getDataDomain();
         
     /**
      * Returns type of the graph
      */
-    public GraphType getType();
+    GraphType getType();
     
     /**
      * Returns selected entity, <code>null</code> if none is selected
      */
-    public Entity getSelectedEntity();
+    Entity getSelectedEntity();
     
     /**
      * Returns cell of an entity
      */
-    public DefaultGraphCell getEntityCell(String entityName);
+    DefaultGraphCell getEntityCell(String entityName);
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/GraphMap.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/GraphMap.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/GraphMap.java
index c0da6b1..3ed6d65 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/GraphMap.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/graph/GraphMap.java
@@ -21,6 +21,7 @@ package org.apache.cayenne.modeler.graph;
 import java.util.HashMap;
 
 import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.modeler.Application;
 import org.apache.cayenne.modeler.ProjectController;
@@ -67,7 +68,8 @@ public class GraphMap extends HashMap<GraphType, GraphBuilder> implements XMLSer
         this.selectedType = selectedType;
     }
 
-    public void encodeAsXML(XMLEncoder encoder) {
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
         encoder.print("<graphs");
 //        if (selectedType != null) {
 //            encoder.print(" selected=\"" + selectedType + "\"");
@@ -76,7 +78,7 @@ public class GraphMap extends HashMap<GraphType, GraphBuilder> implements XMLSer
         encoder.indent(1);
         
         for (GraphBuilder builder : values()) {
-            builder.encodeAsXML(encoder);
+            builder.encodeAsXML(encoder, delegate);
         }
         
         encoder.indent(-1);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/init/CayenneModelerModule.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/init/CayenneModelerModule.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/init/CayenneModelerModule.java
index a0e8a39..30f0f99 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/init/CayenneModelerModule.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/init/CayenneModelerModule.java
@@ -18,6 +18,9 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.init;
 
+import org.apache.cayenne.configuration.xml.DataChannelMetaData;
+import org.apache.cayenne.configuration.xml.DefaultDataChannelMetaData;
+import org.apache.cayenne.configuration.xml.HandlerFactory;
 import org.apache.cayenne.di.Binder;
 import org.apache.cayenne.di.Module;
 import org.apache.cayenne.modeler.Application;
@@ -27,6 +30,7 @@ import org.apache.cayenne.modeler.init.platform.GenericPlatformInitializer;
 import org.apache.cayenne.modeler.init.platform.PlatformInitializer;
 import org.apache.cayenne.modeler.util.DefaultWidgetFactory;
 import org.apache.cayenne.modeler.util.WidgetFactory;
+import org.apache.cayenne.project.extension.ExtensionAwareHandlerFactory;
 
 /**
  * A DI module for bootstrapping CayenneModeler services.
@@ -39,5 +43,7 @@ public class CayenneModelerModule implements Module {
         binder.bind(Application.class).to(Application.class);
         binder.bind(PlatformInitializer.class).to(GenericPlatformInitializer.class);
         binder.bind(WidgetFactory.class).to(DefaultWidgetFactory.class);
+        binder.bind(HandlerFactory.class).to(ExtensionAwareHandlerFactory.class);
+        binder.bind(DataChannelMetaData.class).to(DefaultDataChannelMetaData.class);
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/d608777a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/CayenneTransferable.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/CayenneTransferable.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/CayenneTransferable.java
index ae8fc53..2ac94f7 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/CayenneTransferable.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/CayenneTransferable.java
@@ -27,6 +27,8 @@ import java.io.Serializable;
 import java.io.StringWriter;
 import java.util.List;
 
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.configuration.EmptyConfigurationNodeVisitor;
 import org.apache.cayenne.util.XMLEncoder;
 import org.apache.cayenne.util.XMLSerializable;
 
@@ -59,18 +61,18 @@ public class CayenneTransferable implements Transferable {
         
         if (flavor == CAYENNE_FLAVOR) {
             return data;
-        }
-        else {
+        } else {
             StringWriter out = new StringWriter();
             XMLEncoder encoder = new XMLEncoder(new PrintWriter(out), "\t");
+            ConfigurationNodeVisitor visitor = new EmptyConfigurationNodeVisitor();
+
             encoder.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
             
             if (data instanceof XMLSerializable) {
-                ((XMLSerializable) data).encodeAsXML(encoder);
-            }
-            else if (data instanceof List) {
+                ((XMLSerializable) data).encodeAsXML(encoder, visitor);
+            } else if (data instanceof List) {
                 for (Object o : (List) data) {
-                    ((XMLSerializable) o).encodeAsXML(encoder);
+                    ((XMLSerializable) o).encodeAsXML(encoder, visitor);
                 }
             }