From 98488b3029a33de9f8ca1e09821db30443d99b9c Mon Sep 17 00:00:00 2001 From: olga Date: Thu, 21 Jan 2016 12:27:17 +0300 Subject: [PATCH 1/4] CAY-2051 | Applying new Reverse Engineering to the Modeler --- .../cayenne/project/ConfigurationSaver.java | 8 + .../project/ConfigurationSourceGetter.java | 6 + .../project/ConfigurationSourceSetter.java | 7 + .../DefaultConfigurationNodeParentGetter.java | 6 + .../cayenne/project/FileProjectSaver.java | 541 +++++++------- .../cayenne/project/SaveableNodesGetter.java | 9 + .../validation/DefaultProjectValidator.java | 8 + .../ReverseEngineeringValidator.java | 42 ++ .../project/ReverseEngineeringSaverTest.java | 62 ++ cayenne-server/pom.xml | 8 +- .../org/apache/cayenne/access/DbLoader.java | 2 +- .../loader/DbAttributesPerSchemaLoader.java | 5 +- .../access/loader/filters/PatternFilter.java | 37 +- .../access/loader/filters/SchemaFilter.java | 5 - .../access/loader/filters/TableFilter.java | 11 +- .../BaseConfigurationNodeVisitor.java | 4 + .../ConfigurationNodeVisitor.java | 3 + .../DefaultConfigurationNameMapper.java | 18 + .../XMLDataChannelDescriptorLoader.java | 685 +++++++++--------- .../cayenne/dbimport}/AntNestedElement.java | 2 +- .../org/apache/cayenne/dbimport}/Catalog.java | 6 +- .../DefaultReverseEngineeringLoader.java | 32 +- .../DefaultReverseEngineeringWriter.java | 58 ++ .../cayenne/dbimport}/ExcludeColumn.java | 2 +- .../cayenne/dbimport}/ExcludeProcedure.java | 2 +- .../cayenne/dbimport}/ExcludeTable.java | 4 +- .../cayenne/dbimport}/FilterContainer.java | 21 +- .../dbimport}/FiltersConfigBuilder.java | 116 +-- .../cayenne/dbimport}/IncludeColumn.java | 2 +- .../cayenne/dbimport}/IncludeProcedure.java | 2 +- .../cayenne/dbimport}/IncludeTable.java | 10 +- .../cayenne/dbimport}/PatternParam.java | 8 +- .../cayenne/dbimport}/ReverseEngineering.java | 101 ++- .../dbimport/ReverseEngineeringLoader.java | 36 + .../ReverseEngineeringLoaderException.java | 37 + .../dbimport/ReverseEngineeringWriter.java | 10 +- .../org/apache/cayenne/dbimport}/Schema.java | 8 +- .../java/org/apache/cayenne/map/DataMap.java | 18 +- .../java/org/apache/cayenne/map/DbEntity.java | 8 +- .../org/apache/cayenne/map/MapLoader.java | 27 +- .../cayenne/map/naming/NameCheckers.java | 36 +- .../org/apache/cayenne/resource/Resource.java | 1 + .../DefaultReverseEngineeringLoaderTest.java | 19 +- .../DefaultReverseEngineeringWriterTest.java | 104 +++ .../dbimport}/FiltersConfigBuilderTest.java | 3 +- .../unit/di/server/ServerCaseModule.java | 9 +- .../reverseEngineering-ant-mapping.xml | 0 .../reverseEngineering-catalog-and-schema.xml | 0 .../dbimport}/reverseEngineering-catalog.xml | 0 .../dbimport/reverseEngineering-expected.xml | 22 + .../dbimport}/reverseEngineering-flat.xml | 0 .../reverseEngineering-maven-mapping.xml | 0 .../reverseEngineering-mixed-mapping.xml | 0 .../dbimport}/reverseEngineering-schema.xml | 0 ...verseEngineering-skipPrimaryKeyLoading.xml | 0 ...seEngineering-skipRelationshipsLoading.xml | 0 .../reverseEngineering-tableTypes.xml | 0 .../cayenne/dbimport/reverseEngineering.xml | 3 + cayenne-tools/pom.xml | 1 - .../apache/cayenne/tools/DbImporterTask.java | 21 +- .../tools/dbimport/DbImportAction.java | 208 +----- .../tools/dbimport/DbImportActionDefault.java | 281 +++++++ .../tools/dbimport/DbImportModule.java | 4 +- .../cayenne/tools/dbimport/config/Type.java | 15 + .../tools/dbimport/config/TypeMapper.java | 6 + .../tools/AntDataPortDelegateTest.java | 4 +- ...eneratorTaskCrossMapRelationshipsTest.java | 234 +++--- .../tools/CayenneGeneratorTaskTest.java | 554 +++++++------- .../cayenne/tools/DbGeneratorTaskTest.java | 2 +- .../cayenne/tools/DbImporterTaskTest.java | 357 +++++---- .../cayenne/tools/NamePatternMatcherTest.java | 78 +- .../tools/configuration/ToolsModuleTest.java | 2 +- .../tools/dbimport/DbImportActionTest.java | 574 +++++++-------- .../DbImportDbLoaderDelegateTest.java | 2 +- .../tools/dbimport/DbImportModuleTest.java | 2 +- .../cayenne/modeler/CayenneModelerFrame.java | 4 +- .../cayenne/modeler/ProjectController.java | 386 +++++----- .../modeler/action/DefaultActionManager.java | 4 +- .../cayenne/modeler/action/MigrateAction.java | 14 +- .../modeler/action/OpenProjectAction.java | 3 +- .../cayenne/modeler/action/RemoveAction.java | 8 +- ...ion.java => ReverseEngineeringAction.java} | 71 +- .../modeler/dialog/db/ConnectionWizard.java | 89 --- .../modeler/dialog/db/DBGeneratorOptions.java | 2 +- .../modeler/dialog/db/DataMapViewModel.java | 51 ++ .../dialog/db/DataSourceController.java | 219 ++++++ ...rceWizardView.java => DataSourceView.java} | 8 +- .../modeler/dialog/db/DataSourceWizard.java | 224 ------ .../dialog/db/DbImportActionModeler.java | 120 +++ .../modeler/dialog/db/DbLoaderHelper.java | 180 ++--- .../dialog/db/DbLoaderOptionsDialog.java | 308 -------- .../modeler/dialog/db/MergerOptions.java | 4 - .../db/ReverseEngineeringController.java | 362 +++++++++ .../db/ReverseEngineeringScrollPane.java | 34 + .../dialog/db/ReverseEngineeringView.java | 274 +++++++ .../modeler/dialog/db/model/DBCatalog.java | 37 + .../modeler/dialog/db/model/DBColumn.java | 39 + .../modeler/dialog/db/model/DBElement.java | 50 ++ .../modeler/dialog/db/model/DBEntity.java | 37 + .../modeler/dialog/db/model/DBModel.java | 38 + .../modeler/dialog/db/model/DBProcedure.java | 38 + .../modeler/dialog/db/model/DBSchema.java | 48 ++ .../dialog/pref/FilteredTreeCellRenderer.java | 85 +++ .../modeler/dialog/pref/TreeEditor.java | 101 +++ .../cayenne/modeler/dialog/pref/TreeView.java | 56 ++ .../modeler/dialog/pref/XMLFileEditor.java | 82 +++ .../cayenne/modeler/dialog/pref/XMLView.java | 72 ++ .../modeler/editor/DataMapTabbedView.java | 25 +- .../modeler/undo/RemoveUndoableEdit.java | 4 +- .../cayenne/modeler/util/CellRenderers.java | 17 +- .../apache/cayenne/pref/PreferenceEditor.java | 4 +- .../cayenne/modeler/dialog/db/templateXML.xml | 16 + .../apache/cayenne/tools/DbImporterMojo.java | 9 +- .../DbImporterMojoConfigurationTest.java | 7 +- .../cayenne/tools/DbImporterMojoTest.java | 6 +- 115 files changed, 4739 insertions(+), 2916 deletions(-) create mode 100644 cayenne-project/src/main/java/org/apache/cayenne/project/validation/ReverseEngineeringValidator.java create mode 100644 cayenne-project/src/test/java/org/apache/cayenne/project/ReverseEngineeringSaverTest.java rename {cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/main/java/org/apache/cayenne/dbimport}/AntNestedElement.java (96%) rename {cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/main/java/org/apache/cayenne/dbimport}/Catalog.java (94%) rename {cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/main/java/org/apache/cayenne/dbimport}/DefaultReverseEngineeringLoader.java (92%) create mode 100644 cayenne-server/src/main/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringWriter.java rename {cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/main/java/org/apache/cayenne/dbimport}/ExcludeColumn.java (95%) rename {cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/main/java/org/apache/cayenne/dbimport}/ExcludeProcedure.java (95%) rename {cayenne-tools/src/main/java/org/apache/cayenne/tools => cayenne-server/src/main/java/org/apache/cayenne/dbimport}/ExcludeTable.java (92%) rename {cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/main/java/org/apache/cayenne/dbimport}/FilterContainer.java (91%) rename {cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/main/java/org/apache/cayenne/dbimport}/FiltersConfigBuilder.java (79%) rename {cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/main/java/org/apache/cayenne/dbimport}/IncludeColumn.java (95%) rename {cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/main/java/org/apache/cayenne/dbimport}/IncludeProcedure.java (95%) rename {cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/main/java/org/apache/cayenne/dbimport}/IncludeTable.java (90%) rename {cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/main/java/org/apache/cayenne/dbimport}/PatternParam.java (88%) rename {cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/main/java/org/apache/cayenne/dbimport}/ReverseEngineering.java (54%) create mode 100644 cayenne-server/src/main/java/org/apache/cayenne/dbimport/ReverseEngineeringLoader.java create mode 100644 cayenne-server/src/main/java/org/apache/cayenne/dbimport/ReverseEngineeringLoaderException.java rename cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ReverseEngineeringLoader.java => cayenne-server/src/main/java/org/apache/cayenne/dbimport/ReverseEngineeringWriter.java (82%) rename {cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/main/java/org/apache/cayenne/dbimport}/Schema.java (87%) rename {cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/test/java/org/apache/cayenne/dbimport}/DefaultReverseEngineeringLoaderTest.java (95%) create mode 100644 cayenne-server/src/test/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringWriterTest.java rename {cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/test/java/org/apache/cayenne/dbimport}/FiltersConfigBuilderTest.java (99%) rename {cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/test/resources/org/apache/cayenne/dbimport}/reverseEngineering-ant-mapping.xml (100%) rename {cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/test/resources/org/apache/cayenne/dbimport}/reverseEngineering-catalog-and-schema.xml (100%) rename {cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/test/resources/org/apache/cayenne/dbimport}/reverseEngineering-catalog.xml (100%) create mode 100644 cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-expected.xml rename {cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/test/resources/org/apache/cayenne/dbimport}/reverseEngineering-flat.xml (100%) rename {cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/test/resources/org/apache/cayenne/dbimport}/reverseEngineering-maven-mapping.xml (100%) rename {cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/test/resources/org/apache/cayenne/dbimport}/reverseEngineering-mixed-mapping.xml (100%) rename {cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/test/resources/org/apache/cayenne/dbimport}/reverseEngineering-schema.xml (100%) rename {cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/test/resources/org/apache/cayenne/dbimport}/reverseEngineering-skipPrimaryKeyLoading.xml (100%) rename {cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/test/resources/org/apache/cayenne/dbimport}/reverseEngineering-skipRelationshipsLoading.xml (100%) rename {cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config => cayenne-server/src/test/resources/org/apache/cayenne/dbimport}/reverseEngineering-tableTypes.xml (100%) create mode 100644 cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering.xml create mode 100644 cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportActionDefault.java rename modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/{ImportDBAction.java => ReverseEngineeringAction.java} (51%) delete mode 100644 modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ConnectionWizard.java create mode 100644 modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataMapViewModel.java create mode 100644 modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceController.java rename modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/{DataSourceWizardView.java => DataSourceView.java} (96%) delete mode 100644 modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceWizard.java create mode 100644 modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbImportActionModeler.java delete mode 100644 modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbLoaderOptionsDialog.java create mode 100644 modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ReverseEngineeringController.java create mode 100644 modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ReverseEngineeringScrollPane.java create mode 100644 modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ReverseEngineeringView.java create mode 100644 modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBCatalog.java create mode 100644 modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBColumn.java create mode 100644 modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBElement.java create mode 100644 modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBEntity.java create mode 100644 modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBModel.java create mode 100644 modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBProcedure.java create mode 100644 modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBSchema.java create mode 100644 modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/FilteredTreeCellRenderer.java create mode 100644 modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/TreeEditor.java create mode 100644 modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/TreeView.java create mode 100644 modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/XMLFileEditor.java create mode 100644 modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/XMLView.java create mode 100644 modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/dialog/db/templateXML.xml diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSaver.java b/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSaver.java index 9ed8a8886d..d6b9c97b49 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSaver.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSaver.java @@ -22,6 +22,7 @@ import org.apache.cayenne.configuration.BaseConfigurationNodeVisitor; import org.apache.cayenne.configuration.DataChannelDescriptor; +import org.apache.cayenne.dbimport.ReverseEngineering; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.util.XMLEncoder; @@ -54,6 +55,13 @@ public Void visitDataMap(DataMap node) { return null; } + @Override + public Void visitReverseEngineering(ReverseEngineering node) { + XMLEncoder encoder = new XMLEncoder(printWriter); + node.encodeAsXML(encoder); + return null; + } + private void printXMLHeader(XMLEncoder encoder) { encoder.println(""); } diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSourceGetter.java b/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSourceGetter.java index db9c3c3caf..be68dadebd 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSourceGetter.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSourceGetter.java @@ -20,6 +20,7 @@ import org.apache.cayenne.configuration.BaseConfigurationNodeVisitor; import org.apache.cayenne.configuration.DataChannelDescriptor; +import org.apache.cayenne.dbimport.ReverseEngineering; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.resource.Resource; @@ -39,4 +40,9 @@ public Resource visitDataChannelDescriptor(DataChannelDescriptor descriptor) { public Resource visitDataMap(DataMap dataMap) { return dataMap.getConfigurationSource(); } + + @Override + public Resource visitReverseEngineering(ReverseEngineering reverseEngineering) { + return reverseEngineering.getConfigurationSource(); + } } diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSourceSetter.java b/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSourceSetter.java index 2854df1990..7a3f5d3480 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSourceSetter.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/ConfigurationSourceSetter.java @@ -21,6 +21,7 @@ import org.apache.cayenne.configuration.BaseConfigurationNodeVisitor; import org.apache.cayenne.configuration.DataChannelDescriptor; import org.apache.cayenne.configuration.DataNodeDescriptor; +import org.apache.cayenne.dbimport.ReverseEngineering; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.resource.Resource; @@ -54,4 +55,10 @@ public Void visitDataMap(DataMap node) { node.setConfigurationSource(configurationSource); return null; } + + @Override + public Void visitReverseEngineering(ReverseEngineering node) { + node.setConfigurationSource(configurationSource); + return null; + } } diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/DefaultConfigurationNodeParentGetter.java b/cayenne-project/src/main/java/org/apache/cayenne/project/DefaultConfigurationNodeParentGetter.java index 9af9b387cf..6d48fb5e76 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/DefaultConfigurationNodeParentGetter.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/DefaultConfigurationNodeParentGetter.java @@ -22,6 +22,7 @@ import org.apache.cayenne.configuration.ConfigurationNode; import org.apache.cayenne.configuration.ConfigurationNodeVisitor; import org.apache.cayenne.configuration.DataNodeDescriptor; +import org.apache.cayenne.dbimport.ReverseEngineering; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.map.DbAttribute; import org.apache.cayenne.map.DbEntity; @@ -113,5 +114,10 @@ public ConfigurationNode visitProcedureParameter(ProcedureParameter parameter) { public ConfigurationNode visitQuery(Query query) { return query.getDataMap(); } + + @Override + public ConfigurationNode visitReverseEngineering(ReverseEngineering reverseEngineering) { + return reverseEngineering; + } } } diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/FileProjectSaver.java b/cayenne-project/src/main/java/org/apache/cayenne/project/FileProjectSaver.java index 98249d431c..3ac24d2d04 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/FileProjectSaver.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/FileProjectSaver.java @@ -41,283 +41,282 @@ /** * A ProjectSaver saving project configuration to the file system. - * + * * @since 3.1 */ public class FileProjectSaver implements ProjectSaver { - @Inject - protected ConfigurationNameMapper nameMapper; - - protected ConfigurationNodeVisitor resourceGetter; - protected ConfigurationNodeVisitor> saveableNodesGetter; - protected String fileEncoding; - - public FileProjectSaver() { - resourceGetter = new ConfigurationSourceGetter(); - saveableNodesGetter = new SaveableNodesGetter(); - - // this is not configurable yet... probably doesn't have to be - fileEncoding = "UTF-8"; - } - - public String getSupportedVersion() { - return "7"; - } - - public void save(Project project) { - save(project, project.getConfigurationResource(), true); - } - - public void saveAs(Project project, Resource baseDirectory) { - if (baseDirectory == null) { - throw new NullPointerException("Null 'baseDirectory'"); - } - save(project, baseDirectory, false); - } - - void save(Project project, Resource baseResource, boolean deleteOldResources) { - Collection nodes = project.getRootNode().acceptVisitor(saveableNodesGetter); - Collection units = new ArrayList(nodes.size()); + @Inject + protected ConfigurationNameMapper nameMapper; + + protected ConfigurationNodeVisitor resourceGetter; + protected ConfigurationNodeVisitor> saveableNodesGetter; + protected String fileEncoding; + + public FileProjectSaver() { + resourceGetter = new ConfigurationSourceGetter(); + saveableNodesGetter = new SaveableNodesGetter(); + + // this is not configurable yet... probably doesn't have to be + fileEncoding = "UTF-8"; + } + + public String getSupportedVersion() { + return "7"; + } + + public void save(Project project) { + save(project, project.getConfigurationResource(), true); + } - for (ConfigurationNode node : nodes) { - units.add(createSaveUnit(node, baseResource)); - } + public void saveAs(Project project, Resource baseDirectory) { + if (baseDirectory == null) { + throw new NullPointerException("Null 'baseDirectory'"); + } + save(project, baseDirectory, false); + } - checkAccess(units); + void save(Project project, Resource baseResource, boolean deleteOldResources) { + Collection nodes = project.getRootNode().acceptVisitor(saveableNodesGetter); + Collection units = new ArrayList(nodes.size()); - try { - saveToTempFiles(units); - saveCommit(units); - } finally { - clearTempFiles(units); - } - - try { - if (deleteOldResources) { - clearRenamedFiles(units); - - Collection unusedResources = project.getUnusedResources(); - for (SaveUnit unit : units) { - unusedResources.remove(unit.sourceConfiguration.getURL()); - } - deleteUnusedFiles(unusedResources); - } - } catch (IOException ex) { - throw new CayenneRuntimeException(ex); - } + for (ConfigurationNode node : nodes) { + units.add(createSaveUnit(node, baseResource)); + } - // I guess we should reset projects state regardless of the value of - // 'deleteOldResources' - project.getUnusedResources().clear(); - } - - SaveUnit createSaveUnit(ConfigurationNode node, Resource baseResource) { - - SaveUnit unit = new SaveUnit(); - unit.node = node; - unit.sourceConfiguration = node.acceptVisitor(resourceGetter); - - String targetLocation = nameMapper.configurationLocation(node); - Resource targetResource = baseResource.getRelativeResource(targetLocation); - - if (unit.sourceConfiguration == null) { - unit.sourceConfiguration = targetResource; - } - - // attempt to convert targetResource to a File... if that fails, - // FileProjectSaver is not appropriate for handling a given project.. - - URL targetUrl = targetResource.getURL(); - - try { - unit.targetFile = Util.toFile(targetUrl); - } catch (IllegalArgumentException e) { - throw new CayenneRuntimeException("Can't save configuration to the following location: '%s'. " - + "Is this a valid file location?. (%s)", e, targetUrl, e.getMessage()); - } - - return unit; - } - - void checkAccess(Collection units) { - for (SaveUnit unit : units) { - - File targetFile = unit.targetFile; - - File parent = targetFile.getParentFile(); - if (!parent.exists()) { - if (!parent.mkdirs()) { - throw new CayenneRuntimeException("Error creating directory tree for '%s'", - parent.getAbsolutePath()); - } - } - - if (targetFile.isDirectory()) { - throw new CayenneRuntimeException("Target file '%s' is a directory", targetFile.getAbsolutePath()); - } - - if (targetFile.exists() && !targetFile.canWrite()) { - throw new CayenneRuntimeException("Can't write to file '%s'", targetFile.getAbsolutePath()); - } - - } - } - - void saveToTempFiles(Collection units) { - - for (SaveUnit unit : units) { - - String name = unit.targetFile.getName(); - if (name == null || name.length() < 3) { - name = "cayenne-project"; - } - - File parent = unit.targetFile.getParentFile(); - - try { - unit.targetTempFile = File.createTempFile(name, null, parent); - } catch (IOException e) { - throw new CayenneRuntimeException("Error creating temp file (%s)", e, e.getMessage()); - } - - if (unit.targetTempFile.exists()) { - unit.targetTempFile.delete(); - } - - try (PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream( - unit.targetTempFile), fileEncoding));) { - saveToTempFile(unit, printWriter); - } catch (UnsupportedEncodingException e) { - throw new CayenneRuntimeException("Unsupported encoding '%s' (%s)", e, fileEncoding, e.getMessage()); - } catch (FileNotFoundException e) { - throw new CayenneRuntimeException("File not found '%s' (%s)", e, unit.targetTempFile.getAbsolutePath(), - e.getMessage()); - } - } - } - - void saveToTempFile(SaveUnit unit, PrintWriter printWriter) { - unit.node.acceptVisitor(new ConfigurationSaver(printWriter, getSupportedVersion())); - } - - void saveCommit(Collection units) { - - for (SaveUnit unit : units) { - - File targetFile = unit.targetFile; - - if (targetFile.exists()) { - if (!targetFile.delete()) { - throw new CayenneRuntimeException("Unable to remove old master file '%s'", - targetFile.getAbsolutePath()); - } - } - - File tempFile = unit.targetTempFile; - if (!tempFile.renameTo(targetFile)) { - throw new CayenneRuntimeException("Unable to move '%s' to '%s'", tempFile.getAbsolutePath(), - targetFile.getAbsolutePath()); - } - - unit.targetTempFile = null; - try { - unit.node.acceptVisitor(new ConfigurationSourceSetter(new URLResource(targetFile.toURL()))); - } catch (MalformedURLException e) { - throw new CayenneRuntimeException("Malformed URL for file '%s'", e, targetFile.getAbsolutePath()); - } - } - } - - private void clearTempFiles(Collection units) { - for (SaveUnit unit : units) { - - if (unit.targetTempFile != null && unit.targetTempFile.exists()) { - unit.targetTempFile.delete(); - unit.targetTempFile = null; - } - } - } - - private void clearRenamedFiles(Collection units) throws IOException { - for (SaveUnit unit : units) { - - if (unit.sourceConfiguration == null) { - continue; - } - - URL sourceUrl = unit.sourceConfiguration.getURL(); - File sourceFile; - try { - sourceFile = Util.toFile(sourceUrl); - } catch (IllegalArgumentException e) { - // ignore non-file configurations... - continue; - } - - if (!sourceFile.exists()) { - continue; - } - - // compare against ALL unit target files, not just the current - // unit... if the - // target matches, skip this file - boolean isTarget = false; - for (SaveUnit xunit : units) { - if (isFilesEquals(sourceFile, xunit.targetFile)) { - isTarget = true; - break; - } - } - - if (!isTarget) { - if (!sourceFile.delete()) { - throw new CayenneRuntimeException("Could not delete file '%s'", sourceFile.getCanonicalPath()); - } - } - } - } - - private boolean isFilesEquals(File firstFile, File secondFile) throws IOException { - boolean isFirstFileExists = firstFile.exists(); - boolean isSecondFileExists = secondFile.exists(); - - String firstFilePath = firstFile.getCanonicalPath(); - String secondFilePath = secondFile.getCanonicalPath(); - - return isFirstFileExists && isSecondFileExists && firstFilePath.equals(secondFilePath); - } - - private void deleteUnusedFiles(Collection unusedResources) throws IOException { - for (URL unusedResource : unusedResources) { - - File unusedFile; - try { - unusedFile = Util.toFile(unusedResource); - } catch (IllegalArgumentException e) { - // ignore non-file configurations... - continue; - } - - if (!unusedFile.exists()) { - continue; - } - - if (!unusedFile.delete()) { - throw new CayenneRuntimeException("Could not delete file '%s'", unusedFile.getCanonicalPath()); - } - - } - } - - class SaveUnit { - - private ConfigurationNode node; - - // source can be an abstract resource, but target is always a file... - private Resource sourceConfiguration; - private File targetFile; - private File targetTempFile; - - } + checkAccess(units); + + try { + saveToTempFiles(units); + saveCommit(units); + } finally { + clearTempFiles(units); + } + + try { + if (deleteOldResources) { + clearRenamedFiles(units); + + Collection unusedResources = project.getUnusedResources(); + for (SaveUnit unit : units) { + unusedResources.remove(unit.sourceConfiguration.getURL()); + } + deleteUnusedFiles(unusedResources); + } + } catch (IOException ex) { + throw new CayenneRuntimeException(ex); + } + + // I guess we should reset projects state regardless of the value of + // 'deleteOldResources' + project.getUnusedResources().clear(); + } + + SaveUnit createSaveUnit(ConfigurationNode node, Resource baseResource) { + + SaveUnit unit = new SaveUnit(); + unit.node = node; + unit.sourceConfiguration = node.acceptVisitor(resourceGetter); + + String targetLocation = nameMapper.configurationLocation(node); + Resource targetResource = baseResource.getRelativeResource(targetLocation); + + if (unit.sourceConfiguration == null) { + unit.sourceConfiguration = targetResource; + } + + // attempt to convert targetResource to a File... if that fails, + // FileProjectSaver is not appropriate for handling a given project.. + + URL targetUrl = targetResource.getURL(); + + try { + unit.targetFile = Util.toFile(targetUrl); + } catch (IllegalArgumentException e) { + throw new CayenneRuntimeException("Can't save configuration to the following location: '%s'. " + + "Is this a valid file location?. (%s)", e, targetUrl, e.getMessage()); + } + + return unit; + } + + void checkAccess(Collection units) { + for (SaveUnit unit : units) { + + File targetFile = unit.targetFile; + + File parent = targetFile.getParentFile(); + if (!parent.exists()) { + if (!parent.mkdirs()) { + throw new CayenneRuntimeException("Error creating directory tree for '%s'", + parent.getAbsolutePath()); + } + } + + if (targetFile.isDirectory()) { + throw new CayenneRuntimeException("Target file '%s' is a directory", targetFile.getAbsolutePath()); + } + + if (targetFile.exists() && !targetFile.canWrite()) { + throw new CayenneRuntimeException("Can't write to file '%s'", targetFile.getAbsolutePath()); + } + + } + } + + void saveToTempFiles(Collection units) { + + for (SaveUnit unit : units) { + + String name = unit.targetFile.getName(); + if (name == null || name.length() < 3) { + name = "cayenne-project"; + } + + File parent = unit.targetFile.getParentFile(); + + try { + unit.targetTempFile = File.createTempFile(name, null, parent); + } catch (IOException e) { + throw new CayenneRuntimeException("Error creating temp file (%s)", e, e.getMessage()); + } + + if (unit.targetTempFile.exists()) { + unit.targetTempFile.delete(); + } + try (PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream( + unit.targetTempFile), fileEncoding));) { + saveToTempFile(unit, printWriter); + } catch (UnsupportedEncodingException e) { + throw new CayenneRuntimeException("Unsupported encoding '%s' (%s)", e, fileEncoding, e.getMessage()); + } catch (FileNotFoundException e) { + throw new CayenneRuntimeException("File not found '%s' (%s)", e, unit.targetTempFile.getAbsolutePath(), + e.getMessage()); + } + } + } + + void saveToTempFile(SaveUnit unit, PrintWriter printWriter) { + unit.node.acceptVisitor(new ConfigurationSaver(printWriter, getSupportedVersion())); + } + + void saveCommit(Collection units) { + + for (SaveUnit unit : units) { + + File targetFile = unit.targetFile; + + if (targetFile.exists()) { + if (!targetFile.delete()) { + throw new CayenneRuntimeException("Unable to remove old master file '%s'", + targetFile.getAbsolutePath()); + } + } + + File tempFile = unit.targetTempFile; + if (!tempFile.renameTo(targetFile)) { + throw new CayenneRuntimeException("Unable to move '%s' to '%s'", tempFile.getAbsolutePath(), + targetFile.getAbsolutePath()); + } + + unit.targetTempFile = null; + try { + unit.node.acceptVisitor(new ConfigurationSourceSetter(new URLResource(targetFile.toURL()))); + } catch (MalformedURLException e) { + throw new CayenneRuntimeException("Malformed URL for file '%s'", e, targetFile.getAbsolutePath()); + } + } + } + + private void clearTempFiles(Collection units) { + for (SaveUnit unit : units) { + + if (unit.targetTempFile != null && unit.targetTempFile.exists()) { + unit.targetTempFile.delete(); + unit.targetTempFile = null; + } + } + } + + private void clearRenamedFiles(Collection units) throws IOException { + for (SaveUnit unit : units) { + + if (unit.sourceConfiguration == null) { + continue; + } + + URL sourceUrl = unit.sourceConfiguration.getURL(); + File sourceFile; + try { + sourceFile = Util.toFile(sourceUrl); + } catch (IllegalArgumentException e) { + // ignore non-file configurations... + continue; + } + + if (!sourceFile.exists()) { + continue; + } + + // compare against ALL unit target files, not just the current + // unit... if the + // target matches, skip this file + boolean isTarget = false; + for (SaveUnit xunit : units) { + if (isFilesEquals(sourceFile, xunit.targetFile)) { + isTarget = true; + break; + } + } + + if (!isTarget) { + if (!sourceFile.delete()) { + throw new CayenneRuntimeException("Could not delete file '%s'", sourceFile.getCanonicalPath()); + } + } + } + } + + private boolean isFilesEquals(File firstFile, File secondFile) throws IOException { + boolean isFirstFileExists = firstFile.exists(); + boolean isSecondFileExists = secondFile.exists(); + + String firstFilePath = firstFile.getCanonicalPath(); + String secondFilePath = secondFile.getCanonicalPath(); + + return isFirstFileExists && isSecondFileExists && firstFilePath.equals(secondFilePath); + } + + private void deleteUnusedFiles(Collection unusedResources) throws IOException { + for (URL unusedResource : unusedResources) { + + File unusedFile; + try { + unusedFile = Util.toFile(unusedResource); + } catch (IllegalArgumentException e) { + // ignore non-file configurations... + continue; + } + + if (!unusedFile.exists()) { + continue; + } + + if (!unusedFile.delete()) { + throw new CayenneRuntimeException("Could not delete file '%s'", unusedFile.getCanonicalPath()); + } + + } + } + + class SaveUnit { + + private ConfigurationNode node; + + // source can be an abstract resource, but target is always a file... + private Resource sourceConfiguration; + private File targetFile; + private File targetTempFile; + + } } diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/SaveableNodesGetter.java b/cayenne-project/src/main/java/org/apache/cayenne/project/SaveableNodesGetter.java index ee20da3e91..61c94682fa 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/SaveableNodesGetter.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/SaveableNodesGetter.java @@ -25,6 +25,7 @@ import org.apache.cayenne.configuration.BaseConfigurationNodeVisitor; import org.apache.cayenne.configuration.ConfigurationNode; import org.apache.cayenne.configuration.DataChannelDescriptor; +import org.apache.cayenne.dbimport.ReverseEngineering; import org.apache.cayenne.map.DataMap; /** @@ -42,6 +43,9 @@ public Collection visitDataChannelDescriptor( for (DataMap map : descriptor.getDataMaps()) { nodes.add(map); + if (map.getReverseEngineering() != null) { + nodes.add(map.getReverseEngineering()); + } } return nodes; @@ -51,4 +55,9 @@ public Collection visitDataChannelDescriptor( public Collection visitDataMap(DataMap dataMap) { return Collections. singletonList(dataMap); } + + @Override + public Collection visitReverseEngineering(ReverseEngineering reverseEngineering) { + return null; + } } diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/validation/DefaultProjectValidator.java b/cayenne-project/src/main/java/org/apache/cayenne/project/validation/DefaultProjectValidator.java index ceb56457ec..394ac483ff 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/validation/DefaultProjectValidator.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/validation/DefaultProjectValidator.java @@ -24,6 +24,7 @@ import org.apache.cayenne.configuration.ConfigurationNodeVisitor; import org.apache.cayenne.configuration.DataChannelDescriptor; import org.apache.cayenne.configuration.DataNodeDescriptor; +import org.apache.cayenne.dbimport.ReverseEngineering; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.map.DbAttribute; import org.apache.cayenne.map.DbEntity; @@ -64,6 +65,7 @@ public class DefaultProjectValidator implements ProjectValidator { private ProcedureQueryValidator procedureQueryValidator; private EJBQLQueryValidator ejbqlQueryValidator; private SQLTemplateValidator sqlTemplateValidator; + private ReverseEngineeringValidator reverseEngineeringValidator; DefaultProjectValidator() { dataChannelValidator = new DataChannelValidator(); @@ -83,6 +85,7 @@ public class DefaultProjectValidator implements ProjectValidator { procedureQueryValidator = new ProcedureQueryValidator(); ejbqlQueryValidator = new EJBQLQueryValidator(); sqlTemplateValidator = new SQLTemplateValidator(); + reverseEngineeringValidator = new ReverseEngineeringValidator(); } public ValidationResult validate(ConfigurationNode node) { @@ -268,5 +271,10 @@ else if (query instanceof EJBQLQuery) { return validationResult; } + + public ValidationResult visitReverseEngineering(ReverseEngineering reverseEngineering) { + reverseEngineeringValidator.validate(reverseEngineering, validationResult); + return validationResult; + } } } diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/validation/ReverseEngineeringValidator.java b/cayenne-project/src/main/java/org/apache/cayenne/project/validation/ReverseEngineeringValidator.java new file mode 100644 index 0000000000..99b92ba53a --- /dev/null +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/validation/ReverseEngineeringValidator.java @@ -0,0 +1,42 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.project.validation; + +import org.apache.cayenne.dbimport.ReverseEngineering; +import org.apache.cayenne.util.Util; +import org.apache.cayenne.validation.ValidationResult; + +/** + * @since 4.0 + */ +public class ReverseEngineeringValidator extends ConfigurationNodeValidator{ + void validate(ReverseEngineering reverseEngineering, ValidationResult validationResult) { + validateName(reverseEngineering, validationResult); + } + + void validateName(ReverseEngineering reverseEngineering, ValidationResult validationResult) { + String name = reverseEngineering.getName(); + + // Must have name + if (Util.isEmptyString(name)) { + addFailure(validationResult, reverseEngineering, "Unnamed ReverseEngineering"); + return; + } + } +} diff --git a/cayenne-project/src/test/java/org/apache/cayenne/project/ReverseEngineeringSaverTest.java b/cayenne-project/src/test/java/org/apache/cayenne/project/ReverseEngineeringSaverTest.java new file mode 100644 index 0000000000..38fe391df4 --- /dev/null +++ b/cayenne-project/src/test/java/org/apache/cayenne/project/ReverseEngineeringSaverTest.java @@ -0,0 +1,62 @@ +package org.apache.cayenne.project; + +import org.apache.cayenne.configuration.*; +import org.apache.cayenne.dbimport.ReverseEngineering; +import org.apache.cayenne.di.*; +import org.apache.cayenne.map.DataMap; +import org.apache.cayenne.project.unit.Project2Case; +import org.apache.cayenne.resource.URLResource; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.net.MalformedURLException; + +import static org.junit.Assert.assertTrue; + +/** + * @since 4.0 + */ +public class ReverseEngineeringSaverTest extends Project2Case { + private FileProjectSaver saver; + + @Before + public void setUp() throws Exception { + Module testModule = new Module() { + + public void configure(Binder binder) { + binder.bind(ConfigurationNameMapper.class).to( + DefaultConfigurationNameMapper.class); + } + }; + + saver = new FileProjectSaver(); + Injector injector = DIBootstrap.createInjector(testModule); + injector.injectMembers(saver); + } + + @Test + public void testSaveReversEngineering() throws MalformedURLException { + File testFolder = setupTestDirectory("testSaverRE"); + + DataChannelDescriptor rootNode = new DataChannelDescriptor(); + rootNode.setName("test"); + + DataMap dataMap = new DataMap("datamap1"); + dataMap.setReverseEngineering(new ReverseEngineering("reverseEngineering1")); + rootNode.getDataMaps().add(dataMap); + + Project project = new Project(new ConfigurationTree<>(rootNode)); + saver.saveAs(project, new URLResource(testFolder.toURL())); + + DataMapLoader dataMapLoader = new XMLDataMapLoader(); + DataMap dataMap1 = dataMapLoader.load(dataMap.getConfigurationSource()); + String reverseEngineeringName = dataMap1.getReverseEngineering().getName(); + + File reFile = new File(testFolder, reverseEngineeringName + ".reverseEngineering.xml"); + assertTrue(reFile.exists()); + assertTrue(reFile.length() > 0); + } + + +} diff --git a/cayenne-server/pom.xml b/cayenne-server/pom.xml index 311f8f3cbb..08cb7f4562 100644 --- a/cayenne-server/pom.xml +++ b/cayenne-server/pom.xml @@ -151,7 +151,13 @@ slf4j-simple test - + + xmlunit + xmlunit + 1.5 + test + + diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java index 26cf33341b..af4358ba75 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java @@ -766,7 +766,7 @@ private Map loadProcedures(FiltersConfig filters, String cata procedure.setCatalog(rs.getString("PROCEDURE_CAT")); procedure.setSchema(rs.getString("PROCEDURE_SCHEM")); - if (filters.proceduresFilter(procedure.getCatalog(), procedure.getSchema()).isInclude( + if (!filters.proceduresFilter(procedure.getCatalog(), procedure.getSchema()).isInclude( procedure.getName())) { LOGGER.info("skipping Cayenne PK procedure: " + name); continue; diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbAttributesPerSchemaLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbAttributesPerSchemaLoader.java index 058494e8b3..a7871ad0be 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbAttributesPerSchemaLoader.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbAttributesPerSchemaLoader.java @@ -107,7 +107,10 @@ private Map> loadDbAttributes() throws SQLException { protected List loadDbAttributes(String tableName) { Map> attributes = getAttributes(); if (attributes != null) { - return attributes.get(tableName); + List dbAttributes = attributes.get(tableName); + if (dbAttributes != null) { + return dbAttributes; + } } return new LinkedList(); diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/PatternFilter.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/PatternFilter.java index 83789bac5e..bfc898c151 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/PatternFilter.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/PatternFilter.java @@ -58,7 +58,9 @@ public StringBuilder toString(StringBuilder res) { public static final Comparator PATTERN_COMPARATOR = new Comparator() { @Override public int compare(Pattern o1, Pattern o2) { - return o1.pattern().compareTo(o2.pattern()); + if(o1 != null && o2 != null) { + return o1.pattern().compareTo(o2.pattern()); + } else return -1; } }; @@ -66,8 +68,8 @@ public int compare(Pattern o1, Pattern o2) { private final SortedSet excludes; public PatternFilter() { - this.includes = new TreeSet(PATTERN_COMPARATOR); - this.excludes = new TreeSet(PATTERN_COMPARATOR); + this.includes = new TreeSet<>(PATTERN_COMPARATOR); + this.excludes = new TreeSet<>(PATTERN_COMPARATOR); } public PatternFilter include(Pattern p) { @@ -83,7 +85,7 @@ public PatternFilter exclude(Pattern p) { } public static Pattern pattern(String pattern) { - if (pattern == null) { + if(pattern == null) { return null; } return Pattern.compile(pattern, Pattern.CASE_INSENSITIVE); @@ -100,18 +102,20 @@ public PatternFilter exclude(String p) { public boolean isInclude(String obj) { boolean include = includes.isEmpty(); for (Pattern p : includes) { - if (p.matcher(obj).matches()) { - include = true; - break; + if(p != null) { + if(p.matcher(obj).matches()) { + include = true; + break; + } } } - if (!include) { + if(!include) { return false; } for (Pattern p : excludes) { - if (p.matcher(obj).matches()) { + if(p.matcher(obj).matches()) { return false; } } @@ -121,11 +125,11 @@ public boolean isInclude(String obj) { @Override public boolean equals(Object o) { - if (this == o) { + if(this == o) { return true; } - if (o == null || getClass() != o.getClass()) { + if(o == null || getClass() != o.getClass()) { return false; } @@ -140,21 +144,16 @@ public int hashCode() { return includes.hashCode(); } - @Override - public String toString() { - return toString(new StringBuilder()).toString(); - } - public StringBuilder toString(StringBuilder res) { - if (includes.isEmpty()) { + if(includes.isEmpty()) { // Do nothing. - } else if (includes.size() > 1) { + } else if(includes.size() > 1) { res.append("(").append(StringUtils.join(includes, " OR ")).append(")"); } else { res.append(includes.first().pattern()); } - if (!excludes.isEmpty()) { + if(!excludes.isEmpty()) { res.append(" AND NOT (").append(StringUtils.join(includes, " OR ")).append(")"); } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/SchemaFilter.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/SchemaFilter.java index 2331938673..c294bc4926 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/SchemaFilter.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/SchemaFilter.java @@ -32,11 +32,6 @@ public SchemaFilter(String name, TableFilter tables, PatternFilter procedures) { this.procedures = procedures; } - @Override - public String toString() { - return toString(new StringBuilder(), "").toString(); - } - protected StringBuilder toString(StringBuilder res, String prefix) { res.append(prefix).append("Schema: ").append(name).append("\n"); tables.toString(res, prefix + " "); diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/TableFilter.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/TableFilter.java index 640c0a8ae1..ef75d0ab82 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/TableFilter.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/TableFilter.java @@ -69,8 +69,10 @@ public PatternFilter isIncludeTable(String tableName) { } for (Pattern p : excludes) { - if (p.matcher(tableName).matches()) { - return null; + if(p != null) { + if (p.matcher(tableName).matches()) { + return null; + } } } @@ -91,11 +93,6 @@ public static TableFilter everything() { return new TableFilter(includes, new TreeSet()); } - @Override - public String toString() { - return toString(new StringBuilder(), "").toString(); - } - protected StringBuilder toString(StringBuilder res, String prefix) { res.append(prefix).append("Tables: ").append("\n"); diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/BaseConfigurationNodeVisitor.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/BaseConfigurationNodeVisitor.java index 15699b22a5..06c823bfd7 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/BaseConfigurationNodeVisitor.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/BaseConfigurationNodeVisitor.java @@ -18,6 +18,7 @@ ****************************************************************/ package org.apache.cayenne.configuration; +import org.apache.cayenne.dbimport.ReverseEngineering; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.map.DbAttribute; import org.apache.cayenne.map.DbEntity; @@ -98,4 +99,7 @@ public T visitQuery(Query query) { throw new UnsupportedOperationException("Not implemented for Query"); } + public T visitReverseEngineering(ReverseEngineering reverseEngineering) { + throw new UnsupportedOperationException("Not implemented for ReverseEngineering"); + } } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/ConfigurationNodeVisitor.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/ConfigurationNodeVisitor.java index 998b1e320c..c611a20797 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/ConfigurationNodeVisitor.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/ConfigurationNodeVisitor.java @@ -18,6 +18,7 @@ ****************************************************************/ package org.apache.cayenne.configuration; +import org.apache.cayenne.dbimport.ReverseEngineering; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.map.DbAttribute; import org.apache.cayenne.map.DbEntity; @@ -66,4 +67,6 @@ public interface ConfigurationNodeVisitor { T visitProcedureParameter(ProcedureParameter parameter); T visitQuery(Query query); + + T visitReverseEngineering(ReverseEngineering reverseEngineering); } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/DefaultConfigurationNameMapper.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/DefaultConfigurationNameMapper.java index ffe286853b..24cea5d948 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/DefaultConfigurationNameMapper.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/DefaultConfigurationNameMapper.java @@ -18,6 +18,7 @@ ****************************************************************/ package org.apache.cayenne.configuration; +import org.apache.cayenne.dbimport.ReverseEngineering; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.resource.Resource; @@ -31,6 +32,8 @@ public class DefaultConfigurationNameMapper implements ConfigurationNameMapper { private static final String DATA_MAP_SUFFIX = ".map.xml"; + private static final String REVERSE_ENGINEERING_SUFFIX = ".reverseEngineering.xml"; + protected ConfigurationNodeVisitor nameMapper; public DefaultConfigurationNameMapper() { @@ -48,6 +51,8 @@ public String configurationLocation(Class type, Str return getDataChannelName(name); } else if (DataMap.class.isAssignableFrom(type)) { return getDataMapName(name); + } else if (ReverseEngineering.class.isAssignableFrom(type)) { + return getReverseEngineeringName(name); } throw new IllegalArgumentException("Unrecognized configuration type: " + type.getName()); @@ -104,6 +109,14 @@ protected String getDataMapName(String name) { return name + DATA_MAP_SUFFIX; } + private String getReverseEngineeringName(String name) { + if (name == null) { + throw new NullPointerException("Null Reverse Engineering name"); + } + + return name + REVERSE_ENGINEERING_SUFFIX; + } + final class NameMapper extends BaseConfigurationNodeVisitor { @Override @@ -115,5 +128,10 @@ public String visitDataChannelDescriptor(DataChannelDescriptor descriptor) { public String visitDataMap(DataMap dataMap) { return getDataMapName(dataMap.getName()); } + + @Override + public String visitReverseEngineering(ReverseEngineering reverseEngineering) { + return getReverseEngineeringName(reverseEngineering.getName()); + } } } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java index e763b5b732..3390fe73b4 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java @@ -27,6 +27,9 @@ import org.apache.cayenne.ConfigurationException; import org.apache.cayenne.conn.DataSourceInfo; +import org.apache.cayenne.dbimport.DefaultReverseEngineeringLoader; +import org.apache.cayenne.dbimport.ReverseEngineering; +import org.apache.cayenne.dbimport.ReverseEngineeringLoaderException; import org.apache.cayenne.di.AdhocObjectFactory; import org.apache.cayenne.di.Inject; import org.apache.cayenne.map.DataMap; @@ -34,356 +37,372 @@ import org.apache.cayenne.util.Util; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.xml.sax.Attributes; -import org.xml.sax.ContentHandler; -import org.xml.sax.InputSource; -import org.xml.sax.XMLReader; +import org.xml.sax.*; + +import javax.xml.parsers.ParserConfigurationException; /** * @since 3.1 */ public class XMLDataChannelDescriptorLoader implements DataChannelDescriptorLoader { - private static Log logger = LogFactory.getLog(XMLDataChannelDescriptorLoader.class); - - static final String DOMAIN_TAG = "domain"; - static final String MAP_TAG = "map"; - static final String NODE_TAG = "node"; - static final String PROPERTY_TAG = "property"; - static final String MAP_REF_TAG = "map-ref"; - static final String DATA_SOURCE_TAG = "data-source"; - - /** - * @deprecated the caller should use password resolving strategy instead of - * resolving the password on the spot. For one thing this can be - * used in the Modeler and no password may be available. - */ - @Deprecated - private static String passwordFromURL(URL url) { - InputStream inputStream = null; - String password = null; - - try { - inputStream = url.openStream(); - password = passwordFromInputStream(inputStream); - } catch (IOException exception) { - // Log the error while trying to open the stream. A null - // password will be returned as a result. - logger.warn(exception); - } - - return password; - } - - /** - * @deprecated the caller should use password resolving strategy instead of - * resolving the password on the spot. For one thing this can be - * used in the Modeler and no password may be available. - */ - @Deprecated - private static String passwordFromInputStream(InputStream inputStream) { - String password = null; - - try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));) { - - password = bufferedReader.readLine(); - } catch (IOException exception) { - logger.warn(exception); - } finally { - - try { - inputStream.close(); - } catch (IOException exception) { - } - } - - return password; - } - - @Inject - protected DataMapLoader dataMapLoader; - - @Inject - protected ConfigurationNameMapper nameMapper; - - @Inject - protected AdhocObjectFactory objectFactory; - - @Override - public ConfigurationTree load(Resource configurationResource) throws ConfigurationException { - - if (configurationResource == null) { - throw new NullPointerException("Null configurationResource"); - } - - URL configurationURL = configurationResource.getURL(); - - logger.info("Loading XML configuration resource from " + configurationURL); - - DataChannelDescriptor descriptor = new DataChannelDescriptor(); - descriptor.setConfigurationSource(configurationResource); - descriptor.setName(nameMapper.configurationNodeName(DataChannelDescriptor.class, configurationResource)); - - DataChannelHandler rootHandler; - - InputStream in = null; - - try { - in = configurationURL.openStream(); - XMLReader parser = Util.createXmlReader(); - - rootHandler = new DataChannelHandler(descriptor, parser); - parser.setContentHandler(rootHandler); - parser.setErrorHandler(rootHandler); - parser.parse(new InputSource(in)); - } catch (Exception e) { - throw new ConfigurationException("Error loading configuration from %s", e, configurationURL); - } finally { - try { - if (in != null) { - in.close(); - } - } catch (IOException ioex) { - logger.info("failure closing input stream for " + configurationURL + ", ignoring", ioex); - } - } - - // TODO: andrus 03/10/2010 - actually provide load failures here... - return new ConfigurationTree(descriptor, null); - } - - final class DataChannelHandler extends SAXNestedTagHandler { - - private DataChannelDescriptor descriptor; - - DataChannelHandler(DataChannelDescriptor dataChannelDescriptor, XMLReader parser) { - super(parser, null); - this.descriptor = dataChannelDescriptor; - } - - @Override - protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name, - Attributes attributes) { - - if (localName.equals(DOMAIN_TAG)) { - return new DataChannelChildrenHandler(parser, this); - } - - logger.info(unexpectedTagMessage(localName, DOMAIN_TAG)); - return super.createChildTagHandler(namespaceURI, localName, name, attributes); - } - } - - final class DataChannelChildrenHandler extends SAXNestedTagHandler { - - private DataChannelDescriptor descriptor; - - DataChannelChildrenHandler(XMLReader parser, DataChannelHandler parentHandler) { - super(parser, parentHandler); - this.descriptor = parentHandler.descriptor; - } - - @Override - protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name, - Attributes attributes) { + private static Log logger = LogFactory.getLog(XMLDataChannelDescriptorLoader.class); + + static final String DOMAIN_TAG = "domain"; + static final String MAP_TAG = "map"; + static final String NODE_TAG = "node"; + static final String PROPERTY_TAG = "property"; + static final String MAP_REF_TAG = "map-ref"; + static final String DATA_SOURCE_TAG = "data-source"; + + /** + * @deprecated the caller should use password resolving strategy instead of + * resolving the password on the spot. For one thing this can be + * used in the Modeler and no password may be available. + */ + @Deprecated + private static String passwordFromURL(URL url) { + InputStream inputStream = null; + String password = null; + + try { + inputStream = url.openStream(); + password = passwordFromInputStream(inputStream); + } catch (IOException exception) { + // Log the error while trying to open the stream. A null + // password will be returned as a result. + logger.warn(exception); + } + + return password; + } + + /** + * @deprecated the caller should use password resolving strategy instead of + * resolving the password on the spot. For one thing this can be + * used in the Modeler and no password may be available. + */ + @Deprecated + private static String passwordFromInputStream(InputStream inputStream) { + String password = null; + + try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));) { + + password = bufferedReader.readLine(); + } catch (IOException exception) { + logger.warn(exception); + } finally { + + try { + inputStream.close(); + } catch (IOException exception) { + } + } + + return password; + } + + @Inject + protected DataMapLoader dataMapLoader; + + @Inject + protected ConfigurationNameMapper nameMapper; - if (localName.equals(PROPERTY_TAG)) { + @Inject + protected AdhocObjectFactory objectFactory; + + @Override + public ConfigurationTree load(Resource configurationResource) throws ConfigurationException { + + if (configurationResource == null) { + throw new NullPointerException("Null configurationResource"); + } + + URL configurationURL = configurationResource.getURL(); + + logger.info("Loading XML configuration resource from " + configurationURL); + + DataChannelDescriptor descriptor = new DataChannelDescriptor(); + descriptor.setConfigurationSource(configurationResource); + descriptor.setName(nameMapper.configurationNodeName(DataChannelDescriptor.class, configurationResource)); + + DataChannelHandler rootHandler; + + InputStream in = null; + + try { + in = configurationURL.openStream(); + XMLReader parser = Util.createXmlReader(); + + rootHandler = new DataChannelHandler(descriptor, parser); + parser.setContentHandler(rootHandler); + parser.setErrorHandler(rootHandler); + parser.parse(new InputSource(in)); + } catch (Exception e) { + throw new ConfigurationException("Error loading configuration from %s", e, configurationURL); + } finally { + try { + if (in != null) { + in.close(); + } + } catch (IOException ioex) { + logger.info("failure closing input stream for " + configurationURL + ", ignoring", ioex); + } + } + + // TODO: andrus 03/10/2010 - actually provide load failures here... + return new ConfigurationTree(descriptor, null); + } + + final class DataChannelHandler extends SAXNestedTagHandler { + + private DataChannelDescriptor descriptor; + + DataChannelHandler(DataChannelDescriptor dataChannelDescriptor, XMLReader parser) { + super(parser, null); + this.descriptor = dataChannelDescriptor; + } + + @Override + protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name, + Attributes attributes) { + + if (localName.equals(DOMAIN_TAG)) { + return new DataChannelChildrenHandler(parser, this); + } + + logger.info(unexpectedTagMessage(localName, DOMAIN_TAG)); + return super.createChildTagHandler(namespaceURI, localName, name, attributes); + } + } - String key = attributes.getValue("", "name"); - String value = attributes.getValue("", "value"); - if (key != null && value != null) { - descriptor.getProperties().put(key, value); - } - } else if (localName.equals(MAP_TAG)) { + final class DataChannelChildrenHandler extends SAXNestedTagHandler { + + private DataChannelDescriptor descriptor; - String dataMapName = attributes.getValue("", "name"); - Resource baseResource = descriptor.getConfigurationSource(); + DataChannelChildrenHandler(XMLReader parser, DataChannelHandler parentHandler) { + super(parser, parentHandler); + this.descriptor = parentHandler.descriptor; + } - String dataMapLocation = nameMapper.configurationLocation(DataMap.class, dataMapName); + @Override + protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name, + Attributes attributes) { - Resource dataMapResource = baseResource.getRelativeResource(dataMapLocation); + if (localName.equals(PROPERTY_TAG)) { - logger.info("Loading XML DataMap resource from " + dataMapResource.getURL()); + String key = attributes.getValue("", "name"); + String value = attributes.getValue("", "value"); + if (key != null && value != null) { + descriptor.getProperties().put(key, value); + } + } else if (localName.equals(MAP_TAG)) { - DataMap dataMap = dataMapLoader.load(dataMapResource); - dataMap.setName(dataMapName); - dataMap.setLocation(dataMapLocation); - dataMap.setConfigurationSource(dataMapResource); - dataMap.setDataChannelDescriptor(descriptor); + String dataMapName = attributes.getValue("", "name"); + Resource baseResource = descriptor.getConfigurationSource(); - descriptor.getDataMaps().add(dataMap); - } else if (localName.equals(NODE_TAG)) { + String dataMapLocation = nameMapper.configurationLocation(DataMap.class, dataMapName); - String nodeName = attributes.getValue("", "name"); - if (nodeName == null) { - throw new ConfigurationException("Error: without 'name'."); - } + Resource dataMapResource = baseResource.getRelativeResource(dataMapLocation); - DataNodeDescriptor nodeDescriptor = new DataNodeDescriptor(); - nodeDescriptor.setConfigurationSource(descriptor.getConfigurationSource()); - descriptor.getNodeDescriptors().add(nodeDescriptor); + logger.info("Loading XML DataMap resource from " + dataMapResource.getURL()); - nodeDescriptor.setName(nodeName); - nodeDescriptor.setAdapterType(attributes.getValue("", "adapter")); + DataMap dataMap = dataMapLoader.load(dataMapResource); + dataMap.setName(dataMapName); + dataMap.setLocation(dataMapLocation); + dataMap.setConfigurationSource(dataMapResource); + dataMap.setDataChannelDescriptor(descriptor); - String parameters = attributes.getValue("", "parameters"); - nodeDescriptor.setParameters(parameters); + try { + if (dataMap.getReverseEngineering() != null) { + String reverseEngineeringName = dataMap.getReverseEngineering().getName(); + String reverseEngineeringLocation = nameMapper.configurationLocation(ReverseEngineering.class, reverseEngineeringName); + Resource reverseEngineeringResource = baseResource.getRelativeResource(reverseEngineeringLocation); + DefaultReverseEngineeringLoader reverseEngineeringLoader = new DefaultReverseEngineeringLoader(); + ReverseEngineering reverseEngineering = reverseEngineeringLoader.load(reverseEngineeringResource.getURL().openStream()); + reverseEngineering.setName(reverseEngineeringName); + reverseEngineering.setConfigurationSource(reverseEngineeringResource); + dataMap.setReverseEngineering(reverseEngineering); + } + } catch (ReverseEngineeringLoaderException e) { + logger.info(e.getMessage(), e); + } catch (IOException e) { + logger.info(e.getMessage(), e); + } + + descriptor.getDataMaps().add(dataMap); + } else if (localName.equals(NODE_TAG)) { + + String nodeName = attributes.getValue("", "name"); + if (nodeName == null) { + throw new ConfigurationException("Error: without 'name'."); + } + + DataNodeDescriptor nodeDescriptor = new DataNodeDescriptor(); + nodeDescriptor.setConfigurationSource(descriptor.getConfigurationSource()); + descriptor.getNodeDescriptors().add(nodeDescriptor); + + nodeDescriptor.setName(nodeName); + nodeDescriptor.setAdapterType(attributes.getValue("", "adapter")); + + String parameters = attributes.getValue("", "parameters"); + nodeDescriptor.setParameters(parameters); - String dataSourceFactory = attributes.getValue("", "factory"); - nodeDescriptor.setDataSourceFactoryType(dataSourceFactory); - nodeDescriptor.setSchemaUpdateStrategyType(attributes.getValue("", "schema-update-strategy")); - nodeDescriptor.setDataChannelDescriptor(descriptor); - - return new DataNodeChildrenHandler(parser, this, nodeDescriptor); - } - - return super.createChildTagHandler(namespaceURI, localName, name, attributes); - } - } - - final class DataNodeChildrenHandler extends SAXNestedTagHandler { - - private DataNodeDescriptor nodeDescriptor; - - DataNodeChildrenHandler(XMLReader parser, SAXNestedTagHandler parentHandler, DataNodeDescriptor nodeDescriptor) { - super(parser, parentHandler); - this.nodeDescriptor = nodeDescriptor; - } - - @Override - protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name, - Attributes attributes) { - - if (localName.equals(MAP_REF_TAG)) { - - String mapName = attributes.getValue("", "name"); - nodeDescriptor.getDataMapNames().add(mapName); - } else if (localName.equals(DATA_SOURCE_TAG)) { - - DataSourceInfo dataSourceDescriptor = new DataSourceInfo(); - nodeDescriptor.setDataSourceDescriptor(dataSourceDescriptor); - return new DataSourceChildrenHandler(parser, this, dataSourceDescriptor); - } - - return super.createChildTagHandler(namespaceURI, localName, name, attributes); - } - } - - class DataSourceChildrenHandler extends SAXNestedTagHandler { - - private DataSourceInfo dataSourceDescriptor; - - DataSourceChildrenHandler(XMLReader parser, DataNodeChildrenHandler parentHandler, - DataSourceInfo dataSourceDescriptor) { - super(parser, parentHandler); - this.dataSourceDescriptor = dataSourceDescriptor; - } - - @Override - protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name, - Attributes attributes) { - - if (localName.equals("driver")) { - String className = attributes.getValue("", "value"); - dataSourceDescriptor.setJdbcDriver(className); - } else if (localName.equals("login")) { - - logger.info("loading user name and password."); - - String encoderClass = attributes.getValue("encoderClass"); - - String encoderKey = attributes.getValue("encoderKey"); - if (encoderKey == null) { - encoderKey = attributes.getValue("encoderSalt"); - } - - String password = attributes.getValue("password"); - String passwordLocation = attributes.getValue("passwordLocation"); - String passwordSource = attributes.getValue("passwordSource"); - if (passwordSource == null) { - passwordSource = DataSourceInfo.PASSWORD_LOCATION_MODEL; - } - - String username = attributes.getValue("userName"); - - dataSourceDescriptor.setPasswordEncoderClass(encoderClass); - dataSourceDescriptor.setPasswordEncoderKey(encoderKey); - dataSourceDescriptor.setPasswordLocation(passwordLocation); - dataSourceDescriptor.setPasswordSource(passwordSource); - dataSourceDescriptor.setUserName(username); - - // Replace {} in passwordSource with encoderSalt -- useful for - // EXECUTABLE - // & URL options - if (encoderKey != null) { - passwordSource = passwordSource.replaceAll("\\{\\}", encoderKey); - } - - String encoderType = dataSourceDescriptor.getPasswordEncoderClass(); - PasswordEncoding passwordEncoder = null; - if (encoderType != null) { - passwordEncoder = objectFactory.newInstance(PasswordEncoding.class, encoderType); - } - - if (passwordLocation != null) { - if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_CLASSPATH)) { - - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - URL url = classLoader.getResource(username); - if (url != null) { - password = passwordFromURL(url); - } else { - logger.error("Could not find resource in CLASSPATH: " + passwordSource); - } - } else if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_URL)) { - try { - password = passwordFromURL(new URL(passwordSource)); - } catch (MalformedURLException exception) { - logger.warn(exception); - } - } else if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_EXECUTABLE)) { - if (passwordSource != null) { - try { - Process process = Runtime.getRuntime().exec(passwordSource); - password = passwordFromInputStream(process.getInputStream()); - process.waitFor(); - } catch (IOException exception) { - logger.warn(exception); - } catch (InterruptedException exception) { - logger.warn(exception); - } - } - } - } - - if (password != null && passwordEncoder != null) { - dataSourceDescriptor.setPassword(passwordEncoder.decodePassword(password, encoderKey)); - } - } else if (localName.equals("url")) { - dataSourceDescriptor.setDataSourceUrl(attributes.getValue("value")); - } else if (localName.equals("connectionPool")) { - String min = attributes.getValue("min"); - if (min != null) { - try { - dataSourceDescriptor.setMinConnections(Integer.parseInt(min)); - } catch (NumberFormatException nfex) { - logger.info("Non-numeric 'min' attribute", nfex); - throw new ConfigurationException("Non-numeric 'min' attribute '%s'", nfex, min); - } - } - - String max = attributes.getValue("max"); - if (max != null) { - try { - dataSourceDescriptor.setMaxConnections(Integer.parseInt(max)); - } catch (NumberFormatException nfex) { - logger.info("Non-numeric 'max' attribute", nfex); - throw new ConfigurationException("Non-numeric 'max' attribute '%s'", nfex, max); - } - } - } - - return super.createChildTagHandler(namespaceURI, localName, name, attributes); - } - } + String dataSourceFactory = attributes.getValue("", "factory"); + nodeDescriptor.setDataSourceFactoryType(dataSourceFactory); + nodeDescriptor.setSchemaUpdateStrategyType(attributes.getValue("", "schema-update-strategy")); + nodeDescriptor.setDataChannelDescriptor(descriptor); + + return new DataNodeChildrenHandler(parser, this, nodeDescriptor); + } + + return super.createChildTagHandler(namespaceURI, localName, name, attributes); + } + } + + final class DataNodeChildrenHandler extends SAXNestedTagHandler { + + private DataNodeDescriptor nodeDescriptor; + + DataNodeChildrenHandler(XMLReader parser, SAXNestedTagHandler parentHandler, DataNodeDescriptor nodeDescriptor) { + super(parser, parentHandler); + this.nodeDescriptor = nodeDescriptor; + } + + @Override + protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name, + Attributes attributes) { + + if (localName.equals(MAP_REF_TAG)) { + + String mapName = attributes.getValue("", "name"); + nodeDescriptor.getDataMapNames().add(mapName); + } else if (localName.equals(DATA_SOURCE_TAG)) { + + DataSourceInfo dataSourceDescriptor = new DataSourceInfo(); + nodeDescriptor.setDataSourceDescriptor(dataSourceDescriptor); + return new DataSourceChildrenHandler(parser, this, dataSourceDescriptor); + } + + return super.createChildTagHandler(namespaceURI, localName, name, attributes); + } + } + + class DataSourceChildrenHandler extends SAXNestedTagHandler { + + private DataSourceInfo dataSourceDescriptor; + + DataSourceChildrenHandler(XMLReader parser, DataNodeChildrenHandler parentHandler, + DataSourceInfo dataSourceDescriptor) { + super(parser, parentHandler); + this.dataSourceDescriptor = dataSourceDescriptor; + } + + @Override + protected ContentHandler createChildTagHandler(String namespaceURI, String localName, String name, + Attributes attributes) { + + if (localName.equals("driver")) { + String className = attributes.getValue("", "value"); + dataSourceDescriptor.setJdbcDriver(className); + } else if (localName.equals("login")) { + + logger.info("loading user name and password."); + + String encoderClass = attributes.getValue("encoderClass"); + + String encoderKey = attributes.getValue("encoderKey"); + if (encoderKey == null) { + encoderKey = attributes.getValue("encoderSalt"); + } + + String password = attributes.getValue("password"); + String passwordLocation = attributes.getValue("passwordLocation"); + String passwordSource = attributes.getValue("passwordSource"); + if (passwordSource == null) { + passwordSource = DataSourceInfo.PASSWORD_LOCATION_MODEL; + } + + String username = attributes.getValue("userName"); + + dataSourceDescriptor.setPasswordEncoderClass(encoderClass); + dataSourceDescriptor.setPasswordEncoderKey(encoderKey); + dataSourceDescriptor.setPasswordLocation(passwordLocation); + dataSourceDescriptor.setPasswordSource(passwordSource); + dataSourceDescriptor.setUserName(username); + + // Replace {} in passwordSource with encoderSalt -- useful for + // EXECUTABLE + // & URL options + if (encoderKey != null) { + passwordSource = passwordSource.replaceAll("\\{\\}", encoderKey); + } + + String encoderType = dataSourceDescriptor.getPasswordEncoderClass(); + PasswordEncoding passwordEncoder = null; + if (encoderType != null) { + passwordEncoder = objectFactory.newInstance(PasswordEncoding.class, encoderType); + } + + if (passwordLocation != null) { + if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_CLASSPATH)) { + + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + URL url = classLoader.getResource(username); + if (url != null) { + password = passwordFromURL(url); + } else { + logger.error("Could not find resource in CLASSPATH: " + passwordSource); + } + } else if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_URL)) { + try { + password = passwordFromURL(new URL(passwordSource)); + } catch (MalformedURLException exception) { + logger.warn(exception); + } + } else if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_EXECUTABLE)) { + if (passwordSource != null) { + try { + Process process = Runtime.getRuntime().exec(passwordSource); + password = passwordFromInputStream(process.getInputStream()); + process.waitFor(); + } catch (IOException exception) { + logger.warn(exception); + } catch (InterruptedException exception) { + logger.warn(exception); + } + } + } + } + + if (password != null && passwordEncoder != null) { + dataSourceDescriptor.setPassword(passwordEncoder.decodePassword(password, encoderKey)); + } + } else if (localName.equals("url")) { + dataSourceDescriptor.setDataSourceUrl(attributes.getValue("value")); + } else if (localName.equals("connectionPool")) { + String min = attributes.getValue("min"); + if (min != null) { + try { + dataSourceDescriptor.setMinConnections(Integer.parseInt(min)); + } catch (NumberFormatException nfex) { + logger.info("Non-numeric 'min' attribute", nfex); + throw new ConfigurationException("Non-numeric 'min' attribute '%s'", nfex, min); + } + } + + String max = attributes.getValue("max"); + if (max != null) { + try { + dataSourceDescriptor.setMaxConnections(Integer.parseInt(max)); + } catch (NumberFormatException nfex) { + logger.info("Non-numeric 'max' attribute", nfex); + throw new ConfigurationException("Non-numeric 'max' attribute '%s'", nfex, max); + } + } + } + + return super.createChildTagHandler(namespaceURI, localName, name, attributes); + } + } } diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/AntNestedElement.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/AntNestedElement.java similarity index 96% rename from cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/AntNestedElement.java rename to cayenne-server/src/main/java/org/apache/cayenne/dbimport/AntNestedElement.java index c8a801b710..f300c023c2 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/AntNestedElement.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/AntNestedElement.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. ****************************************************************/ -package org.apache.cayenne.tools.dbimport.config; +package org.apache.cayenne.dbimport; /** * Additional class to handle element under and diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Catalog.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/Catalog.java similarity index 94% rename from cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Catalog.java rename to cayenne-server/src/main/java/org/apache/cayenne/dbimport/Catalog.java index 904d41bba9..99cf4cca0b 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Catalog.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/Catalog.java @@ -16,18 +16,22 @@ * specific language governing permissions and limitations * under the License. ****************************************************************/ -package org.apache.cayenne.tools.dbimport.config; +package org.apache.cayenne.dbimport; +import javax.xml.bind.annotation.*; import java.util.Collection; import java.util.LinkedList; /** * @since 4.0. */ +@XmlAccessorType(XmlAccessType.FIELD) public class Catalog extends FilterContainer { + @XmlAttribute(name = "name") private String name; + @XmlElement(name = "schema") private Collection schemas = new LinkedList(); public Catalog() { diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/DefaultReverseEngineeringLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringLoader.java similarity index 92% rename from cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/DefaultReverseEngineeringLoader.java rename to cayenne-server/src/main/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringLoader.java index 807b7ffc62..cb63ff9ca1 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/DefaultReverseEngineeringLoader.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringLoader.java @@ -16,25 +16,21 @@ * specific language governing permissions and limitations * under the License. ****************************************************************/ -package org.apache.cayenne.tools.dbimport.config; +package org.apache.cayenne.dbimport; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.ParserConfigurationException; - -import org.apache.cayenne.tools.ExcludeTable; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.w3c.dom.Document; +import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; -import org.w3c.dom.Element; - -import org.apache.cayenne.CayenneRuntimeException; -import org.apache.cayenne.resource.Resource; import org.xml.sax.SAXException; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; +import java.io.InputStream; import java.util.Collection; import java.util.LinkedList; import java.util.List; @@ -47,12 +43,13 @@ public class DefaultReverseEngineeringLoader implements ReverseEngineeringLoader private static final Log LOG = LogFactory.getLog(ReverseEngineeringLoader.class); @Override - public ReverseEngineering load(Resource configurationResource) throws CayenneRuntimeException { + public ReverseEngineering load(InputStream inputStream) throws IOException, ReverseEngineeringLoaderException { DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = null; try { - DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); - Document doc = dBuilder.parse(configurationResource.getURL().openStream()); + dBuilder = dbFactory.newDocumentBuilder(); + Document doc = dBuilder.parse(inputStream); ReverseEngineering engineering = new ReverseEngineering(); @@ -72,15 +69,10 @@ public ReverseEngineering load(Resource configurationResource) throws CayenneRun return engineering; } catch (ParserConfigurationException e) { - LOG.info(e.getMessage(), e); + throw new ReverseEngineeringLoaderException(e.getMessage(), e); } catch (SAXException e) { - LOG.info(e.getMessage(), e); - } catch (IOException e) { - LOG.info(e.getMessage(), e); + throw new ReverseEngineeringLoaderException(e.getMessage(), e); } - - - return null; } private Boolean loadBoolean(Element root, String name) { diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringWriter.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringWriter.java new file mode 100644 index 0000000000..be9c7d59c2 --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringWriter.java @@ -0,0 +1,58 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.dbimport; + +import org.apache.cayenne.CayenneRuntimeException; +import org.apache.cayenne.resource.Resource; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import java.io.IOException; +import java.io.Writer; + +/** + * @since 4.0 + */ +public class DefaultReverseEngineeringWriter implements ReverseEngineeringWriter { + private final static Log LOGGER = LogFactory.getLog(DefaultReverseEngineeringWriter.class); + + @Override + public Resource write(ReverseEngineering reverseEngineering, Writer writer) throws CayenneRuntimeException { + + try { + JAXBContext context = JAXBContext.newInstance(reverseEngineering.getClass()); + Marshaller marshaller = context.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + + marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true); + marshaller.marshal(reverseEngineering, writer); + writer.close(); + return reverseEngineering.getConfigurationSource(); + } catch (JAXBException e) { + LOGGER.error(e.getMessage(), e); + throw new CayenneRuntimeException(e); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + throw new CayenneRuntimeException(e); + } + } +} diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ExcludeColumn.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeColumn.java similarity index 95% rename from cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ExcludeColumn.java rename to cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeColumn.java index 94ed854ab2..ff1e0e3af5 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ExcludeColumn.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeColumn.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. ****************************************************************/ -package org.apache.cayenne.tools.dbimport.config; +package org.apache.cayenne.dbimport; /** * @since 4.0. diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ExcludeProcedure.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeProcedure.java similarity index 95% rename from cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ExcludeProcedure.java rename to cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeProcedure.java index f0b060e4b1..e5d7b2d301 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ExcludeProcedure.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeProcedure.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. ****************************************************************/ -package org.apache.cayenne.tools.dbimport.config; +package org.apache.cayenne.dbimport; /** * @since 4.0. diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/ExcludeTable.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeTable.java similarity index 92% rename from cayenne-tools/src/main/java/org/apache/cayenne/tools/ExcludeTable.java rename to cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeTable.java index 779a9faa25..3cbd8d4ebd 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/ExcludeTable.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ExcludeTable.java @@ -16,9 +16,7 @@ * specific language governing permissions and limitations * under the License. ****************************************************************/ -package org.apache.cayenne.tools; - -import org.apache.cayenne.tools.dbimport.config.PatternParam; +package org.apache.cayenne.dbimport; /** * @since 4.0. diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/FilterContainer.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/FilterContainer.java similarity index 91% rename from cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/FilterContainer.java rename to cayenne-server/src/main/java/org/apache/cayenne/dbimport/FilterContainer.java index 57da6ab2e3..5a42d3b58b 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/FilterContainer.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/FilterContainer.java @@ -16,23 +16,36 @@ * specific language governing permissions and limitations * under the License. ****************************************************************/ -package org.apache.cayenne.tools.dbimport.config; - -import org.apache.cayenne.tools.ExcludeTable; +package org.apache.cayenne.dbimport; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; import java.util.Collection; import java.util.LinkedList; /** * @since 4.0. */ +@XmlAccessorType(XmlAccessType.FIELD) public abstract class FilterContainer { + @XmlElement(name = "includeTable") private Collection includeTables = new LinkedList(); + + @XmlElement(name = "excludeTable") private Collection excludeTables = new LinkedList(); + + @XmlElement(name = "includeColumn") private Collection includeColumns = new LinkedList(); + + @XmlElement(name = "excludeColumn") private Collection excludeColumns = new LinkedList(); + + @XmlElement(name = "includeProcedure") private Collection includeProcedures = new LinkedList(); + + @XmlElement(name = "excludeProcedure") private Collection excludeProcedures = new LinkedList(); public Collection getIncludeTables() { @@ -141,4 +154,6 @@ protected void appendCollection(StringBuilder res, String prefix, Collection + * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. ****************************************************************/ -package org.apache.cayenne.tools.dbimport.config; +package org.apache.cayenne.dbimport; import org.apache.cayenne.access.loader.filters.OldFilterConfigBridge; import org.apache.cayenne.access.loader.filters.CatalogFilter; @@ -25,18 +25,15 @@ import org.apache.cayenne.access.loader.filters.TableFilter; import org.apache.cayenne.access.loader.filters.FiltersConfig; import org.apache.cayenne.access.loader.filters.PatternFilter; -import org.apache.cayenne.tools.ExcludeTable; -import java.util.Collection; -import java.util.SortedSet; -import java.util.TreeSet; +import java.util.*; import java.util.regex.Pattern; import static org.apache.commons.lang.StringUtils.isBlank; /** -* @since 4.0. -*/ + * @since 4.0. + */ public final class FiltersConfigBuilder { private final ReverseEngineering engineering; @@ -58,7 +55,7 @@ private CatalogFilter[] transformCatalogs(Collection catalogs) { catalogFilters[i] = new CatalogFilter(catalog.getName(), transformSchemas(catalog.getSchemas())); i++; } - + return catalogFilters; } @@ -68,7 +65,7 @@ private SchemaFilter[] transformSchemas(Collection schemas) { for (Schema schema : schemas) { schemaFilters[i] = new SchemaFilter(schema.getName(), new TableFilter(transformIncludeTable(schema.getIncludeTables()), - transformExcludeTable(schema.getExcludeTables())), + transformExcludeTable(schema.getExcludeTables())), transform(schema.getIncludeProcedures(), schema.getExcludeProcedures())); i++; } @@ -194,11 +191,14 @@ private void compactProcedureFilter() { catalog.setExcludeProcedures(null); for (Schema schema : catalog.getSchemas()) { - schema.getIncludeProcedures().addAll(engIncludeProcedures); - schema.getIncludeProcedures().addAll(catalogIncludeProcedures); - - schema.getExcludeProcedures().addAll(engExcludeProcedures); - schema.getExcludeProcedures().addAll(catalogExcludeProcedures); + if (engIncludeProcedures != null) { + schema.getIncludeProcedures().addAll(engIncludeProcedures); + schema.getIncludeProcedures().addAll(catalogIncludeProcedures); + } + if (engExcludeProcedures != null) { + schema.getExcludeProcedures().addAll(engExcludeProcedures); + schema.getExcludeProcedures().addAll(catalogExcludeProcedures); + } } } @@ -223,11 +223,14 @@ private void compactTableFilter() { catalog.setExcludeTables(null); for (Schema schema : catalog.getSchemas()) { - schema.getIncludeTables().addAll(engIncludeTables); - schema.getIncludeTables().addAll(catalogIncludeTables); - - schema.getExcludeTables().addAll(engExcludeTables); - schema.getExcludeTables().addAll(catalogExcludeTables); + if (engIncludeTables != null) { + schema.getIncludeTables().addAll(engIncludeTables); + schema.getIncludeTables().addAll(catalogIncludeTables); + } + if (engExcludeTables != null) { + schema.getExcludeTables().addAll(engExcludeTables); + schema.getExcludeTables().addAll(catalogExcludeTables); + } } } @@ -258,24 +261,31 @@ private void compactColumnFilters() { schema.setIncludeColumns(null); schema.setExcludeColumns(null); - for (IncludeTable includeTable : schema.getIncludeTables()) { + if (schema != null) { + for (IncludeTable includeTable : schema.getIncludeTables()) { + if (engIncludeColumns != null) { + includeTable.getIncludeColumns().addAll(engIncludeColumns); + includeTable.getIncludeColumns().addAll(catalogIncludeColumns); + includeTable.getIncludeColumns().addAll(schemaIncludeColumns); + } + if (engExcludeColumns != null) { + includeTable.getExcludeColumns().addAll(engExcludeColumns); + includeTable.getExcludeColumns().addAll(catalogExcludeColumns); + includeTable.getExcludeColumns().addAll(schemaExcludeColumns); + } + } + } + } + + if (catalog.getIncludeTables() != null) { + for (IncludeTable includeTable : catalog.getIncludeTables()) { includeTable.getIncludeColumns().addAll(engIncludeColumns); includeTable.getIncludeColumns().addAll(catalogIncludeColumns); - includeTable.getIncludeColumns().addAll(schemaIncludeColumns); includeTable.getExcludeColumns().addAll(engExcludeColumns); includeTable.getExcludeColumns().addAll(catalogExcludeColumns); - includeTable.getExcludeColumns().addAll(schemaExcludeColumns); } } - - for (IncludeTable includeTable : catalog.getIncludeTables()) { - includeTable.getIncludeColumns().addAll(engIncludeColumns); - includeTable.getIncludeColumns().addAll(catalogIncludeColumns); - - includeTable.getExcludeColumns().addAll(engExcludeColumns); - includeTable.getExcludeColumns().addAll(catalogExcludeColumns); - } } for (Schema schema : engineering.getSchemas()) { @@ -294,9 +304,11 @@ private void compactColumnFilters() { } } - for (IncludeTable includeTable : engineering.getIncludeTables()) { - includeTable.getIncludeColumns().addAll(engIncludeColumns); - includeTable.getExcludeColumns().addAll(engExcludeColumns); + if (engineering.getIncludeTables() != null) { + for (IncludeTable includeTable : engineering.getIncludeTables()) { + includeTable.getIncludeColumns().addAll(engIncludeColumns); + includeTable.getExcludeColumns().addAll(engExcludeColumns); + } } } @@ -321,6 +333,10 @@ private void addEmptyElements() { } } + if (engineering.getSchemas() == null) { + engineering.setSchemas(new LinkedList()); + } + for (Schema schema : engineering.getSchemas()) { if (schema.getIncludeTables().isEmpty() && engineering.getIncludeTables().isEmpty()) { @@ -345,7 +361,7 @@ public FiltersConfigBuilder add(OldFilterConfigBridge build) { if (!isBlank(build.getExcludeTableFilters())) { engineering.addExcludeTable(new ExcludeTable(build.getExcludeTableFilters())); } - + if (!isBlank(build.getIncludeColumnFilters())) { engineering.addIncludeColumn(new IncludeColumn(build.getIncludeColumnFilters())); } diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/IncludeColumn.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeColumn.java similarity index 95% rename from cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/IncludeColumn.java rename to cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeColumn.java index ba4362ba2c..899e9874ac 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/IncludeColumn.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeColumn.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. ****************************************************************/ -package org.apache.cayenne.tools.dbimport.config; +package org.apache.cayenne.dbimport; /** * @since 4.0. diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/IncludeProcedure.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeProcedure.java similarity index 95% rename from cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/IncludeProcedure.java rename to cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeProcedure.java index 404e4f2419..a249385d6a 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/IncludeProcedure.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeProcedure.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. ****************************************************************/ -package org.apache.cayenne.tools.dbimport.config; +package org.apache.cayenne.dbimport; /** * @since 4.0. diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/IncludeTable.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeTable.java similarity index 90% rename from cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/IncludeTable.java rename to cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeTable.java index 8d0d1ab4f1..8509108f3d 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/IncludeTable.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/IncludeTable.java @@ -16,20 +16,26 @@ * specific language governing permissions and limitations * under the License. ****************************************************************/ -package org.apache.cayenne.tools.dbimport.config; +package org.apache.cayenne.dbimport; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; import java.util.Collection; import java.util.LinkedList; -import static org.apache.commons.lang.StringUtils.isBlank; import static org.apache.commons.lang.StringUtils.join; /** * @since 4.0. */ +@XmlAccessorType(XmlAccessType.FIELD) public class IncludeTable extends PatternParam { + @XmlElement(name = "includeColumn") private Collection includeColumns = new LinkedList(); + + @XmlElement(name = "excludeColumn") private Collection excludeColumns = new LinkedList(); public IncludeTable() { diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/PatternParam.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/PatternParam.java similarity index 88% rename from cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/PatternParam.java rename to cayenne-server/src/main/java/org/apache/cayenne/dbimport/PatternParam.java index 53b26cca74..9573232a4a 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/PatternParam.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/PatternParam.java @@ -16,13 +16,19 @@ * specific language governing permissions and limitations * under the License. ****************************************************************/ -package org.apache.cayenne.tools.dbimport.config; +package org.apache.cayenne.dbimport; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; /** * @since 4.0. */ +@XmlAccessorType(XmlAccessType.FIELD) public class PatternParam { + @XmlAttribute(name = "pattern") private String pattern; public PatternParam() { diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ReverseEngineering.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ReverseEngineering.java similarity index 54% rename from cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ReverseEngineering.java rename to cayenne-server/src/main/java/org/apache/cayenne/dbimport/ReverseEngineering.java index 07f179536a..7fa0a12ea6 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ReverseEngineering.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ReverseEngineering.java @@ -1,31 +1,50 @@ /***************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. ****************************************************************/ -package org.apache.cayenne.tools.dbimport.config; +package org.apache.cayenne.dbimport; -import java.util.Collection; -import java.util.LinkedList; +import org.apache.cayenne.configuration.ConfigurationNode; +import org.apache.cayenne.configuration.ConfigurationNodeVisitor; +import org.apache.cayenne.resource.Resource; +import org.apache.cayenne.util.XMLEncoder; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.xml.bind.annotation.*; +import java.io.*; +import java.util.*; /** * @since 4.0. */ -public class ReverseEngineering extends FilterContainer { +@XmlRootElement(name = "reverseEngineering") +@XmlAccessorType(XmlAccessType.FIELD) +public class ReverseEngineering extends FilterContainer implements ConfigurationNode, Serializable { + + private static final Log LOG = LogFactory.getLog(ReverseEngineering.class); + + public ReverseEngineering(String name) { + this.name = name; + } + + @XmlTransient + private String name; private Boolean skipRelationshipsLoading; @@ -36,11 +55,21 @@ public class ReverseEngineering extends FilterContainer { * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", * "LOCAL TEMPORARY", "ALIAS", "SYNONYM"., etc. */ + @XmlElement(name = "tableType") private Collection tableTypes = new LinkedList(); + @XmlElement(name = "catalog") private Collection catalogs = new LinkedList(); + + @XmlElement(name = "schema") private Collection schemas = new LinkedList(); + /** + * @since 4.0 + */ + @XmlTransient + protected Resource configurationSource; + public ReverseEngineering() { } @@ -60,6 +89,14 @@ public void setSkipPrimaryKeyLoading(Boolean skipPrimaryKeyLoading) { this.skipPrimaryKeyLoading = skipPrimaryKeyLoading; } + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + public Collection getCatalogs() { return catalogs; } @@ -132,4 +169,28 @@ public String toString() { return super.toString(res, " ").toString(); } + + @Override + public T acceptVisitor(ConfigurationNodeVisitor visitor) { + return visitor.visitReverseEngineering(this); + } + + public void encodeAsXML(XMLEncoder encoder) { + DefaultReverseEngineeringWriter defaultReverseEngineeringWriter = new DefaultReverseEngineeringWriter(); + defaultReverseEngineeringWriter.write(this, encoder.getPrintWriter()); + } + + /** + * @since 4.0 + */ + public Resource getConfigurationSource() { + return configurationSource; + } + + /** + * @since 4.0 + */ + public void setConfigurationSource(Resource configurationSource) { + this.configurationSource = configurationSource; + } } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ReverseEngineeringLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ReverseEngineeringLoader.java new file mode 100644 index 0000000000..b3dbb8d65e --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ReverseEngineeringLoader.java @@ -0,0 +1,36 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.dbimport; + +import org.apache.cayenne.CayenneRuntimeException; +import org.xml.sax.SAXException; + +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +/** + * @since 4.0. + */ +public interface ReverseEngineeringLoader { + + ReverseEngineering load(InputStream inputStream) throws CayenneRuntimeException, SAXException, ParserConfigurationException, IOException, ReverseEngineeringLoaderException; + +} diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ReverseEngineeringLoaderException.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ReverseEngineeringLoaderException.java new file mode 100644 index 0000000000..01e2cb307f --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ReverseEngineeringLoaderException.java @@ -0,0 +1,37 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.dbimport; + +import org.xml.sax.SAXException; + +import javax.xml.parsers.ParserConfigurationException; + +/** + * @since 4.0 + */ +public class ReverseEngineeringLoaderException extends RuntimeException { + + public ReverseEngineeringLoaderException(String message, ParserConfigurationException e) { + super(message, e); + } + + public ReverseEngineeringLoaderException(String message, SAXException e) { + super(message, e); + } +} diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ReverseEngineeringLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ReverseEngineeringWriter.java similarity index 82% rename from cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ReverseEngineeringLoader.java rename to cayenne-server/src/main/java/org/apache/cayenne/dbimport/ReverseEngineeringWriter.java index 241b3d2f90..41b80f6f52 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/ReverseEngineeringLoader.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/ReverseEngineeringWriter.java @@ -16,16 +16,18 @@ * specific language governing permissions and limitations * under the License. ****************************************************************/ -package org.apache.cayenne.tools.dbimport.config; +package org.apache.cayenne.dbimport; import org.apache.cayenne.CayenneRuntimeException; import org.apache.cayenne.resource.Resource; +import java.io.Writer; + /** - * @since 4.0. + * @since 4.0 */ -public interface ReverseEngineeringLoader { +public interface ReverseEngineeringWriter { - ReverseEngineering load(Resource configurationResource) throws CayenneRuntimeException; + Resource write(ReverseEngineering configurationResource, Writer writer) throws CayenneRuntimeException; } diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Schema.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/Schema.java similarity index 87% rename from cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Schema.java rename to cayenne-server/src/main/java/org/apache/cayenne/dbimport/Schema.java index b92cad7e31..8667891eed 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Schema.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/Schema.java @@ -16,13 +16,19 @@ * specific language governing permissions and limitations * under the License. ****************************************************************/ -package org.apache.cayenne.tools.dbimport.config; +package org.apache.cayenne.dbimport; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; /** * @since 4.0. */ +@XmlAccessorType(XmlAccessType.FIELD) public class Schema extends FilterContainer { + @XmlAttribute(name = "name") private String name; public Schema() { diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/DataMap.java b/cayenne-server/src/main/java/org/apache/cayenne/map/DataMap.java index 3d118a1c9c..d05418ce73 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/map/DataMap.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/map/DataMap.java @@ -25,6 +25,7 @@ import org.apache.cayenne.configuration.ConfigurationNode; import org.apache.cayenne.configuration.ConfigurationNodeVisitor; import org.apache.cayenne.configuration.DataChannelDescriptor; +import org.apache.cayenne.dbimport.ReverseEngineering; import org.apache.cayenne.map.event.DbEntityListener; import org.apache.cayenne.map.event.EntityEvent; import org.apache.cayenne.map.event.ObjEntityListener; @@ -146,6 +147,7 @@ public class DataMap implements Serializable, ConfigurationNode, XMLSerializable private SortedMap procedureMap; private SortedMap queryMap; private SortedMap results; + private ReverseEngineering reverseEngineering; /** * @deprecated since 4.0 unused as listeners are no longer tied to a @@ -153,7 +155,7 @@ public class DataMap implements Serializable, ConfigurationNode, XMLSerializable */ private List defaultEntityListeners; - /** + /** * @since 3.1 */ protected Resource configurationSource; @@ -329,6 +331,12 @@ public void encodeAsXML(XMLEncoder encoder) { encoder.printProjectVersion(); encoder.println(">"); + if (reverseEngineering != null) { + encoder.print(""); + } + // properties if (defaultLockType == ObjEntity.LOCK_TYPE_OPTIMISTIC) { encoder.printProperty(DEFAULT_LOCK_TYPE_PROPERTY, "optimistic"); @@ -1401,4 +1409,12 @@ public static String getNameWithPackage(String pack, String name) { public String getNameWithDefaultClientPackage(String name) { return getNameWithPackage(defaultClientPackage, name); } + + public ReverseEngineering getReverseEngineering() { + return reverseEngineering; + } + + public void setReverseEngineering(ReverseEngineering reverseEngineering) { + this.reverseEngineering = reverseEngineering; + } } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/DbEntity.java b/cayenne-server/src/main/java/org/apache/cayenne/map/DbEntity.java index b0ffa5ae9d..376cb07229 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/map/DbEntity.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/map/DbEntity.java @@ -611,9 +611,11 @@ public boolean isFullReplacementIdAttached(ObjectId id) { public Collection mappedObjEntities() { Collection objEntities = new HashSet(); MappingNamespace mns = getDataMap().getNamespace(); - for (ObjEntity objEntity : mns.getObjEntities()) { - if (equals(objEntity.getDbEntity())) { - objEntities.add(objEntity); + if (mns != null) { + for (ObjEntity objEntity : mns.getObjEntities()) { + if (equals(objEntity.getDbEntity())) { + objEntities.add(objEntity); + } } } return objEntities; diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/MapLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/map/MapLoader.java index fa12691fe8..ed687edd14 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/map/MapLoader.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/map/MapLoader.java @@ -24,6 +24,7 @@ import java.util.TreeMap; import org.apache.cayenne.CayenneRuntimeException; +import org.apache.cayenne.dbimport.*; import org.apache.cayenne.dba.TypesMapping; import org.apache.cayenne.exp.Expression; import org.apache.cayenne.util.Util; @@ -44,6 +45,12 @@ public class MapLoader extends DefaultHandler { final static String _2_0_PACKAGE_PREFIX = "org.apache.cayenne."; public static final String DATA_MAP_TAG = "data-map"; + + /** + * @since 4.0 + */ + public static final String REVERSE_ENGINEERING = "reverseEngineering"; + public static final String PROPERTY_TAG = "property"; /** @@ -104,7 +111,6 @@ public class MapLoader extends DefaultHandler { public static final String DB_GENERATOR_TYPE_TAG = "db-generator-type"; public static final String DB_GENERATOR_NAME_TAG = "db-generator-name"; public static final String DB_KEY_CACHE_SIZE_TAG = "db-key-cache-size"; - /** * @since 3.0 */ @@ -145,6 +151,7 @@ public class MapLoader extends DefaultHandler { private Procedure procedure; private QueryLoader queryBuilder; private String sqlKey; + private ReverseEngineering reverseEngineering; private String descending; private String ignoreCase; @@ -169,6 +176,15 @@ void execute(Attributes attributes) throws SAXException { } }); + startTagOpMap.put(REVERSE_ENGINEERING, new StartClosure() { + + @Override + void execute(Attributes attributes) throws SAXException { + processStartReverseEngineering(attributes); + } + }); + + startTagOpMap.put(DB_ENTITY_TAG, new StartClosure() { @Override @@ -561,6 +577,14 @@ void execute() throws SAXException { }); } + private void processStartReverseEngineering(Attributes attributes) { + reverseEngineering = new ReverseEngineering(); + reverseEngineering.setName(attributes.getValue("", "name")); + + dataMap.setReverseEngineering(reverseEngineering); + } + + private void processStartDataMap(Attributes attributes) { this.mapVersion = attributes.getValue("", "project-version"); } @@ -880,7 +904,6 @@ private void processStartDbRelationship(Attributes atts) throws SAXException { throw new SAXException("MapLoader::processStartDbRelationship()," + " Unable to parse name. Attributes:\n" + printAttributes(atts)); } - String sourceName = atts.getValue("", "source"); if (sourceName == null) { throw new SAXException("MapLoader::processStartDbRelationship() - null source entity"); diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/naming/NameCheckers.java b/cayenne-server/src/main/java/org/apache/cayenne/map/naming/NameCheckers.java index eb7fb370ae..7a7ebfb415 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/map/naming/NameCheckers.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/map/naming/NameCheckers.java @@ -21,6 +21,7 @@ import org.apache.cayenne.access.DataDomain; import org.apache.cayenne.configuration.DataChannelDescriptor; +import org.apache.cayenne.configuration.DataNodeDescriptor; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.map.Embeddable; import org.apache.cayenne.map.Entity; @@ -46,16 +47,16 @@ public boolean isNameInUse(Object namingContext, String name) { public boolean isNameInUse(Object namingContext, String name) { // null context is a situation when DataMap is a // top level object of the project - if (namingContext == null) { + if(namingContext == null) { return false; } - if (namingContext instanceof DataDomain) { + if(namingContext instanceof DataDomain) { DataDomain domain = (DataDomain) namingContext; return domain.getDataMap(name) != null; } - if (namingContext instanceof DataChannelDescriptor) { + if(namingContext instanceof DataChannelDescriptor) { DataChannelDescriptor domain = (DataChannelDescriptor) namingContext; return domain.getDataMap(name) != null; } @@ -63,6 +64,23 @@ public boolean isNameInUse(Object namingContext, String name) { } }, + reverseEngineering("reverseEngineering") { + @Override + public boolean isNameInUse(Object namingContext, String name) { + if(namingContext == null) { + return false; + } + + for (DataMap dataMap : ((DataChannelDescriptor) namingContext).getDataMaps()) { + if(dataMap!= null && dataMap.getReverseEngineering() != null && + dataMap.getReverseEngineering().getName()!=null && dataMap.getReverseEngineering().getName().equals(name)) { + return true; + } + } + return false; + } + }, + objEntity("ObjEntity") { @Override public boolean isNameInUse(Object namingContext, String name) { @@ -75,7 +93,7 @@ public boolean isNameInUse(Object namingContext, String name) { @Override public boolean isNameInUse(Object namingContext, String name) { DataMap map = (DataMap) namingContext; - return map.getEmbeddable(map.getNameWithDefaultPackage(name)) != null; + return map.getEmbeddable(map.getNameWithDefaultPackage(name)) != null; } }, @@ -105,7 +123,7 @@ public boolean isNameInUse(Object namingContext, String name) { Procedure procedure = (Procedure) namingContext; for (final ProcedureParameter parameter : procedure .getCallParameters()) { - if (name.equals(parameter.getName())) { + if(name.equals(parameter.getName())) { return true; } } @@ -150,9 +168,9 @@ public boolean isNameInUse(Object namingContext, String name) { @Override public boolean isNameInUse(Object namingContext, String name) { DataChannelDescriptor domain = (DataChannelDescriptor) namingContext; - for (org.apache.cayenne.configuration.DataNodeDescriptor dataNodeDescriptor : domain + for (DataNodeDescriptor dataNodeDescriptor : domain .getNodeDescriptors()) { - if (dataNodeDescriptor.getName().equals(name)) { + if(dataNodeDescriptor.getName().equals(name)) { return true; } } @@ -166,7 +184,7 @@ public boolean isNameInUse(Object namingContext, String name) { ObjEntity ent = (ObjEntity) namingContext; return dbAttribute.isNameInUse(namingContext, name) || ent.getCallbackMethods().contains( - "get" + StringUtils.capitalize(name)); + "get" + StringUtils.capitalize(name)); } }, @@ -184,7 +202,7 @@ public boolean isNameInUse(Object namingContext, String name) { return name.startsWith("get") && dbAttribute.isNameInUse(namingContext, - StringUtils.uncapitalize(name.substring(3))) + StringUtils.uncapitalize(name.substring(3))) || ent.getCallbackMethods().contains(name); } }; diff --git a/cayenne-server/src/main/java/org/apache/cayenne/resource/Resource.java b/cayenne-server/src/main/java/org/apache/cayenne/resource/Resource.java index deb42f665e..8571475084 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/resource/Resource.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/resource/Resource.java @@ -26,6 +26,7 @@ * * @since 3.1 */ + public interface Resource extends Serializable { /** diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/config/DefaultReverseEngineeringLoaderTest.java b/cayenne-server/src/test/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringLoaderTest.java similarity index 95% rename from cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/config/DefaultReverseEngineeringLoaderTest.java rename to cayenne-server/src/test/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringLoaderTest.java index 52c21bdbd7..4dcc690b1a 100644 --- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/config/DefaultReverseEngineeringLoaderTest.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringLoaderTest.java @@ -16,8 +16,8 @@ * specific language governing permissions and limitations * under the License. */ +package org.apache.cayenne.dbimport; -package org.apache.cayenne.tools.dbimport.config; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -27,7 +27,6 @@ import java.util.Iterator; import org.apache.cayenne.resource.URLResource; -import org.apache.cayenne.tools.ExcludeTable; import org.junit.Test; public class DefaultReverseEngineeringLoaderTest { @@ -35,7 +34,7 @@ public class DefaultReverseEngineeringLoaderTest { @Test public void testLoadCatalog() throws Exception { ReverseEngineering engineering = new DefaultReverseEngineeringLoader() - .load(getResource("reverseEngineering-catalog.xml")); + .load(getResource("reverseEngineering-catalog.xml").getURL().openStream()); assertCatalog(engineering); } @@ -88,7 +87,7 @@ public static void assertCatalog(Iterator catalogs) { @Test public void testLoadSchema() throws Exception { ReverseEngineering engineering = new DefaultReverseEngineeringLoader() - .load(getResource("reverseEngineering-schema.xml")); + .load(getResource("reverseEngineering-schema.xml").getURL().openStream()); assertSchema(engineering); } @@ -141,7 +140,7 @@ public static void assertSchemaContent(Schema schema) { @Test public void testLoadCatalogAndSchema() throws Exception { ReverseEngineering engineering = new DefaultReverseEngineeringLoader() - .load(getResource("reverseEngineering-catalog-and-schema.xml")); + .load(getResource("reverseEngineering-catalog-and-schema.xml").getURL().openStream()); assertCatalogAndSchema(engineering); } @@ -159,7 +158,7 @@ public static void assertCatalogAndSchema(ReverseEngineering engineering) { @Test public void testLoadFlat() throws Exception { ReverseEngineering engineering = new DefaultReverseEngineeringLoader() - .load(getResource("reverseEngineering-flat.xml")); + .load(getResource("reverseEngineering-flat.xml").getURL().openStream()); assertFlat(engineering); } @@ -201,7 +200,7 @@ public static void assertFlat(ReverseEngineering engineering) { @Test public void testSkipRelationships() throws Exception { ReverseEngineering engineering = new DefaultReverseEngineeringLoader() - .load(getResource("reverseEngineering-skipRelationshipsLoading.xml")); + .load(getResource("reverseEngineering-skipRelationshipsLoading.xml").getURL().openStream()); assertSkipRelationshipsLoading(engineering); } @@ -213,7 +212,7 @@ public static void assertSkipRelationshipsLoading(ReverseEngineering engineering @Test public void testSkipPrimaryKeyLoading() throws Exception { ReverseEngineering engineering = new DefaultReverseEngineeringLoader() - .load(getResource("reverseEngineering-skipPrimaryKeyLoading.xml")); + .load(getResource("reverseEngineering-skipPrimaryKeyLoading.xml").getURL().openStream()); assertSkipPrimaryKeyLoading(engineering); } @@ -225,7 +224,7 @@ public static void assertSkipPrimaryKeyLoading(ReverseEngineering engineering) { @Test public void testTableTypes() throws Exception { ReverseEngineering engineering = new DefaultReverseEngineeringLoader() - .load(getResource("reverseEngineering-tableTypes.xml")); + .load(getResource("reverseEngineering-tableTypes.xml").getURL().openStream()); assertTableTypes(engineering); } @@ -238,4 +237,4 @@ protected URLResource getResource(String file) throws MalformedURLException { return new URLResource(getClass().getResource(file)); } -} \ No newline at end of file +} diff --git a/cayenne-server/src/test/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringWriterTest.java b/cayenne-server/src/test/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringWriterTest.java new file mode 100644 index 0000000000..e028431950 --- /dev/null +++ b/cayenne-server/src/test/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringWriterTest.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cayenne.dbimport; + +import org.apache.cayenne.CayenneRuntimeException; +import org.apache.cayenne.resource.Resource; +import org.apache.cayenne.resource.URLResource; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.custommonkey.xmlunit.DetailedDiff; +import org.custommonkey.xmlunit.Diff; +import org.custommonkey.xmlunit.Difference; +import org.junit.Test; +import org.xml.sax.SAXException; +import sun.security.util.Resources; + +import javax.xml.bind.JAXBException; +import java.io.*; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; + +import static org.junit.Assert.assertTrue; + +/* + * @since 4.0 + */ + +public class DefaultReverseEngineeringWriterTest { + + @Test + public void testWriteReverseEngineering() throws Exception { + ReverseEngineeringWriter engineering = new DefaultReverseEngineeringWriter(); + ReverseEngineering reverseEngineering = new ReverseEngineering(); + Resource resource = getResource("reverseEngineering.xml"); + reverseEngineering.setConfigurationSource(resource); + + Catalog catalog1 = new Catalog("catalog1"); + Catalog catalog2 = new Catalog("catalog2"); + Catalog catalog3 = new Catalog("catalog3"); + + catalog1.addSchema(new Schema("schema1")); + catalog1.addSchema(new Schema("schema2")); + + catalog1.addExcludeColumn(new ExcludeColumn("excludedColumn1")); + catalog1.addExcludeColumn(new ExcludeColumn("excludedColumn2")); + catalog1.addIncludeColumn(new IncludeColumn("includedColumn1")); + catalog1.addIncludeColumn(new IncludeColumn("includedColumn2")); + + catalog1.addExcludeProcedure(new ExcludeProcedure("excludedProcedure1")); + catalog1.addExcludeProcedure(new ExcludeProcedure("excludedProcedure2")); + catalog1.addIncludeProcedure(new IncludeProcedure("includedProcedure1")); + catalog1.addIncludeProcedure(new IncludeProcedure("includedProcedure2")); + + catalog1.addExcludeTable(new ExcludeTable("excludedTable1")); + catalog1.addExcludeTable(new ExcludeTable("excludedTable2")); + catalog1.addIncludeTable(new IncludeTable("includedTable1")); + catalog1.addIncludeTable(new IncludeTable("includedTable2")); + + reverseEngineering.addCatalog(catalog1); + reverseEngineering.addCatalog(catalog2); + reverseEngineering.addCatalog(catalog3); + + reverseEngineering.addSchema(new Schema("schema3")); + + File file = new File(resource.getURL().getPath()); + PrintWriter printWriter = new PrintWriter(new FileWriter(file)); + + assertReverseEngineering(engineering.write(reverseEngineering, printWriter)); + } + + public void assertReverseEngineering(Resource resource) throws Exception { + URL url1 = resource.getURL(); + URL url2 = getResource("reverseEngineering-expected.xml").getURL(); + + FileReader writedXML; + FileReader expectedXML; + writedXML = new FileReader(url1.getPath()); + expectedXML = new FileReader(url2.getPath()); + Diff diff = new Diff(writedXML, expectedXML); + assertTrue(diff.identical()); + } + + protected URLResource getResource(String file) throws MalformedURLException { + return new URLResource(getClass().getResource(file)); + } +} diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/config/FiltersConfigBuilderTest.java b/cayenne-server/src/test/java/org/apache/cayenne/dbimport/FiltersConfigBuilderTest.java similarity index 99% rename from cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/config/FiltersConfigBuilderTest.java rename to cayenne-server/src/test/java/org/apache/cayenne/dbimport/FiltersConfigBuilderTest.java index e3086a784b..9a9461807a 100644 --- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/config/FiltersConfigBuilderTest.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/dbimport/FiltersConfigBuilderTest.java @@ -17,9 +17,8 @@ * under the License. */ -package org.apache.cayenne.tools.dbimport.config; +package org.apache.cayenne.dbimport; -import org.apache.cayenne.tools.ExcludeTable; import org.junit.Test; import static org.junit.Assert.assertEquals; diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java index abe2a2eeff..ebdc301848 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java @@ -220,12 +220,9 @@ public void configure(Binder binder) { // test-scoped objects binder.bind(EntityResolver.class).toProvider( ServerCaseEntityResolverProvider.class).in(testScope); - binder.bind(DataNode.class).toProvider(ServerCaseDataNodeProvider.class).in( - testScope); - binder.bind(ServerCaseProperties.class).to(ServerCaseProperties.class).in( - testScope); - binder.bind(ServerRuntime.class).toProvider(ServerRuntimeProvider.class).in( - testScope); + binder.bind(DataNode.class).toProvider(ServerCaseDataNodeProvider.class).in(testScope); + binder.bind(ServerCaseProperties.class).to(ServerCaseProperties.class).in(testScope); + binder.bind(ServerRuntime.class).toProvider(ServerRuntimeProvider.class).in(testScope); binder .bind(ObjectContext.class) .toProvider(ServerCaseObjectContextProvider.class) diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-ant-mapping.xml b/cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-ant-mapping.xml similarity index 100% rename from cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-ant-mapping.xml rename to cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-ant-mapping.xml diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-catalog-and-schema.xml b/cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-catalog-and-schema.xml similarity index 100% rename from cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-catalog-and-schema.xml rename to cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-catalog-and-schema.xml diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-catalog.xml b/cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-catalog.xml similarity index 100% rename from cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-catalog.xml rename to cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-catalog.xml diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-expected.xml b/cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-expected.xml new file mode 100644 index 0000000000..4f3f928090 --- /dev/null +++ b/cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-expected.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-flat.xml b/cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-flat.xml similarity index 100% rename from cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-flat.xml rename to cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-flat.xml diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-maven-mapping.xml b/cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-maven-mapping.xml similarity index 100% rename from cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-maven-mapping.xml rename to cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-maven-mapping.xml diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-mixed-mapping.xml b/cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-mixed-mapping.xml similarity index 100% rename from cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-mixed-mapping.xml rename to cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-mixed-mapping.xml diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-schema.xml b/cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-schema.xml similarity index 100% rename from cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-schema.xml rename to cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-schema.xml diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-skipPrimaryKeyLoading.xml b/cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-skipPrimaryKeyLoading.xml similarity index 100% rename from cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-skipPrimaryKeyLoading.xml rename to cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-skipPrimaryKeyLoading.xml diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-skipRelationshipsLoading.xml b/cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-skipRelationshipsLoading.xml similarity index 100% rename from cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-skipRelationshipsLoading.xml rename to cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-skipRelationshipsLoading.xml diff --git a/cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-tableTypes.xml b/cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-tableTypes.xml similarity index 100% rename from cayenne-tools/src/test/resources/org/apache/cayenne/tools/dbimport/config/reverseEngineering-tableTypes.xml rename to cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering-tableTypes.xml diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering.xml b/cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering.xml new file mode 100644 index 0000000000..d6535640e8 --- /dev/null +++ b/cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cayenne-tools/pom.xml b/cayenne-tools/pom.xml index a759107c6f..6d4b1f61f9 100644 --- a/cayenne-tools/pom.xml +++ b/cayenne-tools/pom.xml @@ -113,7 +113,6 @@ xmlunit test - diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java index ebbb7e8f5e..36fe7f1d06 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java +++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java @@ -26,6 +26,17 @@ import org.apache.cayenne.configuration.server.DbAdapterFactory; import org.apache.cayenne.conn.DataSourceInfo; import org.apache.cayenne.dba.DbAdapter; +import org.apache.cayenne.dbimport.AntNestedElement; +import org.apache.cayenne.dbimport.Catalog; +import org.apache.cayenne.dbimport.ExcludeColumn; +import org.apache.cayenne.dbimport.ExcludeProcedure; +import org.apache.cayenne.dbimport.ExcludeTable; +import org.apache.cayenne.dbimport.FiltersConfigBuilder; +import org.apache.cayenne.dbimport.IncludeColumn; +import org.apache.cayenne.dbimport.IncludeProcedure; +import org.apache.cayenne.dbimport.IncludeTable; +import org.apache.cayenne.dbimport.ReverseEngineering; +import org.apache.cayenne.dbimport.Schema; import org.apache.cayenne.di.DIBootstrap; import org.apache.cayenne.di.Injector; import org.apache.cayenne.map.naming.DefaultNameGenerator; @@ -33,16 +44,6 @@ import org.apache.cayenne.tools.dbimport.DbImportAction; import org.apache.cayenne.tools.dbimport.DbImportConfiguration; import org.apache.cayenne.tools.dbimport.DbImportModule; -import org.apache.cayenne.tools.dbimport.config.AntNestedElement; -import org.apache.cayenne.tools.dbimport.config.Catalog; -import org.apache.cayenne.tools.dbimport.config.ExcludeColumn; -import org.apache.cayenne.tools.dbimport.config.ExcludeProcedure; -import org.apache.cayenne.tools.dbimport.config.FiltersConfigBuilder; -import org.apache.cayenne.tools.dbimport.config.IncludeColumn; -import org.apache.cayenne.tools.dbimport.config.IncludeProcedure; -import org.apache.cayenne.tools.dbimport.config.IncludeTable; -import org.apache.cayenne.tools.dbimport.config.ReverseEngineering; -import org.apache.cayenne.tools.dbimport.config.Schema; import org.apache.cayenne.util.Util; import org.apache.commons.logging.Log; import org.apache.tools.ant.BuildException; diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java index 2683d978e2..60813d7ac7 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java +++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java @@ -60,215 +60,15 @@ import org.apache.cayenne.validation.ValidationFailure; import org.apache.cayenne.validation.ValidationResult; import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.xml.sax.InputSource; /** * A thin wrapper around {@link DbLoader} that encapsulates DB import logic for * the benefit of Ant and Maven db importers. - * + * * @since 4.0 */ -public class DbImportAction { - - private final ProjectSaver projectSaver; - private final Log logger; - private final DataSourceFactory dataSourceFactory; - private final DbAdapterFactory adapterFactory; - private final MapLoader mapLoader; - - public DbImportAction(@Inject Log logger, @Inject ProjectSaver projectSaver, - @Inject DataSourceFactory dataSourceFactory, @Inject DbAdapterFactory adapterFactory, - @Inject MapLoader mapLoader) { - this.logger = logger; - this.projectSaver = projectSaver; - this.dataSourceFactory = dataSourceFactory; - this.adapterFactory = adapterFactory; - this.mapLoader = mapLoader; - } - - public void execute(DbImportConfiguration config) throws Exception { - - if (logger.isDebugEnabled()) { - logger.debug("DB connection: " + config.getDataSourceInfo()); - } - - if (logger.isDebugEnabled()) { - logger.debug(config); - } - - DataNodeDescriptor dataNodeDescriptor = config.createDataNodeDescriptor(); - DataSource dataSource = dataSourceFactory.getDataSource(dataNodeDescriptor); - DbAdapter adapter = adapterFactory.createAdapter(dataNodeDescriptor, dataSource); - - DataMap loadedFomDb; - try (Connection c = dataSource.getConnection()) { - loadedFomDb = load(config, adapter, c); - } - - if (loadedFomDb == null) { - logger.info("Nothing was loaded from db."); - return; - } - - DataMap existing = loadExistingDataMap(config.getDataMapFile()); - if (existing == null) { - logger.info(""); - File file = config.getDataMapFile(); - logger.info("Map file does not exist. Loaded db model will be saved into '" - + (file == null ? "null" : file.getAbsolutePath() + "'")); - - saveLoaded(config.initializeDataMap(loadedFomDb)); - } else { - MergerFactory mergerFactory = adapter.mergerFactory(); - - List mergeTokens = new DbMerger(mergerFactory).createMergeTokens(existing, loadedFomDb, - config.getDbLoaderConfig()); - if (mergeTokens.isEmpty()) { - logger.info(""); - logger.info("Detected changes: No changes to import."); - return; - } - - if (!isBlank(config.getDefaultPackage())) { - existing.setDefaultPackage(config.getDefaultPackage()); - } - - final Collection loadedObjEntities = new LinkedList(); - DataMap executed = execute(new ProxyModelMergeDelegate(config.createMergeDelegate()) { - @Override - public void objEntityAdded(ObjEntity ent) { - loadedObjEntities.add(ent); - - super.objEntityAdded(ent); - } - - }, existing, log(sort(reverse(mergerFactory, mergeTokens)))); - - DbLoader.flattenManyToManyRelationships(executed, loadedObjEntities, config.getNameGenerator()); - - relationshipsSanity(executed); - - saveLoaded(executed); - } - } - - private void relationshipsSanity(DataMap executed) { - for (ObjEntity objEntity : executed.getObjEntities()) { - - List rels = new LinkedList(objEntity.getRelationships()); - for (ObjRelationship rel : rels) { - if (rel.getSourceEntity() == null || rel.getTargetEntity() == null) { - logger.error("Incorrect obj relationship source or target entity is null: " + rel); - - objEntity.removeRelationship(rel.getName()); - } - } - } - } - - protected static List sort(List reverse) { - Collections.sort(reverse, new Comparator() { - @Override - public int compare(MergerToken o1, MergerToken o2) { - if (o1 instanceof AddRelationshipToDb && o2 instanceof AddRelationshipToDb) { - return 0; - } - - if (!(o1 instanceof AddRelationshipToDb || o2 instanceof AddRelationshipToDb)) { - return o1.getClass().getSimpleName().compareTo(o2.getClass().getSimpleName()); - } - - return o1 instanceof AddRelationshipToDb ? 1 : -1; - } - }); - - return reverse; - } - - private Collection log(List tokens) { - logger.info(""); - if (tokens.isEmpty()) { - logger.info("Detected changes: No changes to import."); - return tokens; - } - - logger.info("Detected changes: "); - for (MergerToken token : tokens) { - logger.info(String.format(" %-20s %s", token.getTokenName(), token.getTokenValue())); - } - logger.info(""); - - return tokens; - } - - private DataMap loadExistingDataMap(File dataMapFile) throws IOException { - if (dataMapFile != null && dataMapFile.exists() && dataMapFile.canRead()) { - DataMap dataMap = mapLoader.loadDataMap(new InputSource(dataMapFile.getCanonicalPath())); - dataMap.setNamespace(new EntityResolver(Collections.singleton(dataMap))); - dataMap.setConfigurationSource(new URLResource(dataMapFile.toURI().toURL())); - - return dataMap; - } - - return null; - } - - private List reverse(MergerFactory mergerFactory, Iterable mergeTokens) - throws IOException { - List tokens = new LinkedList(); - for (MergerToken token : mergeTokens) { - if (token instanceof AbstractToModelToken) { - continue; - } - tokens.add(token.createReverse(mergerFactory)); - } - return tokens; - } - - /** - * Performs configured schema operations via DbGenerator. - */ - private DataMap execute(ModelMergeDelegate mergeDelegate, DataMap dataMap, Collection tokens) { - MergerContext mergerContext = new ExecutingMergerContext(dataMap, null, null, mergeDelegate); - - for (MergerToken tok : tokens) { - try { - tok.execute(mergerContext); - } catch (Throwable th) { - String message = "Migration Error. Can't apply changes from token: " + tok.getTokenName() + " (" - + tok.getTokenValue() + ")"; - - logger.error(message, th); - mergerContext.getValidationResult().addFailure(new SimpleValidationFailure(th, message)); - } - } - - ValidationResult failures = mergerContext.getValidationResult(); - if (failures == null || !failures.hasFailures()) { - logger.info("Migration Complete Successfully."); - } else { - logger.info("Migration Complete."); - logger.warn("Migration finished. The following problem(s) were ignored."); - for (ValidationFailure failure : failures.getFailures()) { - logger.warn(failure.toString()); - } - } - - return dataMap; - } - - void saveLoaded(DataMap dataMap) throws FileNotFoundException { - ConfigurationTree projectRoot = new ConfigurationTree(dataMap); - Project project = new Project(projectRoot); - projectSaver.save(project); - } - - private DataMap load(DbImportConfiguration config, DbAdapter adapter, Connection connection) throws Exception { - DataMap dataMap = config.createDataMap(); - - DbLoader loader = config.createLoader(adapter, connection, config.createLoaderDelegate()); - loader.load(dataMap, config.getDbLoaderConfig()); - - return dataMap; - } +public interface DbImportAction { + void execute(DbImportConfiguration config) throws Exception; } diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportActionDefault.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportActionDefault.java new file mode 100644 index 0000000000..aa58e56c05 --- /dev/null +++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportActionDefault.java @@ -0,0 +1,281 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cayenne.tools.dbimport; + +import org.apache.cayenne.access.DbLoader; +import org.apache.cayenne.configuration.ConfigurationTree; +import org.apache.cayenne.configuration.DataNodeDescriptor; +import org.apache.cayenne.configuration.server.DataSourceFactory; +import org.apache.cayenne.configuration.server.DbAdapterFactory; +import org.apache.cayenne.dba.DbAdapter; +import org.apache.cayenne.di.Inject; +import org.apache.cayenne.map.DataMap; +import org.apache.cayenne.map.EntityResolver; +import org.apache.cayenne.map.MapLoader; +import org.apache.cayenne.map.ObjEntity; +import org.apache.cayenne.map.ObjRelationship; +import org.apache.cayenne.merge.AbstractToModelToken; +import org.apache.cayenne.merge.AddRelationshipToDb; +import org.apache.cayenne.merge.DbMerger; +import org.apache.cayenne.merge.ExecutingMergerContext; +import org.apache.cayenne.merge.MergerContext; +import org.apache.cayenne.merge.MergerFactory; +import org.apache.cayenne.merge.MergerToken; +import org.apache.cayenne.merge.ModelMergeDelegate; +import org.apache.cayenne.merge.ProxyModelMergeDelegate; +import org.apache.cayenne.project.Project; +import org.apache.cayenne.project.ProjectSaver; +import org.apache.cayenne.resource.URLResource; +import org.apache.cayenne.validation.SimpleValidationFailure; +import org.apache.cayenne.validation.ValidationFailure; +import org.apache.cayenne.validation.ValidationResult; +import org.apache.commons.logging.Log; +import org.xml.sax.InputSource; + +import javax.sql.DataSource; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.sql.Connection; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedList; +import java.util.List; + +import static org.apache.commons.lang.StringUtils.isBlank; + +/** + * A thin wrapper around {@link DbLoader} that encapsulates DB import logic for + * the benefit of Ant and Maven db importers. + * + * @since 4.0 + */ +public class DbImportActionDefault implements DbImportAction { + + private final ProjectSaver projectSaver; + private final Log logger; + private final DataSourceFactory dataSourceFactory; + private final DbAdapterFactory adapterFactory; + private final MapLoader mapLoader; + + public DbImportActionDefault(@Inject Log logger, + @Inject ProjectSaver projectSaver, + @Inject DataSourceFactory dataSourceFactory, + @Inject DbAdapterFactory adapterFactory, + @Inject MapLoader mapLoader) { + this.logger = logger; + this.projectSaver = projectSaver; + this.dataSourceFactory = dataSourceFactory; + this.adapterFactory = adapterFactory; + this.mapLoader = mapLoader; + } + + public void execute(DbImportConfiguration config) throws Exception { + + if (logger.isDebugEnabled()) { + logger.debug("DB connection: " + config.getDataSourceInfo()); + } + + if (logger.isDebugEnabled()) { + logger.debug(config); + } + + DataNodeDescriptor dataNodeDescriptor = config.createDataNodeDescriptor(); + DataSource dataSource = dataSourceFactory.getDataSource(dataNodeDescriptor); + DbAdapter adapter = adapterFactory.createAdapter(dataNodeDescriptor, dataSource); + + DataMap loadedFomDb = load(config, adapter, dataSource.getConnection()); + if (loadedFomDb == null) { + logger.info("Nothing was loaded from db."); + return; + } + + DataMap existing = loadExistingDataMap(config.getDataMapFile()); + if (existing == null) { + logger.info(""); + File file = config.getDataMapFile(); + logger.info("Map file does not exist. Loaded db model will be saved into '" + + (file == null ? "null" : file.getAbsolutePath() + "'")); + + saveLoaded(config.initializeDataMap(loadedFomDb)); + } else { + MergerFactory mergerFactory = adapter.mergerFactory(); + + List mergeTokens = new DbMerger(mergerFactory) + .createMergeTokens(existing, loadedFomDb, config.getDbLoaderConfig()); + if (mergeTokens.isEmpty()) { + logger.info(""); + logger.info("Detected changes: No changes to import."); + return; + } + + if (!isBlank(config.getDefaultPackage())) { + existing.setDefaultPackage(config.getDefaultPackage()); + } + + final Collection loadedObjEntities = new LinkedList<>(); + DataMap executed = execute(new ProxyModelMergeDelegate(config.createMergeDelegate()) { + @Override + public void objEntityAdded(ObjEntity ent) { + loadedObjEntities.add(ent); + + super.objEntityAdded(ent); + } + + }, existing, log(sort(reverse(mergerFactory, mergeTokens)))); + + DbLoader.flattenManyToManyRelationships(executed, loadedObjEntities, config.getNameGenerator()); + + relationshipsSanity(executed); + + + saveLoaded(executed); + } + } + + private void relationshipsSanity(DataMap executed) { + for (ObjEntity objEntity : executed.getObjEntities()) { + List rels = new LinkedList<>(objEntity.getRelationships()); + for (ObjRelationship rel : rels) { + if (rel.getSourceEntity() == null || rel.getTargetEntity() == null) { + logger.error("Incorrect obj relationship source or target entity is null: " + rel); + + objEntity.removeRelationship(rel.getName()); + } + } + } + } + + protected static List sort(List reverse) { + Collections.sort(reverse, new Comparator() { + @Override + public int compare(MergerToken o1, MergerToken o2) { + if (o1 instanceof AddRelationshipToDb && o2 instanceof AddRelationshipToDb) { + return 0; + } + + if (!(o1 instanceof AddRelationshipToDb || o2 instanceof AddRelationshipToDb)) { + return o1.getClass().getSimpleName().compareTo(o2.getClass().getSimpleName()); + } + + return o1 instanceof AddRelationshipToDb ? 1 : -1; + } + }); + + return reverse; + } + + private Collection log(List tokens) { + logger.info(""); + if (tokens.isEmpty()) { + logger.info("Detected changes: No changes to import."); + return tokens; + } + + logger.info("Detected changes: "); + for (MergerToken token : tokens) { + logger.info(String.format(" %-20s %s", token.getTokenName(), token.getTokenValue())); + } + logger.info(""); + + return tokens; + } + + protected DataMap loadExistingDataMap(File dataMapFile) throws IOException { + if (dataMapFile != null && dataMapFile.exists() && dataMapFile.canRead()) { + DataMap dataMap = mapLoader.loadDataMap(new InputSource(dataMapFile.getCanonicalPath())); + dataMap.setNamespace(new EntityResolver(Collections.singleton(dataMap))); + dataMap.setConfigurationSource(new URLResource(dataMapFile.toURI().toURL())); + + return dataMap; + } + + return null; + } + + private List reverse(MergerFactory mergerFactory, Iterable mergeTokens) throws IOException { + List tokens = new LinkedList<>(); + for (MergerToken token : mergeTokens) { + if (token instanceof AbstractToModelToken) { + continue; + } + tokens.add(token.createReverse(mergerFactory)); + } + return tokens; + } + + /** + * Performs configured schema operations via DbGenerator. + */ + private DataMap execute(ModelMergeDelegate mergeDelegate, DataMap dataMap, Collection tokens) { + MergerContext mergerContext = new ExecutingMergerContext( + dataMap, null, null, mergeDelegate); + + for (MergerToken tok : tokens) { + try { + tok.execute(mergerContext); + } catch (Throwable th) { + String message = "Migration Error. Can't apply changes from token: " + tok.getTokenName() + + " (" + tok.getTokenValue() + ")"; + + logger.error(message, th); + mergerContext.getValidationResult().addFailure(new SimpleValidationFailure(th, message)); + } + } + + ValidationResult failures = mergerContext.getValidationResult(); + if (failures == null || !failures.hasFailures()) { + logger.info("Migration Complete Successfully."); + } else { + logger.info("Migration Complete."); + logger.warn("Migration finished. The following problem(s) were ignored."); + for (ValidationFailure failure : failures.getFailures()) { + logger.warn(failure.toString()); + } + } + + return dataMap; + } + + private DbLoader getLoader(DbImportConfiguration config, DbAdapter adapter, Connection connection) throws InstantiationException, IllegalAccessException, ClassNotFoundException { + return config.createLoader(adapter, connection, config.createLoaderDelegate()); + } + + protected void saveLoaded(DataMap dataMap) throws FileNotFoundException { + ConfigurationTree projectRoot = new ConfigurationTree<>(dataMap); + Project project = new Project(projectRoot); + projectSaver.save(project); + } + + protected DataMap load(DbImportConfiguration config, DbAdapter adapter, Connection connection) throws Exception { + DataMap dataMap = config.createDataMap(); + + try { + DbLoader loader = config.createLoader(adapter, connection, config.createLoaderDelegate()); + loader.load(dataMap, config.getDbLoaderConfig()); + } finally { + if (connection != null) { + connection.close(); + } + } + + return dataMap; + } +} \ No newline at end of file diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportModule.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportModule.java index f99a1b2a09..1b4505a65c 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportModule.java +++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportModule.java @@ -19,9 +19,7 @@ package org.apache.cayenne.tools.dbimport; import org.apache.cayenne.configuration.ConfigurationNameMapper; -import org.apache.cayenne.configuration.DataMapLoader; import org.apache.cayenne.configuration.DefaultConfigurationNameMapper; -import org.apache.cayenne.configuration.XMLDataMapLoader; import org.apache.cayenne.di.Binder; import org.apache.cayenne.di.Module; import org.apache.cayenne.map.MapLoader; @@ -38,7 +36,7 @@ public class DbImportModule implements Module { public void configure(Binder binder) { - binder.bind(DbImportAction.class).to(DbImportAction.class); + binder.bind(DbImportAction.class).to(DbImportActionDefault.class); binder.bind(ProjectSaver.class).to(FileProjectSaver.class); binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class); binder.bind(MapLoader.class).to(MapLoader.class); diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Type.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Type.java index fa7413fcbc..b995c62482 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Type.java +++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/Type.java @@ -20,17 +20,32 @@ import org.apache.cayenne.util.ToStringBuilder; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; + /** * @since 4.0. */ +@XmlAccessorType(XmlAccessType.FIELD) public class Type { + @XmlElement(name = "jdbc") private String jdbc; + + @XmlElement(name = "java") private String java; + @XmlElement(name = "length") private Integer length; + + @XmlElement(name = "precision") private Integer precision; + + @XmlElement(name = "scale") private Integer scale; + + @XmlElement(name = "notNull") private Boolean notNull; public String getJdbc() { diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/TypeMapper.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/TypeMapper.java index c83215e5a7..048c753d48 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/TypeMapper.java +++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/TypeMapper.java @@ -21,18 +21,24 @@ import org.apache.cayenne.util.EqualsBuilder; import org.apache.cayenne.util.HashCodeBuilder; +import javax.xml.bind.annotation.*; import java.util.Collection; import java.util.LinkedList; /** * @since 4.0. */ +@XmlRootElement(name = "typeMapper") +@XmlAccessorType(XmlAccessType.FIELD) public class TypeMapper { + @XmlElement(name = "mapperClassName") private String mapperClassName; + @XmlElement(name = "usePrimitives") private Boolean usePrimitives; + @XmlElement(name = "type") private Collection types = new LinkedList(); public String getMapperClassName() { diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/AntDataPortDelegateTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/AntDataPortDelegateTest.java index 584d4c8b55..2cf0dd9589 100644 --- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/AntDataPortDelegateTest.java +++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/AntDataPortDelegateTest.java @@ -43,11 +43,11 @@ public void testPassedDataMapFilter() { assertTrue(delegate.passedDataMapFilter(map)); delegate.mapFilters = new Pattern[] { - Pattern.compile("B") + Pattern.compile("B") }; assertFalse(delegate.passedDataMapFilter(map)); map.setName("BBBB"); assertTrue(delegate.passedDataMapFilter(map)); } -} +} \ No newline at end of file diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/CayenneGeneratorTaskCrossMapRelationshipsTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/CayenneGeneratorTaskCrossMapRelationshipsTest.java index 40877b8bd5..182b4395d6 100644 --- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/CayenneGeneratorTaskCrossMapRelationshipsTest.java +++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/CayenneGeneratorTaskCrossMapRelationshipsTest.java @@ -38,120 +38,120 @@ public class CayenneGeneratorTaskCrossMapRelationshipsTest { - /** - * Tests pairs generation with a cross-DataMap relationship. - */ - @Test - public void testCrossDataMapRelationships() throws Exception { - - CayenneGeneratorTask task = new CayenneGeneratorTask(); - task.setProject(new Project()); - task.setTaskName("Test"); - task.setLocation(Location.UNKNOWN_LOCATION); - - // prepare destination directory - - File destDir = new File(FileUtil.baseTestDirectory(), "cgen12"); - // prepare destination directory - if (!destDir.exists()) { - assertTrue(destDir.mkdirs()); - } - - File map = new File(destDir, "cgen-dependent.map.xml"); - ResourceUtil.copyResourceToFile("org/apache/cayenne/tools/cgen-dependent.map.xml", map); - - File additionalMaps[] = new File[1]; - additionalMaps[0] = new File(destDir, "cgen.map.xml"); - ResourceUtil.copyResourceToFile("org/apache/cayenne/tools/cgen.map.xml", additionalMaps[0]); - - FileList additionalMapsFilelist = new FileList(); - additionalMapsFilelist.setDir(additionalMaps[0].getParentFile()); - additionalMapsFilelist.setFiles(additionalMaps[0].getName()); - - Path additionalMapsPath = new Path(task.getProject()); - additionalMapsPath.addFilelist(additionalMapsFilelist); - - // setup task - task.setMap(map); - task.setAdditionalMaps(additionalMapsPath); - task.setMakepairs(true); - task.setOverwrite(false); - task.setMode("entity"); - task.setIncludeEntities("MyArtGroup"); - task.setDestDir(destDir); - task.setSuperpkg("org.apache.cayenne.testdo.cgen2.auto"); - task.setUsepkgpath(true); - - // run task - task.execute(); - - // check results - File a = new File(destDir, convertPath("org/apache/cayenne/testdo/cgen2/MyArtGroup.java")); - assertTrue(a.isFile()); - assertContents(a, "MyArtGroup", "org.apache.cayenne.testdo.cgen2", "_MyArtGroup"); - - File _a = new File(destDir, convertPath("org/apache/cayenne/testdo/cgen2/auto/_MyArtGroup.java")); - assertTrue(_a.exists()); - assertContents(_a, "_MyArtGroup", "org.apache.cayenne.testdo.cgen2.auto", "CayenneDataObject"); - assertContents(_a, "import org.apache.cayenne.testdo.testmap.ArtGroup;"); - assertContents(_a, " ArtGroup getToParentGroup()"); - assertContents(_a, "setToParentGroup(ArtGroup toParentGroup)"); - } - - private String convertPath(String unixPath) { - return unixPath.replace('/', File.separatorChar); - } - - private void assertContents(File f, String content) throws Exception { - - try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(f)));) { - String s = null; - while ((s = in.readLine()) != null) { - if (s.contains(content)) - return; - } - - fail("<" + content + "> not found in " + f.getAbsolutePath() + "."); - } - - } - - private void assertContents(File f, String className, String packageName, String extendsName) throws Exception { - - try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(f)));) { - assertPackage(in, packageName); - assertClass(in, className, extendsName); - } - } - - private void assertPackage(BufferedReader in, String packageName) throws Exception { - - String s = null; - while ((s = in.readLine()) != null) { - - if (Pattern.matches("^package\\s+([^\\s;]+);", s)) { - assertTrue(s.contains(packageName)); - return; - } - } - - fail("No package declaration found."); - } - - private void assertClass(BufferedReader in, String className, String extendsName) throws Exception { - - Pattern classPattern = Pattern.compile("^public\\s+"); - - String s = null; - while ((s = in.readLine()) != null) { - if (classPattern.matcher(s).find()) { - assertTrue(s.contains(className)); - assertTrue(s.contains(extendsName)); - assertTrue(s.indexOf(className) < s.indexOf(extendsName)); - return; - } - } - - fail("No class declaration found."); - } -} + /** + * Tests pairs generation with a cross-DataMap relationship. + */ + @Test + public void testCrossDataMapRelationships() throws Exception { + + CayenneGeneratorTask task = new CayenneGeneratorTask(); + task.setProject(new Project()); + task.setTaskName("Test"); + task.setLocation(Location.UNKNOWN_LOCATION); + + // prepare destination directory + + File destDir = new File(FileUtil.baseTestDirectory(), "cgen12"); + // prepare destination directory + if (!destDir.exists()) { + assertTrue(destDir.mkdirs()); + } + + File map = new File(destDir, "cgen-dependent.map.xml"); + ResourceUtil.copyResourceToFile("org/apache/cayenne/tools/cgen-dependent.map.xml", map); + + File additionalMaps[] = new File[1]; + additionalMaps[0] = new File(destDir, "cgen.map.xml"); + ResourceUtil.copyResourceToFile("org/apache/cayenne/tools/cgen.map.xml", additionalMaps[0]); + + FileList additionalMapsFilelist = new FileList(); + additionalMapsFilelist.setDir(additionalMaps[0].getParentFile()); + additionalMapsFilelist.setFiles(additionalMaps[0].getName()); + + Path additionalMapsPath = new Path(task.getProject()); + additionalMapsPath.addFilelist(additionalMapsFilelist); + + // setup task + task.setMap(map); + task.setAdditionalMaps(additionalMapsPath); + task.setMakepairs(true); + task.setOverwrite(false); + task.setMode("entity"); + task.setIncludeEntities("MyArtGroup"); + task.setDestDir(destDir); + task.setSuperpkg("org.apache.cayenne.testdo.cgen2.auto"); + task.setUsepkgpath(true); + + // run task + task.execute(); + + // check results + File a = new File(destDir, convertPath("org/apache/cayenne/testdo/cgen2/MyArtGroup.java")); + assertTrue(a.isFile()); + assertContents(a, "MyArtGroup", "org.apache.cayenne.testdo.cgen2", "_MyArtGroup"); + + File _a = new File(destDir, convertPath("org/apache/cayenne/testdo/cgen2/auto/_MyArtGroup.java")); + assertTrue(_a.exists()); + assertContents(_a, "_MyArtGroup", "org.apache.cayenne.testdo.cgen2.auto", "CayenneDataObject"); + assertContents(_a, "import org.apache.cayenne.testdo.testmap.ArtGroup;"); + assertContents(_a, " ArtGroup getToParentGroup()"); + assertContents(_a, "setToParentGroup(ArtGroup toParentGroup)"); + } + + private String convertPath(String unixPath) { + return unixPath.replace('/', File.separatorChar); + } + + private void assertContents(File f, String content) throws Exception { + + try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(f)));) { + String s = null; + while ((s = in.readLine()) != null) { + if (s.contains(content)) + return; + } + + fail("<" + content + "> not found in " + f.getAbsolutePath() + "."); + } + + } + + private void assertContents(File f, String className, String packageName, String extendsName) throws Exception { + + try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(f)));) { + assertPackage(in, packageName); + assertClass(in, className, extendsName); + } + } + + private void assertPackage(BufferedReader in, String packageName) throws Exception { + + String s = null; + while ((s = in.readLine()) != null) { + + if (Pattern.matches("^package\\s+([^\\s;]+);", s)) { + assertTrue(s.contains(packageName)); + return; + } + } + + fail("No package declaration found."); + } + + private void assertClass(BufferedReader in, String className, String extendsName) throws Exception { + + Pattern classPattern = Pattern.compile("^public\\s+"); + + String s = null; + while ((s = in.readLine()) != null) { + if (classPattern.matcher(s).find()) { + assertTrue(s.contains(className)); + assertTrue(s.contains(extendsName)); + assertTrue(s.indexOf(className) < s.indexOf(extendsName)); + return; + } + } + + fail("No class declaration found."); + } +} \ No newline at end of file diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/CayenneGeneratorTaskTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/CayenneGeneratorTaskTest.java index f6f616b812..7ab3328370 100644 --- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/CayenneGeneratorTaskTest.java +++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/CayenneGeneratorTaskTest.java @@ -38,280 +38,280 @@ public class CayenneGeneratorTaskTest { - private static final File baseDir; - private static final File map; - private static final File mapEmbeddables; - private static final File template; - - static { - - baseDir = FileUtil.baseTestDirectory(); - map = new File(baseDir, "antmap.xml"); - mapEmbeddables = new File(baseDir, "antmap-embeddables.xml"); - template = new File(baseDir, "velotemplate.vm"); - - ResourceUtil.copyResourceToFile("testmap.map.xml", map); - ResourceUtil.copyResourceToFile("embeddable.map.xml", mapEmbeddables); - ResourceUtil.copyResourceToFile("org/apache/cayenne/tools/velotemplate.vm", template); - } - - protected CayenneGeneratorTask task; - - @Before - public void setUp() { - - Project project = new Project(); - project.setBaseDir(baseDir); - - task = new CayenneGeneratorTask(); - task.setProject(project); - task.setTaskName("Test"); - task.setLocation(Location.UNKNOWN_LOCATION); - } - - /** - * Test single classes with a non-standard template. - */ - @Test - public void testSingleClassesCustTemplate() throws Exception { - // prepare destination directory - File mapDir = new File(baseDir, "single-classes-custtempl"); - assertTrue(mapDir.mkdirs()); - - // setup task - task.setDestDir(mapDir); - task.setMap(map); - task.setMakepairs(false); - task.setUsepkgpath(true); - task.setTemplate(template.getPath()); - - // run task - task.execute(); - - // check results - File a = new File(mapDir, convertPath("org/apache/cayenne/testdo/testmap/Artist.java")); - assertTrue(a.isFile()); - assertContents(a, "Artist", "org.apache.cayenne.testdo.testmap", "CayenneDataObject"); - - File _a = new File(mapDir, convertPath("org/apache/cayenne/testdo/testmap/_Artist.java")); - assertFalse(_a.exists()); - } - - /** Test single classes generation including full package path. */ - @Test - public void testSingleClasses1() throws Exception { - // prepare destination directory - File mapDir = new File(baseDir, "single-classes-tree"); - assertTrue(mapDir.mkdirs()); - - // setup task - task.setDestDir(mapDir); - task.setMap(map); - task.setMakepairs(false); - task.setUsepkgpath(true); - - // run task - task.execute(); - - // check results - File a = new File(mapDir, convertPath("org/apache/cayenne/testdo/testmap/Artist.java")); - assertTrue(a.isFile()); - assertContents(a, "Artist", "org.apache.cayenne.testdo.testmap", "CayenneDataObject"); - - File _a = new File(mapDir, convertPath("org/apache/cayenne/testdo/testmap/_Artist.java")); - assertFalse(_a.exists()); - } - - /** Test single classes generation ignoring package path. */ - @Test - public void testSingleClasses2() throws Exception { - // prepare destination directory - File mapDir = new File(baseDir, "single-classes-flat"); - assertTrue(mapDir.mkdirs()); - - // setup task - task.setDestDir(mapDir); - task.setMap(map); - task.setMakepairs(false); - task.setUsepkgpath(false); - - // run task - task.execute(); - - // check results - File a = new File(mapDir, convertPath("Artist.java")); - assertTrue(a.exists()); - assertContents(a, "Artist", "org.apache.cayenne.testdo.testmap", "CayenneDataObject"); - - File _a = new File(mapDir, convertPath("_Artist.java")); - assertFalse(_a.exists()); - - File pkga = new File(mapDir, convertPath("org/apache/cayenne/testdo/testmap/Artist.java")); - assertFalse(pkga.exists()); - } - - /** - * Test pairs generation including full package path, default superclass - * package. - */ - @Test - public void testPairs1() throws Exception { - // prepare destination directory - File mapDir = new File(baseDir, "pairs-tree"); - assertTrue(mapDir.mkdirs()); - - // setup task - task.setDestDir(mapDir); - task.setMap(map); - task.setMakepairs(true); - task.setUsepkgpath(true); - - // run task - task.execute(); - - // check results - File a = new File(mapDir, convertPath("org/apache/cayenne/testdo/testmap/Artist.java")); - assertTrue(a.isFile()); - assertContents(a, "Artist", "org.apache.cayenne.testdo.testmap", "_Artist"); - - File _a = new File(mapDir, convertPath("org/apache/cayenne/testdo/testmap/auto/_Artist.java")); - assertTrue(_a.exists()); - assertContents(_a, "_Artist", "org.apache.cayenne.testdo.testmap", "CayenneDataObject"); - } - - /** Test pairs generation in the same directory. */ - @Test - public void testPairs2() throws Exception { - // prepare destination directory - File mapDir = new File(baseDir, "pairs-flat"); - assertTrue(mapDir.mkdirs()); - - // setup task - task.setDestDir(mapDir); - task.setMap(map); - task.setMakepairs(true); - task.setUsepkgpath(false); - - // run task - task.execute(); - - // check results - File a = new File(mapDir, convertPath("Artist.java")); - assertTrue(a.isFile()); - assertContents(a, "Artist", "org.apache.cayenne.testdo.testmap", "_Artist"); - - File _a = new File(mapDir, convertPath("_Artist.java")); - assertTrue(_a.exists()); - assertContents(_a, "_Artist", "org.apache.cayenne.testdo.testmap", "CayenneDataObject"); - - File pkga = new File(mapDir, convertPath("org/apache/cayenne/testdo/testmap/Artist.java")); - assertFalse(pkga.exists()); - } - - /** - * Test pairs generation including full package path with superclass and - * subclass in different packages. - */ - @Test - public void testPairs3() throws Exception { - // prepare destination directory - File mapDir = new File(baseDir, "pairs-tree-split"); - assertTrue(mapDir.mkdirs()); - - // setup task - task.setDestDir(mapDir); - task.setMap(map); - task.setMakepairs(true); - task.setUsepkgpath(true); - task.setSuperpkg("org.apache.cayenne.testdo.testmap.superart"); - - // run task - task.execute(); - - // check results - File a = new File(mapDir, convertPath("org/apache/cayenne/testdo/testmap/Artist.java")); - assertTrue(a.isFile()); - assertContents(a, "Artist", "org.apache.cayenne.testdo.testmap", "_Artist"); - - File _a = new File(mapDir, convertPath("org/apache/cayenne/testdo/testmap/superart/_Artist.java")); - assertTrue(_a.exists()); - assertContents(_a, "_Artist", "org.apache.cayenne.testdo.testmap.superart", "CayenneDataObject"); - } - - @Test - public void testPairsEmbeddable3() throws Exception { - // prepare destination directory - File mapDir = new File(baseDir, "pairs-embeddables3-split"); - assertTrue(mapDir.mkdirs()); - - // setup task - task.setDestDir(mapDir); - task.setMap(mapEmbeddables); - task.setMakepairs(true); - task.setUsepkgpath(true); - task.setSuperpkg("org.apache.cayenne.testdo.embeddable.auto"); - - // run task - task.execute(); - - // check entity results - File a = new File(mapDir, convertPath("org/apache/cayenne/testdo/embeddable/EmbedEntity1.java")); - assertTrue(a.isFile()); - assertContents(a, "EmbedEntity1", "org.apache.cayenne.testdo.embeddable", "_EmbedEntity1"); - - File _a = new File(mapDir, convertPath("org/apache/cayenne/testdo/embeddable/auto/_EmbedEntity1.java")); - assertTrue(_a.exists()); - assertContents(_a, "_EmbedEntity1", "org.apache.cayenne.testdo.embeddable.auto", "CayenneDataObject"); - - // check embeddable results - File e = new File(mapDir, convertPath("org/apache/cayenne/testdo/embeddable/Embeddable1.java")); - assertTrue(e.isFile()); - assertContents(e, "Embeddable1", "org.apache.cayenne.testdo.embeddable", "_Embeddable1"); - - File _e = new File(mapDir, convertPath("org/apache/cayenne/testdo/embeddable/auto/_Embeddable1.java")); - assertTrue(_e.exists()); - assertContents(_e, "_Embeddable1", "org.apache.cayenne.testdo.embeddable.auto", "Object"); - } - - private String convertPath(String unixPath) { - return unixPath.replace('/', File.separatorChar); - } - - private void assertContents(File f, String className, String packageName, String extendsName) throws Exception { - - try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(f)));) { - assertPackage(in, packageName); - assertClass(in, className, extendsName); - } - } - - private void assertPackage(BufferedReader in, String packageName) throws Exception { - - String s = null; - while ((s = in.readLine()) != null) { - if (Pattern.matches("^package\\s+([^\\s;]+);", s)) { - assertTrue(s.indexOf(packageName) > 0); - return; - } - } - - fail("No package declaration found."); - } - - private void assertClass(BufferedReader in, String className, String extendsName) throws Exception { - - Pattern classPattern = Pattern.compile("^public\\s+"); - - String s = null; - while ((s = in.readLine()) != null) { - if (classPattern.matcher(s).find()) { - assertTrue(s.indexOf(className) > 0); - assertTrue(s.indexOf(extendsName) > 0); - assertTrue(s.indexOf(className) < s.indexOf(extendsName)); - return; - } - } - - fail("No class declaration found."); - } -} + private static final File baseDir; + private static final File map; + private static final File mapEmbeddables; + private static final File template; + + static { + + baseDir = FileUtil.baseTestDirectory(); + map = new File(baseDir, "antmap.xml"); + mapEmbeddables = new File(baseDir, "antmap-embeddables.xml"); + template = new File(baseDir, "velotemplate.vm"); + + ResourceUtil.copyResourceToFile("testmap.map.xml", map); + ResourceUtil.copyResourceToFile("embeddable.map.xml", mapEmbeddables); + ResourceUtil.copyResourceToFile("org/apache/cayenne/tools/velotemplate.vm", template); + } + + protected CayenneGeneratorTask task; + + @Before + public void setUp() { + + Project project = new Project(); + project.setBaseDir(baseDir); + + task = new CayenneGeneratorTask(); + task.setProject(project); + task.setTaskName("Test"); + task.setLocation(Location.UNKNOWN_LOCATION); + } + + /** + * Test single classes with a non-standard template. + */ + @Test + public void testSingleClassesCustTemplate() throws Exception { + // prepare destination directory + File mapDir = new File(baseDir, "single-classes-custtempl"); + assertTrue(mapDir.mkdirs()); + + // setup task + task.setDestDir(mapDir); + task.setMap(map); + task.setMakepairs(false); + task.setUsepkgpath(true); + task.setTemplate(template.getPath()); + + // run task + task.execute(); + + // check results + File a = new File(mapDir, convertPath("org/apache/cayenne/testdo/testmap/Artist.java")); + assertTrue(a.isFile()); + assertContents(a, "Artist", "org.apache.cayenne.testdo.testmap", "CayenneDataObject"); + + File _a = new File(mapDir, convertPath("org/apache/cayenne/testdo/testmap/_Artist.java")); + assertFalse(_a.exists()); + } + + /** Test single classes generation including full package path. */ + @Test + public void testSingleClasses1() throws Exception { + // prepare destination directory + File mapDir = new File(baseDir, "single-classes-tree"); + assertTrue(mapDir.mkdirs()); + + // setup task + task.setDestDir(mapDir); + task.setMap(map); + task.setMakepairs(false); + task.setUsepkgpath(true); + + // run task + task.execute(); + + // check results + File a = new File(mapDir, convertPath("org/apache/cayenne/testdo/testmap/Artist.java")); + assertTrue(a.isFile()); + assertContents(a, "Artist", "org.apache.cayenne.testdo.testmap", "CayenneDataObject"); + + File _a = new File(mapDir, convertPath("org/apache/cayenne/testdo/testmap/_Artist.java")); + assertFalse(_a.exists()); + } + + /** Test single classes generation ignoring package path. */ + @Test + public void testSingleClasses2() throws Exception { + // prepare destination directory + File mapDir = new File(baseDir, "single-classes-flat"); + assertTrue(mapDir.mkdirs()); + + // setup task + task.setDestDir(mapDir); + task.setMap(map); + task.setMakepairs(false); + task.setUsepkgpath(false); + + // run task + task.execute(); + + // check results + File a = new File(mapDir, convertPath("Artist.java")); + assertTrue(a.exists()); + assertContents(a, "Artist", "org.apache.cayenne.testdo.testmap", "CayenneDataObject"); + + File _a = new File(mapDir, convertPath("_Artist.java")); + assertFalse(_a.exists()); + + File pkga = new File(mapDir, convertPath("org/apache/cayenne/testdo/testmap/Artist.java")); + assertFalse(pkga.exists()); + } + + /** + * Test pairs generation including full package path, default superclass + * package. + */ + @Test + public void testPairs1() throws Exception { + // prepare destination directory + File mapDir = new File(baseDir, "pairs-tree"); + assertTrue(mapDir.mkdirs()); + + // setup task + task.setDestDir(mapDir); + task.setMap(map); + task.setMakepairs(true); + task.setUsepkgpath(true); + + // run task + task.execute(); + + // check results + File a = new File(mapDir, convertPath("org/apache/cayenne/testdo/testmap/Artist.java")); + assertTrue(a.isFile()); + assertContents(a, "Artist", "org.apache.cayenne.testdo.testmap", "_Artist"); + + File _a = new File(mapDir, convertPath("org/apache/cayenne/testdo/testmap/auto/_Artist.java")); + assertTrue(_a.exists()); + assertContents(_a, "_Artist", "org.apache.cayenne.testdo.testmap", "CayenneDataObject"); + } + + /** Test pairs generation in the same directory. */ + @Test + public void testPairs2() throws Exception { + // prepare destination directory + File mapDir = new File(baseDir, "pairs-flat"); + assertTrue(mapDir.mkdirs()); + + // setup task + task.setDestDir(mapDir); + task.setMap(map); + task.setMakepairs(true); + task.setUsepkgpath(false); + + // run task + task.execute(); + + // check results + File a = new File(mapDir, convertPath("Artist.java")); + assertTrue(a.isFile()); + assertContents(a, "Artist", "org.apache.cayenne.testdo.testmap", "_Artist"); + + File _a = new File(mapDir, convertPath("_Artist.java")); + assertTrue(_a.exists()); + assertContents(_a, "_Artist", "org.apache.cayenne.testdo.testmap", "CayenneDataObject"); + + File pkga = new File(mapDir, convertPath("org/apache/cayenne/testdo/testmap/Artist.java")); + assertFalse(pkga.exists()); + } + + /** + * Test pairs generation including full package path with superclass and + * subclass in different packages. + */ + @Test + public void testPairs3() throws Exception { + // prepare destination directory + File mapDir = new File(baseDir, "pairs-tree-split"); + assertTrue(mapDir.mkdirs()); + + // setup task + task.setDestDir(mapDir); + task.setMap(map); + task.setMakepairs(true); + task.setUsepkgpath(true); + task.setSuperpkg("org.apache.cayenne.testdo.testmap.superart"); + + // run task + task.execute(); + + // check results + File a = new File(mapDir, convertPath("org/apache/cayenne/testdo/testmap/Artist.java")); + assertTrue(a.isFile()); + assertContents(a, "Artist", "org.apache.cayenne.testdo.testmap", "_Artist"); + + File _a = new File(mapDir, convertPath("org/apache/cayenne/testdo/testmap/superart/_Artist.java")); + assertTrue(_a.exists()); + assertContents(_a, "_Artist", "org.apache.cayenne.testdo.testmap.superart", "CayenneDataObject"); + } + + @Test + public void testPairsEmbeddable3() throws Exception { + // prepare destination directory + File mapDir = new File(baseDir, "pairs-embeddables3-split"); + assertTrue(mapDir.mkdirs()); + + // setup task + task.setDestDir(mapDir); + task.setMap(mapEmbeddables); + task.setMakepairs(true); + task.setUsepkgpath(true); + task.setSuperpkg("org.apache.cayenne.testdo.embeddable.auto"); + + // run task + task.execute(); + + // check entity results + File a = new File(mapDir, convertPath("org/apache/cayenne/testdo/embeddable/EmbedEntity1.java")); + assertTrue(a.isFile()); + assertContents(a, "EmbedEntity1", "org.apache.cayenne.testdo.embeddable", "_EmbedEntity1"); + + File _a = new File(mapDir, convertPath("org/apache/cayenne/testdo/embeddable/auto/_EmbedEntity1.java")); + assertTrue(_a.exists()); + assertContents(_a, "_EmbedEntity1", "org.apache.cayenne.testdo.embeddable.auto", "CayenneDataObject"); + + // check embeddable results + File e = new File(mapDir, convertPath("org/apache/cayenne/testdo/embeddable/Embeddable1.java")); + assertTrue(e.isFile()); + assertContents(e, "Embeddable1", "org.apache.cayenne.testdo.embeddable", "_Embeddable1"); + + File _e = new File(mapDir, convertPath("org/apache/cayenne/testdo/embeddable/auto/_Embeddable1.java")); + assertTrue(_e.exists()); + assertContents(_e, "_Embeddable1", "org.apache.cayenne.testdo.embeddable.auto", "Object"); + } + + private String convertPath(String unixPath) { + return unixPath.replace('/', File.separatorChar); + } + + private void assertContents(File f, String className, String packageName, String extendsName) throws Exception { + + try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(f)));) { + assertPackage(in, packageName); + assertClass(in, className, extendsName); + } + } + + private void assertPackage(BufferedReader in, String packageName) throws Exception { + + String s = null; + while ((s = in.readLine()) != null) { + if (Pattern.matches("^package\\s+([^\\s;]+);", s)) { + assertTrue(s.indexOf(packageName) > 0); + return; + } + } + + fail("No package declaration found."); + } + + private void assertClass(BufferedReader in, String className, String extendsName) throws Exception { + + Pattern classPattern = Pattern.compile("^public\\s+"); + + String s = null; + while ((s = in.readLine()) != null) { + if (classPattern.matcher(s).find()) { + assertTrue(s.indexOf(className) > 0); + assertTrue(s.indexOf(extendsName) > 0); + assertTrue(s.indexOf(className) < s.indexOf(extendsName)); + return; + } + } + + fail("No class declaration found."); + } +} \ No newline at end of file diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbGeneratorTaskTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbGeneratorTaskTest.java index 12af0fd466..7f021833d7 100644 --- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbGeneratorTaskTest.java +++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbGeneratorTaskTest.java @@ -72,4 +72,4 @@ public void testSetUrl() throws Exception { task.setUrl("jdbc:///"); assertEquals("jdbc:///", task.url); } -} +} \ No newline at end of file diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java index 075d88de1b..1f60bbcb66 100644 --- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java +++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java @@ -18,12 +18,7 @@ ****************************************************************/ package org.apache.cayenne.tools; -import static org.apache.cayenne.tools.dbimport.config.DefaultReverseEngineeringLoaderTest.assertCatalog; -import static org.apache.cayenne.tools.dbimport.config.DefaultReverseEngineeringLoaderTest.assertCatalogAndSchema; -import static org.apache.cayenne.tools.dbimport.config.DefaultReverseEngineeringLoaderTest.assertFlat; -import static org.apache.cayenne.tools.dbimport.config.DefaultReverseEngineeringLoaderTest.assertSchema; -import static org.apache.cayenne.tools.dbimport.config.DefaultReverseEngineeringLoaderTest.assertSkipRelationshipsLoading; -import static org.apache.cayenne.tools.dbimport.config.DefaultReverseEngineeringLoaderTest.assertTableTypes; +import static org.apache.cayenne.dbimport.DefaultReverseEngineeringLoaderTest.*; import static org.apache.commons.lang.StringUtils.isBlank; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -59,180 +54,180 @@ // based on "cayenneTestConnection", like we do in cayenne-server, etc. public class DbImporterTaskTest { - static { - XMLUnit.setIgnoreWhitespace(true); - } - - @Test - public void testLoadCatalog() throws Exception { - assertCatalog(getCdbImport("build-catalog.xml").getReverseEngineering()); - } - - @Test - public void testLoadSchema() throws Exception { - assertSchema(getCdbImport("build-schema.xml").getReverseEngineering()); - } - - @Test - public void testLoadCatalogAndSchema() throws Exception { - assertCatalogAndSchema(getCdbImport("build-catalog-and-schema.xml").getReverseEngineering()); - } - - @Test - public void testLoadFlat() throws Exception { - assertFlat(getCdbImport("build-flat.xml").getReverseEngineering()); - } - - @Test - public void testSkipRelationshipsLoading() throws Exception { - assertSkipRelationshipsLoading(getCdbImport("build-skip-relationships-loading.xml").getReverseEngineering()); - } - - @Test - public void testTableTypes() throws Exception { - assertTableTypes(getCdbImport("build-table-types.xml").getReverseEngineering()); - } - - @Test - public void testIncludeTable() throws Exception { - test("build-include-table.xml"); - } - - private DbImporterTask getCdbImport(String buildFile) { - Project project = new Project(); - - File map = distDir(buildFile); - ResourceUtil.copyResourceToFile(getPackagePath() + "/" + buildFile, map); - ProjectHelper.configureProject(project, map); - - UnknownElement task = (UnknownElement) project.getTargets().get("dist").getTasks()[0]; - task.maybeConfigure(); - - return (DbImporterTask) task.getRealThing(); - } - - private static File distDir(String name) { - File distDir = new File(FileUtil.baseTestDirectory(), "cdbImport"); - File file = new File(distDir, name); - distDir = file.getParentFile(); - // prepare destination directory - if (!distDir.exists()) { - assertTrue(distDir.mkdirs()); - } - return file; - } - - private String getPackagePath() { - return getClass().getPackage().getName().replace('.', '/'); - } - - private void test(String name) throws Exception { - DbImporterTask cdbImport = getCdbImport("dbimport/" + name); - File mapFile = cdbImport.getMap(); - URL mapUrl = this.getClass().getResource("dbimport/" + mapFile.getName()); - if (mapUrl != null && new File(mapUrl.toURI()).exists()) { - ResourceUtil.copyResourceToFile(mapUrl, mapFile); - } - - URL mapUrlRes = this.getClass().getResource("dbimport/" + mapFile.getName() + "-result"); - if (mapUrlRes != null && new File(mapUrlRes.toURI()).exists()) { - ResourceUtil - .copyResourceToFile(mapUrlRes, new File(mapFile.getParentFile(), mapFile.getName() + "-result")); - } - - File mapFileCopy = distDir("copy-" + mapFile.getName()); - if (mapFile.exists()) { - FileUtils.getFileUtils().copyFile(mapFile, mapFileCopy); - cdbImport.setMap(mapFileCopy); - } else { - mapFileCopy = mapFile; - } - - prepareDatabase(name, cdbImport.toParameters()); - - try { - cdbImport.execute(); - verifyResult(mapFile, mapFileCopy); - } finally { - cleanDb(cdbImport.toParameters()); - } - } - - private void cleanDb(DbImportConfiguration dbImportConfiguration) throws ClassNotFoundException, - IllegalAccessException, InstantiationException, SQLException { - Class.forName(dbImportConfiguration.getDriver()).newInstance(); - // Get a connection - Connection connection = DriverManager.getConnection(dbImportConfiguration.getUrl()); - Statement stmt = connection.createStatement(); - - ResultSet tables = connection.getMetaData().getTables(null, null, null, new String[] { "TABLE" }); - while (tables.next()) { - String schema = tables.getString("TABLE_SCHEM"); - System.out.println("DROP TABLE " + (isBlank(schema) ? "" : schema + ".") + tables.getString("TABLE_NAME")); - stmt.execute("DROP TABLE " + (isBlank(schema) ? "" : schema + ".") + tables.getString("TABLE_NAME")); - } - - ResultSet schemas = connection.getMetaData().getSchemas(); - while (schemas.next()) { - String schem = schemas.getString("TABLE_SCHEM"); - if (schem.startsWith("SCHEMA")) { - System.out.println("DROP SCHEMA " + schem); - stmt.execute("DROP SCHEMA " + schem + " RESTRICT"); - } - } - } - - @SuppressWarnings("unchecked") - private void verifyResult(File map, File mapFileCopy) { - try { - FileReader control = new FileReader(map.getAbsolutePath() + "-result"); - FileReader test = new FileReader(mapFileCopy); - - DetailedDiff diff = new DetailedDiff(new Diff(control, test)); - if (!diff.similar()) { - for (Difference d : ((List) diff.getAllDifferences())) { - - System.out.println("-------------------------------------------"); - System.out.println(d.getTestNodeDetail().getNode()); - System.out.println(d.getControlNodeDetail().getValue()); - } - fail(diff.toString()); - } - - } catch (SAXException e) { - e.printStackTrace(); - fail(); - } catch (IOException e) { - e.printStackTrace(); - fail(); - } - } - - private void prepareDatabase(String sqlFile, DbImportConfiguration dbImportConfiguration) throws Exception { - - URL sqlUrl = ResourceUtil.getResource(getClass(), "dbimport/" + sqlFile + ".sql"); - assertNotNull(sqlUrl); - - Class.forName(dbImportConfiguration.getDriver()).newInstance(); - - try (Connection c = DriverManager.getConnection(dbImportConfiguration.getUrl());) { - - // TODO: move parsing SQL files to a common utility (DBHelper?) . - // ALso see UnitDbApater.executeDDL - this should use the same - // utility - - try (Statement stmt = c.createStatement();) { - for (String sql : SQLReader.statements(sqlUrl, ";")) { - - // skip comments - if (sql.startsWith("-- ")) { - continue; - } - - stmt.execute(sql); - } - } - } - } + static { + XMLUnit.setIgnoreWhitespace(true); + } + + @Test + public void testLoadCatalog() throws Exception { + assertCatalog(getCdbImport("build-catalog.xml").getReverseEngineering()); + } + + @Test + public void testLoadSchema() throws Exception { + assertSchema(getCdbImport("build-schema.xml").getReverseEngineering()); + } + + @Test + public void testLoadCatalogAndSchema() throws Exception { + assertCatalogAndSchema(getCdbImport("build-catalog-and-schema.xml").getReverseEngineering()); + } + + @Test + public void testLoadFlat() throws Exception { + assertFlat(getCdbImport("build-flat.xml").getReverseEngineering()); + } + + @Test + public void testSkipRelationshipsLoading() throws Exception { + assertSkipRelationshipsLoading(getCdbImport("build-skip-relationships-loading.xml").getReverseEngineering()); + } + + @Test + public void testTableTypes() throws Exception { + assertTableTypes(getCdbImport("build-table-types.xml").getReverseEngineering()); + } + + @Test + public void testIncludeTable() throws Exception { + test("build-include-table.xml"); + } + + private DbImporterTask getCdbImport(String buildFile) { + Project project = new Project(); + + File map = distDir(buildFile); + ResourceUtil.copyResourceToFile(getPackagePath() + "/" + buildFile, map); + ProjectHelper.configureProject(project, map); + + UnknownElement task = (UnknownElement) project.getTargets().get("dist").getTasks()[0]; + task.maybeConfigure(); + + return (DbImporterTask) task.getRealThing(); + } + + private static File distDir(String name) { + File distDir = new File(FileUtil.baseTestDirectory(), "cdbImport"); + File file = new File(distDir, name); + distDir = file.getParentFile(); + // prepare destination directory + if (!distDir.exists()) { + assertTrue(distDir.mkdirs()); + } + return file; + } + + private String getPackagePath() { + return getClass().getPackage().getName().replace('.', '/'); + } + + private void test(String name) throws Exception { + DbImporterTask cdbImport = getCdbImport("dbimport/" + name); + File mapFile = cdbImport.getMap(); + URL mapUrl = this.getClass().getResource("dbimport/" + mapFile.getName()); + if (mapUrl != null && new File(mapUrl.toURI()).exists()) { + ResourceUtil.copyResourceToFile(mapUrl, mapFile); + } + + URL mapUrlRes = this.getClass().getResource("dbimport/" + mapFile.getName() + "-result"); + if (mapUrlRes != null && new File(mapUrlRes.toURI()).exists()) { + ResourceUtil + .copyResourceToFile(mapUrlRes, new File(mapFile.getParentFile(), mapFile.getName() + "-result")); + } + + File mapFileCopy = distDir("copy-" + mapFile.getName()); + if (mapFile.exists()) { + FileUtils.getFileUtils().copyFile(mapFile, mapFileCopy); + cdbImport.setMap(mapFileCopy); + } else { + mapFileCopy = mapFile; + } + + prepareDatabase(name, cdbImport.toParameters()); + + try { + cdbImport.execute(); + verifyResult(mapFile, mapFileCopy); + } finally { + cleanDb(cdbImport.toParameters()); + } + } + + private void cleanDb(DbImportConfiguration dbImportConfiguration) throws ClassNotFoundException, + IllegalAccessException, InstantiationException, SQLException { + Class.forName(dbImportConfiguration.getDriver()).newInstance(); + // Get a connection + Connection connection = DriverManager.getConnection(dbImportConfiguration.getUrl()); + Statement stmt = connection.createStatement(); + + ResultSet tables = connection.getMetaData().getTables(null, null, null, new String[] { "TABLE" }); + while (tables.next()) { + String schema = tables.getString("TABLE_SCHEM"); + System.out.println("DROP TABLE " + (isBlank(schema) ? "" : schema + ".") + tables.getString("TABLE_NAME")); + stmt.execute("DROP TABLE " + (isBlank(schema) ? "" : schema + ".") + tables.getString("TABLE_NAME")); + } + + ResultSet schemas = connection.getMetaData().getSchemas(); + while (schemas.next()) { + String schem = schemas.getString("TABLE_SCHEM"); + if (schem.startsWith("SCHEMA")) { + System.out.println("DROP SCHEMA " + schem); + stmt.execute("DROP SCHEMA " + schem + " RESTRICT"); + } + } + } + + @SuppressWarnings("unchecked") + private void verifyResult(File map, File mapFileCopy) { + try { + FileReader control = new FileReader(map.getAbsolutePath() + "-result"); + FileReader test = new FileReader(mapFileCopy); + + DetailedDiff diff = new DetailedDiff(new Diff(control, test)); + if (!diff.similar()) { + for (Difference d : ((List) diff.getAllDifferences())) { + + System.out.println("-------------------------------------------"); + System.out.println(d.getTestNodeDetail().getNode()); + System.out.println(d.getControlNodeDetail().getValue()); + } + fail(diff.toString()); + } + + } catch (SAXException e) { + e.printStackTrace(); + fail(); + } catch (IOException e) { + e.printStackTrace(); + fail(); + } + } + + private void prepareDatabase(String sqlFile, DbImportConfiguration dbImportConfiguration) throws Exception { + + URL sqlUrl = ResourceUtil.getResource(getClass(), "dbimport/" + sqlFile + ".sql"); + assertNotNull(sqlUrl); + + Class.forName(dbImportConfiguration.getDriver()).newInstance(); + + try (Connection c = DriverManager.getConnection(dbImportConfiguration.getUrl());) { + + // TODO: move parsing SQL files to a common utility (DBHelper?) . + // ALso see UnitDbApater.executeDDL - this should use the same + // utility + + try (Statement stmt = c.createStatement();) { + for (String sql : SQLReader.statements(sqlUrl, ";")) { + + // skip comments + if (sql.startsWith("-- ")) { + continue; + } + + stmt.execute(sql); + } + } + } + } } \ No newline at end of file diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/NamePatternMatcherTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/NamePatternMatcherTest.java index 161f44e578..11223a24c9 100644 --- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/NamePatternMatcherTest.java +++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/NamePatternMatcherTest.java @@ -27,48 +27,48 @@ public class NamePatternMatcherTest { - /** - * Test pattern expansion. - */ - @Test - public void testReplaceWildcardInStringWithString() throws Exception { - assertEquals(null, replaceWildcardInStringWithString("*", null, "Entity")); - assertEquals("*.java", replaceWildcardInStringWithString(null, "*.java", "Entity")); - assertEquals("Entity.java", replaceWildcardInStringWithString("*", "*.java", "Entity")); - assertEquals("java.Entity", replaceWildcardInStringWithString("*", "java.*", "Entity")); - assertEquals("Entity.Entity", replaceWildcardInStringWithString("*", "*.*", "Entity")); - assertEquals("EntityEntity", replaceWildcardInStringWithString("*", "**", "Entity")); - assertEquals("EditEntityReport.vm", replaceWildcardInStringWithString("*", "Edit*Report.vm", "Entity")); - assertEquals("Entity", replaceWildcardInStringWithString("*", "*", "Entity")); - } + /** + * Test pattern expansion. + */ + @Test + public void testReplaceWildcardInStringWithString() throws Exception { + assertEquals(null, replaceWildcardInStringWithString("*", null, "Entity")); + assertEquals("*.java", replaceWildcardInStringWithString(null, "*.java", "Entity")); + assertEquals("Entity.java", replaceWildcardInStringWithString("*", "*.java", "Entity")); + assertEquals("java.Entity", replaceWildcardInStringWithString("*", "java.*", "Entity")); + assertEquals("Entity.Entity", replaceWildcardInStringWithString("*", "*.*", "Entity")); + assertEquals("EntityEntity", replaceWildcardInStringWithString("*", "**", "Entity")); + assertEquals("EditEntityReport.vm", replaceWildcardInStringWithString("*", "Edit*Report.vm", "Entity")); + assertEquals("Entity", replaceWildcardInStringWithString("*", "*", "Entity")); + } - /** - * Test tokenizing - */ - @Test - public void testTokenizer() { + /** + * Test tokenizing + */ + @Test + public void testTokenizer() { - String[] nullFilters = NamePatternMatcher.tokenizePattern(null); - assertEquals(0, nullFilters.length); + String[] nullFilters = NamePatternMatcher.tokenizePattern(null); + assertEquals(0, nullFilters.length); - String[] filters = NamePatternMatcher.tokenizePattern("billing_*,user?"); - assertEquals(2, filters.length); - assertEquals("^billing_.*$", filters[0]); - assertEquals("^user.?$", filters[1]); - } + String[] filters = NamePatternMatcher.tokenizePattern("billing_*,user?"); + assertEquals(2, filters.length); + assertEquals("^billing_.*$", filters[0]); + assertEquals("^user.?$", filters[1]); + } - /** - * Test tokenizing - */ - @Test - public void testTokenizerEntities() { + /** + * Test tokenizing + */ + @Test + public void testTokenizerEntities() { - String includePattern = "Organization,SecGroup,SecIndividual"; + String includePattern = "Organization,SecGroup,SecIndividual"; - String[] filters = NamePatternMatcher.tokenizePattern(includePattern); - assertEquals(3, filters.length); - assertEquals("^Organization$", filters[0]); - assertEquals("^SecGroup$", filters[1]); - assertEquals("^SecIndividual$", filters[2]); - } -} + String[] filters = NamePatternMatcher.tokenizePattern(includePattern); + assertEquals(3, filters.length); + assertEquals("^Organization$", filters[0]); + assertEquals("^SecGroup$", filters[1]); + assertEquals("^SecIndividual$", filters[2]); + } +} \ No newline at end of file diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/configuration/ToolsModuleTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/configuration/ToolsModuleTest.java index ae22f25d2f..3e74cff7a5 100644 --- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/configuration/ToolsModuleTest.java +++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/configuration/ToolsModuleTest.java @@ -62,4 +62,4 @@ public void testDbApdater() throws Exception { assertTrue(factory.createAdapter(nodeDescriptor, dataSource) instanceof AutoAdapter); } -} +} \ No newline at end of file diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportActionTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportActionTest.java index b49c8731ce..f4964a6a2a 100644 --- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportActionTest.java +++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportActionTest.java @@ -18,35 +18,6 @@ */ package org.apache.cayenne.tools.dbimport; -import static java.util.Arrays.asList; -import static org.apache.cayenne.merge.builders.ObjectMother.dbAttr; -import static org.apache.cayenne.merge.builders.ObjectMother.dbEntity; -import static org.apache.cayenne.merge.builders.ObjectMother.objAttr; -import static org.apache.cayenne.merge.builders.ObjectMother.objEntity; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.stub; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.io.File; -import java.net.URL; -import java.sql.Connection; -import java.sql.SQLException; -import java.util.LinkedList; -import java.util.List; - -import javax.sql.DataSource; - import org.apache.cayenne.CayenneRuntimeException; import org.apache.cayenne.access.DbLoader; import org.apache.cayenne.access.DbLoaderDelegate; @@ -77,266 +48,301 @@ import org.junit.Test; import org.xml.sax.InputSource; +import javax.sql.DataSource; +import java.io.File; +import java.net.URL; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.LinkedList; +import java.util.List; + +import static java.util.Arrays.asList; +import static org.apache.cayenne.merge.builders.ObjectMother.dbAttr; +import static org.apache.cayenne.merge.builders.ObjectMother.dbEntity; +import static org.apache.cayenne.merge.builders.ObjectMother.objAttr; +import static org.apache.cayenne.merge.builders.ObjectMother.objEntity; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.stub; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + public class DbImportActionTest { - public static final File FILE_STUB = new File("") { - - private static final long serialVersionUID = -7513956717393115824L; - - @Override - public boolean exists() { - return true; - } - - @Override - public boolean canRead() { - return true; - } - }; - - @Test - public void testNewDataMapImport() throws Exception { - - DbLoader dbLoader = new DbLoader(null, null, null) { - @Override - public void load(DataMap dataMap, DbLoaderConfiguration config) throws SQLException { - new DataMapBuilder(dataMap).withDbEntities(2).build(); - } - - @Override - public String[] getDefaultTableTypes() { - return null; - } - }; - - DbImportConfiguration params = mock(DbImportConfiguration.class); - when(params.createLoader(any(DbAdapter.class), any(Connection.class), any(DbLoaderDelegate.class))).thenReturn( - dbLoader); - - when(params.createDataMap()).thenReturn(new DataMap("testImport")); - when(params.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate()); - when(params.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration()); - - final DataMap DATA_MAP = new DataMap(); - when(params.initializeDataMap(any(DataMap.class))).thenReturn(DATA_MAP); - - final boolean[] haveWeTriedToSave = { false }; - DbImportAction action = buildDbImportAction(new FileProjectSaver() { - @Override - public void save(Project project) { - haveWeTriedToSave[0] = true; - - // Validation phase - assertEquals(DATA_MAP, project.getRootNode()); - } - }, null); - - action.execute(params); - - assertTrue("We should try to save.", haveWeTriedToSave[0]); - } - - @Test - public void testImportWithFieldChanged() throws Exception { - DbLoader dbLoader = new DbLoader(null, null, null) { - @Override - public void load(DataMap dataMap, DbLoaderConfiguration config) throws SQLException { - new DataMapBuilder(dataMap).with( - dbEntity("ARTGROUP").attributes(dbAttr("GROUP_ID").typeInt().primaryKey(), - dbAttr("NAME").typeVarchar(100).mandatory(), - dbAttr("NAME_01").typeVarchar(100).mandatory(), dbAttr("PARENT_GROUP_ID").typeInt())) - .with(objEntity("org.apache.cayenne.testdo.testmap", "ArtGroup", "ARTGROUP").attributes( - objAttr("name").type(String.class).dbPath("NAME"))); - } - - @Override - public String[] getDefaultTableTypes() { - return null; - } - }; - - DbImportConfiguration params = mock(DbImportConfiguration.class); - when(params.createLoader(any(DbAdapter.class), any(Connection.class), any(DbLoaderDelegate.class))).thenReturn( - dbLoader); - - when(params.createDataMap()).thenReturn(new DataMap("testImport")); - when(params.getDataMapFile()).thenReturn(FILE_STUB); - when(params.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate()); - when(params.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration()); - - final boolean[] haveWeTriedToSave = { false }; - DbImportAction action = buildDbImportAction(new FileProjectSaver() { - @Override - public void save(Project project) { - haveWeTriedToSave[0] = true; - - // Validation phase - DataMap rootNode = (DataMap) project.getRootNode(); - assertEquals(1, rootNode.getObjEntities().size()); - assertEquals(1, rootNode.getDbEntityMap().size()); - - DbEntity entity = rootNode.getDbEntity("ARTGROUP"); - assertNotNull(entity); - assertEquals(4, entity.getAttributes().size()); - assertNotNull(entity.getAttribute("NAME_01")); - } - }, new MapLoader() { - - @Override - public synchronized DataMap loadDataMap(InputSource src) throws CayenneRuntimeException { - return new DataMapBuilder() - .with(dbEntity("ARTGROUP").attributes(dbAttr("GROUP_ID").typeInt().primaryKey(), - dbAttr("NAME").typeVarchar(100).mandatory(), dbAttr("PARENT_GROUP_ID").typeInt())) - .with(objEntity("org.apache.cayenne.testdo.testmap", "ArtGroup", "ARTGROUP").attributes( - objAttr("name").type(String.class).dbPath("NAME"))).build(); - } - }); - - action.execute(params); - - assertTrue("We should try to save.", haveWeTriedToSave[0]); - } - - @Test - public void testImportWithoutChanges() throws Exception { - DbLoader dbLoader = new DbLoader(null, null, null) { - @Override - public void load(DataMap dataMap, DbLoaderConfiguration config) throws SQLException { - new DataMapBuilder(dataMap).with(dbEntity("ARTGROUP").attributes( - dbAttr("NAME").typeVarchar(100).mandatory())); - } - - @Override - public String[] getDefaultTableTypes() { - return null; - } - }; - - DbImportConfiguration params = mock(DbImportConfiguration.class); - when(params.createLoader(any(DbAdapter.class), any(Connection.class), any(DbLoaderDelegate.class))).thenReturn( - dbLoader); - - when(params.createDataMap()).thenReturn(new DataMap("testImport")); - when(params.getDataMapFile()).thenReturn(FILE_STUB); - when(params.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate()); - when(params.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration()); - - Log log = mock(Log.class); - when(log.isDebugEnabled()).thenReturn(false); - when(log.isInfoEnabled()).thenReturn(false); - - FileProjectSaver projectSaver = mock(FileProjectSaver.class); - doNothing().when(projectSaver).save(any(Project.class)); - - MapLoader mapLoader = mock(MapLoader.class); - stub(mapLoader.loadDataMap(any(InputSource.class))).toReturn( - new DataMapBuilder().with(dbEntity("ARTGROUP").attributes(dbAttr("NAME").typeVarchar(100).mandatory())) - .build()); - - DbImportAction action = buildDbImportAction(log, projectSaver, mapLoader); - - action.execute(params); - - verify(projectSaver, never()).save(any(Project.class)); - verify(mapLoader, times(1)).loadDataMap(any(InputSource.class)); - } - - @Test - public void testImportWithDbError() throws Exception { - DbLoader dbLoader = mock(DbLoader.class); - when(dbLoader.getDefaultTableTypes()).thenReturn(null); - doThrow(new SQLException()).when(dbLoader).load(any(DataMap.class), any(DbLoaderConfiguration.class)); - - DbImportConfiguration params = mock(DbImportConfiguration.class); - when(params.createLoader(any(DbAdapter.class), any(Connection.class), any(DbLoaderDelegate.class))).thenReturn( - dbLoader); - - FileProjectSaver projectSaver = mock(FileProjectSaver.class); - doNothing().when(projectSaver).save(any(Project.class)); - - MapLoader mapLoader = mock(MapLoader.class); - when(mapLoader.loadDataMap(any(InputSource.class))).thenReturn(null); - - DbImportAction action = buildDbImportAction(projectSaver, mapLoader); - - try { - action.execute(params); - fail(); - } catch (SQLException e) { - // expected - } - - verify(projectSaver, never()).save(any(Project.class)); - verify(mapLoader, never()).loadDataMap(any(InputSource.class)); - } - - private DbImportAction buildDbImportAction(FileProjectSaver projectSaver, MapLoader mapLoader) throws Exception { - Log log = mock(Log.class); - when(log.isDebugEnabled()).thenReturn(true); - when(log.isInfoEnabled()).thenReturn(true); - - return buildDbImportAction(log, projectSaver, mapLoader); - } - - private DbImportAction buildDbImportAction(Log log, FileProjectSaver projectSaver, MapLoader mapLoader) - throws Exception { - DbAdapter dbAdapter = mock(DbAdapter.class); - when(dbAdapter.mergerFactory()).thenReturn(new MergerFactory()); - - DbAdapterFactory adapterFactory = mock(DbAdapterFactory.class); - when(adapterFactory.createAdapter(any(DataNodeDescriptor.class), any(DataSource.class))).thenReturn(dbAdapter); - - DataSourceFactory dataSourceFactory = mock(DataSourceFactory.class); - DataSource mock = mock(DataSource.class); - when(dataSourceFactory.getDataSource(any(DataNodeDescriptor.class))).thenReturn(mock); - - return new DbImportAction(log, projectSaver, dataSourceFactory, adapterFactory, mapLoader); - } - - @Test - public void testSaveLoaded() throws Exception { - Log log = mock(Log.class); - Injector i = DIBootstrap.createInjector(new ToolsModule(log), new DbImportModule()); - - DbImportAction action = i.getInstance(DbImportAction.class); - - String packagePath = getClass().getPackage().getName().replace('.', '/'); - URL packageUrl = getClass().getClassLoader().getResource(packagePath); - assertNotNull(packageUrl); - URL outUrl = new URL(packageUrl, "dbimport/testSaveLoaded1.map.xml"); - - File out = new File(outUrl.toURI()); - out.delete(); - assertFalse(out.isFile()); - - DataMap map = new DataMap("testSaveLoaded1"); - map.setConfigurationSource(new URLResource(outUrl)); + public static final File FILE_STUB = new File("") { + @Override + public boolean exists() { + return true; + } + + @Override + public boolean canRead() { + return true; + } + }; + + @Test + public void testNewDataMapImport() throws Exception { + + DbLoader dbLoader = new DbLoader(null, null, null) { + @Override + public void load(DataMap dataMap, DbLoaderConfiguration config) throws SQLException { + new DataMapBuilder(dataMap).withDbEntities(2).build(); + } + + @Override + public String[] getDefaultTableTypes() { + return null; + } + }; + + DbImportConfiguration params = mock(DbImportConfiguration.class); + when(params.createLoader(any(DbAdapter.class), any(Connection.class), any(DbLoaderDelegate.class))) + .thenReturn(dbLoader); + + when(params.createDataMap()).thenReturn(new DataMap("testImport")); + when(params.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate()); + when(params.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration()); + + final DataMap DATA_MAP = new DataMap(); + when(params.initializeDataMap(any(DataMap.class))).thenReturn(DATA_MAP); + + final boolean[] haveWeTriedToSave = {false}; + DbImportActionDefault action = buildDbImportAction(new FileProjectSaver() { + @Override + public void save(Project project) { + haveWeTriedToSave[0] = true; + + // Validation phase + assertEquals(DATA_MAP, project.getRootNode()); + } + }, null); + + action.execute(params); + + assertTrue("We should try to save.", haveWeTriedToSave[0]); + } + + @Test + public void testImportWithFieldChanged() throws Exception { + DbLoader dbLoader = new DbLoader(null, null, null) { + @Override + public void load(DataMap dataMap, DbLoaderConfiguration config) throws SQLException { + new DataMapBuilder(dataMap).with( + dbEntity("ARTGROUP").attributes( + dbAttr("GROUP_ID").typeInt().primaryKey(), + dbAttr("NAME").typeVarchar(100).mandatory(), + dbAttr("NAME_01").typeVarchar(100).mandatory(), + dbAttr("PARENT_GROUP_ID").typeInt() + )).with( + objEntity("org.apache.cayenne.testdo.testmap", "ArtGroup", "ARTGROUP").attributes( + objAttr("name").type(String.class).dbPath("NAME") + )); + } + + @Override + public String[] getDefaultTableTypes() { + return null; + } + }; + + DbImportConfiguration params = mock(DbImportConfiguration.class); + when(params.createLoader(any(DbAdapter.class), any(Connection.class), any(DbLoaderDelegate.class))) + .thenReturn(dbLoader); + + when(params.createDataMap()).thenReturn(new DataMap("testImport")); + when(params.getDataMapFile()).thenReturn(FILE_STUB); + when(params.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate()); + when(params.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration()); + + final boolean[] haveWeTriedToSave = {false}; + DbImportActionDefault action = buildDbImportAction(new FileProjectSaver() { + @Override + public void save(Project project) { + haveWeTriedToSave[0] = true; + + // Validation phase + DataMap rootNode = (DataMap) project.getRootNode(); + assertEquals(1, rootNode.getObjEntities().size()); + assertEquals(1, rootNode.getDbEntityMap().size()); + + DbEntity entity = rootNode.getDbEntity("ARTGROUP"); + assertNotNull(entity); + assertEquals(4, entity.getAttributes().size()); + assertNotNull(entity.getAttribute("NAME_01")); + } + }, new MapLoader() { + + @Override + public synchronized DataMap loadDataMap(InputSource src) throws CayenneRuntimeException { + return new DataMapBuilder().with( + dbEntity("ARTGROUP").attributes( + dbAttr("GROUP_ID").typeInt().primaryKey(), + dbAttr("NAME").typeVarchar(100).mandatory(), + dbAttr("PARENT_GROUP_ID").typeInt() + )).with( + objEntity("org.apache.cayenne.testdo.testmap", "ArtGroup", "ARTGROUP").attributes( + objAttr("name").type(String.class).dbPath("NAME") + )).build(); + } + }); + + action.execute(params); + + assertTrue("We should try to save.", haveWeTriedToSave[0]); + } + + @Test + public void testImportWithoutChanges() throws Exception { + DbLoader dbLoader = new DbLoader(null, null, null) { + @Override + public void load(DataMap dataMap, DbLoaderConfiguration config) throws SQLException { + new DataMapBuilder(dataMap).with( + dbEntity("ARTGROUP").attributes( + dbAttr("NAME").typeVarchar(100).mandatory() + )); + } + + @Override + public String[] getDefaultTableTypes() { + return null; + } + }; + + DbImportConfiguration params = mock(DbImportConfiguration.class); + when(params.createLoader(any(DbAdapter.class), any(Connection.class), any(DbLoaderDelegate.class))) + .thenReturn(dbLoader); + + when(params.createDataMap()).thenReturn(new DataMap("testImport")); + when(params.getDataMapFile()).thenReturn(FILE_STUB); + when(params.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate()); + when(params.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration()); + + Log log = mock(Log.class); + when(log.isDebugEnabled()).thenReturn(false); + when(log.isInfoEnabled()).thenReturn(false); + + FileProjectSaver projectSaver = mock(FileProjectSaver.class); + doNothing().when(projectSaver).save(any(Project.class)); + + MapLoader mapLoader = mock(MapLoader.class); + stub(mapLoader.loadDataMap(any(InputSource.class))).toReturn(new DataMapBuilder().with( + dbEntity("ARTGROUP").attributes( + dbAttr("NAME").typeVarchar(100).mandatory() + )).build()); + + DbImportActionDefault action = buildDbImportAction(log, projectSaver, mapLoader); + + action.execute(params); + + verify(projectSaver, never()).save(any(Project.class)); + verify(mapLoader, times(1)).loadDataMap(any(InputSource.class)); + } + + @Test + public void testImportWithDbError() throws Exception { + DbLoader dbLoader = mock(DbLoader.class); + when(dbLoader.getDefaultTableTypes()).thenReturn(null); + doThrow(new SQLException()).when(dbLoader).load(any(DataMap.class), any(DbLoaderConfiguration.class)); + + DbImportConfiguration params = mock(DbImportConfiguration.class); + when(params.createLoader(any(DbAdapter.class), any(Connection.class), any(DbLoaderDelegate.class))) + .thenReturn(dbLoader); + + FileProjectSaver projectSaver = mock(FileProjectSaver.class); + doNothing().when(projectSaver).save(any(Project.class)); + + MapLoader mapLoader = mock(MapLoader.class); + when(mapLoader.loadDataMap(any(InputSource.class))).thenReturn(null); + + DbImportActionDefault action = buildDbImportAction(projectSaver, mapLoader); + + try { + action.execute(params); + fail(); + } catch (SQLException e) { + // expected + } + + verify(projectSaver, never()).save(any(Project.class)); + verify(mapLoader, never()).loadDataMap(any(InputSource.class)); + } + + private DbImportActionDefault buildDbImportAction(FileProjectSaver projectSaver, MapLoader mapLoader) throws Exception { + Log log = mock(Log.class); + when(log.isDebugEnabled()).thenReturn(true); + when(log.isInfoEnabled()).thenReturn(true); + + return buildDbImportAction(log, projectSaver, mapLoader); + } + + private DbImportActionDefault buildDbImportAction(Log log, FileProjectSaver projectSaver, MapLoader mapLoader) throws Exception { + DbAdapter dbAdapter = mock(DbAdapter.class); + when(dbAdapter.mergerFactory()).thenReturn(new MergerFactory()); + + DbAdapterFactory adapterFactory = mock(DbAdapterFactory.class); + when(adapterFactory.createAdapter(any(DataNodeDescriptor.class), any(DataSource.class))).thenReturn(dbAdapter); + + DataSourceFactory dataSourceFactory = mock(DataSourceFactory.class); + DataSource mock = mock(DataSource.class); + when(dataSourceFactory.getDataSource(any(DataNodeDescriptor.class))).thenReturn(mock); + + return new DbImportActionDefault(log, projectSaver, dataSourceFactory, adapterFactory, mapLoader); + } + + @Test + public void testSaveLoaded() throws Exception { + Log log = mock(Log.class); + Injector i = DIBootstrap.createInjector(new ToolsModule(log), new DbImportModule()); + + DbImportActionDefault action = (DbImportActionDefault) i.getInstance(DbImportAction.class); + + String packagePath = getClass().getPackage().getName().replace('.', '/'); + URL packageUrl = getClass().getClassLoader().getResource(packagePath); + assertNotNull(packageUrl); + URL outUrl = new URL(packageUrl, "dbimport/testSaveLoaded1.map.xml"); + + File out = new File(outUrl.toURI()); + out.delete(); + assertFalse(out.isFile()); + + DataMap map = new DataMap("testSaveLoaded1"); + map.setConfigurationSource(new URLResource(outUrl)); - action.saveLoaded(map); + action.saveLoaded(map); - assertTrue(out.isFile()); + assertTrue(out.isFile()); - String contents = Util.stringFromFile(out); - assertTrue("Has no project version saved", contents.contains("project-version=\"")); - } + String contents = Util.stringFromFile(out); + assertTrue("Has no project version saved", contents.contains("project-version=\"")); + } - @Test - public void testMergeTokensSorting() { - LinkedList tokens = new LinkedList(); - tokens.add(new AddColumnToDb(null, null)); - tokens.add(new AddRelationshipToDb(null, null)); - tokens.add(new CreateTableToDb(null)); - tokens.add(new CreateTableToModel(null)); + @Test + public void testMergeTokensSorting() { + LinkedList tokens = new LinkedList(); + tokens.add(new AddColumnToDb(null, null)); + tokens.add(new AddRelationshipToDb(null, null)); + tokens.add(new CreateTableToDb(null)); + tokens.add(new CreateTableToModel(null)); - assertEquals(asList("AddColumnToDb", "CreateTableToDb", "CreateTableToModel", "AddRelationshipToDb"), - toClasses(DbImportAction.sort(tokens))); - } + assertEquals(asList("AddColumnToDb", "CreateTableToDb", "CreateTableToModel", "AddRelationshipToDb"), + toClasses(DbImportActionDefault.sort(tokens))); + } - private List toClasses(List sort) { - LinkedList res = new LinkedList(); - for (MergerToken mergerToken : sort) { - res.add(mergerToken.getClass().getSimpleName()); - } - return res; - } -} + private List toClasses(List sort) { + LinkedList res = new LinkedList(); + for (MergerToken mergerToken : sort) { + res.add(mergerToken.getClass().getSimpleName()); + } + return res; + } +} \ No newline at end of file diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegateTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegateTest.java index 52bae8a43d..2e8bc60896 100644 --- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegateTest.java +++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegateTest.java @@ -99,4 +99,4 @@ public void testObjEntityRemoved() { assertEquals(Arrays.asList(objEntity), delegate.getRemovedObjEntities()); } -} +} \ No newline at end of file diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportModuleTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportModuleTest.java index 62b65ea364..5eab2263be 100644 --- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportModuleTest.java +++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportModuleTest.java @@ -36,4 +36,4 @@ public void testModuleContents() { Injector i = DIBootstrap.createInjector(new ToolsModule(log), new DbImportModule()); assertTrue(i.getInstance(DbImportAction.class) instanceof DbImportAction); } -} +} \ No newline at end of file diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/CayenneModelerFrame.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/CayenneModelerFrame.java index bf1f398e72..0b78d9e7ed 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/CayenneModelerFrame.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/CayenneModelerFrame.java @@ -62,7 +62,7 @@ import org.apache.cayenne.modeler.action.FindAction; import org.apache.cayenne.modeler.action.GenerateCodeAction; import org.apache.cayenne.modeler.action.GenerateDBAction; -import org.apache.cayenne.modeler.action.ImportDBAction; +import org.apache.cayenne.modeler.action.ReverseEngineeringAction; import org.apache.cayenne.modeler.action.ImportDataMapAction; import org.apache.cayenne.modeler.action.ImportEOModelAction; import org.apache.cayenne.modeler.action.InferRelationshipsAction; @@ -224,7 +224,7 @@ protected void initMenus() { projectMenu.addSeparator(); projectMenu.add(getAction(RemoveAction.class).buildMenu()); - toolMenu.add(getAction(ImportDBAction.class).buildMenu()); + toolMenu.add(getAction(ReverseEngineeringAction.class).buildMenu()); toolMenu.add(getAction(InferRelationshipsAction.class).buildMenu()); toolMenu.add(getAction(ImportEOModelAction.class).buildMenu()); toolMenu.addSeparator(); diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectController.java index 4d756854f2..3e1160339f 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectController.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ProjectController.java @@ -619,11 +619,11 @@ public void removeDbEntityListener(DbEntityListener listener) { } public void addProjectOnSaveListener(ProjectOnSaveListener listener) { - listenerList.add(ProjectOnSaveListener.class, listener); + listenerList.add(ProjectOnSaveListener.class, listener); } public void removeProjectOnSaveListener(ProjectOnSaveListener listener) { - listenerList.remove(ProjectOnSaveListener.class, listener); + listenerList.remove(ProjectOnSaveListener.class, listener); } public void addObjEntityListener(ObjEntityListener listener) { @@ -774,11 +774,11 @@ public void fireDomainEvent(DomainEvent e) { for (EventListener listener : listenerList.getListeners(DomainListener.class)) { DomainListener temp = (DomainListener) listener; switch (e.getId()) { - case MapEvent.CHANGE: - temp.domainChanged(e); - break; - default: - throw new IllegalArgumentException("Invalid DomainEvent type: " + e.getId()); + case MapEvent.CHANGE: + temp.domainChanged(e); + break; + default: + throw new IllegalArgumentException("Invalid DomainEvent type: " + e.getId()); } } } @@ -825,17 +825,17 @@ public void fireDataNodeEvent(DataNodeEvent e) { for (EventListener listener : listenerList.getListeners(DataNodeListener.class)) { DataNodeListener temp = (DataNodeListener) listener; switch (e.getId()) { - case MapEvent.ADD: - temp.dataNodeAdded(e); - break; - case MapEvent.CHANGE: - temp.dataNodeChanged(e); - break; - case MapEvent.REMOVE: - temp.dataNodeRemoved(e); - break; - default: - throw new IllegalArgumentException("Invalid DataNodeEvent type: " + e.getId()); + case MapEvent.ADD: + temp.dataNodeAdded(e); + break; + case MapEvent.CHANGE: + temp.dataNodeChanged(e); + break; + case MapEvent.REMOVE: + temp.dataNodeRemoved(e); + break; + default: + throw new IllegalArgumentException("Invalid DataNodeEvent type: " + e.getId()); } } } @@ -865,7 +865,7 @@ public void fireDataMapDisplayEvent(DataMapDisplayEvent e) { EventListener[] list = listenerList.getListeners(DataMapDisplayListener.class); for (EventListener listener : list) { DataMapDisplayListener temp = (DataMapDisplayListener) listener; - temp.currentDataMapChanged(e); + temp.currentDataMapChanged(e); } } @@ -883,17 +883,17 @@ public void fireDataMapEvent(DataMapEvent e) { for (EventListener eventListener : listenerList.getListeners(DataMapListener.class)) { DataMapListener listener = (DataMapListener) eventListener; switch (e.getId()) { - case MapEvent.ADD: - listener.dataMapAdded(e); - break; - case MapEvent.CHANGE: - listener.dataMapChanged(e); - break; - case MapEvent.REMOVE: - listener.dataMapRemoved(e); - break; - default: - throw new IllegalArgumentException("Invalid DataMapEvent type: " + e.getId()); + case MapEvent.ADD: + listener.dataMapAdded(e); + break; + case MapEvent.CHANGE: + listener.dataMapChanged(e); + break; + case MapEvent.REMOVE: + listener.dataMapRemoved(e); + break; + default: + throw new IllegalArgumentException("Invalid DataMapEvent type: " + e.getId()); } } } @@ -916,17 +916,17 @@ public void fireObjEntityEvent(EntityEvent e) { for (EventListener listener : listenerList.getListeners(ObjEntityListener.class)) { ObjEntityListener temp = (ObjEntityListener) listener; switch (e.getId()) { - case MapEvent.ADD: - temp.objEntityAdded(e); - break; - case MapEvent.CHANGE: - temp.objEntityChanged(e); - break; - case MapEvent.REMOVE: - temp.objEntityRemoved(e); - break; - default: - throw new IllegalArgumentException("Invalid EntityEvent type: " + e.getId()); + case MapEvent.ADD: + temp.objEntityAdded(e); + break; + case MapEvent.CHANGE: + temp.objEntityChanged(e); + break; + case MapEvent.REMOVE: + temp.objEntityRemoved(e); + break; + default: + throw new IllegalArgumentException("Invalid EntityEvent type: " + e.getId()); } } } @@ -949,17 +949,17 @@ public void fireDbEntityEvent(EntityEvent e) { for (EventListener listener : listenerList.getListeners(DbEntityListener.class)) { DbEntityListener temp = (DbEntityListener) listener; switch (e.getId()) { - case MapEvent.ADD: - temp.dbEntityAdded(e); - break; - case MapEvent.CHANGE: - temp.dbEntityChanged(e); - break; - case MapEvent.REMOVE: - temp.dbEntityRemoved(e); - break; - default: - throw new IllegalArgumentException("Invalid EntityEvent type: " + e.getId()); + case MapEvent.ADD: + temp.dbEntityAdded(e); + break; + case MapEvent.CHANGE: + temp.dbEntityChanged(e); + break; + case MapEvent.REMOVE: + temp.dbEntityRemoved(e); + break; + default: + throw new IllegalArgumentException("Invalid EntityEvent type: " + e.getId()); } } } @@ -978,17 +978,17 @@ public void fireQueryEvent(QueryEvent e) { for (EventListener eventListener : listenerList.getListeners(QueryListener.class)) { QueryListener listener = (QueryListener) eventListener; switch (e.getId()) { - case MapEvent.ADD: - listener.queryAdded(e); - break; - case MapEvent.CHANGE: - listener.queryChanged(e); - break; - case MapEvent.REMOVE: - listener.queryRemoved(e); - break; - default: - throw new IllegalArgumentException("Invalid ProcedureEvent type: " + e.getId()); + case MapEvent.ADD: + listener.queryAdded(e); + break; + case MapEvent.CHANGE: + listener.queryChanged(e); + break; + case MapEvent.REMOVE: + listener.queryRemoved(e); + break; + default: + throw new IllegalArgumentException("Invalid ProcedureEvent type: " + e.getId()); } } } @@ -1007,17 +1007,17 @@ public void fireProcedureEvent(ProcedureEvent e) { for (EventListener eventListener : listenerList.getListeners(ProcedureListener.class)) { ProcedureListener listener = (ProcedureListener) eventListener; switch (e.getId()) { - case MapEvent.ADD: - listener.procedureAdded(e); - break; - case MapEvent.CHANGE: - listener.procedureChanged(e); - break; - case MapEvent.REMOVE: - listener.procedureRemoved(e); - break; - default: - throw new IllegalArgumentException("Invalid ProcedureEvent type: " + e.getId()); + case MapEvent.ADD: + listener.procedureAdded(e); + break; + case MapEvent.CHANGE: + listener.procedureChanged(e); + break; + case MapEvent.REMOVE: + listener.procedureRemoved(e); + break; + default: + throw new IllegalArgumentException("Invalid ProcedureEvent type: " + e.getId()); } } } @@ -1033,17 +1033,17 @@ public void fireProcedureParameterEvent(ProcedureParameterEvent e) { for (EventListener eventListener : list) { ProcedureParameterListener listener = (ProcedureParameterListener) eventListener; switch (e.getId()) { - case MapEvent.ADD: - listener.procedureParameterAdded(e); - break; - case MapEvent.CHANGE: - listener.procedureParameterChanged(e); - break; - case MapEvent.REMOVE: - listener.procedureParameterRemoved(e); - break; - default: - throw new IllegalArgumentException("Invalid ProcedureParameterEvent type: " + e.getId()); + case MapEvent.ADD: + listener.procedureParameterAdded(e); + break; + case MapEvent.CHANGE: + listener.procedureParameterChanged(e); + break; + case MapEvent.REMOVE: + listener.procedureParameterRemoved(e); + break; + default: + throw new IllegalArgumentException("Invalid ProcedureParameterEvent type: " + e.getId()); } } } @@ -1317,17 +1317,17 @@ public void fireDbAttributeEvent(AttributeEvent e) { for (EventListener listener : listenerList.getListeners(DbAttributeListener.class)) { DbAttributeListener temp = (DbAttributeListener) listener; switch (e.getId()) { - case MapEvent.ADD: - temp.dbAttributeAdded(e); - break; - case MapEvent.CHANGE: - temp.dbAttributeChanged(e); - break; - case MapEvent.REMOVE: - temp.dbAttributeRemoved(e); - break; - default: - throw new IllegalArgumentException("Invalid AttributeEvent type: " + e.getId()); + case MapEvent.ADD: + temp.dbAttributeAdded(e); + break; + case MapEvent.CHANGE: + temp.dbAttributeChanged(e); + break; + case MapEvent.REMOVE: + temp.dbAttributeRemoved(e); + break; + default: + throw new IllegalArgumentException("Invalid AttributeEvent type: " + e.getId()); } } } @@ -1359,17 +1359,17 @@ public void fireObjAttributeEvent(AttributeEvent e) { for (EventListener listener : listenerList.getListeners(ObjAttributeListener.class)) { ObjAttributeListener temp = (ObjAttributeListener) listener; switch (e.getId()) { - case MapEvent.ADD: - temp.objAttributeAdded(e); - break; - case MapEvent.CHANGE: - temp.objAttributeChanged(e); - break; - case MapEvent.REMOVE: - temp.objAttributeRemoved(e); - break; - default: - throw new IllegalArgumentException("Invalid AttributeEvent type: " + e.getId()); + case MapEvent.ADD: + temp.objAttributeAdded(e); + break; + case MapEvent.CHANGE: + temp.objAttributeChanged(e); + break; + case MapEvent.REMOVE: + temp.objAttributeRemoved(e); + break; + default: + throw new IllegalArgumentException("Invalid AttributeEvent type: " + e.getId()); } } } @@ -1427,17 +1427,17 @@ public void fireDbRelationshipEvent(RelationshipEvent e) { for (EventListener listener : listenerList.getListeners(DbRelationshipListener.class)) { DbRelationshipListener temp = (DbRelationshipListener) listener; switch (e.getId()) { - case MapEvent.ADD: - temp.dbRelationshipAdded(e); - break; - case MapEvent.CHANGE: - temp.dbRelationshipChanged(e); - break; - case MapEvent.REMOVE: - temp.dbRelationshipRemoved(e); - break; - default: - throw new IllegalArgumentException("Invalid RelationshipEvent type: " + e.getId()); + case MapEvent.ADD: + temp.dbRelationshipAdded(e); + break; + case MapEvent.CHANGE: + temp.dbRelationshipChanged(e); + break; + case MapEvent.REMOVE: + temp.dbRelationshipRemoved(e); + break; + default: + throw new IllegalArgumentException("Invalid RelationshipEvent type: " + e.getId()); } } } @@ -1469,17 +1469,17 @@ public void fireObjRelationshipEvent(RelationshipEvent e) { for (EventListener listener : listenerList.getListeners(ObjRelationshipListener.class)) { ObjRelationshipListener temp = (ObjRelationshipListener) listener; switch (e.getId()) { - case MapEvent.ADD: - temp.objRelationshipAdded(e); - break; - case MapEvent.CHANGE: - temp.objRelationshipChanged(e); - break; - case MapEvent.REMOVE: - temp.objRelationshipRemoved(e); - break; - default: - throw new IllegalArgumentException("Invalid RelationshipEvent type: " + e.getId()); + case MapEvent.ADD: + temp.objRelationshipAdded(e); + break; + case MapEvent.CHANGE: + temp.objRelationshipChanged(e); + break; + case MapEvent.REMOVE: + temp.objRelationshipRemoved(e); + break; + default: + throw new IllegalArgumentException("Invalid RelationshipEvent type: " + e.getId()); } } } @@ -1616,17 +1616,17 @@ public void fireCallbackMethodEvent(CallbackMethodEvent e) { for (EventListener listener : listenerList.getListeners(CallbackMethodListener.class)) { CallbackMethodListener temp = (CallbackMethodListener) listener; switch (e.getId()) { - case MapEvent.ADD: - temp.callbackMethodAdded(e); - break; - case MapEvent.CHANGE: - temp.callbackMethodChanged(e); - break; - case MapEvent.REMOVE: - temp.callbackMethodRemoved(e); - break; - default: - throw new IllegalArgumentException("Invalid CallbackEvent type: " + e.getId()); + case MapEvent.ADD: + temp.callbackMethodAdded(e); + break; + case MapEvent.CHANGE: + temp.callbackMethodChanged(e); + break; + case MapEvent.REMOVE: + temp.callbackMethodRemoved(e); + break; + default: + throw new IllegalArgumentException("Invalid CallbackEvent type: " + e.getId()); } } } @@ -1653,17 +1653,17 @@ public void fireEntityListenerEvent(EntityListenerEvent e) { for (EventListener listener : listenerList.getListeners(EntityListenerListener.class)) { EntityListenerListener temp = (EntityListenerListener) listener; switch (e.getId()) { - case MapEvent.ADD: - temp.entityListenerAdded(e); - break; - case MapEvent.CHANGE: - temp.entityListenerChanged(e); - break; - case MapEvent.REMOVE: - temp.entityListenerRemoved(e); - break; - default: - throw new IllegalArgumentException("Invalid CallbackEvent type: " + e.getId()); + case MapEvent.ADD: + temp.entityListenerAdded(e); + break; + case MapEvent.CHANGE: + temp.entityListenerChanged(e); + break; + case MapEvent.REMOVE: + temp.entityListenerRemoved(e); + break; + default: + throw new IllegalArgumentException("Invalid CallbackEvent type: " + e.getId()); } } } @@ -1735,17 +1735,17 @@ public void fireEmbeddableEvent(EmbeddableEvent e, DataMap map) { EmbeddableListener temp = (EmbeddableListener) listener; switch (e.getId()) { - case MapEvent.ADD: - temp.embeddableAdded(e, map); - break; - case MapEvent.CHANGE: - temp.embeddableChanged(e, map); - break; - case MapEvent.REMOVE: - temp.embeddableRemoved(e, map); - break; - default: - throw new IllegalArgumentException("Invalid RelationshipEvent type: " + e.getId()); + case MapEvent.ADD: + temp.embeddableAdded(e, map); + break; + case MapEvent.CHANGE: + temp.embeddableChanged(e, map); + break; + case MapEvent.REMOVE: + temp.embeddableRemoved(e, map); + break; + default: + throw new IllegalArgumentException("Invalid RelationshipEvent type: " + e.getId()); } } } @@ -1756,27 +1756,27 @@ public void fireEmbeddableAttributeEvent(EmbeddableAttributeEvent e) { EmbeddableAttributeListener temp = (EmbeddableAttributeListener) listener; switch (e.getId()) { - case MapEvent.ADD: - temp.embeddableAttributeAdded(e); - break; - case MapEvent.CHANGE: - temp.embeddableAttributeChanged(e); - break; - case MapEvent.REMOVE: - temp.embeddableAttributeRemoved(e); - break; - default: - throw new IllegalArgumentException("Invalid RelationshipEvent type: " + e.getId()); + case MapEvent.ADD: + temp.embeddableAttributeAdded(e); + break; + case MapEvent.CHANGE: + temp.embeddableAttributeChanged(e); + break; + case MapEvent.REMOVE: + temp.embeddableAttributeRemoved(e); + break; + default: + throw new IllegalArgumentException("Invalid RelationshipEvent type: " + e.getId()); } } } - + public void fireProjectOnSaveEvent(ProjectOnSaveEvent e){ - for(EventListener listener : listenerList.getListeners(ProjectOnSaveListener.class)){ - ProjectOnSaveListener temp = (ProjectOnSaveListener) listener; - temp.beforeSaveChanges(e); - } - + for(EventListener listener : listenerList.getListeners(ProjectOnSaveListener.class)){ + ProjectOnSaveListener temp = (ProjectOnSaveListener) listener; + temp.beforeSaveChanges(e); + } + } public ArrayList getEmbeddableNamesInCurRentDataDomain() { @@ -1820,8 +1820,8 @@ public int getEntityTabSelection() { */ public void setEntityTabSelection(int entityTabSelection) { this.entityTabSelection = entityTabSelection; - } - + } + /** * If true, all save buttons become available. * @param enable @@ -1832,29 +1832,29 @@ public void enableSave(boolean enable) { } /** - * Set currently selected ObjAttributes - */ + * Set currently selected ObjAttributes + */ public void setCurrentObjAttributes(ObjAttribute[] attrs) { -currentState.objAttrs = attrs; -} + currentState.objAttrs = attrs; + } /** - * Set currently selected ObjRelationships - */ + * Set currently selected ObjRelationships + */ public void setCurrentObjRelationships(ObjRelationship[] rels) { -currentState.objRels = rels; -} + currentState.objRels = rels; + } /** - * Set currently selected DbAttributes - */ + * Set currently selected DbAttributes + */ public void setCurrentDbAttributes(DbAttribute[] attrs) { currentState.dbAttrs = attrs; } /** - * Set currently selected DbRelationships - */ + * Set currently selected DbRelationships + */ public void setCurrentDbRelationships(DbRelationship[] rels) { currentState.dbRels = rels; } 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 c625bb4073..80bd3557bb 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 @@ -95,7 +95,7 @@ public DefaultActionManager(@Inject Application application) { registerAction(new ObjEntitySyncAction(application)); registerAction(new DbEntityCounterpartAction(application)); registerAction(new ObjEntityCounterpartAction(application)); - registerAction(new ImportDBAction(application)); + registerAction(new ReverseEngineeringAction(application)); registerAction(new InferRelationshipsAction(application)); registerAction(new ImportEOModelAction(application)); registerAction(new GenerateDBAction(application)); @@ -165,7 +165,7 @@ private void initActions() { CreateDataMapAction.class.getName(), RemoveAction.class.getName(), CreateNodeAction.class.getName(), - ImportDBAction.class.getName(), + ReverseEngineeringAction.class.getName(), ImportEOModelAction.class.getName(), GenerateCodeAction.class.getName(), GenerateDBAction.class.getName(), diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MigrateAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MigrateAction.java index c5f33145b8..dce909eb5f 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MigrateAction.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MigrateAction.java @@ -29,7 +29,7 @@ import org.apache.cayenne.dba.DbAdapter; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.modeler.Application; -import org.apache.cayenne.modeler.dialog.db.DataSourceWizard; +import org.apache.cayenne.modeler.dialog.db.DataSourceController; import org.apache.cayenne.modeler.dialog.db.DbMigrateOptionsDialog; import org.apache.cayenne.modeler.dialog.db.MergerOptions; import org.apache.cayenne.modeler.pref.DBConnectionInfo; @@ -52,7 +52,7 @@ public void performAction(ActionEvent e) { DBConnectionInfo nodeInfo = preferredDataSource(); String nodeKey = preferredDataSourceLabel(nodeInfo); - DataSourceWizard connectWizard = new DataSourceWizard( + DataSourceController connectWizard = new DataSourceController( getProjectController(), "Migrate DB Schema: Connect to Database", nodeKey, @@ -62,10 +62,10 @@ public void performAction(ActionEvent e) { // canceled return; } - + DataMap map = getProjectController().getCurrentDataMap(); //migarte options - + // sanity check if (map == null) { throw new IllegalStateException("No current DataMap selected."); @@ -88,7 +88,7 @@ public void performAction(ActionEvent e) { "Error loading schemas dialog", JOptionPane.ERROR_MESSAGE); } - + // ... show dialog... new MergerOptions( @@ -97,8 +97,8 @@ public void performAction(ActionEvent e) { connectWizard.getConnectionInfo(), map, selectedSchema).startupAction(); } - - private List getSchemas(DataSourceWizard connectWizard) throws Exception { + + private List getSchemas(DataSourceController connectWizard) throws Exception { DbAdapter dbAdapter = connectWizard.getConnectionInfo() .makeAdapter(getApplication().getClassLoadingService()); DataSource dataSource = connectWizard.getConnectionInfo() diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/OpenProjectAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/OpenProjectAction.java index 61d89278d1..cb5bfc5312 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/OpenProjectAction.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/OpenProjectAction.java @@ -145,7 +145,7 @@ public void openProject(File file) { else if (UpgradeType.INTERMEDIATE_UPGRADE_NEEDED == md.getUpgradeType()) { JOptionPane .showMessageDialog(Application.getFrame(), - // TODO: andrus 05/02/2010 - this message shows intermediate + // TODO: andrus 05/02/2010 - this message shows intermediate // version of the project XML, not the Modeler code // version that // can be used for upgrade @@ -201,7 +201,6 @@ private Project openProjectResourse( .getInjector() .getInstance(ProjectLoader.class) .loadProject(resource); - controller.projectOpenedAction(project); return project; diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/RemoveAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/RemoveAction.java index 8dc55d09dc..8409a98725 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/RemoveAction.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/RemoveAction.java @@ -72,6 +72,7 @@ import java.awt.event.KeyEvent; import java.net.URL; import java.util.ArrayList; +import java.util.Collection; import java.util.Iterator; /** @@ -448,7 +449,12 @@ public void removeDataMap(DataMap map) { domain.getDataMaps().remove(map); if (map.getConfigurationSource() != null) { URL mapURL = map.getConfigurationSource().getURL(); - getCurrentProject().getUnusedResources().add(mapURL); + Collection unusedResources = getCurrentProject().getUnusedResources(); + unusedResources.add(mapURL); + if (map.getReverseEngineering() != null && map.getReverseEngineering().getConfigurationSource() != null) { + URL reverseEngineeringURL = map.getReverseEngineering().getConfigurationSource().getURL(); + unusedResources.add(reverseEngineeringURL); + } } Iterator iterator = domain.getNodeDescriptors().iterator(); diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportDBAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ReverseEngineeringAction.java similarity index 51% rename from modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportDBAction.java rename to modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ReverseEngineeringAction.java index 95c8224bb1..287e703694 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ImportDBAction.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ReverseEngineeringAction.java @@ -24,22 +24,32 @@ import javax.swing.SwingUtilities; +import org.apache.cayenne.configuration.DataChannelDescriptor; +import org.apache.cayenne.configuration.event.DataMapEvent; import org.apache.cayenne.dba.DbAdapter; +import org.apache.cayenne.map.DataMap; +import org.apache.cayenne.map.event.MapEvent; +import org.apache.cayenne.map.naming.DefaultUniqueNameGenerator; +import org.apache.cayenne.map.naming.NameCheckers; import org.apache.cayenne.modeler.Application; -import org.apache.cayenne.modeler.dialog.db.ConnectionWizard; +import org.apache.cayenne.modeler.CayenneModelerController; +import org.apache.cayenne.modeler.ProjectController; +import org.apache.cayenne.modeler.dialog.db.ReverseEngineeringController; import org.apache.cayenne.modeler.dialog.db.DbLoaderHelper; +import org.apache.cayenne.modeler.dialog.db.ReverseEngineeringScrollPane; import org.apache.cayenne.modeler.pref.DBConnectionInfo; +import org.apache.cayenne.modeler.util.CayenneAction; /** * Action that imports database structure into a DataMap. */ -public class ImportDBAction extends DBWizardAction { +public class ReverseEngineeringAction extends CayenneAction { public static String getActionName() { return "Reengineer Database Schema"; } - public ImportDBAction(Application application) { + public ReverseEngineeringAction(Application application) { super(getActionName(), application); } @@ -47,50 +57,21 @@ public ImportDBAction(Application application) { * Connects to DB and delegates processing to DbLoaderController, starting it * asynchronously. */ + @Override public void performAction(ActionEvent event) { - - // guess node connection - DBConnectionInfo nodeInfo = preferredDataSource(); - String nodeKey = preferredDataSourceLabel(nodeInfo); - - // connect - ConnectionWizard connectWizard = new ConnectionWizard( - getProjectController(), - "Reengineer DB Schema: Connect to Database", - nodeKey, - nodeInfo); - - if (!connectWizard.startupAction()) { - // canceled - return; + ProjectController projectController = getProjectController(); + DataMap dataMap = projectController.getCurrentDataMap(); + DataChannelDescriptor dataChannelDescriptor = projectController.getCurrentDataChanel(); + if (dataMap == null) { + dataMap = new DataMap(DefaultUniqueNameGenerator.generate(NameCheckers.dataMap)); + dataMap.setName(DefaultUniqueNameGenerator.generate(NameCheckers.dataMap, projectController.getProject().getRootNode())); + dataChannelDescriptor.getDataMaps().add(dataMap); + getProjectController().fireDataMapEvent(new DataMapEvent(this, dataMap, MapEvent.ADD)); } - Connection connection = connectWizard.getConnection(); - DbAdapter adapter = connectWizard.getAdapter(); - DBConnectionInfo dataSourceInfo = connectWizard.getConnectionInfo(); - - // from here pass control to DbLoaderHelper, running it from a thread separate - // from EventDispatch - - final DbLoaderHelper helper = new DbLoaderHelper( - getProjectController(), - connection, - adapter, - dataSourceInfo.getUserName()); - Thread th = new Thread(new Runnable() { - - public void run() { - helper.execute(); - - SwingUtilities.invokeLater(new Runnable() { - - public void run() { - application.getUndoManager().discardAllEdits(); - } - }); - } - }); - - th.start(); + ((CayenneModelerController) projectController.getParent()) + .getEditorView() + .getDataMapView() + .setSelectedIndex(1); } } diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ConnectionWizard.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ConnectionWizard.java deleted file mode 100644 index dfe24b31ed..0000000000 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ConnectionWizard.java +++ /dev/null @@ -1,89 +0,0 @@ -/***************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - ****************************************************************/ - -package org.apache.cayenne.modeler.dialog.db; - -import java.sql.Connection; - -import org.apache.cayenne.dba.DbAdapter; -import org.apache.cayenne.modeler.ClassLoadingService; -import org.apache.cayenne.modeler.pref.DBConnectionInfo; -import org.apache.cayenne.modeler.util.CayenneController; - -/** - * A component for choosing a DataSource. Users can choose from the DataSources configured - * in preferences, and one extra set of connection settings. This object will create and - * keep open a JDBC connection. It is caller responsibility to dispose of it properly. - * - */ -// TODO: after refactoring DbLoader to accept a DataSource instead of connection this -// dialog should be merged with superclass - DataSourceWizard. -public class ConnectionWizard extends DataSourceWizard { - protected Connection connection; - protected DbAdapter adapter; - - public ConnectionWizard(CayenneController parent, String title, - String altDataSourceKey, DBConnectionInfo altDataSource) { - super(parent, title, altDataSourceKey, altDataSource); - } - - /** - * Overrides superclass to keep an open connection around for the caller's use. - */ - public void okAction() { - // build connection and adapter... - - DBConnectionInfo info = getConnectionInfo(); - ClassLoadingService classLoader = getApplication().getClassLoadingService(); - - try { - this.adapter = info.makeAdapter(classLoader); - } - catch (Throwable th) { - reportError("DbAdapter Error", th); - return; - } - - try { - this.connection = info.makeDataSource(classLoader).getConnection(); - } - catch (Throwable th) { - reportError("Connection Error", th); - return; - } - - // set success flag, and unblock the caller... - canceled = false; - view.dispose(); - } - - /** - * Returns configured DB connection. - */ - public Connection getConnection() { - return connection; - } - - /** - * Returns configured DbAdapter. - */ - public DbAdapter getAdapter() { - return adapter; - } -} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DBGeneratorOptions.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DBGeneratorOptions.java index 4e277d1010..1747c87f0f 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DBGeneratorOptions.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DBGeneratorOptions.java @@ -249,7 +249,7 @@ public void refreshSQLAction() { */ public void generateSchemaAction() { - DataSourceWizard connectWizard = new DataSourceWizard( + DataSourceController connectWizard = new DataSourceController( this.getParent(), "Generate DB Schema: Connect to Database", null, diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataMapViewModel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataMapViewModel.java new file mode 100644 index 0000000000..17482075d6 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataMapViewModel.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cayenne.modeler.dialog.db; + +import org.apache.cayenne.modeler.dialog.db.model.DBModel; + +/** + * @since 4.0 + */ +public class DataMapViewModel { + private final String dataMapName; + + private String reverseEngineeringText; + private DBModel reverseEngineeringTree; + + public DataMapViewModel(String dataMapName) { + this.dataMapName = dataMapName; + } + + public String getReverseEngineeringText() { + return reverseEngineeringText; + } + + public void setReverseEngineeringText(String reverseEngineeringText) { + this.reverseEngineeringText = reverseEngineeringText; + } + + public DBModel getReverseEngineeringTree() { + return reverseEngineeringTree; + } + + public void setReverseEngineeringTree(DBModel reverseEngineeringTree) { + this.reverseEngineeringTree = reverseEngineeringTree; + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceController.java new file mode 100644 index 0000000000..2ba7819271 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceController.java @@ -0,0 +1,219 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.dialog.db; + +import java.awt.Component; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.Iterator; +import java.util.Map; + +import org.apache.cayenne.modeler.ClassLoadingService; +import org.apache.cayenne.modeler.dialog.pref.PreferenceDialog; +import org.apache.cayenne.modeler.pref.DBConnectionInfo; +import org.apache.cayenne.modeler.util.CayenneController; +import org.apache.cayenne.swing.BindingBuilder; +import org.apache.cayenne.swing.ObjectBinding; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.WindowConstants; + +public class DataSourceController extends CayenneController { + + protected DataSourceView view; + + protected DBConnectionInfo altDataSource; + protected String altDataSourceKey; + protected ObjectBinding dataSourceBinding; + protected Map dataSources; + + protected String dataSourceKey; + + // this object is a clone of an object selected from the dropdown, as we + // need to allow + // local temporary modifications + protected DBConnectionInfo connectionInfo; + + protected boolean canceled; + + public DataSourceController(CayenneController parent, String title, String altDataSourceKey, + DBConnectionInfo altDataSource) { + super(parent); + + this.view = createView(); + this.view.setTitle(title); + this.altDataSource = altDataSource; + this.altDataSourceKey = altDataSourceKey; + this.connectionInfo = new DBConnectionInfo(); + + initBindings(); + } + + /** + * Creates swing dialog for this wizard + */ + protected DataSourceView createView() { + return new DataSourceView(this); + } + + protected void initBindings() { + BindingBuilder builder = new BindingBuilder(getApplication().getBindingFactory(), this); + + dataSourceBinding = builder.bindToComboSelection(view.getDataSources(), "dataSourceKey"); + + builder.bindToAction(view.getCancelButton(), "cancelAction()"); + builder.bindToAction(view.getOkButton(), "okAction()"); + builder.bindToAction(view.getConfigButton(), "dataSourceConfigAction()"); + } + + public String getDataSourceKey() { + return dataSourceKey; + } + + public void setDataSourceKey(String dataSourceKey) { + this.dataSourceKey = dataSourceKey; + + // update a clone object that will be used to obtain connection... + DBConnectionInfo currentInfo = (DBConnectionInfo) dataSources.get(dataSourceKey); + if (currentInfo != null) { + currentInfo.copyTo(connectionInfo); + } else { + connectionInfo = new DBConnectionInfo(); + } + + view.getConnectionInfo().setConnectionInfo(connectionInfo); + } + + /** + * Main action method that pops up a dialog asking for user selection. + * Returns true if the selection was confirmed, false - if canceled. + */ + public boolean startupAction() { + this.canceled = true; + + refreshDataSources(); + + view.pack(); + view.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + view.setModal(true); + makeCloseableOnEscape(); + centerView(); + view.setVisible(true); + + return !canceled; + } + + public DBConnectionInfo getConnectionInfo() { + return connectionInfo; + } + + /** + * Tests that the entered information is valid and can be used to open a + * conneciton. Does not store the open connection. + */ + public void okAction() { + DBConnectionInfo info = getConnectionInfo(); + ClassLoadingService classLoader = getApplication().getClassLoadingService(); + + // try making an adapter... + try { + info.makeAdapter(classLoader); + } catch (Throwable th) { + reportError("DbAdapter Error", th); + return; + } + + // doing connection testing... + // attempt opening the connection, and close it right away + try { + + try (Connection connection = info.makeDataSource(classLoader).getConnection();) { + // + } catch (SQLException ex) { + // ignore close error + } + } catch (Throwable th) { + reportError("Connection Error", th); + return; + } + + // set success flag, and unblock the caller... + canceled = false; + view.dispose(); + } + + public void cancelAction() { + canceled = true; + view.dispose(); + } + + /** + * Opens preferences panel to allow configuration of DataSource presets. + */ + public void dataSourceConfigAction() { + PreferenceDialog prefs = new PreferenceDialog(this); + prefs.showDataSourceEditorAction(dataSourceKey); + refreshDataSources(); + } + + public Component getView() { + return view; + } + + protected void refreshDataSources() { + this.dataSources = getApplication().getCayenneProjectPreferences().getDetailObject(DBConnectionInfo.class) + .getChildrenPreferences(); + + // 1.2 migration fix - update data source adapter names + Iterator it = dataSources.values().iterator(); + + final String _12package = "org.objectstyle.cayenne."; + while (it.hasNext()) { + DBConnectionInfo info = (DBConnectionInfo) it.next(); + if (info.getDbAdapter() != null && info.getDbAdapter().startsWith(_12package)) { + info.setDbAdapter("org.apache.cayenne." + info.getDbAdapter().substring(_12package.length())); + + // info.getObjectContext().commitChanges(); + } + } + + if (altDataSourceKey != null && !dataSources.containsKey(altDataSourceKey) && altDataSource != null) { + dataSources.put(altDataSourceKey, altDataSource); + } + + Object[] keys = dataSources.keySet().toArray(); + Arrays.sort(keys); + view.getDataSources().setModel(new DefaultComboBoxModel(keys)); + + if (getDataSourceKey() == null) { + String key = null; + + if (altDataSourceKey != null) { + key = altDataSourceKey; + } else if (keys.length > 0) { + key = keys[0].toString(); + } + + setDataSourceKey(key); + dataSourceBinding.updateView(); + } + } +} \ No newline at end of file diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceWizardView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceView.java similarity index 96% rename from modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceWizardView.java rename to modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceView.java index 10cf0d7215..3258a54fc7 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceWizardView.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceView.java @@ -37,7 +37,7 @@ /** */ -public class DataSourceWizardView extends JDialog { +public class DataSourceView extends JDialog { protected JComboBox dataSources; protected JButton configButton; @@ -45,9 +45,9 @@ public class DataSourceWizardView extends JDialog { protected JButton cancelButton; protected DBConnectionInfoEditor connectionInfo; - public DataSourceWizardView(CayenneController controller) { + public DataSourceView(CayenneController controller) { super(Application.getFrame()); - + this.dataSources = new JComboBox(); this.configButton = new JButton("..."); @@ -97,4 +97,4 @@ public JButton getOkButton() { public DBConnectionInfoEditor getConnectionInfo() { return connectionInfo; } -} +} \ No newline at end of file diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceWizard.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceWizard.java deleted file mode 100644 index 3ca4a9f3de..0000000000 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DataSourceWizard.java +++ /dev/null @@ -1,224 +0,0 @@ -/***************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - ****************************************************************/ - -package org.apache.cayenne.modeler.dialog.db; - -import java.awt.Component; -import java.sql.Connection; -import java.sql.SQLException; -import java.util.Arrays; -import java.util.Iterator; -import java.util.Map; - -import javax.swing.DefaultComboBoxModel; -import javax.swing.WindowConstants; - -import org.apache.cayenne.modeler.ClassLoadingService; -import org.apache.cayenne.modeler.dialog.pref.PreferenceDialog; -import org.apache.cayenne.modeler.pref.DBConnectionInfo; -import org.apache.cayenne.modeler.util.CayenneController; -import org.apache.cayenne.swing.BindingBuilder; -import org.apache.cayenne.swing.ObjectBinding; - -/** - * A subclass of ConnectionWizard that tests configured DataSource, but does not - * keep an open connection. - * - */ -public class DataSourceWizard extends CayenneController { - - protected DataSourceWizardView view; - - protected DBConnectionInfo altDataSource; - protected String altDataSourceKey; - protected ObjectBinding dataSourceBinding; - protected Map dataSources; - - protected String dataSourceKey; - - // this object is a clone of an object selected from the dropdown, as we - // need to allow - // local temporary modifications - protected DBConnectionInfo connectionInfo; - - protected boolean canceled; - - public DataSourceWizard(CayenneController parent, String title, String altDataSourceKey, - DBConnectionInfo altDataSource) { - super(parent); - - this.view = createView(); - this.view.setTitle(title); - this.altDataSource = altDataSource; - this.altDataSourceKey = altDataSourceKey; - this.connectionInfo = new DBConnectionInfo(); - - initBindings(); - } - - /** - * Creates swing dialog for this wizard - */ - protected DataSourceWizardView createView() { - return new DataSourceWizardView(this); - } - - protected void initBindings() { - BindingBuilder builder = new BindingBuilder(getApplication().getBindingFactory(), this); - - dataSourceBinding = builder.bindToComboSelection(view.getDataSources(), "dataSourceKey"); - - builder.bindToAction(view.getCancelButton(), "cancelAction()"); - builder.bindToAction(view.getOkButton(), "okAction()"); - builder.bindToAction(view.getConfigButton(), "dataSourceConfigAction()"); - } - - public String getDataSourceKey() { - return dataSourceKey; - } - - public void setDataSourceKey(String dataSourceKey) { - this.dataSourceKey = dataSourceKey; - - // update a clone object that will be used to obtain connection... - DBConnectionInfo currentInfo = (DBConnectionInfo) dataSources.get(dataSourceKey); - if (currentInfo != null) { - currentInfo.copyTo(connectionInfo); - } else { - connectionInfo = new DBConnectionInfo(); - } - - view.getConnectionInfo().setConnectionInfo(connectionInfo); - } - - /** - * Main action method that pops up a dialog asking for user selection. - * Returns true if the selection was confirmed, false - if canceled. - */ - public boolean startupAction() { - this.canceled = true; - - refreshDataSources(); - - view.pack(); - view.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - view.setModal(true); - makeCloseableOnEscape(); - centerView(); - view.setVisible(true); - - return !canceled; - } - - public DBConnectionInfo getConnectionInfo() { - return connectionInfo; - } - - /** - * Tests that the entered information is valid and can be used to open a - * conneciton. Does not store the open connection. - */ - public void okAction() { - DBConnectionInfo info = getConnectionInfo(); - ClassLoadingService classLoader = getApplication().getClassLoadingService(); - - // try making an adapter... - try { - info.makeAdapter(classLoader); - } catch (Throwable th) { - reportError("DbAdapter Error", th); - return; - } - - // doing connection testing... - // attempt opening the connection, and close it right away - try { - - try (Connection connection = info.makeDataSource(classLoader).getConnection();) { - // - } catch (SQLException ex) { - // ignore close error - } - } catch (Throwable th) { - reportError("Connection Error", th); - return; - } - - // set success flag, and unblock the caller... - canceled = false; - view.dispose(); - } - - public void cancelAction() { - canceled = true; - view.dispose(); - } - - /** - * Opens preferences panel to allow configuration of DataSource presets. - */ - public void dataSourceConfigAction() { - PreferenceDialog prefs = new PreferenceDialog(this); - prefs.showDataSourceEditorAction(dataSourceKey); - refreshDataSources(); - } - - public Component getView() { - return view; - } - - protected void refreshDataSources() { - this.dataSources = getApplication().getCayenneProjectPreferences().getDetailObject(DBConnectionInfo.class) - .getChildrenPreferences(); - - // 1.2 migration fix - update data source adapter names - Iterator it = dataSources.values().iterator(); - - final String _12package = "org.objectstyle.cayenne."; - while (it.hasNext()) { - DBConnectionInfo info = (DBConnectionInfo) it.next(); - if (info.getDbAdapter() != null && info.getDbAdapter().startsWith(_12package)) { - info.setDbAdapter("org.apache.cayenne." + info.getDbAdapter().substring(_12package.length())); - - // info.getObjectContext().commitChanges(); - } - } - - if (altDataSourceKey != null && !dataSources.containsKey(altDataSourceKey) && altDataSource != null) { - dataSources.put(altDataSourceKey, altDataSource); - } - - Object[] keys = dataSources.keySet().toArray(); - Arrays.sort(keys); - view.getDataSources().setModel(new DefaultComboBoxModel(keys)); - - if (getDataSourceKey() == null) { - String key = null; - - if (altDataSourceKey != null) { - key = altDataSourceKey; - } else if (keys.length > 0) { - key = keys[0].toString(); - } - - setDataSourceKey(key); - dataSourceBinding.updateView(); - } - } -} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbImportActionModeler.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbImportActionModeler.java new file mode 100644 index 0000000000..b131dd8554 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbImportActionModeler.java @@ -0,0 +1,120 @@ +package org.apache.cayenne.modeler.dialog.db; /***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + + +import org.apache.cayenne.configuration.DataChannelDescriptor; +import org.apache.cayenne.configuration.event.DataMapEvent; +import org.apache.cayenne.configuration.server.DataSourceFactory; +import org.apache.cayenne.configuration.server.DbAdapterFactory; +import org.apache.cayenne.dba.DbAdapter; +import org.apache.cayenne.di.Inject; +import org.apache.cayenne.map.DataMap; +import org.apache.cayenne.map.MapLoader; +import org.apache.cayenne.map.event.MapEvent; +import org.apache.cayenne.modeler.Application; +import org.apache.cayenne.modeler.ProjectController; +import org.apache.cayenne.modeler.event.DataMapDisplayEvent; +import org.apache.cayenne.project.ProjectSaver; +import org.apache.cayenne.resource.Resource; +import org.apache.cayenne.tools.dbimport.DbImportAction; +import org.apache.cayenne.tools.dbimport.DbImportActionDefault; +import org.apache.cayenne.tools.dbimport.DbImportConfiguration; +import org.apache.commons.logging.Log; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.sql.Connection; + +public class DbImportActionModeler implements DbImportAction { + + private final Log logger; + + private final DbLoaderHelper dbLoaderHelper; + + @Inject + private ProjectSaver projectSaver; + + @Inject + private DataSourceFactory dataSourceFactory; + + @Inject + private DbAdapterFactory adapterFactory; + + @Inject + private MapLoader mapLoader; + + public DbImportActionModeler(Log logger, DbLoaderHelper dbLoaderHelper) { + this.logger = logger; + this.dbLoaderHelper = dbLoaderHelper; + } + + @Override + public void execute(DbImportConfiguration config) throws Exception { + if (dbLoaderHelper == null) { + throw new IllegalStateException("Before using execute method you must set dbLoaderHelper"); + } + + new DbImportActionDefault(logger, projectSaver, dataSourceFactory, adapterFactory, mapLoader) { + + @Override + protected DataMap loadExistingDataMap(File dataMapFile) { + return dbLoaderHelper.getDataMap(); + } + + @Override + protected void saveLoaded(DataMap dataMap) { + dbLoaderHelper.cleanup(); + + ProjectController mediator = dbLoaderHelper.getMediator(); + + if (mediator.getCurrentDataMap() != null) { + mediator.fireDataMapEvent(new DataMapEvent(Application.getFrame(), dataMap, MapEvent.REMOVE)); + mediator.fireDataMapEvent(new DataMapEvent(Application.getFrame(), dataMap, MapEvent.ADD)); + } else { + DataChannelDescriptor currentDomain = (DataChannelDescriptor) mediator.getProject().getRootNode(); + Resource baseResource = currentDomain.getConfigurationSource(); + + // this will be new data map so need to set configuration source + // for it + if (baseResource != null) { + Resource dataMapResource = baseResource.getRelativeResource(dataMap.getName()); + dataMap.setConfigurationSource(dataMapResource); + } + mediator.addDataMap(Application.getFrame(), dataMap); + } + } + + @Override + protected DataMap load(DbImportConfiguration config, DbAdapter adapter, Connection connection) throws Exception { + DataMap dataMap; + + try { + dataMap = dbLoaderHelper.getLoader().load(config.getDbLoaderConfig()); + } finally { + if (connection != null) { + connection.close(); + } + } + + return dataMap; + } + }.execute(config); + } +} \ No newline at end of file diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbLoaderHelper.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbLoaderHelper.java index d81e4989bf..e629fcd1a2 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbLoaderHelper.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbLoaderHelper.java @@ -21,13 +21,13 @@ import org.apache.cayenne.CayenneRuntimeException; import org.apache.cayenne.access.DbLoader; -import org.apache.cayenne.access.loader.DbLoaderConfiguration; import org.apache.cayenne.access.loader.DefaultDbLoaderDelegate; -import org.apache.cayenne.access.loader.filters.OldFilterConfigBridge; import org.apache.cayenne.configuration.DataChannelDescriptor; -import org.apache.cayenne.configuration.DefaultConfigurationNameMapper; -import org.apache.cayenne.configuration.event.DataMapEvent; import org.apache.cayenne.dba.DbAdapter; +import org.apache.cayenne.dbimport.FiltersConfigBuilder; +import org.apache.cayenne.dbimport.ReverseEngineering; +import org.apache.cayenne.di.DIBootstrap; +import org.apache.cayenne.di.Injector; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.map.DbEntity; import org.apache.cayenne.map.DbRelationship; @@ -38,12 +38,11 @@ import org.apache.cayenne.map.naming.NameCheckers; import org.apache.cayenne.modeler.Application; import org.apache.cayenne.modeler.ProjectController; -import org.apache.cayenne.modeler.event.DataMapDisplayEvent; +import org.apache.cayenne.modeler.pref.DBConnectionInfo; import org.apache.cayenne.modeler.util.LongRunningTask; -import org.apache.cayenne.resource.Resource; -import org.apache.cayenne.tools.dbimport.config.FiltersConfigBuilder; -import org.apache.cayenne.tools.dbimport.config.ReverseEngineering; -import org.apache.cayenne.util.DeleteRuleUpdater; +import org.apache.cayenne.tools.configuration.ToolsModule; +import org.apache.cayenne.tools.dbimport.DbImportConfiguration; +import org.apache.cayenne.tools.dbimport.DbImportModule; import org.apache.cayenne.util.Util; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -51,16 +50,15 @@ import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; +import java.io.File; import java.sql.Connection; import java.sql.SQLException; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; /** * Stateful helper class that encapsulates access to DbLoader. - * */ public class DbLoaderHelper { @@ -75,17 +73,14 @@ public class DbLoaderHelper { protected boolean existingMap; protected ProjectController mediator; - protected String dbUserName; protected String dbCatalog; protected DbLoader loader; protected DataMap dataMap; - protected boolean meaningfulPk; protected List schemas; protected List catalogs; protected DbAdapter adapter; - - private final OldFilterConfigBridge filterBuilder = new OldFilterConfigBridge(); - + protected DbImportConfiguration config; + protected ReverseEngineering reverseEngineering; protected String loadStatusNote; /** @@ -93,8 +88,8 @@ public class DbLoaderHelper { */ protected List addedObjEntities; - public DbLoaderHelper(ProjectController mediator, Connection connection, DbAdapter adapter, String dbUserName) { - this.dbUserName = dbUserName; + public DbLoaderHelper(ProjectController mediator, Connection connection, DbAdapter adapter, + DBConnectionInfo dbConnectionInfo, ReverseEngineering reverseEngineering) { this.mediator = mediator; try { this.dbCatalog = connection.getCatalog(); @@ -102,7 +97,24 @@ public DbLoaderHelper(ProjectController mediator, Connection connection, DbAdapt logObj.warn("Error getting catalog.", e); } this.adapter = adapter; - this.loader = new DbLoader(connection, adapter, new LoaderDelegate()); + this.reverseEngineering = reverseEngineering; + + this.config = new DbImportConfiguration(); + this.config.setAdapter(adapter.getClass().getName()); + this.config.setUsername(dbConnectionInfo.getUserName()); + this.config.setPassword(dbConnectionInfo.getPassword()); + this.config.setDriver(dbConnectionInfo.getJdbcDriver()); + this.config.setUrl(dbConnectionInfo.getUrl()); + try { + this.dbCatalog = connection.getCatalog(); + } catch (SQLException e) { + logObj.warn("Error getting catalog.", e); + } + try { + this.loader = config.createLoader(adapter, connection, new LoaderDelegate()); + } catch (Throwable th) { + processException(th, "Error creating DbLoader."); + } } public void setStoppingReverseEngineering(boolean stopReverseEngineering) { @@ -113,6 +125,10 @@ public boolean isStoppingReverseEngineering() { return stoppingReverseEngineering; } + public DataMap getDataMap() { + return dataMap; + } + /** * Performs reverse engineering of the DB using internal DbLoader. This * method should be invoked outside EventDispatchThread, or it will throw an @@ -139,41 +155,11 @@ public void execute() { return; } - final DbLoaderOptionsDialog dialog = new DbLoaderOptionsDialog(schemas, catalogs, dbUserName, dbCatalog, false); - - try { - // since we are not inside EventDispatcher Thread, must run it via - // SwingUtilities - SwingUtilities.invokeAndWait(new Runnable() { - - public void run() { - dialog.setVisible(true); - dialog.dispose(); - } - }); - } catch (Throwable th) { - processException(th, "Error Reengineering Database"); - return; - } - - if (dialog.getChoice() == DbLoaderOptionsDialog.CANCEL) { - return; - } - - this.filterBuilder.catalog(dialog.getSelectedCatalog()); - this.filterBuilder.schema(dialog.getSelectedSchema()); - this.filterBuilder.includeTables(dialog.getTableNamePattern()); - this.filterBuilder.setProceduresFilters(dialog.isLoadingProcedures()); - this.filterBuilder.includeProcedures(dialog.getProcedureNamePattern()); - - this.meaningfulPk = dialog.isMeaningfulPk(); - this.addedObjEntities = new ArrayList(); + this.loader.setCreatingMeaningfulPK(true); - this.loader.setNameGenerator(dialog.getNamingStrategy()); - - // load DataMap... LongRunningTask loadDataMapTask = new LoadDataMapTask(Application.getFrame(), "Reengineering DB"); loadDataMapTask.startAndWait(); + } protected void processException(final Throwable th, final String message) { @@ -222,7 +208,6 @@ public void objEntityAdded(ObjEntity entity) { checkCanceled(); loadStatusNote = "Creating ObjEntity '" + entity.getName() + "'..."; - addedObjEntities.add(entity); if (existingMap) { mediator.fireObjEntityEvent(new EntityEvent(this, entity, MapEvent.ADD)); @@ -346,7 +331,8 @@ protected void execute() { } } - final class LoadDataMapTask extends DbLoaderTask { + + public final class LoadDataMapTask extends DbLoaderTask { public LoadDataMapTask(JFrame frame, String title) { super(frame, title); @@ -363,80 +349,50 @@ protected void execute() { if (!existingMap) { dataMap = new DataMap(DefaultUniqueNameGenerator.generate(NameCheckers.dataMap)); dataMap.setName(DefaultUniqueNameGenerator.generate(NameCheckers.dataMap, mediator.getProject().getRootNode())); - dataMap.setDefaultCatalog(filterBuilder.catalog()); - dataMap.setDefaultSchema(filterBuilder.schema()); } if (isCanceled()) { return; } - importingTables(); - importingProcedures(); - - cleanup(); - - // fire up events - loadStatusNote = "Updating view..."; - if (mediator.getCurrentDataMap() != null) { - mediator.fireDataMapEvent(new DataMapEvent(Application.getFrame(), dataMap, MapEvent.CHANGE)); - mediator.fireDataMapDisplayEvent(new DataMapDisplayEvent(Application.getFrame(), dataMap, - (DataChannelDescriptor) mediator.getProject().getRootNode(), mediator.getCurrentDataNode())); - } else { - DataChannelDescriptor currentDomain = (DataChannelDescriptor) mediator.getProject().getRootNode(); - Resource baseResource = currentDomain.getConfigurationSource(); - - // this will be new data map so need to set configuration source - // for it - if (baseResource != null) { - DefaultConfigurationNameMapper nameMapper = new DefaultConfigurationNameMapper(); - Resource dataMapResource = baseResource.getRelativeResource(nameMapper.configurationLocation(dataMap)); - dataMap.setConfigurationSource(dataMapResource); + DataMap dataMap = mediator.getCurrentDataMap(); + DataChannelDescriptor dataChannelDescriptor = mediator.getCurrentDataChanel(); + if (dataMap.getReverseEngineering() != null) { + if (dataMap.getReverseEngineering().getName() != null) { + reverseEngineering.setName(dataMap.getReverseEngineering().getName()); + reverseEngineering.setConfigurationSource(dataMap.getReverseEngineering().getConfigurationSource()); } - mediator.addDataMap(Application.getFrame(), dataMap); + } else { + reverseEngineering.setName(DefaultUniqueNameGenerator.generate(NameCheckers.reverseEngineering, dataChannelDescriptor)); } - } - private void importingProcedures() { - if (!filterBuilder.isLoadProcedures()) { - return; + if (dataMap.getConfigurationSource() != null) { + config.setDataMapFile(new File(dataMap.getConfigurationSource().getURL().getPath())); } - loadStatusNote = "Importing procedures..."; - try { - DbLoaderConfiguration configuration = new DbLoaderConfiguration(); - configuration.setFiltersConfig(new FiltersConfigBuilder(new ReverseEngineering()) - .add(filterBuilder).filtersConfig()); + FiltersConfigBuilder filtersConfigBuilder = new FiltersConfigBuilder(reverseEngineering); + config.getDbLoaderConfig().setFiltersConfig(filtersConfigBuilder.filtersConfig()); - loader.loadProcedures(dataMap, new DbLoaderConfiguration()); - } catch (Throwable th) { - if (!isCanceled()) { - processException(th, "Error Reengineering Database"); - } - } - } - private void importingTables() { - loadStatusNote = "Importing tables..."; + DbImportActionModeler importAction = new DbImportActionModeler(logObj, DbLoaderHelper.this); + Injector injector = DIBootstrap.createInjector(new ToolsModule(logObj), new DbImportModule()); + injector.injectMembers(importAction); try { - loader.setCreatingMeaningfulPK(meaningfulPk); - - DbLoaderConfiguration configuration = new DbLoaderConfiguration(); - configuration.setFiltersConfig(new FiltersConfigBuilder(new ReverseEngineering()) - .add(filterBuilder).filtersConfig()); - loader.load(dataMap, configuration); - - /** - * Update default rules for relationships - */ - for (ObjEntity addedObjEntity : addedObjEntities) { - DeleteRuleUpdater.updateObjEntity(addedObjEntity); - } - } catch (Throwable th) { - if (!isCanceled()) { - processException(th, "Error Reengineering Database"); - } + importAction.execute(config); + dataMap.setReverseEngineering(reverseEngineering); + } catch (Exception e) { + processException(e, "Error importing database schema."); } } } + + protected ProjectController getMediator() { + return mediator; + } + + protected DbLoader getLoader() { + return loader; + } + + } diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbLoaderOptionsDialog.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbLoaderOptionsDialog.java deleted file mode 100644 index 713e4594d2..0000000000 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbLoaderOptionsDialog.java +++ /dev/null @@ -1,308 +0,0 @@ -/***************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - ****************************************************************/ - -package org.apache.cayenne.modeler.dialog.db; - -import com.jgoodies.forms.builder.DefaultFormBuilder; -import com.jgoodies.forms.layout.FormLayout; -import org.apache.cayenne.access.DbLoader; -import org.apache.cayenne.map.naming.ObjectNameGenerator; -import org.apache.cayenne.modeler.Application; -import org.apache.cayenne.modeler.ClassLoadingService; -import org.apache.cayenne.modeler.util.CayenneDialog; -import org.apache.cayenne.modeler.util.NameGeneratorPreferences; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.DefaultComboBoxModel; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import java.awt.BorderLayout; -import java.awt.FlowLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.Collection; -import java.util.Vector; - -/** - * Dialog for selecting database reverse-engineering parameters. - */ -public class DbLoaderOptionsDialog extends CayenneDialog { - - private static final Log logObj = LogFactory.getLog(DbLoaderOptionsDialog.class); - - public static final int CANCEL = 0; - public static final int SELECT = 1; - - protected JLabel catalogLabel; - protected JComboBox catalogSelector; - protected JLabel schemaLabel; - protected JComboBox schemaSelector; - protected JTextField tableNamePatternField; - protected JCheckBox loadProcedures; - protected JCheckBox meaningfulPk; - protected JTextField procNamePatternField; - protected JLabel procedureLabel; - protected JButton selectButton; - protected JButton cancelButton; - - /** - * Combobox for naming strategy - */ - protected JComboBox strategyCombo; - - protected ObjectNameGenerator strategy; - - protected int choice; - - /** - * Creates and initializes new ChooseSchemaDialog. - */ - public DbLoaderOptionsDialog(Collection schemas, Collection catalogs, String dbUserName, - String dbCatalog, boolean loadProcedures) { - super(Application.getFrame(), "Reengineer DB Schema: Select Options"); - - init(); - initController(); - initFromModel(schemas, catalogs, dbUserName, dbCatalog, loadProcedures); - - pack(); - setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); - setModal(true); - centerWindow(); - } - - /** Sets up the graphical components. */ - protected void init() { - - // create widgets... - selectButton = new JButton("Continue"); - cancelButton = new JButton("Cancel"); - catalogSelector = new JComboBox(); - schemaSelector = new JComboBox(); - tableNamePatternField = new JTextField(); - procNamePatternField = new JTextField(); - loadProcedures = new JCheckBox(); - meaningfulPk = new JCheckBox(); - strategyCombo = new JComboBox(); - strategyCombo.setEditable(true); - - // assemble - FormLayout layout = new FormLayout( - "right:pref, 3dlu, fill:max(170dlu;pref):grow", - ""); - DefaultFormBuilder builder = new DefaultFormBuilder(layout); - builder.setDefaultDialogBorder(); - - catalogLabel = builder.append("Select Catalog:", catalogSelector); - schemaLabel = builder.append("Select Schema:", schemaSelector); - builder.append("Table Name Pattern:", tableNamePatternField); - builder.append("Load Procedures:", loadProcedures); - procedureLabel = builder.append("Procedure Name Pattern:", procNamePatternField); - builder.append("Naming Strategy:", strategyCombo); - builder.append("Meaningful PK", meaningfulPk); - - JPanel buttons = new JPanel(new FlowLayout(FlowLayout.RIGHT)); - buttons.add(cancelButton); - buttons.add(selectButton); - - getContentPane().setLayout(new BorderLayout()); - getContentPane().add(builder.getPanel(), BorderLayout.CENTER); - getContentPane().add(buttons, BorderLayout.SOUTH); - } - - protected void initController() { - selectButton.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - processSelect(); - } - }); - - cancelButton.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - processCancel(); - } - }); - - loadProcedures.addChangeListener(new ChangeListener() { - - public void stateChanged(ChangeEvent e) { - procNamePatternField.setEnabled(loadProcedures.isSelected()); - procedureLabel.setEnabled(loadProcedures.isSelected()); - } - }); - } - - protected void initFromModel( - Collection schemas, - Collection catalogs, - String dbUserName, - String dbCatalog, - boolean shouldLoadProcedures) { - - this.choice = CANCEL; - this.tableNamePatternField.setText(DbLoader.WILDCARD_PATTERN); - this.loadProcedures.setSelected(shouldLoadProcedures); - this.procNamePatternField.setText(DbLoader.WILDCARD_PATTERN); - this.procNamePatternField.setEnabled(shouldLoadProcedures); - this.procedureLabel.setEnabled(shouldLoadProcedures); - - Vector arr = NameGeneratorPreferences - .getInstance() - .getLastUsedStrategies(); - strategyCombo.setModel(new DefaultComboBoxModel(arr)); - - boolean showSchemaSelector = schemas != null && !schemas.isEmpty(); - schemaSelector.setVisible(showSchemaSelector); - schemaLabel.setVisible(showSchemaSelector); - - if (showSchemaSelector) { - - schemaSelector.setModel(new DefaultComboBoxModel(schemas.toArray())); - - // select schema belonging to the user - if (dbUserName != null) { - for (String schema : schemas) { - if (dbUserName.equalsIgnoreCase(schema)) { - schemaSelector.setSelectedItem(schema); - break; - } - } - } - } - - boolean showCatalogSelector = catalogs != null && !catalogs.isEmpty(); - catalogSelector.setVisible(showCatalogSelector); - catalogLabel.setVisible(showCatalogSelector); - - if (showCatalogSelector) { - catalogSelector.setModel(new DefaultComboBoxModel(catalogs.toArray())); - - if (dbCatalog != null && !dbCatalog.isEmpty()) { - for (String catalog : catalogs) { - if (dbCatalog.equalsIgnoreCase(catalog)) { - catalogSelector.setSelectedItem(catalog); - break; - } - } - } - } - - } - - public int getChoice() { - return choice; - } - - private void processSelect() { - try { - ClassLoadingService classLoader = Application - .getInstance() - .getClassLoadingService(); - String strategyClass = (String) strategyCombo.getSelectedItem(); - - this.strategy = classLoader - .loadClass(ObjectNameGenerator.class, strategyClass) - .newInstance(); - - /** - * Be user-friendly and update preferences with specified strategy - */ - NameGeneratorPreferences - .getInstance() - .addToLastUsedStrategies(strategyClass); - } - catch (Throwable th) { - logObj.error("Error in " + getClass().getName(), th); - - JOptionPane.showMessageDialog( - this, - "Naming Strategy Initialization Error: " + th.getMessage(), - "Naming Strategy Initialization Error", - JOptionPane.ERROR_MESSAGE); - - return; - } - - choice = SELECT; - setVisible(false); - } - - private void processCancel() { - choice = CANCEL; - setVisible(false); - } - - /** - * Returns selected catalog. - */ - public String getSelectedCatalog() { - String catalog = (String) catalogSelector.getSelectedItem(); - return "".equals(catalog) ? null : catalog; - } - - /** - * Returns selected schema. - */ - public String getSelectedSchema() { - String schema = (String) schemaSelector.getSelectedItem(); - return "".equals(schema) ? null : schema; - } - - /** - * Returns the tableNamePattern. - */ - public String getTableNamePattern() { - return "".equals(tableNamePatternField.getText()) ? null : tableNamePatternField - .getText(); - } - - public boolean isLoadingProcedures() { - return loadProcedures.isSelected(); - } - - public boolean isMeaningfulPk() { - return meaningfulPk.isSelected(); - } - - /** - * Returns the procedure name pattern. - */ - public String getProcedureNamePattern() { - return "".equals(procNamePatternField.getText()) ? null : procNamePatternField - .getText(); - } - - /** - * Returns configured naming strategy - */ - public ObjectNameGenerator getNamingStrategy() { - return strategy; - } -} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java index bd2cf691f5..b18fe9c667 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java @@ -68,15 +68,11 @@ import org.apache.cayenne.resource.Resource; import org.apache.cayenne.swing.BindingBuilder; import org.apache.cayenne.swing.ObjectBinding; -import org.apache.cayenne.tools.dbimport.config.FiltersConfigBuilder; -import org.apache.cayenne.tools.dbimport.config.ReverseEngineering; -import org.apache.cayenne.tools.dbimport.config.Schema; import org.apache.cayenne.validation.ValidationResult; public class MergerOptions extends CayenneController { protected MergerOptionsView view; - // protected ObjectBinding[] optionBindings; protected ObjectBinding sqlBinding; protected DBConnectionInfo connectionInfo; diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ReverseEngineeringController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ReverseEngineeringController.java new file mode 100644 index 0000000000..f0841878c3 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ReverseEngineeringController.java @@ -0,0 +1,362 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.dialog.db; + +import org.apache.cayenne.access.DbLoader; +import org.apache.cayenne.access.loader.DbLoaderConfiguration; +import org.apache.cayenne.access.loader.DefaultDbLoaderDelegate; +import org.apache.cayenne.access.loader.filters.CatalogFilter; +import org.apache.cayenne.access.loader.filters.SchemaFilter; +import org.apache.cayenne.dba.DbAdapter; +import org.apache.cayenne.dbimport.FiltersConfigBuilder; +import org.apache.cayenne.dbimport.ReverseEngineering; +import org.apache.cayenne.dbimport.ReverseEngineeringLoaderException; +import org.apache.cayenne.map.DataMap; +import org.apache.cayenne.map.DbAttribute; +import org.apache.cayenne.map.DbEntity; +import org.apache.cayenne.map.Procedure; +import org.apache.cayenne.modeler.ClassLoadingService; +import org.apache.cayenne.modeler.ProjectController; +import org.apache.cayenne.modeler.dialog.db.model.DBCatalog; +import org.apache.cayenne.modeler.dialog.db.model.DBColumn; +import org.apache.cayenne.modeler.dialog.db.model.DBElement; +import org.apache.cayenne.modeler.dialog.db.model.DBEntity; +import org.apache.cayenne.modeler.dialog.db.model.DBModel; +import org.apache.cayenne.modeler.dialog.db.model.DBProcedure; +import org.apache.cayenne.modeler.dialog.db.model.DBSchema; +import org.apache.cayenne.modeler.dialog.pref.PreferenceDialog; +import org.apache.cayenne.modeler.dialog.pref.TreeEditor; +import org.apache.cayenne.modeler.dialog.pref.XMLFileEditor; +import org.apache.cayenne.modeler.pref.DBConnectionInfo; +import org.apache.cayenne.modeler.util.CayenneController; +import org.apache.cayenne.swing.BindingBuilder; +import org.apache.cayenne.swing.ObjectBinding; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.SwingUtilities; +import java.awt.Component; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * A component for performing reverse engineering. Users can choose required dataMap and execute + * reverse engineering. Also they can see tree view of db objects clicking on sync button. + */ +public class ReverseEngineeringController extends CayenneController { + private static final Log LOGGER = LogFactory.getLog(ReverseEngineeringController.class); + + protected ProjectController projectController; + protected ReverseEngineeringView view; + protected Map reverseEngineeringMap; + protected DBModel dbModel; + + protected Connection connection; + protected DbAdapter adapter; + + protected DBConnectionInfo connectionInfo; + protected ObjectBinding dataSourceBinding; + protected Map dataSources; + protected String dataSourceKey; + protected boolean canceled; + + public ReverseEngineeringController(ProjectController controller, + ReverseEngineeringView source) { + super(controller); + this.projectController = controller; + this.view = source; + + this.connectionInfo = new DBConnectionInfo(); + this.reverseEngineeringMap = view.getReverseEngineeringViewMap(); + initBindings(); + refreshDataSources(); + } + + protected void initBindings() { + BindingBuilder builder = new BindingBuilder(getApplication().getBindingFactory(), this); + + dataSourceBinding = builder.bindToComboSelection(view.getDataSources(), "dataSourceKey"); + + builder.bindToAction(view.getSyncButton(), "syncAction()"); + builder.bindToAction(view.getExecuteButton(), "executeAction()"); + builder.bindToAction(view.getConfigButton(), "dataSourceConfigAction()"); + } + + private void buildDBProperties() throws Exception { + ClassLoadingService classLoader = getApplication().getClassLoadingService(); + this.connection = connectionInfo.makeDataSource(classLoader).getConnection(); + this.adapter = connectionInfo.makeAdapter(classLoader); + } + + public void syncAction() throws SQLException { + final TreeEditor treeEditor = view.getTreeEditor(); + XMLFileEditor xmlFileEditor = view.getXmlFileEditor(); + xmlFileEditor.removeAlertMessage(); + try { + buildDBProperties(); + + DbLoader dbLoader = new DbLoader(connection, adapter, new DefaultDbLoaderDelegate()) { + @Override + public DataMap load(DbLoaderConfiguration config) throws SQLException { + DataMap dataMap = new DataMap(); + Map procedureMap = loadProcedures(dataMap, config); + load(dataMap, config, procedureMap); + return dataMap; + } + + public void load(DataMap dataMap, DbLoaderConfiguration config, Map procedureMap + ) + throws SQLException { + LOGGER.info("Schema loading..."); + + String[] types = config.getTableTypes(); + if (types == null || types.length == 0) { + types = getDefaultTableTypes(); + } + + treeEditor.setRoot(dataSourceKey); + dbModel = new DBModel(dataSourceKey); + boolean catalogSetted = false; + DBElement currentDBCatalog = null; + DBElement currentDBSchema = null; + + for (CatalogFilter catalog : config.getFiltersConfig().catalogs) { + for (SchemaFilter schema : catalog.schemas) { + boolean entityChecked = false; + List entityList = createTableLoader(catalog.name, schema.name, schema.tables).loadDbEntities( + dataMap, config, types); + DbEntity entityFromLoader = entityList.get(0); + + if (entityFromLoader != null) { + if (catalogSetted == false && entityFromLoader.getCatalog() != null) { + currentDBCatalog = new DBCatalog(entityFromLoader.getCatalog()); + dbModel.addElement(currentDBCatalog); + catalogSetted = true; + } + + if (entityFromLoader.getSchema() != null) { + currentDBSchema = new DBSchema(entityFromLoader.getSchema()); + if(currentDBCatalog != null) { + currentDBCatalog.addElement(currentDBSchema); + } else { + dbModel.addElement(currentDBSchema); + } + } + entityChecked = true; + } + + if (!entityChecked && !procedureMap.isEmpty()) { + Map.Entry entry = procedureMap.entrySet().iterator().next(); + Procedure procedure = entry.getValue(); + + if (catalogSetted && procedure.getCatalog() != null) { + currentDBCatalog = new DBCatalog(procedure.getCatalog()); + dbModel.addElement(currentDBCatalog); + catalogSetted = true; + } + + if (procedure.getSchema() != null) { + currentDBSchema = new DBSchema(procedure.getSchema()); + if(currentDBCatalog != null) { + currentDBCatalog.addElement(currentDBSchema); + } else { + dbModel.addElement(currentDBSchema); + } + } + } + + DBEntity currentDBEntity; + if (currentDBSchema != null) { + for (DbEntity dbEntity : entityList) { + currentDBEntity = new DBEntity(dbEntity.getName()); + currentDBSchema.addElement(currentDBEntity); + for (DbAttribute dbColumn : dbEntity.getAttributes()) { + currentDBEntity.addElement(new DBColumn(dbColumn.getName())); + } + } + } else { + for (DbEntity dbEntity : entityList) { + currentDBEntity = new DBEntity(dbEntity.getName()); + for (DbAttribute dbColumn : dbEntity.getAttributes()) { + currentDBEntity.addElement(new DBColumn(dbColumn.getName())); + } + currentDBCatalog.addElement(currentDBEntity); + } + } + + if (currentDBSchema != null) { + for (Map.Entry entry : procedureMap.entrySet()) { + currentDBSchema.addElement(new DBProcedure(entry.getValue().getName())); + } + } else { + for (Map.Entry entry : procedureMap.entrySet()) { + currentDBCatalog.addElement(new DBProcedure(entry.getValue().getName())); + } + } + currentDBSchema = null; + } + catalogSetted = false; + currentDBCatalog = null; + } + } + }; + + ReverseEngineering reverseEngineering = xmlFileEditor.convertTextIntoReverseEngineering(); + + FiltersConfigBuilder filtersConfigBuilder = new FiltersConfigBuilder(reverseEngineering); + DbLoaderConfiguration dbLoaderConfiguration = new DbLoaderConfiguration(); + dbLoaderConfiguration.setFiltersConfig(filtersConfigBuilder.filtersConfig()); + + dbLoader.load(dbLoaderConfiguration); + + String mapName = projectController.getCurrentDataMap().getName(); + + DataMapViewModel dataMapViewModel = new DataMapViewModel(mapName); + dataMapViewModel.setReverseEngineeringTree(dbModel); + dataMapViewModel.setReverseEngineeringText(xmlFileEditor.getView().getEditorPane().getText()); + reverseEngineeringMap.put(mapName, dataMapViewModel); + treeEditor.convertTreeViewIntoTreeNode(dbModel); + } catch (ReverseEngineeringLoaderException e) { + xmlFileEditor.addAlertMessage(e.getMessage()); + } catch (Exception e) { + xmlFileEditor.addAlertMessage(e.getMessage()); + } + } + + public void executeAction() { + XMLFileEditor xmlFileEditor = view.getXmlFileEditor(); + xmlFileEditor.removeAlertMessage(); + try { + buildDBProperties(); + + ReverseEngineering reverseEngineering = xmlFileEditor.convertTextIntoReverseEngineering(); + + final DbLoaderHelper helper = new DbLoaderHelper( + projectController, + connection, + adapter, + connectionInfo, reverseEngineering); + Thread th = new Thread(new Runnable() { + + public void run() { + helper.execute(); + + SwingUtilities.invokeLater(new Runnable() { + + public void run() { + application.getUndoManager().discardAllEdits(); + } + }); + } + }); + + th.start(); + view.setTempDataMap(projectController.getCurrentDataMap()); + } catch (ReverseEngineeringLoaderException e) { + xmlFileEditor.addAlertMessage(e.getMessage()); + } catch (Exception e) { + xmlFileEditor.addAlertMessage(e.getMessage()); + } + } + + /** + * Returns configured DB connection. + */ + public Connection getConnection() { + return connection; + } + + /** + * Returns configured DbAdapter. + */ + public DbAdapter getAdapter() { + return adapter; + } + + + public String getDataSourceKey() { + return dataSourceKey; + } + + public void setDataSourceKey(String dataSourceKey) { + XMLFileEditor xmlFileEditor = view.getXmlFileEditor(); + xmlFileEditor.removeAlertMessage(); + + this.dataSourceKey = dataSourceKey; + + DBConnectionInfo currentInfo = (DBConnectionInfo) dataSources.get(dataSourceKey); + if (currentInfo != null) { + currentInfo.copyTo(connectionInfo); + } else { + connectionInfo = new DBConnectionInfo(); + } + } + + /** + * Opens preferences panel to allow configuration of DataSource presets. + */ + public void dataSourceConfigAction() { + PreferenceDialog prefs = new PreferenceDialog(this); + prefs.showDataSourceEditorAction(dataSourceKey); + refreshDataSources(); + } + + public Component getView() { + return view; + } + + protected void refreshDataSources() { + this.dataSources = getApplication().getCayenneProjectPreferences().getDetailObject(DBConnectionInfo.class) + .getChildrenPreferences(); + + // 1.2 migration fix - update data source adapter names + Iterator it = dataSources.values().iterator(); + + final String _12package = "org.objectstyle.cayenne."; + while (it.hasNext()) { + DBConnectionInfo info = (DBConnectionInfo) it.next(); + if (info.getDbAdapter() != null && info.getDbAdapter().startsWith(_12package)) { + info.setDbAdapter("org.apache.cayenne." + info.getDbAdapter().substring(_12package.length())); + } + } + + Object[] keys = dataSources.keySet().toArray(); + Arrays.sort(keys); + view.getDataSources().setModel(new DefaultComboBoxModel(keys)); + + if (dataSources.isEmpty()) { + dataSourceKey = null; + } + String key = null; + if (keys.length > 0) { + key = keys[0].toString(); + } + setDataSourceKey(key); + + if (getDataSourceKey() == null) { + dataSourceBinding.updateView(); + } + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ReverseEngineeringScrollPane.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ReverseEngineeringScrollPane.java new file mode 100644 index 0000000000..bc8c46662b --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ReverseEngineeringScrollPane.java @@ -0,0 +1,34 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.modeler.dialog.db; + +import javax.swing.JScrollPane; + +/** + * @since 4.0 + */ +public class ReverseEngineeringScrollPane extends JScrollPane { + + private ReverseEngineeringView reverseEngineeringView; + + public ReverseEngineeringScrollPane(ReverseEngineeringView reverseEngineeringView) { + super(reverseEngineeringView); + this.reverseEngineeringView = reverseEngineeringView; + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ReverseEngineeringView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ReverseEngineeringView.java new file mode 100644 index 0000000000..087ab26ef3 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ReverseEngineeringView.java @@ -0,0 +1,274 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.dialog.db; + +import com.jgoodies.forms.builder.PanelBuilder; +import com.jgoodies.forms.layout.CellConstraints; +import com.jgoodies.forms.layout.FormLayout; +import org.apache.cayenne.CayenneRuntimeException; +import org.apache.cayenne.dbimport.ReverseEngineering; +import org.apache.cayenne.map.DataMap; +import org.apache.cayenne.modeler.CayenneModelerController; +import org.apache.cayenne.modeler.ProjectController; +import org.apache.cayenne.modeler.dialog.db.model.DBModel; +import org.apache.cayenne.modeler.dialog.pref.TreeEditor; +import org.apache.cayenne.modeler.dialog.pref.XMLFileEditor; +import org.apache.cayenne.modeler.event.DataMapDisplayEvent; +import org.apache.cayenne.modeler.event.DataMapDisplayListener; +import org.apache.cayenne.modeler.util.ModelerUtil; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSeparator; +import javax.swing.JSplitPane; +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + */ +public class ReverseEngineeringView extends JPanel { + protected ProjectController controller; + public ReverseEngineeringController reverseEngineeringController; + protected JPanel reverseEngineering; + + protected JComboBox dataSources; + protected JButton configButton; + protected JButton syncButton; + protected JButton executeButton; + + protected PanelBuilder builder; + protected JSeparator separator; + protected JSplitPane splitPane; + protected JLabel xmlLabel; + protected JLabel treeLabel; + protected Icon icon; + + protected XMLFileEditor xmlFileEditor; + protected TreeEditor treeEditor; + + protected DataMap tempDataMap; + + protected Map reverseEngineeringViewMap; + + + private String template = + "\n" + + " false\n" + + " false\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + public ReverseEngineeringView(ProjectController controller) { + this.controller = controller; + + this.reverseEngineeringViewMap = new HashMap<>(); + initView(); + initController(); + } + + private void initView() { + this.reverseEngineering = new JPanel(); + this.dataSources = new JComboBox(); + this.splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true); + this.configButton = new JButton("..."); + this.configButton.setToolTipText("configure local DataSource"); + this.syncButton = new JButton(); + this.icon = ModelerUtil.buildIcon("icon-refresh.png"); + this.syncButton.setIcon(icon); + this.syncButton.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); + this.executeButton = new JButton("Execute"); + this.treeLabel = new JLabel("Preview"); + this.xmlLabel = new JLabel("Reverse Engineering XML Editor"); + this.treeLabel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5)); + this.xmlLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 10, 5)); + + this.treeEditor = new TreeEditor(controller); + this.xmlFileEditor = new XMLFileEditor(controller); + + CellConstraints cc = new CellConstraints(); + this.builder = new PanelBuilder(new FormLayout( + "210dlu:grow, pref, 0dlu, fill:max(172dlu;pref), 3dlu, fill:20dlu", + "p")); + builder.setDefaultDialogBorder(); + builder.add(dataSources, cc.xy(4, 1)); + builder.add(configButton, cc.xy(6, 1)); + + JPanel buttons = new JPanel(new FlowLayout(FlowLayout.RIGHT)); + buttons.add(executeButton); + + JPanel treeHeaderComponent = new JPanel(new FlowLayout(FlowLayout.LEFT)); + treeHeaderComponent.add(treeLabel); + treeHeaderComponent.add(syncButton); + + JPanel leftComponent = new JPanel(); + leftComponent.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); + leftComponent.setLayout(new BorderLayout()); + leftComponent.add(xmlLabel, BorderLayout.NORTH); + leftComponent.add(xmlFileEditor.getView().getScrollPane(), BorderLayout.CENTER); + + JPanel rightComponent = new JPanel(); + rightComponent.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5)); + rightComponent.setLayout(new BorderLayout()); + rightComponent.add(treeHeaderComponent, BorderLayout.NORTH); + rightComponent.add(treeEditor.getView().getScrollPane(), BorderLayout.CENTER); + + splitPane.setLeftComponent(leftComponent); + splitPane.setRightComponent(rightComponent); + splitPane.setResizeWeight(0.5); + + JPanel splitWithErrorsPanel = new JPanel(); + splitWithErrorsPanel.setLayout(new BorderLayout()); + splitWithErrorsPanel.add(splitPane, BorderLayout.CENTER); + xmlFileEditor.getView().getLabel().setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); + splitWithErrorsPanel.add(xmlFileEditor.getView().getLabel(), BorderLayout.SOUTH); + + setLayout(new BorderLayout()); + add(builder.getPanel(), BorderLayout.NORTH); + add(splitWithErrorsPanel, BorderLayout.CENTER); + add(buttons, BorderLayout.SOUTH); + } + + public void initController() { + controller.addDataMapDisplayListener(new DataMapDisplayListener() { + public void currentDataMapChanged(DataMapDisplayEvent e) { + DataMap map = e.getDataMap(); + + if (tempDataMap != null) { + String mapName = tempDataMap.getName(); + DataMapViewModel dataMapViewModel = new DataMapViewModel(mapName); + String xmlText = xmlFileEditor.getView().getEditorPane().getText(); + dataMapViewModel.setReverseEngineeringText(xmlText); + if (reverseEngineeringViewMap.containsKey(mapName)) { + DataMapViewModel dataMapViewPrevious = reverseEngineeringViewMap.get(mapName); + if (dataMapViewPrevious.getReverseEngineeringTree() != null) { + dataMapViewModel.setReverseEngineeringTree(dataMapViewPrevious.getReverseEngineeringTree()); + } else { + dataMapViewModel.setReverseEngineeringTree(new DBModel("")); + } + } else { + dataMapViewModel.setReverseEngineeringTree(new DBModel("")); + } + reverseEngineeringViewMap.put(mapName, dataMapViewModel); + } + tempDataMap = map; + + if (map != null) { + loadPreviousData(); + xmlFileEditor.removeAlertMessage(); + } + } + }); + + this.reverseEngineeringController = new ReverseEngineeringController(controller, this); + } + + public void loadPreviousData() { + DataMap dataMap = controller.getCurrentDataMap(); + try { + if (dataMap != null) { + String reverseEngineeringText = null; + if (reverseEngineeringViewMap.containsKey(dataMap.getName())) { + reverseEngineeringText = reverseEngineeringViewMap.get(dataMap.getName()).getReverseEngineeringText(); + } + if (reverseEngineeringText != null) { + xmlFileEditor.getView().getEditorPane().setText(reverseEngineeringText); + } else { + if (dataMap.getReverseEngineering() == null) { + getXmlFileEditor().getView().getEditorPane().setText(template); + } else { + ReverseEngineering reverseEngineering = dataMap.getReverseEngineering(); + if (reverseEngineering.getConfigurationSource() != null) { + xmlFileEditor.getView().getEditorPane().setPage(reverseEngineering.getConfigurationSource().getURL()); + } + } + } + + if (reverseEngineeringViewMap.containsKey(dataMap.getName())) { + if (reverseEngineeringViewMap.get(dataMap.getName()).getReverseEngineeringTree() != null) { + DBModel loadedPreviousTree = reverseEngineeringViewMap.get(dataMap.getName()).getReverseEngineeringTree(); + treeEditor.convertTreeViewIntoTreeNode(loadedPreviousTree); + } else { + treeEditor.setRoot(""); + } + } else { + treeEditor.setRoot(""); + } + } + + if (((CayenneModelerController) controller.getParent()) + .getEditorView() + .getDataMapView() + .getSelectedIndex() == 1) { + ((CayenneModelerController) controller.getParent()) + .getEditorView() + .getDataMapView() + .setSelectedIndex(1); + } + } catch (IOException e) { + throw new CayenneRuntimeException("Invalid URL"); + } + } + + public JComboBox getDataSources() { + return dataSources; + } + + public JButton getConfigButton() { + return configButton; + } + + public JButton getSyncButton() { + return syncButton; + } + + public TreeEditor getTreeEditor() { + return treeEditor; + } + + public XMLFileEditor getXmlFileEditor() { + return xmlFileEditor; + } + + public JButton getExecuteButton() { + return executeButton; + } + + public Map getReverseEngineeringViewMap() { + return reverseEngineeringViewMap; + } + + public void setTempDataMap(DataMap dataMap) { + tempDataMap = dataMap; + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBCatalog.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBCatalog.java new file mode 100644 index 0000000000..c7e1416785 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBCatalog.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cayenne.modeler.dialog.db.model; + +/** + * @since 4.0 + */ +public class DBCatalog extends DBElement{ + public DBCatalog(String name) { + super(name); + } + + public void addElement(DBElement dbElement){ + dbElements.add(dbElement); + } + + @Override + public String toString() { + return name; + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBColumn.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBColumn.java new file mode 100644 index 0000000000..ed083c9022 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBColumn.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cayenne.modeler.dialog.db.model; + +/** + * @since 4.0 + */ +public class DBColumn extends DBElement{ + + public DBColumn(String name) { + super(name); + } + + @Override + public String toString() { + return name; + } + + @Override + public void addElement(DBElement dbElement) { + throw new UnsupportedOperationException(); + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBElement.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBElement.java new file mode 100644 index 0000000000..b3a352f80c --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBElement.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cayenne.modeler.dialog.db.model; + +import java.util.LinkedList; +import java.util.List; + +/** + * @since 4.0 + */ +public abstract class DBElement { + protected String name; + protected List dbElements; + + public DBElement(String name) { + this.name = name; + dbElements = new LinkedList<>(); + } + + public List getDbElements() { + return dbElements; + } + + public abstract void addElement(DBElement dbElement); + + public String getName() { + return name; + } + + @Override + public String toString() { + return name; + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBEntity.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBEntity.java new file mode 100644 index 0000000000..069a3982b7 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBEntity.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cayenne.modeler.dialog.db.model; + +/** + * @since 4.0 + */ +public class DBEntity extends DBElement{ + public DBEntity(String name) { + super(name); + } + + public void addElement(DBElement dbElement){ + dbElements.add(dbElement); + } + + @Override + public String toString() { + return name; + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBModel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBModel.java new file mode 100644 index 0000000000..449f43670e --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBModel.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cayenne.modeler.dialog.db.model; + +/** + * @since 4.0 + */ +public class DBModel extends DBElement { + public DBModel(String name) { + super(name); + } + + @Override + public void addElement(DBElement dbElement) { + dbElements.add(dbElement); + } + + @Override + public String toString() { + return name; + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBProcedure.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBProcedure.java new file mode 100644 index 0000000000..268eaf4646 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBProcedure.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cayenne.modeler.dialog.db.model; + +/** + * @since 4.0 + */ +public class DBProcedure extends DBElement{ + public DBProcedure(String name) { + super(name); + } + + @Override + public void addElement(DBElement dbElement) { + throw new UnsupportedOperationException(); + } + + @Override + public String toString() { + return name; + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBSchema.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBSchema.java new file mode 100644 index 0000000000..c6a7d34ca7 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBSchema.java @@ -0,0 +1,48 @@ + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cayenne.modeler.dialog.db.model; + +import java.util.LinkedList; +import java.util.List; + +/** + * @since 4.0 + */ +public class DBSchema extends DBElement{ + public List getDbElements() { + return dbElements; + } + + protected List dbElements; + + public DBSchema(String name) { + super(name); + dbElements = new LinkedList<>(); + } + + public void addElement(DBElement dbElement){ + dbElements.add(dbElement); + } + + @Override + public String toString() { + return name; + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/FilteredTreeCellRenderer.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/FilteredTreeCellRenderer.java new file mode 100644 index 0000000000..c831f231be --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/FilteredTreeCellRenderer.java @@ -0,0 +1,85 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.modeler.dialog.pref; + +import org.apache.cayenne.modeler.dialog.db.model.DBCatalog; +import org.apache.cayenne.modeler.dialog.db.model.DBColumn; +import org.apache.cayenne.modeler.dialog.db.model.DBEntity; +import org.apache.cayenne.modeler.dialog.db.model.DBProcedure; +import org.apache.cayenne.modeler.dialog.db.model.DBSchema; +import org.apache.cayenne.modeler.util.CellRenderers; + +import javax.swing.ImageIcon; +import javax.swing.JTree; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellRenderer; +import java.awt.Component; + +/** + * @since 4.0 + */ +public class FilteredTreeCellRenderer extends DefaultTreeCellRenderer { + + @Override + public Component getTreeCellRendererComponent( + JTree tree, + Object value, + boolean sel, + boolean expanded, + boolean leaf, + int row, + boolean hasFocus) { + + super.getTreeCellRendererComponent( + tree, value, sel, + expanded, leaf, row, + hasFocus); + if ((value != null) && (value instanceof DefaultMutableTreeNode)) { + Object userObject = ((DefaultMutableTreeNode) value) + .getUserObject(); + ImageIcon imageIcon = CellRenderers.iconForObject(userObject); + + if (userObject instanceof DBCatalog) { + setText(((DBCatalog) userObject).getName()); + setIcon(imageIcon); + } + + if (userObject instanceof DBSchema) { + setText(((DBSchema) userObject).getName()); + setIcon(imageIcon); + } + + if (userObject instanceof DBEntity) { + setText(((DBEntity) userObject).getName()); + setIcon(imageIcon); + } + + if (userObject instanceof DBColumn) { + setText(((DBColumn) userObject).getName()); + setIcon(imageIcon); + } + + if (userObject instanceof DBProcedure) { + setText(((DBProcedure) userObject).getName()); + setIcon(imageIcon); + } + } + return this; + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/TreeEditor.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/TreeEditor.java new file mode 100644 index 0000000000..3550f41333 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/TreeEditor.java @@ -0,0 +1,101 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.modeler.dialog.pref; + +import org.apache.cayenne.modeler.dialog.db.model.DBCatalog; +import org.apache.cayenne.modeler.dialog.db.model.DBElement; +import org.apache.cayenne.modeler.dialog.db.model.DBEntity; +import org.apache.cayenne.modeler.dialog.db.model.DBModel; +import org.apache.cayenne.modeler.dialog.db.model.DBSchema; +import org.apache.cayenne.modeler.util.CayenneController; + +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; + +/** + * @since 4.0 + */ +public class TreeEditor extends CayenneController { + protected TreeView treeView; + protected DefaultMutableTreeNode root; + + public TreeEditor(CayenneController parent) { + super(parent); + + this.treeView = new TreeView(root); + } + + @Override + public TreeView getView() { + return treeView; + } + + public void setRoot(String dataSource) { + root = new DefaultMutableTreeNode(dataSource); + DefaultTreeModel model = (DefaultTreeModel) treeView.getTree().getModel(); + model.setRoot(root); + } + + public void convertTreeViewIntoTreeNode(DBModel dbModel) { + DefaultMutableTreeNode modelNode = new DefaultMutableTreeNode(dbModel); + for (DBElement dbElement: dbModel.getDbElements()) { + DefaultMutableTreeNode elementNode = new DefaultMutableTreeNode(dbElement); + if(dbElement instanceof DBCatalog) { + parseCatalog(dbElement, elementNode); + } + if(dbElement instanceof DBSchema) { + parseSchema(dbElement, elementNode); + } + modelNode.add(elementNode); + } + root = modelNode; + DefaultTreeModel model = (DefaultTreeModel) treeView.getTree().getModel(); + model.setRoot(root); + } + + public void parseCatalog(DBElement catalog, DefaultMutableTreeNode elementNode) { + for (DBElement dbElement: catalog.getDbElements()) { + DefaultMutableTreeNode element = new DefaultMutableTreeNode(dbElement); + if(dbElement instanceof DBSchema) { + parseSchema(dbElement, element); + } + if(dbElement instanceof DBEntity){ + parseEntity(dbElement, element); + } + elementNode.add(element); + } + } + + public void parseSchema(DBElement schema, DefaultMutableTreeNode elementNode) { + for (DBElement element: schema.getDbElements()) { + DefaultMutableTreeNode entityNode = new DefaultMutableTreeNode(element); + if(element instanceof DBEntity) { + parseEntity(element, entityNode); + } + elementNode.add(entityNode); + } + } + + private void parseEntity(DBElement entity, DefaultMutableTreeNode entityNode) { + for (DBElement column: entity.getDbElements()) { + DefaultMutableTreeNode columnNode = new DefaultMutableTreeNode(column); + entityNode.add(columnNode); + } + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/TreeView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/TreeView.java new file mode 100644 index 0000000000..f46435936e --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/TreeView.java @@ -0,0 +1,56 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.modeler.dialog.pref; + +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTree; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreeCellRenderer; +import java.awt.Dimension; + +/** + * @since 4.0 + */ +public class TreeView extends JPanel { + protected JTree tree; + protected JScrollPane scrollPane; + + public JTree getTree() { + return tree; + } + + public void setTree(JTree tree) { + this.tree = tree; + } + + public TreeView(DefaultMutableTreeNode root) { + this.tree = new JTree(root); + + TreeCellRenderer renderer = new FilteredTreeCellRenderer(); + tree.setCellRenderer(renderer); + + scrollPane = new JScrollPane(tree); + scrollPane.setPreferredSize(new Dimension(210, 300)); + } + + public JScrollPane getScrollPane() { + return scrollPane; + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/XMLFileEditor.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/XMLFileEditor.java new file mode 100644 index 0000000000..920e2ad205 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/XMLFileEditor.java @@ -0,0 +1,82 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.modeler.dialog.pref; + +import org.apache.cayenne.dbimport.DefaultReverseEngineeringLoader; +import org.apache.cayenne.dbimport.DefaultReverseEngineeringWriter; +import org.apache.cayenne.dbimport.ReverseEngineering; +import org.apache.cayenne.dbimport.ReverseEngineeringLoaderException; +import org.apache.cayenne.modeler.util.CayenneController; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; + +/** + * @since 4.0 + */ +public class XMLFileEditor extends CayenneController { + private static final Log LOGGER = LogFactory.getLog(XMLFileEditor.class); + + protected XMLView XMLview; + + + public XMLFileEditor(CayenneController parent) { + super(parent); + + this.XMLview = new XMLView(); + } + + public ReverseEngineering convertTextIntoReverseEngineering() throws ReverseEngineeringLoaderException { + String text = XMLview.getEditorPane().getText(); + try(InputStream inputStream = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8))) { + ReverseEngineering reverseEngineering = (new DefaultReverseEngineeringLoader()).load(inputStream); + return reverseEngineering; + } catch (IOException e) { + addAlertMessage(e.getMessage()); + } + return null; + } + + public void convertReverseEngineeringIntoText(ReverseEngineering reverseEngineering) { + StringWriter buffer = new StringWriter(); + PrintWriter writer = new PrintWriter(buffer); + DefaultReverseEngineeringWriter reverseEngineeringWriter = new DefaultReverseEngineeringWriter(); + reverseEngineeringWriter.write(reverseEngineering, writer); + XMLview.getEditorPane().setText(buffer.toString()); + } + + @Override + public XMLView getView() { + return XMLview; + } + + public void addAlertMessage(String message) { + XMLview.addAlertMessage(message); + } + + public void removeAlertMessage() { + XMLview.removeAlertMessage(); + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/XMLView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/XMLView.java new file mode 100644 index 0000000000..8dab6c5930 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/pref/XMLView.java @@ -0,0 +1,72 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.modeler.dialog.pref; + + +import javax.swing.JEditorPane; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import java.awt.Color; +import java.awt.Dimension; + +/** + * @since 4.0 + */ +public class XMLView extends JPanel { + protected JEditorPane editorPane; + protected JScrollPane scrollPane; + protected JLabel label; + + public XMLView() { + this.editorPane = new JEditorPane(); + this.scrollPane = new JScrollPane(editorPane); + this.label = new JLabel(); + this.label.setVisible(false); + + scrollPane = new JScrollPane(editorPane); + scrollPane.setPreferredSize(new Dimension(210, 300)); + } + + public JEditorPane getEditorPane() { + return editorPane; + } + + public JScrollPane getScrollPane() { + return scrollPane; + } + + public JLabel getLabel() { + return label; + } + + public void setLabel(JLabel label) { + this.label = label; + } + + public void addAlertMessage(String message) { + label.setText(message); + label.setForeground (Color.red); + label.setVisible(true); + } + + public void removeAlertMessage() { + label.setVisible(false); + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DataMapTabbedView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DataMapTabbedView.java index e33e3195c0..81acc243de 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DataMapTabbedView.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/DataMapTabbedView.java @@ -20,19 +20,28 @@ import javax.swing.JScrollPane; import javax.swing.JTabbedPane; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import org.apache.cayenne.modeler.ProjectController; +import org.apache.cayenne.modeler.dialog.db.ReverseEngineeringScrollPane; +import org.apache.cayenne.modeler.dialog.db.ReverseEngineeringView; + +import java.awt.event.ActionEvent; /** * Data map editing tabs container * */ -public class DataMapTabbedView extends JTabbedPane { +public class DataMapTabbedView extends JTabbedPane + implements ChangeListener { ProjectController mediator; + private ReverseEngineeringScrollPane reverseEngineeringScrollPane; /** * constructor + * * @param mediator mediator instance */ public DataMapTabbedView(ProjectController mediator) { @@ -45,7 +54,6 @@ public DataMapTabbedView(ProjectController mediator) { * create tabs */ private void initView() { - setTabPlacement(JTabbedPane.TOP); // add panels to tabs @@ -53,6 +61,19 @@ private void initView() { // must be wrapped in a scroll pane JScrollPane dataMapView = new JScrollPane(new DataMapView(mediator)); addTab("DataMap", dataMapView); + + ReverseEngineeringView reverseEngineeringView = new ReverseEngineeringView(mediator); + reverseEngineeringScrollPane = new ReverseEngineeringScrollPane(reverseEngineeringView); + addTab("Reverse Engineering", reverseEngineeringScrollPane); + addChangeListener(this); + } + + @Override + public void stateChanged(ChangeEvent changeEvent) { + if (getSelectedComponent().equals(reverseEngineeringScrollPane)) { + ActionEvent actionEvent = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, ""); + actionEvent.setSource(reverseEngineeringScrollPane); + } } } diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/RemoveUndoableEdit.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/RemoveUndoableEdit.java index 0791acf6c6..2a438520ce 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/RemoveUndoableEdit.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/undo/RemoveUndoableEdit.java @@ -81,7 +81,7 @@ public RemoveUndoableEdit(Application application) { } public RemoveUndoableEdit(Application application, DataNodeDescriptor node, - DataMap map) { + DataMap map) { this.map = map; this.dataNode = node; this.mode = REMOVE_MODE.MAP_FROM_NODE; @@ -330,4 +330,4 @@ public void undo() throws CannotUndoException { } } } -} +} \ No newline at end of file diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/CellRenderers.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/CellRenderers.java index 85cb6470b7..1c9afb2558 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/CellRenderers.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/CellRenderers.java @@ -35,6 +35,7 @@ import org.apache.cayenne.configuration.DataChannelDescriptor; import org.apache.cayenne.configuration.DataNodeDescriptor; +import org.apache.cayenne.dbimport.Schema; import org.apache.cayenne.map.Attribute; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.map.DbEntity; @@ -46,6 +47,7 @@ import org.apache.cayenne.map.Relationship; import org.apache.cayenne.modeler.Application; import org.apache.cayenne.modeler.ProjectController; +import org.apache.cayenne.modeler.dialog.db.model.*; import org.apache.cayenne.query.Query; import org.apache.cayenne.util.CayenneMapEntry; @@ -67,6 +69,7 @@ public final class CellRenderers { protected static ImageIcon procedureIcon; protected static ImageIcon queryIcon; protected static ImageIcon embeddableIcon; + protected static ImageIcon catalogIcon; static { domainIcon = ModelerUtil.buildIcon("icon-dom.gif"); @@ -79,6 +82,7 @@ public final class CellRenderers { relationshipIcon = ModelerUtil.buildIcon("icon-relationship.gif"); attributeIcon = ModelerUtil.buildIcon("icon-attribute.gif"); embeddableIcon = ModelerUtil.buildIcon("icon-embeddable.gif"); + catalogIcon = ModelerUtil.buildIcon("icon-open.gif"); } public static ImageIcon iconForObject(Object object) { @@ -119,7 +123,18 @@ else if (object instanceof Attribute) { else if (object instanceof Embeddable) { return embeddableIcon; } - + else if (object instanceof DBColumn) { + return attributeIcon; + } + else if (object instanceof DBProcedure) { + return procedureIcon; + } + else if (object instanceof DBEntity) { + return dbEntityIcon; + } + else if (object instanceof DBCatalog) { + return catalogIcon; + } return null; } diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/pref/PreferenceEditor.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/pref/PreferenceEditor.java index 1a1305cf43..0cb0811f85 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/pref/PreferenceEditor.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/pref/PreferenceEditor.java @@ -26,7 +26,7 @@ */ public interface PreferenceEditor { - public void save(); + void save(); - public void revert(); + void revert(); } diff --git a/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/dialog/db/templateXML.xml b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/dialog/db/templateXML.xml new file mode 100644 index 0000000000..f911b05c79 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/resources/org/apache/cayenne/modeler/dialog/db/templateXML.xml @@ -0,0 +1,16 @@ + + false + false + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java b/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java index 0d3376f88c..864c63f499 100644 --- a/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java +++ b/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java @@ -30,10 +30,10 @@ import org.apache.cayenne.tools.dbimport.DbImportAction; import org.apache.cayenne.tools.dbimport.DbImportConfiguration; import org.apache.cayenne.tools.dbimport.DbImportModule; -import org.apache.cayenne.tools.dbimport.config.Catalog; -import org.apache.cayenne.tools.dbimport.config.FiltersConfigBuilder; -import org.apache.cayenne.tools.dbimport.config.ReverseEngineering; -import org.apache.cayenne.tools.dbimport.config.Schema; +import org.apache.cayenne.dbimport.Catalog; +import org.apache.cayenne.dbimport.FiltersConfigBuilder; +import org.apache.cayenne.dbimport.ReverseEngineering; +import org.apache.cayenne.dbimport.Schema; import org.apache.cayenne.util.Util; import org.apache.commons.logging.Log; import org.apache.maven.plugin.AbstractMojo; @@ -41,7 +41,6 @@ import org.apache.maven.plugin.MojoFailureException; import javax.sql.DataSource; -import java.io.File; /** * Maven mojo to reverse engineer datamap from DB. diff --git a/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java b/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java index 4ca219082d..91d588dcfc 100644 --- a/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java +++ b/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java @@ -18,18 +18,17 @@ ****************************************************************/ package org.apache.cayenne.tools; -import static org.apache.cayenne.tools.dbimport.config.DefaultReverseEngineeringLoaderTest.*; +import static org.apache.cayenne.dbimport.DefaultReverseEngineeringLoaderTest.*; import org.apache.cayenne.access.loader.filters.FiltersConfig; import org.apache.cayenne.access.loader.filters.IncludeTableFilter; import org.apache.cayenne.access.loader.filters.PatternFilter; import org.apache.cayenne.access.loader.filters.TableFilter; import org.apache.cayenne.tools.dbimport.DbImportConfiguration; -import org.apache.cayenne.tools.dbimport.config.Schema; +import org.apache.cayenne.dbimport.Schema; import org.apache.maven.plugin.testing.AbstractMojoTestCase; import org.junit.Test; -import java.util.Collections; import java.util.TreeSet; import java.util.regex.Pattern; @@ -67,7 +66,7 @@ public void testLoadSchema2() throws Exception { public void testLoadCatalogAndSchema() throws Exception { assertCatalogAndSchema(getCdbImport("pom-catalog-and-schema.xml").getReverseEngineering()); } - + @Test public void testDefaultPackage() throws Exception { DbImportConfiguration config = getCdbImport("pom-default-package.xml").toParameters(); diff --git a/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java b/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java index 858d75bba1..7365a6bd46 100644 --- a/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java +++ b/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java @@ -21,9 +21,9 @@ import org.apache.cayenne.test.jdbc.SQLReader; import org.apache.cayenne.test.resource.ResourceUtil; import org.apache.cayenne.tools.dbimport.DbImportConfiguration; -import org.apache.cayenne.tools.dbimport.config.Catalog; -import org.apache.cayenne.tools.dbimport.config.IncludeTable; -import org.apache.cayenne.tools.dbimport.config.Schema; +import org.apache.cayenne.dbimport.Catalog; +import org.apache.cayenne.dbimport.IncludeTable; +import org.apache.cayenne.dbimport.Schema; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.testing.AbstractMojoTestCase; import org.codehaus.plexus.util.FileUtils; From 3711bf5b24a36ca26aa6fa8dcd38817395722d04 Mon Sep 17 00:00:00 2001 From: ollybondareva Date: Tue, 2 Feb 2016 19:47:59 +0100 Subject: [PATCH 2/4] Improvement of cdbimport behavior in maven and ant --- .../DefaultReverseEngineeringWriterTest.java | 63 ++++------ .../cayenne/dbimport/reverseEngineering.xml | 21 +++- .../apache/cayenne/tools/DbImporterTask.java | 117 ++++++++++++++---- .../apache/cayenne/tools/DbImporterMojo.java | 109 +++++++++++++--- .../cayenne/tools/DbImporterMojoTest.java | 1 + 5 files changed, 229 insertions(+), 82 deletions(-) diff --git a/cayenne-server/src/test/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringWriterTest.java b/cayenne-server/src/test/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringWriterTest.java index e028431950..68a214dd05 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringWriterTest.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/dbimport/DefaultReverseEngineeringWriterTest.java @@ -1,56 +1,42 @@ -/* - * 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 +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ + * 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.dbimport; -import org.apache.cayenne.CayenneRuntimeException; import org.apache.cayenne.resource.Resource; import org.apache.cayenne.resource.URLResource; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.custommonkey.xmlunit.DetailedDiff; import org.custommonkey.xmlunit.Diff; -import org.custommonkey.xmlunit.Difference; import org.junit.Test; -import org.xml.sax.SAXException; -import sun.security.util.Resources; - -import javax.xml.bind.JAXBException; import java.io.*; import java.net.MalformedURLException; import java.net.URL; -import java.util.List; +import java.net.URLDecoder; import static org.junit.Assert.assertTrue; -/* - * @since 4.0 - */ - public class DefaultReverseEngineeringWriterTest { @Test public void testWriteReverseEngineering() throws Exception { ReverseEngineeringWriter engineering = new DefaultReverseEngineeringWriter(); ReverseEngineering reverseEngineering = new ReverseEngineering(); - Resource resource = getResource("reverseEngineering.xml"); - reverseEngineering.setConfigurationSource(resource); Catalog catalog1 = new Catalog("catalog1"); Catalog catalog2 = new Catalog("catalog2"); @@ -80,10 +66,13 @@ public void testWriteReverseEngineering() throws Exception { reverseEngineering.addSchema(new Schema("schema3")); - File file = new File(resource.getURL().getPath()); - PrintWriter printWriter = new PrintWriter(new FileWriter(file)); + URL url = getClass().getResource("reverseEngineering.xml"); + String decodedURL = URLDecoder.decode(url.getPath(), "UTF-8"); + Writer printWriter = new PrintWriter(decodedURL); - assertReverseEngineering(engineering.write(reverseEngineering, printWriter)); + reverseEngineering.setConfigurationSource(new URLResource(url)); + Resource reverseEngineeringResource = engineering.write(reverseEngineering, printWriter); + assertReverseEngineering(reverseEngineeringResource); } public void assertReverseEngineering(Resource resource) throws Exception { @@ -92,8 +81,8 @@ public void assertReverseEngineering(Resource resource) throws Exception { FileReader writedXML; FileReader expectedXML; - writedXML = new FileReader(url1.getPath()); - expectedXML = new FileReader(url2.getPath()); + writedXML = new FileReader(URLDecoder.decode(url1.getPath(), "UTF-8")); + expectedXML = new FileReader(URLDecoder.decode(url2.getPath(), "UTF-8")); Diff diff = new Diff(writedXML, expectedXML); assertTrue(diff.identical()); } diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering.xml b/cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering.xml index d6535640e8..28a73d0aa5 100644 --- a/cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering.xml +++ b/cayenne-server/src/test/resources/org/apache/cayenne/dbimport/reverseEngineering.xml @@ -1,3 +1,22 @@ - + + + \ No newline at end of file diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java index 36fe7f1d06..ddc44aec12 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java +++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java @@ -19,27 +19,24 @@ package org.apache.cayenne.tools; import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; import org.apache.cayenne.access.loader.filters.OldFilterConfigBridge; import org.apache.cayenne.configuration.DataNodeDescriptor; +import org.apache.cayenne.configuration.XMLDataMapLoader; import org.apache.cayenne.configuration.server.DataSourceFactory; import org.apache.cayenne.configuration.server.DbAdapterFactory; import org.apache.cayenne.conn.DataSourceInfo; import org.apache.cayenne.dba.DbAdapter; -import org.apache.cayenne.dbimport.AntNestedElement; -import org.apache.cayenne.dbimport.Catalog; -import org.apache.cayenne.dbimport.ExcludeColumn; -import org.apache.cayenne.dbimport.ExcludeProcedure; -import org.apache.cayenne.dbimport.ExcludeTable; -import org.apache.cayenne.dbimport.FiltersConfigBuilder; -import org.apache.cayenne.dbimport.IncludeColumn; -import org.apache.cayenne.dbimport.IncludeProcedure; -import org.apache.cayenne.dbimport.IncludeTable; -import org.apache.cayenne.dbimport.ReverseEngineering; -import org.apache.cayenne.dbimport.Schema; +import org.apache.cayenne.dbimport.*; import org.apache.cayenne.di.DIBootstrap; import org.apache.cayenne.di.Injector; +import org.apache.cayenne.map.DataMap; import org.apache.cayenne.map.naming.DefaultNameGenerator; +import org.apache.cayenne.resource.Resource; +import org.apache.cayenne.resource.URLResource; import org.apache.cayenne.tools.configuration.ToolsModule; import org.apache.cayenne.tools.dbimport.DbImportAction; import org.apache.cayenne.tools.dbimport.DbImportConfiguration; @@ -57,6 +54,7 @@ public class DbImporterTask extends Task { private final DbImportConfiguration config; private final ReverseEngineering reverseEngineering = new ReverseEngineering(); + private boolean isReverseEngineeringDefined = false; private final OldFilterConfigBridge filterBuilder = new OldFilterConfigBridge(); @@ -69,7 +67,7 @@ public DbImporterTask() { @Override public void execute() { - + File dataMapFile = config.getDataMapFile(); config.setFiltersConfig(new FiltersConfigBuilder(reverseEngineering) .add(filterBuilder) .filtersConfig()); @@ -82,26 +80,78 @@ public void execute() { config.setSkipPrimaryKeyLoading(reverseEngineering.getSkipPrimaryKeyLoading()); config.setTableTypes(reverseEngineering.getTableTypes()); - Injector injector = DIBootstrap.createInjector(new ToolsModule(logger), new DbImportModule()); + if (isReverseEngineeringDefined) { + Injector injector = DIBootstrap.createInjector(new ToolsModule(logger), new DbImportModule()); - validateDbImportConfiguration(config, injector); + validateDbImportConfiguration(config, injector); - try { - injector.getInstance(DbImportAction.class).execute(config); - } catch (Exception ex) { - Throwable th = Util.unwindException(ex); + try { + injector.getInstance(DbImportAction.class).execute(config); + } catch (Exception ex) { + Throwable th = Util.unwindException(ex); - String message = "Error importing database schema"; + String message = "Error importing database schema"; - if (th.getLocalizedMessage() != null) { - message += ": " + th.getLocalizedMessage(); - } + if (th.getLocalizedMessage() != null) { + message += ": " + th.getLocalizedMessage(); + } - log(message, Project.MSG_ERR); - throw new BuildException(message, th); + log(message, Project.MSG_ERR); + throw new BuildException(message, th); + } + finally { + injector.shutdown(); + } } - finally { - injector.shutdown(); + else { + if (dataMapFile.exists()) { + try { + URL url = dataMapFile.toURI().toURL(); + URLResource resource = new URLResource(url); + + XMLDataMapLoader xmlDataMapLoader = new XMLDataMapLoader(); + DataMap dataMap = xmlDataMapLoader.load(resource); + if (dataMap.getReverseEngineering() != null) { + Resource reverseEngineeringResource = new URLResource(dataMapFile.toURL()).getRelativeResource(dataMap.getReverseEngineering().getName() + ".reverseEngineering.xml"); + + DefaultReverseEngineeringLoader reverseEngineeringLoader = new DefaultReverseEngineeringLoader(); + ReverseEngineering reverseEngineering = reverseEngineeringLoader.load(reverseEngineeringResource.getURL().openStream()); + reverseEngineering.setName(dataMap.getReverseEngineering().getName()); + reverseEngineering.setConfigurationSource(reverseEngineeringResource); + dataMap.setReverseEngineering(reverseEngineering); + + FiltersConfigBuilder filtersConfigBuilder = new FiltersConfigBuilder(dataMap.getReverseEngineering()); + config.getDbLoaderConfig().setFiltersConfig(filtersConfigBuilder.filtersConfig()); + Injector injector = DIBootstrap.createInjector(new ToolsModule(logger), new DbImportModule()); + + validateDbImportConfiguration(config, injector); + + try { + injector.getInstance(DbImportAction.class).execute(config); + } catch (Exception ex) { + Throwable th = Util.unwindException(ex); + + String message = "Error importing database schema"; + + if (th.getLocalizedMessage() != null) { + message += ": " + th.getLocalizedMessage(); + } + + log(message, Project.MSG_ERR); + throw new BuildException(message, th); + } + finally { + injector.shutdown(); + } + } + } catch (MalformedURLException e) { + log(e.getMessage(), Project.MSG_ERR); + throw new BuildException(e.getMessage(), e); + } catch (IOException e) { + log(e.getMessage(), Project.MSG_ERR); + throw new BuildException(e.getMessage(), e); + } + } } } @@ -163,6 +213,7 @@ public void setOverwrite(boolean overwrite) { */ @Deprecated public void setSchemaName(String schemaName) { + isReverseEngineeringDefined = true; this.setSchema(schemaName); } @@ -170,6 +221,7 @@ public void setSchemaName(String schemaName) { * @since 4.0 */ public void setSchema(String schema) { + isReverseEngineeringDefined = true; filterBuilder.schema(schema); } @@ -181,14 +233,17 @@ public void setDefaultPackage(String defaultPackage) { } public void setTablePattern(String tablePattern) { + isReverseEngineeringDefined = true; filterBuilder.includeTables(tablePattern); } public void setImportProcedures(boolean importProcedures) { + isReverseEngineeringDefined = true; filterBuilder.setProceduresFilters(importProcedures); } public void setProcedurePattern(String procedurePattern) { + isReverseEngineeringDefined = true; filterBuilder.includeProcedures(procedurePattern); } @@ -242,6 +297,7 @@ public void setUserName(String username) { * @since 4.0 */ public void setIncludeTables(String includeTables) { + isReverseEngineeringDefined = true; filterBuilder.includeTables(includeTables); } @@ -249,6 +305,7 @@ public void setIncludeTables(String includeTables) { * @since 4.0 */ public void setExcludeTables(String excludeTables) { + isReverseEngineeringDefined = true; filterBuilder.excludeTables(excludeTables); } @@ -264,26 +321,32 @@ public void setSkipRelationshipsLoading(Boolean skipRelationshipsLoading) { } public void addConfiguredIncludeColumn(IncludeColumn includeColumn) { + isReverseEngineeringDefined = true; reverseEngineering.addIncludeColumn(includeColumn); } public void addConfiguredExcludeColumn(ExcludeColumn excludeColumn) { + isReverseEngineeringDefined = true; reverseEngineering.addExcludeColumn(excludeColumn); } public void addConfiguredIncludeTable(IncludeTable includeTable) { + isReverseEngineeringDefined = true; reverseEngineering.addIncludeTable(includeTable); } public void addConfiguredExcludeTable(ExcludeTable excludeTable) { + isReverseEngineeringDefined = true; reverseEngineering.addExcludeTable(excludeTable); } public void addConfiguredIncludeProcedure(IncludeProcedure includeProcedure) { + isReverseEngineeringDefined = true; reverseEngineering.addIncludeProcedure(includeProcedure); } public void addConfiguredExcludeProcedure(ExcludeProcedure excludeProcedure) { + isReverseEngineeringDefined = true; reverseEngineering.addExcludeProcedure(excludeProcedure); } @@ -292,10 +355,12 @@ public void addConfiguredSchema(Schema schema) { } public void addConfiguredCatalog(Catalog catalog) { + isReverseEngineeringDefined = true; reverseEngineering.addCatalog(catalog); } public void addConfiguredTableType(AntNestedElement type) { + isReverseEngineeringDefined = true; reverseEngineering.addTableType(type.getName()); } diff --git a/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java b/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java index 864c63f499..f3dfdc7488 100644 --- a/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java +++ b/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java @@ -18,22 +18,27 @@ ****************************************************************/ package org.apache.cayenne.tools; -import org.apache.cayenne.access.loader.filters.OldFilterConfigBridge; +import org.apache.cayenne.access.loader.filters.*; import org.apache.cayenne.configuration.DataNodeDescriptor; +import org.apache.cayenne.configuration.XMLDataMapLoader; import org.apache.cayenne.configuration.server.DataSourceFactory; import org.apache.cayenne.configuration.server.DbAdapterFactory; import org.apache.cayenne.dba.DbAdapter; import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; + +import org.apache.cayenne.dbimport.*; import org.apache.cayenne.di.DIBootstrap; import org.apache.cayenne.di.Injector; +import org.apache.cayenne.map.DataMap; +import org.apache.cayenne.resource.Resource; +import org.apache.cayenne.resource.URLResource; import org.apache.cayenne.tools.configuration.ToolsModule; import org.apache.cayenne.tools.dbimport.DbImportAction; import org.apache.cayenne.tools.dbimport.DbImportConfiguration; import org.apache.cayenne.tools.dbimport.DbImportModule; -import org.apache.cayenne.dbimport.Catalog; -import org.apache.cayenne.dbimport.FiltersConfigBuilder; -import org.apache.cayenne.dbimport.ReverseEngineering; -import org.apache.cayenne.dbimport.Schema; import org.apache.cayenne.util.Util; import org.apache.commons.logging.Log; import org.apache.maven.plugin.AbstractMojo; @@ -51,7 +56,6 @@ * @goal cdbimport */ public class DbImporterMojo extends AbstractMojo { - /** * DataMap XML file to use as a base for DB importing. * @@ -153,6 +157,12 @@ public class DbImporterMojo extends AbstractMojo { */ private ReverseEngineering reverseEngineering = new ReverseEngineering(); + private boolean isReverseEngineeringDefined = false; + + public void setIsReverseEngineeringDefined(boolean isReverseEngineeringDefined) { + this.isReverseEngineeringDefined = isReverseEngineeringDefined; + } + /** * DB schema to use for DB importing. * @@ -163,6 +173,7 @@ public class DbImporterMojo extends AbstractMojo { private DbImportConfiguration config; private void setSchemaName(String schemaName) { + isReverseEngineeringDefined = true; getLog().warn("'schemaName' property is deprecated. Use 'schema' instead"); filterBuilder.schema(schemaName); @@ -177,6 +188,7 @@ private void setSchemaName(String schemaName) { private Schema schema; public void setSchema(Schema schema) { + isReverseEngineeringDefined = true; if (schema.isEmptyContainer()) { filterBuilder.schema(schema.getName()); } else { @@ -194,6 +206,7 @@ public void setSchema(Schema schema) { private String tablePattern; public void setTablePattern(String tablePattern) { + isReverseEngineeringDefined = true; filterBuilder.includeTables(tablePattern); } @@ -222,6 +235,7 @@ public void setImportProcedures(boolean importProcedures) { private String procedurePattern; public void setProcedurePattern(String procedurePattern) { + isReverseEngineeringDefined = true; filterBuilder.includeProcedures(procedurePattern); } @@ -248,23 +262,74 @@ public void execute() throws MojoExecutionException, MojoFailureException { DbImportConfiguration config = toParameters(); config.setLogger(logger); - Injector injector = DIBootstrap.createInjector(new ToolsModule(logger), new DbImportModule()); + File dataMapFile = config.getDataMapFile(); - validateDbImportConfiguration(config, injector); + if (isReverseEngineeringDefined) { + Injector injector = DIBootstrap.createInjector(new ToolsModule(logger), new DbImportModule()); - try { - injector.getInstance(DbImportAction.class).execute(config); - } catch (Exception ex) { - Throwable th = Util.unwindException(ex); + validateDbImportConfiguration(config, injector); - String message = "Error importing database schema"; + try { + injector.getInstance(DbImportAction.class).execute(config); + } catch (Exception ex) { + Throwable th = Util.unwindException(ex); - if (th.getLocalizedMessage() != null) { - message += ": " + th.getLocalizedMessage(); - } + String message = "Error importing database schema"; - getLog().error(message); - throw new MojoExecutionException(message, th); + if (th.getLocalizedMessage() != null) { + message += ": " + th.getLocalizedMessage(); + } + + getLog().error(message); + throw new MojoExecutionException(message, th); + } + } + else { + if (dataMapFile.exists()) { + try { + URL url = dataMapFile.toURI().toURL(); + URLResource resource = new URLResource(url); + + XMLDataMapLoader xmlDataMapLoader = new XMLDataMapLoader(); + DataMap dataMap = xmlDataMapLoader.load(resource); + if (dataMap.getReverseEngineering() != null) { + Resource reverseEngineeringResource = new URLResource(dataMapFile.toURI().toURL()).getRelativeResource(dataMap.getReverseEngineering().getName() + ".reverseEngineering.xml"); + + DefaultReverseEngineeringLoader reverseEngineeringLoader = new DefaultReverseEngineeringLoader(); + ReverseEngineering reverseEngineering = reverseEngineeringLoader.load(reverseEngineeringResource.getURL().openStream()); + reverseEngineering.setName(dataMap.getReverseEngineering().getName()); + reverseEngineering.setConfigurationSource(reverseEngineeringResource); + dataMap.setReverseEngineering(reverseEngineering); + + FiltersConfigBuilder filtersConfigBuilder = new FiltersConfigBuilder(dataMap.getReverseEngineering()); + config.getDbLoaderConfig().setFiltersConfig(filtersConfigBuilder.filtersConfig()); + Injector injector = DIBootstrap.createInjector(new ToolsModule(logger), new DbImportModule()); + + validateDbImportConfiguration(config, injector); + + try { + injector.getInstance(DbImportAction.class).execute(config); + } catch (Exception ex) { + Throwable th = Util.unwindException(ex); + + String message = "Error importing database schema"; + + if (th.getLocalizedMessage() != null) { + message += ": " + th.getLocalizedMessage(); + } + + getLog().error(message); + throw new MojoExecutionException(message, th); + } + } + } catch (MalformedURLException e) { + getLog().error(e); + throw new MojoExecutionException(e.getMessage(), e); + } catch (IOException e) { + getLog().error(e); + throw new MojoExecutionException(e.getMessage(), e); + } + } } } @@ -349,6 +414,7 @@ public void setUrl(String url) { private String includeTables; public void setIncludeTables(String includeTables) { + isReverseEngineeringDefined = true; filterBuilder.includeTables(includeTables); } @@ -361,10 +427,12 @@ public void setIncludeTables(String includeTables) { private String excludeTables; public void setExcludeTables(String excludeTables) { + isReverseEngineeringDefined = true; filterBuilder.excludeTables(excludeTables); } public void addSchema(Schema schema) { + isReverseEngineeringDefined = true; reverseEngineering.addSchema(schema); } @@ -377,6 +445,8 @@ public void addSchema(Schema schema) { private Catalog catalog[]; public void addCatalog(Catalog catalog) { + isReverseEngineeringDefined = true; + if (catalog != null) { if (catalog.isEmptyContainer()) { filterBuilder.catalog(catalog.getName()); @@ -391,6 +461,9 @@ public ReverseEngineering getReverseEngineering() { } public void setReverseEngineering(ReverseEngineering reverseEngineering) { + isReverseEngineeringDefined = true; this.reverseEngineering = reverseEngineering; } } + + diff --git a/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java b/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java index 7365a6bd46..7f60aa1ec0 100644 --- a/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java +++ b/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java @@ -296,6 +296,7 @@ private void test(String name) throws Exception { DbImportConfiguration parameters = cdbImport.toParameters(); prepareDatabase(name, parameters); + cdbImport.setIsReverseEngineeringDefined(true); try { cdbImport.execute(); verifyResult(mapFile, mapFileCopy); From 2b56d2d050ec7313c187ca0c5f6e3591f0b40d4b Mon Sep 17 00:00:00 2001 From: Olya Bondareva Date: Wed, 24 Feb 2016 20:50:36 +0100 Subject: [PATCH 3/4] modification of reverse engineering file name, modification of reverse engineering name in datamap and initialization of name mapper in mvn and ant using di --- .../DefaultConfigurationNameMapper.java | 2 +- .../java/org/apache/cayenne/map/DataMap.java | 2 +- .../org/apache/cayenne/map/MapLoader.java | 2 +- .../apache/cayenne/tools/DbImporterTask.java | 39 +++++----- .../apache/cayenne/tools/DbImporterMojo.java | 75 +++++++++++-------- 5 files changed, 62 insertions(+), 58 deletions(-) diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/DefaultConfigurationNameMapper.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/DefaultConfigurationNameMapper.java index 24cea5d948..16b782a2cb 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/DefaultConfigurationNameMapper.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/DefaultConfigurationNameMapper.java @@ -32,7 +32,7 @@ public class DefaultConfigurationNameMapper implements ConfigurationNameMapper { private static final String DATA_MAP_SUFFIX = ".map.xml"; - private static final String REVERSE_ENGINEERING_SUFFIX = ".reverseEngineering.xml"; + private static final String REVERSE_ENGINEERING_SUFFIX = ".xml"; protected ConfigurationNodeVisitor nameMapper; diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/DataMap.java b/cayenne-server/src/main/java/org/apache/cayenne/map/DataMap.java index d05418ce73..fb534047f9 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/map/DataMap.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/map/DataMap.java @@ -332,7 +332,7 @@ public void encodeAsXML(XMLEncoder encoder) { encoder.println(">"); if (reverseEngineering != null) { - encoder.print(""); } diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/MapLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/map/MapLoader.java index ed687edd14..7c47bc0d5e 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/map/MapLoader.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/map/MapLoader.java @@ -49,7 +49,7 @@ public class MapLoader extends DefaultHandler { /** * @since 4.0 */ - public static final String REVERSE_ENGINEERING = "reverseEngineering"; + public static final String REVERSE_ENGINEERING = "reverse-engineering-config"; public static final String PROPERTY_TAG = "property"; diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java index ddc44aec12..b524409d5a 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java +++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java @@ -24,6 +24,7 @@ import java.net.URL; import org.apache.cayenne.access.loader.filters.OldFilterConfigBridge; +import org.apache.cayenne.configuration.ConfigurationNameMapper; import org.apache.cayenne.configuration.DataNodeDescriptor; import org.apache.cayenne.configuration.XMLDataMapLoader; import org.apache.cayenne.configuration.server.DataSourceFactory; @@ -98,12 +99,10 @@ public void execute() { log(message, Project.MSG_ERR); throw new BuildException(message, th); - } - finally { + } finally { injector.shutdown(); } - } - else { + } else { if (dataMapFile.exists()) { try { URL url = dataMapFile.toURI().toURL(); @@ -112,21 +111,21 @@ public void execute() { XMLDataMapLoader xmlDataMapLoader = new XMLDataMapLoader(); DataMap dataMap = xmlDataMapLoader.load(resource); if (dataMap.getReverseEngineering() != null) { - Resource reverseEngineeringResource = new URLResource(dataMapFile.toURL()).getRelativeResource(dataMap.getReverseEngineering().getName() + ".reverseEngineering.xml"); - - DefaultReverseEngineeringLoader reverseEngineeringLoader = new DefaultReverseEngineeringLoader(); - ReverseEngineering reverseEngineering = reverseEngineeringLoader.load(reverseEngineeringResource.getURL().openStream()); - reverseEngineering.setName(dataMap.getReverseEngineering().getName()); - reverseEngineering.setConfigurationSource(reverseEngineeringResource); - dataMap.setReverseEngineering(reverseEngineering); - - FiltersConfigBuilder filtersConfigBuilder = new FiltersConfigBuilder(dataMap.getReverseEngineering()); - config.getDbLoaderConfig().setFiltersConfig(filtersConfigBuilder.filtersConfig()); Injector injector = DIBootstrap.createInjector(new ToolsModule(logger), new DbImportModule()); - - validateDbImportConfiguration(config, injector); - try { + ConfigurationNameMapper nameMapper = injector.getInstance(ConfigurationNameMapper.class); + String reverseEngineeringLocation = nameMapper.configurationLocation(ReverseEngineering.class, dataMap.getReverseEngineering().getName()); + Resource reverseEngineeringResource = new URLResource(dataMapFile.toURI().toURL()).getRelativeResource(reverseEngineeringLocation); + + DefaultReverseEngineeringLoader reverseEngineeringLoader = new DefaultReverseEngineeringLoader(); + ReverseEngineering reverseEngineering = reverseEngineeringLoader.load(reverseEngineeringResource.getURL().openStream()); + reverseEngineering.setName(dataMap.getReverseEngineering().getName()); + reverseEngineering.setConfigurationSource(reverseEngineeringResource); + dataMap.setReverseEngineering(reverseEngineering); + + FiltersConfigBuilder filtersConfigBuilder = new FiltersConfigBuilder(dataMap.getReverseEngineering()); + config.getDbLoaderConfig().setFiltersConfig(filtersConfigBuilder.filtersConfig()); + validateDbImportConfiguration(config, injector); injector.getInstance(DbImportAction.class).execute(config); } catch (Exception ex) { Throwable th = Util.unwindException(ex); @@ -139,17 +138,13 @@ public void execute() { log(message, Project.MSG_ERR); throw new BuildException(message, th); - } - finally { + } finally { injector.shutdown(); } } } catch (MalformedURLException e) { log(e.getMessage(), Project.MSG_ERR); throw new BuildException(e.getMessage(), e); - } catch (IOException e) { - log(e.getMessage(), Project.MSG_ERR); - throw new BuildException(e.getMessage(), e); } } } diff --git a/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java b/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java index f3dfdc7488..30cae6ede2 100644 --- a/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java +++ b/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java @@ -18,12 +18,14 @@ ****************************************************************/ package org.apache.cayenne.tools; -import org.apache.cayenne.access.loader.filters.*; +import org.apache.cayenne.access.loader.filters.OldFilterConfigBridge; +import org.apache.cayenne.configuration.ConfigurationNameMapper; import org.apache.cayenne.configuration.DataNodeDescriptor; import org.apache.cayenne.configuration.XMLDataMapLoader; import org.apache.cayenne.configuration.server.DataSourceFactory; import org.apache.cayenne.configuration.server.DbAdapterFactory; import org.apache.cayenne.dba.DbAdapter; + import java.io.File; import java.io.IOException; import java.net.MalformedURLException; @@ -31,6 +33,7 @@ import org.apache.cayenne.dbimport.*; import org.apache.cayenne.di.DIBootstrap; +import org.apache.cayenne.di.Inject; import org.apache.cayenne.di.Injector; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.resource.Resource; @@ -49,16 +52,16 @@ /** * Maven mojo to reverse engineer datamap from DB. - * + * * @since 3.0 - * + * * @phase generate-sources * @goal cdbimport */ public class DbImporterMojo extends AbstractMojo { /** * DataMap XML file to use as a base for DB importing. - * + * * @parameter map="map" * @required */ @@ -68,7 +71,7 @@ public class DbImporterMojo extends AbstractMojo { * A default package for ObjEntity Java classes. If not specified, and the * existing DataMap already has the default package, the existing package * will be used. - * + * * @parameter defaultPackage="defaultPackage" * @since 4.0 */ @@ -78,7 +81,7 @@ public class DbImporterMojo extends AbstractMojo { * Indicates that the old mapping should be completely removed and replaced * with the new data based on reverse engineering. Default is * true. - * + * * @parameter overwrite="overwrite" default-value="true" */ private boolean overwrite; @@ -93,9 +96,9 @@ public class DbImporterMojo extends AbstractMojo { * Java class implementing org.apache.cayenne.map.naming.NamingStrategy. * This is used to specify how ObjEntities will be mapped from the imported * DB schema. - * + * * The default is a basic naming strategy. - * + * * @parameter namingStrategy="namingStrategy" * default-value="org.apache.cayenne.map.naming.DefaultNameGenerator" */ @@ -105,7 +108,7 @@ public class DbImporterMojo extends AbstractMojo { * Java class implementing org.apache.cayenne.dba.DbAdapter. This attribute * is optional, the default is AutoAdapter, i.e. Cayenne would try to guess * the DB type. - * + * * @parameter adapter="adapter" * default-value="org.apache.cayenne.dba.AutoAdapter" */ @@ -113,7 +116,7 @@ public class DbImporterMojo extends AbstractMojo { /** * A class of JDBC driver to use for the target database. - * + * * @parameter driver="driver" * @required */ @@ -121,7 +124,7 @@ public class DbImporterMojo extends AbstractMojo { /** * JDBC connection URL of a target database. - * + * * @parameter url="url" * @required */ @@ -129,21 +132,21 @@ public class DbImporterMojo extends AbstractMojo { /** * Database user name. - * + * * @parameter username="username" */ private String username; /** * Database user password. - * + * * @parameter password="password" */ private String password; /** * If true, would use primitives instead of numeric and boolean classes. - * + * * @parameter usePrimitives="usePrimitives" default-value="true" */ private boolean usePrimitives; @@ -157,6 +160,16 @@ public class DbImporterMojo extends AbstractMojo { */ private ReverseEngineering reverseEngineering = new ReverseEngineering(); + /** + * Flag which defines from where to take the configuration of cdbImport. + * If we define the config of cdbImport in pom.xml + * we should set it to true or it will be setted to true automatically + * if we will define some configuration parameters in pom.xml + * Else it remains default(false) and for cdbImport + * we use the configuration defined in signed dataMap + * + * @parameter isReverseEngineeringDefined="isReverseEngineeringDefined" default-value="false" + */ private boolean isReverseEngineeringDefined = false; public void setIsReverseEngineeringDefined(boolean isReverseEngineeringDefined) { @@ -283,8 +296,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { getLog().error(message); throw new MojoExecutionException(message, th); } - } - else { + } else { if (dataMapFile.exists()) { try { URL url = dataMapFile.toURI().toURL(); @@ -293,21 +305,21 @@ public void execute() throws MojoExecutionException, MojoFailureException { XMLDataMapLoader xmlDataMapLoader = new XMLDataMapLoader(); DataMap dataMap = xmlDataMapLoader.load(resource); if (dataMap.getReverseEngineering() != null) { - Resource reverseEngineeringResource = new URLResource(dataMapFile.toURI().toURL()).getRelativeResource(dataMap.getReverseEngineering().getName() + ".reverseEngineering.xml"); - - DefaultReverseEngineeringLoader reverseEngineeringLoader = new DefaultReverseEngineeringLoader(); - ReverseEngineering reverseEngineering = reverseEngineeringLoader.load(reverseEngineeringResource.getURL().openStream()); - reverseEngineering.setName(dataMap.getReverseEngineering().getName()); - reverseEngineering.setConfigurationSource(reverseEngineeringResource); - dataMap.setReverseEngineering(reverseEngineering); - - FiltersConfigBuilder filtersConfigBuilder = new FiltersConfigBuilder(dataMap.getReverseEngineering()); - config.getDbLoaderConfig().setFiltersConfig(filtersConfigBuilder.filtersConfig()); - Injector injector = DIBootstrap.createInjector(new ToolsModule(logger), new DbImportModule()); - - validateDbImportConfiguration(config, injector); - try { + Injector injector = DIBootstrap.createInjector(new ToolsModule(logger), new DbImportModule()); + ConfigurationNameMapper nameMapper = injector.getInstance(ConfigurationNameMapper.class); + String reverseEngineeringLocation = nameMapper.configurationLocation(ReverseEngineering.class, dataMap.getReverseEngineering().getName()); + Resource reverseEngineeringResource = new URLResource(dataMapFile.toURI().toURL()).getRelativeResource(reverseEngineeringLocation); + + DefaultReverseEngineeringLoader reverseEngineeringLoader = new DefaultReverseEngineeringLoader(); + ReverseEngineering reverseEngineering = reverseEngineeringLoader.load(reverseEngineeringResource.getURL().openStream()); + reverseEngineering.setName(dataMap.getReverseEngineering().getName()); + reverseEngineering.setConfigurationSource(reverseEngineeringResource); + dataMap.setReverseEngineering(reverseEngineering); + + FiltersConfigBuilder filtersConfigBuilder = new FiltersConfigBuilder(dataMap.getReverseEngineering()); + config.getDbLoaderConfig().setFiltersConfig(filtersConfigBuilder.filtersConfig()); + validateDbImportConfiguration(config, injector); injector.getInstance(DbImportAction.class).execute(config); } catch (Exception ex) { Throwable th = Util.unwindException(ex); @@ -325,9 +337,6 @@ public void execute() throws MojoExecutionException, MojoFailureException { } catch (MalformedURLException e) { getLog().error(e); throw new MojoExecutionException(e.getMessage(), e); - } catch (IOException e) { - getLog().error(e); - throw new MojoExecutionException(e.getMessage(), e); } } } From dd09fb6e2e76b57cc280dce3a1222190894973d8 Mon Sep 17 00:00:00 2001 From: Olya Bondareva Date: Thu, 25 Feb 2016 15:12:30 +0100 Subject: [PATCH 4/4] modification when we don't sign catalog and schema in filterConfig --- .../org/apache/cayenne/access/DbLoader.java | 20 ++ .../apache/cayenne/tools/DbImporterTask.java | 1 - .../db/ReverseEngineeringController.java | 214 +++++++++++++----- .../modeler/dialog/db/model/DBElement.java | 9 + .../apache/cayenne/tools/DbImporterMojo.java | 2 - 5 files changed, 182 insertions(+), 64 deletions(-) diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java index af4358ba75..67477dd98a 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java @@ -117,6 +117,26 @@ private DatabaseMetaData getMetaData() throws SQLException { return metaData; } + /** + * Check if database support schemas. + */ + protected boolean supportSchemas() throws SQLException { + if (metaData == null) { + metaData = connection.getMetaData(); + } + return metaData.supportsSchemasInTableDefinitions(); + } + + /** + * Check if database support catalogs. + */ + protected boolean supportCatalogs() throws SQLException { + if (metaData == null) { + metaData = connection.getMetaData(); + } + return metaData.supportsCatalogsInTableDefinitions(); + } + /** * @since 3.0 */ diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java index b524409d5a..119ebf41e0 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java +++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java @@ -19,7 +19,6 @@ package org.apache.cayenne.tools; import java.io.File; -import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ReverseEngineeringController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ReverseEngineeringController.java index f0841878c3..ad8b2b8216 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ReverseEngineeringController.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ReverseEngineeringController.java @@ -1,22 +1,21 @@ /***************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. ****************************************************************/ - package org.apache.cayenne.modeler.dialog.db; import org.apache.cayenne.access.DbLoader; @@ -117,25 +116,62 @@ public void syncAction() throws SQLException { try { buildDBProperties(); - DbLoader dbLoader = new DbLoader(connection, adapter, new DefaultDbLoaderDelegate()) { + final DbLoader dbLoader = new DbLoader(connection, adapter, new DefaultDbLoaderDelegate()) { @Override public DataMap load(DbLoaderConfiguration config) throws SQLException { DataMap dataMap = new DataMap(); Map procedureMap = loadProcedures(dataMap, config); - load(dataMap, config, procedureMap); + load(dataMap, config); + addProcedures(procedureMap); return dataMap; } - public void load(DataMap dataMap, DbLoaderConfiguration config, Map procedureMap - ) - throws SQLException { - LOGGER.info("Schema loading..."); - - String[] types = config.getTableTypes(); - if (types == null || types.length == 0) { - types = getDefaultTableTypes(); + private void addProcedures(Map procedureMap) throws SQLException { + DBElement currentDBCatalog; + DBElement currentDBSchema; + for (Map.Entry procedure : procedureMap.entrySet()) { + if (supportCatalogs()) { + String dbCatalogName = procedure.getValue().getCatalog(); + DBElement dbCatalog = dbModel.getExistingElement(dbCatalogName); + if (dbCatalog != null) { + currentDBCatalog = dbCatalog; + } else { + currentDBCatalog = new DBCatalog(dbCatalogName); + dbModel.addElement(currentDBCatalog); + } + if (supportSchemas()) { + String dbSchemaName = procedure.getValue().getSchema(); + DBElement dbSchema = currentDBCatalog.getExistingElement(dbSchemaName); + if (dbSchema != null) { + currentDBSchema = dbSchema; + } else { + currentDBSchema = new DBSchema(dbSchemaName); + currentDBCatalog.addElement(currentDBSchema); + } + DBProcedure currentProcedure = new DBProcedure(procedure.getValue().getName()); + currentDBSchema.addElement(currentProcedure); + } else { + DBProcedure currentProcedure = new DBProcedure(procedure.getValue().getName()); + currentDBCatalog.addElement(currentProcedure); + } + } else { + if (supportSchemas()) { + String dbSchemaName = procedure.getValue().getSchema(); + DBElement dbSchema = dbModel.getExistingElement(dbSchemaName); + if (dbSchema != null) { + currentDBSchema = dbSchema; + } else { + currentDBSchema = new DBSchema(dbSchemaName); + dbModel.addElement(currentDBSchema); + } + DBProcedure currentProcedure = new DBProcedure(procedure.getValue().getName()); + currentDBSchema.addElement(currentProcedure); + } + } } + } + private void createIfNotNull(DataMap dataMap, DbLoaderConfiguration config, String[] types) throws SQLException { treeEditor.setRoot(dataSourceKey); dbModel = new DBModel(dataSourceKey); boolean catalogSetted = false; @@ -144,13 +180,12 @@ public void load(DataMap dataMap, DbLoaderConfiguration config, Map entityList = createTableLoader(catalog.name, schema.name, schema.tables).loadDbEntities( dataMap, config, types); DbEntity entityFromLoader = entityList.get(0); if (entityFromLoader != null) { - if (catalogSetted == false && entityFromLoader.getCatalog() != null) { + if (!catalogSetted && entityFromLoader.getCatalog() != null) { currentDBCatalog = new DBCatalog(entityFromLoader.getCatalog()); dbModel.addElement(currentDBCatalog); catalogSetted = true; @@ -158,28 +193,7 @@ public void load(DataMap dataMap, DbLoaderConfiguration config, Map entry = procedureMap.entrySet().iterator().next(); - Procedure procedure = entry.getValue(); - - if (catalogSetted && procedure.getCatalog() != null) { - currentDBCatalog = new DBCatalog(procedure.getCatalog()); - dbModel.addElement(currentDBCatalog); - catalogSetted = true; - } - - if (procedure.getSchema() != null) { - currentDBSchema = new DBSchema(procedure.getSchema()); - if(currentDBCatalog != null) { + if (currentDBCatalog != null) { currentDBCatalog.addElement(currentDBSchema); } else { dbModel.addElement(currentDBSchema); @@ -205,22 +219,100 @@ public void load(DataMap dataMap, DbLoaderConfiguration config, Map entry : procedureMap.entrySet()) { - currentDBSchema.addElement(new DBProcedure(entry.getValue().getName())); - } - } else { - for (Map.Entry entry : procedureMap.entrySet()) { - currentDBCatalog.addElement(new DBProcedure(entry.getValue().getName())); - } - } currentDBSchema = null; } catalogSetted = false; currentDBCatalog = null; } } + + private void createIfNull(DataMap dataMap, DbLoaderConfiguration config, String[] types) throws SQLException { + treeEditor.setRoot(dataSourceKey); + dbModel = new DBModel(dataSourceKey); + DBElement currentDBCatalog; + DBElement currentDBSchema; + + for (CatalogFilter catalog : config.getFiltersConfig().catalogs) { + for (SchemaFilter schema : catalog.schemas) { + List entityList = createTableLoader(catalog.name, schema.name, schema.tables).loadDbEntities( + dataMap, config, types); + + for (DbEntity dbEntity : entityList) { + if (supportCatalogs()) { + String dbCatalogName = dbEntity.getCatalog(); + DBElement dbCatalog = dbModel.getExistingElement(dbCatalogName); + if (dbCatalog != null) { + currentDBCatalog = dbCatalog; + } else { + currentDBCatalog = new DBCatalog(dbCatalogName); + dbModel.addElement(currentDBCatalog); + } + if (supportSchemas()) { + String dbSchemaName = dbEntity.getSchema(); + DBElement dbSchema = currentDBCatalog.getExistingElement(dbSchemaName); + if (dbSchema != null) { + currentDBSchema = dbSchema; + } else { + currentDBSchema = new DBSchema(dbSchemaName); + currentDBCatalog.addElement(currentDBSchema); + } + DBEntity currentDBEntity = new DBEntity(dbEntity.getName()); + currentDBSchema.addElement(currentDBEntity); + for (DbAttribute dbColumn : dbEntity.getAttributes()) { + currentDBEntity.addElement(new DBColumn(dbColumn.getName())); + } + } else { + DBEntity currentDBEntity = new DBEntity(dbEntity.getName()); + currentDBCatalog.addElement(currentDBEntity); + for (DbAttribute dbColumn : dbEntity.getAttributes()) { + currentDBEntity.addElement(new DBColumn(dbColumn.getName())); + } + } + } else { + if (supportSchemas()) { + String dbSchemaName = dbEntity.getSchema(); + DBElement dbSchema = dbModel.getExistingElement(dbSchemaName); + if (dbSchema != null) { + currentDBSchema = dbSchema; + } else { + currentDBSchema = new DBSchema(dbSchemaName); + dbModel.addElement(currentDBSchema); + } + DBEntity currentDBEntity = new DBEntity(dbEntity.getName()); + currentDBSchema.addElement(currentDBEntity); + for (DbAttribute dbColumn : dbEntity.getAttributes()) { + currentDBEntity.addElement(new DBColumn(dbColumn.getName())); + } + } + } + } + } + } + } + + public void load(DataMap dataMap, DbLoaderConfiguration config + ) + throws SQLException { + LOGGER.info("Schema loading..."); + + String[] types = config.getTableTypes(); + if (types == null || types.length == 0) { + types = getDefaultTableTypes(); + } + boolean isNullDetected = false; + for (CatalogFilter catalog : config.getFiltersConfig().catalogs) { + for (SchemaFilter schema : catalog.schemas) { + if (schema.name == null && catalog.name == null) { + isNullDetected = true; + } + } + } + if (isNullDetected) { + createIfNull(dataMap, config, types); + } else { + createIfNotNull(dataMap, config, types); + } + } }; ReverseEngineering reverseEngineering = xmlFileEditor.convertTextIntoReverseEngineering(); diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBElement.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBElement.java index b3a352f80c..c9c9411ceb 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBElement.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/model/DBElement.java @@ -37,6 +37,15 @@ public List getDbElements() { return dbElements; } + public DBElement getExistingElement(String name) { + for (DBElement dbElement : dbElements) { + if (dbElement.name.equals(name)) { + return dbElement; + } + } + return null; + } + public abstract void addElement(DBElement dbElement); public String getName() { diff --git a/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java b/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java index 30cae6ede2..f3198d8134 100644 --- a/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java +++ b/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java @@ -27,13 +27,11 @@ import org.apache.cayenne.dba.DbAdapter; import java.io.File; -import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import org.apache.cayenne.dbimport.*; import org.apache.cayenne.di.DIBootstrap; -import org.apache.cayenne.di.Inject; import org.apache.cayenne.di.Injector; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.resource.Resource;