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 69f1bf066 Drag and drop in DbImport targetTree (#622)
69f1bf066 is described below
commit 69f1bf066ec1f846db8ed1af919d2793c1bac0be
Author: Mikhail Dzianishchyts <[email protected]>
AuthorDate: Fri Aug 2 14:56:13 2024 +0300
Drag and drop in DbImport targetTree (#622)
* sorting only by type
* migrate from TreeSet to List(to prevent auto sorting patterns), tests
added
* sort button functionality
* modified equals in TableFilter
* cleanUp
* setDirty after sorting added
* drag and drop in DbImport target tree
* fix bugs, refactoring
* fixed bug with moving node on the parent
* Use interfaces for args and returns
* Keep expanded nodes on model reload
* Add dummy node to fix drag and drop issues
* Check for duplicates on drag and drop
* Clean up
* Update tests
---------
Co-authored-by: Ivan Nikitka
<[email protected]>
Co-authored-by: Ivan Nikitka <[email protected]>
---
.../dbsync/reverse/dbimport/PatternParam.java | 27 ++--
.../reverse/filters/FiltersConfigBuilder.java | 10 +-
.../dbsync/reverse/filters/IncludeTableFilter.java | 21 ++-
.../dbsync/reverse/filters/PatternFilter.java | 43 ++++--
.../dbsync/reverse/filters/TableFilter.java | 37 +++--
.../cayenne/dbsync/reverse/dbload/DbLoaderIT.java | 43 ++++++
.../dbsync/reverse/filters/FiltersConfigTest.java | 134 +++++++++++++++++-
.../dbsync/reverse/filters/TableFilterTest.java | 55 ++++++--
.../tools/DbImporterMojoConfigurationTest.java | 7 +-
.../modeler/action/DefaultActionManager.java | 3 +
.../cayenne/modeler/action/SortNodesAction.java | 59 ++++++++
.../modeler/action/dbimport/DeleteNodeAction.java | 6 +-
.../action/dbimport/DragAndDropNodeAction.java | 157 +++++++++++++++++++++
.../modeler/action/dbimport/EditNodeAction.java | 4 +-
.../action/dbimport/MoveImportNodeAction.java | 8 +-
.../action/dbimport/TreeManipulationAction.java | 2 +-
.../modeler/dialog/db/load/DbImportTreeNode.java | 60 +++++---
.../modeler/dialog/db/load/TransferableNode.java | 5 +-
.../modeler/editor/dbimport/DbImportSorter.java | 22 +--
.../modeler/editor/dbimport/DbImportTree.java | 46 ++++--
.../editor/dbimport/DbImportTreeCellEditor.java | 7 +-
.../editor/dbimport/DbImportTreeCellRenderer.java | 54 ++++++-
.../editor/dbimport/DraggableTreePanel.java | 121 +++++++++++++---
.../editor/dbimport/PrintColumnsBiFunction.java | 2 +-
.../editor/dbimport/PrintTablesBiFunction.java | 3 +-
.../modeler/editor/dbimport/TreeToolbarPanel.java | 40 ++++--
.../modeler/undo/DbImportTreeUndoableEdit.java | 6 +-
.../cayenne/modeler/images/icon-dbi-sort.png | Bin 0 -> 315 bytes
.../editor/dbimport/DbImportSorterTest.java | 40 ++++--
29 files changed, 848 insertions(+), 174 deletions(-)
diff --git
a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/PatternParam.java
b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/PatternParam.java
index 598bd132d..b62beb4e2 100644
---
a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/PatternParam.java
+++
b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/PatternParam.java
@@ -19,6 +19,8 @@
package org.apache.cayenne.dbsync.reverse.dbimport;
+import java.util.Objects;
+
import static org.apache.cayenne.util.Util.isBlank;
/**
@@ -77,16 +79,6 @@ public class PatternParam {
set(pattern.getName());
}
- @Override
- public String toString() {
- return toString(new StringBuilder(), "").toString();
- }
-
- public StringBuilder toString(StringBuilder res, String s) {
- res.append(s).append(getClass().getSimpleName()).append(":
").append(pattern).append("\n");
- return res;
- }
-
@Override
public boolean equals(Object obj) {
if (obj == this) {
@@ -101,4 +93,19 @@ public class PatternParam {
PatternParam patternParam = (PatternParam) obj;
return patternParam.getPattern().equals(pattern);
}
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(pattern);
+ }
+
+ @Override
+ public String toString() {
+ return toString(new StringBuilder(), "").toString();
+ }
+
+ public StringBuilder toString(StringBuilder res, String s) {
+ res.append(s).append(getClass().getSimpleName()).append(":
").append(pattern).append("\n");
+ return res;
+ }
}
diff --git
a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilder.java
b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilder.java
index aca90baf3..8303c960b 100644
---
a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilder.java
+++
b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilder.java
@@ -27,8 +27,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import java.util.SortedSet;
-import java.util.TreeSet;
import java.util.regex.Pattern;
import org.apache.cayenne.dba.DbAdapter;
@@ -156,16 +154,16 @@ public final class FiltersConfigBuilder {
return schemaFilters;
}
- private SortedSet<Pattern> transformExcludeTable(Collection<ExcludeTable>
excludeTables) {
- SortedSet<Pattern> res = new
TreeSet<>(PatternFilter.PATTERN_COMPARATOR);
+ private List<Pattern> transformExcludeTable(Collection<ExcludeTable>
excludeTables) {
+ List<Pattern> res = new ArrayList<>();
for (ExcludeTable exclude : excludeTables) {
res.add(PatternFilter.pattern(exclude.getPattern()));
}
return res;
}
- private SortedSet<IncludeTableFilter>
transformIncludeTable(Collection<IncludeTable> includeTables) {
- SortedSet<IncludeTableFilter> includeTableFilters = new TreeSet<>();
+ private List<IncludeTableFilter>
transformIncludeTable(Collection<IncludeTable> includeTables) {
+ List<IncludeTableFilter> includeTableFilters = new ArrayList<>();
for (IncludeTable includeTable : includeTables) {
includeTableFilters.add(new
IncludeTableFilter(includeTable.getPattern()
, transform(includeTable.getIncludeColumns(),
includeTable.getExcludeColumns())
diff --git
a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/IncludeTableFilter.java
b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/IncludeTableFilter.java
index 35d504f5b..670b63823 100644
---
a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/IncludeTableFilter.java
+++
b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/IncludeTableFilter.java
@@ -18,11 +18,12 @@
****************************************************************/
package org.apache.cayenne.dbsync.reverse.filters;
+import java.util.Objects;
import java.util.regex.Pattern;
/**
-* @since 4.0.
-*/
+ * @since 4.0.
+ */
public class IncludeTableFilter implements Comparable<IncludeTableFilter> {
public final Pattern pattern;
@@ -50,14 +51,14 @@ public class IncludeTableFilter implements
Comparable<IncludeTableFilter> {
this.relationshipFilter = relationshipFilter;
}
- public boolean isIncludeColumn (String name) {
+ public boolean isIncludeColumn(String name) {
return columnsFilter.isIncluded(name);
}
/**
* @since 4.1
*/
- public boolean isIncludeRelationship (String name) {
+ public boolean isIncludeRelationship(String name) {
return relationshipFilter.isIncluded(name);
}
@@ -75,6 +76,18 @@ public class IncludeTableFilter implements
Comparable<IncludeTableFilter> {
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ IncludeTableFilter that = (IncludeTableFilter) o;
+
+ if (!Objects.equals(pattern, that.pattern)) return false;
+ if (!Objects.equals(columnsFilter, that.columnsFilter)) return false;
+ return Objects.equals(relationshipFilter, that.relationshipFilter);
+ }
+
@Override
public String toString() {
return toString(new StringBuilder(), "").toString();
diff --git
a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilter.java
b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilter.java
index c06861903..704c14a2f 100644
---
a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilter.java
+++
b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilter.java
@@ -20,9 +20,9 @@ package org.apache.cayenne.dbsync.reverse.filters;
import org.apache.cayenne.util.Util;
+import java.util.ArrayList;
import java.util.Comparator;
-import java.util.SortedSet;
-import java.util.TreeSet;
+import java.util.List;
import java.util.regex.Pattern;
/**
@@ -63,18 +63,22 @@ public class PatternFilter {
}
};
- private final SortedSet<Pattern> includes;
- private final SortedSet<Pattern> excludes;
+ private final List<Pattern> includes;
+ private final List<Pattern> excludes;
public PatternFilter() {
- this.includes = new TreeSet<>(PATTERN_COMPARATOR);
- this.excludes = new TreeSet<>(PATTERN_COMPARATOR);
+ this.includes = new ArrayList<>();
+ this.excludes = new ArrayList<>();
}
- public SortedSet<Pattern> getIncludes() {
+ public List<Pattern> getIncludes() {
return includes;
}
+ public List<Pattern> getExcludes() {
+ return excludes;
+ }
+
public PatternFilter include(Pattern p) {
includes.add(p);
@@ -132,14 +136,29 @@ public class PatternFilter {
return true;
}
- if (o == null || getClass() != o.getClass()) {
+ if (!(o instanceof PatternFilter)) {
return false;
}
+ PatternFilter that = (PatternFilter) o;
+
+ if (includes == that.includes) {
+ return true;
+ }
+
+ if (includes.size() != that.includes.size()) {
+ return false;
+ }
- PatternFilter filter = (PatternFilter) o;
- return includes.equals(filter.includes)
- && excludes.equals(filter.excludes);
+ // Check if the lists have the same patterns in the same order
+ for (int i = 0; i < includes.size(); i++) {
+ Pattern pattern = excludes.get(i);
+ Pattern thatPattern = that.excludes.get(i);
+ if (!pattern.pattern().equals(thatPattern.pattern())) {
+ return false;
+ }
+ }
+ return true;
}
@Override
@@ -153,7 +172,7 @@ public class PatternFilter {
} else if (includes.size() > 1) {
res.append("(").append(Util.join(includes, " OR ")).append(")");
} else {
- res.append(includes.first().pattern());
+ res.append(includes.get(0).pattern());
}
if (!excludes.isEmpty()) {
diff --git
a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/TableFilter.java
b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/TableFilter.java
index c403ba0ef..7b7f6d80c 100644
---
a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/TableFilter.java
+++
b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/TableFilter.java
@@ -19,7 +19,9 @@
package org.apache.cayenne.dbsync.reverse.filters;
-import java.util.SortedSet;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Pattern;
@@ -30,13 +32,13 @@ import org.apache.cayenne.util.Util;
*/
public class TableFilter {
- private final SortedSet<IncludeTableFilter> includes;
- private final SortedSet<Pattern> excludes;
+ private final List<IncludeTableFilter> includes;
+ private final List<Pattern> excludes;
/**
* Includes can contain only one include table
*/
- public TableFilter(SortedSet<IncludeTableFilter> includes,
SortedSet<Pattern> excludes) {
+ public TableFilter(List<IncludeTableFilter> includes, List<Pattern>
excludes) {
this.includes = includes;
this.excludes = excludes;
}
@@ -89,22 +91,26 @@ public class TableFilter {
return include;
}
- public SortedSet<IncludeTableFilter> getIncludes() {
+ public List<IncludeTableFilter> getIncludes() {
return includes;
}
+ public List<Pattern> getExcludes() {
+ return excludes;
+ }
+
public static TableFilter include(String tablePattern) {
- TreeSet<IncludeTableFilter> includes = new TreeSet<>();
+ List<IncludeTableFilter> includes = new ArrayList<>();
includes.add(new IncludeTableFilter(tablePattern == null ? null :
tablePattern.replaceAll("%", ".*")));
- return new TableFilter(includes, new TreeSet<>());
+ return new TableFilter(includes, new ArrayList<>());
}
public static TableFilter everything() {
- TreeSet<IncludeTableFilter> includes = new TreeSet<>();
+ List<IncludeTableFilter> includes = new ArrayList<>();
includes.add(new IncludeTableFilter(null));
- return new TableFilter(includes, new TreeSet<>());
+ return new TableFilter(includes, new ArrayList<>());
}
protected StringBuilder toString(StringBuilder res, String prefix) {
@@ -133,9 +139,18 @@ public class TableFilter {
TableFilter that = (TableFilter) o;
- return excludes.equals(that.excludes)
- && includes.equals(that.includes);
+ boolean excludeEquals = true;
+ // Check if the lists have the same patterns in the same order
+ for (int i = 0; i < excludes.size(); i++) {
+ Pattern pattern = excludes.get(i);
+ Pattern thatPattern = that.excludes.get(i);
+ if (!pattern.pattern().equals(thatPattern.pattern())) {
+ excludeEquals = false;
+ break;
+ }
+ }
+ return includes.equals(that.includes) && excludeEquals;
}
@Override
diff --git
a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoaderIT.java
b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoaderIT.java
index 4bf07fb10..39303bce9 100644
---
a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoaderIT.java
+++
b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoaderIT.java
@@ -22,6 +22,12 @@ package org.apache.cayenne.dbsync.reverse.dbload;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator;
import org.apache.cayenne.dbsync.naming.NoStemStemmer;
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeColumn;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeTable;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
+import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig;
+import org.apache.cayenne.dbsync.reverse.filters.FiltersConfigBuilder;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.DbAttribute;
@@ -42,6 +48,7 @@ import java.sql.Connection;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
@@ -67,6 +74,38 @@ public class DbLoaderIT extends RuntimeCase {
private Connection connection;
+ @Test
+ public void testLoadingOrder() throws Exception {
+ ReverseEngineering engineering = new ReverseEngineering();
+ IncludeTable artistTableWithExclusion = new IncludeTable("ARTIST");
+ artistTableWithExclusion.addExcludeColumn(new
ExcludeColumn("DATE_OF_BIRTH"));
+ engineering.addIncludeTable(artistTableWithExclusion);
+ engineering.addIncludeTable(new IncludeTable("ARTIST"));
+
+ IncludeTable paintingTableWithExclusion = new IncludeTable("PAINTING");
+ paintingTableWithExclusion.addExcludeColumn(new
ExcludeColumn("PAINTING_DESCRIPTION"));
+ engineering.addIncludeTable(new IncludeTable("PAINTING"));
+ engineering.addIncludeTable(paintingTableWithExclusion);
+
+ FiltersConfigBuilder configBuilder = new
FiltersConfigBuilder(engineering);
+ FiltersConfig filtersConfig = configBuilder.build();
+
+ DbLoaderConfiguration dbLoaderConfiguration = new
DbLoaderConfiguration();
+ dbLoaderConfiguration.setFiltersConfig(filtersConfig);
+
+ DbLoader loader = createDbLoader(dbLoaderConfiguration);
+ DataMap loaded = loader.load();
+ assertNotNull(loaded);
+
+ DbEntity artist = loaded.getDbEntity("ARTIST");
+ DbEntity painting = loaded.getDbEntity("PAINTING");
+ assertNotNull(artist);
+ assertNotNull(painting);
+ assertNull(getDbAttribute(artist,"DATE_OF_BIRTH"));
+ assertNotNull(getDbAttribute(painting,"PAINTING_DESCRIPTION"));
+ }
+
+
/**
* Test that parts of loader are in place
*/
@@ -124,6 +163,10 @@ public class DbLoaderIT extends RuntimeCase {
return new DbLoader(adapter, connection, CONFIG, null, new
DefaultObjectNameGenerator(NoStemStemmer.getInstance()));
}
+ private DbLoader createDbLoader(DbLoaderConfiguration configuration) {
+ return new DbLoader(adapter, connection, configuration, null, new
DefaultObjectNameGenerator(NoStemStemmer.getInstance()));
+ }
+
@After
public void after() throws Exception {
connection.close();
diff --git
a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigTest.java
b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigTest.java
index e947b31c0..da277837f 100644
---
a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigTest.java
+++
b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigTest.java
@@ -20,14 +20,60 @@
package org.apache.cayenne.dbsync.reverse.filters;
import junit.framework.TestCase;
+import org.apache.cayenne.dbsync.reverse.dbimport.Catalog;
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeColumn;
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeProcedure;
+import org.apache.cayenne.dbsync.reverse.dbimport.ExcludeTable;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeColumn;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeProcedure;
+import org.apache.cayenne.dbsync.reverse.dbimport.IncludeTable;
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
+import java.util.ArrayList;
import java.util.Collections;
-import java.util.SortedSet;
-import java.util.TreeSet;
+import java.util.List;
import java.util.regex.Pattern;
+import static org.junit.Assert.assertThrows;
+
public class FiltersConfigTest extends TestCase {
+ private FiltersConfig filtersConfig;
+
+ @Override
+ protected void setUp() throws Exception {
+ ReverseEngineering engineering = new ReverseEngineering();
+ Catalog catalog = new Catalog("catalog");
+ Schema schema = new Schema("schema");
+
+ schema.addIncludeTable(new IncludeTable("iT2"));
+ schema.addIncludeTable(new IncludeTable("iT1"));
+
+ schema.addExcludeTable(new ExcludeTable("eT2"));
+ schema.addExcludeTable(new ExcludeTable("eT1"));
+
+ schema.addIncludeProcedure(new IncludeProcedure("iP2"));
+ schema.addIncludeProcedure(new IncludeProcedure("iP1"));
+
+ schema.addExcludeProcedure(new ExcludeProcedure("eP2"));
+ schema.addExcludeProcedure(new ExcludeProcedure("eP1"));
+
+ schema.addIncludeColumn(new IncludeColumn("iC2"));
+ schema.addIncludeColumn(new IncludeColumn("iC1"));
+
+ schema.addExcludeColumn(new ExcludeColumn("eC2"));
+ schema.addExcludeColumn(new ExcludeColumn("eC1"));
+
+ catalog.addSchema(schema);
+ engineering.addCatalog(catalog);
+
+ FiltersConfigBuilder configBuilder = new
FiltersConfigBuilder(engineering);
+ configBuilder.compact();
+
+ filtersConfig = configBuilder.build();
+ }
+
public void testToString_01() {
FiltersConfig config = FiltersConfig.create(null, null,
TableFilter.everything(), PatternFilter.INCLUDE_EVERYTHING);
@@ -75,16 +121,92 @@ public class FiltersConfigTest extends TestCase {
" Procedures: NONE\n", config.toString());
}
- private SortedSet<Pattern> excludes(String ... p) {
- SortedSet<Pattern> patterns = new
TreeSet<Pattern>(PatternFilter.PATTERN_COMPARATOR);
+ public void testTableFilter(){
+ assertNull(filtersConfig.tableFilter(null,null));
+
+ TableFilter tableFilter = filtersConfig.tableFilter("catalog",
"schema");
+ assertNotNull(tableFilter);
+ assertEquals(2,tableFilter.getIncludes().size());
+ assertEquals(2,tableFilter.getExcludes().size());
+ }
+
+ public void testProceduresFilter(){
+ assertNull(filtersConfig.proceduresFilter(null,null));
+
+ PatternFilter patternFilter =
filtersConfig.proceduresFilter("catalog", "schema");
+ assertNotNull(patternFilter);
+ assertEquals(2,patternFilter.getIncludes().size());
+ assertEquals(2,patternFilter.getExcludes().size());
+ }
+
+ public void testGetCatalogs(){
+ CatalogFilter[] catalogs = filtersConfig.getCatalogs();
+ assertNotNull(catalogs);
+ assertEquals(1,catalogs.length);
+ }
+
+ public void testGetCatalog(){
+ assertNull(filtersConfig.getCatalog(null));
+ CatalogFilter catalog = filtersConfig.getCatalog("catalog");
+ assertNotNull(catalog);
+ assertEquals("catalog",catalog.name);
+ assertEquals(1,catalog.schemas.length);
+ }
+
+ public void testGetSchemaFilter() {
+ assertNull(filtersConfig.getSchemaFilter(null,null));
+
+ SchemaFilter schemaFilter = filtersConfig.getSchemaFilter("catalog",
"schema");
+ assertNotNull(schemaFilter);
+ assertEquals("schema",schemaFilter.name);
+ assertEquals(2,schemaFilter.procedures.getIncludes().size());
+ assertEquals(2,schemaFilter.procedures.getExcludes().size());
+ }
+
+ public void testNullArgumentBuild() {
+ FiltersConfigBuilder configBuilder = new FiltersConfigBuilder(null);
+ assertThrows(NullPointerException.class, configBuilder::build);
+ }
+
+ public void testKeepingOrder() {
+ SchemaFilter schemaFilter =
filtersConfig.getCatalog("catalog").getSchema("schema");
+
+ List<IncludeTableFilter> tablesIncludes =
schemaFilter.tables.getIncludes();
+ List<Pattern> includeColumns =
tablesIncludes.get(0).columnsFilter.getIncludes();
+ List<Pattern> excludeColumns =
tablesIncludes.get(0).columnsFilter.getExcludes();
+ List<Pattern> tablesExcludes = schemaFilter.tables.getExcludes();
+ List<Pattern> proceduresIncludes =
schemaFilter.procedures.getIncludes();
+ List<Pattern> proceduresExcludes =
schemaFilter.procedures.getExcludes();
+
+ assertEquals("iT2", tablesIncludes.get(0).pattern.pattern());
+ assertEquals("iT1", tablesIncludes.get(1).pattern.pattern());
+
+ assertEquals("eT2", tablesExcludes.get(0).pattern());
+ assertEquals("eT1", tablesExcludes.get(1).pattern());
+
+ assertEquals("iC2", includeColumns.get(0).pattern());
+ assertEquals("iC1", includeColumns.get(1).pattern());
+
+ assertEquals("eC2", excludeColumns.get(0).pattern());
+ assertEquals("eC1", excludeColumns.get(1).pattern());
+
+ assertEquals("iP2", proceduresIncludes.get(0).pattern());
+ assertEquals("iP1", proceduresIncludes.get(1).pattern());
+
+ assertEquals("eP2", proceduresExcludes.get(0).pattern());
+ assertEquals("eP1", proceduresExcludes.get(1).pattern());
+ }
+
+ private List<Pattern> excludes(String ... p) {
+ List<Pattern> patterns = new ArrayList<Pattern>();
for (String pattern : p) {
patterns.add(PatternFilter.pattern(pattern));
}
return patterns;
}
- protected SortedSet<IncludeTableFilter> includes(IncludeTableFilter ...
filters) {
- SortedSet<IncludeTableFilter> includeTableFilters = new
TreeSet<IncludeTableFilter>();
+ protected List<IncludeTableFilter> includes(IncludeTableFilter ...
filters) {
+ List<IncludeTableFilter> includeTableFilters = new ArrayList<>();
Collections.addAll(includeTableFilters, filters);
return includeTableFilters;
diff --git
a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/TableFilterTest.java
b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/TableFilterTest.java
index 21b0e2179..a7a633c84 100644
---
a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/TableFilterTest.java
+++
b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/TableFilterTest.java
@@ -18,6 +18,8 @@
****************************************************************/
package org.apache.cayenne.dbsync.reverse.filters;
+import java.util.ArrayList;
+import java.util.List;
import java.util.TreeSet;
import java.util.regex.Pattern;
@@ -39,11 +41,11 @@ public class TableFilterTest {
@Test
public void testInclude() {
- TreeSet<IncludeTableFilter> includes = new TreeSet<>();
+ List<IncludeTableFilter> includes = new ArrayList<>();
includes.add(new IncludeTableFilter("aaa"));
includes.add(new IncludeTableFilter("bb"));
- TableFilter filter = new TableFilter(includes, new
TreeSet<>(PatternFilter.PATTERN_COMPARATOR));
+ TableFilter filter = new TableFilter(includes, new ArrayList<>());
assertTrue(filter.isIncludeTable("aaa"));
assertFalse(filter.isIncludeTable("aa"));
@@ -56,11 +58,11 @@ public class TableFilterTest {
@Test
public void testExclude() {
- TreeSet<Pattern> excludes = new
TreeSet<>(PatternFilter.PATTERN_COMPARATOR);
+ List<Pattern> excludes = new ArrayList<>();
excludes.add(Pattern.compile("aaa"));
excludes.add(Pattern.compile("bb"));
- TreeSet<IncludeTableFilter> includes = new TreeSet<>();
+ List<IncludeTableFilter> includes = new ArrayList<>();
includes.add(new IncludeTableFilter(null,
PatternFilter.INCLUDE_EVERYTHING));
TableFilter filter = new TableFilter(includes, excludes);
@@ -76,11 +78,11 @@ public class TableFilterTest {
@Test
public void testIncludeExclude() {
- TreeSet<Pattern> excludes = new
TreeSet<>(PatternFilter.PATTERN_COMPARATOR);
+ List<Pattern> excludes = new ArrayList<>();
excludes.add(Pattern.compile("aaa"));
excludes.add(Pattern.compile("bb"));
- TreeSet<IncludeTableFilter> includes = new TreeSet<>();
+ List<IncludeTableFilter> includes = new ArrayList<>();
includes.add(new IncludeTableFilter("aa.*"));
TableFilter filter = new TableFilter(includes, excludes);
@@ -96,11 +98,11 @@ public class TableFilterTest {
@Test
public void testGetTableFilter() {
- TreeSet<IncludeTableFilter> includes = new
TreeSet<IncludeTableFilter>();
+ List<IncludeTableFilter> includes = new ArrayList<>();
includes.add(new IncludeTableFilter("aaa"));
includes.add(new IncludeTableFilter("bb"));
- TreeSet<Pattern> excludes = new TreeSet<>();
+ List<Pattern> excludes = new ArrayList<>();
TableFilter filter = new TableFilter(includes, excludes);
@@ -112,4 +114,41 @@ public class TableFilterTest {
assertNull(filter.getIncludeTableColumnFilter(""));
assertNull(filter.getIncludeTableColumnFilter("bbbb"));
}
+
+ @Test
+ public void testExcludePriority(){
+ List<IncludeTableFilter> includes = new ArrayList<>();
+ includes.add(new IncludeTableFilter("a"));
+
+ List<Pattern> excludes = new ArrayList<>();
+ excludes.add(Pattern.compile("a"));
+
+ TableFilter tableFilter = new TableFilter(includes, excludes);
+
+ assertNull( tableFilter.getIncludeTableColumnFilter("a"));
+ }
+
+ @Test
+ public void testPatternsOrder(){
+ List<IncludeTableFilter> includes = new ArrayList<>();
+ includes.add(new IncludeTableFilter("b"));
+ includes.add(new IncludeTableFilter("a"));
+
+ List<Pattern> excludes = new ArrayList<>();
+ excludes.add(Pattern.compile("b"));
+ excludes.add(Pattern.compile("a"));
+
+ TableFilter tableFilter = new TableFilter(includes, excludes);
+
+ assertEquals("b",tableFilter.getIncludes().get(0).pattern.pattern());
+ assertEquals("b",tableFilter.getExcludes().get(0).pattern());
+ }
+ @Test
+ public void testNullArguments(){
+ TableFilter tableFilter = new TableFilter(null, null);
+ assertNotNull(tableFilter);
+ assertThrows(NullPointerException.class, () ->
tableFilter.isIncludeTable(null) );
+
+ }
+
}
\ No newline at end of file
diff --git
a/maven-plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java
b/maven-plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java
index 6ca8ef2ac..d2c056379 100644
---
a/maven-plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java
+++
b/maven-plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java
@@ -18,9 +18,10 @@
****************************************************************/
package org.apache.cayenne.tools;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
-import java.util.TreeSet;
import java.util.regex.Pattern;
import org.apache.cayenne.dbsync.reverse.dbimport.Catalog;
@@ -75,10 +76,10 @@ public class DbImporterMojoConfigurationTest extends
AbstractMojoTestCase {
FiltersConfig filters =
dbImportConfiguration.getDbLoaderConfig().getFiltersConfig();
- TreeSet<IncludeTableFilter> includes = new TreeSet<>();
+ List<IncludeTableFilter> includes = new ArrayList<>();
includes.add(new IncludeTableFilter(null, new
PatternFilter().exclude("^ETL_.*")));
- TreeSet<Pattern> excludes = new
TreeSet<>(PatternFilter.PATTERN_COMPARATOR);
+ List<Pattern> excludes = new ArrayList<>();
excludes.add(PatternFilter.pattern("^ETL_.*"));
assertEquals(filters.tableFilter(null, "NHL_STATS"),
diff --git
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DefaultActionManager.java
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DefaultActionManager.java
index 1aec38f2f..24dd89518 100644
---
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DefaultActionManager.java
+++
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DefaultActionManager.java
@@ -31,6 +31,7 @@ import
org.apache.cayenne.modeler.action.dbimport.AddIncludeProcedureAction;
import org.apache.cayenne.modeler.action.dbimport.AddIncludeTableAction;
import org.apache.cayenne.modeler.action.dbimport.AddSchemaAction;
import org.apache.cayenne.modeler.action.dbimport.DeleteNodeAction;
+import org.apache.cayenne.modeler.action.dbimport.DragAndDropNodeAction;
import org.apache.cayenne.modeler.action.dbimport.EditNodeAction;
import org.apache.cayenne.modeler.action.dbimport.MoveImportNodeAction;
import org.apache.cayenne.modeler.action.dbimport.MoveInvertNodeAction;
@@ -124,7 +125,9 @@ public class DefaultActionManager implements ActionManager {
registerAction(new EditNodeAction(application)).setAlwaysOn(true);
registerAction(new DeleteNodeAction(application)).setAlwaysOn(true);
registerAction(new
MoveImportNodeAction(application)).setAlwaysOn(true);
+ registerAction(new
DragAndDropNodeAction(application)).setAlwaysOn(true);
registerAction(new LoadDbSchemaAction(application)).setAlwaysOn(true);
+ registerAction(new SortNodesAction(application)).setAlwaysOn(true);
registerAction(new
MoveInvertNodeAction(application)).setAlwaysOn(true);
registerAction(new AboutAction(application)).setAlwaysOn(true);
registerAction(new DocumentationAction(application)).setAlwaysOn(true);
diff --git
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/SortNodesAction.java
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/SortNodesAction.java
new file mode 100644
index 000000000..fd7f856ff
--- /dev/null
+++
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/SortNodesAction.java
@@ -0,0 +1,59 @@
+/*****************************************************************
+ * 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.action;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.action.dbimport.TreeManipulationAction;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.modeler.editor.dbimport.DbImportSorter;
+
+import java.awt.event.ActionEvent;
+import java.util.List;
+
+/**
+ * @since 5.0
+ */
+public class SortNodesAction extends TreeManipulationAction {
+
+ private static final String ACTION_NAME = "Sort";
+ private static final String ICON_NAME = "icon-dbi-sort.png";
+
+ public SortNodesAction(Application application) {
+ super(ACTION_NAME, application);
+ }
+
+ public String getIconName() {
+ return ICON_NAME;
+ }
+
+ @Override
+ public void performAction(ActionEvent e) {
+ tree.stopEditing();
+ ReverseEngineering reverseEngineeringOldCopy = new
ReverseEngineering(tree.getReverseEngineering());
+ List<DbImportTreeNode> treeExpandList = tree.getTreeExpandList();
+ DbImportSorter.sortSubtree(tree.getRootNode(),
DbImportSorter.NODE_COMPARATOR_BY_TYPE_BY_NAME);
+ putReverseEngineeringToUndoManager(reverseEngineeringOldCopy);
+ getProjectController().setDirty(true);
+ tree.reloadModelKeepingExpanded();
+ tree.expandTree(treeExpandList);
+ }
+
+}
diff --git
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/DeleteNodeAction.java
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/DeleteNodeAction.java
index 70f51a47d..4093d9553 100644
---
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/DeleteNodeAction.java
+++
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/DeleteNodeAction.java
@@ -38,7 +38,7 @@ import
org.apache.cayenne.modeler.editor.dbimport.DraggableTreePanel;
import javax.swing.tree.TreePath;
import java.awt.event.ActionEvent;
-import java.util.ArrayList;
+import java.util.List;
/**
* @since 4.1
@@ -117,7 +117,7 @@ public class DeleteNodeAction extends
TreeManipulationAction {
DbImportModel model = (DbImportModel) tree.getModel();
model.removeNodeFromParent(selectedElement);
getProjectController().setDirty(true);
- model.reload(parentElement);
+ tree.reloadModelKeepingExpanded(parentElement);
}
@Override
@@ -152,7 +152,7 @@ public class DeleteNodeAction extends
TreeManipulationAction {
}
if (paths.length > 1) {
getProjectController().setDirty(true);
- ArrayList<DbImportTreeNode> expandList =
tree.getTreeExpandList();
+ List<DbImportTreeNode> expandList = tree.getTreeExpandList();
tree.translateReverseEngineeringToTree(tree.getReverseEngineering(), false);
tree.expandTree(expandList);
} else {
diff --git
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/DragAndDropNodeAction.java
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/DragAndDropNodeAction.java
new file mode 100644
index 000000000..8779723eb
--- /dev/null
+++
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/DragAndDropNodeAction.java
@@ -0,0 +1,157 @@
+/*****************************************************************
+ * 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.action.dbimport;
+
+import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
+import org.apache.cayenne.modeler.editor.dbimport.DbImportModel;
+import org.apache.cayenne.modeler.editor.dbimport.DbImportSorter;
+
+import javax.swing.JOptionPane;
+import javax.swing.JTree;
+import javax.swing.tree.TreePath;
+import java.awt.event.ActionEvent;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @since 5.0
+ */
+public class DragAndDropNodeAction extends TreeManipulationAction {
+
+ private static final String ACTION_NAME = "DragAndDrop";
+ private DbImportTreeNode[] nodes;
+ private DbImportTreeNode dropLocationParentNode;
+ private DbImportTreeNode sourceParentNode;
+ private JTree.DropLocation dropLocation;
+
+ public DragAndDropNodeAction(Application application) {
+ super(ACTION_NAME, application);
+ }
+
+ @Override
+ public void performAction(ActionEvent e) {
+ if (dropLocationDuplicateFound()) {
+ return;
+ }
+ DbImportModel model = (DbImportModel) tree.getModel();
+ ReverseEngineering reverseEngineeringOldCopy = new
ReverseEngineering(tree.getReverseEngineering());
+ List<DbImportTreeNode> nodesToExpand = Arrays.stream(nodes)
+ .filter(node -> tree.isExpanded(new TreePath(node.getPath())))
+ .collect(Collectors.toList());
+
+ for (DbImportTreeNode node : nodes) {
+ if (checkDropPossibility(node)) {
+ int index = calculateDropIndex();
+ model.removeNodeFromParent(node);
+ model.insertNodeInto(node, dropLocationParentNode, index);
+ }
+ }
+ getProjectController().setDirty(true);
+ DbImportSorter.syncUserObjectItems(dropLocationParentNode);
+ DbImportSorter.syncUserObjectItems(sourceParentNode);
+ putReverseEngineeringToUndoManager(reverseEngineeringOldCopy);
+ tree.reloadModelKeepingExpanded(dropLocationParentNode);
+ tree.expandTree(nodesToExpand);
+ }
+
+ private boolean dropLocationDuplicateFound() {
+ for (DbImportTreeNode node : nodes) {
+ if (dropLocationParentNode.isNodeChild(node)) {
+ // we are fine about this
+ continue;
+ }
+ int duplicateIndex =
dropLocationParentNode.getChildNodes().indexOf(node);
+ if (duplicateIndex >= 0) {
+ JOptionPane.showMessageDialog(
+ Application.getFrame(),
+ dropLocationParentNode.getSimpleNodeName() + " already
contains " + node.getSimpleNodeName(),
+ "Error moving",
+ JOptionPane.ERROR_MESSAGE);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private int calculateDropIndex() {
+ int index = dropLocation.getChildIndex();
+ //node moving inside a one node
+ if (sourceParentNode == dropLocationParentNode) {
+ int childCount = dropLocationParentNode.getChildCount();
+ int childIndex = dropLocation.getChildIndex();
+ if (childIndex == childCount) {
+ index = childCount - 1;
+ }
+ }
+ //If target node is collapsed
+ if (index == -1 && sourceParentNode != dropLocationParentNode) {
+ index = dropLocationParentNode.getChildCount();
+ }
+
+ //If the target node is an expanded parent node, we place the node in
the first position
+ if (index == -1 && sourceParentNode == dropLocationParentNode) {
+ index = 0;
+ }
+ return index;
+ }
+
+ private boolean checkDropPossibility(DbImportTreeNode node) {
+ // Don't allow a node to be dropped onto itself
+ if (node == dropLocationParentNode) {
+ return false;
+ }
+ // Don't allow a node to be dropped onto one of its descendants
+ for (DbImportTreeNode childNode : node.getChildNodes()) {
+ if (isNodeAncestor(childNode, dropLocationParentNode)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean isNodeAncestor(DbImportTreeNode node1, DbImportTreeNode
node2) {
+ if (node2 == null) {
+ return false;
+ }
+ if (node2.getParent() == node1) {
+ return true;
+ }
+ return isNodeAncestor(node1, node2.getParent());
+ }
+
+ public void setNodes(DbImportTreeNode[] nodes) {
+ this.nodes = nodes;
+ }
+
+ public void setDropLocationParentNode(DbImportTreeNode
dropLocationParentNode) {
+ this.dropLocationParentNode = dropLocationParentNode;
+ }
+
+ public void setSourceParentNode(DbImportTreeNode sourceParentNode) {
+ this.sourceParentNode = sourceParentNode;
+ }
+
+ public void setDropLocation(JTree.DropLocation dropLocation) {
+ this.dropLocation = dropLocation;
+ }
+}
diff --git
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/EditNodeAction.java
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/EditNodeAction.java
index 1e1864a4b..a1e9ffc3a 100644
---
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/EditNodeAction.java
+++
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/EditNodeAction.java
@@ -79,8 +79,8 @@ public class EditNodeAction extends TreeManipulationAction {
putReverseEngineeringToUndoManager(reverseEngineeringOldCopy);
}
}
- DbImportSorter.sortSingleNode(selectedElement.getParent());
- tree.reloadModel();
+
DbImportSorter.sortSingleNode(selectedElement.getParent(),DbImportSorter.NODE_COMPARATOR_BY_TYPE);
+ tree.reloadModelKeepingExpanded();
tree.setSelectionPath(new TreePath(selectedElement.getPath()));
selectedElement = null;
}
diff --git
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/MoveImportNodeAction.java
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/MoveImportNodeAction.java
index 455082808..4c0474051 100644
---
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/MoveImportNodeAction.java
+++
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/MoveImportNodeAction.java
@@ -39,8 +39,8 @@ import org.apache.cayenne.modeler.util.CayenneAction;
import javax.swing.tree.TreePath;
import java.awt.event.ActionEvent;
-import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
@@ -187,7 +187,7 @@ public class MoveImportNodeAction extends CayenneAction {
}
if ((paths.length > 1) && (targetTree.getSelectionPath() !=
null)) {
getProjectController().setDirty(true);
- ArrayList<DbImportTreeNode> expandList =
targetTree.getTreeExpandList();
+ List<DbImportTreeNode> expandList =
targetTree.getTreeExpandList();
targetTree.translateReverseEngineeringToTree(targetTree.getReverseEngineering(),
false);
targetTree.expandTree(expandList);
}
@@ -199,8 +199,8 @@ public class MoveImportNodeAction extends CayenneAction {
getProjectController().getApplication().getUndoManager().addEdit(undoableEdit);
}
if (foundNode != null) {
- DbImportSorter.sortSubtree((DbImportTreeNode)
foundNode.getRoot());
- targetTree.reloadModel();
+ DbImportSorter.sortSubtree((DbImportTreeNode)
foundNode.getRoot(),DbImportSorter.NODE_COMPARATOR_BY_TYPE);
+ targetTree.reloadModelKeepingExpanded();
targetTree.setSelectionPath(new
TreePath(foundNode.getLastChild().getPath()));
}
} finally {
diff --git
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/TreeManipulationAction.java
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/TreeManipulationAction.java
index fbbc47879..e3cbd9462 100644
---
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/TreeManipulationAction.java
+++
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/dbimport/TreeManipulationAction.java
@@ -190,7 +190,7 @@ public abstract class TreeManipulationAction extends
CayenneAction {
if (!updateSelected) {
savedPath = new TreePath(parentElement.getPath());
}
- model.reload(updateSelected ? selectedElement : parentElement);
+ tree.reloadModelKeepingExpanded(updateSelected ? selectedElement :
parentElement);
if ((savedPath != null) && (parentElement.getUserObject().getClass()
!= ReverseEngineering.class)) {
tree.setSelectionPath(savedPath);
}
diff --git
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbImportTreeNode.java
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbImportTreeNode.java
index ada7428d0..332953b9f 100644
---
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbImportTreeNode.java
+++
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbImportTreeNode.java
@@ -36,6 +36,7 @@ import javax.swing.tree.DefaultMutableTreeNode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import java.util.stream.Collectors;
@@ -50,64 +51,72 @@ public class DbImportTreeNode extends
DefaultMutableTreeNode {
this(null);
}
+ public DbImportTreeNode(Object userObject) {
+ this(userObject, true);
+ }
+
private DbImportTreeNode(Object userObject, boolean allowsChildren) {
super();
this.userObject = userObject;
this.allowsChildren = allowsChildren;
parent = null;
+
+ if (userObject != null && (isCatalog() || isSchema() ||
isIncludeTable())) {
+ add(new ExpandableEnforcerNode());
+ }
}
public boolean isIncludeTable() {
- return (getUserObject().getClass() == IncludeTable.class);
+ return (getUserObjectClass() == IncludeTable.class);
}
public boolean isExcludeTable() {
- return (getUserObject().getClass() == ExcludeTable.class);
+ return (getUserObjectClass() == ExcludeTable.class);
}
public boolean isIncludeColumn() {
- return (getUserObject().getClass() == IncludeColumn.class);
+ return (getUserObjectClass() == IncludeColumn.class);
}
public boolean isExcludeColumn() {
- return (getUserObject().getClass() == ExcludeColumn.class);
+ return (getUserObjectClass() == ExcludeColumn.class);
}
public boolean isExcludeProcedure() {
- return (getUserObject().getClass() == ExcludeProcedure.class);
+ return (getUserObjectClass() == ExcludeProcedure.class);
}
public boolean isIncludeProcedure() {
- return (getUserObject().getClass() == IncludeProcedure.class);
+ return (getUserObjectClass() == IncludeProcedure.class);
}
public boolean isLabel() {
- return (getUserObject().getClass() == String.class);
+ return (getUserObjectClass() == String.class);
}
public boolean isSchema() {
- return (getUserObject().getClass() == Schema.class);
+ return (getUserObjectClass() == Schema.class);
}
public boolean isCatalog() {
- return (getUserObject().getClass() == Catalog.class);
+ return (getUserObjectClass() == Catalog.class);
}
public boolean isReverseEngineering() {
- return (getUserObject().getClass() == ReverseEngineering.class);
+ return (getUserObjectClass() == ReverseEngineering.class);
}
- public DbImportTreeNode(Object userObject) {
- this(userObject, true);
+ public Class<?> getUserObjectClass() {
+ return getUserObject() != null ? getUserObject().getClass() : null;
}
// Compare parents chain
public boolean parentsIsEqual(DbImportTreeNode reverseEngineeringNode) {
ArrayList<DbImportTreeNode> reverseEngineeringNodeParents;
if (reverseEngineeringNode == null) {
- reverseEngineeringNodeParents = new ArrayList<>();
+ reverseEngineeringNodeParents = new ArrayList<>();
} else {
- reverseEngineeringNodeParents =
reverseEngineeringNode.getParents();
+ reverseEngineeringNodeParents =
reverseEngineeringNode.getParents();
}
ArrayList<DbImportTreeNode> dbNodeParents = getParents();
for (DbImportTreeNode node : reverseEngineeringNodeParents) {
@@ -140,7 +149,7 @@ public class DbImportTreeNode extends
DefaultMutableTreeNode {
@Override
public DbImportTreeNode getParent() {
- return (DbImportTreeNode)super.getParent();
+ return (DbImportTreeNode) super.getParent();
}
protected String getFormattedName(String className, String nodeName) {
@@ -194,13 +203,13 @@ public class DbImportTreeNode extends
DefaultMutableTreeNode {
return false;
}
DbImportTreeNode objNode = (DbImportTreeNode) obj;
- if (!objNode.getSimpleNodeName().equals(this.getSimpleNodeName())) {
- return false;
- }
- if (objNode.getUserObject().getClass() !=
this.getUserObject().getClass()) {
- return false;
- }
- return true;
+ return Objects.equals(getSimpleNodeName(), objNode.getSimpleNodeName())
+ && getUserObjectClass() == objNode.getUserObjectClass();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getSimpleNodeName(), getUserObjectClass());
}
public boolean isLoaded() {
@@ -250,4 +259,11 @@ public class DbImportTreeNode extends
DefaultMutableTreeNode {
public DbImportTreeNode getLastChild() {
return (DbImportTreeNode) super.getLastChild();
}
+
+ public static class ExpandableEnforcerNode extends DbImportTreeNode {
+
+ public ExpandableEnforcerNode() {
+ super("", false);
+ }
+ }
}
diff --git
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/TransferableNode.java
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/TransferableNode.java
index a7d8af6b3..7a8eaa8f0 100644
---
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/TransferableNode.java
+++
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/TransferableNode.java
@@ -20,11 +20,8 @@
package org.apache.cayenne.modeler.dialog.db.load;
import org.apache.cayenne.dbsync.reverse.dbimport.Catalog;
-import org.apache.cayenne.dbsync.reverse.dbimport.FilterContainer;
-import org.apache.cayenne.dbsync.reverse.dbimport.IncludeProcedure;
import org.apache.cayenne.dbsync.reverse.dbimport.IncludeTable;
import org.apache.cayenne.dbsync.reverse.dbimport.PatternParam;
-import org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
import java.awt.datatransfer.DataFlavor;
@@ -45,7 +42,7 @@ public class TransferableNode extends DbImportTreeNode
implements Transferable {
includeTableFlavor, patternParamFlavor };
public TransferableNode(Object userObject) {
- this.userObject = userObject;
+ super(userObject);
}
@Override
diff --git
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportSorter.java
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportSorter.java
index b44bc6246..2b585d6d4 100644
---
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportSorter.java
+++
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportSorter.java
@@ -36,28 +36,32 @@ import java.util.List;
* @since 5.0
*/
public class DbImportSorter {
- private static final Comparator<DbImportTreeNode> NODE_COMPARATOR =
Comparator
+ public static final Comparator<DbImportTreeNode> NODE_COMPARATOR_BY_TYPE =
Comparator
+ .comparing(DbImportTreeNode::getNodeType);
+
+
+ public static final Comparator<DbImportTreeNode>
NODE_COMPARATOR_BY_TYPE_BY_NAME = Comparator
.comparing(DbImportTreeNode::getNodeType)
.thenComparing(DbImportTreeNode::getSimpleNodeName);
- public static void sortSingleNode(DbImportTreeNode node) {
- sortNodeItems(node);
+ public static void sortSingleNode(DbImportTreeNode node,
Comparator<DbImportTreeNode> comparator) {
+ sortNodeItems(node, comparator);
syncUserObjectItems(node);
}
- public static void sortSubtree(DbImportTreeNode root) {
- sortSingleNode(root);
- root.getChildNodes().forEach(DbImportSorter::sortSubtree);
+ public static void sortSubtree(DbImportTreeNode
root,Comparator<DbImportTreeNode> comparator) {
+ sortSingleNode(root, comparator);
+ root.getChildNodes().forEach(r -> sortSubtree(r, comparator));
}
- private static void sortNodeItems(DbImportTreeNode node) {
+ private static void sortNodeItems(DbImportTreeNode node,
Comparator<DbImportTreeNode> comparator) {
List<DbImportTreeNode> childNodes = node.getChildNodes();
node.removeAllChildren();
- childNodes.sort(NODE_COMPARATOR);
+ childNodes.sort(comparator);
childNodes.forEach(node::add);
}
- private static void syncUserObjectItems(DbImportTreeNode parentNode) {
+ public static void syncUserObjectItems(DbImportTreeNode parentNode) {
Object userObject = parentNode.getUserObject();
diff --git
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTree.java
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTree.java
index 93afaedb8..b2262e071 100644
---
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTree.java
+++
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTree.java
@@ -35,11 +35,13 @@ import
org.apache.cayenne.modeler.dialog.db.load.TransferableNode;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
+import javax.swing.plaf.basic.BasicTreeUI;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
import java.util.function.BiFunction;
@@ -53,6 +55,8 @@ public class DbImportTree extends JTree {
public DbImportTree(TreeNode node) {
super(node);
+ setRowHeight(0);
+ setUI(new TreeUI());
createTreeExpandListener();
}
@@ -71,7 +75,7 @@ public class DbImportTree extends JTree {
printParams(reverseEngineering.getExcludeColumns(), root);
printParams(reverseEngineering.getIncludeProcedures(), root);
printParams(reverseEngineering.getExcludeProcedures(), root);
- DbImportSorter.sortSubtree(root);
+ DbImportSorter.sortSubtree(root,
DbImportSorter.NODE_COMPARATOR_BY_TYPE);
model.reload();
}
@@ -212,7 +216,7 @@ public class DbImportTree extends JTree {
}
// Create list of expanded elements
- private ArrayList<DbImportTreeNode> createTreeExpandList(DbImportTreeNode
rootNode, ArrayList<DbImportTreeNode> resultList) {
+ private List<DbImportTreeNode> createTreeExpandList(DbImportTreeNode
rootNode, List<DbImportTreeNode> resultList) {
for (int i = 0; i < rootNode.getChildCount(); i++) {
DbImportTreeNode childNode = (DbImportTreeNode)
rootNode.getChildAt(i);
TreePath childPath = new TreePath(childNode.getPath());
@@ -226,12 +230,23 @@ public class DbImportTree extends JTree {
return resultList;
}
- public ArrayList<DbImportTreeNode> getTreeExpandList() {
+ public void reloadModelKeepingExpanded(DbImportTreeNode node) {
+ DbImportModel model = (DbImportModel) getModel();
+ List<DbImportTreeNode> nodesToExpand = getTreeExpandList();
+ model.reload(node);
+ expandTree(nodesToExpand);
+ }
+
+ public void reloadModelKeepingExpanded() {
+ reloadModelKeepingExpanded(getRootNode());
+ }
+
+ public List<DbImportTreeNode> getTreeExpandList() {
ArrayList<DbImportTreeNode> resultList = new ArrayList<>();
return createTreeExpandList(getRootNode(), resultList);
}
- private void expandBeginningWithNode(DbImportTreeNode rootNode,
ArrayList<DbImportTreeNode> list) {
+ private void expandBeginningWithNode(DbImportTreeNode rootNode,
List<DbImportTreeNode> list) {
for (int i = 0; i < rootNode.getChildCount(); i++) {
DbImportTreeNode childNode = (DbImportTreeNode)
rootNode.getChildAt(i);
list.forEach((element) -> {
@@ -245,7 +260,7 @@ public class DbImportTree extends JTree {
}
}
- public void expandTree(ArrayList<DbImportTreeNode> expandIndexesList) {
+ public void expandTree(List<DbImportTreeNode> expandIndexesList) {
expandBeginningWithNode(getRootNode(), expandIndexesList);
}
@@ -258,15 +273,10 @@ public class DbImportTree extends JTree {
}
}
- public void reloadModel(){
- DbImportModel model = (DbImportModel)this.getModel();
- model.reload();
- }
-
private void printIncludeTables(Collection<IncludeTable> collection,
DbImportTreeNode parent) {
for (IncludeTable includeTable : collection) {
DbImportTreeNode node = !isTransferable ? new
DbImportTreeNode(includeTable) : new TransferableNode(includeTable);
- if (!node.getSimpleNodeName().equals("")) {
+ if (!node.getSimpleNodeName().isEmpty()) {
if (isTransferable &&
includeTable.getIncludeColumns().isEmpty() &&
includeTable.getExcludeColumns().isEmpty()) {
printParams(Collections.singletonList(new
IncludeColumn("Loading...")), node);
@@ -370,4 +380,18 @@ public class DbImportTree extends JTree {
public boolean isTransferable() {
return isTransferable;
}
+
+ static class TreeUI extends BasicTreeUI {
+
+ @Override
+ protected boolean shouldPaintExpandControl(TreePath path, int row,
boolean isExpanded,
+ boolean hasBeenExpanded,
boolean isLeaf) {
+ DbImportTreeNode node = (DbImportTreeNode)
path.getLastPathComponent();
+ int childCount = node.getChildCount();
+ boolean onlyEnforcerChild = childCount == 1
+ && node.getFirstChild().getClass() ==
DbImportTreeNode.ExpandableEnforcerNode.class;
+ return super.shouldPaintExpandControl(path, row, isExpanded,
hasBeenExpanded, isLeaf)
+ && (childCount > 1 || !onlyEnforcerChild);
+ }
+ }
}
diff --git
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTreeCellEditor.java
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTreeCellEditor.java
index 1789f25cb..e4e354c54 100644
---
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTreeCellEditor.java
+++
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTreeCellEditor.java
@@ -26,6 +26,7 @@ import
org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
import org.apache.cayenne.util.Util;
import javax.swing.JTree;
+import javax.swing.UIManager;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.tree.DefaultTreeCellEditor;
@@ -44,6 +45,7 @@ public class DbImportTreeCellEditor extends
DefaultTreeCellEditor {
public DbImportTreeCellEditor(JTree tree, DefaultTreeCellRenderer
renderer) {
super(tree, renderer);
+ setFont(UIManager.getFont("Tree.font"));
this.addCellEditorListener(new CellEditorListener() {
@Override
public void editingStopped(ChangeEvent e) {
@@ -73,8 +75,7 @@ public class DbImportTreeCellEditor extends
DefaultTreeCellEditor {
if (value instanceof DbImportTreeNode) {
value = ((DbImportTreeNode) value).getSimpleNodeName();
}
- return super.getTreeCellEditorComponent(tree, value, isSelected,
expanded,
- leaf, row);
+ return super.getTreeCellEditorComponent(tree, value, isSelected,
expanded, leaf, row);
}
@Override
@@ -122,7 +123,7 @@ public class DbImportTreeCellEditor extends
DefaultTreeCellEditor {
}
if (tree.getSelectionPath() != null) {
DbImportTreeNode selectedNode = (DbImportTreeNode)
tree.getSelectionPath().getLastPathComponent();
- ((DbImportModel) tree.getModel()).reload(selectedNode);
+ ((DbImportTree) tree).reloadModelKeepingExpanded(selectedNode);
}
}
diff --git
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTreeCellRenderer.java
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTreeCellRenderer.java
index d2a1ce14e..4e5e5ed47 100644
---
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTreeCellRenderer.java
+++
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportTreeCellRenderer.java
@@ -30,10 +30,13 @@ import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
import org.apache.cayenne.modeler.dialog.db.load.DbImportTreeNode;
import org.apache.cayenne.modeler.util.ModelerUtil;
+import javax.swing.Icon;
import javax.swing.ImageIcon;
+import javax.swing.JLabel;
import javax.swing.JTree;
import javax.swing.tree.DefaultTreeCellRenderer;
import java.awt.Component;
+import java.awt.Dimension;
import java.util.HashMap;
import java.util.Map;
@@ -43,16 +46,15 @@ import java.util.Map;
public class DbImportTreeCellRenderer extends DefaultTreeCellRenderer {
protected DbImportTreeNode node;
- private Map<Class, String> icons;
- private Map<Class, String> transferableTreeIcons;
+ private Map<Class<?>, String> icons;
+ private Map<Class<?>, String> transferableTreeIcons;
public DbImportTreeCellRenderer() {
- super();
initIcons();
- initTrasferableTreeIcons();
+ initTransferableTreeIcons();
}
- private void initTrasferableTreeIcons() {
+ private void initTransferableTreeIcons() {
transferableTreeIcons = new HashMap<>();
transferableTreeIcons.put(Catalog.class, "icon-dbi-catalog.png");
transferableTreeIcons.put(Schema.class, "icon-dbi-schema.png");
@@ -73,7 +75,7 @@ public class DbImportTreeCellRenderer extends
DefaultTreeCellRenderer {
icons.put(ExcludeProcedure.class, "icon-dbi-excludeProcedure.png");
}
- private ImageIcon getIconByNodeType(Class nodeClass, boolean
isTransferable) {
+ private ImageIcon getIconByNodeType(Class<?> nodeClass, boolean
isTransferable) {
String iconName = !isTransferable ? icons.get(nodeClass) :
transferableTreeIcons.get(nodeClass);
if (iconName == null) {
return null;
@@ -91,6 +93,44 @@ public class DbImportTreeCellRenderer extends
DefaultTreeCellRenderer {
super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf,
row, hasFocus);
node = (DbImportTreeNode) value;
setIcon(getIconByNodeType(node.getUserObject().getClass(),
((DbImportTree) tree).isTransferable()));
- return this;
+ return value instanceof DbImportTreeNode.ExpandableEnforcerNode
+ ? ExpandableEnforcer.getInstance()
+ : this;
+ }
+
+ @Override
+ public Icon getLeafIcon() {
+ return null;
+ }
+
+ @Override
+ public Icon getOpenIcon() {
+ return null;
+ }
+
+ @Override
+ public Icon getClosedIcon() {
+ return null;
+ }
+
+ private static class ExpandableEnforcer extends JLabel {
+
+ private static ExpandableEnforcer instance;
+
+ public ExpandableEnforcer() {
+ setPreferredSize(new Dimension(0, 0));
+ }
+
+ public static ExpandableEnforcer getInstance() {
+ if (instance == null) {
+ instance = new ExpandableEnforcer();
+ }
+ return instance;
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ return super.getPreferredSize();
+ }
}
}
diff --git
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DraggableTreePanel.java
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DraggableTreePanel.java
index 320ac406b..a24b3ad3a 100644
---
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DraggableTreePanel.java
+++
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DraggableTreePanel.java
@@ -38,6 +38,7 @@ import
org.apache.cayenne.modeler.action.dbimport.AddIncludeColumnAction;
import org.apache.cayenne.modeler.action.dbimport.AddIncludeProcedureAction;
import org.apache.cayenne.modeler.action.dbimport.AddIncludeTableAction;
import org.apache.cayenne.modeler.action.dbimport.AddSchemaAction;
+import org.apache.cayenne.modeler.action.dbimport.DragAndDropNodeAction;
import org.apache.cayenne.modeler.action.dbimport.MoveImportNodeAction;
import org.apache.cayenne.modeler.action.dbimport.MoveInvertNodeAction;
import org.apache.cayenne.modeler.action.dbimport.TreeManipulationAction;
@@ -54,7 +55,6 @@ import javax.swing.JTree;
import javax.swing.TransferHandler;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
-import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreePath;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
@@ -93,6 +93,7 @@ public class DraggableTreePanel extends JScrollPane {
private CayenneAction.CayenneToolbarButton moveButton;
private CayenneAction.CayenneToolbarButton moveInvertButton;
+ private ImportSourceTree importSourceTree;
public DraggableTreePanel(ProjectController projectController,
DbImportTree sourceTree, DbImportTree targetTree) {
super(sourceTree);
@@ -143,6 +144,7 @@ public class DraggableTreePanel extends JScrollPane {
targetTree.setTransferHandler(new TargetTreeTransferHandler());
targetTree.addTreeSelectionListener(new TargetTreeSelectionListener());
targetTree.setDragEnabled(true);
+ targetTree.setDropMode(DropMode.INSERT);
}
private boolean canBeInverted() {
@@ -174,12 +176,6 @@ public class DraggableTreePanel extends JScrollPane {
moveInvertButton = (CayenneAction.CayenneToolbarButton)
actionInv.buildButton();
moveInvertButton.setShowingText(true);
moveInvertButton.setText(MOVE_INV_BUTTON_LABEL);
-
-
- DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer)
sourceTree.getCellRenderer();
- renderer.setLeafIcon(null);
- renderer.setClosedIcon(null);
- renderer.setOpenIcon(null);
}
private void initLevels() {
@@ -226,7 +222,7 @@ public class DraggableTreePanel extends JScrollPane {
if (selectedElement.isIncludeColumn() ||
selectedElement.isExcludeColumn()) {
DbImportTreeNode node =
targetTree.findNode(targetTree.getRootNode(), selectedElement.getParent(), 0);
- if(node != null && node.isExcludeTable()) {
+ if (node != null && node.isExcludeTable()) {
return false;
}
}
@@ -273,7 +269,7 @@ public class DraggableTreePanel extends JScrollPane {
return sourceTree;
}
- private static class SourceTreeTransferHandler extends TransferHandler {
+ private class SourceTreeTransferHandler extends TransferHandler {
@Override
public int getSourceActions(JComponent c) {
@@ -282,6 +278,7 @@ public class DraggableTreePanel extends JScrollPane {
@Override
public Transferable createTransferable(JComponent c) {
+ importSourceTree = ImportSourceTree.SOURCE_TREE;
JTree tree = (JTree) c;
TreePath[] paths = tree.getSelectionPaths();
int pathLength = paths == null ? 0 : paths.length;
@@ -356,14 +353,59 @@ public class DraggableTreePanel extends JScrollPane {
}
private class TargetTreeTransferHandler extends TransferHandler {
+ private DbImportTreeNode sourceParentNode;
+
+ @Override
+ protected Transferable createTransferable(JComponent c) {
+ JTree tree = (JTree) c;
+ importSourceTree = ImportSourceTree.TARGET_TREE;
+ TreePath[] paths = tree.getSelectionPaths();
+ DbImportTreeNode lastSelectedNode = (DbImportTreeNode)
tree.getLastSelectedPathComponent();
+ sourceParentNode = lastSelectedNode.getParent();
+ if (paths != null && paths.length > 0) {
+ DbImportTreeNode[] nodes = new DbImportTreeNode[paths.length];
+ for (int i = 0; i < paths.length; i++) {
+ nodes[i] = (DbImportTreeNode)
paths[i].getLastPathComponent();
+ }
+ return new Transferable() {
+ @Override
+ public DataFlavor[] getTransferDataFlavors() {
+ return TransferableNode.flavors;
+ }
+
+ @Override
+ public boolean isDataFlavorSupported(DataFlavor flavor) {
+ return true;
+ }
+
+ @Override
+ public Object getTransferData(DataFlavor flavor) {
+ return nodes;
+ }
+ };
+ }
+ return null;
+ }
@Override
public int getSourceActions(JComponent c) {
- return COPY_OR_MOVE;
+ return TransferHandler.MOVE;
}
@Override
public boolean canImport(TransferSupport support) {
+ JTree.DropLocation dropLocation = (JTree.DropLocation)
support.getDropLocation();
+ DbImportTreeNode dropLocationParentNode = (DbImportTreeNode)
dropLocation.getPath().getLastPathComponent();
+
+ List<Class<?>> allowedItemsList =
insertableLevels.get(dropLocationParentNode.getUserObject().getClass());
+ DbImportTreeNode[] nodes = getNodesFromSupport(support);
+ if (nodes != null && allowedItemsList != null) {
+ for (DbImportTreeNode node : nodes) {
+ if
(!allowedItemsList.contains(node.getUserObject().getClass())) {
+ return false;
+ }
+ }
+ }
return support.isDrop();
}
@@ -372,19 +414,21 @@ public class DraggableTreePanel extends JScrollPane {
if (!canImport(support)) {
return false;
}
- if (!canBeMoved()) {
- return false;
+ if (importSourceTree == ImportSourceTree.TARGET_TREE) {
+ return importDataFromTargetTree(support);
}
- Transferable transferable = support.getTransferable();
- DbImportTreeNode[] transferData = null;
- try {
- for (DataFlavor dataFlavor :
transferable.getTransferDataFlavors()) {
- transferData = (DbImportTreeNode[])
transferable.getTransferData(dataFlavor);
- }
- } catch (IOException | UnsupportedFlavorException e) {
+ if (importSourceTree == ImportSourceTree.SOURCE_TREE) {
+ return importDataFromSourceTree(support);
+ }
+ return false;
+ }
+
+ private boolean importDataFromSourceTree(TransferSupport support) {
+ if (!canBeMoved()) {
return false;
}
- if (transferData != null) {
+ DbImportTreeNode[] nodes = getNodesFromSupport(support);
+ if (nodes != null) {
MoveImportNodeAction action =
projectController.getApplication().getActionManager()
.getAction(MoveImportNodeAction.class);
action.setSourceTree(sourceTree);
@@ -395,6 +439,38 @@ public class DraggableTreePanel extends JScrollPane {
}
return false;
}
+
+ private boolean importDataFromTargetTree(TransferSupport support) {
+ JTree.DropLocation dropLocation = (JTree.DropLocation)
support.getDropLocation();
+ DbImportTreeNode dropLocationParentNode = (DbImportTreeNode)
dropLocation.getPath().getLastPathComponent();
+
+ DbImportTreeNode[] nodes = getNodesFromSupport(support);
+ if (nodes != null) {
+ DragAndDropNodeAction action =
projectController.getApplication().getActionManager()
+ .getAction(DragAndDropNodeAction.class);
+ action.setDropLocationParentNode(dropLocationParentNode);
+ action.setSourceParentNode(sourceParentNode);
+ action.setDropLocation(dropLocation);
+ action.setNodes(nodes);
+ action.setTree(targetTree);
+ action.performAction(null);
+ return true;
+ }
+ return false;
+ }
+
+ private DbImportTreeNode[] getNodesFromSupport(TransferSupport
support) {
+ Transferable transferable = support.getTransferable();
+ DbImportTreeNode[] nodes = null;
+ try {
+ for (DataFlavor dataFlavor :
transferable.getTransferDataFlavors()) {
+ nodes = (DbImportTreeNode[])
transferable.getTransferData(dataFlavor);
+ }
+ } catch (IOException | UnsupportedFlavorException e) {
+ return null;
+ }
+ return nodes;
+ }
}
private class SourceTreeSelectionListener implements TreeSelectionListener
{
@@ -418,4 +494,9 @@ public class DraggableTreePanel extends JScrollPane {
}
}
}
+
+ private enum ImportSourceTree {
+ TARGET_TREE,
+ SOURCE_TREE
+ }
}
diff --git
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/PrintColumnsBiFunction.java
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/PrintColumnsBiFunction.java
index be77314be..6781c8a8e 100644
---
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/PrintColumnsBiFunction.java
+++
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/PrintColumnsBiFunction.java
@@ -55,6 +55,6 @@ public class PrintColumnsBiFunction implements
BiFunction<FilterContainer, DbImp
dbImportTree.packColumns(tableFilter, container);
container.setLoaded(true);
- model.reload(container);
+ dbImportTree.reloadModelKeepingExpanded(container);
}
}
diff --git
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/PrintTablesBiFunction.java
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/PrintTablesBiFunction.java
index b547fb9a2..65f50b52d 100644
---
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/PrintTablesBiFunction.java
+++
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/PrintTablesBiFunction.java
@@ -39,7 +39,6 @@ public class PrintTablesBiFunction implements
BiFunction<FilterContainer, DbImpo
@Override
public Void apply(FilterContainer filterContainer, DbImportTreeNode root) {
- DbImportModel model = (DbImportModel) dbImportTree.getModel();
boolean isTransferable = dbImportTree.isTransferable();
if (root.getChildCount() != 0) {
root.removeAllChildren();
@@ -58,7 +57,7 @@ public class PrintTablesBiFunction implements
BiFunction<FilterContainer, DbImpo
root.add(node);
dbImportTree.packColumns(includeTable, node);
}
- model.reload(root);
+ dbImportTree.reloadModelKeepingExpanded(root);
return null;
}
diff --git
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/TreeToolbarPanel.java
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/TreeToolbarPanel.java
index 506cc2d05..00f8d406c 100644
---
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/TreeToolbarPanel.java
+++
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/TreeToolbarPanel.java
@@ -30,6 +30,7 @@ import
org.apache.cayenne.dbsync.reverse.dbimport.ReverseEngineering;
import org.apache.cayenne.dbsync.reverse.dbimport.Schema;
import org.apache.cayenne.modeler.ProjectController;
import org.apache.cayenne.modeler.action.GetDbConnectionAction;
+import org.apache.cayenne.modeler.action.SortNodesAction;
import org.apache.cayenne.modeler.action.dbimport.AddCatalogAction;
import org.apache.cayenne.modeler.action.dbimport.AddExcludeColumnAction;
import org.apache.cayenne.modeler.action.dbimport.AddExcludeProcedureAction;
@@ -68,6 +69,7 @@ class TreeToolbarPanel extends JToolBar {
private JButton editButton;
private JButton deleteButton;
private JButton configureButton;
+ private JButton sortButton;
private DbImportTree reverseEngineeringTree;
private Map<Class, List<JButton>> levels;
@@ -170,6 +172,7 @@ class TreeToolbarPanel extends JToolBar {
this.add(includeProcedureButton);
this.add(excludeProcedureButton);
this.add(editButton);
+ this.add(sortButton);
this.addSeparator();
this.add(deleteButton);
this.add(configureButton);
@@ -198,6 +201,23 @@ class TreeToolbarPanel extends JToolBar {
deleteButton.setEnabled(true);
}
+
+
+ private void createButtons(DraggableTreePanel panel) {
+ schemaButton = createButton(AddSchemaAction.class, 0);
+ catalogButton = createButton(AddCatalogAction.class, 0);
+ includeTableButton = createButton(AddIncludeTableAction.class, 1);
+ excludeTableButton = createButton(AddExcludeTableAction.class, 2,
ExcludeTable.class);
+ includeColumnButton = createButton(AddIncludeColumnAction.class, 2,
IncludeColumn.class);
+ excludeColumnButton = createButton(AddExcludeColumnAction.class, 2,
ExcludeColumn.class);
+ includeProcedureButton = createButton(AddIncludeProcedureAction.class,
2, IncludeProcedure.class);
+ excludeProcedureButton = createButton(AddExcludeProcedureAction.class,
3, ExcludeProcedure.class);
+ sortButton = createButton(SortNodesAction.class,0);
+ editButton = createButton(EditNodeAction.class, 0);
+ deleteButton = createDeleteButton(panel);
+ configureButton = createConfigureButton();
+ }
+
private <T extends TreeManipulationAction> JButton createButton(Class<T>
actionClass, int position) {
TreeManipulationAction action =
projectController.getApplication().getActionManager().getAction(actionClass);
action.setTree(reverseEngineeringTree);
@@ -211,21 +231,15 @@ class TreeToolbarPanel extends JToolBar {
return action.buildButton(position);
}
- private void createButtons(DraggableTreePanel panel) {
- schemaButton = createButton(AddSchemaAction.class, 0);
- catalogButton = createButton(AddCatalogAction.class, 0);
- includeTableButton = createButton(AddIncludeTableAction.class, 1);
- excludeTableButton = createButton(AddExcludeTableAction.class, 2,
ExcludeTable.class);
- includeColumnButton = createButton(AddIncludeColumnAction.class, 2,
IncludeColumn.class);
- excludeColumnButton = createButton(AddExcludeColumnAction.class, 2,
ExcludeColumn.class);
- includeProcedureButton = createButton(AddIncludeProcedureAction.class,
2, IncludeProcedure.class);
- excludeProcedureButton = createButton(AddExcludeProcedureAction.class,
3, ExcludeProcedure.class);
- editButton = createButton(EditNodeAction.class, 0);
+ private JButton createConfigureButton() {
+ GetDbConnectionAction action =
projectController.getApplication().getActionManager().getAction(GetDbConnectionAction.class);
+ return action.buildButton(0);
+ }
+
+ private JButton createDeleteButton(DraggableTreePanel panel) {
DeleteNodeAction deleteNodeAction =
projectController.getApplication().getActionManager().getAction(DeleteNodeAction.class);
deleteNodeAction.setTree(reverseEngineeringTree);
deleteNodeAction.setPanel(panel);
- deleteButton = deleteNodeAction.buildButton(0);
- GetDbConnectionAction action =
projectController.getApplication().getActionManager().getAction(GetDbConnectionAction.class);
- configureButton = action.buildButton(0);
+ return deleteNodeAction.buildButton(0);
}
}
diff --git
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/DbImportTreeUndoableEdit.java
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/DbImportTreeUndoableEdit.java
index 6fe77b051..2d775e4ae 100644
---
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/DbImportTreeUndoableEdit.java
+++
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/DbImportTreeUndoableEdit.java
@@ -27,7 +27,7 @@ import
org.apache.cayenne.modeler.editor.dbimport.DbImportTree;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
-import java.util.ArrayList;
+import java.util.List;
/**
* @since 4.1
@@ -56,7 +56,7 @@ public class DbImportTreeUndoableEdit extends
AbstractUndoableEdit {
public void redo() throws CannotRedoException {
tree.stopEditing();
tree.setReverseEngineering(this.nextReverseEngineering);
- ArrayList<DbImportTreeNode> list = tree.getTreeExpandList();
+ List<DbImportTreeNode> list = tree.getTreeExpandList();
projectController.getApplication().getMetaData().add(projectController.getCurrentDataMap(),
tree.getReverseEngineering());
projectController.setDirty(true);
tree.translateReverseEngineeringToTree(tree.getReverseEngineering(),
false);
@@ -67,7 +67,7 @@ public class DbImportTreeUndoableEdit extends
AbstractUndoableEdit {
public void undo() throws CannotUndoException {
tree.stopEditing();
tree.setReverseEngineering(this.previousReverseEngineering);
- ArrayList<DbImportTreeNode> list = tree.getTreeExpandList();
+ List<DbImportTreeNode> list = tree.getTreeExpandList();
projectController.getApplication().getMetaData().add(projectController.getCurrentDataMap(),
tree.getReverseEngineering());
projectController.setDirty(true);
tree.translateReverseEngineeringToTree(tree.getReverseEngineering(),
false);
diff --git
a/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-sort.png
b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-sort.png
new file mode 100644
index 000000000..f7dca9afe
Binary files /dev/null and
b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/images/icon-dbi-sort.png
differ
diff --git
a/modeler/cayenne-modeler/src/test/java/org/apache/cayenne/modeler/editor/dbimport/DbImportSorterTest.java
b/modeler/cayenne-modeler/src/test/java/org/apache/cayenne/modeler/editor/dbimport/DbImportSorterTest.java
index 50c57bf2a..a64ab86fa 100644
---
a/modeler/cayenne-modeler/src/test/java/org/apache/cayenne/modeler/editor/dbimport/DbImportSorterTest.java
+++
b/modeler/cayenne-modeler/src/test/java/org/apache/cayenne/modeler/editor/dbimport/DbImportSorterTest.java
@@ -47,22 +47,44 @@ public class DbImportSorterTest {
}
@Test
- public void sortNodeTest(){
- DbImportSorter.sortSingleNode(node);
+ public void sortByTypeByNameSingleNodeTest(){
+
DbImportSorter.sortSingleNode(node,DbImportSorter.NODE_COMPARATOR_BY_TYPE_BY_NAME);
- assertEquals("a", node.getChildNodes().get(0).getSimpleNodeName());
- assertEquals("b", node.getChildNodes().get(1).getSimpleNodeName());
- assertEquals("c", node.getChildNodes().get(2).getSimpleNodeName());
+ // DbImportTreeNode.ExpandableEnforcerNode at index 0
+ assertEquals("a", node.getChildNodes().get(1).getSimpleNodeName());
+ assertEquals("b", node.getChildNodes().get(2).getSimpleNodeName());
+ assertEquals("c", node.getChildNodes().get(3).getSimpleNodeName());
+ }
+
+ @Test
+ public void sortByTypeSingleNodeTest(){
+
DbImportSorter.sortSingleNode(node,DbImportSorter.NODE_COMPARATOR_BY_TYPE);
+
+ // DbImportTreeNode.ExpandableEnforcerNode at index 0
+ assertEquals("a", node.getChildNodes().get(3).getSimpleNodeName());
+ assertEquals("b", node.getChildNodes().get(2).getSimpleNodeName());
+ assertEquals("c", node.getChildNodes().get(1).getSimpleNodeName());
}
@Test
- public void sortNodeWithAllChildrenTest(){
- DbImportSorter.sortSubtree(node);
+ public void sortByTypeByNameSubtreeTest(){
+
DbImportSorter.sortSubtree(node,DbImportSorter.NODE_COMPARATOR_BY_TYPE_BY_NAME);
- DbImportTreeNode tableNode = node.getChildNodes().get(0);
- DbImportTreeNode columnNode = tableNode.getChildNodes().get(0);
+ // DbImportTreeNode.ExpandableEnforcerNode at index 0
+ DbImportTreeNode tableNode = node.getChildNodes().get(1);
+ DbImportTreeNode columnNode = tableNode.getChildNodes().get(1);
assertEquals("1", columnNode.getSimpleNodeName());
}
+ @Test
+ public void sortByTypeBySubtreeTest(){
+
DbImportSorter.sortSubtree(node,DbImportSorter.NODE_COMPARATOR_BY_TYPE);
+
+ // DbImportTreeNode.ExpandableEnforcerNode at index 0
+ DbImportTreeNode tableNode = node.getChildNodes().get(3);
+ DbImportTreeNode columnNode = tableNode.getChildNodes().get(1);
+ assertEquals("2", columnNode.getSimpleNodeName());
+ }
+
}