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 2020/02/05 08:57:22 UTC

[cayenne] branch master updated: Refactor cgen UI code

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 2ed52e7  Refactor cgen UI code
2ed52e7 is described below

commit 2ed52e70d8a25da64aff9683cf6daa8a5d14c47f
Author: Nikita Timofeev <st...@gmail.com>
AuthorDate: Wed Feb 5 11:27:35 2020 +0300

    Refactor cgen UI code
---
 .../cayenne/modeler/editor/DataMapTabbedView.java  |   2 +-
 .../modeler/editor/cgen/ClientModeController.java  |   2 +-
 .../editor/cgen/CodeGeneratorController.java       | 313 ++++++++++++-
 .../editor/cgen/CodeGeneratorControllerBase.java   | 506 ---------------------
 .../modeler/editor/cgen/CodeGeneratorPane.java     |   8 +-
 .../modeler/editor/cgen/CustomModeController.java  |   2 +-
 .../modeler/editor/cgen/CustomModePanel.java       |   2 +-
 .../modeler/editor/cgen/GeneratorController.java   |  10 +-
 .../editor/cgen/GeneratorControllerPanel.java      |   2 +-
 .../editor/cgen/GeneratorTabController.java        |  15 +-
 .../modeler/editor/cgen/SelectionModel.java        | 201 ++++++++
 .../editor/cgen/StandardModeController.java        |   2 +-
 .../modeler/editor/cgen/StandardModePanel.java     |   4 +-
 13 files changed, 525 insertions(+), 544 deletions(-)

diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DataMapTabbedView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DataMapTabbedView.java
index 7a5fdf2..e949078 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DataMapTabbedView.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DataMapTabbedView.java
@@ -71,7 +71,7 @@ public class DataMapTabbedView extends JTabbedPane{
 
         addChangeListener(tab -> {
             if(isCgenTabActive()) {
-                codeGeneratorController.startup(mediator.getCurrentDataMap());
+                codeGeneratorController.initFromModel();
             } else if(isDbImportTabActive()) {
                 dbImportView.initFromModel();
             }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/ClientModeController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/ClientModeController.java
index 02f28a2..4cf77d7 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/ClientModeController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/ClientModeController.java
@@ -27,7 +27,7 @@ import org.apache.cayenne.gen.ClientClassGenerationAction;
  */
 public class ClientModeController extends StandardModeController {
 
-    public ClientModeController(CodeGeneratorControllerBase parent) {
+    public ClientModeController(CodeGeneratorController parent) {
         super(parent);
     }
 
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CodeGeneratorController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CodeGeneratorController.java
index 7ee45ae..29882f3 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CodeGeneratorController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CodeGeneratorController.java
@@ -19,11 +19,21 @@
 
 package org.apache.cayenne.modeler.editor.cgen;
 
+import javax.swing.Icon;
+import javax.swing.JLabel;
 import javax.swing.JOptionPane;
-import java.awt.Component;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.function.Predicate;
+import java.util.prefs.Preferences;
+import java.util.stream.Collectors;
 
 import org.apache.cayenne.configuration.event.DataMapEvent;
 import org.apache.cayenne.configuration.event.DataMapListener;
@@ -34,6 +44,8 @@ import org.apache.cayenne.gen.ClassGenerationAction;
 import org.apache.cayenne.gen.ClassGenerationActionFactory;
 import org.apache.cayenne.gen.ClientClassGenerationAction;
 import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.Embeddable;
+import org.apache.cayenne.map.Entity;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.event.EmbeddableEvent;
 import org.apache.cayenne.map.event.EmbeddableListener;
@@ -41,10 +53,15 @@ import org.apache.cayenne.map.event.EntityEvent;
 import org.apache.cayenne.map.event.ObjEntityListener;
 import org.apache.cayenne.modeler.ProjectController;
 import org.apache.cayenne.modeler.dialog.ErrorDebugDialog;
+import org.apache.cayenne.modeler.dialog.pref.GeneralPreferences;
 import org.apache.cayenne.modeler.editor.DbImportController;
 import org.apache.cayenne.modeler.util.CayenneController;
+import org.apache.cayenne.modeler.util.CellRenderers;
+import org.apache.cayenne.modeler.util.ModelerUtil;
 import org.apache.cayenne.swing.BindingBuilder;
 import org.apache.cayenne.tools.CayenneToolsModuleProvider;
+import org.apache.cayenne.validation.ValidationFailure;
+import org.apache.cayenne.validation.ValidationResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -52,11 +69,22 @@ import org.slf4j.LoggerFactory;
  * @since 4.1
  * A controller for the class generator dialog.
  */
-public class CodeGeneratorController extends CodeGeneratorControllerBase implements ObjEntityListener, EmbeddableListener, DataMapListener {
+public class CodeGeneratorController extends CayenneController implements ObjEntityListener, EmbeddableListener, DataMapListener {
     /**
      * Logger to print stack traces
      */
     private static Logger logObj = LoggerFactory.getLogger(ErrorDebugDialog.class);
+    protected static Icon errorIcon = ModelerUtil.buildIcon("icon-error.png");
+    public static final String SELECTED_PROPERTY = "selected";
+
+    protected ProjectController projectController;
+    protected ValidationResult lastValidationResult;
+
+    protected List<Object> classes;
+    protected SelectionModel selectionModel;
+    protected Object currentClass;
+
+    protected boolean initFromModel;
 
     protected CodeGeneratorPane view;
 
@@ -65,17 +93,22 @@ public class CodeGeneratorController extends CodeGeneratorControllerBase impleme
     private ConcurrentMap<DataMap, GeneratorController> prevGeneratorController;
 
     public CodeGeneratorController(CayenneController parent, ProjectController projectController) {
-        super(parent, projectController);
+        super(parent);
         this.classesSelector = new ClassesTabController(this);
         this.generatorSelector = new GeneratorTabController(this);
         this.view = new CodeGeneratorPane(generatorSelector.getView(), classesSelector.getView());
         this.prevGeneratorController = new ConcurrentHashMap<>();
+        this.projectController = projectController;
+        this.classes = new ArrayList<>();
+        this.selectionModel = new SelectionModel();
         initBindings();
         initListeners();
     }
 
-    public void startup(DataMap dataMap) {
-        super.startup(dataMap);
+    public void initFromModel() {
+        initFromModel = true;
+        prepareClasses(projectController.getCurrentDataMap());
+        DataMap dataMap = projectController.getCurrentDataMap();
         classesSelectedAction();
         CgenConfiguration cgenConfiguration = createConfiguration();
         GeneratorController modeController = prevGeneratorController.get(dataMap) != null
@@ -117,9 +150,7 @@ public class CodeGeneratorController extends CodeGeneratorControllerBase impleme
     }
 
     protected void initBindings() {
-        BindingBuilder builder = new BindingBuilder(
-                getApplication().getBindingFactory(),
-                this);
+        BindingBuilder builder = new BindingBuilder(getApplication().getBindingFactory(), this);
 
         builder.bindToAction(view.getGenerateButton(), "generateAction()");
         builder.bindToAction(this, "classesSelectedAction()", SELECTED_PROPERTY);
@@ -177,17 +208,269 @@ public class CodeGeneratorController extends CodeGeneratorControllerBase impleme
         view.getGenerateButton().setEnabled(enable);
     }
 
+    private void prepareClasses(DataMap dataMap) {
+        classes.clear();
+        classes.add(dataMap);
+        classes.addAll(dataMap.getObjEntities());
+        classes.addAll(dataMap.getEmbeddables());
+        selectionModel.initCollectionsForSelection(dataMap);
+    }
+
+    /**
+     * Creates a class generator for provided selections.
+     */
+    public CgenConfiguration createConfiguration() {
+        DataMap map = projectController.getCurrentDataMap();
+        CgenConfiguration cgenConfiguration = projectController.getApplication().getMetaData().get(map, CgenConfiguration.class);
+        if(cgenConfiguration != null){
+            addToSelectedEntities(cgenConfiguration.getEntities());
+            addToSelectedEmbeddables(cgenConfiguration.getEmbeddables());
+            cgenConfiguration.setForce(true);
+            return cgenConfiguration;
+        }
+
+        cgenConfiguration = new CgenConfiguration(false);
+        cgenConfiguration.setForce(true);
+        cgenConfiguration.setDataMap(map);
+
+        Path basePath = Paths.get(ModelerUtil.initOutputFolder());
+
+        // TODO: this should be done in actual generation, not here
+        // no such folder
+        if (!Files.exists(basePath)) {
+            try {
+                Files.createDirectories(basePath);
+            } catch (IOException e) {
+                JOptionPane.showMessageDialog(getView(), "Can't create directory. Select a different one.");
+                return null;
+            }
+        }
+        // not a directory
+        if (!Files.isDirectory(basePath)) {
+            JOptionPane.showMessageDialog(this.getView(), basePath + " is not a valid directory.");
+            return null;
+        }
+
+        cgenConfiguration.setRootPath(basePath);
+        Preferences preferences = application.getPreferencesNode(GeneralPreferences.class, "");
+        if (preferences != null) {
+            cgenConfiguration.setEncoding(preferences.get(GeneralPreferences.ENCODING_PREFERENCE, null));
+        }
+
+        addToSelectedEntities(map.getObjEntities()
+                .stream()
+                .map(Entity::getName)
+                .collect(Collectors.toList()));
+        addToSelectedEmbeddables(map.getEmbeddables()
+                .stream()
+                .map(Embeddable::getClassName)
+                .collect(Collectors.toList()));
+        getApplication().getMetaData().add(map, cgenConfiguration);
+        projectController.setDirty(true);
+
+        return cgenConfiguration;
+    }
+
+    public List<Object> getClasses() {
+        return classes;
+    }
+
+    public void validate(GeneratorController validator) {
+        ValidationResult validationResult = new ValidationResult();
+        if (validator != null) {
+            for (Object classObj : classes) {
+                if (classObj instanceof ObjEntity) {
+                    validator.validateEntity(validationResult, (ObjEntity) classObj, false);
+                } else if (classObj instanceof Embeddable) {
+                    validator.validateEmbeddable(validationResult, (Embeddable) classObj);
+                }
+            }
+        }
+        this.lastValidationResult = validationResult;
+    }
+
+    public boolean updateSelection(Predicate<Object> predicate) {
+        boolean modified = selectionModel.updateSelection(predicate, classes);
+
+        for (Object classObj : classes) {
+            if(classObj instanceof DataMap) {
+                boolean select = predicate.test(classObj);
+                updateArtifactGenerationMode(classObj, select);
+            }
+        }
+
+        if (modified) {
+            firePropertyChange(SELECTED_PROPERTY, null, null);
+        }
+
+        return modified;
+    }
+
+    private void updateArtifactGenerationMode(Object classObj, boolean selected) {
+        DataMap dataMap = (DataMap) classObj;
+        CgenConfiguration cgenConfiguration = projectController.getApplication().getMetaData().get(dataMap, CgenConfiguration.class);
+        if(selected) {
+            cgenConfiguration.setArtifactsGenerationMode("all");
+        } else {
+            cgenConfiguration.setArtifactsGenerationMode("entity");
+        }
+    }
+
+    public boolean isSelected() {
+        return selectionModel.isSelected(currentClass);
+    }
+
+    public void setSelected(boolean selectedFlag) {
+        if (currentClass instanceof DataMap) {
+            updateArtifactGenerationMode(currentClass, selectedFlag);
+        }
+        if (selectionModel.setSelected(currentClass, selectedFlag)) {
+            firePropertyChange(SELECTED_PROPERTY, null, null);
+        }
+    }
+
+    /**
+     * Returns the first encountered validation problem for an antity matching the name or
+     * null if the entity is valid or the entity is not present.
+     */
+    public JLabel getProblem(Object obj) {
+        String name = null;
+        if (obj instanceof ObjEntity) {
+            name = ((ObjEntity) obj).getName();
+        } else if (obj instanceof Embeddable) {
+            name = ((Embeddable) obj).getClassName();
+        }
+
+        ValidationFailure validationFailure = null;
+        if (lastValidationResult != null) {
+            List<ValidationFailure> failures = lastValidationResult.getFailures(name);
+            if (!failures.isEmpty()) {
+                validationFailure = failures.get(0);
+            }
+        }
+
+        JLabel labelIcon = new JLabel();
+        labelIcon.setVisible(true);
+        if(validationFailure != null) {
+            labelIcon.setIcon(errorIcon);
+            labelIcon.setToolTipText(validationFailure.getDescription());
+        }
+        return labelIcon;
+    }
+
+    public JLabel getItemName(Object obj) {
+        String className;
+        Icon icon;
+        if (obj instanceof Embeddable) {
+            className = ((Embeddable) obj).getClassName();
+            icon = CellRenderers.iconForObject(new Embeddable());
+        } else if(obj instanceof ObjEntity) {
+            className = ((ObjEntity) obj).getName();
+            icon = CellRenderers.iconForObject(new ObjEntity());
+        } else {
+            className = ((DataMap) obj).getName();
+            icon = CellRenderers.iconForObject(new DataMap());
+        }
+        JLabel labelIcon = new JLabel();
+        labelIcon.setIcon(icon);
+        labelIcon.setVisible(true);
+        labelIcon.setText(className);
+        return labelIcon;
+    }
+
+    public Object getCurrentClass() {
+        return currentClass;
+    }
+
+    public void setCurrentClass(Object currentClass) {
+        this.currentClass = currentClass;
+    }
+
+    public void updateSelectedEntities(){
+        updateEntities();
+        updateEmbeddables();
+    }
+
+    CgenConfiguration getCurrentConfiguration() {
+        DataMap map = getProjectController().getCurrentDataMap();
+        return projectController.getApplication().getMetaData().get(map, CgenConfiguration.class);
+    }
+
+    private void updateEntities() {
+        CgenConfiguration cgenConfiguration = getCurrentConfiguration();
+        if(cgenConfiguration != null) {
+            cgenConfiguration.getEntities().clear();
+            for(ObjEntity entity: selectionModel.getSelectedEntities(classes)) {
+                cgenConfiguration.loadEntity(entity);
+            }
+        }
+    }
+
+    private void updateEmbeddables() {
+        CgenConfiguration cgenConfiguration = getCurrentConfiguration();
+        if(cgenConfiguration != null) {
+            cgenConfiguration.getEmbeddables().clear();
+            for(Embeddable embeddable : selectionModel.getSelectedEmbeddables(classes)) {
+                cgenConfiguration.loadEmbeddable(embeddable.getClassName());
+            }
+        }
+    }
+
+    private void addToSelectedEntities(Collection<String> entities) {
+        selectionModel.addSelectedEntities(entities);
+        updateEntities();
+    }
+
+    void addEntity(DataMap dataMap, ObjEntity objEntity) {
+        prepareClasses(dataMap);
+        selectionModel.addSelectedEntity(objEntity.getName());
+        CgenConfiguration cgenConfiguration = getCurrentConfiguration();
+        if(cgenConfiguration != null) {
+            cgenConfiguration.loadEntity(objEntity);
+        }
+    }
+
+    private void addToSelectedEmbeddables(Collection<String> embeddables) {
+        selectionModel.addSelectedEmbeddables(embeddables);
+        updateEmbeddables();
+    }
+
+
+    public int getSelectedEntitiesSize() {
+        return selectionModel.getSelectedEntitiesCount();
+    }
+
+    public int getSelectedEmbeddablesSize() {
+        return selectionModel.getSelecetedEmbeddablesCount();
+    }
+
+    public boolean isDataMapSelected() {
+        return selectionModel.getSelectedDataMapsCount() > 0;
+    }
+
+    public ProjectController getProjectController() {
+        return projectController;
+    }
+
+    public boolean isInitFromModel() {
+        return initFromModel;
+    }
+
+    public void setInitFromModel(boolean initFromModel) {
+        this.initFromModel = initFromModel;
+    }
+
     @Override
     public void objEntityChanged(EntityEvent e) {}
 
     @Override
     public void objEntityAdded(EntityEvent e) {
-        super.addEntity(e.getEntity().getDataMap(), (ObjEntity) e.getEntity());
+        addEntity(e.getEntity().getDataMap(), (ObjEntity) e.getEntity());
     }
 
     @Override
     public void objEntityRemoved(EntityEvent e) {
-        super.removeFromSelectedEntities((ObjEntity) e.getEntity());
+        selectionModel.removeFromSelectedEntities((ObjEntity) e.getEntity());
         DataMap map = e.getEntity().getDataMap();
         CgenConfiguration cgenConfiguration = projectController.getApplication().getMetaData().get(map, CgenConfiguration.class);
         if(cgenConfiguration != null) {
@@ -200,12 +483,18 @@ public class CodeGeneratorController extends CodeGeneratorControllerBase impleme
 
     @Override
     public void embeddableAdded(EmbeddableEvent e, DataMap map) {
-        super.addEmbeddable(e.getEmbeddable().getDataMap(), e.getEmbeddable());
+        prepareClasses(map);
+        String embeddableClassName = e.getEmbeddable().getClassName();
+        selectionModel.addSelectedEmbeddable(embeddableClassName);
+        CgenConfiguration cgenConfiguration = getCurrentConfiguration();
+        if(cgenConfiguration != null) {
+            cgenConfiguration.loadEmbeddable(embeddableClassName);
+        }
     }
 
     @Override
     public void embeddableRemoved(EmbeddableEvent e, DataMap map) {
-        super.removeFromSelectedEmbeddables(e.getEmbeddable());
+        selectionModel.removeFromSelectedEmbeddables(e.getEmbeddable());
         CgenConfiguration cgenConfiguration = projectController.getApplication().getMetaData().get(map, CgenConfiguration.class);
         if(cgenConfiguration != null) {
             cgenConfiguration.getEmbeddables().remove(e.getEmbeddable().getClassName());
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CodeGeneratorControllerBase.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CodeGeneratorControllerBase.java
deleted file mode 100644
index 375960a..0000000
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CodeGeneratorControllerBase.java
+++ /dev/null
@@ -1,506 +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
- *
- *    https://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.modeler.editor.cgen;
-
-import javax.swing.Icon;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import java.awt.Component;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Predicate;
-import java.util.prefs.Preferences;
-import java.util.stream.Collectors;
-
-import org.apache.cayenne.gen.CgenConfiguration;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.Embeddable;
-import org.apache.cayenne.map.Entity;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.modeler.ProjectController;
-import org.apache.cayenne.modeler.dialog.pref.GeneralPreferences;
-import org.apache.cayenne.modeler.util.CayenneController;
-import org.apache.cayenne.modeler.util.CellRenderers;
-import org.apache.cayenne.modeler.util.ModelerUtil;
-import org.apache.cayenne.validation.ValidationFailure;
-import org.apache.cayenne.validation.ValidationResult;
-
-/**
- * @since 4.1
- * A base superclass of a top controller for the code generator. Defines all common model
- * parts used in class generation.
- *
- */
-public abstract class CodeGeneratorControllerBase extends CayenneController {
-
-    protected static Icon errorIcon = ModelerUtil.buildIcon("icon-error.png");
-    public static final String SELECTED_PROPERTY = "selected";
-
-    protected DataMap dataMap;
-    protected ValidationResult validation;
-    protected List<Object> classes;
-    private Set<String> selectedEntities;
-    private Set<String> selectedEmbeddables;
-    private Set<String> isDataMapSelected;
-    private Map<DataMap, Set<String>> selectedEntitiesForDataMap;
-    private Map<DataMap, Set<String>> selectedEmbeddablesForDataMap;
-    private Map<DataMap, Set<String>> selectedDataMaps;
-    protected transient Object currentClass;
-    protected ProjectController projectController;
-
-    protected boolean initFromModel;
-
-    public CodeGeneratorControllerBase(CayenneController parent, ProjectController projectController) {
-        super(parent);
-        this.projectController = projectController;
-        this.classes = new ArrayList<>();
-        this.selectedEntitiesForDataMap = new HashMap<>();
-        this.selectedEmbeddablesForDataMap = new HashMap<>();
-        this.selectedDataMaps = new HashMap<>();
-        this.selectedEntities = new HashSet<>();
-        this.selectedEmbeddables = new HashSet<>();
-        this.isDataMapSelected = new HashSet<>();
-    }
-
-    public void startup(DataMap dataMap){
-        initFromModel = true;
-        this.dataMap = dataMap;
-        prepareClasses(dataMap);
-    }
-
-    private void prepareClasses(DataMap dataMap) {
-        classes.clear();
-        this.classes.add(dataMap);
-        this.classes.addAll(dataMap.getObjEntities());
-        this.classes.addAll(dataMap.getEmbeddables());
-        initCollectionsForSelection(dataMap);
-    }
-
-    private void initCollectionsForSelection(DataMap dataMap) {
-        selectedEntities = selectedEntitiesForDataMap.compute(dataMap, (key,value) ->
-                value == null ? new HashSet<>() : value);
-        selectedEmbeddables = selectedEmbeddablesForDataMap.compute(dataMap, (key, value) ->
-                value == null ? new HashSet<>() : value);
-        isDataMapSelected = selectedDataMaps.compute(dataMap, (key, value) ->
-                value == null ? new HashSet<>() : value);
-    }
-
-    /**
-     * Creates a class generator for provided selections.
-     */
-    public CgenConfiguration createConfiguration() {
-        DataMap map = projectController.getCurrentDataMap();
-        CgenConfiguration cgenConfiguration = projectController.getApplication().getMetaData().get(map, CgenConfiguration.class);
-        if(cgenConfiguration != null){
-            addToSelectedEntities(cgenConfiguration.getEntities());
-            addToSelectedEmbeddables(cgenConfiguration.getEmbeddables());
-            cgenConfiguration.setForce(true);
-            return cgenConfiguration;
-        }
-
-        cgenConfiguration = new CgenConfiguration(false);
-        cgenConfiguration.setForce(true);
-        cgenConfiguration.setDataMap(map);
-
-        Path basePath = Paths.get(ModelerUtil.initOutputFolder());
-
-        // no such folder
-        if (!Files.exists(basePath)) {
-            try {
-                Files.createDirectories(basePath);
-            } catch (IOException e) {
-                JOptionPane.showMessageDialog(getView(), "Can't create directory. Select a different one.");
-                return null;
-            }
-        }
-
-        // not a directory
-        if (!Files.isDirectory(basePath)) {
-            JOptionPane.showMessageDialog(this.getView(), basePath + " is not a valid directory.");
-            return null;
-        }
-
-        cgenConfiguration.setRootPath(basePath);
-        Preferences preferences = application.getPreferencesNode(GeneralPreferences.class, "");
-        if (preferences != null) {
-            cgenConfiguration.setEncoding(preferences.get(GeneralPreferences.ENCODING_PREFERENCE, null));
-        }
-
-        addToSelectedEntities(map.getObjEntities()
-                .stream()
-                .map(Entity::getName)
-                .collect(Collectors.toList()));
-        addToSelectedEmbeddables(map.getEmbeddables()
-                .stream()
-                .map(Embeddable::getClassName)
-                .collect(Collectors.toList()));
-        getApplication().getMetaData().add(map, cgenConfiguration);
-        projectController.setDirty(true);
-
-        return cgenConfiguration;
-    }
-
-    public List<Object> getClasses() {
-        return classes;
-    }
-
-    public abstract Component getView();
-
-    public void validate(GeneratorController validator) {
-
-        ValidationResult validationBuffer = new ValidationResult();
-
-        if (validator != null) {
-            for (Object classObj : classes) {
-                if (classObj instanceof ObjEntity) {
-                    validator.validateEntity(
-                            validationBuffer,
-                            (ObjEntity) classObj,
-                            false);
-                }
-                else if (classObj instanceof Embeddable) {
-                    validator.validateEmbeddable(validationBuffer, (Embeddable) classObj);
-                }
-            }
-
-        }
-
-        this.validation = validationBuffer;
-    }
-
-    public boolean updateSelection(Predicate<Object> predicate) {
-        boolean modified = false;
-
-        for (Object classObj : classes) {
-            boolean select = predicate.test(classObj);
-            if (classObj instanceof ObjEntity) {
-
-                if (select) {
-                    if(selectedEntities.add(((ObjEntity) classObj).getName())) {
-                        modified = true;
-                    }
-                }
-                else {
-                    if(selectedEntities.remove(((ObjEntity) classObj).getName())) {
-                        modified = true;
-                    }
-                }
-            }
-            else if (classObj instanceof Embeddable) {
-                if (select) {
-                    if(selectedEmbeddables.add(((Embeddable) classObj).getClassName())) {
-                        modified = true;
-                    }
-                }
-                else {
-                    if(selectedEmbeddables.remove(((Embeddable) classObj).getClassName())) {
-                        modified = true;
-                    }
-                }
-            } else if (classObj instanceof DataMap) {
-                updateArtifactGenerationMode(classObj, select);
-                if(select) {
-                    if(isDataMapSelected.add(((DataMap) classObj).getName())) {
-                        modified = true;
-                    }
-                } else {
-                    if(isDataMapSelected.remove(((DataMap) classObj).getName())) {
-                        modified = true;
-                    }
-                }
-            }
-
-        }
-
-        if (modified) {
-            firePropertyChange(SELECTED_PROPERTY, null, null);
-        }
-
-        return modified;
-    }
-
-    private List<Embeddable> getSelectedEmbeddables() {
-        List<Embeddable> selected = new ArrayList<>(selectedEmbeddables.size());
-        for (Object classObj : classes) {
-            if(classObj instanceof Embeddable) {
-                String name = ((Embeddable) classObj).getClassName();
-                if(selectedEmbeddables.contains(name)) {
-                    selected.add((Embeddable) classObj);
-                }
-            }
-        }
-
-        return selected;
-    }
-
-    private List<ObjEntity> getSelectedEntities() {
-        List<ObjEntity> selected = new ArrayList<>(selectedEntities.size());
-        for (Object classObj : classes) {
-            if(classObj instanceof ObjEntity) {
-                String name = ((ObjEntity) classObj).getName();
-                if(selectedEntities.contains(name)) {
-                    selected.add(((ObjEntity) classObj));
-                }
-            }
-        }
-
-        return selected;
-    }
-
-    private void updateArtifactGenerationMode(Object classObj, boolean selected) {
-        DataMap dataMap = (DataMap) classObj;
-        CgenConfiguration cgenConfiguration = projectController.getApplication().getMetaData().get(dataMap, CgenConfiguration.class);
-        if(selected) {
-            cgenConfiguration.setArtifactsGenerationMode("all");
-        } else {
-            cgenConfiguration.setArtifactsGenerationMode("entity");
-        }
-    }
-
-    public boolean isSelected() {
-        return isSelected(currentClass);
-    }
-
-    public boolean isSelected(Object currentClass) {
-        if (currentClass instanceof ObjEntity) {
-            return selectedEntities
-                    .contains(((ObjEntity) currentClass).getName());
-        }
-        if (currentClass instanceof Embeddable) {
-            return selectedEmbeddables
-                    .contains(((Embeddable) currentClass).getClassName());
-        }
-        if(currentClass instanceof DataMap) {
-            return isDataMapSelected
-                    .contains(((DataMap) currentClass).getName());
-        }
-        return false;
-    }
-
-    public void setSelected(boolean selectedFlag) {
-        setSelected(currentClass, selectedFlag);
-    }
-
-    public void setSelected(Object currentClass, boolean selectedFlag) {
-        if (currentClass == null) {
-            return;
-        }
-        if (currentClass instanceof ObjEntity) {
-            if (selectedFlag) {
-                if (selectedEntities.add(((ObjEntity) currentClass).getName())) {
-                    firePropertyChange(SELECTED_PROPERTY, null, null);
-                }
-            } else {
-                if (selectedEntities.remove(((ObjEntity) currentClass).getName())) {
-                    firePropertyChange(SELECTED_PROPERTY, null, null);
-                }
-            }
-        }
-        if (currentClass instanceof Embeddable) {
-            if (selectedFlag) {
-                if (selectedEmbeddables.add(((Embeddable) currentClass).getClassName())) {
-                    firePropertyChange(SELECTED_PROPERTY, null, null);
-                }
-            } else {
-                if (selectedEmbeddables
-                        .remove(((Embeddable) currentClass).getClassName())) {
-                    firePropertyChange(SELECTED_PROPERTY, null, null);
-                }
-            }
-        }
-        if(currentClass instanceof DataMap) {
-            updateArtifactGenerationMode(currentClass, selectedFlag);
-            if(selectedFlag) {
-                if(isDataMapSelected.add(dataMap.getName())) {
-                    firePropertyChange(SELECTED_PROPERTY, null, null);
-                }
-            } else {
-                if(isDataMapSelected
-                        .remove(((DataMap) currentClass).getName())) {
-                    firePropertyChange(SELECTED_PROPERTY, null, null);
-                }
-            }
-        }
-    }
-
-    /**
-     * Returns the first encountered validation problem for an antity matching the name or
-     * null if the entity is valid or the entity is not present.
-     */
-    public JLabel getProblem(Object obj) {
-        String name = null;
-        if (obj instanceof ObjEntity) {
-            name = ((ObjEntity) obj).getName();
-        } else if (obj instanceof Embeddable) {
-            name = ((Embeddable) obj).getClassName();
-        }
-
-        ValidationFailure validationFailure = null;
-        if (validation != null) {
-            List<ValidationFailure> failures = validation.getFailures(name);
-            if (!failures.isEmpty()) {
-                validationFailure = failures.get(0);
-            }
-        }
-
-        JLabel labelIcon = new JLabel();
-        labelIcon.setVisible(true);
-        if(validationFailure != null) {
-            labelIcon.setIcon(errorIcon);
-            labelIcon.setToolTipText(validationFailure.getDescription());
-        }
-        return labelIcon;
-    }
-
-    public JLabel getItemName(Object obj) {
-        String className;
-        Icon icon;
-        if (obj instanceof Embeddable) {
-            className = ((Embeddable) obj).getClassName();
-            icon = CellRenderers.iconForObject(new Embeddable());
-        } else if(obj instanceof ObjEntity) {
-            className = ((ObjEntity) obj).getName();
-            icon = CellRenderers.iconForObject(new ObjEntity());
-        } else {
-            className = ((DataMap) obj).getName();
-            icon = CellRenderers.iconForObject(new DataMap());
-        }
-        JLabel labelIcon = new JLabel();
-        labelIcon.setIcon(icon);
-        labelIcon.setVisible(true);
-        labelIcon.setText(className);
-        return labelIcon;
-    }
-
-    public Object getCurrentClass() {
-        return currentClass;
-    }
-
-    public void setCurrentClass(Object currentClass) {
-        this.currentClass = currentClass;
-    }
-
-    public void updateSelectedEntities(){
-        updateEntities();
-        updateEmbeddables();
-    }
-
-    CgenConfiguration getCurrentConfiguration() {
-        DataMap map = getProjectController().getCurrentDataMap();
-        return projectController.getApplication().getMetaData().get(map, CgenConfiguration.class);
-    }
-
-    private void updateEntities() {
-        CgenConfiguration cgenConfiguration = getCurrentConfiguration();
-        if(cgenConfiguration != null) {
-            cgenConfiguration.getEntities().clear();
-            for(ObjEntity entity: getSelectedEntities()) {
-                cgenConfiguration.loadEntity(entity);
-            }
-        }
-    }
-
-    private void updateEmbeddables() {
-        CgenConfiguration cgenConfiguration = getCurrentConfiguration();
-        if(cgenConfiguration != null) {
-            cgenConfiguration.getEmbeddables().clear();
-            for(Embeddable embeddable : getSelectedEmbeddables()) {
-                cgenConfiguration.loadEmbeddable(embeddable.getClassName());
-            }
-        }
-    }
-
-    private void addToSelectedEntities(Collection<String> entities) {
-        selectedEntities.addAll(entities);
-        updateEntities();
-    }
-
-    void addEntity(DataMap dataMap, ObjEntity objEntity) {
-        prepareClasses(dataMap);
-        selectedEntities.add(objEntity.getName());
-        CgenConfiguration cgenConfiguration = getCurrentConfiguration();
-        if(cgenConfiguration != null) {
-            cgenConfiguration.loadEntity(objEntity);
-        }
-    }
-
-    private void addToSelectedEmbeddables(Collection<String> embeddables) {
-        selectedEmbeddables.addAll(embeddables);
-        updateEmbeddables();
-    }
-
-    void addEmbeddable(DataMap dataMap, Embeddable embeddable) {
-        prepareClasses(dataMap);
-        selectedEmbeddables.add(embeddable.getClassName());
-        CgenConfiguration cgenConfiguration = getCurrentConfiguration();
-        if(cgenConfiguration != null) {
-            cgenConfiguration.loadEmbeddable(embeddable.getClassName());
-        }
-    }
-
-    public int getSelectedEntitiesSize() {
-        return selectedEntities != null ? selectedEntities.size() : 0;
-    }
-
-    public int getSelectedEmbeddablesSize() {
-        return selectedEmbeddables != null ? selectedEmbeddables.size() : 0;
-    }
-
-    public boolean isDataMapSelected() {
-        return isDataMapSelected != null && isDataMapSelected.size() == 1;
-    }
-
-    public DataMap getDataMap() {
-        return dataMap;
-    }
-
-    public ProjectController getProjectController() {
-        return projectController;
-    }
-
-    public boolean isInitFromModel() {
-        return initFromModel;
-    }
-
-    public void setInitFromModel(boolean initFromModel) {
-        this.initFromModel = initFromModel;
-    }
-
-    public abstract void enableGenerateButton(boolean enabled);
-
-    void removeFromSelectedEntities(ObjEntity objEntity) {
-        initCollectionsForSelection(objEntity.getDataMap());
-        selectedEntities.remove(objEntity.getName());
-    }
-
-    void removeFromSelectedEmbeddables(Embeddable embeddable) {
-        initCollectionsForSelection(embeddable.getDataMap());
-        selectedEmbeddables.remove(embeddable.getClassName());
-    }
-}
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CodeGeneratorPane.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CodeGeneratorPane.java
index 4000b7b..ee41300 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CodeGeneratorPane.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CodeGeneratorPane.java
@@ -40,7 +40,6 @@ import java.awt.FlowLayout;
  */
 public class CodeGeneratorPane extends JPanel {
 
-    private JPanel toolBarPanel;
     private JButton generateButton;
     private JCheckBox checkAll;
     private JLabel checkAllLabel;
@@ -49,7 +48,7 @@ public class CodeGeneratorPane extends JPanel {
         super();
         this.setLayout(new BorderLayout());
 
-        this.toolBarPanel = new JPanel();
+        JPanel toolBarPanel = new JPanel();
         toolBarPanel.setLayout(new BorderLayout());
 
         FormLayout layout = new FormLayout(
@@ -66,8 +65,7 @@ public class CodeGeneratorPane extends JPanel {
         checkAll.addItemListener(event -> {
             if (checkAll.isSelected()) {
                 checkAllLabel.setText("Uncheck All Classess");
-            }
-            else {
+            } else {
                 checkAllLabel.setText("Check All Classes");
             }
         });
@@ -83,7 +81,7 @@ public class CodeGeneratorPane extends JPanel {
                 generatorPanel,
                 ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
                 ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
-        scrollPane.setPreferredSize(new Dimension(150,400));
+        scrollPane.setPreferredSize(new Dimension(150, 400));
 
         // assemble
         splitPane.setRightComponent(scrollPane);
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CustomModeController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CustomModeController.java
index 760f2eb..6d5be73 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CustomModeController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CustomModeController.java
@@ -42,7 +42,7 @@ public class CustomModeController extends GeneratorController {
 
     protected CustomModePanel view;
 
-    public CustomModeController(CodeGeneratorControllerBase parent) {
+    public CustomModeController(CodeGeneratorController parent) {
         super(parent);
         bind();
         initListeners();
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CustomModePanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CustomModePanel.java
index 7bb7912..9b7e265 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CustomModePanel.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CustomModePanel.java
@@ -55,7 +55,7 @@ public class CustomModePanel extends GeneratorControllerPanel {
 
     private JButton manageTemplatesLink;
 
-    CustomModePanel(ProjectController projectController, CodeGeneratorControllerBase codeGeneratorControllerBase) {
+    CustomModePanel(ProjectController projectController, CodeGeneratorController codeGeneratorControllerBase) {
         super(projectController, codeGeneratorControllerBase);
         JComboBox<String> superclassField = new JComboBox<>();
         this.superclassTemplate = new ComboBoxAdapter<String>(superclassField) {
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/GeneratorController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/GeneratorController.java
index 1c08e54..ba856cb 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/GeneratorController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/GeneratorController.java
@@ -51,7 +51,7 @@ public abstract class GeneratorController extends CayenneController {
 
     protected CgenConfiguration cgenConfiguration;
 
-    public GeneratorController(CodeGeneratorControllerBase parent) {
+    public GeneratorController(CodeGeneratorController parent) {
         super(parent);
 
         createView();
@@ -63,8 +63,8 @@ public abstract class GeneratorController extends CayenneController {
         bindingBuilder.bindToAction(outputSelect, "selectOutputFolderAction()");
     }
 
-    protected CodeGeneratorControllerBase getParentController() {
-        return (CodeGeneratorControllerBase) getParent();
+    protected CodeGeneratorController getParentController() {
+        return (CodeGeneratorController) getParent();
     }
 
     protected abstract void createView();
@@ -76,8 +76,8 @@ public abstract class GeneratorController extends CayenneController {
         this.cgenConfiguration = cgenConfiguration;
         getView().getOutputFolder().setText(cgenConfiguration.buildPath().toString());
         if(cgenConfiguration.getArtifactsGenerationMode().equalsIgnoreCase("all")) {
-            ((CodeGeneratorControllerBase) parent).setCurrentClass(cgenConfiguration.getDataMap());
-            ((CodeGeneratorControllerBase) parent).setSelected(true);
+            getParentController().setCurrentClass(cgenConfiguration.getDataMap());
+            getParentController().setSelected(true);
         }
     }
 
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/GeneratorControllerPanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/GeneratorControllerPanel.java
index 140bbf6..8b424fb 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/GeneratorControllerPanel.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/GeneratorControllerPanel.java
@@ -39,7 +39,7 @@ public class GeneratorControllerPanel extends JPanel {
     protected JButton selectOutputFolder;
     protected ProjectController projectController;
 
-    public GeneratorControllerPanel(ProjectController projectController, CodeGeneratorControllerBase codeGeneratorControllerBase) {
+    public GeneratorControllerPanel(ProjectController projectController, CodeGeneratorController codeGeneratorControllerBase) {
         this.projectController = projectController;
         this.outputFolder = new TextAdapter(new JTextField()) {
             @Override
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/GeneratorTabController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/GeneratorTabController.java
index 8ff0dbd..d7a6121 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/GeneratorTabController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/GeneratorTabController.java
@@ -47,7 +47,7 @@ public class GeneratorTabController extends CayenneController {
     protected Map<String, GeneratorController> controllers;
     protected PreferenceDetail preferences;
 
-    public GeneratorTabController(CodeGeneratorControllerBase parent) {
+    public GeneratorTabController(CodeGeneratorController parent) {
         super(parent);
         this.controllers = new HashMap<>(3);
         controllers.put(STANDARD_OBJECTS_MODE, new StandardModeController(parent));
@@ -55,20 +55,19 @@ public class GeneratorTabController extends CayenneController {
         controllers.put(ADVANCED_MODE, new CustomModeController(parent));
         Component[] modePanels = new Component[GENERATION_MODES.length];
         for (int i = 0; i < GENERATION_MODES.length; i++) {
-            modePanels[i] = controllers.get(GENERATION_MODES[i])
-                    .getView();
+            modePanels[i] = controllers.get(GENERATION_MODES[i]).getView();
         }
         this.view = new GeneratorTabPanel(GENERATION_MODES, modePanels);
         initBindings();
         view.setPreferredSize(new Dimension(550, 480));
     }
 
-    public Component getView() {
+    public GeneratorTabPanel getView() {
         return view;
     }
 
-    protected CodeGeneratorControllerBase getParentController() {
-        return (CodeGeneratorControllerBase) getParent();
+    protected CodeGeneratorController getParentController() {
+        return (CodeGeneratorController) getParent();
     }
 
     public PreferenceDetail getPreferences() {
@@ -82,14 +81,14 @@ public class GeneratorTabController extends CayenneController {
             CgenConfiguration cgenConfiguration = getParentController().createConfiguration();
             modeController.updateConfiguration(cgenConfiguration);
             controllers.get(name).initForm(cgenConfiguration);
-            ((CodeGeneratorController)getParentController()).getPrevGeneratorController().put(cgenConfiguration.getDataMap(), modeController);
+            getParentController().getPrevGeneratorController().put(cgenConfiguration.getDataMap(), modeController);
         });
     }
 
     public void setSelectedController(GeneratorController generatorController) {
         for(String key : controllers.keySet()) {
             if(generatorController.equals(controllers.get(key))) {
-                ((GeneratorTabPanel)getView()).getGenerationMode().setSelectedItem(key);
+                getView().getGenerationMode().setSelectedItem(key);
             }
         }
     }
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/SelectionModel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/SelectionModel.java
new file mode 100644
index 0000000..3ef4a1e
--- /dev/null
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/SelectionModel.java
@@ -0,0 +1,201 @@
+/*****************************************************************
+ *   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
+ *
+ *    https://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.modeler.editor.cgen;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Predicate;
+
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.Embeddable;
+import org.apache.cayenne.map.ObjEntity;
+
+/**
+ * @since 4.2
+ */
+class SelectionModel {
+    private Set<String> selectedEntities;
+    private Set<String> selectedEmbeddables;
+    private Set<String> selectedDataMaps;
+
+    private Map<DataMap, Set<String>> selectedEntitiesForDataMap;
+    private Map<DataMap, Set<String>> selectedEmbeddablesForDataMap;
+    private Map<DataMap, Set<String>> selectedDataMapsForDataMap;
+
+    SelectionModel() {
+        selectedEntitiesForDataMap = new HashMap<>();
+        selectedEmbeddablesForDataMap = new HashMap<>();
+        selectedDataMapsForDataMap = new HashMap<>();
+        selectedEntities = new HashSet<>();
+        selectedEmbeddables = new HashSet<>();
+        selectedDataMaps = new HashSet<>();
+    }
+
+    void initCollectionsForSelection(DataMap dataMap) {
+        selectedEntities = selectedEntitiesForDataMap.computeIfAbsent(dataMap, dm -> new HashSet<>());
+        selectedEmbeddables = selectedEmbeddablesForDataMap.computeIfAbsent(dataMap, dm -> new HashSet<>());
+        selectedDataMaps = selectedDataMapsForDataMap.computeIfAbsent(dataMap, dm -> new HashSet<>());
+    }
+
+    boolean updateSelection(Predicate<Object> predicate, List<Object> classes) {
+        boolean modified = false;
+        for (Object classObj : classes) {
+            boolean select = predicate.test(classObj);
+            if (classObj instanceof ObjEntity) {
+                if (select) {
+                    if (selectedEntities.add(((ObjEntity) classObj).getName())) {
+                        modified = true;
+                    }
+                } else {
+                    if (selectedEntities.remove(((ObjEntity) classObj).getName())) {
+                        modified = true;
+                    }
+                }
+            } else if (classObj instanceof Embeddable) {
+                if (select) {
+                    if (selectedEmbeddables.add(((Embeddable) classObj).getClassName())) {
+                        modified = true;
+                    }
+                } else {
+                    if (selectedEmbeddables.remove(((Embeddable) classObj).getClassName())) {
+                        modified = true;
+                    }
+                }
+            } else if (classObj instanceof DataMap) {
+                if (select) {
+                    if (selectedDataMaps.add(((DataMap) classObj).getName())) {
+                        modified = true;
+                    }
+                } else {
+                    if (selectedDataMaps.remove(((DataMap) classObj).getName())) {
+                        modified = true;
+                    }
+                }
+            }
+        }
+        return modified;
+    }
+
+    List<Embeddable> getSelectedEmbeddables(List<Object> classes) {
+        List<Embeddable> selected = new ArrayList<>(selectedEmbeddables.size());
+        for (Object classObj : classes) {
+            if (classObj instanceof Embeddable) {
+                String name = ((Embeddable) classObj).getClassName();
+                if (selectedEmbeddables.contains(name)) {
+                    selected.add((Embeddable) classObj);
+                }
+            }
+        }
+
+        return selected;
+    }
+
+    List<ObjEntity> getSelectedEntities(List<Object> classes) {
+        List<ObjEntity> selected = new ArrayList<>(selectedEntities.size());
+        for (Object classObj : classes) {
+            if (classObj instanceof ObjEntity) {
+                String name = ((ObjEntity) classObj).getName();
+                if (selectedEntities.contains(name)) {
+                    selected.add(((ObjEntity) classObj));
+                }
+            }
+        }
+
+        return selected;
+    }
+
+    boolean isSelected(Object currentClass) {
+        if (currentClass instanceof ObjEntity) {
+            return selectedEntities.contains(((ObjEntity) currentClass).getName());
+        } else if (currentClass instanceof Embeddable) {
+            return selectedEmbeddables.contains(((Embeddable) currentClass).getClassName());
+        } else if (currentClass instanceof DataMap) {
+            return selectedDataMaps.contains(((DataMap) currentClass).getName());
+        }
+        return false;
+    }
+
+    boolean setSelected(Object currentClass, boolean selectedFlag) {
+        if (currentClass instanceof ObjEntity) {
+            if (selectedFlag) {
+                return selectedEntities.add(((ObjEntity) currentClass).getName());
+            } else {
+                return selectedEntities.remove(((ObjEntity) currentClass).getName());
+            }
+        } else if (currentClass instanceof Embeddable) {
+            if (selectedFlag) {
+                return selectedEmbeddables.add(((Embeddable) currentClass).getClassName());
+            } else {
+                return selectedEmbeddables.remove(((Embeddable) currentClass).getClassName());
+            }
+        } else if (currentClass instanceof DataMap) {
+            if (selectedFlag) {
+                return selectedDataMaps.add(((DataMap) currentClass).getName());
+            } else {
+                return selectedDataMaps.remove(((DataMap) currentClass).getName());
+            }
+        }
+        return false;
+    }
+
+    void removeFromSelectedEntities(ObjEntity objEntity) {
+        initCollectionsForSelection(objEntity.getDataMap());
+        selectedEntities.remove(objEntity.getName());
+    }
+
+    void removeFromSelectedEmbeddables(Embeddable embeddable) {
+        initCollectionsForSelection(embeddable.getDataMap());
+        selectedEmbeddables.remove(embeddable.getClassName());
+    }
+
+    void addSelectedEntities(Collection<String> entities) {
+        selectedEntities.addAll(entities);
+    }
+
+    void addSelectedEntity(String entity) {
+        selectedEntities.add(entity);
+    }
+
+    void addSelectedEmbeddables(Collection<String> entities) {
+        selectedEmbeddables.addAll(entities);
+    }
+
+    void addSelectedEmbeddable(String entity) {
+        selectedEmbeddables.add(entity);
+    }
+
+    int getSelectedEntitiesCount() {
+        return selectedEntities.size();
+    }
+
+    int getSelecetedEmbeddablesCount() {
+        return selectedEmbeddables.size();
+    }
+
+    int getSelectedDataMapsCount() {
+        return selectedDataMaps.size();
+    }
+
+}
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/StandardModeController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/StandardModeController.java
index a948b6f..90368ab 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/StandardModeController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/StandardModeController.java
@@ -31,7 +31,7 @@ public class StandardModeController extends GeneratorController {
     protected StandardModePanel view;
     protected DataMapDefaults preferences;
 
-    public StandardModeController(CodeGeneratorControllerBase parent) {
+    public StandardModeController(CodeGeneratorController parent) {
         super(parent);
     }
 
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/StandardModePanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/StandardModePanel.java
index 8aa2554..f9cf04d 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/StandardModePanel.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/StandardModePanel.java
@@ -30,8 +30,8 @@ import java.awt.BorderLayout;
  */
 public class StandardModePanel extends GeneratorControllerPanel {
 
-    public StandardModePanel(CodeGeneratorControllerBase codeGeneratorControllerBase) {
-        super(Application.getInstance().getFrameController().getProjectController(), codeGeneratorControllerBase);
+    public StandardModePanel(CodeGeneratorController codeGeneratorController) {
+        super(Application.getInstance().getFrameController().getProjectController(), codeGeneratorController);
         FormLayout layout = new FormLayout(
                 "right:83dlu, 1dlu, fill:240:grow, 1dlu, left:100dlu, 100dlu", "");