Cgen tab, cgen configuration, cgen in maven, ant, gradle.

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

Branch: refs/heads/master
Commit: 52ea45b5d72b5a6b1466e7779e03753c74ebaf3b
Parents: 6a43436
Author: Arseni Bulatski <ancars...@gmail.com>
Authored: Wed Oct 31 16:33:52 2018 +0300
Committer: Arseni Bulatski <ancars...@gmail.com>
Committed: Thu Nov 8 17:08:08 2018 +0300

----------------------------------------------------------------------
 .../cayenne/tools/CayenneGeneratorTask.java     |  141 ++-
 .../cayenne/tools/CgenWithConfigTest.java       |   41 +-
 cayenne-ant/src/test/resources/cgenTest.map.xml |   19 +-
 .../apache/cayenne/gen/CgenConfiguration.java   |  363 ++++++
 .../cayenne/gen/ClassGenerationAction.java      |  669 +++--------
 .../gen/ClientClassGenerationAction.java        |   39 +-
 .../cayenne/gen/xml/CgenConfigHandler.java      |   32 +-
 .../cayenne/gen/xml/CgenSaverDelegate.java      |   14 +-
 .../CayenneGeneratorEmbeddableFilterAction.java |   29 +
 .../CayenneGeneratorEntityFilterAction.java     |   22 +-
 .../cayenne/gen/ClassGenerationActionTest.java  |   37 +-
 .../java/org/apache/cayenne/tools/CgenTask.java |  137 ++-
 .../org/apache/cayenne/tools/CgenTaskIT.java    |   60 +-
 .../org/apache/cayenne/tools/CgenTaskTest.java  |   43 +-
 .../cayenne/tools/CgenTaskWithConfigIT.java     |   71 --
 .../org/apache/cayenne/tools/cgenConfig.map.xml |   22 +
 .../org/apache/cayenne/tools/cgenMap.map.xml    |   19 +-
 .../cayenne/tools/cgen_with_config.gradle       |    3 +-
 .../cayenne/tools/cgen_with_configs.gradle      |   32 +
 .../cayenne/tools/CayenneGeneratorMojo.java     |  135 ++-
 .../cayenne/tools/CayenneGeneratorMojoTest.java |   48 +
 .../cayenne/tools/CgenWithConfigMojoTest.java   |   51 -
 .../resources/cgen/project-to-test/cgen-pom.xml |    2 -
 .../cgen/project-to-test/datamap-and-pom.xml    |   54 +
 .../src/test/resources/cgen/testCgen.map.xml    |   22 +
 .../src/test/resources/cgen/testCgenMap.map.xml |   19 +-
 .../modeler/action/GenerateCodeAction.java      |   12 +-
 .../dialog/codegen/ClassesTabController.java    |  406 +++----
 .../modeler/dialog/codegen/ClassesTabPanel.java |  282 ++---
 .../dialog/codegen/ClientModeController.java    |  162 +--
 .../dialog/codegen/CodeGeneratorController.java |  338 +++---
 .../codegen/CodeGeneratorControllerBase.java    |  760 ++++++------
 .../dialog/codegen/CodeGeneratorDialog.java     |  198 +--
 .../dialog/codegen/CustomModeController.java    |  470 ++++----
 .../modeler/dialog/codegen/CustomModePanel.java |  274 ++---
 .../codegen/CustomPreferencesUpdater.java       |  418 +++----
 .../dialog/codegen/GeneratorController.java     | 1123 +++++++++---------
 .../codegen/GeneratorControllerPanel.java       |  110 +-
 .../dialog/codegen/GeneratorTabController.java  |  230 ++--
 .../dialog/codegen/GeneratorTabPanel.java       |  130 +-
 .../dialog/codegen/StandardModeController.java  |  164 +--
 .../dialog/codegen/StandardModePanel.java       |   84 +-
 .../dialog/codegen/StandardPanelComponent.java  |  162 +--
 .../modeler/editor/DataDomainTabbedView.java    |  183 +--
 .../modeler/editor/DataMapTabbedView.java       |   12 +-
 .../editor/cgen/ClientModeController.java       |   12 +-
 .../editor/cgen/CodeGeneratorController.java    |   51 +-
 .../cgen/CodeGeneratorControllerBase.java       |   37 +-
 .../editor/cgen/CustomModeController.java       |   58 +-
 .../editor/cgen/GeneratorController.java        |   88 +-
 .../editor/cgen/GeneratorControllerPanel.java   |    6 +-
 .../editor/cgen/GeneratorTabController.java     |   51 +-
 .../editor/cgen/StandardModeController.java     |   17 +-
 .../modeler/editor/cgen/domain/CgenPanel.java   |   59 +
 .../modeler/editor/cgen/domain/CgenTab.java     |   89 ++
 .../editor/cgen/domain/CgenTabController.java   |  197 +++
 .../cayenne/modeler/util/ModelerUtil.java       |   43 +
 57 files changed, 4547 insertions(+), 3803 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/52ea45b5/cayenne-ant/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
----------------------------------------------------------------------
diff --git 
a/cayenne-ant/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java 
b/cayenne-ant/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
index a82931e..02cc0bf 100644
--- 
a/cayenne-ant/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
+++ 
b/cayenne-ant/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
@@ -24,6 +24,7 @@ import org.apache.cayenne.dbsync.filter.NamePatternMatcher;
 import org.apache.cayenne.dbsync.reverse.configuration.ToolsModule;
 import org.apache.cayenne.di.DIBootstrap;
 import org.apache.cayenne.di.Injector;
+import org.apache.cayenne.gen.CgenConfiguration;
 import org.apache.cayenne.gen.CgenModule;
 import org.apache.cayenne.gen.ClassGenerationAction;
 import org.apache.cayenne.gen.ClientClassGenerationAction;
@@ -34,6 +35,8 @@ import org.apache.velocity.VelocityContext;
 import org.slf4j.LoggerFactory;
 
 import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 
 /**
  * An Ant task to perform class generation based on CayenneDataMap.
@@ -44,6 +47,7 @@ public class CayenneGeneratorTask extends CayenneTask {
 
     protected String includeEntitiesPattern;
     protected String excludeEntitiesPattern;
+    protected String excludeEmbeddablesPattern;
     protected VPPConfig vppConfig;
 
     protected File map;
@@ -63,7 +67,11 @@ public class CayenneGeneratorTask extends CayenneTask {
     protected String querytemplate;
     protected String querysupertemplate;
     protected Boolean usepkgpath;
-    protected Boolean createpropertynames;
+    protected boolean createpropertynames;
+
+    private boolean force;
+
+    private boolean useConfigFromDataMap;
 
     private transient Injector injector;
 
@@ -82,36 +90,6 @@ public class CayenneGeneratorTask extends CayenneTask {
         return vppConfig.getVelocityContext();
     }
 
-    protected ClassGenerationAction createGeneratorAction(DataMap dataMap) {
-        ClassGenerationAction action = 
injector.getInstance(DataChannelMetaData.class).get(dataMap, 
ClassGenerationAction.class);
-
-        if (client) {
-            action = new ClientClassGenerationAction();
-        } else {
-            if(action == null) {
-                action = new ClassGenerationAction();
-            }
-        }
-
-        action.setContext(getVppContext());
-        action.setDestDir(destDir);
-        action.setEncoding(encoding != null ? encoding : action.getEncoding());
-        action.setMakePairs(makepairs != null ? makepairs : 
action.isMakePairs());
-        action.setArtifactsGenerationMode(mode != null ? mode : 
action.getArtifactsGenerationMode());
-        action.setOutputPattern(outputPattern != null ? outputPattern : 
action.getOutputPattern());
-        action.setOverwrite(overwrite != null ? overwrite : 
action.isOverwrite());
-        action.setSuperPkg(superpkg != null ? superpkg : action.getSuperPkg());
-        action.setSuperTemplate(supertemplate != null ? supertemplate : 
action.getSuperclassTemplate());
-        action.setTemplate(template != null ? template : action.getTemplate());
-        action.setEmbeddableSuperTemplate(embeddablesupertemplate != null ? 
embeddablesupertemplate : action.getEmbeddableSuperTemplate());
-        action.setEmbeddableTemplate(embeddabletemplate != null ? 
embeddabletemplate : action.getEmbeddableTemplate());
-        action.setUsePkgPath(usepkgpath != null ? usepkgpath : 
action.isUsePkgPath());
-        action.setCreatePropertyNames(createpropertynames != null ? 
createpropertynames : action.isCreatePropertyNames());
-        action.setQueryTemplate(querytemplate != null ? querytemplate : 
action.getQueryTemplate());
-        action.setQuerySuperTemplate(querysupertemplate != null ? 
querysupertemplate : action.getQuerySuperTemplate());
-        return action;
-    }
-
     /**
      * Executes the task. It will be called by ant framework.
      */
@@ -127,23 +105,28 @@ public class CayenneGeneratorTask extends CayenneTask {
         loadAction.setMainDataMapFile(map);
         loadAction.setAdditionalDataMapFiles(additionalMaps);
 
-        CayenneGeneratorEntityFilterAction filterAction = new 
CayenneGeneratorEntityFilterAction();
-        filterAction.setClient(client);
-        filterAction.setNameFilter(NamePatternMatcher.build(logger, 
includeEntitiesPattern, excludeEntitiesPattern));
+        CayenneGeneratorEntityFilterAction filterEntityAction = new 
CayenneGeneratorEntityFilterAction();
+        filterEntityAction.setClient(client);
+        filterEntityAction.setNameFilter(NamePatternMatcher.build(logger, 
includeEntitiesPattern, excludeEntitiesPattern));
 
+        CayenneGeneratorEmbeddableFilterAction filterEmbeddableAction = new 
CayenneGeneratorEmbeddableFilterAction();
+        filterEmbeddableAction.setNameFilter(NamePatternMatcher.build(logger, 
null, excludeEmbeddablesPattern));
         try {
 
             DataMap dataMap = loadAction.getMainDataMap();
 
-            ClassGenerationAction generatorAction = 
createGeneratorAction(dataMap);
+            ClassGenerationAction generatorAction = createGenerator(dataMap);
             generatorAction.setLogger(logger);
-            generatorAction.setTimestamp(map.lastModified());
-            generatorAction.setDataMap(dataMap);
-            if(!generatorAction.getEntities().isEmpty() || 
!generatorAction.getEmbeddables().isEmpty()){
+            if(force) {
+                // will (re-)generate all files
+                generatorAction.getCgenConfiguration().setForce(true);
+            }
+            
generatorAction.getCgenConfiguration().setTimestamp(map.lastModified());
+            if(!hasConfig() && useConfigFromDataMap) {
                 generatorAction.prepareArtifacts();
             } else {
-                
generatorAction.addEntities(filterAction.getFilteredEntities(dataMap));
-                
generatorAction.addEmbeddables(filterAction.getFilteredEmbeddables(dataMap));
+                
generatorAction.addEntities(filterEntityAction.getFilteredEntities(dataMap));
+                
generatorAction.addEmbeddables(filterEmbeddableAction.getFilteredEmbeddables(dataMap));
                 generatorAction.addQueries(dataMap.getQueryDescriptors());
             }
             generatorAction.execute();
@@ -153,6 +136,76 @@ public class CayenneGeneratorTask extends CayenneTask {
         }
     }
 
+    private ClassGenerationAction createGenerator(DataMap dataMap) {
+        CgenConfiguration cgenConfiguration = buildConfiguration(dataMap);
+        ClassGenerationAction classGenerationAction = 
cgenConfiguration.isClient() ? new 
ClientClassGenerationAction(cgenConfiguration) :
+                new ClassGenerationAction(cgenConfiguration);
+        injector.injectMembers(classGenerationAction);
+
+        return classGenerationAction;
+    }
+
+    private boolean hasConfig() {
+        return destDir != null || encoding != null || client || 
excludeEntitiesPattern != null || excludeEmbeddablesPattern != null || 
includeEntitiesPattern != null ||
+                makepairs != null || mode != null || outputPattern != null || 
overwrite != null || superpkg != null ||
+                supertemplate != null || template != null || 
embeddabletemplate != null || embeddablesupertemplate != null ||
+                usepkgpath != null || createpropertynames || querytemplate != 
null ||
+                querysupertemplate != null || createpkproperties || force;
+    }
+
+    private CgenConfiguration buildConfiguration(DataMap dataMap) {
+        CgenConfiguration cgenConfiguration = 
injector.getInstance(DataChannelMetaData.class).get(dataMap, 
CgenConfiguration.class);
+        if(hasConfig()) {
+            return cgenConfigFromPom(dataMap);
+        } else if(cgenConfiguration != null) {
+            useConfigFromDataMap = true;
+            java.nio.file.Path resourcePath = Paths.get(map.getPath());
+            if(Files.isRegularFile(resourcePath)) {
+                resourcePath = resourcePath.getParent();
+            }
+            
cgenConfiguration.setRelPath(resourcePath.resolve(cgenConfiguration.getRelPath()));
+            return cgenConfiguration;
+        } else {
+            cgenConfiguration = new CgenConfiguration();
+            cgenConfiguration.setDataMap(dataMap);
+            return cgenConfiguration;
+        }
+    }
+
+    private CgenConfiguration cgenConfigFromPom(DataMap dataMap){
+        CgenConfiguration cgenConfiguration = new CgenConfiguration();
+        cgenConfiguration.setDataMap(dataMap);
+        cgenConfiguration.setRelPath(destDir != null ? destDir.getPath() : 
cgenConfiguration.getRelPath());
+        cgenConfiguration.setEncoding(encoding != null ? encoding : 
cgenConfiguration.getEncoding());
+        cgenConfiguration.setMakePairs(makepairs != null ? makepairs : 
cgenConfiguration.isMakePairs());
+        cgenConfiguration.setArtifactsGenerationMode(mode != null ? mode : 
cgenConfiguration.getArtifactsGenerationMode());
+        cgenConfiguration.setOutputPattern(outputPattern != null ? 
outputPattern : cgenConfiguration.getOutputPattern());
+        cgenConfiguration.setOverwrite(overwrite != null ? overwrite : 
cgenConfiguration.isOverwrite());
+        cgenConfiguration.setSuperPkg(superpkg != null ? superpkg : 
cgenConfiguration.getSuperPkg());
+        cgenConfiguration.setSuperTemplate(supertemplate != null ? 
supertemplate : cgenConfiguration.getSuperTemplate());
+        cgenConfiguration.setTemplate(template != null ? template :  
cgenConfiguration.getTemplate());
+        cgenConfiguration.setEmbeddableSuperTemplate(embeddablesupertemplate 
!= null ? embeddablesupertemplate : 
cgenConfiguration.getEmbeddableSuperTemplate());
+        cgenConfiguration.setEmbeddableTemplate(embeddabletemplate != null ? 
embeddabletemplate : cgenConfiguration.getEmbeddableTemplate());
+        cgenConfiguration.setUsePkgPath(usepkgpath != null ? usepkgpath : 
cgenConfiguration.isUsePkgPath());
+        cgenConfiguration.setCreatePropertyNames(createpropertynames);
+        cgenConfiguration.setQueryTemplate(querytemplate != null ? 
querytemplate : cgenConfiguration.getQueryTemplate());
+        cgenConfiguration.setQuerySuperTemplate(querysupertemplate != null ? 
querysupertemplate : cgenConfiguration.getQuerySuperTemplate());
+        cgenConfiguration.setCreatePKProperties(createpkproperties);
+        cgenConfiguration.setClient(client);
+        if(!cgenConfiguration.isMakePairs()) {
+            if(template == null) {
+                cgenConfiguration.setTemplate(client ? 
ClientClassGenerationAction.SINGLE_CLASS_TEMPLATE : 
ClassGenerationAction.SINGLE_CLASS_TEMPLATE);
+            }
+            if(embeddabletemplate == null) {
+                
cgenConfiguration.setEmbeddableTemplate(ClassGenerationAction.EMBEDDABLE_SINGLE_CLASS_TEMPLATE);
+            }
+            if(querytemplate == null) {
+                cgenConfiguration.setQueryTemplate(client ? 
ClientClassGenerationAction.DATAMAP_SINGLE_CLASS_TEMPLATE : 
ClassGenerationAction.DATAMAP_SINGLE_CLASS_TEMPLATE);
+            }
+        }
+        return cgenConfiguration;
+    }
+
     /**
      * Validates attributes that are not related to internal 
DefaultClassGenerator. Throws
      * BuildException if attributes are invalid.
@@ -278,6 +331,10 @@ public class CayenneGeneratorTask extends CayenneTask {
         this.includeEntitiesPattern = includeEntitiesPattern;
     }
 
+    public void setExcludeEmbeddablesPattern(String excludeEmbeddablesPattern) 
{
+        this.excludeEmbeddablesPattern = excludeEmbeddablesPattern;
+    }
+
     /**
      * Sets <code>outputPattern</code> property.
      */
@@ -314,6 +371,10 @@ public class CayenneGeneratorTask extends CayenneTask {
         this.createpkproperties = createpkproperties;
     }
 
+    public void setForce(boolean force) {
+        this.force = force;
+    }
+
     /**
      * Provides a <code>VPPConfig</code> object to configure. (Written with 
createConfig()
      * instead of addConfig() to avoid run-time dependency on VPP).

http://git-wip-us.apache.org/repos/asf/cayenne/blob/52ea45b5/cayenne-ant/src/test/java/org/apache/cayenne/tools/CgenWithConfigTest.java
----------------------------------------------------------------------
diff --git 
a/cayenne-ant/src/test/java/org/apache/cayenne/tools/CgenWithConfigTest.java 
b/cayenne-ant/src/test/java/org/apache/cayenne/tools/CgenWithConfigTest.java
index cdccd49..4241105 100644
--- a/cayenne-ant/src/test/java/org/apache/cayenne/tools/CgenWithConfigTest.java
+++ b/cayenne-ant/src/test/java/org/apache/cayenne/tools/CgenWithConfigTest.java
@@ -64,25 +64,58 @@ public class CgenWithConfigTest {
         File mapDir = new File(baseDir, "cgenConfigTest");
         assertTrue(mapDir.mkdirs());
 
+        task.setMap(map);
+
+        // run task
+        task.execute();
+
+        // check results
+        File entity = new File(mapDir, convertPath("ObjEntity1.txt"));
+        assertTrue(entity.isFile());
+
+        File datamap = new File(mapDir, convertPath("Antmap_cgen_xml.txt"));
+        assertTrue(datamap.isFile());
+
+        File notIncludedEntity = new File(mapDir, "ObjEntity.txt");
+        assertFalse(notIncludedEntity.exists());
+
+        File notIncludeSuperDatamap = new File("_Antmap_cgen_xml.txt");
+        assertFalse(notIncludeSuperDatamap.exists());
+    }
+
+    @Test
+    public void testCgenWithDmAndPomConfigs() throws Exception {
+        File mapDir = new File(baseDir, "cgenDmPomTest");
+        assertTrue(mapDir.mkdirs());
+
         task.setDestDir(mapDir);
         task.setMap(map);
+        task.setExcludeEntities("ObjEntity1");
         task.setMode("entity");
+        task.setMakepairs(false);
+        task.setOutputPattern("*.txt");
 
         // run task
         task.execute();
 
         // check results
-        File entity = new File(mapDir, convertPath("ObjEntity1.txt"));
+        File entity = new File(mapDir, convertPath("ObjEntity.txt"));
         assertTrue(entity.isFile());
 
-        File datamap = new File(mapDir, convertPath("TestCgenMap.txt"));
+        File embeddable = new File(mapDir, convertPath("Embeddable.txt"));
+        assertTrue(embeddable.isFile());
+
+        File datamap = new File(mapDir, convertPath("Antmap_cgen_xml.txt"));
         assertFalse(datamap.exists());
 
-        File notIncludedEntity = new File(mapDir, "ObjEntity.txt");
+        File notIncludedEntity = new File(mapDir, "ObjEntity1.txt");
         assertFalse(notIncludedEntity.exists());
 
-        File notIncludeSuperDatamap = new File("_TestCgenMap.txt");
+        File notIncludeSuperDatamap = new File("_Antmap_cgen_xml.txt");
         assertFalse(notIncludeSuperDatamap.exists());
+
+        File notIncludedSuperEntity = new File(mapDir, 
convertPath("_ObjEntity.txt"));
+        assertFalse(notIncludedSuperEntity.exists());
     }
 
     private String convertPath(String unixPath) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/52ea45b5/cayenne-ant/src/test/resources/cgenTest.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-ant/src/test/resources/cgenTest.map.xml 
b/cayenne-ant/src/test/resources/cgenTest.map.xml
index 930acbc..d249f0f 100644
--- a/cayenne-ant/src/test/resources/cgenTest.map.xml
+++ b/cayenne-ant/src/test/resources/cgenTest.map.xml
@@ -7,21 +7,16 @@
     <obj-entity name="ObjEntity" className="ObjEntity"/>
     <obj-entity name="ObjEntity1" className="ObjEntity1"/>
     <cgen xmlns="http://cayenne.apache.org/schema/10/cgen";>
-        <objEntity>
-            <name>ObjEntity1</name>
-        </objEntity>
-        <generationMode>all</generationMode>
-        <dataMapTemplate>templates/v4_1/datamap-subclass.vm</dataMapTemplate>
-        
<dataMapSuperclassTemplate>templates/v4_1/datamap-superclass.vm</dataMapSuperclassTemplate>
-        <subclassTemplate>templates/v4_1/subclass.vm</subclassTemplate>
-        <superclassTemplate>templates/v4_1/superclass.vm</superclassTemplate>
-        
<embeddableTemplate>templates/v4_1/embeddable-subclass.vm</embeddableTemplate>
-        
<embeddableSuperclassTemplate>templates/v4_1/embeddable-superclass.vm</embeddableSuperclassTemplate>
+        <destDir>cgenConfigTest</destDir>
+        <excludeEntities>ObjEntity</excludeEntities>
+        <excludeEmbeddables>Embeddable</excludeEmbeddables>
+        <mode>all</mode>
+        <template>templates/v4_1/subclass.vm</template>
+        <superTemplate>templates/v4_1/superclass.vm</superTemplate>
         <outputPattern>*.txt</outputPattern>
         <makePairs>false</makePairs>
         <usePkgPath>true</usePkgPath>
-        <overwriteSubclasses>false</overwriteSubclasses>
+        <overwrite>false</overwrite>
         <createPropertyNames>false</createPropertyNames>
-        <encoding>UTF-8</encoding>
     </cgen>
 </data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/52ea45b5/cayenne-cgen/src/main/java/org/apache/cayenne/gen/CgenConfiguration.java
----------------------------------------------------------------------
diff --git 
a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/CgenConfiguration.java 
b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/CgenConfiguration.java
new file mode 100644
index 0000000..8d4157d
--- /dev/null
+++ b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/CgenConfiguration.java
@@ -0,0 +1,363 @@
+package org.apache.cayenne.gen;
+
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.gen.xml.CgenExtension;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.Embeddable;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.util.XMLEncoder;
+import org.apache.cayenne.util.XMLSerializable;
+
+import java.io.Serializable;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.stream.Collectors;
+
+public class CgenConfiguration implements Serializable, XMLSerializable {
+
+    private Collection<Artifact> artifacts;
+    private Collection<String> entityArtifacts;
+    private Collection<String> excludeEntityArtifacts;
+    private Collection<String> embeddableArtifacts;
+    private Collection<String> excludeEmbeddableArtifacts;
+
+    private String superPkg;
+    private DataMap dataMap;
+
+    private ArtifactsGenerationMode artifactsGenerationMode;
+    private boolean makePairs;
+
+    private Path rootPath;
+    private Path relPath;
+    private boolean overwrite;
+    private boolean usePkgPath;
+
+    private String template;
+    private String superTemplate;
+    private String embeddableTemplate;
+    private String embeddableSuperTemplate;
+    private String queryTemplate;
+    private String querySuperTemplate;
+    private long timestamp;
+    private String outputPattern;
+    private String encoding;
+    private boolean createPropertyNames;
+    private boolean force; // force run generator
+    /**
+     * @since 4.1
+     */
+    private boolean createPKProperties;
+
+    private boolean client;
+
+    public CgenConfiguration() {
+        this.outputPattern = "*.java";
+        this.timestamp = 0L;
+        this.usePkgPath = true;
+        this.makePairs = true;
+
+        this.artifacts = new ArrayList<>();
+        this.entityArtifacts = new ArrayList<>();
+        this.excludeEntityArtifacts = new ArrayList<>();
+        this.embeddableArtifacts = new ArrayList<>();
+        this.excludeEmbeddableArtifacts = new ArrayList<>();
+        this.artifactsGenerationMode = ArtifactsGenerationMode.ENTITY;
+
+        this.template = ClassGenerationAction.SUBCLASS_TEMPLATE;
+        this.superTemplate = ClassGenerationAction.SUPERCLASS_TEMPLATE;
+        this.embeddableTemplate = 
ClassGenerationAction.EMBEDDABLE_SUBCLASS_TEMPLATE;
+        this.embeddableSuperTemplate = 
ClassGenerationAction.EMBEDDABLE_SUPERCLASS_TEMPLATE;
+        this.queryTemplate = ClassGenerationAction.DATAMAP_SUBCLASS_TEMPLATE;
+        this.querySuperTemplate = 
ClassGenerationAction.DATAMAP_SUPERCLASS_TEMPLATE;
+    }
+
+    public void resetCollections(){
+        embeddableArtifacts.clear();
+        entityArtifacts.clear();
+    }
+
+    public String getSuperPkg() {
+        return superPkg;
+    }
+
+    public void setSuperPkg(String superPkg) {
+        this.superPkg = superPkg;
+    }
+
+    public DataMap getDataMap() {
+        return dataMap;
+    }
+
+    public void setDataMap(DataMap dataMap) {
+        this.dataMap = dataMap;
+    }
+
+    public void setArtifactsGenerationMode(String mode) {
+        if (ArtifactsGenerationMode.ENTITY.getLabel().equalsIgnoreCase(mode)) {
+            this.artifactsGenerationMode = ArtifactsGenerationMode.ENTITY;
+        } else {
+            this.artifactsGenerationMode = ArtifactsGenerationMode.ALL;
+        }
+    }
+
+    public String getArtifactsGenerationMode(){
+        return artifactsGenerationMode.getLabel();
+    }
+
+
+    public boolean isMakePairs() {
+        return makePairs;
+    }
+
+    public void setMakePairs(boolean makePairs) {
+        this.makePairs = makePairs;
+    }
+
+    public Path getRootPath() {
+        return rootPath;
+    }
+
+    public void setRootPath(Path rootPath) {
+        this.rootPath = rootPath;
+    }
+
+    public void setRelPath(Path relPath) {
+        this.relPath = relPath;
+    }
+
+    public void setRelPath(String path) {
+               this.relPath = rootPath != null ? 
rootPath.relativize(Paths.get(path)) : Paths.get(path);
+       }
+
+    public boolean isOverwrite() {
+        return overwrite;
+    }
+
+    public void setOverwrite(boolean overwrite) {
+        this.overwrite = overwrite;
+    }
+
+    public boolean isUsePkgPath() {
+        return usePkgPath;
+    }
+
+    public void setUsePkgPath(boolean usePkgPath) {
+        this.usePkgPath = usePkgPath;
+    }
+
+    public String getTemplate() {
+        return template;
+    }
+
+    public void setTemplate(String template) {
+        this.template = template;
+    }
+
+    public String getSuperTemplate() {
+        return superTemplate;
+    }
+
+    public void setSuperTemplate(String superTemplate) {
+        this.superTemplate = superTemplate;
+    }
+
+    public String getEmbeddableTemplate() {
+        return embeddableTemplate;
+    }
+
+    public void setEmbeddableTemplate(String embeddableTemplate) {
+        this.embeddableTemplate = embeddableTemplate;
+    }
+
+    public String getEmbeddableSuperTemplate() {
+        return embeddableSuperTemplate;
+    }
+
+    public void setEmbeddableSuperTemplate(String embeddableSuperTemplate) {
+        this.embeddableSuperTemplate = embeddableSuperTemplate;
+    }
+
+    public String getQueryTemplate() {
+        return queryTemplate;
+    }
+
+    public void setQueryTemplate(String queryTemplate) {
+        this.queryTemplate = queryTemplate;
+    }
+
+    public String getQuerySuperTemplate() {
+        return querySuperTemplate;
+    }
+
+    public void setQuerySuperTemplate(String querySuperTemplate) {
+        this.querySuperTemplate = querySuperTemplate;
+    }
+
+    public long getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(long timestamp) {
+        this.timestamp = timestamp;
+    }
+
+    public String getOutputPattern() {
+        return outputPattern;
+    }
+
+    public void setOutputPattern(String outputPattern) {
+        this.outputPattern = outputPattern;
+    }
+
+    public String getEncoding() {
+        return encoding;
+    }
+
+    public void setEncoding(String encoding) {
+        this.encoding = encoding;
+    }
+
+    public boolean isCreatePropertyNames() {
+        return createPropertyNames;
+    }
+
+    public void setCreatePropertyNames(boolean createPropertyNames) {
+        this.createPropertyNames = createPropertyNames;
+    }
+
+    public boolean isForce() {
+        return force;
+    }
+
+    public void setForce(boolean force) {
+        this.force = force;
+    }
+
+    public boolean isCreatePKProperties() {
+        return createPKProperties;
+    }
+
+    public void setCreatePKProperties(boolean createPKProperties) {
+        this.createPKProperties = createPKProperties;
+    }
+
+    public String getRelPath() {
+        if(relPath == null || relPath.toString().isEmpty()) {
+            return ".";
+        }
+        return relPath.toString();
+    }
+
+    public String getDir(){
+        return rootPath != null ? relPath != null ? 
rootPath.resolve(relPath).toAbsolutePath().normalize().toString() : 
rootPath.toString() : null;
+    }
+
+    public Collection<Artifact> getArtifacts() {
+        return artifacts;
+    }
+
+    public Collection<String> getEntities() {
+        return entityArtifacts;
+    }
+
+    public Collection<String> getEmbeddables() {
+        return embeddableArtifacts;
+    }
+
+    public Path buildPath() {
+               return rootPath != null ? relPath != null ? 
rootPath.resolve(relPath).toAbsolutePath().normalize() : rootPath : relPath;
+       }
+
+    /**
+     * @since 4.1
+     */
+    public void loadEntity(String name) {
+        entityArtifacts.add(name);
+    }
+
+    /**
+     * @since 4.1
+     */
+    public void loadEmbeddable(String name) {
+        embeddableArtifacts.add(name);
+    }
+
+    public void loadEntities(String entities) {
+        excludeEntityArtifacts.addAll(Arrays.asList(entities.split(",")));
+    }
+
+    private String getExcludeEntites() {
+        Collection<String> excludeEntities = dataMap.getObjEntities()
+                .stream()
+                .filter(entity -> !entityArtifacts.contains(entity.getName()))
+                .map(ObjEntity::getName)
+                .collect(Collectors.toList());
+        return org.apache.commons.lang3.StringUtils.join(excludeEntities, ",");
+    }
+
+    public void loadEmbeddables(String embeddables) {
+        
excludeEmbeddableArtifacts.addAll(Arrays.asList(embeddables.split(",")));
+    }
+
+    private String getExcludeEmbeddables() {
+        Collection<String> excludeEmbeddable = dataMap.getEmbeddables()
+                .stream()
+                .filter(embeddable -> 
!embeddableArtifacts.contains(embeddable.getClassName()))
+                .map(Embeddable::getClassName)
+                .collect(Collectors.toList());
+        return org.apache.commons.lang3.StringUtils.join(excludeEmbeddable, 
",");
+    }
+
+       public void resolveExcludeEntities() {
+               entityArtifacts = dataMap.getObjEntities()
+                               .stream()
+                               .filter(entity -> 
!excludeEntityArtifacts.contains(entity.getName()))
+                               .map(ObjEntity::getName)
+                               .collect(Collectors.toList());
+       }
+
+       public void resolveExcludeEmbeddables() {
+       embeddableArtifacts = dataMap.getEmbeddables()
+                               .stream()
+                               .filter(embeddable -> 
!excludeEmbeddableArtifacts.contains(embeddable.getClassName()))
+                               .map(Embeddable::getClassName)
+                               .collect(Collectors.toList());
+       }
+
+    public boolean isClient() {
+        return client;
+    }
+
+    public void setClient(boolean client) {
+        this.client = client;
+    }
+
+    public void addArtifact(Artifact artifact) {
+        artifacts.add(artifact);
+    }
+
+    @Override
+    public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor 
delegate) {
+        encoder.start("cgen")
+                .attribute("xmlns", CgenExtension.NAMESPACE)
+                .simpleTag("excludeEntities", getExcludeEntites())
+                .simpleTag("excludeEmbeddables",getExcludeEmbeddables())
+                .simpleTag("destDir", getRelPath())
+                .simpleTag("mode", this.artifactsGenerationMode.getLabel())
+                .simpleTag("template", this.template)
+                .simpleTag("superTemplate", this.superTemplate)
+                .simpleTag("outputPattern", this.outputPattern)
+                .simpleTag("makePairs", Boolean.toString(this.makePairs))
+                .simpleTag("usePkgPath", Boolean.toString(this.usePkgPath))
+                .simpleTag("overwrite", Boolean.toString(this.overwrite))
+                .simpleTag("createPropertyNames", 
Boolean.toString(this.createPropertyNames))
+                .simpleTag("superPkg", this.superPkg)
+                .simpleTag("createPKProperties", 
Boolean.toString(this.createPKProperties))
+                .simpleTag("client", Boolean.toString(client))
+                .end();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/52ea45b5/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 434421f..36ba514 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
@@ -20,14 +20,9 @@
 package org.apache.cayenne.gen;
 
 import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
-import org.apache.cayenne.gen.xml.CgenExtension;
-import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.Embeddable;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.QueryDescriptor;
-import org.apache.cayenne.util.XMLEncoder;
-import org.apache.cayenne.util.XMLSerializable;
 import org.apache.velocity.Template;
 import org.apache.velocity.VelocityContext;
 import org.apache.velocity.app.VelocityEngine;
@@ -36,12 +31,12 @@ import org.slf4j.Logger;
 import java.io.*;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.util.*;
 import java.util.stream.Collectors;
 
-public class ClassGenerationAction implements Serializable, XMLSerializable {
-       static final String TEMPLATES_DIR_NAME = "templates/v4_1/";
+public class ClassGenerationAction {
+
+       private static final String TEMPLATES_DIR_NAME = "templates/v4_1/";
 
        public static final String SINGLE_CLASS_TEMPLATE = TEMPLATES_DIR_NAME + 
"singleclass.vm";
        public static final String SUBCLASS_TEMPLATE = TEMPLATES_DIR_NAME + 
"subclass.vm";
@@ -58,159 +53,105 @@ public class ClassGenerationAction implements 
Serializable, XMLSerializable {
        public static final String SUPERCLASS_PREFIX = "_";
        private static final String WILDCARD = "*";
 
-       Collection<Artifact> artifacts;
-       private Collection<String> entityArtifacts;
-       private Collection<String> excludeEntityArtifacts;
-       private Collection<String> embeddableArtifacts;
-       private Collection<String> excludeEmbeddableArtifacts;
-
-       protected String superPkg;
-       protected DataMap dataMap;
-
-       protected ArtifactsGenerationMode artifactsGenerationMode;
-       protected boolean makePairs;
-
+       protected CgenConfiguration cgenConfiguration;
        protected Logger logger;
 
-       protected Path rootPath;
-       protected Path relPath;
+    // runtime ivars
+    protected VelocityContext context;
+    protected Map<String, Template> templateCache;
 
-       protected boolean overwrite;
-       protected boolean usePkgPath;
-
-       protected String template;
-       protected String superTemplate;
-       protected String embeddableTemplate;
-       protected String embeddableSuperTemplate;
-       protected String queryTemplate;
-       protected String querySuperTemplate;
-       protected long timestamp;
-       protected String outputPattern;
-       protected String encoding;
-       protected boolean createPropertyNames;
-       protected boolean force; // force run generator
-
-       /**
-        * @since 4.1
-        */
-       protected boolean createPKProperties;
-
-       // runtime ivars
-       protected VelocityContext context;
-       protected Map<String, Template> templateCache;
-
-
-       public ClassGenerationAction() {
-        this.outputPattern = "*.java";
-        this.timestamp = 0L;
-        this.usePkgPath = true;
-        this.makePairs = true;
-        this.context = new VelocityContext();
-        this.templateCache = new HashMap<>(5);
-
-        this.artifacts = new ArrayList<>();
-        this.entityArtifacts = new ArrayList<>();
-        this.excludeEntityArtifacts = new ArrayList<>();
-        this.embeddableArtifacts = new ArrayList<>();
-        this.excludeEmbeddableArtifacts = new ArrayList<>();
-        this.artifactsGenerationMode = ArtifactsGenerationMode.ENTITY;
-
-        this.overwrite = false;
-               this.template = SUBCLASS_TEMPLATE;
-               this.superTemplate = SUPERCLASS_TEMPLATE;
-               this.embeddableTemplate = EMBEDDABLE_SUBCLASS_TEMPLATE;
-               this.embeddableSuperTemplate = EMBEDDABLE_SUPERCLASS_TEMPLATE;
-
-               this.queryTemplate = DATAMAP_SUBCLASS_TEMPLATE;
-               this.querySuperTemplate = DATAMAP_SUPERCLASS_TEMPLATE;
+       public ClassGenerationAction(CgenConfiguration cgenConfiguration) {
+               this.context = new VelocityContext();
+               this.templateCache = new HashMap<>(5);
+               this.cgenConfiguration = cgenConfiguration;
        }
 
-       protected String defaultTemplateName(TemplateType type) {
+       public String defaultTemplateName(TemplateType type) {
                switch (type) {
-               case ENTITY_SINGLE_CLASS:
-                       return ClassGenerationAction.SINGLE_CLASS_TEMPLATE;
-               case ENTITY_SUBCLASS:
-                       return ClassGenerationAction.SUBCLASS_TEMPLATE;
-               case ENTITY_SUPERCLASS:
-                       return ClassGenerationAction.SUPERCLASS_TEMPLATE;
-               case EMBEDDABLE_SUBCLASS:
-                       return 
ClassGenerationAction.EMBEDDABLE_SUBCLASS_TEMPLATE;
-               case EMBEDDABLE_SUPERCLASS:
-                       return 
ClassGenerationAction.EMBEDDABLE_SUPERCLASS_TEMPLATE;
-               case EMBEDDABLE_SINGLE_CLASS:
-                       return 
ClassGenerationAction.EMBEDDABLE_SINGLE_CLASS_TEMPLATE;
-               case DATAMAP_SINGLE_CLASS:
-                       return 
ClassGenerationAction.DATAMAP_SINGLE_CLASS_TEMPLATE;
-               case DATAMAP_SUPERCLASS:
-                       return 
ClassGenerationAction.DATAMAP_SUPERCLASS_TEMPLATE;
-               case DATAMAP_SUBCLASS:
-                       return ClassGenerationAction.DATAMAP_SUBCLASS_TEMPLATE;
-               default:
-                       throw new IllegalArgumentException("Invalid template 
type: " + type);
+                       case ENTITY_SINGLE_CLASS:
+                               return SINGLE_CLASS_TEMPLATE;
+                       case ENTITY_SUBCLASS:
+                               return SUBCLASS_TEMPLATE;
+                       case ENTITY_SUPERCLASS:
+                               return SUPERCLASS_TEMPLATE;
+                       case EMBEDDABLE_SUBCLASS:
+                               return EMBEDDABLE_SUBCLASS_TEMPLATE;
+                       case EMBEDDABLE_SUPERCLASS:
+                               return EMBEDDABLE_SUPERCLASS_TEMPLATE;
+                       case EMBEDDABLE_SINGLE_CLASS:
+                               return EMBEDDABLE_SINGLE_CLASS_TEMPLATE;
+                       case DATAMAP_SINGLE_CLASS:
+                               return DATAMAP_SINGLE_CLASS_TEMPLATE;
+                       case DATAMAP_SUPERCLASS:
+                               return DATAMAP_SUPERCLASS_TEMPLATE;
+                       case DATAMAP_SUBCLASS:
+                               return DATAMAP_SUBCLASS_TEMPLATE;
+                       default:
+                               throw new IllegalArgumentException("Invalid 
template type: " + type);
                }
        }
 
-       private String customTemplateName(TemplateType type) {
+       public String customTemplateName(TemplateType type) {
                switch (type) {
-               case ENTITY_SINGLE_CLASS:
-                       return template;
-               case ENTITY_SUBCLASS:
-                       return template;
-               case ENTITY_SUPERCLASS:
-                       return superTemplate;
-               case EMBEDDABLE_SINGLE_CLASS:
-                       return embeddableTemplate;
-               case EMBEDDABLE_SUBCLASS:
-                       return embeddableTemplate;
-               case EMBEDDABLE_SUPERCLASS:
-                       return embeddableSuperTemplate;
-               case DATAMAP_SINGLE_CLASS:
-                       return queryTemplate;
-               case DATAMAP_SUPERCLASS:
-                       return querySuperTemplate;
-               case DATAMAP_SUBCLASS:
-                       return queryTemplate;
-               default:
-                       throw new IllegalArgumentException("Invalid template 
type: " + type);
+                       case ENTITY_SINGLE_CLASS:
+                               return cgenConfiguration.getTemplate();
+                       case ENTITY_SUBCLASS:
+                               return cgenConfiguration.getTemplate();
+                       case ENTITY_SUPERCLASS:
+                               return cgenConfiguration.getSuperTemplate();
+                       case EMBEDDABLE_SINGLE_CLASS:
+                               return 
cgenConfiguration.getEmbeddableTemplate();
+                       case EMBEDDABLE_SUBCLASS:
+                               return 
cgenConfiguration.getEmbeddableTemplate();
+                       case EMBEDDABLE_SUPERCLASS:
+                               return 
cgenConfiguration.getEmbeddableSuperTemplate();
+                       case DATAMAP_SINGLE_CLASS:
+                               return cgenConfiguration.getQueryTemplate();
+                       case DATAMAP_SUPERCLASS:
+                               return 
cgenConfiguration.getQuerySuperTemplate();
+                       case DATAMAP_SUBCLASS:
+                               return cgenConfiguration.getQueryTemplate();
+                       default:
+                               throw new IllegalArgumentException("Invalid 
template type: " + type);
                }
        }
 
-       /**
-        * VelocityContext initialization method called once per artifact.
-        */
-       private void resetContextForArtifact(Artifact artifact) {
-               StringUtils stringUtils = StringUtils.getInstance();
+    /**
+     * VelocityContext initialization method called once per artifact.
+     */
+    public void resetContextForArtifact(Artifact artifact) {
+        StringUtils stringUtils = StringUtils.getInstance();
 
-               String qualifiedClassName = artifact.getQualifiedClassName();
-               String packageName = stringUtils.stripClass(qualifiedClassName);
-               String className = 
stringUtils.stripPackageName(qualifiedClassName);
+        String qualifiedClassName = artifact.getQualifiedClassName();
+        String packageName = stringUtils.stripClass(qualifiedClassName);
+        String className = stringUtils.stripPackageName(qualifiedClassName);
 
-               String qualifiedBaseClassName = 
artifact.getQualifiedBaseClassName();
-               String basePackageName = 
stringUtils.stripClass(qualifiedBaseClassName);
-               String baseClassName = 
stringUtils.stripPackageName(qualifiedBaseClassName);
+        String qualifiedBaseClassName = artifact.getQualifiedBaseClassName();
+        String basePackageName = 
stringUtils.stripClass(qualifiedBaseClassName);
+        String baseClassName = 
stringUtils.stripPackageName(qualifiedBaseClassName);
 
-               String superClassName = getSuperclassPrefix() + 
stringUtils.stripPackageName(qualifiedClassName);
+        String superClassName = SUPERCLASS_PREFIX + 
stringUtils.stripPackageName(qualifiedClassName);
 
-               String superPackageName = this.superPkg;
-               if (superPackageName == null) {
-                       superPackageName = packageName + ".auto";
-               }
+        String superPackageName = cgenConfiguration.getSuperPkg();
+        if (superPackageName == null) {
+            superPackageName = packageName + ".auto";
+        }
 
-               context.put(Artifact.BASE_CLASS_KEY, baseClassName);
-               context.put(Artifact.BASE_PACKAGE_KEY, basePackageName);
+        context.put(Artifact.BASE_CLASS_KEY, baseClassName);
+        context.put(Artifact.BASE_PACKAGE_KEY, basePackageName);
 
-               context.put(Artifact.SUB_CLASS_KEY, className);
-               context.put(Artifact.SUB_PACKAGE_KEY, packageName);
+        context.put(Artifact.SUB_CLASS_KEY, className);
+        context.put(Artifact.SUB_PACKAGE_KEY, packageName);
 
-               context.put(Artifact.SUPER_CLASS_KEY, superClassName);
-               context.put(Artifact.SUPER_PACKAGE_KEY, superPackageName);
+        context.put(Artifact.SUPER_CLASS_KEY, superClassName);
+        context.put(Artifact.SUPER_PACKAGE_KEY, superPackageName);
 
-               context.put(Artifact.OBJECT_KEY, artifact.getObject());
-               context.put(Artifact.STRING_UTILS_KEY, stringUtils);
+        context.put(Artifact.OBJECT_KEY, artifact.getObject());
+        context.put(Artifact.STRING_UTILS_KEY, stringUtils);
 
-               context.put(Artifact.CREATE_PROPERTY_NAMES, 
createPropertyNames);
-               context.put(Artifact.CREATE_PK_PROPERTIES, createPKProperties);
-       }
+        context.put(Artifact.CREATE_PROPERTY_NAMES, 
cgenConfiguration.isCreatePropertyNames());
+        context.put(Artifact.CREATE_PK_PROPERTIES, 
cgenConfiguration.isCreatePKProperties());
+    }
 
        /**
         * VelocityContext initialization method called once per each artifact 
and
@@ -221,11 +162,50 @@ public class ClassGenerationAction implements 
Serializable, XMLSerializable {
                artifact.postInitContext(context);
        }
 
+       /**
+        * Adds entities to the internal entity list.
+        * @param entities collection
+        *
+        * @since 4.0 throws exception
+        */
+       public void addEntities(Collection<ObjEntity> entities) {
+               if (entities != null) {
+                       for (ObjEntity entity : entities) {
+                               cgenConfiguration.addArtifact(new 
EntityArtifact(entity));
+                       }
+               }
+       }
+
+       public void addEmbeddables(Collection<Embeddable> embeddables) {
+               if (embeddables != null) {
+                       for (Embeddable embeddable : embeddables) {
+                               cgenConfiguration.addArtifact(new 
EmbeddableArtifact(embeddable));
+                       }
+               }
+       }
+
+       public void addQueries(Collection<QueryDescriptor> queries) {
+               if 
(cgenConfiguration.getArtifactsGenerationMode().equals(ArtifactsGenerationMode.ALL.getLabel()))
 {
+                       // TODO: andrus 10.12.2010 - why not also check for 
empty query list??
+                       // Or create a better API for enabling DataMapArtifact
+                       if (queries != null) {
+                               Artifact artifact = new 
DataMapArtifact(cgenConfiguration.getDataMap(), queries);
+                               
if(!cgenConfiguration.getArtifacts().contains(artifact)) {
+                                       cgenConfiguration.addArtifact(artifact);
+                               }
+                       }
+               }
+       }
+
        public void prepareArtifacts() {
-               this.artifacts.clear();
-        addAllEntities();
-        addAllEmbeddables();
-        addQueries(dataMap.getQueryDescriptors());
+               cgenConfiguration.getArtifacts().clear();
+               addEntities(cgenConfiguration.getEntities().stream()
+                               .map(entity -> 
cgenConfiguration.getDataMap().getObjEntity(entity))
+                               .collect(Collectors.toList()));
+               addEmbeddables(cgenConfiguration.getEmbeddables().stream()
+                               .map(embeddable -> 
cgenConfiguration.getDataMap().getEmbeddable(embeddable))
+                               .collect(Collectors.toList()));
+               
addQueries(cgenConfiguration.getDataMap().getQueryDescriptors());
     }
 
        /**
@@ -236,14 +216,14 @@ public class ClassGenerationAction implements 
Serializable, XMLSerializable {
                validateAttributes();
 
                try {
-                       for (Artifact artifact : artifacts) {
+                       for (Artifact artifact : 
cgenConfiguration.getArtifacts()) {
                                execute(artifact);
                        }
                } finally {
                        // must reset engine at the end of class generator run 
to avoid
                        // memory
                        // leaks and stale templates
-                       this.templateCache.clear();
+                       templateCache.clear();
                }
        }
 
@@ -254,7 +234,7 @@ public class ClassGenerationAction implements Serializable, 
XMLSerializable {
 
                resetContextForArtifact(artifact);
 
-               ArtifactGenerationMode artifactMode = makePairs ? 
ArtifactGenerationMode.GENERATION_GAP
+               ArtifactGenerationMode artifactMode = 
cgenConfiguration.isMakePairs() ? ArtifactGenerationMode.GENERATION_GAP
                                : ArtifactGenerationMode.SINGLE_CLASS;
 
                TemplateType[] templateTypes = 
artifact.getTemplateTypes(artifactMode);
@@ -307,10 +287,17 @@ public class ClassGenerationAction implements 
Serializable, XMLSerializable {
         * Called internally from "execute".
         */
        private void validateAttributes() {
-               Path dir = buildPath();
+               Path dir = cgenConfiguration.buildPath();
                if (dir == null) {
                        throw new CayenneRuntimeException("'rootPath' attribute 
is missing.");
                }
+               if(Files.notExists(dir)) {
+                       try {
+                               Files.createDirectories(dir);
+                       } catch (IOException e) {
+                               throw new CayenneRuntimeException("can't create 
directory");
+                       }
+               }
 
                if (!Files.isDirectory(dir)) {
                        throw new CayenneRuntimeException("'destDir' is not a 
directory.");
@@ -343,7 +330,7 @@ public class ClassGenerationAction implements Serializable, 
XMLSerializable {
                // return writer with specified encoding
                FileOutputStream out = new FileOutputStream(outFile);
 
-               return (encoding != null) ? new OutputStreamWriter(out, 
encoding) : new OutputStreamWriter(out);
+               return (cgenConfiguration.getEncoding() != null) ? new 
OutputStreamWriter(out, cgenConfiguration.getEncoding()) : new 
OutputStreamWriter(out);
        }
 
        /**
@@ -355,10 +342,10 @@ public class ClassGenerationAction implements 
Serializable, XMLSerializable {
                String packageName = (String) 
context.get(Artifact.SUPER_PACKAGE_KEY);
                String className = (String) 
context.get(Artifact.SUPER_CLASS_KEY);
 
-               String filename = 
StringUtils.getInstance().replaceWildcardInStringWithString(WILDCARD, 
outputPattern, className);
-               File dest = new File(mkpath(new File(getDir()), packageName), 
filename);
+               String filename = 
StringUtils.getInstance().replaceWildcardInStringWithString(WILDCARD, 
cgenConfiguration.getOutputPattern(), className);
+               File dest = new File(mkpath(new 
File(cgenConfiguration.buildPath().toString()), packageName), filename);
 
-               if (dest.exists() && !fileNeedUpdate(dest, superTemplate)) {
+               if (dest.exists() && !fileNeedUpdate(dest, 
cgenConfiguration.getSuperTemplate())) {
                        return null;
                }
 
@@ -374,21 +361,21 @@ public class ClassGenerationAction implements 
Serializable, XMLSerializable {
                String packageName = (String) 
context.get(Artifact.SUB_PACKAGE_KEY);
                String className = (String) context.get(Artifact.SUB_CLASS_KEY);
 
-               String filename = 
StringUtils.getInstance().replaceWildcardInStringWithString(WILDCARD, 
outputPattern, className);
-               File dest = new File(mkpath(new 
File(Objects.requireNonNull(buildPath()).toString()), packageName), filename);
+               String filename = 
StringUtils.getInstance().replaceWildcardInStringWithString(WILDCARD, 
cgenConfiguration.getOutputPattern(), className);
+               File dest = new File(mkpath(new 
File(Objects.requireNonNull(cgenConfiguration.buildPath()).toString()), 
packageName), filename);
 
                if (dest.exists()) {
                        // no overwrite of subclasses
-                       if (makePairs) {
+                       if (cgenConfiguration.isMakePairs()) {
                                return null;
                        }
 
                        // skip if said so
-                       if (!overwrite) {
+                       if (!cgenConfiguration.isOverwrite()) {
                                return null;
                        }
 
-                       if (!fileNeedUpdate(dest, template)) {
+                       if (!fileNeedUpdate(dest, 
cgenConfiguration.getTemplate())) {
                                return null;
                        }
                }
@@ -402,7 +389,7 @@ public class ClassGenerationAction implements Serializable, 
XMLSerializable {
         * last saved AND the template is older than the destination file
         */
        protected boolean fileNeedUpdate(File dest, String templateFileName) {
-               if(force) {
+               if(cgenConfiguration.isForce()) {
                        return true;
                }
 
@@ -421,7 +408,7 @@ public class ClassGenerationAction implements Serializable, 
XMLSerializable {
         * Is file modified after internal timestamp (usually equal to mtime of 
datamap file)
         */
        protected boolean isOld(File file) {
-               return file.lastModified() > timestamp;
+               return file.lastModified() > cgenConfiguration.getTimestamp();
        }
 
        /**
@@ -431,7 +418,7 @@ public class ClassGenerationAction implements Serializable, 
XMLSerializable {
         */
        private File mkpath(File dest, String pkgName) throws Exception {
 
-               if (!usePkgPath || pkgName == null) {
+               if (!cgenConfiguration.isUsePkgPath() || pkgName == null) {
                        return dest;
                }
 
@@ -445,242 +432,6 @@ public class ClassGenerationAction implements 
Serializable, XMLSerializable {
        }
 
        /**
-        * Adds entities to the internal entity list.
-        * @param entities collection
-        *
-        * @since 4.0 throws exception
-        */
-       public void addEntities(Collection<ObjEntity> entities) {
-               if (entities != null) {
-                       for (ObjEntity entity : entities) {
-                               artifacts.add(new EntityArtifact(entity));
-                       }
-               }
-       }
-
-       public void addEmbeddables(Collection<Embeddable> embeddables) {
-               if (embeddables != null) {
-                       for (Embeddable embeddable : embeddables) {
-                               artifacts.add(new 
EmbeddableArtifact(embeddable));
-                       }
-               }
-       }
-
-       public void addQueries(Collection<QueryDescriptor> queries) {
-               if (artifactsGenerationMode == ArtifactsGenerationMode.ALL) {
-                       // TODO: andrus 10.12.2010 - why not also check for 
empty query list??
-                       // Or create a better API for enabling DataMapArtifact
-                       if (queries != null) {
-                               Artifact artifact = new 
DataMapArtifact(dataMap, queries);
-                               if(!artifacts.contains(artifact)) {
-                                       artifacts.add(artifact);
-                               }
-                       }
-               }
-       }
-
-    private void addAllEntities() {
-               entityArtifacts.forEach(val -> {
-                       Artifact artifact = new 
EntityArtifact(dataMap.getObjEntity(val));
-                       if(!artifacts.contains(artifact)) {
-                               artifacts.add(artifact);
-                       }
-               });
-       }
-
-    private void addAllEmbeddables() {
-               embeddableArtifacts.forEach(val -> {
-                       Artifact artifact = new 
EmbeddableArtifact(dataMap.getEmbeddable(val));
-                       if(!artifacts.contains(artifact)) {
-                               artifacts.add(artifact);
-                       }
-               });
-       }
-
-    /**
-     * @since 4.1
-     */
-       public void loadEntity(String name) {
-               entityArtifacts.add(name);
-       }
-
-       /**
-        * @since 4.1
-        */
-       public void loadEmbeddable(String name) {
-               embeddableArtifacts.add(name);
-       }
-
-       public void setArtifactsGenerationMode(String mode) {
-               if 
(ArtifactsGenerationMode.ENTITY.getLabel().equalsIgnoreCase(mode)) {
-                       this.artifactsGenerationMode = 
ArtifactsGenerationMode.ENTITY;
-               } else {
-                       this.artifactsGenerationMode = 
ArtifactsGenerationMode.ALL;
-               }
-       }
-
-       public Path buildPath() {
-               return rootPath != null ? relPath != null ? 
rootPath.resolve(relPath).toAbsolutePath().normalize() : rootPath : null;
-       }
-
-       public void loadEntities(String entities) {
-               
excludeEntityArtifacts.addAll(Arrays.asList(entities.split(",")));
-       }
-
-       public void resolveExcludeEntities() {
-               entityArtifacts = dataMap.getObjEntities()
-                               .stream()
-                               .filter(entity -> 
!excludeEntityArtifacts.contains(entity.getName()))
-                               .map(ObjEntity::getName)
-                               .collect(Collectors.toList());
-       }
-
-       public void loadEmbeddables(String embeddables) {
-               
excludeEmbeddableArtifacts.addAll(Arrays.asList(embeddables.split(",")));
-       }
-
-       public void resolveExcludeEmbeddables() {
-       embeddableArtifacts = dataMap.getEmbeddables()
-                               .stream()
-                               .filter(embeddable -> 
!excludeEmbeddableArtifacts.contains(embeddable.getClassName()))
-                               .map(Embeddable::getClassName)
-                               .collect(Collectors.toList());
-       }
-
-    public void resetCollections(){
-               this.embeddableArtifacts.clear();
-               this.entityArtifacts.clear();
-       }
-
-       private String getExcludeEntites() {
-               Collection<String> excludeEntities = dataMap.getObjEntities()
-                               .stream()
-                               .filter(entity -> 
!entityArtifacts.contains(entity.getName()))
-                               .map(ObjEntity::getName)
-                               .collect(Collectors.toList());
-               return 
org.apache.commons.lang3.StringUtils.join(excludeEntities, ",");
-       }
-
-       private String getExcludeEmbeddables() {
-               Collection<String> excludeEmbeddable = dataMap.getEmbeddables()
-                               .stream()
-                               .filter(embeddable -> 
!embeddableArtifacts.contains(embeddable.getClassName()))
-                               .map(Embeddable::getClassName)
-                               .collect(Collectors.toList());
-               return 
org.apache.commons.lang3.StringUtils.join(excludeEmbeddable, ",");
-       }
-
-       /**
-        * Returns a String used to prefix class name to create a generated
-        * superclass. Default value is "_".
-        */
-       private String getSuperclassPrefix() {
-               return ClassGenerationAction.SUPERCLASS_PREFIX;
-       }
-
-       public Collection<String> getEmbeddables() {
-               return embeddableArtifacts;
-       }
-
-       /**
-        * @since 4.1
-        */
-       public boolean isCreatePKProperties() {
-               return createPKProperties;
-       }
-
-       public boolean isMakePairs() {
-               return makePairs;
-       }
-
-       public boolean isOverwrite() {
-               return overwrite;
-       }
-
-       public boolean isUsePkgPath() {
-               return usePkgPath;
-       }
-
-       public boolean isCreatePropertyNames() {
-               return createPropertyNames;
-       }
-
-       public String getOutputPattern() {
-               return outputPattern;
-       }
-
-       public String getSuperclassTemplate(){
-               return superTemplate;
-       }
-
-       public DataMap getDataMap() {
-               return dataMap;
-       }
-
-       public String getDir(){
-               return rootPath != null ? relPath != null ? 
rootPath.resolve(relPath).toAbsolutePath().normalize().toString() : 
rootPath.toString() : null;
-       }
-
-       public String getTemplate() {
-               return template;
-       }
-
-       public String getSuperPkg(){
-               return superPkg;
-       }
-
-       public Collection<String> getEntities() {
-               return entityArtifacts;
-       }
-
-       public String getRelPath() {
-       if(relPath == null || relPath.toString().isEmpty()) {
-               return ".";
-               }
-               return relPath.toString();
-       }
-
-       public String getArtifactsGenerationMode(){
-               return artifactsGenerationMode.getLabel();
-       }
-
-       public boolean isForce() {
-               return force;
-       }
-
-       public void setForce(boolean force) {
-               this.force = force;
-       }
-
-       public String getEncoding() {
-               return encoding;
-       }
-
-       public String getEmbeddableTemplate() {
-               return embeddableTemplate;
-       }
-
-       public String getEmbeddableSuperTemplate() {
-               return embeddableSuperTemplate;
-       }
-
-       public String getQueryTemplate() {
-               return queryTemplate;
-       }
-
-       public String getQuerySuperTemplate() {
-               return querySuperTemplate;
-       }
-
-       /**
-        * Sets an optional shared nVelocityContext. Useful with tools like VPP 
that
-        * can set custom values in the context, not known to Cayenne.
-        */
-       public void setContext(VelocityContext context) {
-               this.context = context;
-       }
-
-       /**
         * Injects an optional logger that will be used to trace generated 
files at
         * the info level.
         */
@@ -688,132 +439,20 @@ public class ClassGenerationAction implements 
Serializable, XMLSerializable {
                this.logger = logger;
        }
 
-       public void setTimestamp(long timestamp) {
-               this.timestamp = timestamp;
+       public CgenConfiguration getCgenConfiguration() {
+               return cgenConfiguration;
        }
 
        /**
-        * Sets file encoding. If set to null, default system encoding will be 
used.
-        */
-       public void setEncoding(String encoding) {
-               this.encoding = encoding;
-       }
-
-       /**
-        * Sets "superPkg" property value.
-        */
-       public void setSuperPkg(String superPkg) {
-               this.superPkg = superPkg;
-       }
-
-       /**
-        * @param dataMap The dataMap to set.
-        */
-       public void setDataMap(DataMap dataMap) {
-               this.dataMap = dataMap;
-       }
-
-       public void setEmbeddableTemplate(String embeddableTemplate) {
-               this.embeddableTemplate = embeddableTemplate;
-       }
-
-       public void setEmbeddableSuperTemplate(String embeddableSuperTemplate) {
-               this.embeddableSuperTemplate = embeddableSuperTemplate;
-       }
-
-       /**
-        * Sets <code>overwrite</code> property.
-        */
-       public void setOverwrite(boolean overwrite) {
-               this.overwrite = overwrite;
-       }
-
-       /**
-        * Sets <code>makepairs</code> property.
-        */
-       public void setMakePairs(boolean makePairs) {
-               this.makePairs = makePairs;
-       }
-
-       /**
-        * Sets <code>template</code> property.
-        */
-       public void setTemplate(String template) {
-               this.template = template;
-       }
-
-       /**
-        * Sets <code>superTemplate</code> property.
-        */
-       public void setSuperTemplate(String superTemplate) {
-               this.superTemplate = superTemplate;
-       }
-
-       public void setQueryTemplate(String queryTemplate) {
-               this.queryTemplate = queryTemplate;
-       }
-
-       public void setQuerySuperTemplate(String querySuperTemplate) {
-               this.querySuperTemplate = querySuperTemplate;
-       }
-
-       /**
-        * Sets <code>usepkgpath</code> property.
-        */
-       public void setUsePkgPath(boolean usePkgPath) {
-               this.usePkgPath = usePkgPath;
-       }
-
-       /**
-        * Sets <code>outputPattern</code> property.
-        */
-       public void setOutputPattern(String outputPattern) {
-               this.outputPattern = outputPattern;
-       }
-
-       /**
-        * Sets <code>createPropertyNames</code> property.
-        */
-       public void setCreatePropertyNames(boolean createPropertyNames) {
-               this.createPropertyNames = createPropertyNames;
-       }
-
-       /**
-        * @since 4.1
+        * Sets an optional shared VelocityContext. Useful with tools like VPP 
that
+        * can set custom values in the context, not known to Cayenne.
         */
-       public void setCreatePKProperties(boolean createPKProperties) {
-               this.createPKProperties = createPKProperties;
-       }
-
-       public void setRootPath(Path rootPath) {
-               this.rootPath = rootPath;
-       }
-
-       public void setRelPath(Path relPath) {
-               this.relPath = relPath;
+       public void setContext(VelocityContext context) {
+               this.context = context;
        }
 
-       public void setRelPath(String path) {
-               this.relPath = rootPath.relativize(Paths.get(path));
+       public void setCgenConfiguration(CgenConfiguration cgenConfiguration) {
+               this.cgenConfiguration = cgenConfiguration;
        }
 
-       @Override
-       public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor 
delegate) {
-               encoder.start("cgen")
-                               .attribute("xmlns", CgenExtension.NAMESPACE)
-                               .simpleTag("excludeEntities", 
getExcludeEntites())
-                               
.simpleTag("excludeEmbeddables",getExcludeEmbeddables())
-                               .simpleTag("outputDirectory", getRelPath())
-                               .simpleTag("generationMode", 
this.artifactsGenerationMode.getLabel())
-                               .simpleTag("subclassTemplate", this.template)
-                               .simpleTag("superclassTemplate", 
this.superTemplate)
-                               .simpleTag("outputPattern", this.outputPattern)
-                               .simpleTag("makePairs", 
Boolean.toString(this.makePairs))
-                               .simpleTag("usePkgPath", 
Boolean.toString(this.usePkgPath))
-                               .simpleTag("overwriteSubclasses", 
Boolean.toString(this.overwrite))
-                               .simpleTag("createPropertyNames", 
Boolean.toString(this.createPropertyNames))
-                               .simpleTag("superPkg", this.superPkg)
-                               .simpleTag("createPKProperties", 
Boolean.toString(this.createPKProperties))
-                               .end();
-       }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/52ea45b5/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 c8880aa..b823c85 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
@@ -30,18 +30,27 @@ import java.util.Collection;
  */
 public class ClientClassGenerationAction extends ClassGenerationAction {
 
+    private static final String TEMPLATES_DIR_NAME = "templates/v4_1/";
     public static final String SUBCLASS_TEMPLATE = TEMPLATES_DIR_NAME + 
"client-subclass.vm";
     public static final String SUPERCLASS_TEMPLATE = TEMPLATES_DIR_NAME + 
"client-superclass.vm";
     public static final String SINGLE_CLASS_TEMPLATE = TEMPLATES_DIR_NAME + 
"client-singleclass.vm";
-    
+
     public static final String DMAP_SUBCLASS_TEMPLATE = TEMPLATES_DIR_NAME + 
"client-datamap-subclass.vm";
     public static final String DMAP_SUPERCLASS_TEMPLATE = TEMPLATES_DIR_NAME + 
"client-datamap-superclass.vm";
-    public static final String DMAP_SINGLE_CLASS_TEMPLATE = TEMPLATES_DIR_NAME 
+ "client-datamap-singleclass.vm";
+    public static final String DATAMAP_SINGLE_CLASS_TEMPLATE = 
TEMPLATES_DIR_NAME + "client-datamap-singleclass.vm";
 
     public static final String CLIENT_SUPERCLASS_PREFIX = "_Client";
 
+    public ClientClassGenerationAction(CgenConfiguration cgenConfiguration) {
+        super(cgenConfiguration);
+        cgenConfiguration.setTemplate(SUBCLASS_TEMPLATE);
+        cgenConfiguration.setSuperTemplate(SUPERCLASS_TEMPLATE);
+        cgenConfiguration.setQueryTemplate(DMAP_SUBCLASS_TEMPLATE);
+        cgenConfiguration.setQuerySuperTemplate(DMAP_SUPERCLASS_TEMPLATE);
+    }
+
     @Override
-    protected String defaultTemplateName(TemplateType type) {
+    public String defaultTemplateName(TemplateType type) {
         switch (type) {
             case ENTITY_SUBCLASS:
                 return SUBCLASS_TEMPLATE;
@@ -51,18 +60,18 @@ public class ClientClassGenerationAction extends 
ClassGenerationAction {
                 return SINGLE_CLASS_TEMPLATE;
 
             case EMBEDDABLE_SUBCLASS:
-                return EMBEDDABLE_SUBCLASS_TEMPLATE;
+                return ClassGenerationAction.EMBEDDABLE_SUBCLASS_TEMPLATE;
             case EMBEDDABLE_SUPERCLASS:
-                return EMBEDDABLE_SUPERCLASS_TEMPLATE;
+                return ClassGenerationAction.EMBEDDABLE_SUPERCLASS_TEMPLATE;
             case EMBEDDABLE_SINGLE_CLASS:
-                return EMBEDDABLE_SINGLE_CLASS_TEMPLATE;
-            
+                return ClassGenerationAction.EMBEDDABLE_SINGLE_CLASS_TEMPLATE;
+
             case DATAMAP_SUPERCLASS:
-                return ClientClassGenerationAction.DMAP_SUPERCLASS_TEMPLATE;
+                return DMAP_SUPERCLASS_TEMPLATE;
             case DATAMAP_SUBCLASS:
-                return ClientClassGenerationAction.DMAP_SUBCLASS_TEMPLATE;
+                return DMAP_SUBCLASS_TEMPLATE;
             case DATAMAP_SINGLE_CLASS:
-                return DMAP_SINGLE_CLASS_TEMPLATE;
+                return DATAMAP_SINGLE_CLASS_TEMPLATE;
 
             default:
                 throw new IllegalArgumentException("Unsupported template type: 
" + type);
@@ -73,14 +82,14 @@ public class ClientClassGenerationAction extends 
ClassGenerationAction {
      * @since 4.0 throws exception
      */
     @Override
-    public void addEntities(Collection<ObjEntity> entities) throws 
CayenneRuntimeException {
-        if (!dataMap.isClientSupported()) {
+    public void addEntities(Collection<ObjEntity> entities) {
+        if (!cgenConfiguration.getDataMap().isClientSupported()) {
             throw new CayenneRuntimeException("Can't create client classes. 
Check client supported option on DataMap configuration.");
         }
         if (entities != null) {
             for (ObjEntity entity : entities) {
                 if (!entity.isServerOnly()) {
-                    artifacts.add(new ClientEntityArtifact(entity));
+                    cgenConfiguration.addArtifact(new 
ClientEntityArtifact(entity));
                 }
             }
         }
@@ -88,9 +97,9 @@ public class ClientClassGenerationAction extends 
ClassGenerationAction {
 
     @Override
     public void addQueries(Collection<QueryDescriptor> queries) {
-        if (artifactsGenerationMode == ArtifactsGenerationMode.ALL) {
+        if 
(cgenConfiguration.getArtifactsGenerationMode().equals(ArtifactsGenerationMode.ALL.getLabel()))
 {
             if (queries != null) {
-                artifacts.add(new ClientDataMapArtifact(dataMap, queries));
+                cgenConfiguration.addArtifact(new 
ClientDataMapArtifact(cgenConfiguration.getDataMap(), queries));
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/52ea45b5/cayenne-cgen/src/main/java/org/apache/cayenne/gen/xml/CgenConfigHandler.java
----------------------------------------------------------------------
diff --git 
a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/xml/CgenConfigHandler.java 
b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/xml/CgenConfigHandler.java
index 7883ca2..1f4dd5e 100644
--- 
a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/xml/CgenConfigHandler.java
+++ 
b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/xml/CgenConfigHandler.java
@@ -20,7 +20,7 @@ package org.apache.cayenne.gen.xml;
 
 import org.apache.cayenne.configuration.xml.DataChannelMetaData;
 import org.apache.cayenne.configuration.xml.NamespaceAwareNestedTagHandler;
-import org.apache.cayenne.gen.ClassGenerationAction;
+import org.apache.cayenne.gen.CgenConfiguration;
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 
@@ -33,23 +33,24 @@ public class CgenConfigHandler extends 
NamespaceAwareNestedTagHandler{
 
     public static final String CONFIG_TAG = "cgen";
 
-    private static final String OUTPUT_DIRECTORY_TAG = "outputDirectory";
-    private static final String GENERATION_MODE_TAG = "generationMode";
-    private static final String SUBCLASS_TEMPLATE_TAG = "subclassTemplate";
+    private static final String OUTPUT_DIRECTORY_TAG = "destDir";
+    private static final String GENERATION_MODE_TAG = "mode";
+    private static final String SUBCLASS_TEMPLATE_TAG = "template";
     private static final String SUPERCLASS_TEMPLATE_TAG = "superclassTemplate";
     private static final String OUTPUT_PATTERN_TAG = "outputPattern";
     private static final String MAKE_PAIRS_TAG = "makePairs";
     private static final String USE_PKG_PATH_TAG = "usePkgPath";
-    private static final String OVERWRITE_SUBCLASSES_TAG = 
"overwriteSubclasses";
+    private static final String OVERWRITE_SUBCLASSES_TAG = "overwrite";
     private static final String CREATE_PROPERTY_NAMES_TAG = 
"createPropertyNames";
     private static final String EXCLUDE_ENTITIES_TAG = "excludeEntities";
     private static final String EXCLUDE_EMBEDDABLES_TAG = "excludeEmbeddables";
     private static final String CREATE_PK_PROPERTIES = "createPKProperties";
+    private static final String CLIENT_TAG = "client";
 
     public static final String TRUE = "true";
 
     private DataChannelMetaData metaData;
-    private ClassGenerationAction configuration;
+    private CgenConfiguration configuration;
 
     CgenConfigHandler(NamespaceAwareNestedTagHandler parentHandler, 
DataChannelMetaData metaData) {
         super(parentHandler);
@@ -106,6 +107,9 @@ public class CgenConfigHandler extends 
NamespaceAwareNestedTagHandler{
             case CREATE_PK_PROPERTIES:
                 createPkPropertiesTag(data);
                 break;
+            case CLIENT_TAG:
+                createClient(data);
+                break;
         }
     }
 
@@ -249,8 +253,22 @@ public class CgenConfigHandler extends 
NamespaceAwareNestedTagHandler{
         }
     }
 
+    private void createClient(String data) {
+        if(data.trim().length() == 0) {
+            return;
+        }
+
+        if(configuration != null) {
+            if(data.equals(TRUE)) {
+                configuration.setClient(true);
+            } else {
+                configuration.setClient(false);
+            }
+        }
+    }
+
     private void createConfig() {
-        configuration = new ClassGenerationAction();
+        configuration = new CgenConfiguration();
         loaderContext.addDataMapListener(dataMap -> {
             configuration.setDataMap(dataMap);
             configuration.resolveExcludeEntities();

http://git-wip-us.apache.org/repos/asf/cayenne/blob/52ea45b5/cayenne-cgen/src/main/java/org/apache/cayenne/gen/xml/CgenSaverDelegate.java
----------------------------------------------------------------------
diff --git 
a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/xml/CgenSaverDelegate.java 
b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/xml/CgenSaverDelegate.java
index fc23e50..aa008b1 100644
--- 
a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/xml/CgenSaverDelegate.java
+++ 
b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/xml/CgenSaverDelegate.java
@@ -19,7 +19,7 @@
 package org.apache.cayenne.gen.xml;
 
 import org.apache.cayenne.configuration.xml.DataChannelMetaData;
-import org.apache.cayenne.gen.ClassGenerationAction;
+import org.apache.cayenne.gen.CgenConfiguration;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.project.extension.BaseSaverDelegate;
 
@@ -41,7 +41,7 @@ public class CgenSaverDelegate extends BaseSaverDelegate{
 
     @Override
     public Void visitDataMap(DataMap dataMap) {
-        ClassGenerationAction cgen = metaData.get(dataMap, 
ClassGenerationAction.class);
+        CgenConfiguration cgen = metaData.get(dataMap, 
CgenConfiguration.class);
         if(cgen != null){
             resolveOutputDir(cgen);
             encoder.nested(cgen, getParentDelegate());
@@ -49,8 +49,11 @@ public class CgenSaverDelegate extends BaseSaverDelegate{
         return null;
     }
 
-    private void resolveOutputDir(ClassGenerationAction classGenerationAction) 
{
-        Path prevPath = classGenerationAction.buildPath();
+    private void resolveOutputDir(CgenConfiguration cgenConfiguration) {
+        if(cgenConfiguration.getRootPath() == null) {
+            return;
+        }
+        Path prevPath = cgenConfiguration.buildPath();
         URL url = getBaseDirectory().getURL();
         if(url != null) {
             Path resourcePath = Paths.get(url.getPath());
@@ -59,9 +62,8 @@ public class CgenSaverDelegate extends BaseSaverDelegate{
             }
 
             if(prevPath != null && resourcePath.compareTo(prevPath) != 0) {
-                classGenerationAction.setRootPath(resourcePath);
                 Path relPath = resourcePath.relativize(prevPath);
-                classGenerationAction.setRelPath(relPath);
+                cgenConfiguration.setRelPath(relPath);
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/52ea45b5/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEmbeddableFilterAction.java
----------------------------------------------------------------------
diff --git 
a/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEmbeddableFilterAction.java
 
b/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEmbeddableFilterAction.java
new file mode 100644
index 0000000..00ab16a
--- /dev/null
+++ 
b/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEmbeddableFilterAction.java
@@ -0,0 +1,29 @@
+package org.apache.cayenne.tools;
+
+import org.apache.cayenne.dbsync.filter.NameFilter;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.Embeddable;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+class CayenneGeneratorEmbeddableFilterAction {
+
+    private NameFilter nameFilter;
+
+    Collection<Embeddable> getFilteredEmbeddables(DataMap mainDataMap) {
+        Collection<Embeddable> embeddables = new 
ArrayList<>(mainDataMap.getEmbeddables());
+
+        // filter out excluded entities...
+
+        // note that unlike entity, embeddable is matched by class name as it 
doesn't
+        // have a symbolic name...
+        embeddables.removeIf(e -> !nameFilter.isIncluded(e.getClassName()));
+
+        return embeddables;
+    }
+
+    public void setNameFilter(NameFilter nameFilter) {
+        this.nameFilter = nameFilter;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/52ea45b5/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEntityFilterAction.java
----------------------------------------------------------------------
diff --git 
a/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEntityFilterAction.java
 
b/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEntityFilterAction.java
index 4d068d8..7d53536 100644
--- 
a/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEntityFilterAction.java
+++ 
b/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEntityFilterAction.java
@@ -26,7 +26,6 @@ import org.apache.cayenne.map.ObjEntity;
 import java.net.MalformedURLException;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Iterator;
 
 /**
  * Performs entity filtering to build a collection of entities that should be 
used in
@@ -43,17 +42,10 @@ class CayenneGeneratorEntityFilterAction {
         Collection<Embeddable> embeddables = new 
ArrayList<>(mainDataMap.getEmbeddables());
 
         // filter out excluded entities...
-        Iterator<Embeddable> it = embeddables.iterator();
 
-        while (it.hasNext()) {
-            Embeddable e = it.next();
-
-            // note that unlike entity, embeddable is matched by class name as 
it doesn't
-            // have a symbolic name...
-            if (!nameFilter.isIncluded(e.getClassName())) {
-                it.remove();
-            }
-        }
+        // note that unlike entity, embeddable is matched by class name as it 
doesn't
+        // have a symbolic name...
+        embeddables.removeIf(e -> !nameFilter.isIncluded(e.getClassName()));
 
         return embeddables;
     }
@@ -64,13 +56,7 @@ class CayenneGeneratorEntityFilterAction {
         Collection<ObjEntity> entities = new 
ArrayList<>(mainDataMap.getObjEntities());
 
         // filter out excluded entities...
-        Iterator<ObjEntity> it = entities.iterator();
-        while (it.hasNext()) {
-            ObjEntity e = it.next();
-            if (e.isGeneric() || client && !e.isClientAllowed() || 
!nameFilter.isIncluded(e.getName())) {
-                it.remove();
-            }
-        }
+        entities.removeIf(e -> e.isGeneric() || client && !e.isClientAllowed() 
|| !nameFilter.isIncluded(e.getName()));
 
         return entities;
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/52ea45b5/cayenne-cgen/src/test/java/org/apache/cayenne/gen/ClassGenerationActionTest.java
----------------------------------------------------------------------
diff --git 
a/cayenne-cgen/src/test/java/org/apache/cayenne/gen/ClassGenerationActionTest.java
 
b/cayenne-cgen/src/test/java/org/apache/cayenne/gen/ClassGenerationActionTest.java
index 721a129..89dfaaa 100644
--- 
a/cayenne-cgen/src/test/java/org/apache/cayenne/gen/ClassGenerationActionTest.java
+++ 
b/cayenne-cgen/src/test/java/org/apache/cayenne/gen/ClassGenerationActionTest.java
@@ -48,10 +48,13 @@ public class ClassGenerationActionTest {
        protected ClassGenerationAction action;
        protected Collection<StringWriter> writers;
 
+       protected CgenConfiguration cgenConfiguration;
+
        @Before
        public void setUp() throws Exception {
                writers = new ArrayList<>(3);
-               action = new ClassGenerationAction() {
+               cgenConfiguration = new CgenConfiguration();
+               action = new ClassGenerationAction(cgenConfiguration) {
 
                        @Override
                        protected Writer openWriter(TemplateType templateType) 
throws Exception {
@@ -74,8 +77,8 @@ public class ClassGenerationActionTest {
                ObjEntity testEntity1 = new ObjEntity("TE1");
                testEntity1.setClassName("org.example.TestClass1");
 
-               action.setMakePairs(true);
-               action.setSuperPkg("org.example.auto");
+               cgenConfiguration.setMakePairs(true);
+               cgenConfiguration.setSuperPkg("org.example.auto");
 
                List<String> generated = execute(new 
EntityArtifact(testEntity1));
                assertNotNull(generated);
@@ -116,7 +119,7 @@ public class ClassGenerationActionTest {
                relationship.setCollectionType("java.util.Map");
                testEntity1.addRelationship(relationship);
 
-               action.setMakePairs(true);
+               cgenConfiguration.setMakePairs(true);
 
                List<String> generated = execute(new 
EntityArtifact(testEntity1));
                assertNotNull(generated);
@@ -143,7 +146,7 @@ public class ClassGenerationActionTest {
                testEntity1.addAttribute(attr);
                testEntity1.addAttribute(attr1);
 
-               action.setMakePairs(true);
+               cgenConfiguration.setMakePairs(true);
 
                List<String> generated = execute(new 
EntityArtifact(testEntity1));
                assertNotNull(generated);
@@ -213,7 +216,7 @@ public class ClassGenerationActionTest {
 
                if (isClient) {
 
-                       action = new ClientClassGenerationAction() {
+                       action = new 
ClientClassGenerationAction(cgenConfiguration) {
                                @Override
                                protected Writer openWriter(TemplateType 
templateType) throws Exception {
                                        StringWriter writer = new 
StringWriter();
@@ -225,7 +228,7 @@ public class ClassGenerationActionTest {
 
                }
 
-               action.setMakePairs(true);
+               cgenConfiguration.setMakePairs(true);
 
                List<String> generated = execute(new 
EntityArtifact(testEntity1));
                assertNotNull(generated);
@@ -261,10 +264,10 @@ public class ClassGenerationActionTest {
                File file = mock(File.class);
                when(file.lastModified()).thenReturn(1000L);
 
-               action.setTimestamp(0);
+               cgenConfiguration.setTimestamp(0);
                assertTrue(action.isOld(file));
 
-               action.setTimestamp(2000L);
+               cgenConfiguration.setTimestamp(2000L);
                assertFalse(action.isOld(file));
        }
 
@@ -273,23 +276,23 @@ public class ClassGenerationActionTest {
                File file = mock(File.class);
                when(file.lastModified()).thenReturn(1000L);
 
-               action.setTimestamp(0);
-               action.setForce(false);
+               cgenConfiguration.setTimestamp(0);
+               cgenConfiguration.setForce(false);
 
                assertFalse(action.fileNeedUpdate(file, null));
 
-               action.setTimestamp(2000L);
-               action.setForce(false);
+               cgenConfiguration.setTimestamp(2000L);
+               cgenConfiguration.setForce(false);
 
                assertTrue(action.fileNeedUpdate(file, null));
 
-               action.setTimestamp(0);
-               action.setForce(true);
+               cgenConfiguration.setTimestamp(0);
+               cgenConfiguration.setForce(true);
 
                assertTrue(action.fileNeedUpdate(file, null));
 
-               action.setTimestamp(2000L);
-               action.setForce(true);
+               cgenConfiguration.setTimestamp(2000L);
+               cgenConfiguration.setForce(true);
 
                assertTrue(action.fileNeedUpdate(file, null));
        }

Reply via email to