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

commit 847ada1ebe897deddfe54a1ee2c4490d953ce028
Author: keyris <keyris.xd.s...@gmail.com>
AuthorDate: Tue May 18 11:16:04 2021 +0300

    CAY-2710 Modeler: modeler throws IllegalArgumentsException when root and 
rel paths have different roots
---
 .../org/apache/cayenne/gen/CgenConfiguration.java  |  88 ++++----
 .../apache/cayenne/gen/xml/CgenSaverDelegate.java  |   8 +-
 .../apache/cayenne/gen/CgenConfigurationTest.java  | 248 +++++++++++++++++++++
 .../cayenne/gen/xml/CgenSaverDelegateTest.java     |   4 +
 .../editor/cgen/CodeGeneratorController.java       |  54 +++--
 .../modeler/editor/cgen/GeneratorController.java   |   5 +-
 .../editor/cgen/GeneratorControllerPanel.java      |  10 +-
 7 files changed, 349 insertions(+), 68 deletions(-)

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
index 06cd354..02e81cd 100644
--- a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/CgenConfiguration.java
+++ b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/CgenConfiguration.java
@@ -22,11 +22,7 @@ package org.apache.cayenne.gen;
 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.HashSet;
-import java.util.Set;
+import java.util.*;
 import java.util.stream.Collectors;
 
 import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
@@ -36,12 +32,14 @@ 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 org.apache.cayenne.validation.ValidationException;
 
 /**
  * Used to keep config of class generation action.
  * Previously was the part of ClassGeneretionAction class.
  * Now CgenConfiguration is saved in dataMap file.
  * You can reuse it in next cgen actions.
+ *
  * @since 4.1
  */
 public class CgenConfiguration implements Serializable, XMLSerializable {
@@ -85,7 +83,7 @@ public class CgenConfiguration implements Serializable, 
XMLSerializable {
      * @since 4.2
      */
     private String externalToolConfig;
-    
+
     public CgenConfiguration(boolean client) {
         /**
          * {@link #isDefault()} method should be in sync with the following 
values
@@ -105,7 +103,7 @@ public class CgenConfiguration implements Serializable, 
XMLSerializable {
 
         this.client = client;
 
-        if(!client) {
+        if (!client) {
             this.template = ClassGenerationAction.SUBCLASS_TEMPLATE;
             this.superTemplate = ClassGenerationAction.SUPERCLASS_TEMPLATE;
             this.queryTemplate = 
ClassGenerationAction.DATAMAP_SUBCLASS_TEMPLATE;
@@ -120,7 +118,7 @@ public class CgenConfiguration implements Serializable, 
XMLSerializable {
         this.embeddableSuperTemplate = 
ClassGenerationAction.EMBEDDABLE_SUPERCLASS_TEMPLATE;
     }
 
-    public void resetCollections(){
+    public void resetCollections() {
         embeddableArtifacts.clear();
         entityArtifacts.clear();
     }
@@ -149,7 +147,7 @@ public class CgenConfiguration implements Serializable, 
XMLSerializable {
         }
     }
 
-    public String getArtifactsGenerationMode(){
+    public String getArtifactsGenerationMode() {
         return artifactsGenerationMode.getLabel();
     }
 
@@ -176,12 +174,20 @@ public class CgenConfiguration implements Serializable, 
XMLSerializable {
 
     public void setRelPath(String pathStr) {
         Path path = Paths.get(pathStr);
-        if(path.isAbsolute() && rootPath != null) {
-            this.relPath = rootPath.relativize(path);
-        } else {
-            this.relPath = path;
+
+        if (rootPath != null) {
+
+            if (!rootPath.isAbsolute()) {
+                throw new ValidationException("Root path : " + '"' + 
rootPath.toString() + '"' + "should be absolute");
+            }
+
+            if (path.isAbsolute() && 
rootPath.getRoot().equals(path.getRoot())) {
+                this.relPath = rootPath.relativize(path);
+                return;
+            }
         }
-       }
+        this.relPath = path;
+    }
 
     public boolean isOverwrite() {
         return overwrite;
@@ -300,7 +306,7 @@ public class CgenConfiguration implements Serializable, 
XMLSerializable {
     }
 
     public String buildRelPath() {
-        if(relPath == null || relPath.toString().isEmpty()) {
+        if (relPath == null || relPath.toString().isEmpty()) {
             return ".";
         }
         return relPath.toString();
@@ -327,23 +333,23 @@ public class CgenConfiguration implements Serializable, 
XMLSerializable {
     }
 
     public String getExternalToolConfig() {
-       return externalToolConfig;
+        return externalToolConfig;
     }
-    
+
     public void setExternalToolConfig(String config) {
-       this.externalToolConfig = config;
+        this.externalToolConfig = config;
     }
-    
+
     void addArtifact(Artifact artifact) {
         artifacts.add(artifact);
     }
 
     public Path buildPath() {
-               return rootPath != null ? relPath != null ? 
rootPath.resolve(relPath).toAbsolutePath().normalize() : rootPath : relPath;
-       }
+        return rootPath != null ? relPath != null ? 
rootPath.resolve(relPath).toAbsolutePath().normalize() : rootPath : relPath;
+    }
 
     public void loadEntity(ObjEntity entity) {
-        if(!entity.isGeneric()) {
+        if (!entity.isGeneric()) {
             entityArtifacts.add(entity.getName());
         }
     }
@@ -378,23 +384,23 @@ public class CgenConfiguration implements Serializable, 
XMLSerializable {
         return String.join(",", excludeEmbeddable);
     }
 
-       public void resolveExcludeEntities() {
-               entityArtifacts = dataMap.getObjEntities()
-                               .stream()
-                               .map(ObjEntity::getName)
-                               .filter(name -> 
!excludeEntityArtifacts.contains(name))
-                               .collect(Collectors.toSet());
-       }
+    public void resolveExcludeEntities() {
+        entityArtifacts = dataMap.getObjEntities()
+                .stream()
+                .map(ObjEntity::getName)
+                .filter(name -> !excludeEntityArtifacts.contains(name))
+                .collect(Collectors.toSet());
+    }
 
-       public void resolveExcludeEmbeddables() {
-       embeddableArtifacts = dataMap.getEmbeddables()
-                               .stream()
-                               .map(Embeddable::getClassName)
-                               .filter(className -> 
!excludeEmbeddableArtifacts.contains(className))
-                               .collect(Collectors.toSet());
-       }
+    public void resolveExcludeEmbeddables() {
+        embeddableArtifacts = dataMap.getEmbeddables()
+                .stream()
+                .map(Embeddable::getClassName)
+                .filter(className -> 
!excludeEmbeddableArtifacts.contains(className))
+                .collect(Collectors.toSet());
+    }
 
-       public Collection<String> getExcludeEntityArtifacts() {
+    public Collection<String> getExcludeEntityArtifacts() {
         return excludeEntityArtifacts;
     }
 
@@ -442,12 +448,12 @@ public class CgenConfiguration implements Serializable, 
XMLSerializable {
                 && !createPropertyNames
                 && "*.java".equals(outputPattern)
                 && (template.equals(ClassGenerationAction.SUBCLASS_TEMPLATE)
-                    || 
template.equals(ClientClassGenerationAction.SUBCLASS_TEMPLATE))
+                || 
template.equals(ClientClassGenerationAction.SUBCLASS_TEMPLATE))
                 && 
(superTemplate.equals(ClassGenerationAction.SUPERCLASS_TEMPLATE)
-                    || 
superTemplate.equals(ClientClassGenerationAction.SUPERCLASS_TEMPLATE))
+                || 
superTemplate.equals(ClientClassGenerationAction.SUPERCLASS_TEMPLATE))
                 && (superPkg == null
-                    || superPkg.isEmpty())
+                || superPkg.isEmpty())
                 && (externalToolConfig == null
-                    || externalToolConfig.isEmpty());
+                || externalToolConfig.isEmpty());
     }
 }
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 ea94c72..2724cb8 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
@@ -72,9 +72,15 @@ public class CgenSaverDelegate extends BaseSaverDelegate {
         Path prevPath = cgenConfiguration.buildPath();
         if(prevPath != null) {
             if(prevPath.isAbsolute()) {
-                Path relPath = resourcePath.relativize(prevPath).normalize();
+
+                Path relPath = prevPath;
+
+                if (resourcePath.getRoot().equals(prevPath.getRoot())) {
+                    relPath = resourcePath.relativize(prevPath).normalize();
+                }
                 cgenConfiguration.setRelPath(relPath);
             }
+
             Path templatePath = Paths.get(cgenConfiguration.getTemplate());
             if(templatePath.isAbsolute()) {
                 
cgenConfiguration.setTemplate(resourcePath.relativize(templatePath).normalize().toString());
diff --git 
a/cayenne-cgen/src/test/java/org/apache/cayenne/gen/CgenConfigurationTest.java 
b/cayenne-cgen/src/test/java/org/apache/cayenne/gen/CgenConfigurationTest.java
new file mode 100644
index 0000000..fd5572c
--- /dev/null
+++ 
b/cayenne-cgen/src/test/java/org/apache/cayenne/gen/CgenConfigurationTest.java
@@ -0,0 +1,248 @@
+/*****************************************************************
+ *   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.gen;
+
+import org.apache.cayenne.validation.ValidationException;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.runner.RunWith;
+
+import java.nio.file.InvalidPathException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Locale;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(Enclosed.class)
+public class CgenConfigurationTest {
+
+    public static class СgenWindowsConfigurationTest {
+
+        CgenConfiguration configuration;
+
+        @Before
+        public void setUp() {
+            configuration = new CgenConfiguration(false);
+        }
+
+        @Before
+        public void checkPlatform() {
+            
Assume.assumeTrue(System.getProperty("os.name").toLowerCase(Locale.ROOT).startsWith("win"));
+        }
+
+        @Test
+        public void equalRootsEqualDirectories() {
+            configuration.setRootPath(Paths.get("C:\\test1\\test2\\test3"));
+            Path relPath = Paths.get("C:\\test1\\test2\\test3");
+            configuration.setRelPath(relPath.toString());
+
+            assertEquals(Paths.get(""), configuration.getRelPath());
+            assertEquals(relPath, configuration.buildPath());
+        }
+
+        @Test
+        public void equalRootsNotEqualDirectories() {
+            configuration.setRootPath(Paths.get("C:\\test1\\test2\\test3"));
+            Path relPath = Paths.get("C:\\test1\\test2\\testAnother");
+            configuration.setRelPath(relPath.toString());
+
+            assertEquals(Paths.get("..\\testAnother"), 
configuration.getRelPath());
+            assertEquals(relPath, configuration.buildPath());
+        }
+
+        @Test
+        public void equalRootsEmptyDirectories() {
+            configuration.setRootPath(Paths.get("C:\\"));
+            Path relPath = Paths.get("C:\\");
+            configuration.setRelPath(relPath.toString());
+
+            assertEquals(Paths.get(""), configuration.getRelPath());
+            assertEquals(relPath, configuration.buildPath());
+        }
+
+        @Test
+        public void notEqualRootsEqualDirectories() {
+            configuration.setRootPath(Paths.get("C:\\test1\\test2\\test3"));
+            Path relPath = Paths.get("E:\\test1\\test2\\test3");
+            configuration.setRelPath(relPath.toString());
+
+            assertEquals(Paths.get("E:\\test1\\test2\\test3"), 
configuration.getRelPath());
+            assertEquals(relPath, configuration.buildPath());
+        }
+
+        @Test
+        public void notEqualRootsNotEqualDirectories() {
+            configuration.setRootPath(Paths.get("C:\\test1\\test2\\test3"));
+            Path relPath = Paths.get("E:\\test1\\test2\\testAnother");
+            configuration.setRelPath(relPath.toString());
+
+            assertEquals(Paths.get("E:\\test1\\test2\\testAnother"), 
configuration.getRelPath());
+            assertEquals(relPath, configuration.buildPath());
+        }
+
+        @Test
+        public void notEqualRootsEmptyDirectories() {
+            configuration.setRootPath(Paths.get("C:\\"));
+            Path relPath = Paths.get("E:\\");
+            configuration.setRelPath(relPath.toString());
+
+            assertEquals(Paths.get("E:\\"), configuration.getRelPath());
+            assertEquals(relPath, configuration.buildPath());
+        }
+
+        @Test(expected = ValidationException.class)
+        public void emptyRootNotEmptyRelPath() {
+            configuration.setRootPath(Paths.get(""));
+            Path relPath = Paths.get("E:\\");
+            configuration.setRelPath(relPath.toString());
+
+            assertEquals(Paths.get("E:\\"), configuration.getRelPath());
+            assertEquals(relPath, configuration.buildPath());
+        }
+
+        @Test
+        public void notEmptyRootEmptyRelPath() {
+            configuration.setRootPath(Paths.get("E:\\"));
+            Path relPath = Paths.get("");
+
+            configuration.setRelPath(relPath);
+
+            assertEquals(relPath, configuration.getRelPath());
+            assertEquals(Paths.get("E:\\"), configuration.buildPath());
+        }
+
+        @Test(expected = InvalidPathException.class)
+        public void invalidRelPath() {
+            configuration.setRootPath(Paths.get("C:\\test1\\test2\\test3"));
+            configuration.setRelPath("invalidRoot:\\test");
+        }
+
+        @Test(expected = InvalidPathException.class)
+        public void invalidRootPath() {
+            configuration.setRootPath(Paths.get("invalidRoot:\\test"));
+            configuration.setRelPath("C:\\test1\\test2\\test3");
+        }
+
+        @Test
+        public void nullRootPath() {
+            configuration.setRelPath("C:\\test1\\test2\\test3");
+            assertEquals(Paths.get("C:\\test1\\test2\\test3"), 
configuration.getRelPath());
+            assertEquals(Paths.get("C:\\test1\\test2\\test3"), 
configuration.buildPath());
+        }
+    }
+
+    public static class СgenUnixConfigurationTest {
+
+        CgenConfiguration configuration;
+
+        @Before
+        public void setUp() {
+            configuration = new CgenConfiguration(false);
+        }
+
+        @Before
+        public void checkPlatform() {
+            
Assume.assumeFalse(System.getProperty("os.name").toLowerCase(Locale.ROOT).startsWith("win"));
+        }
+
+        @Test
+        public void equalRootsEqualDirectories() {
+            configuration.setRootPath(Paths.get("/test1/test2/test3"));
+            Path relPath = Paths.get("/test1/test2/test3");
+            configuration.setRelPath(relPath.toString());
+
+
+            assertEquals(Paths.get(""), configuration.getRelPath());
+            assertEquals(relPath, configuration.buildPath());
+        }
+
+        @Test
+        public void equalRootsNotEqualDirectories() {
+            configuration.setRootPath(Paths.get("/test1/test2/test3"));
+            Path relPath = Paths.get("/test1/test2/testAnother");
+            configuration.setRelPath(relPath.toString());
+
+            assertEquals(Paths.get("../testAnother"), 
configuration.getRelPath());
+            assertEquals(relPath, configuration.buildPath());
+        }
+
+        @Test
+        public void equalRootsEmptyDirectories() {
+            configuration.setRootPath(Paths.get("/"));
+            Path relPath = Paths.get("/");
+            configuration.setRelPath(relPath.toString());
+
+            assertEquals(Paths.get(""), configuration.getRelPath());
+            assertEquals(relPath, configuration.buildPath());
+        }
+
+        @Test
+        public void concatCorrectRootPathAndRelPath() {
+            configuration.setRootPath(Paths.get("/test1/test2/test3"));
+            Path relPath = Paths.get("test1/test2/test3");
+            configuration.setRelPath(relPath.toString());
+
+            assertEquals(Paths.get("test1/test2/test3"), 
configuration.getRelPath());
+            assertEquals(Paths.get("/test1/test2/test3/test1/test2/test3"), 
configuration.buildPath());
+        }
+
+        @Test(expected = ValidationException.class)
+        public void emptyRootNotEmptyRelPath() {
+            configuration.setRootPath(Paths.get(""));
+            Path relPath = Paths.get("/");
+            configuration.setRelPath(relPath.toString());
+
+            assertEquals(Paths.get("/"), configuration.getRelPath());
+            assertEquals(relPath, configuration.buildPath());
+        }
+
+        @Test
+        public void notEmptyRootEmptyRelPath() {
+            configuration.setRootPath(Paths.get("/"));
+            configuration.setRelPath("");
+
+            assertEquals(Paths.get(""), configuration.getRelPath());
+            assertEquals(Paths.get("/"), configuration.buildPath());
+        }
+
+        @Test(expected = ValidationException.class)
+        public void invalidRootPath() {
+            configuration.setRootPath(Paths.get("invalidRoot:/test"));
+            configuration.setRelPath("/test1/test2/test3");
+        }
+
+        @Test(expected = ValidationException.class)
+        public void concatInvalidRootPathAndRelPath() {
+            configuration.setRootPath(Paths.get("invalidRoot:/test"));
+            configuration.setRelPath("test1/test2/test3");
+        }
+
+        @Test
+        public void nullRootPath() {
+            configuration.setRelPath("/test1/test2/test3");
+            assertEquals(Paths.get("/test1/test2/test3"), 
configuration.getRelPath());
+            assertEquals(Paths.get("/test1/test2/test3"), 
configuration.buildPath());
+        }
+    }
+
+}
\ No newline at end of file
diff --git 
a/cayenne-cgen/src/test/java/org/apache/cayenne/gen/xml/CgenSaverDelegateTest.java
 
b/cayenne-cgen/src/test/java/org/apache/cayenne/gen/xml/CgenSaverDelegateTest.java
index 37c910b..78be02e 100644
--- 
a/cayenne-cgen/src/test/java/org/apache/cayenne/gen/xml/CgenSaverDelegateTest.java
+++ 
b/cayenne-cgen/src/test/java/org/apache/cayenne/gen/xml/CgenSaverDelegateTest.java
@@ -73,4 +73,8 @@ public class CgenSaverDelegateTest {
     }
 
 
+
+
+
+
 }
\ No newline at end of file
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 d292ac2..8b85e06 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
@@ -101,8 +101,8 @@ public class CodeGeneratorController extends 
CayenneController implements ObjEnt
         createConfiguration(dataMap);
 
         GeneratorController modeController = 
prevGeneratorController.get(dataMap);
-        if(modeController == null) {
-            if(cgenConfiguration.isDefault()) {
+        if (modeController == null) {
+            if (cgenConfiguration.isDefault()) {
                 modeController = cgenConfiguration.isClient()
                         ? generatorSelector.getClientGeneratorController()
                         : generatorSelector.getStandartController();
@@ -118,7 +118,7 @@ public class CodeGeneratorController extends 
CayenneController implements ObjEnt
         classesSelector.validate(classes);
     }
 
-    private void initListeners(){
+    private void initListeners() {
         projectController.addObjEntityListener(this);
         projectController.addEmbeddableListener(this);
         projectController.addDataMapListener(this);
@@ -207,7 +207,7 @@ public class CodeGeneratorController extends 
CayenneController implements ObjEnt
      */
     public void createConfiguration(DataMap map) {
         cgenConfiguration = 
projectController.getApplication().getMetaData().get(map, 
CgenConfiguration.class);
-        if(cgenConfiguration != null){
+        if (cgenConfiguration != null) {
             addToSelectedEntities(cgenConfiguration.getEntities());
             addToSelectedEmbeddables(cgenConfiguration.getEmbeddables());
             cgenConfiguration.setForce(true);
@@ -236,7 +236,9 @@ public class CodeGeneratorController extends 
CayenneController implements ObjEnt
             return;
         }
 
-        cgenConfiguration.setRootPath(basePath);
+        if (map.getLocation() != null) {
+            cgenConfiguration.setRootPath(basePath);
+        }
         Preferences preferences = 
application.getPreferencesNode(GeneralPreferences.class, "");
         if (preferences != null) {
             
cgenConfiguration.setEncoding(preferences.get(GeneralPreferences.ENCODING_PREFERENCE,
 null));
@@ -260,7 +262,7 @@ public class CodeGeneratorController extends 
CayenneController implements ObjEnt
         boolean modified = selectionModel.updateSelection(predicate, classes);
 
         for (Object classObj : classes) {
-            if(classObj instanceof DataMap) {
+            if (classObj instanceof DataMap) {
                 boolean selected = predicate.test(classObj);
                 updateArtifactGenerationMode(selected);
             }
@@ -270,7 +272,7 @@ public class CodeGeneratorController extends 
CayenneController implements ObjEnt
     }
 
     private void updateArtifactGenerationMode(boolean selected) {
-        if(selected) {
+        if (selected) {
             cgenConfiguration.setArtifactsGenerationMode("all");
         } else {
             cgenConfiguration.setArtifactsGenerationMode("entity");
@@ -293,19 +295,19 @@ public class CodeGeneratorController extends 
CayenneController implements ObjEnt
         this.currentClass = currentClass;
     }
 
-    public void updateSelectedEntities(){
+    public void updateSelectedEntities() {
         updateEntities();
         updateEmbeddables();
     }
 
     public void checkCgenConfigDirty() {
-        if(initFromModel || cgenConfiguration == null) {
+        if (initFromModel || cgenConfiguration == null) {
             return;
         }
 
         DataMap map = projectController.getCurrentDataMap();
         CgenConfiguration existingConfig = 
projectController.getApplication().getMetaData().get(map, 
CgenConfiguration.class);
-        if(existingConfig == null) {
+        if (existingConfig == null) {
             getApplication().getMetaData().add(map, cgenConfiguration);
         }
 
@@ -313,9 +315,9 @@ public class CodeGeneratorController extends 
CayenneController implements ObjEnt
     }
 
     private void updateEntities() {
-        if(cgenConfiguration != null) {
+        if (cgenConfiguration != null) {
             cgenConfiguration.getEntities().clear();
-            for(ObjEntity entity: selectionModel.getSelectedEntities(classes)) 
{
+            for (ObjEntity entity : 
selectionModel.getSelectedEntities(classes)) {
                 cgenConfiguration.loadEntity(entity);
             }
         }
@@ -323,9 +325,9 @@ public class CodeGeneratorController extends 
CayenneController implements ObjEnt
     }
 
     private void updateEmbeddables() {
-        if(cgenConfiguration != null) {
+        if (cgenConfiguration != null) {
             cgenConfiguration.getEmbeddables().clear();
-            for(Embeddable embeddable : 
selectionModel.getSelectedEmbeddables(classes)) {
+            for (Embeddable embeddable : 
selectionModel.getSelectedEmbeddables(classes)) {
                 cgenConfiguration.loadEmbeddable(embeddable.getClassName());
             }
         }
@@ -340,7 +342,7 @@ public class CodeGeneratorController extends 
CayenneController implements ObjEnt
     void addEntity(DataMap dataMap, ObjEntity objEntity) {
         prepareClasses(dataMap);
         selectionModel.addSelectedEntity(objEntity.getName());
-        if(cgenConfiguration != null) {
+        if (cgenConfiguration != null) {
             cgenConfiguration.loadEntity(objEntity);
         }
         checkCgenConfigDirty();
@@ -376,7 +378,8 @@ public class CodeGeneratorController extends 
CayenneController implements ObjEnt
     }
 
     @Override
-    public void objEntityChanged(EntityEvent e) {}
+    public void objEntityChanged(EntityEvent e) {
+    }
 
     @Override
     public void objEntityAdded(EntityEvent e) {
@@ -386,21 +389,22 @@ public class CodeGeneratorController extends 
CayenneController implements ObjEnt
     @Override
     public void objEntityRemoved(EntityEvent e) {
         selectionModel.removeFromSelectedEntities((ObjEntity) e.getEntity());
-        if(cgenConfiguration != null) {
+        if (cgenConfiguration != null) {
             cgenConfiguration.getEntities().remove(e.getEntity().getName());
         }
         checkCgenConfigDirty();
     }
 
     @Override
-    public void embeddableChanged(EmbeddableEvent e, DataMap map) {}
+    public void embeddableChanged(EmbeddableEvent e, DataMap map) {
+    }
 
     @Override
     public void embeddableAdded(EmbeddableEvent e, DataMap map) {
         prepareClasses(map);
         String embeddableClassName = e.getEmbeddable().getClassName();
         selectionModel.addSelectedEmbeddable(embeddableClassName);
-        if(cgenConfiguration != null) {
+        if (cgenConfiguration != null) {
             cgenConfiguration.loadEmbeddable(embeddableClassName);
         }
         checkCgenConfigDirty();
@@ -409,7 +413,7 @@ public class CodeGeneratorController extends 
CayenneController implements ObjEnt
     @Override
     public void embeddableRemoved(EmbeddableEvent e, DataMap map) {
         selectionModel.removeFromSelectedEmbeddables(e.getEmbeddable());
-        if(cgenConfiguration != null) {
+        if (cgenConfiguration != null) {
             
cgenConfiguration.getEmbeddables().remove(e.getEmbeddable().getClassName());
         }
         checkCgenConfigDirty();
@@ -417,8 +421,8 @@ public class CodeGeneratorController extends 
CayenneController implements ObjEnt
 
     @Override
     public void dataMapChanged(DataMapEvent e) {
-        if(e.getSource() instanceof DbImportController) {
-            if(cgenConfiguration != null) {
+        if (e.getSource() instanceof DbImportController) {
+            if (cgenConfiguration != null) {
                 for (ObjEntity objEntity : e.getDataMap().getObjEntities()) {
                     if 
(!cgenConfiguration.getExcludeEntityArtifacts().contains(objEntity.getName())) {
                         addEntity(cgenConfiguration.getDataMap(), objEntity);
@@ -430,10 +434,12 @@ public class CodeGeneratorController extends 
CayenneController implements ObjEnt
     }
 
     @Override
-    public void dataMapAdded(DataMapEvent e) {}
+    public void dataMapAdded(DataMapEvent e) {
+    }
 
     @Override
-    public void dataMapRemoved(DataMapEvent e) {}
+    public void dataMapRemoved(DataMapEvent e) {
+    }
 
     public CgenConfiguration getCgenConfiguration() {
         return cgenConfiguration;
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 545bee0..5346e2a 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
@@ -62,7 +62,10 @@ public abstract class GeneratorController extends 
CayenneController {
 
     protected void initForm(CgenConfiguration cgenConfiguration) {
         this.cgenConfiguration = cgenConfiguration;
-        
getView().getOutputFolder().setText(cgenConfiguration.buildPath().toString());
+
+        if (cgenConfiguration.getRootPath() != null) {
+            
getView().getOutputFolder().setText(cgenConfiguration.buildPath().toString());
+        }
         
if(cgenConfiguration.getArtifactsGenerationMode().equalsIgnoreCase("all")) {
             
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 22e5c37..90f418b 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
@@ -27,6 +27,8 @@ import org.apache.cayenne.validation.ValidationException;
 import javax.swing.JButton;
 import javax.swing.JPanel;
 import javax.swing.JTextField;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 
 /**
  * @since 4.1
@@ -45,8 +47,14 @@ public class GeneratorControllerPanel extends JPanel {
         this.outputFolder = new TextAdapter(new JTextField()) {
             @Override
             protected void updateModel(String text) throws ValidationException 
{
+
                 CgenConfiguration cgenByDataMap = getCgenConfig();
-                if(cgenByDataMap != null) {
+
+                if (cgenByDataMap != null) {
+
+                    if (cgenByDataMap.getRootPath() == null && 
!Paths.get(text).isAbsolute()) {
+                        throw new ValidationException("You should save project 
to use rel path as output directory ");
+                    }
                     cgenByDataMap.setRelPath(text);
                     checkConfigDirty();
                 }

Reply via email to