You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2016/09/29 17:38:47 UTC
[01/15] cayenne git commit: CAY-2116 Split schema synchronization
code in a separate module
Repository: cayenne
Updated Branches:
refs/heads/master 8c7bec0f4 -> 2f7b1d533
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/MigrateAction.java
----------------------------------------------------------------------
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 ac0ed01..b2fb25b 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
@@ -19,14 +19,9 @@
package org.apache.cayenne.modeler.action;
-import java.awt.event.ActionEvent;
-import java.util.List;
-
-import javax.sql.DataSource;
-import javax.swing.JOptionPane;
-
-import org.apache.cayenne.access.DbLoader;
import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider;
+import org.apache.cayenne.dbsync.reverse.DbLoader;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.modeler.Application;
import org.apache.cayenne.modeler.dialog.db.DataSourceController;
@@ -34,19 +29,24 @@ import org.apache.cayenne.modeler.dialog.db.DbMigrateOptionsDialog;
import org.apache.cayenne.modeler.dialog.db.MergerOptions;
import org.apache.cayenne.modeler.pref.DBConnectionInfo;
+import javax.sql.DataSource;
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.util.List;
+
/**
* Action that alter database schema to match a DataMap.
*/
public class MigrateAction extends DBWizardAction {
- public static String getActionName() {
- return "Migrate Database Schema";
- }
-
public MigrateAction(Application application) {
super(getActionName(), application);
}
+ public static String getActionName() {
+ return "Migrate Database Schema";
+ }
+
public void performAction(ActionEvent e) {
DBConnectionInfo nodeInfo = preferredDataSource();
@@ -71,38 +71,40 @@ public class MigrateAction extends DBWizardAction {
throw new IllegalStateException("No current DataMap selected.");
}
//showOptions dialog
- String selectedSchema = null;
- try {
- List<String> schemas = getSchemas(connectWizard);
- if (schemas != null && !schemas.isEmpty()) {
- DbMigrateOptionsDialog optionsDialog = new DbMigrateOptionsDialog(schemas, connectWizard.getConnectionInfo().getUserName());
- optionsDialog.showDialog();
- if (optionsDialog.getChoice() == DbMigrateOptionsDialog.SELECT) {
- selectedSchema = optionsDialog.getSelectedSchema();
- }
- }
- } catch (Exception ex) {
- JOptionPane.showMessageDialog(
- Application.getFrame(),
- ex.getMessage(),
- "Error loading schemas dialog",
- JOptionPane.ERROR_MESSAGE);
- }
-
+ String selectedSchema = null;
+ try {
+ List<String> schemas = getSchemas(connectWizard);
+ if (schemas != null && !schemas.isEmpty()) {
+ DbMigrateOptionsDialog optionsDialog = new DbMigrateOptionsDialog(schemas, connectWizard.getConnectionInfo().getUserName());
+ optionsDialog.showDialog();
+ if (optionsDialog.getChoice() == DbMigrateOptionsDialog.SELECT) {
+ selectedSchema = optionsDialog.getSelectedSchema();
+ }
+ }
+ } catch (Exception ex) {
+ JOptionPane.showMessageDialog(
+ Application.getFrame(),
+ ex.getMessage(),
+ "Error loading schemas dialog",
+ JOptionPane.ERROR_MESSAGE);
+ }
+
+ MergerTokenFactoryProvider mergerTokenFactoryProvider =
+ getApplication().getInjector().getInstance(MergerTokenFactoryProvider.class);
// ... show dialog...
new MergerOptions(
getProjectController(),
"Migrate DB Schema: Options",
connectWizard.getConnectionInfo(),
- map, selectedSchema).startupAction();
+ map, selectedSchema, mergerTokenFactoryProvider).startupAction();
}
private List<String> getSchemas(DataSourceController connectWizard) throws Exception {
- DbAdapter dbAdapter = connectWizard.getConnectionInfo()
- .makeAdapter(getApplication().getClassLoadingService());
- DataSource dataSource = connectWizard.getConnectionInfo()
- .makeDataSource(getApplication().getClassLoadingService());
- return new DbLoader(dataSource.getConnection(), dbAdapter, null).getSchemas();
+ DbAdapter dbAdapter = connectWizard.getConnectionInfo()
+ .makeAdapter(getApplication().getClassLoadingService());
+ DataSource dataSource = connectWizard.getConnectionInfo()
+ .makeDataSource(getApplication().getClassLoadingService());
+ return new DbLoader(dataSource.getConnection(), dbAdapter, null).getSchemas();
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ObjEntitySyncAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ObjEntitySyncAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ObjEntitySyncAction.java
index d851225..756d7fa 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ObjEntitySyncAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/ObjEntitySyncAction.java
@@ -19,13 +19,8 @@
package org.apache.cayenne.modeler.action;
-import java.awt.Toolkit;
-import java.awt.event.ActionEvent;
-import java.awt.event.KeyEvent;
-
-import javax.swing.KeyStroke;
-
import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.dbsync.merge.EntityMergeSupport;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.event.EntityEvent;
import org.apache.cayenne.map.event.MapEvent;
@@ -34,7 +29,11 @@ import org.apache.cayenne.modeler.ProjectController;
import org.apache.cayenne.modeler.dialog.objentity.EntitySyncController;
import org.apache.cayenne.modeler.event.EntityDisplayEvent;
import org.apache.cayenne.modeler.util.CayenneAction;
-import org.apache.cayenne.util.EntityMergeSupport;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
/**
* Action that synchronizes a given ObjEntity with the current state of the underlying
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/DbLoaderHelper.java
----------------------------------------------------------------------
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 743d410..92123c0 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
@@ -20,12 +20,13 @@
package org.apache.cayenne.modeler.dialog.db;
import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.access.DbLoader;
-import org.apache.cayenne.access.loader.DefaultDbLoaderDelegate;
import org.apache.cayenne.configuration.DataChannelDescriptor;
import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dbimport.FiltersConfigBuilder;
import org.apache.cayenne.dbimport.ReverseEngineering;
+import org.apache.cayenne.dbsync.CayenneDbSyncModule;
+import org.apache.cayenne.dbsync.reverse.DbLoader;
+import org.apache.cayenne.dbsync.reverse.DefaultDbLoaderDelegate;
+import org.apache.cayenne.dbsync.reverse.FiltersConfigBuilder;
import org.apache.cayenne.di.DIBootstrap;
import org.apache.cayenne.di.Injector;
import org.apache.cayenne.map.DataMap;
@@ -47,9 +48,7 @@ import org.apache.cayenne.util.Util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import javax.swing.JFrame;
-import javax.swing.JOptionPane;
-import javax.swing.SwingUtilities;
+import javax.swing.*;
import java.io.File;
import java.sql.Connection;
import java.sql.SQLException;
@@ -375,7 +374,10 @@ public class DbLoaderHelper {
ModelerDbImportAction importAction = new ModelerDbImportAction(logObj, DbLoaderHelper.this);
- Injector injector = DIBootstrap.createInjector(new ToolsModule(logObj), new DbImportModule());
+
+ // TODO: we can keep all these things in the Modeler Injector instead of creating a new one?
+ // we already have CayenneDbSyncModule in there
+ Injector injector = DIBootstrap.createInjector(new CayenneDbSyncModule(), new ToolsModule(logObj), new DbImportModule());
injector.injectMembers(importAction);
try {
importAction.execute(config);
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java
----------------------------------------------------------------------
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 ab09801..0d07706 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
@@ -19,13 +19,21 @@
package org.apache.cayenne.modeler.dialog.db;
-import org.apache.cayenne.access.loader.DbLoaderConfiguration;
-import org.apache.cayenne.access.loader.filters.FiltersConfig;
-import org.apache.cayenne.access.loader.filters.PatternFilter;
-import org.apache.cayenne.access.loader.filters.TableFilter;
import org.apache.cayenne.configuration.DataChannelDescriptor;
import org.apache.cayenne.configuration.DataNodeDescriptor;
import org.apache.cayenne.dba.JdbcAdapter;
+import org.apache.cayenne.dbsync.merge.AbstractToDbToken;
+import org.apache.cayenne.dbsync.merge.DbMerger;
+import org.apache.cayenne.dbsync.merge.MergeDirection;
+import org.apache.cayenne.dbsync.merge.MergerContext;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.ModelMergeDelegate;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.dbsync.reverse.DbLoaderConfiguration;
+import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig;
+import org.apache.cayenne.dbsync.reverse.filters.PatternFilter;
+import org.apache.cayenne.dbsync.reverse.filters.TableFilter;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
@@ -35,12 +43,6 @@ import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.ObjRelationship;
import org.apache.cayenne.map.event.EntityEvent;
import org.apache.cayenne.map.event.MapEvent;
-import org.apache.cayenne.merge.AbstractToDbToken;
-import org.apache.cayenne.merge.DbMerger;
-import org.apache.cayenne.merge.MergeDirection;
-import org.apache.cayenne.merge.MergerContext;
-import org.apache.cayenne.merge.MergerToken;
-import org.apache.cayenne.merge.ModelMergeDelegate;
import org.apache.cayenne.modeler.ProjectController;
import org.apache.cayenne.modeler.dialog.ValidationResultBrowser;
import org.apache.cayenne.modeler.event.AttributeDisplayEvent;
@@ -79,11 +81,17 @@ public class MergerOptions extends CayenneController {
protected DbMerger merger;
protected MergerTokenSelectorController tokens;
protected String defaultSchema;
-
- public MergerOptions(ProjectController parent, String title,
- DBConnectionInfo connectionInfo, DataMap dataMap, String defaultSchema) {
+ private MergerTokenFactoryProvider mergerTokenFactoryProvider;
+
+ public MergerOptions(ProjectController parent,
+ String title,
+ DBConnectionInfo connectionInfo,
+ DataMap dataMap,
+ String defaultSchema,
+ MergerTokenFactoryProvider mergerTokenFactoryProvider) {
super(parent);
+ this.mergerTokenFactoryProvider = mergerTokenFactoryProvider;
this.dataMap = dataMap;
this.tokens = new MergerTokenSelectorController(parent);
this.view = new MergerOptionsView(tokens.getView());
@@ -124,20 +132,6 @@ public class MergerOptions extends CayenneController {
sqlBinding = builder.bindToTextArea(view.getSql(), "textForSQL");
- /*
- * optionBindings = new ObjectBinding[5]; optionBindings[0] =
- * builder.bindToStateChangeAndAction(view.getCreateFK(),
- * "generatorDefaults.createFK", "refreshSQLAction()"); optionBindings[1] =
- * builder.bindToStateChangeAndAction(view.getCreatePK(),
- * "generatorDefaults.createPK", "refreshSQLAction()"); optionBindings[2] =
- * builder.bindToStateChangeAndAction(view.getCreateTables(),
- * "generatorDefaults.createTables", "refreshSQLAction()"); optionBindings[3] =
- * builder.bindToStateChangeAndAction(view.getDropPK(),
- * "generatorDefaults.dropPK", "refreshSQLAction()"); optionBindings[4] =
- * builder.bindToStateChangeAndAction(view.getDropTables(),
- * "generatorDefaults.dropTables", "refreshSQLAction()");
- */
-
builder.bindToAction(view.getGenerateButton(), "generateSchemaAction()");
builder.bindToAction(view.getSaveSqlButton(), "storeSQLAction()");
builder.bindToAction(view.getCancelButton(), "closeAction()");
@@ -161,8 +155,11 @@ public class MergerOptions extends CayenneController {
protected void prepareMigrator() {
try {
adapter = (JdbcAdapter) connectionInfo.makeAdapter(getApplication().getClassLoadingService());
- tokens.setMergerFactory(adapter.mergerFactory());
- merger = new DbMerger(adapter.mergerFactory());
+
+ MergerTokenFactory mergerTokenFactory = mergerTokenFactoryProvider.get(adapter);
+
+ tokens.setMergerTokenFactory(mergerTokenFactory);
+ merger = new DbMerger(mergerTokenFactory);
DbLoaderConfiguration config = new DbLoaderConfiguration();
config.setFiltersConfig(FiltersConfig.create(null, defaultSchema, TableFilter.everything(), PatternFilter.INCLUDE_NOTHING));
@@ -173,8 +170,7 @@ public class MergerOptions extends CayenneController {
dataMap,
config);
tokens.setTokens(mergerTokens);
- }
- catch (Exception ex) {
+ } catch (Exception ex) {
reportError("Error loading adapter", ex);
}
}
@@ -451,15 +447,13 @@ public class MergerOptions extends CayenneController {
if (failures == null || !failures.hasFailures()) {
JOptionPane.showMessageDialog(getView(), "Migration Complete.");
- }
- else {
+ } else {
new ValidationResultBrowser(this).startupAction(
"Migration Complete",
"Migration finished. The following problem(s) were ignored.",
failures);
}
- }
- catch (Throwable th) {
+ } catch (Throwable th) {
reportError("Migration Error", th);
}
}
@@ -488,8 +482,7 @@ public class MergerOptions extends CayenneController {
pw.print(textForSQL);
pw.flush();
pw.close();
- }
- catch (IOException ex) {
+ } catch (IOException ex) {
reportError("Error Saving SQL", ex);
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenSelectorController.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenSelectorController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenSelectorController.java
index 35adce2..a5c6e96 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenSelectorController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenSelectorController.java
@@ -18,27 +18,25 @@
****************************************************************/
package org.apache.cayenne.modeler.dialog.db;
-import java.awt.Component;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import org.apache.cayenne.dbsync.merge.MergeDirection;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.modeler.Application;
+import org.apache.cayenne.modeler.util.CayenneController;
+import org.apache.cayenne.swing.BindingBuilder;
+import org.apache.cayenne.swing.ObjectBinding;
-import javax.swing.DefaultCellEditor;
-import javax.swing.JComboBox;
+import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
-
-import org.apache.cayenne.merge.MergeDirection;
-import org.apache.cayenne.merge.MergerFactory;
-import org.apache.cayenne.merge.MergerToken;
-import org.apache.cayenne.modeler.Application;
-import org.apache.cayenne.modeler.util.CayenneController;
-import org.apache.cayenne.swing.BindingBuilder;
-import org.apache.cayenne.swing.ObjectBinding;
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
public class MergerTokenSelectorController extends CayenneController {
@@ -49,7 +47,7 @@ public class MergerTokenSelectorController extends CayenneController {
protected int permanentlyExcludedCount;
protected Set<MergerToken> excludedTokens;
protected List<MergerToken> selectableTokensList;
- protected MergerFactory mergerFactory;
+ protected MergerTokenFactory mergerTokenFactory;
public MergerTokenSelectorController(CayenneController parent) {
super(parent);
@@ -59,8 +57,8 @@ public class MergerTokenSelectorController extends CayenneController {
initController();
}
- public void setMergerFactory(MergerFactory mergerFactory) {
- this.mergerFactory = mergerFactory;
+ public void setMergerTokenFactory(MergerTokenFactory mergerTokenFactory) {
+ this.mergerTokenFactory = mergerTokenFactory;
}
public void setTokens(List<MergerToken> tokens) {
@@ -197,7 +195,7 @@ public class MergerTokenSelectorController extends CayenneController {
return;
}
int i = selectableTokensList.indexOf(token);
- MergerToken reverse = token.createReverse(mergerFactory);
+ MergerToken reverse = token.createReverse(mergerTokenFactory);
selectableTokensList.set(i, reverse);
if (excludedTokens.remove(token)) {
excludedTokens.add(reverse);
@@ -228,7 +226,7 @@ public class MergerTokenSelectorController extends CayenneController {
for (int i = 0; i < selectableTokensList.size(); i++) {
MergerToken token = selectableTokensList.get(i);
- MergerToken reverse = token.createReverse(mergerFactory);
+ MergerToken reverse = token.createReverse(mergerTokenFactory);
selectableTokensList.set(i, reverse);
if (excludedTokens.remove(token)) {
excludedTokens.add(reverse);
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenTableModel.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenTableModel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenTableModel.java
index f69d43d..488b1e8 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenTableModel.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerTokenTableModel.java
@@ -18,12 +18,12 @@
****************************************************************/
package org.apache.cayenne.modeler.dialog.db;
-import java.util.List;
+import org.apache.cayenne.dbsync.merge.MergeDirection;
+import org.apache.cayenne.dbsync.merge.MergerToken;
import javax.swing.table.AbstractTableModel;
+import java.util.List;
-import org.apache.cayenne.merge.MergeDirection;
-import org.apache.cayenne.merge.MergerToken;
public class MergerTokenTableModel extends AbstractTableModel {
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ModelerDbImportAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ModelerDbImportAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ModelerDbImportAction.java
index 3be2ba3..b7e6ce2 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ModelerDbImportAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ModelerDbImportAction.java
@@ -23,6 +23,7 @@ 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.dbsync.merge.factory.MergerTokenFactoryProvider;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.MapLoader;
@@ -57,6 +58,9 @@ public class ModelerDbImportAction implements DbImportAction {
@Inject
private MapLoader mapLoader;
+ @Inject
+ private MergerTokenFactoryProvider mergerTokenFactoryProvider;
+
public ModelerDbImportAction(Log logger, DbLoaderHelper dbLoaderHelper) {
this.logger = logger;
this.dbLoaderHelper = dbLoaderHelper;
@@ -68,7 +72,7 @@ public class ModelerDbImportAction implements DbImportAction {
throw new IllegalStateException("Before using execute method you must set dbLoaderHelper");
}
- new DefaultDbImportAction(logger, projectSaver, dataSourceFactory, adapterFactory, mapLoader) {
+ new DefaultDbImportAction(logger, projectSaver, dataSourceFactory, adapterFactory, mapLoader, mergerTokenFactoryProvider) {
@Override
protected DataMap loadExistingDataMap(File dataMapFile) {
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ReverseEngineeringController.java
----------------------------------------------------------------------
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 b2ac550..e83a36a 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
@@ -18,14 +18,14 @@
****************************************************************/
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.dbsync.reverse.DbLoader;
+import org.apache.cayenne.dbsync.reverse.DbLoaderConfiguration;
+import org.apache.cayenne.dbsync.reverse.DefaultDbLoaderDelegate;
+import org.apache.cayenne.dbsync.reverse.FiltersConfigBuilder;
+import org.apache.cayenne.dbsync.reverse.filters.CatalogFilter;
+import org.apache.cayenne.dbsync.reverse.filters.SchemaFilter;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
@@ -49,9 +49,8 @@ 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 javax.swing.*;
+import java.awt.*;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Arrays;
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/EntitySyncController.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/EntitySyncController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/EntitySyncController.java
index 6e07559..2941159 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/EntitySyncController.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/EntitySyncController.java
@@ -19,19 +19,18 @@
package org.apache.cayenne.modeler.dialog.objentity;
-import java.awt.Component;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.Collection;
-import java.util.Collections;
-
+import org.apache.cayenne.dbsync.merge.EntityMergeSupport;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.map.naming.DefaultNameGenerator;
import org.apache.cayenne.map.naming.ObjectNameGenerator;
import org.apache.cayenne.modeler.util.CayenneController;
import org.apache.cayenne.modeler.util.NameGeneratorPreferences;
-import org.apache.cayenne.util.EntityMergeSupport;
+
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Collection;
+import java.util.Collections;
public class EntitySyncController extends CayenneController {
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMojo.java
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMojo.java b/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMojo.java
index 87a3156..ec990cc 100644
--- a/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMojo.java
+++ b/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMojo.java
@@ -19,7 +19,7 @@
package org.apache.cayenne.tools;
-import org.apache.cayenne.access.loader.NamePatternMatcher;
+import org.apache.cayenne.dbsync.reverse.NamePatternMatcher;
import org.apache.cayenne.gen.ClassGenerationAction;
import org.apache.cayenne.gen.ClientClassGenerationAction;
import org.apache.cayenne.map.DataMap;
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbGeneratorMojo.java
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbGeneratorMojo.java b/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbGeneratorMojo.java
index e15c65e..99a649f 100644
--- a/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbGeneratorMojo.java
+++ b/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbGeneratorMojo.java
@@ -19,13 +19,11 @@
package org.apache.cayenne.tools;
-import java.io.File;
-import java.sql.Driver;
-
import org.apache.cayenne.access.DbGenerator;
import org.apache.cayenne.datasource.DriverDataSource;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.JdbcAdapter;
+import org.apache.cayenne.dbsync.CayenneDbSyncModule;
import org.apache.cayenne.di.AdhocObjectFactory;
import org.apache.cayenne.di.DIBootstrap;
import org.apache.cayenne.di.Injector;
@@ -40,6 +38,9 @@ import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.xml.sax.InputSource;
+import java.io.File;
+import java.sql.Driver;
+
/**
* Maven mojo to perform class generation from data map. This class is a Maven
* adapter to DefaultClassGenerator class.
@@ -141,7 +142,7 @@ public class DbGeneratorMojo extends AbstractMojo {
public void execute() throws MojoExecutionException, MojoFailureException {
Log logger = new MavenLogger(this);
- Injector injector = DIBootstrap.createInjector(new ToolsModule(logger));
+ Injector injector = DIBootstrap.createInjector(new CayenneDbSyncModule(), new ToolsModule(logger));
AdhocObjectFactory objectFactory = injector.getInstance(AdhocObjectFactory.class);
logger.info(String.format("connection settings - [driver: %s, url: %s, username: %s]", driver, url, username));
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/plugins/maven-cayenne-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java
----------------------------------------------------------------------
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 3e05c5f..7c8872b 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,19 +18,19 @@
****************************************************************/
package org.apache.cayenne.tools;
-import org.apache.cayenne.access.loader.filters.LegacyFilterConfigBridge;
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.net.MalformedURLException;
-import java.net.URL;
-
-import org.apache.cayenne.dbimport.*;
+import org.apache.cayenne.dbimport.Catalog;
+import org.apache.cayenne.dbimport.DefaultReverseEngineeringLoader;
+import org.apache.cayenne.dbimport.ReverseEngineering;
+import org.apache.cayenne.dbimport.Schema;
+import org.apache.cayenne.dbsync.CayenneDbSyncModule;
+import org.apache.cayenne.dbsync.reverse.FiltersConfigBuilder;
+import org.apache.cayenne.dbsync.reverse.filters.LegacyFilterConfigBridge;
import org.apache.cayenne.di.DIBootstrap;
import org.apache.cayenne.di.Injector;
import org.apache.cayenne.map.DataMap;
@@ -47,6 +47,9 @@ import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import javax.sql.DataSource;
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
/**
* Maven mojo to reverse engineer datamap from DB.
@@ -276,7 +279,7 @@ public class DbImporterMojo extends AbstractMojo {
File dataMapFile = config.getDataMapFile();
if (isReverseEngineeringDefined) {
- Injector injector = DIBootstrap.createInjector(new ToolsModule(logger), new DbImportModule());
+ Injector injector = DIBootstrap.createInjector(new CayenneDbSyncModule(), new ToolsModule(logger), new DbImportModule());
validateDbImportConfiguration(config, injector);
@@ -304,7 +307,7 @@ public class DbImporterMojo extends AbstractMojo {
DataMap dataMap = xmlDataMapLoader.load(resource);
if (dataMap.getReverseEngineering() != null) {
try {
- Injector injector = DIBootstrap.createInjector(new ToolsModule(logger), new DbImportModule());
+ Injector injector = DIBootstrap.createInjector(new CayenneDbSyncModule(), 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);
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java
----------------------------------------------------------------------
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 7061916..f76eb90 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
@@ -20,10 +20,10 @@ package org.apache.cayenne.tools;
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.dbsync.reverse.filters.FiltersConfig;
+import org.apache.cayenne.dbsync.reverse.filters.IncludeTableFilter;
+import org.apache.cayenne.dbsync.reverse.filters.PatternFilter;
+import org.apache.cayenne.dbsync.reverse.filters.TableFilter;
import org.apache.cayenne.tools.dbimport.DbImportConfiguration;
import org.apache.cayenne.dbimport.Schema;
import org.apache.maven.plugin.testing.AbstractMojoTestCase;
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index ba88917..3632bf2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -53,6 +53,7 @@
<module>cayenne-di</module>
<module>cayenne-server</module>
<module>cayenne-client</module>
+ <module>cayenne-dbsync</module>
<module>cayenne-tools</module>
<module>cayenne-project</module>
<module>cayenne-lifecycle</module>
[06/15] cayenne git commit: CAY-2116 Split schema synchronization
code in a separate module
Posted by aa...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseMergerFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseMergerFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseMergerFactory.java
deleted file mode 100644
index 9750aeb..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseMergerFactory.java
+++ /dev/null
@@ -1,144 +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.dba.openbase;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbJoin;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.merge.CreateTableToDb;
-import org.apache.cayenne.merge.DropRelationshipToDb;
-import org.apache.cayenne.merge.MergerFactory;
-import org.apache.cayenne.merge.MergerToken;
-import org.apache.cayenne.merge.SetAllowNullToDb;
-import org.apache.cayenne.merge.SetColumnTypeToDb;
-import org.apache.cayenne.merge.SetNotNullToDb;
-
-public class OpenBaseMergerFactory extends MergerFactory {
-
- @Override
- public MergerToken createCreateTableToDb(DbEntity entity) {
- return new CreateTableToDb(entity) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- List<String> sqls = new ArrayList<String>();
- // create table first as OpenBase adapter created primary key in its
- // getPkGenerator().createAutoPkStatements
- sqls.add(adapter.createTable(getEntity()));
- sqls.addAll(adapter.getPkGenerator().createAutoPkStatements(
- Collections.singletonList(getEntity())));
- return sqls;
- }
-
- };
- }
-
- @Override
- public MergerToken createDropRelationshipToDb(
- final DbEntity entity,
- final DbRelationship rel) {
- return new DropRelationshipToDb(entity, rel) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
-
-
- // FK_NAME form jdbc metadata seem to be wrong. It contain a column name
- // and not the 'relationshipName'
- // TODO: tell openbase developer mail list
-
- DbEntity source = getEntity();
- DbEntity dest = rel.getTargetEntity();
-
- // only use the first. See adapter
- // TODO: can we be sure this is the first and same as used by the adapter?
- DbJoin join = rel.getJoins().get(0);
-
- // see comment in adapter for why source and dest is switched around..
-
- return Collections.singletonList("delete from _SYS_RELATIONSHIP where "
- + " source_table = '" + dest.getFullyQualifiedName() + "'"
- + " and source_column = '" + join.getTargetName() + "'"
- + " and dest_table = '" + source.getFullyQualifiedName() + "'"
- + " and dest_column = '" + join.getSourceName() + "'");
- }
-
- };
- }
-
- @Override
- public MergerToken createSetColumnTypeToDb(
- final DbEntity entity,
- final DbAttribute columnOriginal,
- final DbAttribute columnNew) {
- return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- List<String> sqls = new ArrayList<String>();
-
- if (columnOriginal.getMaxLength() != columnNew.getMaxLength()) {
- sqls.add("ALTER TABLE "
- + entity.getFullyQualifiedName()
- + " COLUMN "
- + columnNew.getName()
- + " SET LENGTH "
- + columnNew.getMaxLength());
- }
-
- return sqls;
- }
-
- };
- }
-
- @Override
- public MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column) {
- return new SetNotNullToDb(entity, column) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
-
- return Collections.singletonList("ALTER TABLE " + getEntity().getFullyQualifiedName()
- + " COLUMN " + getColumn().getName() + " SET NOT NULL");
- }
-
- };
- }
-
- @Override
- public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
- return new SetAllowNullToDb(entity, column) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
-
- return Collections.singletonList("ALTER TABLE " + getEntity().getFullyQualifiedName()
- + " COLUMN " + getColumn().getName() + " SET NULL");
- }
-
- };
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleAdapter.java
index adfd6dd..668676f 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleAdapter.java
@@ -26,7 +26,11 @@ import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
import org.apache.cayenne.access.translator.select.QualifierTranslator;
import org.apache.cayenne.access.translator.select.QueryAssembler;
import org.apache.cayenne.access.translator.select.SelectTranslator;
-import org.apache.cayenne.access.types.*;
+import org.apache.cayenne.access.types.ByteType;
+import org.apache.cayenne.access.types.ExtendedType;
+import org.apache.cayenne.access.types.ExtendedTypeFactory;
+import org.apache.cayenne.access.types.ExtendedTypeMap;
+import org.apache.cayenne.access.types.ShortType;
import org.apache.cayenne.configuration.Constants;
import org.apache.cayenne.configuration.RuntimeProperties;
import org.apache.cayenne.dba.JdbcAdapter;
@@ -35,12 +39,20 @@ import org.apache.cayenne.di.Inject;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.merge.MergerFactory;
-import org.apache.cayenne.query.*;
+import org.apache.cayenne.query.BatchQuery;
+import org.apache.cayenne.query.InsertBatchQuery;
+import org.apache.cayenne.query.Query;
+import org.apache.cayenne.query.SQLAction;
+import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.query.UpdateBatchQuery;
import org.apache.cayenne.resource.ResourceLocator;
import java.lang.reflect.Field;
-import java.sql.*;
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -330,9 +342,4 @@ public class OracleAdapter extends JdbcAdapter {
return st.wasNull() ? null : i == 0 ? Boolean.FALSE : Boolean.TRUE;
}
}
-
- @Override
- public MergerFactory mergerFactory() {
- return new OracleMergerFactory();
- }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleMergerFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleMergerFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleMergerFactory.java
deleted file mode 100644
index 7b52185..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleMergerFactory.java
+++ /dev/null
@@ -1,112 +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.dba.oracle;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.merge.AddColumnToDb;
-import org.apache.cayenne.merge.MergerFactory;
-import org.apache.cayenne.merge.MergerToken;
-import org.apache.cayenne.merge.SetAllowNullToDb;
-import org.apache.cayenne.merge.SetColumnTypeToDb;
-import org.apache.cayenne.merge.SetNotNullToDb;
-
-
-public class OracleMergerFactory extends MergerFactory {
-
- @Override
- public MergerToken createAddColumnToDb(final DbEntity entity, final DbAttribute column) {
- return new AddColumnToDb(entity, column) {
-
- @Override
- protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(entity));
- sqlBuffer.append(" ADD ");
- sqlBuffer.append(context.quotedName(column));
- sqlBuffer.append(" ");
- }
- };
- }
-
- @Override
- public MergerToken createSetColumnTypeToDb(
- final DbEntity entity,
- DbAttribute columnOriginal,
- final DbAttribute columnNew) {
-
- return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
-
- @Override
- protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(entity));
- sqlBuffer.append(" MODIFY ");
- sqlBuffer.append(context.quotedName(columnNew));
- sqlBuffer.append(" ");
- }
- };
- }
-
- @Override
- public MergerToken createSetAllowNullToDb(DbEntity entity, final DbAttribute column) {
- return new SetAllowNullToDb(entity, column) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- StringBuffer sqlBuffer = new StringBuffer();
-
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity()));
- sqlBuffer.append(" MODIFY ");
-
- adapter.createTableAppendColumn(sqlBuffer, column);
-
- return Collections.singletonList(sqlBuffer.toString());
- }
-
- };
- }
-
- @Override
- public MergerToken createSetNotNullToDb(DbEntity entity, final DbAttribute column) {
-
- return new SetNotNullToDb(entity, column) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- StringBuffer sqlBuffer = new StringBuffer();
-
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity()));
- sqlBuffer.append(" MODIFY ");
-
- adapter.createTableAppendColumn(sqlBuffer, column);
-
- return Collections.singletonList(sqlBuffer.toString());
- }
-
- };
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java
index 7df4354..98c9944 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java
@@ -39,7 +39,6 @@ import org.apache.cayenne.di.Inject;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.merge.MergerFactory;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SelectQuery;
@@ -272,11 +271,6 @@ public class PostgresAdapter extends JdbcAdapter {
}
@Override
- public MergerFactory mergerFactory() {
- return new PostgresMergerFactory();
- }
-
- @Override
public boolean supportsCatalogsOnReverseEngineering() {
return false;
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresMergerFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresMergerFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresMergerFactory.java
deleted file mode 100644
index 6e5db58..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresMergerFactory.java
+++ /dev/null
@@ -1,50 +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.dba.postgres;
-
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.merge.MergerFactory;
-import org.apache.cayenne.merge.MergerToken;
-import org.apache.cayenne.merge.SetColumnTypeToDb;
-
-public class PostgresMergerFactory extends MergerFactory {
-
- @Override
- public MergerToken createSetColumnTypeToDb(
- final DbEntity entity,
- DbAttribute columnOriginal,
- final DbAttribute columnNew) {
-
- return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
-
- @Override
- protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy quotingStrategy) {
- // http://www.postgresql.org/docs/8.2/static/sql-altertable.html
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(quotingStrategy.quotedFullyQualifiedName(entity));
- sqlBuffer.append(" ALTER ");
- sqlBuffer.append(quotingStrategy.quotedName(columnNew));
- sqlBuffer.append(" TYPE ");
- }
- };
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java
index 537296d..3faec45 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java
@@ -31,7 +31,6 @@ import org.apache.cayenne.dba.sybase.SybaseAdapter;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.merge.MergerFactory;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SelectQuery;
@@ -138,9 +137,4 @@ public class SQLServerAdapter extends SybaseAdapter {
}
}
- @Override
- public MergerFactory mergerFactory() {
- return new SQLServerMergerFactory();
- }
-
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerMergerFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerMergerFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerMergerFactory.java
deleted file mode 100644
index 202f09c..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerMergerFactory.java
+++ /dev/null
@@ -1,114 +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.dba.sqlserver;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.merge.AddColumnToDb;
-import org.apache.cayenne.merge.MergerFactory;
-import org.apache.cayenne.merge.MergerToken;
-import org.apache.cayenne.merge.SetAllowNullToDb;
-import org.apache.cayenne.merge.SetColumnTypeToDb;
-import org.apache.cayenne.merge.SetNotNullToDb;
-
-public class SQLServerMergerFactory extends MergerFactory {
-
- @Override
- public MergerToken createSetColumnTypeToDb(
- final DbEntity entity,
- DbAttribute columnOriginal,
- final DbAttribute columnNew) {
-
- return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
-
- @Override
- protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
- // http://msdn2.microsoft.com/en-us/library/ms190273.aspx
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(entity));
- sqlBuffer.append(" ALTER COLUMN ");
- sqlBuffer.append(context.quotedName(columnNew));
- sqlBuffer.append(" ");
- }
- };
- }
-
- @Override
- public MergerToken createAddColumnToDb(final DbEntity entity, final DbAttribute column) {
- return new AddColumnToDb(entity, column) {
-
- @Override
- protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
- // http://msdn2.microsoft.com/en-us/library/ms190273.aspx
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(entity));
- sqlBuffer.append(" ADD ");
- sqlBuffer.append(context.quotedName(column));
- sqlBuffer.append(" ");
- }
- };
- }
-
- @Override
- public MergerToken createSetAllowNullToDb(DbEntity entity, final DbAttribute column) {
- return new SetAllowNullToDb(entity, column) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- StringBuffer sqlBuffer = new StringBuffer();
-
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity()));
- sqlBuffer.append(" ALTER COLUMN ");
-
- adapter.createTableAppendColumn(sqlBuffer, column);
-
- return Collections.singletonList(sqlBuffer.toString());
- }
-
- };
- }
-
- @Override
- public MergerToken createSetNotNullToDb(DbEntity entity, final DbAttribute column) {
-
- return new SetNotNullToDb(entity, column) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- StringBuffer sqlBuffer = new StringBuffer();
-
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity()));
- sqlBuffer.append(" ALTER COLUMN ");
-
- adapter.createTableAppendColumn(sqlBuffer, column);
-
- return Collections.singletonList(sqlBuffer.toString());
- }
-
- };
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseAdapter.java
index 2b0ca86..073290a 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseAdapter.java
@@ -21,7 +21,13 @@ package org.apache.cayenne.dba.sybase;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
-import org.apache.cayenne.access.types.*;
+import org.apache.cayenne.access.types.ByteArrayType;
+import org.apache.cayenne.access.types.ByteType;
+import org.apache.cayenne.access.types.CharType;
+import org.apache.cayenne.access.types.ExtendedType;
+import org.apache.cayenne.access.types.ExtendedTypeFactory;
+import org.apache.cayenne.access.types.ExtendedTypeMap;
+import org.apache.cayenne.access.types.ShortType;
import org.apache.cayenne.configuration.Constants;
import org.apache.cayenne.configuration.RuntimeProperties;
import org.apache.cayenne.dba.DefaultQuotingStrategy;
@@ -29,7 +35,6 @@ import org.apache.cayenne.dba.JdbcAdapter;
import org.apache.cayenne.dba.PkGenerator;
import org.apache.cayenne.dba.QuotingStrategy;
import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.merge.MergerFactory;
import org.apache.cayenne.resource.ResourceLocator;
import java.sql.PreparedStatement;
@@ -122,9 +127,4 @@ public class SybaseAdapter extends JdbcAdapter {
super.bindParameter(statement, binding);
}
}
-
- @Override
- public MergerFactory mergerFactory() {
- return new SybaseMergerFactory();
- }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseMergerFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseMergerFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseMergerFactory.java
deleted file mode 100644
index b3d204f..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sybase/SybaseMergerFactory.java
+++ /dev/null
@@ -1,167 +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.dba.sybase;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.merge.AddColumnToDb;
-import org.apache.cayenne.merge.DropColumnToDb;
-import org.apache.cayenne.merge.MergerFactory;
-import org.apache.cayenne.merge.MergerToken;
-import org.apache.cayenne.merge.SetAllowNullToDb;
-import org.apache.cayenne.merge.SetColumnTypeToDb;
-import org.apache.cayenne.merge.SetNotNullToDb;
-
-/**
- * @since 3.0
- */
-public class SybaseMergerFactory extends MergerFactory {
-
- /**
- * @since 3.0
- */
- @Override
- public MergerToken createAddColumnToDb(DbEntity entity, final DbAttribute column) {
- return new AddColumnToDb(entity, column) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
-
- StringBuffer sqlBuffer = new StringBuffer();
- QuotingStrategy context = adapter.getQuotingStrategy();
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
- sqlBuffer.append(" ADD ");
- boolean magnatory = column.isMandatory();
- column.setMandatory(false);
- adapter.createTableAppendColumn(sqlBuffer, column);
- if(magnatory){
- column.setMandatory(magnatory);
- }
- return Collections.singletonList(sqlBuffer.toString());
- }
-
- };
- }
-
- /**
- * @since 3.0
- */
- @Override
- public MergerToken createDropColumnToDb(DbEntity entity, DbAttribute column) {
- return new DropColumnToDb(entity, column) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- StringBuilder sqlBuffer = new StringBuilder();
- QuotingStrategy context = adapter.getQuotingStrategy();
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
- sqlBuffer.append(" DROP ");
- sqlBuffer.append(context.quotedName(getColumn()));
-
- return Collections.singletonList(sqlBuffer.toString());
- }
-
- };
- }
-
- /**
- * @since 3.0
- */
- @Override
- public MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column) {
- return new SetNotNullToDb(entity, column) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
-
- StringBuffer sqlBuffer = createStringQuery(
- adapter,
- getEntity(),
- getColumn());
-
- return Collections.singletonList(sqlBuffer.toString());
- }
-
- };
- }
-
- /**
- * @since 3.0
- */
- @Override
- public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
- return new SetAllowNullToDb(entity, column) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- StringBuffer sqlBuffer = createStringQuery(
- adapter,
- getEntity(),
- getColumn());
- return Collections.singletonList(sqlBuffer.toString());
- }
- };
- }
-
- /**
- * @since 3.0
- */
- @Override
- public MergerToken createSetColumnTypeToDb(
- final DbEntity entity,
- DbAttribute columnOriginal,
- final DbAttribute columnNew) {
-
- return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
-
- @Override
- protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
- // http://dev.mysql.com/tech-resources/articles/mysql-cluster-50.html
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(entity));
- sqlBuffer.append(" MODIFY ");
- sqlBuffer.append(context.quotedName(columnNew));
- sqlBuffer.append(" ");
- }
-
- };
- }
-
- private static StringBuffer createStringQuery(
- DbAdapter adapter,
- DbEntity entity,
- DbAttribute column) {
- StringBuffer sqlBuffer = new StringBuffer();
- QuotingStrategy context = adapter.getQuotingStrategy();
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(entity));
- sqlBuffer.append(" MODIFY ");
- adapter.createTableAppendColumn(sqlBuffer, column);
-
- return sqlBuffer;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dbimport/FiltersConfigBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/FiltersConfigBuilder.java b/cayenne-server/src/main/java/org/apache/cayenne/dbimport/FiltersConfigBuilder.java
deleted file mode 100644
index d7c4d9d..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dbimport/FiltersConfigBuilder.java
+++ /dev/null
@@ -1,383 +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
- * <p/>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p/>
- * 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.access.loader.filters.LegacyFilterConfigBridge;
-import org.apache.cayenne.access.loader.filters.CatalogFilter;
-import org.apache.cayenne.access.loader.filters.IncludeTableFilter;
-import org.apache.cayenne.access.loader.filters.SchemaFilter;
-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 java.util.*;
-import java.util.regex.Pattern;
-
-import static org.apache.commons.lang.StringUtils.isBlank;
-
-/**
- * @since 4.0.
- */
-public final class FiltersConfigBuilder {
-
- private final ReverseEngineering engineering;
-
- public FiltersConfigBuilder(ReverseEngineering engineering) {
- this.engineering = engineering;
- }
-
- public FiltersConfig filtersConfig() {
- compact();
-
- return new FiltersConfig(transformCatalogs(engineering.getCatalogs()));
- }
-
- private CatalogFilter[] transformCatalogs(Collection<Catalog> catalogs) {
- CatalogFilter[] catalogFilters = new CatalogFilter[catalogs.size()];
- int i = 0;
- for (Catalog catalog : catalogs) {
- catalogFilters[i] = new CatalogFilter(catalog.getName(), transformSchemas(catalog.getSchemas()));
- i++;
- }
-
- return catalogFilters;
- }
-
- private SchemaFilter[] transformSchemas(Collection<Schema> schemas) {
- SchemaFilter[] schemaFilters = new SchemaFilter[schemas.size()];
- int i = 0;
- for (Schema schema : schemas) {
- schemaFilters[i] = new SchemaFilter(schema.getName(),
- new TableFilter(transformIncludeTable(schema.getIncludeTables()),
- transformExcludeTable(schema.getExcludeTables())),
- transform(schema.getIncludeProcedures(), schema.getExcludeProcedures()));
- i++;
- }
-
- return schemaFilters;
- }
-
- private SortedSet<Pattern> transformExcludeTable(Collection<ExcludeTable> excludeTables) {
- SortedSet<Pattern> res = new TreeSet<Pattern>(PatternFilter.PATTERN_COMPARATOR);
- for (ExcludeTable exclude : excludeTables) {
- res.add(PatternFilter.pattern(exclude.getPattern()));
- }
- return res;
- }
-
- private SortedSet<IncludeTableFilter> transformIncludeTable(Collection<IncludeTable> includeTables) {
- SortedSet<IncludeTableFilter> includeTableFilters = new TreeSet<IncludeTableFilter>();
- for (IncludeTable includeTable : includeTables) {
- includeTableFilters.add(new IncludeTableFilter(includeTable.getPattern(),
- transform(includeTable.getIncludeColumns(), includeTable.getExcludeColumns())));
- }
-
- return includeTableFilters;
- }
-
- private PatternFilter transform(Collection<? extends PatternParam> include,
- Collection<? extends PatternParam> exclude) {
- PatternFilter filter = new PatternFilter();
-
- for (PatternParam patternParam : include) {
- filter.include(patternParam.getPattern());
- }
-
- for (PatternParam patternParam : exclude) {
- filter.exclude(patternParam.getPattern());
- }
-
- return filter;
-
- }
-
- /**
- * Goal of this method transform ReverseEngineering config into more regular form
- * From
- * ReverseEngineering
- * Catalog
- * Schema
- * IncludeTable
- * IncludeColumn
- * ExcludeColumn
- * ExcludeTable
- * IncludeProcedures
- * ExcludeProcedures
- * IncludeColumn
- * ExcludeColumn
- * IncludeTable
- * IncludeColumn
- * ExcludeColumn
- * ExcludeTable
- * IncludeProcedures
- * ExcludeProcedures
- * IncludeColumn
- * ExcludeColumn
- * Schema
- * IncludeTable
- * IncludeColumn
- * ExcludeColumn
- * ExcludeTable
- * IncludeProcedures
- * ExcludeProcedures
- * IncludeColumn
- * ExcludeColumn
- * IncludeTable
- * IncludeColumn
- * ExcludeColumn
- * ExcludeTable
- * IncludeProcedures
- * ExcludeProcedures
- * IncludeColumn
- * ExcludeColumn
- *
- * Into
- * ReverseEngineering
- * Catalog
- * Schema
- * IncludeTable
- * IncludeColumn
- * ExcludeColumn
- * ExcludeTable
- * IncludeProcedures
- * ExcludeProcedures
- *
- *
- * */
- public void compact() {
- addEmptyElements();
-
- compactColumnFilters();
- compactTableFilter();
- compactProcedureFilter();
- compactSchemas();
- }
-
- private void compactSchemas() {
- for (Catalog catalog : engineering.getCatalogs()) {
- catalog.getSchemas().addAll(engineering.getSchemas());
- }
- engineering.setSchemas(null);
- }
-
- private void compactProcedureFilter() {
- Collection<IncludeProcedure> engIncludeProcedures = engineering.getIncludeProcedures();
- Collection<ExcludeProcedure> engExcludeProcedures = engineering.getExcludeProcedures();
-
- engineering.setIncludeProcedures(null);
- engineering.setExcludeProcedures(null);
-
- for (Catalog catalog : engineering.getCatalogs()) {
- Collection<IncludeProcedure> catalogIncludeProcedures = catalog.getIncludeProcedures();
- Collection<ExcludeProcedure> catalogExcludeProcedures = catalog.getExcludeProcedures();
-
- catalog.setIncludeProcedures(null);
- catalog.setExcludeProcedures(null);
-
- for (Schema schema : catalog.getSchemas()) {
- if (engIncludeProcedures != null) {
- schema.getIncludeProcedures().addAll(engIncludeProcedures);
- schema.getIncludeProcedures().addAll(catalogIncludeProcedures);
- }
- if (engExcludeProcedures != null) {
- schema.getExcludeProcedures().addAll(engExcludeProcedures);
- schema.getExcludeProcedures().addAll(catalogExcludeProcedures);
- }
- }
- }
-
- for (Schema schema : engineering.getSchemas()) {
- schema.getIncludeProcedures().addAll(engIncludeProcedures);
- schema.getExcludeProcedures().addAll(engExcludeProcedures);
- }
- }
-
- private void compactTableFilter() {
- Collection<IncludeTable> engIncludeTables = engineering.getIncludeTables();
- Collection<ExcludeTable> engExcludeTables = engineering.getExcludeTables();
-
- engineering.setIncludeTables(null);
- engineering.setExcludeTables(null);
-
- for (Catalog catalog : engineering.getCatalogs()) {
- Collection<IncludeTable> catalogIncludeTables = catalog.getIncludeTables();
- Collection<ExcludeTable> catalogExcludeTables = catalog.getExcludeTables();
-
- catalog.setIncludeTables(null);
- catalog.setExcludeTables(null);
-
- for (Schema schema : catalog.getSchemas()) {
- if (engIncludeTables != null) {
- schema.getIncludeTables().addAll(engIncludeTables);
- schema.getIncludeTables().addAll(catalogIncludeTables);
- }
- if (engExcludeTables != null) {
- schema.getExcludeTables().addAll(engExcludeTables);
- schema.getExcludeTables().addAll(catalogExcludeTables);
- }
- }
- }
-
- for (Schema schema : engineering.getSchemas()) {
- schema.getIncludeTables().addAll(engIncludeTables);
- schema.getExcludeTables().addAll(engExcludeTables);
- }
- }
-
- private void compactColumnFilters() {
- Collection<IncludeColumn> engIncludeColumns = engineering.getIncludeColumns();
- Collection<ExcludeColumn> engExcludeColumns = engineering.getExcludeColumns();
-
- engineering.setIncludeColumns(null);
- engineering.setExcludeColumns(null);
-
- for (Catalog catalog : engineering.getCatalogs()) {
- Collection<IncludeColumn> catalogIncludeColumns = catalog.getIncludeColumns();
- Collection<ExcludeColumn> catalogExcludeColumns = catalog.getExcludeColumns();
-
- catalog.setIncludeColumns(null);
- catalog.setExcludeColumns(null);
-
- for (Schema schema : catalog.getSchemas()) {
- Collection<IncludeColumn> schemaIncludeColumns = schema.getIncludeColumns();
- Collection<ExcludeColumn> schemaExcludeColumns = schema.getExcludeColumns();
-
- schema.setIncludeColumns(null);
- schema.setExcludeColumns(null);
-
- 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.getExcludeColumns().addAll(engExcludeColumns);
- includeTable.getExcludeColumns().addAll(catalogExcludeColumns);
- }
- }
- }
-
- for (Schema schema : engineering.getSchemas()) {
- Collection<IncludeColumn> schemaIncludeColumns = schema.getIncludeColumns();
- Collection<ExcludeColumn> schemaExcludeColumns = schema.getExcludeColumns();
-
- schema.setIncludeColumns(null);
- schema.setExcludeColumns(null);
-
- for (IncludeTable includeTable : schema.getIncludeTables()) {
- includeTable.getIncludeColumns().addAll(engIncludeColumns);
- includeTable.getIncludeColumns().addAll(schemaIncludeColumns);
-
- includeTable.getExcludeColumns().addAll(engExcludeColumns);
- includeTable.getExcludeColumns().addAll(schemaExcludeColumns);
- }
- }
-
- if (engineering.getIncludeTables() != null) {
- for (IncludeTable includeTable : engineering.getIncludeTables()) {
- includeTable.getIncludeColumns().addAll(engIncludeColumns);
- includeTable.getExcludeColumns().addAll(engExcludeColumns);
- }
- }
- }
-
- private void addEmptyElements() {
- if (engineering.getCatalogs().isEmpty()) {
- engineering.addCatalog(new Catalog());
- }
-
- for (Catalog catalog : engineering.getCatalogs()) {
- if (catalog.getSchemas().isEmpty()
- && engineering.getSchemas().isEmpty()) {
- catalog.addSchema(new Schema());
- }
-
- for (Schema schema : catalog.getSchemas()) {
- if (schema.getIncludeTables().isEmpty()
- && catalog.getIncludeTables().isEmpty()
- && engineering.getIncludeTables().isEmpty()) {
-
- schema.addIncludeTable(new IncludeTable());
- }
- }
- }
-
- if (engineering.getSchemas() == null) {
- engineering.setSchemas(new LinkedList<Schema>());
- }
-
- for (Schema schema : engineering.getSchemas()) {
- if (schema.getIncludeTables().isEmpty()
- && engineering.getIncludeTables().isEmpty()) {
-
- schema.addIncludeTable(new IncludeTable());
- }
- }
- }
-
- public FiltersConfigBuilder add(LegacyFilterConfigBridge build) {
- if (!isBlank(build.catalog())) {
- engineering.addCatalog(new Catalog(build.catalog()));
- }
-
- if (!isBlank(build.schema())) {
- engineering.addSchema(new Schema(build.schema()));
- }
-
- if (!isBlank(build.getIncludeTableFilters())) {
- engineering.addIncludeTable(new IncludeTable(build.getIncludeTableFilters()));
- }
- if (!isBlank(build.getExcludeTableFilters())) {
- engineering.addExcludeTable(new ExcludeTable(build.getExcludeTableFilters()));
- }
-
- if (!isBlank(build.getIncludeColumnFilters())) {
- engineering.addIncludeColumn(new IncludeColumn(build.getIncludeColumnFilters()));
- }
- if (!isBlank(build.getExcludeColumnFilters())) {
- engineering.addExcludeColumn(new ExcludeColumn(build.getExcludeColumnFilters()));
- }
-
- if (build.isLoadProcedures()) {
- if (!isBlank(build.getIncludeProceduresFilters())) {
- engineering.addIncludeProcedure(new IncludeProcedure(build.getIncludeProceduresFilters()));
- }
- if (!isBlank(build.getExcludeProceduresFilters())) {
- engineering.addExcludeProcedure(new ExcludeProcedure(build.getExcludeProceduresFilters()));
- }
- }
-
- return this;
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/AbstractToDbToken.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/AbstractToDbToken.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/AbstractToDbToken.java
deleted file mode 100644
index 7430ba3..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/AbstractToDbToken.java
+++ /dev/null
@@ -1,126 +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.merge;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.log.JdbcEventLogger;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.validation.SimpleValidationFailure;
-
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.List;
-
-/**
- * Common abstract superclass for all {@link MergerToken}s going from the model
- * to the database.
- */
-public abstract class AbstractToDbToken implements MergerToken, Comparable<MergerToken> {
-
- private final String tokenName;
-
- protected AbstractToDbToken(String tokenName) {
- this.tokenName = tokenName;
- }
-
- @Override
- public final String getTokenName() {
- return tokenName;
- }
-
- @Override
- public final MergeDirection getDirection() {
- return MergeDirection.TO_DB;
- }
-
- @Override
- public void execute(MergerContext mergerContext) {
- for (String sql : createSql(mergerContext.getDataNode().getAdapter())) {
- executeSql(mergerContext, sql);
- }
- }
-
- protected void executeSql(MergerContext mergerContext, String sql) {
- JdbcEventLogger logger = mergerContext.getDataNode().getJdbcEventLogger();
- logger.log(sql);
-
- try (Connection conn = mergerContext.getDataNode().getDataSource().getConnection();) {
-
- try (Statement st = conn.createStatement();) {
- st.execute(sql);
- }
- } catch (SQLException e) {
- mergerContext.getValidationResult().addFailure(new SimpleValidationFailure(sql, e.getMessage()));
- logger.logQueryError(e);
- }
- }
-
- @Override
- public String toString() {
- return getTokenName() + ' ' + getTokenValue() + ' ' + getDirection();
- }
-
- public abstract List<String> createSql(DbAdapter adapter);
-
- abstract static class Entity extends AbstractToDbToken {
-
- private DbEntity entity;
-
- public Entity(String tokenName, DbEntity entity) {
- super(tokenName);
- this.entity = entity;
- }
-
- public DbEntity getEntity() {
- return entity;
- }
-
- public String getTokenValue() {
- return getEntity().getName();
- }
-
- public int compareTo(MergerToken o) {
- // default order as tokens are created
- return 0;
- }
-
- }
-
- abstract static class EntityAndColumn extends Entity {
-
- private DbAttribute column;
-
- public EntityAndColumn(String tokenName, DbEntity entity, DbAttribute column) {
- super(tokenName, entity);
- this.column = column;
- }
-
- public DbAttribute getColumn() {
- return column;
- }
-
- @Override
- public String getTokenValue() {
- return getEntity().getName() + "." + getColumn().getName();
- }
-
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/AbstractToModelToken.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/AbstractToModelToken.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/AbstractToModelToken.java
deleted file mode 100644
index 49b680b..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/AbstractToModelToken.java
+++ /dev/null
@@ -1,122 +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.merge;
-
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.map.ObjRelationship;
-
-/**
- * Common abstract superclass for all {@link MergerToken}s going from the database to the
- * model.
- *
- */
-public abstract class AbstractToModelToken implements MergerToken {
-
- private final String tokenName;
-
- protected AbstractToModelToken(String tokenName) {
- this.tokenName = tokenName;
- }
-
- @Override
- public final String getTokenName() {
- return tokenName;
- }
-
- public final MergeDirection getDirection() {
- return MergeDirection.TO_MODEL;
- }
-
- protected static void remove(ModelMergeDelegate mergerContext, DbRelationship rel, boolean reverse) {
- if (rel == null) {
- return;
- }
- if (reverse) {
- remove(mergerContext, rel.getReverseRelationship(), false);
- }
-
- DbEntity dbEntity = rel.getSourceEntity();
- for (ObjEntity objEntity : dbEntity.mappedObjEntities()) {
- remove(mergerContext, objEntity.getRelationshipForDbRelationship(rel), true);
- }
-
- rel.getSourceEntity().removeRelationship(rel.getName());
- mergerContext.dbRelationshipRemoved(rel);
- }
-
- protected static void remove(ModelMergeDelegate mergerContext, ObjRelationship rel, boolean reverse) {
- if (rel == null) {
- return;
- }
- if (reverse) {
- remove(mergerContext, rel.getReverseRelationship(), false);
- }
- rel.getSourceEntity().removeRelationship(rel.getName());
- mergerContext.objRelationshipRemoved(rel);
- }
-
- @Override
- public String toString() {
- return getTokenName() + ' ' + getTokenValue() + ' ' + getDirection();
- }
-
- abstract static class Entity extends AbstractToModelToken {
-
- private final DbEntity entity;
-
- protected Entity(String tokenName, DbEntity entity) {
- super(tokenName);
- this.entity = entity;
- }
-
- public DbEntity getEntity() {
- return entity;
- }
-
- public String getTokenValue() {
- return getEntity().getName();
- }
-
- }
-
- abstract static class EntityAndColumn extends Entity {
-
- private final DbAttribute column;
-
- protected EntityAndColumn(String tokenName, DbEntity entity, DbAttribute column) {
- super(tokenName, entity);
- this.column = column;
- }
-
- public DbAttribute getColumn() {
- return column;
- }
-
- @Override
- public String getTokenValue() {
- return getEntity().getName() + "." + getColumn().getName();
- }
-
- }
-
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToDb.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToDb.java
deleted file mode 100644
index 77b7486..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToDb.java
+++ /dev/null
@@ -1,64 +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.merge;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.JdbcAdapter;
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-
-public class AddColumnToDb extends AbstractToDbToken.EntityAndColumn {
-
- public AddColumnToDb(DbEntity entity, DbAttribute column) {
- super("Add Column", entity, column);
- }
-
- /**
- * append the part of the token before the actual column data type
- */
- protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
-
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
- sqlBuffer.append(" ADD COLUMN ");
- sqlBuffer.append(context.quotedName(getColumn()));
- sqlBuffer.append(" ");
- }
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- StringBuffer sqlBuffer = new StringBuffer();
- QuotingStrategy context = adapter.getQuotingStrategy();
- appendPrefix(sqlBuffer, context);
-
- sqlBuffer.append(JdbcAdapter.getType(adapter, getColumn()));
- sqlBuffer.append(JdbcAdapter.sizeAndPrecision(adapter, getColumn()));
-
- return Collections.singletonList(sqlBuffer.toString());
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return factory.createDropColumnToModel(getEntity(), getColumn());
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToModel.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToModel.java
deleted file mode 100644
index 9e96928..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToModel.java
+++ /dev/null
@@ -1,55 +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.merge;
-
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.util.EntityMergeSupport;
-
-/**
- * A {@link MergerToken} to add a {@link DbAttribute} to a {@link DbEntity}. The
- * {@link EntityMergeSupport} will be used to update the mapped {@link ObjEntity}
- *
- */
-public class AddColumnToModel extends AbstractToModelToken.EntityAndColumn {
-
- public AddColumnToModel(DbEntity entity, DbAttribute column) {
- super("Add Column", entity, column);
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return factory.createDropColumnToDb(getEntity(), getColumn());
- }
-
- public void execute(MergerContext mergerContext) {
- getEntity().addAttribute(getColumn());
-
- // TODO: use EntityMergeSupport from DbImportConfiguration... otherwise we are ignoring a bunch of
- // important settings
-
- EntityMergeSupport entityMergeSupport = new EntityMergeSupport(mergerContext.getDataMap());
- for(ObjEntity e : getEntity().mappedObjEntities()) {
- entityMergeSupport.synchronizeOnDbAttributeAdded(e, getColumn());
- }
-
- mergerContext.getModelMergeDelegate().dbAttributeAdded(getColumn());
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToDb.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToDb.java
deleted file mode 100644
index dbd65d8..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToDb.java
+++ /dev/null
@@ -1,86 +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.merge;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.cayenne.access.DbGenerator;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbRelationship;
-
-public class AddRelationshipToDb extends AbstractToDbToken.Entity {
-
- private DbRelationship rel;
-
- public AddRelationshipToDb(DbEntity entity, DbRelationship rel) {
- super("Add foreign key", entity);
- this.rel = rel;
- }
-
- /**
- * @see DbGenerator#createConstraintsQueries(org.apache.cayenne.map.DbEntity)
- */
- @Override
- public List<String> createSql(DbAdapter adapter) {
- // TODO: skip FK to a different DB
-
- if (this.shouldGenerateFkConstraint()) {
- String fksql = adapter.createFkConstraint(rel);
- if (fksql != null) {
- return Collections.singletonList(fksql);
- }
- }
- return Collections.emptyList();
- }
-
- public boolean shouldGenerateFkConstraint() {
- return !rel.isToMany()
- && rel.isToPK() // TODO it is not necessary primary key it can be unique index
- && !rel.isToDependentPK();
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return factory.createDropRelationshipToModel(getEntity(), rel);
- }
-
- @Override
- public String getTokenValue() {
- if (this.shouldGenerateFkConstraint()) {
- return rel.getSourceEntity().getName() + "->" + rel.getTargetEntityName();
- } else {
- return "Skip. No sql representation.";
- }
- }
-
- public DbRelationship getRelationship() {
- return rel;
- }
-
- @Override
- public int compareTo(MergerToken o) {
- // add all AddRelationshipToDb to the end.
- if (o instanceof AddRelationshipToDb) {
- return super.compareTo(o);
- }
- return 1;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToModel.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToModel.java
deleted file mode 100644
index 42d7329..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToModel.java
+++ /dev/null
@@ -1,95 +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.merge;
-
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbJoin;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.util.EntityMergeSupport;
-
-public class AddRelationshipToModel extends AbstractToModelToken.Entity {
-
- public static final String COMMA_SEPARATOR = ", ";
- public static final int COMMA_SEPARATOR_LENGTH = COMMA_SEPARATOR.length();
- private DbRelationship rel;
-
- public AddRelationshipToModel(DbEntity entity, DbRelationship rel) {
- super("Add Relationship", entity);
- this.rel = rel;
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return factory.createDropRelationshipToDb(getEntity(), rel);
- }
-
- public void execute(MergerContext mergerContext) {
- getEntity().addRelationship(rel);
- // TODO: add reverse relationship as well if it does not exist
-
- // TODO: use EntityMergeSupport from DbImportConfiguration... otherwise we are ignoring a bunch of
- // important settings
-
- EntityMergeSupport entityMergeSupport = new EntityMergeSupport(mergerContext.getDataMap());
- for(ObjEntity e : getEntity().mappedObjEntities()) {
- entityMergeSupport.synchronizeOnDbRelationshipAdded(e, rel);
- }
-
- mergerContext.getModelMergeDelegate().dbRelationshipAdded(rel);
- }
-
- @Override
- public String getTokenValue() {
- String attributes = "";
- if (rel.getJoins().size() == 1) {
- attributes = rel.getJoins().get(0).getTargetName();
- } else {
- for (DbJoin dbJoin : rel.getJoins()) {
- attributes += dbJoin.getTargetName() + COMMA_SEPARATOR;
- }
-
- attributes = "{" + attributes.substring(0, attributes.length() - COMMA_SEPARATOR_LENGTH) + "}";
- }
-
- return rel.getName() + " " + rel.getSourceEntity().getName() + "->" + rel.getTargetEntityName() + "." + attributes;
- }
-
-
- public static String getTokenValue(DbRelationship rel) {
- String attributes = "";
- if (rel.getJoins().size() == 1) {
- attributes = rel.getJoins().get(0).getTargetName();
- } else {
- for (DbJoin dbJoin : rel.getJoins()) {
- attributes += dbJoin.getTargetName() + COMMA_SEPARATOR;
- }
-
- attributes = "{" + attributes.substring(0, attributes.length() - COMMA_SEPARATOR_LENGTH) + "}";
- }
-
- return rel.getName() + " " + rel.getSourceEntity().getName() + "->" + rel.getTargetEntityName() + "." + attributes;
- }
-
- public DbRelationship getRelationship() {
- return rel;
- }
-
-
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToDb.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToDb.java
deleted file mode 100644
index 077ec74..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToDb.java
+++ /dev/null
@@ -1,65 +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.merge;
-
-import org.apache.cayenne.access.DataNode;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.validation.SimpleValidationFailure;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-public class CreateTableToDb extends AbstractToDbToken.Entity {
-
- public CreateTableToDb(DbEntity entity) {
- super("Create Table", entity);
- }
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- List<String> sqls = new ArrayList<String>();
- sqls.addAll(adapter.getPkGenerator().createAutoPkStatements(
- Collections.singletonList(getEntity())));
- sqls.add(adapter.createTable(getEntity()));
- return sqls;
- }
-
- @Override
- public void execute(MergerContext mergerContext) {
- try {
- DataNode node = mergerContext.getDataNode();
- DbAdapter adapter = node.getAdapter();
- adapter.getPkGenerator().createAutoPk(
- node,
- Collections.singletonList(getEntity()));
- executeSql(mergerContext, adapter.createTable(getEntity()));
- }
- catch (Exception e) {
- mergerContext.getValidationResult().addFailure(
- new SimpleValidationFailure(this, e.getMessage()));
- }
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return factory.createDropTableToModel(getEntity());
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToModel.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToModel.java
deleted file mode 100644
index cdd6009..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToModel.java
+++ /dev/null
@@ -1,102 +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.merge;
-
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.map.naming.NameConverter;
-import org.apache.cayenne.util.EntityMergeSupport;
-
-/**
- * A {@link MergerToken} to add a {@link DbEntity} to a {@link DataMap}
- *
- */
-public class CreateTableToModel extends AbstractToModelToken.Entity {
-
- /**
- * className if {@link ObjEntity} should be generated with a
- * special class name.
- * Setting this to <code>null</code>, because by default class name should be generated
- */
- private String objEntityClassName = null; //CayenneDataObject.class.getName();
-
- public CreateTableToModel(DbEntity entity) {
- super("Create Table", entity);
- }
-
- /**
- * Set the {@link ObjEntity} className if {@link ObjEntity} should be generated with a
- * special class name. Set to null if the {@link ObjEntity} should be created with a
- * name based on {@link DataMap#getDefaultPackage()} and {@link ObjEntity#getName()}
- * <p>
- * The default value is <code>null</code>
- */
- public void setObjEntityClassName(String n) {
- objEntityClassName = n;
- }
-
- public void execute(MergerContext mergerContext) {
- DataMap map = mergerContext.getDataMap();
- map.addDbEntity(getEntity());
-
- // create a ObjEntity
- String objEntityName = NameConverter.underscoredToJava(getEntity().getName(), true);
- // this loop will terminate even if no valid name is found
- // to prevent loader from looping forever (though such case is very unlikely)
- String baseName = objEntityName;
- for (int i = 1; i < 1000 && map.getObjEntity(objEntityName) != null; i++) {
- objEntityName = baseName + i;
- }
-
- ObjEntity objEntity = new ObjEntity(objEntityName);
- objEntity.setDbEntity(getEntity());
-
- // try to find a class name for the ObjEntity
- String className = objEntityClassName;
- if (className == null) {
- // we should generate a className based on the objEntityName
- className = map.getNameWithDefaultPackage(objEntityName);
- }
-
- objEntity.setClassName(className);
- objEntity.setSuperClassName(map.getDefaultSuperclass());
-
- if (map.isClientSupported()) {
- objEntity.setClientClassName(map.getNameWithDefaultClientPackage(objEntity.getName()));
- objEntity.setClientSuperClassName(map.getDefaultClientSuperclass());
- }
-
- map.addObjEntity(objEntity);
-
- // presumably there are no other ObjEntities pointing to this DbEntity, so syncing just this one...
-
- // TODO: use EntityMergeSupport from DbImportConfiguration... otherwise we are ignoring a bunch of
- // important settings
- new EntityMergeSupport(map).synchronizeWithDbEntity(objEntity);
-
- mergerContext.getModelMergeDelegate().dbEntityAdded(getEntity());
- mergerContext.getModelMergeDelegate().objEntityAdded(objEntity);
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return factory.createDropTableToDb(getEntity());
- }
-
-}
[13/15] cayenne git commit: CAY-2116 Split schema synchronization
code in a separate module
Posted by aa...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DefaultMergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DefaultMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DefaultMergerTokenFactory.java
new file mode 100644
index 0000000..c2f96ce
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DefaultMergerTokenFactory.java
@@ -0,0 +1,181 @@
+/*****************************************************************
+ * 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.dbsync.merge.factory;
+
+import org.apache.cayenne.dbsync.merge.AddColumnToDb;
+import org.apache.cayenne.dbsync.merge.AddColumnToModel;
+import org.apache.cayenne.dbsync.merge.AddRelationshipToDb;
+import org.apache.cayenne.dbsync.merge.AddRelationshipToModel;
+import org.apache.cayenne.dbsync.merge.CreateTableToDb;
+import org.apache.cayenne.dbsync.merge.CreateTableToModel;
+import org.apache.cayenne.dbsync.merge.DropColumnToDb;
+import org.apache.cayenne.dbsync.merge.DropColumnToModel;
+import org.apache.cayenne.dbsync.merge.DropRelationshipToDb;
+import org.apache.cayenne.dbsync.merge.DropRelationshipToModel;
+import org.apache.cayenne.dbsync.merge.DropTableToDb;
+import org.apache.cayenne.dbsync.merge.DropTableToModel;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToModel;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToModel;
+import org.apache.cayenne.dbsync.merge.SetNotNullToDb;
+import org.apache.cayenne.dbsync.merge.SetNotNullToModel;
+import org.apache.cayenne.dbsync.merge.SetPrimaryKeyToDb;
+import org.apache.cayenne.dbsync.merge.SetPrimaryKeyToModel;
+import org.apache.cayenne.dbsync.merge.SetValueForNullToDb;
+import org.apache.cayenne.dbsync.merge.ValueForNullProvider;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+
+import java.util.Collection;
+
+/**
+ * @since 4.0
+ */
+public class DefaultMergerTokenFactory implements MergerTokenFactory {
+
+ @Override
+ public MergerToken createCreateTableToModel(DbEntity entity) {
+ return new CreateTableToModel(entity);
+ }
+
+ @Override
+ public MergerToken createCreateTableToDb(DbEntity entity) {
+ return new CreateTableToDb(entity);
+ }
+
+ @Override
+ public MergerToken createDropTableToModel(DbEntity entity) {
+ return new DropTableToModel(entity);
+ }
+
+ @Override
+ public MergerToken createDropTableToDb(DbEntity entity) {
+ return new DropTableToDb(entity);
+ }
+
+ @Override
+ public MergerToken createAddColumnToModel(DbEntity entity, DbAttribute column) {
+ return new AddColumnToModel(entity, column);
+ }
+
+ @Override
+ public MergerToken createAddColumnToDb(DbEntity entity, DbAttribute column) {
+ return new AddColumnToDb(entity, column);
+ }
+
+ @Override
+ public MergerToken createDropColumnToModel(DbEntity entity, DbAttribute column) {
+ return new DropColumnToModel(entity, column);
+ }
+
+ @Override
+ public MergerToken createDropColumnToDb(DbEntity entity, DbAttribute column) {
+ return new DropColumnToDb(entity, column);
+ }
+
+ @Override
+ public MergerToken createSetNotNullToModel(DbEntity entity, DbAttribute column) {
+ return new SetNotNullToModel(entity, column);
+ }
+
+ @Override
+ public MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetNotNullToDb(entity, column);
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToModel(DbEntity entity, DbAttribute column) {
+ return new SetAllowNullToModel(entity, column);
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetAllowNullToDb(entity, column);
+ }
+
+ @Override
+ public MergerToken createSetValueForNullToDb(DbEntity entity, DbAttribute column, ValueForNullProvider valueForNullProvider) {
+ return new SetValueForNullToDb(entity, column, valueForNullProvider);
+ }
+
+ @Override
+ public MergerToken createSetColumnTypeToModel(
+ DbEntity entity,
+ DbAttribute columnOriginal,
+ DbAttribute columnNew) {
+ return new SetColumnTypeToModel(entity, columnOriginal, columnNew);
+ }
+
+ @Override
+ public MergerToken createSetColumnTypeToDb(
+ DbEntity entity,
+ DbAttribute columnOriginal,
+ DbAttribute columnNew) {
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew);
+ }
+
+ @Override
+ public MergerToken createAddRelationshipToDb(DbEntity entity, DbRelationship rel) {
+ return new AddRelationshipToDb(entity, rel);
+ }
+
+ @Override
+ public MergerToken createAddRelationshipToModel(DbEntity entity, DbRelationship rel) {
+ return new AddRelationshipToModel(entity, rel);
+ }
+
+ @Override
+ public MergerToken createDropRelationshipToDb(DbEntity entity, DbRelationship rel) {
+ return new DropRelationshipToDb(entity, rel);
+ }
+
+ @Override
+ public MergerToken createDropRelationshipToModel(DbEntity entity, DbRelationship rel) {
+ return new DropRelationshipToModel(entity, rel);
+ }
+
+ @Override
+ public MergerToken createSetPrimaryKeyToDb(
+ DbEntity entity,
+ Collection<DbAttribute> primaryKeyOriginal,
+ Collection<DbAttribute> primaryKeyNew,
+ String detectedPrimaryKeyName) {
+ return new SetPrimaryKeyToDb(
+ entity,
+ primaryKeyOriginal,
+ primaryKeyNew,
+ detectedPrimaryKeyName);
+ }
+
+ @Override
+ public MergerToken createSetPrimaryKeyToModel(
+ DbEntity entity,
+ Collection<DbAttribute> primaryKeyOriginal,
+ Collection<DbAttribute> primaryKeyNew,
+ String detectedPrimaryKeyName) {
+ return new SetPrimaryKeyToModel(
+ entity,
+ primaryKeyOriginal,
+ primaryKeyNew,
+ detectedPrimaryKeyName);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DerbyMergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DerbyMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DerbyMergerTokenFactory.java
new file mode 100644
index 0000000..398d5cc
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DerbyMergerTokenFactory.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.dbsync.merge.factory;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+import org.apache.cayenne.dbsync.merge.SetNotNullToDb;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+import java.util.Collections;
+import java.util.List;
+
+public class DerbyMergerTokenFactory extends DefaultMergerTokenFactory {
+
+ @Override
+ public MergerToken createSetColumnTypeToDb(
+ final DbEntity entity,
+ DbAttribute columnOriginal,
+ final DbAttribute columnNew) {
+
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ // http://db.apache.org/derby/manuals/reference/sqlj26.html
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" ALTER ");
+ sqlBuffer.append(context.quotedName(columnNew));
+ sqlBuffer.append(" SET DATA TYPE ");
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetNotNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ QuotingStrategy context = adapter.getQuotingStrategy();
+
+ return Collections.singletonList("ALTER TABLE " + context.quotedFullyQualifiedName(getEntity())
+ + " ALTER COLUMN " + context.quotedName(getColumn()) + " NOT NULL");
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetAllowNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ QuotingStrategy context = adapter.getQuotingStrategy();
+
+ return Collections.singletonList("ALTER TABLE " + context.quotedFullyQualifiedName(getEntity())
+ + " ALTER COLUMN " + context.quotedName(getColumn()) + " NULL");
+ }
+
+ };
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/FirebirdMergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/FirebirdMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/FirebirdMergerTokenFactory.java
new file mode 100644
index 0000000..4368977
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/FirebirdMergerTokenFactory.java
@@ -0,0 +1,91 @@
+/*****************************************************************
+ * 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.dbsync.merge.factory;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.AddColumnToDb;
+import org.apache.cayenne.dbsync.merge.DropColumnToDb;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetNotNullToDb;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+import java.util.Collections;
+import java.util.List;
+
+public class FirebirdMergerTokenFactory extends DefaultMergerTokenFactory {
+
+ @Override
+ public MergerToken createDropColumnToDb(DbEntity entity, DbAttribute column) {
+ return new DropColumnToDb(entity, column) {
+ public List<String> createSql(DbAdapter adapter) {
+ QuotingStrategy quoting = adapter.getQuotingStrategy();
+ return Collections.singletonList("ALTER TABLE " + quoting.quotedFullyQualifiedName(getEntity())
+ + " DROP " + quoting.quotedName(getColumn()));
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetNotNullToDb(entity, column) {
+ public List<String> createSql(DbAdapter adapter) {
+ QuotingStrategy context = adapter.getQuotingStrategy();
+ String entityName = context.quotedFullyQualifiedName(getEntity()) ;
+ String columnName = context.quotedName(getColumn());
+ // Firebird doesn't support ALTER TABLE table_name ALTER column_name SET NOT NULL
+ // but this might be achived by modyfication of system tables
+ return Collections.singletonList(String.format("UPDATE RDB$RELATION_FIELDS SET RDB$NULL_FLAG = 1 "+
+ "WHERE RDB$FIELD_NAME = '%s' AND RDB$RELATION_NAME = '%s'", columnName, entityName));
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetAllowNullToDb(entity, column) {
+ public List<String> createSql(DbAdapter adapter) {
+ QuotingStrategy context = adapter.getQuotingStrategy();
+ String entityName = context.quotedFullyQualifiedName(getEntity()) ;
+ String columnName = context.quotedName(getColumn());
+ // Firebird doesn't support ALTER TABLE table_name ALTER column_name DROP NOT NULL
+ // but this might be achived by modyfication system tables
+ return Collections.singletonList(String.format("UPDATE RDB$RELATION_FIELDS SET RDB$NULL_FLAG = NULL "+
+ " WHERE RDB$FIELD_NAME = '%s' AND RDB$RELATION_NAME = '%s'", columnName, entityName));
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createAddColumnToDb(DbEntity entity, DbAttribute column) {
+ return new AddColumnToDb(entity, column) {
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" ADD ");
+ sqlBuffer.append(context.quotedName(getColumn()));
+ sqlBuffer.append(" ");
+ }
+ };
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/H2MergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/H2MergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/H2MergerTokenFactory.java
new file mode 100644
index 0000000..8acafc3
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/H2MergerTokenFactory.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.dbsync.merge.factory;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+import org.apache.cayenne.dbsync.merge.SetPrimaryKeyToDb;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @since 3.0
+ */
+public class H2MergerTokenFactory extends DefaultMergerTokenFactory {
+
+ @Override
+ public MergerToken createSetColumnTypeToDb(final DbEntity entity, DbAttribute columnOriginal,
+ final DbAttribute columnNew) {
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" ALTER ");
+ sqlBuffer.append(context.quotedName(columnNew));
+ sqlBuffer.append(" ");
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetAllowNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ return Collections.singletonList("ALTER TABLE " + getEntity().getFullyQualifiedName()
+ + " ALTER COLUMN " + getColumn().getName() + " SET NULL");
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetPrimaryKeyToDb(DbEntity entity, Collection<DbAttribute> primaryKeyOriginal,
+ Collection<DbAttribute> primaryKeyNew, String detectedPrimaryKeyName) {
+ return new SetPrimaryKeyToDb(entity, primaryKeyOriginal, primaryKeyNew, detectedPrimaryKeyName) {
+
+ @Override
+ protected void appendDropOriginalPrimaryKeySQL(DbAdapter adapter, List<String> sqls) {
+ sqls.add("ALTER TABLE " + adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity())
+ + " DROP PRIMARY KEY");
+ }
+
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/HSQLMergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/HSQLMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/HSQLMergerTokenFactory.java
new file mode 100644
index 0000000..15cfa18
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/HSQLMergerTokenFactory.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.dbsync.merge.factory;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+import org.apache.cayenne.dbsync.merge.SetPrimaryKeyToDb;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+public class HSQLMergerTokenFactory extends DefaultMergerTokenFactory {
+
+ @Override
+ public MergerToken createSetColumnTypeToDb(final DbEntity entity, DbAttribute columnOriginal,
+ final DbAttribute columnNew) {
+
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" ALTER ");
+ sqlBuffer.append(context.quotedName(columnNew));
+ sqlBuffer.append(" ");
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetAllowNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ QuotingStrategy context = adapter.getQuotingStrategy();
+
+ return Collections.singletonList("ALTER TABLE " + context.quotedFullyQualifiedName(getEntity())
+ + " ALTER COLUMN " + context.quotedName(getColumn()) + " NULL");
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetPrimaryKeyToDb(DbEntity entity, Collection<DbAttribute> primaryKeyOriginal,
+ Collection<DbAttribute> primaryKeyNew, String detectedPrimaryKeyName) {
+ return new SetPrimaryKeyToDb(entity, primaryKeyOriginal, primaryKeyNew, detectedPrimaryKeyName) {
+
+ @Override
+ protected void appendDropOriginalPrimaryKeySQL(DbAdapter adapter, List<String> sqls) {
+ sqls.add("ALTER TABLE " + adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity())
+ + " DROP PRIMARY KEY");
+ }
+
+ };
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/IngresMergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/IngresMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/IngresMergerTokenFactory.java
new file mode 100644
index 0000000..19d2860
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/IngresMergerTokenFactory.java
@@ -0,0 +1,224 @@
+/*****************************************************************
+ * 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.dbsync.merge.factory;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.AddRelationshipToDb;
+import org.apache.cayenne.dbsync.merge.DropColumnToDb;
+import org.apache.cayenne.dbsync.merge.DropRelationshipToDb;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+import org.apache.cayenne.dbsync.merge.SetNotNullToDb;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+
+import java.util.Collections;
+import java.util.List;
+
+public class IngresMergerTokenFactory extends DefaultMergerTokenFactory {
+
+ @Override
+ public MergerToken createSetColumnTypeToDb(final DbEntity entity, DbAttribute columnOriginal,
+ final DbAttribute columnNew) {
+
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" ALTER COLUMN ");
+ sqlBuffer.append(context.quotedName(columnNew));
+ sqlBuffer.append(" ");
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createDropColumnToDb(DbEntity entity, DbAttribute column) {
+ return new DropColumnToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuilder buf = new StringBuilder();
+ QuotingStrategy context = adapter.getQuotingStrategy();
+ buf.append("ALTER TABLE ");
+ buf.append(context.quotedFullyQualifiedName(getEntity()));
+ buf.append(" DROP COLUMN ");
+ buf.append(context.quotedName(getColumn()));
+ buf.append(" RESTRICT ");
+
+ return Collections.singletonList(buf.toString());
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createAddRelationshipToDb(DbEntity entity, final DbRelationship rel) {
+ return new AddRelationshipToDb(entity, rel) {
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ if (!rel.isToMany() && rel.isToPK() && !rel.isToDependentPK()) {
+
+ DbEntity source = (DbEntity) rel.getSourceEntity();
+ QuotingStrategy context = adapter.getQuotingStrategy();
+ StringBuilder buf = new StringBuilder();
+ StringBuilder refBuf = new StringBuilder();
+
+ buf.append("ALTER TABLE ");
+ buf.append(context.quotedFullyQualifiedName(source));
+
+ // requires the ADD CONSTRAINT statement
+ buf.append(" ADD CONSTRAINT ");
+ String name = "U_" + rel.getSourceEntity().getName() + "_"
+ + (long) (System.currentTimeMillis() / (Math.random() * 100000));
+
+ buf.append(context.quotedIdentifier(rel.getSourceEntity(), name));
+ buf.append(" FOREIGN KEY (");
+
+ boolean first = true;
+ for (DbJoin join : rel.getJoins()) {
+ if (!first) {
+ buf.append(", ");
+ refBuf.append(", ");
+ } else
+ first = false;
+
+ buf.append(context.quotedSourceName(join));
+ refBuf.append(context.quotedTargetName(join));
+ }
+
+ buf.append(") REFERENCES ");
+ buf.append(context.quotedFullyQualifiedName((DbEntity) rel.getTargetEntity()));
+ buf.append(" (");
+ buf.append(refBuf.toString());
+ buf.append(')');
+
+ // also make sure we delete dependent FKs
+ buf.append(" ON DELETE CASCADE");
+
+ String fksql = buf.toString();
+
+ if (fksql != null) {
+ return Collections.singletonList(fksql);
+ }
+ }
+
+ return Collections.emptyList();
+
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetNotNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+
+ /*
+ * TODO: we generate this query as in ingres db documentation,
+ * but unfortunately ingres don't support it
+ */
+
+ StringBuilder sqlBuffer = new StringBuilder();
+
+ QuotingStrategy context = adapter.getQuotingStrategy();
+
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(getEntity().getFullyQualifiedName());
+ sqlBuffer.append(" ALTER COLUMN ");
+ sqlBuffer.append(context.quotedName(getColumn()));
+ sqlBuffer.append(" ");
+ sqlBuffer.append(adapter.externalTypesForJdbcType(getColumn().getType())[0]);
+
+ if (adapter.typeSupportsLength(getColumn().getType()) && getColumn().getMaxLength() > 0) {
+ sqlBuffer.append("(");
+ sqlBuffer.append(getColumn().getMaxLength());
+ sqlBuffer.append(")");
+ }
+
+ sqlBuffer.append(" NOT NULL");
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetAllowNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuilder sqlBuffer = new StringBuilder();
+ QuotingStrategy context = adapter.getQuotingStrategy();
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" ALTER COLUMN ");
+ sqlBuffer.append(context.quotedName(getColumn()));
+ sqlBuffer.append(" ");
+ sqlBuffer.append(adapter.externalTypesForJdbcType(getColumn().getType())[0]);
+
+ if (adapter.typeSupportsLength(getColumn().getType()) && getColumn().getMaxLength() > 0) {
+ sqlBuffer.append("(");
+ sqlBuffer.append(getColumn().getMaxLength());
+ sqlBuffer.append(")");
+ }
+
+ sqlBuffer.append(" WITH NULL");
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createDropRelationshipToDb(final DbEntity entity, DbRelationship rel) {
+
+ return new DropRelationshipToDb(entity, rel) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ String fkName = getFkName();
+
+ if (fkName == null) {
+ return Collections.emptyList();
+ }
+
+ StringBuilder buf = new StringBuilder();
+ buf.append("ALTER TABLE ");
+ buf.append(adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity()));
+ buf.append(" DROP CONSTRAINT ");
+ buf.append(fkName);
+ buf.append(" CASCADE ");
+
+ return Collections.singletonList(buf.toString());
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactory.java
new file mode 100644
index 0000000..46b6ef3
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactory.java
@@ -0,0 +1,88 @@
+/*****************************************************************
+ * 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.dbsync.merge.factory;
+
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.ValueForNullProvider;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+
+import java.util.Collection;
+
+public interface MergerTokenFactory {
+
+ MergerToken createCreateTableToModel(DbEntity entity);
+
+ MergerToken createCreateTableToDb(DbEntity entity);
+
+ MergerToken createDropTableToModel(DbEntity entity);
+
+ MergerToken createDropTableToDb(DbEntity entity);
+
+ MergerToken createAddColumnToModel(DbEntity entity, DbAttribute column);
+
+ MergerToken createAddColumnToDb(DbEntity entity, DbAttribute column);
+
+ MergerToken createDropColumnToModel(DbEntity entity, DbAttribute column);
+
+ MergerToken createDropColumnToDb(DbEntity entity, DbAttribute column);
+
+ MergerToken createSetNotNullToModel(DbEntity entity, DbAttribute column);
+
+ MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column);
+
+ MergerToken createSetAllowNullToModel(DbEntity entity, DbAttribute column);
+
+ MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column);
+
+ MergerToken createSetValueForNullToDb(DbEntity entity,
+ DbAttribute column,
+ ValueForNullProvider valueForNullProvider);
+
+ MergerToken createSetColumnTypeToModel(
+ DbEntity entity,
+ DbAttribute columnOriginal,
+ DbAttribute columnNew);
+
+ MergerToken createSetColumnTypeToDb(
+ DbEntity entity,
+ DbAttribute columnOriginal,
+ DbAttribute columnNew);
+
+ MergerToken createAddRelationshipToDb(DbEntity entity, DbRelationship rel);
+
+ MergerToken createAddRelationshipToModel(DbEntity entity, DbRelationship rel);
+
+ MergerToken createDropRelationshipToDb(DbEntity entity, DbRelationship rel);
+
+ MergerToken createDropRelationshipToModel(DbEntity entity, DbRelationship rel);
+
+ MergerToken createSetPrimaryKeyToDb(
+ DbEntity entity,
+ Collection<DbAttribute> primaryKeyOriginal,
+ Collection<DbAttribute> primaryKeyNew,
+ String detectedPrimaryKeyName);
+
+ MergerToken createSetPrimaryKeyToModel(
+ DbEntity entity,
+ Collection<DbAttribute> primaryKeyOriginal,
+ Collection<DbAttribute> primaryKeyNew,
+ String detectedPrimaryKeyName);
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactoryProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactoryProvider.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactoryProvider.java
new file mode 100644
index 0000000..8d5b573
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactoryProvider.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.dbsync.merge.factory;
+
+import org.apache.cayenne.dba.PerAdapterProvider;
+import org.apache.cayenne.dbsync.CayenneDbSyncModule;
+import org.apache.cayenne.di.Inject;
+
+import java.util.Map;
+
+/**
+ * @since 4.0
+ */
+public class MergerTokenFactoryProvider extends PerAdapterProvider<MergerTokenFactory> {
+
+ public MergerTokenFactoryProvider(@Inject(CayenneDbSyncModule.MERGER_FACTORIES_MAP) Map<String,
+ MergerTokenFactory> perAdapterValues, @Inject MergerTokenFactory defaultValue) {
+ super(perAdapterValues, defaultValue);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MySQLMergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MySQLMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MySQLMergerTokenFactory.java
new file mode 100644
index 0000000..2193446
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MySQLMergerTokenFactory.java
@@ -0,0 +1,156 @@
+/*****************************************************************
+ * 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.dbsync.merge.factory;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.DropRelationshipToDb;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+import org.apache.cayenne.dbsync.merge.SetNotNullToDb;
+import org.apache.cayenne.dbsync.merge.SetPrimaryKeyToDb;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+public class MySQLMergerTokenFactory extends DefaultMergerTokenFactory {
+
+ @Override
+ public MergerToken createSetNotNullToDb(
+ final DbEntity entity,
+ final DbAttribute column) {
+ return new SetNotNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuffer sqlBuffer = new StringBuffer();
+
+ QuotingStrategy context = adapter.getQuotingStrategy();
+
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" CHANGE ");
+ sqlBuffer.append(context.quotedName(getColumn()));
+ sqlBuffer.append(" ");
+ adapter.createTableAppendColumn(sqlBuffer, column);
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToDb(
+ final DbEntity entity,
+ final DbAttribute column) {
+ return new SetAllowNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuffer sqlBuffer = new StringBuffer();
+
+ QuotingStrategy context = adapter.getQuotingStrategy();
+
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" CHANGE ");
+ sqlBuffer.append(context.quotedName(getColumn()));
+ sqlBuffer.append(" ");
+ adapter.createTableAppendColumn(sqlBuffer, column);
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetColumnTypeToDb(
+ final DbEntity entity,
+ DbAttribute columnOriginal,
+ final DbAttribute columnNew) {
+
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ // http://dev.mysql.com/tech-resources/articles/mysql-cluster-50.html
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" MODIFY ");
+ sqlBuffer.append(context.quotedName(columnNew));
+ sqlBuffer.append(" ");
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createDropRelationshipToDb(
+ final DbEntity entity,
+ DbRelationship rel) {
+
+ return new DropRelationshipToDb(entity, rel) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ String fkName = getFkName();
+
+ if (fkName == null) {
+ return Collections.emptyList();
+ }
+ QuotingStrategy context = adapter.getQuotingStrategy();
+
+ // http://dev.mysql.com/tech-resources/articles/mysql-cluster-50.html
+ return Collections.singletonList("ALTER TABLE " + context.quotedFullyQualifiedName(entity) + " DROP FOREIGN KEY " + fkName);
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createSetPrimaryKeyToDb(
+ DbEntity entity,
+ Collection<DbAttribute> primaryKeyOriginal,
+ Collection<DbAttribute> primaryKeyNew,
+ String detectedPrimaryKeyName) {
+ return new SetPrimaryKeyToDb(
+ entity,
+ primaryKeyOriginal,
+ primaryKeyNew,
+ detectedPrimaryKeyName) {
+
+ @Override
+ protected void appendDropOriginalPrimaryKeySQL(
+ DbAdapter adapter,
+ List<String> sqls) {
+ sqls.add("ALTER TABLE "
+ + adapter.getQuotingStrategy()
+ .quotedFullyQualifiedName(getEntity())
+ + " DROP PRIMARY KEY");
+ }
+
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/OpenBaseMergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/OpenBaseMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/OpenBaseMergerTokenFactory.java
new file mode 100644
index 0000000..7235f6b
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/OpenBaseMergerTokenFactory.java
@@ -0,0 +1,143 @@
+/*****************************************************************
+ * 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.dbsync.merge.factory;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dbsync.merge.CreateTableToDb;
+import org.apache.cayenne.dbsync.merge.DropRelationshipToDb;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+import org.apache.cayenne.dbsync.merge.SetNotNullToDb;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class OpenBaseMergerTokenFactory extends DefaultMergerTokenFactory {
+
+ @Override
+ public MergerToken createCreateTableToDb(DbEntity entity) {
+ return new CreateTableToDb(entity) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ List<String> sqls = new ArrayList<String>();
+ // create table first as OpenBase adapter created primary key in its
+ // getPkGenerator().createAutoPkStatements
+ sqls.add(adapter.createTable(getEntity()));
+ sqls.addAll(adapter.getPkGenerator().createAutoPkStatements(
+ Collections.singletonList(getEntity())));
+ return sqls;
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createDropRelationshipToDb(
+ final DbEntity entity,
+ final DbRelationship rel) {
+ return new DropRelationshipToDb(entity, rel) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+
+
+ // FK_NAME form jdbc metadata seem to be wrong. It contain a column name
+ // and not the 'relationshipName'
+ // TODO: tell openbase developer mail list
+
+ DbEntity source = getEntity();
+ DbEntity dest = rel.getTargetEntity();
+
+ // only use the first. See adapter
+ // TODO: can we be sure this is the first and same as used by the adapter?
+ DbJoin join = rel.getJoins().get(0);
+
+ // see comment in adapter for why source and dest is switched around..
+
+ return Collections.singletonList("delete from _SYS_RELATIONSHIP where "
+ + " source_table = '" + dest.getFullyQualifiedName() + "'"
+ + " and source_column = '" + join.getTargetName() + "'"
+ + " and dest_table = '" + source.getFullyQualifiedName() + "'"
+ + " and dest_column = '" + join.getSourceName() + "'");
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetColumnTypeToDb(
+ final DbEntity entity,
+ final DbAttribute columnOriginal,
+ final DbAttribute columnNew) {
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ List<String> sqls = new ArrayList<String>();
+
+ if (columnOriginal.getMaxLength() != columnNew.getMaxLength()) {
+ sqls.add("ALTER TABLE "
+ + entity.getFullyQualifiedName()
+ + " COLUMN "
+ + columnNew.getName()
+ + " SET LENGTH "
+ + columnNew.getMaxLength());
+ }
+
+ return sqls;
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetNotNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+
+ return Collections.singletonList("ALTER TABLE " + getEntity().getFullyQualifiedName()
+ + " COLUMN " + getColumn().getName() + " SET NOT NULL");
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetAllowNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+
+ return Collections.singletonList("ALTER TABLE " + getEntity().getFullyQualifiedName()
+ + " COLUMN " + getColumn().getName() + " SET NULL");
+ }
+
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/OracleMergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/OracleMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/OracleMergerTokenFactory.java
new file mode 100644
index 0000000..2c4032b
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/OracleMergerTokenFactory.java
@@ -0,0 +1,111 @@
+/*****************************************************************
+ * 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.dbsync.merge.factory;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.AddColumnToDb;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+import org.apache.cayenne.dbsync.merge.SetNotNullToDb;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+import java.util.Collections;
+import java.util.List;
+
+
+public class OracleMergerTokenFactory extends DefaultMergerTokenFactory {
+
+ @Override
+ public MergerToken createAddColumnToDb(final DbEntity entity, final DbAttribute column) {
+ return new AddColumnToDb(entity, column) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" ADD ");
+ sqlBuffer.append(context.quotedName(column));
+ sqlBuffer.append(" ");
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createSetColumnTypeToDb(
+ final DbEntity entity,
+ DbAttribute columnOriginal,
+ final DbAttribute columnNew) {
+
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" MODIFY ");
+ sqlBuffer.append(context.quotedName(columnNew));
+ sqlBuffer.append(" ");
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToDb(DbEntity entity, final DbAttribute column) {
+ return new SetAllowNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuffer sqlBuffer = new StringBuffer();
+
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" MODIFY ");
+
+ adapter.createTableAppendColumn(sqlBuffer, column);
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetNotNullToDb(DbEntity entity, final DbAttribute column) {
+
+ return new SetNotNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuffer sqlBuffer = new StringBuffer();
+
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" MODIFY ");
+
+ adapter.createTableAppendColumn(sqlBuffer, column);
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/PostgresMergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/PostgresMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/PostgresMergerTokenFactory.java
new file mode 100644
index 0000000..935ecfb
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/PostgresMergerTokenFactory.java
@@ -0,0 +1,49 @@
+/*****************************************************************
+ * 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.dbsync.merge.factory;
+
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+
+public class PostgresMergerTokenFactory extends DefaultMergerTokenFactory {
+
+ @Override
+ public MergerToken createSetColumnTypeToDb(
+ final DbEntity entity,
+ DbAttribute columnOriginal,
+ final DbAttribute columnNew) {
+
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy quotingStrategy) {
+ // http://www.postgresql.org/docs/8.2/static/sql-altertable.html
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(quotingStrategy.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" ALTER ");
+ sqlBuffer.append(quotingStrategy.quotedName(columnNew));
+ sqlBuffer.append(" TYPE ");
+ }
+ };
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/SQLServerMergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/SQLServerMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/SQLServerMergerTokenFactory.java
new file mode 100644
index 0000000..768b957
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/SQLServerMergerTokenFactory.java
@@ -0,0 +1,112 @@
+/*****************************************************************
+ * 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.dbsync.merge.factory;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.AddColumnToDb;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+import org.apache.cayenne.dbsync.merge.SetNotNullToDb;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+import java.util.Collections;
+import java.util.List;
+
+public class SQLServerMergerTokenFactory extends DefaultMergerTokenFactory {
+
+ @Override
+ public MergerToken createSetColumnTypeToDb(
+ final DbEntity entity,
+ DbAttribute columnOriginal,
+ final DbAttribute columnNew) {
+
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ // http://msdn2.microsoft.com/en-us/library/ms190273.aspx
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" ALTER COLUMN ");
+ sqlBuffer.append(context.quotedName(columnNew));
+ sqlBuffer.append(" ");
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createAddColumnToDb(final DbEntity entity, final DbAttribute column) {
+ return new AddColumnToDb(entity, column) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ // http://msdn2.microsoft.com/en-us/library/ms190273.aspx
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" ADD ");
+ sqlBuffer.append(context.quotedName(column));
+ sqlBuffer.append(" ");
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToDb(DbEntity entity, final DbAttribute column) {
+ return new SetAllowNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuffer sqlBuffer = new StringBuffer();
+
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" ALTER COLUMN ");
+
+ adapter.createTableAppendColumn(sqlBuffer, column);
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetNotNullToDb(DbEntity entity, final DbAttribute column) {
+
+ return new SetNotNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuffer sqlBuffer = new StringBuffer();
+
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" ALTER COLUMN ");
+
+ adapter.createTableAppendColumn(sqlBuffer, column);
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/SybaseMergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/SybaseMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/SybaseMergerTokenFactory.java
new file mode 100644
index 0000000..f295305
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/SybaseMergerTokenFactory.java
@@ -0,0 +1,166 @@
+/*****************************************************************
+ * 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.dbsync.merge.factory;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.AddColumnToDb;
+import org.apache.cayenne.dbsync.merge.DropColumnToDb;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+import org.apache.cayenne.dbsync.merge.SetNotNullToDb;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @since 3.0
+ */
+public class SybaseMergerTokenFactory extends DefaultMergerTokenFactory {
+
+ /**
+ * @since 3.0
+ */
+ @Override
+ public MergerToken createAddColumnToDb(DbEntity entity, final DbAttribute column) {
+ return new AddColumnToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+
+ StringBuffer sqlBuffer = new StringBuffer();
+ QuotingStrategy context = adapter.getQuotingStrategy();
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" ADD ");
+ boolean magnatory = column.isMandatory();
+ column.setMandatory(false);
+ adapter.createTableAppendColumn(sqlBuffer, column);
+ if(magnatory){
+ column.setMandatory(magnatory);
+ }
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+
+ /**
+ * @since 3.0
+ */
+ @Override
+ public MergerToken createDropColumnToDb(DbEntity entity, DbAttribute column) {
+ return new DropColumnToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuilder sqlBuffer = new StringBuilder();
+ QuotingStrategy context = adapter.getQuotingStrategy();
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" DROP ");
+ sqlBuffer.append(context.quotedName(getColumn()));
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+
+ /**
+ * @since 3.0
+ */
+ @Override
+ public MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetNotNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+
+ StringBuffer sqlBuffer = createStringQuery(
+ adapter,
+ getEntity(),
+ getColumn());
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+
+ /**
+ * @since 3.0
+ */
+ @Override
+ public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetAllowNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuffer sqlBuffer = createStringQuery(
+ adapter,
+ getEntity(),
+ getColumn());
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+ };
+ }
+
+ /**
+ * @since 3.0
+ */
+ @Override
+ public MergerToken createSetColumnTypeToDb(
+ final DbEntity entity,
+ DbAttribute columnOriginal,
+ final DbAttribute columnNew) {
+
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ // http://dev.mysql.com/tech-resources/articles/mysql-cluster-50.html
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" MODIFY ");
+ sqlBuffer.append(context.quotedName(columnNew));
+ sqlBuffer.append(" ");
+ }
+
+ };
+ }
+
+ private static StringBuffer createStringQuery(
+ DbAdapter adapter,
+ DbEntity entity,
+ DbAttribute column) {
+ StringBuffer sqlBuffer = new StringBuffer();
+ QuotingStrategy context = adapter.getQuotingStrategy();
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" MODIFY ");
+ adapter.createTableAppendColumn(sqlBuffer, column);
+
+ return sqlBuffer;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesBaseLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesBaseLoader.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesBaseLoader.java
new file mode 100644
index 0000000..2bb55c0
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesBaseLoader.java
@@ -0,0 +1,107 @@
+/*****************************************************************
+ * 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.dbsync.reverse;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.TypesMapping;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Set;
+
+/**
+* @since 4.0.
+*/
+public abstract class DbAttributesBaseLoader implements DbAttributesLoader {
+ private final String catalog;
+ private final String schema;
+
+ private final DatabaseMetaData metaData;
+ private final DbAdapter adapter;
+
+ public DbAttributesBaseLoader(String catalog, String schema, DatabaseMetaData metaData, DbAdapter adapter) {
+ this.catalog = catalog;
+ this.schema = schema;
+ this.metaData = metaData;
+ this.adapter = adapter;
+ }
+
+ protected DbAttribute loadDbAttribute(Set<String> columns, ResultSet rs) throws SQLException {
+
+ // gets attribute's (column's) information
+ int columnType = rs.getInt("DATA_TYPE");
+
+ // ignore precision of non-decimal columns
+ int decimalDigits = -1;
+ if (TypesMapping.isDecimal(columnType)) {
+ decimalDigits = rs.getInt("DECIMAL_DIGITS");
+ if (rs.wasNull()) {
+ decimalDigits = -1;
+ }
+ }
+
+ // create attribute delegating this task to adapter
+ DbAttribute attr = adapter.buildAttribute(
+ rs.getString("COLUMN_NAME"),
+ rs.getString("TYPE_NAME"),
+ columnType,
+ rs.getInt("COLUMN_SIZE"),
+ decimalDigits,
+ rs.getBoolean("NULLABLE"));
+
+ if (columns.contains("IS_AUTOINCREMENT")) {
+ String autoIncrement = rs.getString("IS_AUTOINCREMENT");
+ if ("YES".equals(autoIncrement)) {
+ attr.setGenerated(true);
+ }
+ }
+ return attr;
+ }
+
+ @Override
+ public void loadDbAttributes(DbEntity entity) {
+ for (DbAttribute attr : loadDbAttributes(entity.getName())) {
+ attr.setEntity(entity);
+
+ // override existing attributes if it comes again
+ if (entity.getAttribute(attr.getName()) != null) {
+ entity.removeAttribute(attr.getName());
+ }
+ entity.addAttribute(attr);
+ }
+ }
+
+ protected abstract List<DbAttribute> loadDbAttributes(String tableName);
+
+ protected String getCatalog() {
+ return catalog;
+ }
+
+ protected String getSchema() {
+ return schema;
+ }
+
+ protected DatabaseMetaData getMetaData() {
+ return metaData;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesLoader.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesLoader.java
new file mode 100644
index 0000000..6658cdc
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesLoader.java
@@ -0,0 +1,43 @@
+/*****************************************************************
+ * 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.dbsync.reverse;
+
+import org.apache.cayenne.map.DbEntity;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Interface responsible for attributes loading. Several options possible here
+ * 1) load attributes for each table separately
+ * 2) load attributes for schema and group it by table names
+ *
+ * here is a trade of between count of queries and amount af calculation.
+ *
+ *
+ * @since 4.0
+ */
+public interface DbAttributesLoader {
+
+ // TODO use instant field for logging
+ Log LOGGER = LogFactory.getLog(DbTableLoader.class);
+
+ void loadDbAttributes(DbEntity entity);
+
+}
+
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesPerSchemaLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesPerSchemaLoader.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesPerSchemaLoader.java
new file mode 100644
index 0000000..83ce60b
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesPerSchemaLoader.java
@@ -0,0 +1,130 @@
+/*****************************************************************
+ * 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.dbsync.reverse;
+
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.cayenne.dbsync.reverse.filters.PatternFilter;
+import org.apache.cayenne.dbsync.reverse.filters.TableFilter;
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.map.DbAttribute;
+
+/**
+ * Load all attributes for schema and return it for each table
+ * */
+public class DbAttributesPerSchemaLoader extends DbAttributesBaseLoader {
+
+ private final TableFilter filter;
+
+ private Map<String, List<DbAttribute>> attributes;
+
+ public DbAttributesPerSchemaLoader(String catalog, String schema, DatabaseMetaData metaData, DbAdapter adapter,
+ TableFilter filter) {
+ super(catalog, schema, metaData, adapter);
+
+ this.filter = filter;
+ }
+
+ private Map<String, List<DbAttribute>> loadDbAttributes() throws SQLException {
+ Map<String, List<DbAttribute>> attributes = new HashMap<>();
+
+ try (ResultSet rs = getMetaData().getColumns(getCatalog(), getSchema(), "%", "%");) {
+ Set<String> columns = new HashSet<String>();
+
+ while (rs.next()) {
+ if (columns.isEmpty()) {
+ ResultSetMetaData rsMetaData = rs.getMetaData();
+ for (int i = 1; i <= rsMetaData.getColumnCount(); i++) {
+ columns.add(rsMetaData.getColumnLabel(i));
+ }
+ }
+
+ // for a reason not quiet apparent to me, Oracle sometimes
+ // returns duplicate record sets for the same table, messing up
+ // table
+ // names. E.g. for the system table "WK$_ATTR_MAPPING" columns
+ // are
+ // returned twice - as "WK$_ATTR_MAPPING" and
+ // "WK$$_ATTR_MAPPING"... Go figure
+ String tableName = rs.getString("TABLE_NAME");
+ String columnName = rs.getString("COLUMN_NAME");
+
+ PatternFilter columnFilter = filter.isIncludeTable(tableName);
+ /*
+ * Here is possible optimization if filter will contain
+ * map<tableName, columnFilter> we can replace it after tables
+ * loading since already done pattern matching once and exactly
+ * know all tables that we want to process
+ */
+ if (columnFilter == null || !columnFilter.isInclude(columnName)) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Skip column '" + tableName + "." + columnName + "' (Path: " + getCatalog() + "/"
+ + getSchema() + "; Filter: " + columnFilter + ")");
+ }
+ continue;
+ }
+
+ List<DbAttribute> attrs = attributes.get(tableName);
+ if (attrs == null) {
+ attrs = new LinkedList<DbAttribute>();
+
+ attributes.put(tableName, attrs);
+ }
+
+ attrs.add(loadDbAttribute(columns, rs));
+ }
+ }
+
+ return attributes;
+ }
+
+ @Override
+ protected List<DbAttribute> loadDbAttributes(String tableName) {
+ Map<String, List<DbAttribute>> attributes = getAttributes();
+ if (attributes != null) {
+ List<DbAttribute> dbAttributes = attributes.get(tableName);
+ if (dbAttributes != null) {
+ return dbAttributes;
+ }
+ }
+
+ return new LinkedList<DbAttribute>();
+ }
+
+ public Map<String, List<DbAttribute>> getAttributes() {
+ if (attributes == null) {
+ try {
+ attributes = loadDbAttributes();
+ } catch (SQLException e) {
+ LOGGER.error(e);
+ attributes = new HashMap<>();
+ }
+ }
+ return attributes;
+ }
+}
[08/15] cayenne git commit: CAY-2116 Split schema synchronization
code in a separate module
Posted by aa...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoaderDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoaderDelegate.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoaderDelegate.java
deleted file mode 100644
index ec31e10..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoaderDelegate.java
+++ /dev/null
@@ -1,58 +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.access;
-
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.ObjEntity;
-
-/**
- * DbLoaderDelegate defines API that allows to control the behavior of DbLoader
- * during the database reverse-engineering. Delegate is also notified of the
- * progress of reverse-engineering.
- */
-public interface DbLoaderDelegate {
-
- void dbEntityAdded(DbEntity entity);
-
- void dbEntityRemoved(DbEntity entity);
-
- /**
- * Called before relationship loading for db-entity
- * @param entity
- *
- * @return true in case you want process relationships for this entity
- * false otherwise
- */
- boolean dbRelationship(DbEntity entity);
-
- /**
- * Called before relationship will be added into db-entity but after it was loaded from db
- * @param entity
- *
- * @return true in case you want add this relationship into entity
- * false otherwise
- */
- boolean dbRelationshipLoaded(DbEntity entity, DbRelationship relationship);
-
- void objEntityAdded(ObjEntity entity);
-
- void objEntityRemoved(ObjEntity entity);
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbAttributesBaseLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbAttributesBaseLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbAttributesBaseLoader.java
deleted file mode 100644
index 57e35ac..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbAttributesBaseLoader.java
+++ /dev/null
@@ -1,107 +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.access.loader;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.TypesMapping;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-
-import java.sql.DatabaseMetaData;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.List;
-import java.util.Set;
-
-/**
-* @since 4.0.
-*/
-public abstract class DbAttributesBaseLoader implements DbAttributesLoader {
- private final String catalog;
- private final String schema;
-
- private final DatabaseMetaData metaData;
- private final DbAdapter adapter;
-
- public DbAttributesBaseLoader(String catalog, String schema, DatabaseMetaData metaData, DbAdapter adapter) {
- this.catalog = catalog;
- this.schema = schema;
- this.metaData = metaData;
- this.adapter = adapter;
- }
-
- protected DbAttribute loadDbAttribute(Set<String> columns, ResultSet rs) throws SQLException {
-
- // gets attribute's (column's) information
- int columnType = rs.getInt("DATA_TYPE");
-
- // ignore precision of non-decimal columns
- int decimalDigits = -1;
- if (TypesMapping.isDecimal(columnType)) {
- decimalDigits = rs.getInt("DECIMAL_DIGITS");
- if (rs.wasNull()) {
- decimalDigits = -1;
- }
- }
-
- // create attribute delegating this task to adapter
- DbAttribute attr = adapter.buildAttribute(
- rs.getString("COLUMN_NAME"),
- rs.getString("TYPE_NAME"),
- columnType,
- rs.getInt("COLUMN_SIZE"),
- decimalDigits,
- rs.getBoolean("NULLABLE"));
-
- if (columns.contains("IS_AUTOINCREMENT")) {
- String autoIncrement = rs.getString("IS_AUTOINCREMENT");
- if ("YES".equals(autoIncrement)) {
- attr.setGenerated(true);
- }
- }
- return attr;
- }
-
- @Override
- public void loadDbAttributes(DbEntity entity) {
- for (DbAttribute attr : loadDbAttributes(entity.getName())) {
- attr.setEntity(entity);
-
- // override existing attributes if it comes again
- if (entity.getAttribute(attr.getName()) != null) {
- entity.removeAttribute(attr.getName());
- }
- entity.addAttribute(attr);
- }
- }
-
- protected abstract List<DbAttribute> loadDbAttributes(String tableName);
-
- protected String getCatalog() {
- return catalog;
- }
-
- protected String getSchema() {
- return schema;
- }
-
- protected DatabaseMetaData getMetaData() {
- return metaData;
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbAttributesLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbAttributesLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbAttributesLoader.java
deleted file mode 100644
index e4113b4..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbAttributesLoader.java
+++ /dev/null
@@ -1,43 +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.access.loader;
-
-import org.apache.cayenne.map.DbEntity;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Interface responsible for attributes loading. Several options possible here
- * 1) load attributes for each table separately
- * 2) load attributes for schema and group it by table names
- *
- * here is a trade of between count of queries and amount af calculation.
- *
- *
- * @since 4.0
- */
-public interface DbAttributesLoader {
-
- // TODO use instant field for logging
- Log LOGGER = LogFactory.getLog(DbTableLoader.class);
-
- void loadDbAttributes(DbEntity entity);
-
-}
-
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbAttributesPerSchemaLoader.java
----------------------------------------------------------------------
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
deleted file mode 100644
index a7871ad..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbAttributesPerSchemaLoader.java
+++ /dev/null
@@ -1,130 +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.access.loader;
-
-import java.sql.DatabaseMetaData;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.SQLException;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.cayenne.access.loader.filters.PatternFilter;
-import org.apache.cayenne.access.loader.filters.TableFilter;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.map.DbAttribute;
-
-/**
- * Load all attributes for schema and return it for each table
- * */
-public class DbAttributesPerSchemaLoader extends DbAttributesBaseLoader {
-
- private final TableFilter filter;
-
- private Map<String, List<DbAttribute>> attributes;
-
- public DbAttributesPerSchemaLoader(String catalog, String schema, DatabaseMetaData metaData, DbAdapter adapter,
- TableFilter filter) {
- super(catalog, schema, metaData, adapter);
-
- this.filter = filter;
- }
-
- private Map<String, List<DbAttribute>> loadDbAttributes() throws SQLException {
- Map<String, List<DbAttribute>> attributes = new HashMap<>();
-
- try (ResultSet rs = getMetaData().getColumns(getCatalog(), getSchema(), "%", "%");) {
- Set<String> columns = new HashSet<String>();
-
- while (rs.next()) {
- if (columns.isEmpty()) {
- ResultSetMetaData rsMetaData = rs.getMetaData();
- for (int i = 1; i <= rsMetaData.getColumnCount(); i++) {
- columns.add(rsMetaData.getColumnLabel(i));
- }
- }
-
- // for a reason not quiet apparent to me, Oracle sometimes
- // returns duplicate record sets for the same table, messing up
- // table
- // names. E.g. for the system table "WK$_ATTR_MAPPING" columns
- // are
- // returned twice - as "WK$_ATTR_MAPPING" and
- // "WK$$_ATTR_MAPPING"... Go figure
- String tableName = rs.getString("TABLE_NAME");
- String columnName = rs.getString("COLUMN_NAME");
-
- PatternFilter columnFilter = filter.isIncludeTable(tableName);
- /*
- * Here is possible optimization if filter will contain
- * map<tableName, columnFilter> we can replace it after tables
- * loading since already done pattern matching once and exactly
- * know all tables that we want to process
- */
- if (columnFilter == null || !columnFilter.isInclude(columnName)) {
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("Skip column '" + tableName + "." + columnName + "' (Path: " + getCatalog() + "/"
- + getSchema() + "; Filter: " + columnFilter + ")");
- }
- continue;
- }
-
- List<DbAttribute> attrs = attributes.get(tableName);
- if (attrs == null) {
- attrs = new LinkedList<DbAttribute>();
-
- attributes.put(tableName, attrs);
- }
-
- attrs.add(loadDbAttribute(columns, rs));
- }
- }
-
- return attributes;
- }
-
- @Override
- protected List<DbAttribute> loadDbAttributes(String tableName) {
- Map<String, List<DbAttribute>> attributes = getAttributes();
- if (attributes != null) {
- List<DbAttribute> dbAttributes = attributes.get(tableName);
- if (dbAttributes != null) {
- return dbAttributes;
- }
- }
-
- return new LinkedList<DbAttribute>();
- }
-
- public Map<String, List<DbAttribute>> getAttributes() {
- if (attributes == null) {
- try {
- attributes = loadDbAttributes();
- } catch (SQLException e) {
- LOGGER.error(e);
- attributes = new HashMap<>();
- }
- }
- return attributes;
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbLoaderConfiguration.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbLoaderConfiguration.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbLoaderConfiguration.java
deleted file mode 100644
index 59365cc..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbLoaderConfiguration.java
+++ /dev/null
@@ -1,150 +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.access.loader;
-
-import org.apache.cayenne.access.loader.filters.TableFilter;
-import org.apache.cayenne.access.loader.filters.FiltersConfig;
-import org.apache.cayenne.access.loader.filters.PatternFilter;
-
-/**
- * @since 4.0
- */
-public class DbLoaderConfiguration {
-
- /**
- * Returns a name of a generic class that should be used for all
- * ObjEntities. The most common generic class is
- * {@link org.apache.cayenne.CayenneDataObject}. If generic class name is
- * null (which is the default), DbLoader will assign each entity a unique
- * class name derived from the table name.
- *
- */
- private String genericClassName;
-
-/*
- // TODO: Andrus, 10/29/2005 - this type of filtering should be delegated to adapter
- TODO by default should skip name.startsWith("BIN$")
-
- private NameFilter tableFilter = NamePatternMatcher.build(null, null, "BIN$");
-
- private NameFilter columnFilter;
-
- private NameFilter proceduresFilter = new NameFilter() {
- private final Collection<String> excludedProcedures = Arrays.asList(
- "auto_pk_for_table",
- "auto_pk_for_table;1" // the last name is some Mac OS X Sybase artifact
- );
-
- @Override
- public boolean isIncluded(String string) {
- return !excludedProcedures.contains(string);
- }
- };
-*/
-
-
- /**
- * Java class implementing org.apache.cayenne.map.naming.NamingStrategy.
- * This is used to specify how ObjEntities will be mapped from the imported
- * DB schema.
- */
- private String namingStrategy;
-
- private Boolean skipRelationshipsLoading;
-
- private Boolean skipPrimaryKeyLoading;
-
- private String[] tableTypes;
-
- private FiltersConfig filtersConfig;
-
- public String getGenericClassName() {
- return genericClassName;
- }
-
- public void setGenericClassName(String genericClassName) {
- this.genericClassName = genericClassName;
- }
-
- public String[] getTableTypes() {
- return tableTypes;
- }
-
- public void setTableTypes(String[] tableTypes) {
- this.tableTypes = tableTypes;
- }
-
- public String getNamingStrategy() {
- return namingStrategy;
- }
-
- public void setNamingStrategy(String namingStrategy) {
- this.namingStrategy = namingStrategy;
- }
-
- public FiltersConfig getFiltersConfig() {
- if (filtersConfig == null) {
- // this case is used often in tests where config not initialized properly
- return FiltersConfig.create(null, null, TableFilter.everything(), PatternFilter.INCLUDE_NOTHING);
- }
- return filtersConfig;
- }
-
- public void setFiltersConfig(FiltersConfig filtersConfig) {
- this.filtersConfig = filtersConfig;
- }
-
- public boolean isSkipRelationshipsLoading() {
- return skipRelationshipsLoading != null && skipRelationshipsLoading;
- }
-
- public Boolean getSkipRelationshipsLoading() {
- return skipRelationshipsLoading;
- }
-
- public void setSkipRelationshipsLoading(Boolean skipRelationshipsLoading) {
- this.skipRelationshipsLoading = skipRelationshipsLoading;
- }
-
- public void setSkipPrimaryKeyLoading(Boolean skipPrimaryKeyLoading) {
- this.skipPrimaryKeyLoading = skipPrimaryKeyLoading;
- }
-
- public boolean getSkipPrimaryKeyLoading() {
- return skipPrimaryKeyLoading;
- }
-
- public boolean isSkipPrimaryKeyLoading() {
- return skipPrimaryKeyLoading != null && skipPrimaryKeyLoading;
- }
-
- @Override
- public String toString() {
- String res = "EntitiesFilters: " + getFiltersConfig();
- if (isSkipRelationshipsLoading()) {
- res += "\n Skip Loading Relationships! \n";
- }
-
- if (isSkipPrimaryKeyLoading()) {
- res += "\n Skip Loading PrimaryKeys! \n";
- }
-
- return res;
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbTableLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbTableLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbTableLoader.java
deleted file mode 100644
index baad305..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DbTableLoader.java
+++ /dev/null
@@ -1,196 +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.access.loader;
-
-import java.sql.DatabaseMetaData;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.apache.cayenne.access.DbLoaderDelegate;
-import org.apache.cayenne.access.loader.filters.PatternFilter;
-import org.apache.cayenne.access.loader.filters.TableFilter;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DetectedDbEntity;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * @since 4.0
- */
-public class DbTableLoader {
-
- private static final Log LOGGER = LogFactory.getLog(DbTableLoader.class);
-
- private static final String WILDCARD = "%";
-
- private final String catalog;
- private final String schema;
-
- private final DatabaseMetaData metaData;
- private final DbLoaderDelegate delegate;
-
- private final DbAttributesLoader attributesLoader;
-
- public DbTableLoader(String catalog, String schema, DatabaseMetaData metaData, DbLoaderDelegate delegate,
- DbAttributesLoader attributesLoader) {
- this.catalog = catalog;
- this.schema = schema;
- this.metaData = metaData;
- this.delegate = delegate;
-
- this.attributesLoader = attributesLoader;
- }
-
- /**
- * Returns all tables for given combination of the criteria. Tables returned
- * as DbEntities without any attributes or relationships.
- *
- * @param types
- * The types of table names to retrieve, null returns all types.
- * @return
- * @since 4.0
- */
- public List<DetectedDbEntity> getDbEntities(TableFilter filters, String[] types) throws SQLException {
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("Read tables: catalog=" + catalog + ", schema=" + schema + ", types=" + Arrays.toString(types));
- }
-
- List<DetectedDbEntity> tables = new LinkedList<DetectedDbEntity>();
- try (ResultSet rs = metaData.getTables(catalog, schema, WILDCARD, types);) {
- while (rs.next()) {
- // Oracle 9i and newer has a nifty recycle bin feature... but we
- // don't
- // want dropped tables to be included here; in fact they may
- // even result
- // in errors on reverse engineering as their names have special
- // chars like
- // "/", etc. So skip them all together
-
- String name = rs.getString("TABLE_NAME");
- if (name == null) {
- continue;
- }
-
- DetectedDbEntity table = new DetectedDbEntity(name);
-
- String catalog = rs.getString("TABLE_CAT");
- table.setCatalog(catalog);
-
- String schema = rs.getString("TABLE_SCHEM");
- table.setSchema(schema);
- if (!(this.catalog == null || this.catalog.equals(catalog))
- || !(this.schema == null || this.schema.equals(schema))) {
-
- LOGGER.error(catalog + "." + schema + "." + name + " wrongly loaded for catalog/schema : "
- + this.catalog + "." + this.schema);
-
- continue;
- }
-
- PatternFilter includeTable = filters.isIncludeTable(table.getName());
- if (includeTable != null) {
- tables.add(table);
- }
- }
- }
- return tables;
- }
-
- /**
- * Loads dbEntities for the specified tables.
- *
- * @param config
- * @param types
- */
- public List<DbEntity> loadDbEntities(DataMap map, DbLoaderConfiguration config, String[] types) throws SQLException {
- /** List of db entities to process. */
-
- List<DetectedDbEntity> tables = getDbEntities(config.getFiltersConfig().tableFilter(catalog, schema), types);
-
- List<DbEntity> dbEntities = new ArrayList<DbEntity>();
- for (DbEntity dbEntity : tables) {
- DbEntity oldEnt = map.getDbEntity(dbEntity.getName());
- if (oldEnt != null) {
- Collection<ObjEntity> oldObjEnt = map.getMappedEntities(oldEnt);
- if (!oldObjEnt.isEmpty()) {
- for (ObjEntity objEntity : oldObjEnt) {
- LOGGER.debug("Delete ObjEntity: " + objEntity.getName());
- map.removeObjEntity(objEntity.getName(), true);
- delegate.objEntityRemoved(objEntity);
- }
- }
-
- LOGGER.debug("Overwrite DbEntity: " + oldEnt.getName());
- map.removeDbEntity(oldEnt.getName(), true);
- delegate.dbEntityRemoved(oldEnt);
- }
-
- map.addDbEntity(dbEntity);
-
- delegate.dbEntityAdded(dbEntity);
-
- // delegate might have thrown this entity out... so check if it is
- // still
- // around before continuing processing
- if (map.getDbEntity(dbEntity.getName()) == dbEntity) {
- dbEntities.add(dbEntity);
- attributesLoader.loadDbAttributes(dbEntity);
- if (!config.isSkipPrimaryKeyLoading()) {
- loadPrimaryKey(dbEntity);
- }
- }
- }
-
- return dbEntities;
- }
-
- private void loadPrimaryKey(DbEntity dbEntity) throws SQLException {
-
- try (ResultSet rs = metaData.getPrimaryKeys(dbEntity.getCatalog(), dbEntity.getSchema(), dbEntity.getName());) {
- while (rs.next()) {
- String columnName = rs.getString("COLUMN_NAME");
- DbAttribute attribute = dbEntity.getAttribute(columnName);
-
- if (attribute != null) {
- attribute.setPrimaryKey(true);
- } else {
- // why an attribute might be null is not quiet clear
- // but there is a bug report 731406 indicating that it is
- // possible
- // so just print the warning, and ignore
- LOGGER.warn("Can't locate attribute for primary key: " + columnName);
- }
-
- String pkName = rs.getString("PK_NAME");
- if (pkName != null && dbEntity instanceof DetectedDbEntity) {
- ((DetectedDbEntity) dbEntity).setPrimaryKeyName(pkName);
- }
-
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DefaultDbLoaderDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DefaultDbLoaderDelegate.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DefaultDbLoaderDelegate.java
deleted file mode 100644
index 70a0230..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/DefaultDbLoaderDelegate.java
+++ /dev/null
@@ -1,60 +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.access.loader;
-
-import org.apache.cayenne.access.DbLoaderDelegate;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.ObjEntity;
-
-/**
- * @since 4.0.
- */
-public class DefaultDbLoaderDelegate implements DbLoaderDelegate {
-
- @Override
- public void dbEntityAdded(DbEntity entity) {
-
- }
-
- @Override
- public void dbEntityRemoved(DbEntity entity) {
-
- }
-
- @Override
- public boolean dbRelationship(DbEntity entity) {
- return true;
- }
-
- @Override
- public boolean dbRelationshipLoaded(DbEntity entity, DbRelationship relationship) {
- return true;
- }
-
- @Override
- public void objEntityAdded(ObjEntity entity) {
-
- }
-
- @Override
- public void objEntityRemoved(ObjEntity entity) {
-
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/loader/LoggingDbLoaderDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/LoggingDbLoaderDelegate.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/LoggingDbLoaderDelegate.java
deleted file mode 100644
index 8c77a87..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/LoggingDbLoaderDelegate.java
+++ /dev/null
@@ -1,76 +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.access.loader;
-
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.commons.logging.Log;
-
-/**
- * @since 4.0
- */
-public class LoggingDbLoaderDelegate extends DefaultDbLoaderDelegate {
-
- private final Log logger;
-
- public LoggingDbLoaderDelegate(Log logger) {
- this.logger = logger;
- }
-
- @Override
- public void dbEntityAdded(DbEntity entity) {
- logger.info(" Table: " + entity.getFullyQualifiedName());
- }
-
- @Override
- public void dbEntityRemoved(DbEntity entity) {
- logger.info(" Table removed: " + entity.getFullyQualifiedName());
- }
-
- @Override
- public boolean dbRelationship(DbEntity entity) {
- if (logger.isDebugEnabled()) {
- logger.debug(" Relationships for " + entity.getFullyQualifiedName());
- }
-
- return true;
- }
-
- @Override
- public boolean dbRelationshipLoaded(DbEntity entity, DbRelationship relationship) {
- logger.info(" " + relationship);
-
- return true;
- }
-
- @Override
- public void objEntityAdded(ObjEntity entity) {
- if (logger.isDebugEnabled()) {
- logger.debug(" Class: " + entity.getName());
- }
- }
-
- @Override
- public void objEntityRemoved(ObjEntity entity) {
- if (logger.isDebugEnabled()) {
- logger.debug(" Class removed: " + entity.getName());
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntity.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntity.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntity.java
deleted file mode 100644
index 6b93f19..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntity.java
+++ /dev/null
@@ -1,142 +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.access.loader;
-
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.map.ObjRelationship;
-import org.apache.cayenne.map.naming.DefaultUniqueNameGenerator;
-import org.apache.cayenne.map.naming.ExportedKey;
-import org.apache.cayenne.map.naming.NameCheckers;
-import org.apache.cayenne.map.naming.ObjectNameGenerator;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Class represent ObjEntity that may be optimized using flattened relationships
- * as many to many table
- */
-public class ManyToManyCandidateEntity {
-
- private static final Log LOG = LogFactory.getLog(ManyToManyCandidateEntity.class);
-
- private final ObjEntity joinEntity;
-
- private final DbRelationship dbRel1;
- private final DbRelationship dbRel2;
-
- private final ObjEntity entity1;
- private final ObjEntity entity2;
-
- private final DbRelationship reverseRelationship1;
- private final DbRelationship reverseRelationship2;
-
- private ManyToManyCandidateEntity(ObjEntity entityValue, List<ObjRelationship> relationships) {
- joinEntity = entityValue;
-
- ObjRelationship rel1 = relationships.get(0);
- ObjRelationship rel2 = relationships.get(1);
-
- dbRel1 = rel1.getDbRelationships().get(0);
- dbRel2 = rel2.getDbRelationships().get(0);
-
- reverseRelationship1 = dbRel1.getReverseRelationship();
- reverseRelationship2 = dbRel2.getReverseRelationship();
-
- entity1 = rel1.getTargetEntity();
- entity2 = rel2.getTargetEntity();
- }
-
- /**
- * Method check - if current entity represent many to many temporary table
- * @return true if current entity is represent many to many table; otherwise returns false
- */
- public static ManyToManyCandidateEntity build(ObjEntity joinEntity) {
- ArrayList<ObjRelationship> relationships = new ArrayList<ObjRelationship>(joinEntity.getRelationships());
- if (relationships.size() != 2 || (relationships.get(0).getDbRelationships().isEmpty() || relationships.get(1).getDbRelationships().isEmpty())) {
- return null;
- }
-
- ManyToManyCandidateEntity candidateEntity = new ManyToManyCandidateEntity(joinEntity, relationships);
- if (candidateEntity.isManyToMany()) {
- return candidateEntity;
- }
-
- return null;
- }
-
- private boolean isManyToMany() {
- boolean isNotHaveAttributes = joinEntity.getAttributes().size() == 0;
-
- return isNotHaveAttributes
- && reverseRelationship1 != null && reverseRelationship1.isToDependentPK()
- && reverseRelationship2 != null && reverseRelationship2.isToDependentPK()
- && entity1 != null && entity2 != null;
- }
-
- private void addFlattenedRelationship(ObjectNameGenerator nameGenerator, ObjEntity srcEntity, ObjEntity dstEntity,
- DbRelationship rel1, DbRelationship rel2) {
-
- if (rel1.getSourceAttributes().isEmpty() && rel2.getTargetAttributes().isEmpty()) {
- LOG.warn("Wrong call ManyToManyCandidateEntity.addFlattenedRelationship(... , " + srcEntity.getName()
- + ", " + dstEntity.getName() + ", ...)");
-
- return;
- }
-
- ExportedKey key = new ExportedKey(
- rel1.getSourceEntity().getName(),
- rel1.getSourceAttributes().iterator().next().getName(),
- null,
- rel2.getTargetEntity().getName(),
- rel2.getTargetAttributes().iterator().next().getName(),
- null,
- (short) 1);
-
- ObjRelationship newRelationship = new ObjRelationship();
- newRelationship.setName(DefaultUniqueNameGenerator.generate(NameCheckers.objRelationship, srcEntity,
- nameGenerator.createDbRelationshipName(key, true)));
-
- newRelationship.setSourceEntity(srcEntity);
- newRelationship.setTargetEntityName(dstEntity);
-
- newRelationship.addDbRelationship(rel1);
- newRelationship.addDbRelationship(rel2);
-
- srcEntity.addRelationship(newRelationship);
- }
-
- /**
- * Method make direct relationships between 2 entities and remove relationships to
- * many to many entity
- *
- * @param nameGenerator
- */
- public void optimizeRelationships(ObjectNameGenerator nameGenerator) {
- entity1.removeRelationship(reverseRelationship1.getName());
- entity2.removeRelationship(reverseRelationship2.getName());
-
- addFlattenedRelationship(nameGenerator, entity1, entity2, reverseRelationship1, dbRel2);
- addFlattenedRelationship(nameGenerator, entity2, entity1, reverseRelationship2, dbRel1);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/loader/NameFilter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/NameFilter.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/NameFilter.java
deleted file mode 100644
index b0269d4..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/NameFilter.java
+++ /dev/null
@@ -1,27 +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.access.loader;
-
-/**
- * @since 4.0.
- */
-public interface NameFilter {
-
- boolean isIncluded(String string);
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/loader/NamePatternMatcher.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/NamePatternMatcher.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/NamePatternMatcher.java
deleted file mode 100644
index 6faa7e4..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/NamePatternMatcher.java
+++ /dev/null
@@ -1,225 +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.access.loader;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-
-import org.apache.cayenne.util.CayenneMapEntry;
-import org.apache.commons.logging.Log;
-
-/**
- * Provides name pattern matching functionality.
- *
- * @since 1.2
- */
-public class NamePatternMatcher implements NameFilter {
-
- private static final String[] EMPTY_ARRAY = new String[0];
- private static final Pattern COMMA = Pattern.compile(",");
-
- private final Pattern[] itemIncludeFilters;
- private final Pattern[] itemExcludeFilters;
-
- public static NamePatternMatcher build(Log logger, String includePattern, String excludePattern) {
- return new NamePatternMatcher(createPatterns(logger, includePattern), createPatterns(logger, excludePattern));
- }
-
- public NamePatternMatcher(Pattern[] itemIncludeFilters, Pattern[] itemExcludeFilters) {
- this.itemIncludeFilters = itemIncludeFilters;
- this.itemExcludeFilters = itemExcludeFilters;
- }
-
- /**
- * Applies preconfigured list of filters to the list, removing entities that do not
- * pass the filter.
- *
- * @deprecated since 3.0 still used by AntDataPortDelegate, which itself should
- * probably be deprecated
- */
- @Deprecated
- public List<?> filter(List<?> items) {
- if (items == null || items.isEmpty()) {
- return items;
- }
-
- if (itemIncludeFilters.length == 0 && itemExcludeFilters.length == 0) {
- return items;
- }
-
- Iterator<?> it = items.iterator();
- while (it.hasNext()) {
- CayenneMapEntry entity = (CayenneMapEntry) it.next();
-
- if (!passedIncludeFilter(entity.getName())) {
- it.remove();
- continue;
- }
-
- if (!passedExcludeFilter(entity.getName())) {
- it.remove();
- }
- }
-
- return items;
- }
-
- /**
- * Returns an array of Patterns. Takes a comma-separated list of patterns, attempting
- * to convert them to the java.util.regex.Pattern syntax. E.g.
- * <p>
- * <code>"billing_*,user?"</code> will become an array of two expressions:
- * <p>
- * <code>^billing_.*$</code><br>
- * <code>^user.?$</code><br>
- */
- public static Pattern[] createPatterns(Log logger, String patternString) {
- if (patternString == null) {
- return new Pattern[0];
- }
- String[] patternStrings = tokenizePattern(patternString);
- List<Pattern> patterns = new ArrayList<Pattern>(patternStrings.length);
-
- for (String patternString1 : patternStrings) {
-
- // test the pattern
- try {
- patterns.add(Pattern.compile(patternString1));
- } catch (PatternSyntaxException e) {
-
- if (logger != null) {
- logger.warn("Ignoring invalid pattern [" + patternString1 + "], reason: " + e.getMessage());
- }
- }
- }
-
- return patterns.toArray(new Pattern[patterns.size()]);
- }
-
- /**
- * Returns an array of valid regular expressions. Takes a comma-separated list of
- * patterns, attempting to convert them to the java.util.regex.Pattern syntax. E.g.
- * <p>
- * <code>"billing_*,user?"</code> will become an array of two expressions:
- * <p>
- * <code>^billing_.*$</code><br>
- * <code>^user.?$</code><br>
- */
- public static String[] tokenizePattern(String pattern) {
- if (pattern == null || pattern.isEmpty()) {
- return EMPTY_ARRAY;
- }
-
- String[] patterns = COMMA.split(pattern);
- if (patterns.length == 0) {
- return EMPTY_ARRAY;
- }
-
- for (int i = 0; i < patterns.length; i++) {
- // convert * into regex syntax
- // e.g. abc*x becomes ^abc.*x$
- // or abc?x becomes ^abc.?x$
- patterns[i] = "^" + patterns[i].replaceAll("[*?]", ".$0") + "$";
- }
-
- return patterns;
- }
-
- /**
- * Returns true if a given object property satisfies the include/exclude patterns.
- *
- * @since 3.0
- */
- @Override
- public boolean isIncluded(String string) {
- return passedIncludeFilter(string) && passedExcludeFilter(string);
- }
-
- /**
- * Returns true if an object matches any one of the "include" patterns, or if there is
- * no "include" patterns defined.
- *
- * @since 3.0
- */
- private boolean passedIncludeFilter(String item) {
- if (itemIncludeFilters.length == 0) {
- return true;
- }
-
- for (Pattern itemIncludeFilter : itemIncludeFilters) {
- if (itemIncludeFilter.matcher(item).find()) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Returns true if an object does not match any one of the "exclude" patterns, or if
- * there is no "exclude" patterns defined.
- *
- * @since 3.0
- */
- private boolean passedExcludeFilter(String item) {
- if (itemExcludeFilters.length == 0) {
- return true;
- }
-
- for (Pattern itemExcludeFilter : itemExcludeFilters) {
- if (itemExcludeFilter.matcher(item).find()) {
- return false;
- }
- }
-
- return true;
- }
-
- public static String replaceWildcardInStringWithString(
- String wildcard,
- String pattern,
- String replacement) {
-
- if (pattern == null || wildcard == null) {
- return pattern;
- }
-
- StringBuilder buffer = new StringBuilder();
- int lastPos = 0;
- int wildCardPos = pattern.indexOf(wildcard);
- while (wildCardPos != -1) {
- if (lastPos != wildCardPos) {
- buffer.append(pattern.substring(lastPos, wildCardPos));
- }
- buffer.append(replacement);
- lastPos += wildCardPos + wildcard.length();
- wildCardPos = pattern.indexOf(wildcard, lastPos);
- }
-
- if (lastPos < pattern.length()) {
- buffer.append(pattern.substring(lastPos));
- }
-
- return buffer.toString();
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/CatalogFilter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/CatalogFilter.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/CatalogFilter.java
deleted file mode 100644
index 830c9c8..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/CatalogFilter.java
+++ /dev/null
@@ -1,62 +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.access.loader.filters;
-
-import java.util.Arrays;
-
-/**
-* @since 4.0.
-*/
-public class CatalogFilter {
- public final String name;
- public final SchemaFilter[] schemas;
-
- public CatalogFilter(String name, SchemaFilter... schemas) {
- if (schemas == null || schemas.length == 0) {
- throw new IllegalArgumentException("schemas(" + Arrays.toString(schemas) + ") can't be null or empty");
- }
-
- this.name = name;
- this.schemas = schemas;
- }
-
- public SchemaFilter getSchema(String schema) {
- for (SchemaFilter schemaFilter : schemas) {
- if (schemaFilter.name == null || schemaFilter.name.equals(schema)) {
- return schemaFilter;
- }
- }
-
- return null;
- }
-
- @Override
- public String toString() {
- return toString(new StringBuilder(), "").toString();
- }
-
- public StringBuilder toString(StringBuilder res, String prefix) {
- res.append(prefix).append("Catalog: ").append(name).append("\n");
- for (SchemaFilter schema : schemas) {
- schema.toString(res, prefix + " ");
- }
-
- return res;
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/FiltersConfig.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/FiltersConfig.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/FiltersConfig.java
deleted file mode 100644
index 7a6823e..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/FiltersConfig.java
+++ /dev/null
@@ -1,81 +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.access.loader.filters;
-
-import java.util.Arrays;
-
-/**
- * @since 4.0.
- */
-public class FiltersConfig {
-
- public final CatalogFilter[] catalogs;
-
- public FiltersConfig(CatalogFilter ... catalogs) {
- if (catalogs == null || catalogs.length == 0) {
- throw new IllegalArgumentException("catalogs(" + Arrays.toString(catalogs) + ") can't be null or empty");
- }
-
- this.catalogs = catalogs;
- }
-
- public PatternFilter proceduresFilter(String catalog, String schema) {
- return getSchemaFilter(catalog, schema).procedures;
- }
-
- public TableFilter tableFilter(String catalog, String schema) {
- return getSchemaFilter(catalog, schema).tables;
- }
-
- protected SchemaFilter getSchemaFilter(String catalog, String schema) {
- CatalogFilter catalogFilter = getCatalog(catalog);
- if (catalogFilter == null) {
- return null;
- }
-
- return catalogFilter.getSchema(schema);
- }
-
- protected CatalogFilter getCatalog(String catalog) {
- for (CatalogFilter catalogFilter : catalogs) {
- if (catalogFilter.name == null || catalogFilter.name.equals(catalog)) {
- return catalogFilter;
- }
- }
-
- return null;
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- for (CatalogFilter catalog : catalogs) {
- catalog.toString(builder, "");
- }
-
- return builder.toString();
- }
-
- public static FiltersConfig create(String catalog, String schema, TableFilter tableFilter, PatternFilter procedures) {
- return new FiltersConfig(
- new CatalogFilter(catalog,
- new SchemaFilter(schema, tableFilter, procedures)));
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/IncludeTableFilter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/IncludeTableFilter.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/IncludeTableFilter.java
deleted file mode 100644
index dcb144b..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/IncludeTableFilter.java
+++ /dev/null
@@ -1,71 +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.access.loader.filters;
-
-import java.util.regex.Pattern;
-
-/**
-* @since 4.0.
-*/
-public class IncludeTableFilter implements Comparable<IncludeTableFilter> {
- public final Pattern pattern;
-
- public final PatternFilter columnsFilter;
-
- public IncludeTableFilter(String pattern) {
- this(pattern, PatternFilter.INCLUDE_EVERYTHING);
- }
-
- public IncludeTableFilter(String pattern, PatternFilter columnsFilter) {
- this.pattern = PatternFilter.pattern(pattern);
- this.columnsFilter = columnsFilter;
- }
-
- public boolean isIncludeColumn (String name) {
- return columnsFilter.isInclude(name);
- }
-
- @Override
- public int compareTo(IncludeTableFilter o) {
- if (pattern == null && o.pattern == null) {
- return 0;
- } else if (pattern == null) {
- return 1;
- } else if (o.pattern == null) {
- return -1;
- } else {
- return pattern.pattern().compareTo(o.pattern.pattern());
- }
-
- }
-
-
- @Override
- public String toString() {
- return toString(new StringBuilder(), "").toString();
- }
-
- protected StringBuilder toString(StringBuilder res, String prefix) {
- res.append(prefix).append("Include: ").append(String.valueOf(pattern)).append(" Columns: ");
- columnsFilter.toString(res);
- res.append("\n");
-
- return res;
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/LegacyFilterConfigBridge.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/LegacyFilterConfigBridge.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/LegacyFilterConfigBridge.java
deleted file mode 100644
index 90545c6..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/LegacyFilterConfigBridge.java
+++ /dev/null
@@ -1,150 +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.access.loader.filters;
-
-import static org.apache.commons.lang.StringUtils.isBlank;
-
-/**
- * @since 4.0
- */
-public class LegacyFilterConfigBridge {
-
- private String catalog;
- private String schema;
-
- private String includeTableFilters;
- private String includeColumnFilters;
- private String includeProceduresFilters;
- private String excludeTableFilters;
- private String excludeColumnFilters;
- private String excludeProceduresFilters;
-
- private boolean loadProcedures;
-
- public LegacyFilterConfigBridge() {
- }
-
- public LegacyFilterConfigBridge catalog(String catalog) {
- this.catalog = catalog;
- return this;
- }
-
- public String catalog() {
- return catalog;
- }
-
- public LegacyFilterConfigBridge schema(String schema) {
- this.schema = schema;
- return this;
- }
-
- public String schema() {
- return schema;
- }
-
- public LegacyFilterConfigBridge includeTables(String tableFilters) {
- if (isBlank(tableFilters)) {
- return this;
- }
-
- this.includeTableFilters = transform(tableFilters);
- return this;
- }
-
- public LegacyFilterConfigBridge includeColumns(String columnFilters) {
- if (isBlank(columnFilters)) {
- return this;
- }
-
- this.includeColumnFilters = transform(columnFilters);
- return this;
- }
-
- public LegacyFilterConfigBridge includeProcedures(String proceduresFilters) {
- if (isBlank(proceduresFilters)) {
- return this;
- }
-
- this.includeProceduresFilters = transform(proceduresFilters);
- return this;
- }
-
- public LegacyFilterConfigBridge excludeTables(String tableFilters) {
- if (isBlank(tableFilters)) {
- return this;
- }
-
- this.excludeTableFilters = transform(tableFilters);
- return this;
- }
-
- public LegacyFilterConfigBridge excludeColumns(String columnFilters) {
- if (isBlank(columnFilters)) {
- return this;
- }
-
- this.excludeColumnFilters = transform(columnFilters);
- return this;
- }
-
- public LegacyFilterConfigBridge excludeProcedures(String proceduresFilters) {
- if (isBlank(proceduresFilters)) {
- return this;
- }
-
- this.excludeProceduresFilters = transform(proceduresFilters);
- return this;
- }
-
- private static String transform(String pattern) {
- return "^" + pattern.replaceAll("[*?]", ".$0") + "$";
- }
-
- public void setProceduresFilters(boolean loadProcedures) {
- this.loadProcedures = loadProcedures;
- }
-
- public String getIncludeTableFilters() {
- return includeTableFilters;
- }
-
- public String getIncludeColumnFilters() {
- return includeColumnFilters;
- }
-
- public String getIncludeProceduresFilters() {
- return includeProceduresFilters;
- }
-
- public String getExcludeTableFilters() {
- return excludeTableFilters;
- }
-
- public String getExcludeColumnFilters() {
- return excludeColumnFilters;
- }
-
- public String getExcludeProceduresFilters() {
- return excludeProceduresFilters;
- }
-
- public boolean isLoadProcedures() {
- return loadProcedures;
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/PatternFilter.java
----------------------------------------------------------------------
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
deleted file mode 100644
index 82c45cc..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/PatternFilter.java
+++ /dev/null
@@ -1,169 +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.access.loader.filters;
-
-import org.apache.commons.lang.StringUtils;
-
-import java.util.Comparator;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import java.util.regex.Pattern;
-
-/**
- * @since 4.0
- */
-public class PatternFilter {
-
- public static final PatternFilter INCLUDE_EVERYTHING = new PatternFilter() {
-
- @Override
- public boolean isInclude(String obj) {
- return true;
- }
-
- @Override
- public StringBuilder toString(StringBuilder res) {
- return res.append("ALL");
- }
- };
-
- public static final PatternFilter INCLUDE_NOTHING = new PatternFilter() {
- @Override
- public boolean isInclude(String obj) {
- return false;
- }
-
- @Override
- public StringBuilder toString(StringBuilder res) {
- return res.append("NONE");
- }
- };
-
- public static final Comparator<Pattern> PATTERN_COMPARATOR = new Comparator<Pattern>() {
- @Override
- public int compare(Pattern o1, Pattern o2) {
- if (o1 != null && o2 != null) {
- return o1.pattern().compareTo(o2.pattern());
- }
- else {
- return -1;
- }
- }
- };
-
- private final SortedSet<Pattern> includes;
- private final SortedSet<Pattern> excludes;
-
- public PatternFilter() {
- this.includes = new TreeSet<>(PATTERN_COMPARATOR);
- this.excludes = new TreeSet<>(PATTERN_COMPARATOR);
- }
-
- public PatternFilter include(Pattern p) {
- includes.add(p);
-
- return this;
- }
-
- public PatternFilter exclude(Pattern p) {
- excludes.add(p);
-
- return this;
- }
-
- public static Pattern pattern(String pattern) {
- if (pattern == null) {
- return null;
- }
- return Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
- }
-
- public PatternFilter include(String p) {
- return include(pattern(p));
- }
-
- public PatternFilter exclude(String p) {
- return exclude(pattern(p));
- }
-
- public boolean isInclude(String obj) {
- boolean include = includes.isEmpty();
- for (Pattern p : includes) {
- if (p != null) {
- if (p.matcher(obj).matches()) {
- include = true;
- break;
- }
- }
- }
-
- if (!include) {
- return false;
- }
-
- for (Pattern p : excludes) {
- if (p.matcher(obj).matches()) {
- return false;
- }
- }
-
- return true;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
-
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
-
-
- PatternFilter filter = (PatternFilter) o;
- return includes.equals(filter.includes)
- && excludes.equals(filter.excludes);
- }
-
- @Override
- public int hashCode() {
- return includes.hashCode();
- }
-
- public StringBuilder toString(StringBuilder res) {
- if (includes.isEmpty()) {
- // Do nothing.
- } else if (includes.size() > 1) {
- res.append("(").append(StringUtils.join(includes, " OR ")).append(")");
- } else {
- res.append(includes.first().pattern());
- }
-
- if (!excludes.isEmpty()) {
- res.append(" AND NOT (").append(StringUtils.join(includes, " OR ")).append(")");
- }
-
- return res;
- }
-
- public boolean isEmpty() {
- return includes.isEmpty() && excludes.isEmpty();
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/SchemaFilter.java
----------------------------------------------------------------------
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
deleted file mode 100644
index c294bc4..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/SchemaFilter.java
+++ /dev/null
@@ -1,44 +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.access.loader.filters;
-
-/**
-* @since 4.0.
-*/
-public class SchemaFilter {
- public final String name;
- public final TableFilter tables;
- public final PatternFilter procedures;
-
- public SchemaFilter(String name, TableFilter tables, PatternFilter procedures) {
- this.name = name;
- this.tables = tables;
- this.procedures = procedures;
- }
-
- protected StringBuilder toString(StringBuilder res, String prefix) {
- res.append(prefix).append("Schema: ").append(name).append("\n");
- tables.toString(res, prefix + " ");
-
- res.append(prefix).append(" Procedures: ");
- procedures.toString(res).append("\n");
-
- return res;
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/TableFilter.java
----------------------------------------------------------------------
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
deleted file mode 100644
index 7d3c8f6..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/TableFilter.java
+++ /dev/null
@@ -1,133 +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.access.loader.filters;
-
-import org.apache.commons.lang.StringUtils;
-
-import java.util.SortedSet;
-import java.util.TreeSet;
-import java.util.regex.Pattern;
-
-/**
- * TableFilter contain at least one IncludeTable always
- *
- */
-public class TableFilter {
-
- private final SortedSet<IncludeTableFilter> includes;
- private final SortedSet<Pattern> excludes;
-
- /**
- * Includes can contain only One includetable
- *
- * @param includes
- * @param excludes
- */
- public TableFilter(SortedSet<IncludeTableFilter> includes, SortedSet<Pattern> excludes) {
- if (includes.isEmpty()) {
- throw new IllegalArgumentException("TableFilter should contain at least one IncludeTableFilter always " +
- "and it is builder responsibility. If you need table filter without includes, use EmptyTableFilter");
- }
-
- this.includes = includes;
- this.excludes = excludes;
- }
-
- /**
- * Return filter for columns in case we should take this table
- *
- * @param tableName
- * @return
- */
- public PatternFilter isIncludeTable(String tableName) {
- IncludeTableFilter include = null;
- for (IncludeTableFilter p : includes) {
- if (p.pattern == null || p.pattern.matcher(tableName).matches()) {
- include = p;
- break;
- }
- }
-
- if (include == null) {
- return null;
- }
-
- for (Pattern p : excludes) {
- if (p != null) {
- if (p.matcher(tableName).matches()) {
- return null;
- }
- }
- }
-
- return include.columnsFilter;
- }
-
- public static TableFilter include(String tablePattern) {
- TreeSet<IncludeTableFilter> includes = new TreeSet<IncludeTableFilter>();
- includes.add(new IncludeTableFilter(tablePattern == null ? null : tablePattern.replaceAll("%", ".*")));
-
- return new TableFilter(includes, new TreeSet<Pattern>());
- }
-
- public static TableFilter everything() {
- TreeSet<IncludeTableFilter> includes = new TreeSet<IncludeTableFilter>();
- includes.add(new IncludeTableFilter(null));
-
- return new TableFilter(includes, new TreeSet<Pattern>());
- }
-
- protected StringBuilder toString(StringBuilder res, String prefix) {
- res.append(prefix).append("Tables: ").append("\n");
-
- for (IncludeTableFilter include : includes) {
- include.toString(res, prefix + " ");
- }
-
- if (!excludes.isEmpty()) {
- res.append(prefix).append(" ").append(StringUtils.join(excludes, " OR ")).append("\n");
- }
-
- return res;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
-
- if (!(o instanceof TableFilter)) {
- return false;
- }
-
- TableFilter that = (TableFilter) o;
-
- return excludes.equals(that.excludes)
- && includes.equals(that.includes);
-
- }
-
- @Override
- public int hashCode() {
- int result = includes.hashCode();
- result = 31 * result + excludes.hashCode();
- return result;
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/DbType.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/DbType.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/DbType.java
deleted file mode 100644
index 806b437..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/DbType.java
+++ /dev/null
@@ -1,194 +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.access.loader.mapper;
-
-import org.apache.cayenne.util.EqualsBuilder;
-import org.apache.cayenne.util.HashCodeBuilder;
-import org.apache.commons.lang.builder.CompareToBuilder;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import static org.apache.commons.lang.StringUtils.isBlank;
-
-/**
- * @since 4.0
- */
-public class DbType implements Comparable<DbType> {
-
- private static final Log LOG = LogFactory.getLog(DbType.class);
-
- public final String jdbc;
-
- public final Integer length;
- public final Integer precision;
- public final Integer scale;
- public final Boolean notNull;
-
- public DbType(String jdbc) {
- this(jdbc, null, null, null, null);
- }
-
- public DbType(String jdbc, Integer length, Integer precision, Integer scale, Boolean notNull) {
- if (isBlank(jdbc)) {
- throw new IllegalArgumentException("Jdbc type can't be null");
- }
- this.jdbc = jdbc;
-
- this.length = getValidInt(length);
- this.precision = getValidInt(precision);
- this.scale = getValidInt(scale);
- this.notNull = notNull;
- }
-
- public String getJdbc() {
- return jdbc;
- }
-
- public Integer getLength() {
- return length;
- }
-
- public Integer getPrecision() {
- return precision;
- }
-
- public Integer getScale() {
- return scale;
- }
-
- public Boolean getNotNull() {
- return notNull;
- }
-
-
- @Override
- public boolean equals(Object obj) {
- if (obj == null) {
- return false;
- }
- if (obj == this) {
- return true;
- }
- if (obj.getClass() != getClass()) {
- return false;
- }
- DbType rhs = (DbType) obj;
- return new EqualsBuilder()
- .append(this.jdbc, rhs.jdbc)
- .append(this.length, rhs.length)
- .append(this.precision, rhs.precision)
- .append(this.scale, rhs.scale)
- .append(this.notNull, rhs.notNull)
- .isEquals();
- }
-
- @Override
- public int hashCode() {
- return new HashCodeBuilder()
- .append(jdbc)
- .append(length)
- .append(precision)
- .append(scale)
- .append(notNull)
- .toHashCode();
- }
-
-
- @Override
- public String toString() {
- String res = jdbc;
-
- String len = "*";
- if (isPositive(length)) {
- len = length.toString();
- }
- if (isPositive(precision)) {
- len = precision.toString();
- }
-
- res += " (" + len;
- if (isPositive(scale)) {
- res += ", " + scale;
- }
- res += ")";
-
- if (notNull != null && notNull) {
- res += " NOT NULL";
- }
-
- return res;
- }
-
- private boolean isPositive(Integer num) {
- return num != null && num > 0;
- }
-
- private Integer getValidInt(Integer num) {
- if (num == null || num > 0) {
- return num;
- }
-
- LOG.warn("Invalid int value '" + num + "'");
- return null;
- }
-
- /**
- * Compare by specificity the most specific DbPath should be first in ordered list
- */
- @Override
- public int compareTo(DbType dbType) {
- return new CompareToBuilder()
- .append(dbType.jdbc, jdbc)
- .append(dbType.getSpecificity(), getSpecificity())
- .append(dbType.length, length)
- .append(dbType.precision, precision)
- .append(dbType.scale, scale)
- .append(dbType.notNull, notNull)
- .toComparison();
- }
-
- private int getSpecificity() {
- int res = 0;
- if (isPositive(length)) {
- res += 100;
- }
- if (isPositive(precision)) {
- res += 100;
- }
- if (isPositive(scale)) {
- res += 10;
- }
- if (this.notNull != null) {
- res += 5;
- }
-
- return res;
- }
-
- public boolean isCover(DbType type) {
- return this.jdbc.equals(type.jdbc)
- && (isCover(length, type.length) || length == null && type.length == null && isCover(precision, type.precision))
- && isCover(scale, type.scale)
- && isCover(notNull, type.notNull);
- }
-
- private boolean isCover(Object a, Object b) {
- return a == null || a.equals(b);
- }
-}
[15/15] cayenne git commit: CAY-2116 Split schema synchronization
code in a separate module
Posted by aa...@apache.org.
CAY-2116 Split schema synchronization code in a separate module
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/2f7b1d53
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/2f7b1d53
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/2f7b1d53
Branch: refs/heads/master
Commit: 2f7b1d53388883a2e341e9156bddd8d694f7ef88
Parents: 8c7bec0
Author: Andrus Adamchik <an...@objectstyle.com>
Authored: Thu Sep 29 20:33:54 2016 +0300
Committer: Andrus Adamchik <an...@objectstyle.com>
Committed: Thu Sep 29 20:38:29 2016 +0300
----------------------------------------------------------------------
assembly/pom.xml | 6 +
.../resources/assemblies/assembly-generic.xml | 1 +
.../main/resources/assemblies/assembly-mac.xml | 1 +
.../resources/assemblies/assembly-windows.xml | 1 +
cayenne-dbsync/pom.xml | 117 +++
.../cayenne/dbsync/CayenneDbSyncModule.java | 82 ++
.../cayenne/dbsync/merge/AbstractToDbToken.java | 126 +++
.../dbsync/merge/AbstractToModelToken.java | 122 +++
.../cayenne/dbsync/merge/AddColumnToDb.java | 65 ++
.../cayenne/dbsync/merge/AddColumnToModel.java | 55 ++
.../dbsync/merge/AddRelationshipToDb.java | 87 ++
.../dbsync/merge/AddRelationshipToModel.java | 95 +++
.../cayenne/dbsync/merge/CreateTableToDb.java | 66 ++
.../dbsync/merge/CreateTableToModel.java | 102 +++
.../apache/cayenne/dbsync/merge/DbMerger.java | 405 +++++++++
.../cayenne/dbsync/merge/DbMergerConfig.java | 63 ++
.../dbsync/merge/DefaultModelMergeDelegate.java | 89 ++
.../merge/DefaultValueForNullProvider.java | 62 ++
.../cayenne/dbsync/merge/DropColumnToDb.java | 52 ++
.../cayenne/dbsync/merge/DropColumnToModel.java | 75 ++
.../dbsync/merge/DropRelationshipToDb.java | 72 ++
.../dbsync/merge/DropRelationshipToModel.java | 51 ++
.../cayenne/dbsync/merge/DropTableToDb.java | 50 ++
.../cayenne/dbsync/merge/DropTableToModel.java | 49 ++
.../cayenne/dbsync/merge/DummyReverseToken.java | 60 ++
.../dbsync/merge/EmptyValueForNullProvider.java | 40 +
.../dbsync/merge/EntityMergeSupport.java | 522 ++++++++++++
.../cayenne/dbsync/merge/MergeDirection.java | 70 ++
.../cayenne/dbsync/merge/MergerContext.java | 118 +++
.../cayenne/dbsync/merge/MergerToken.java | 53 ++
.../dbsync/merge/ModelMergeDelegate.java | 62 ++
.../dbsync/merge/ProxyModelMergeDelegate.java | 108 +++
.../cayenne/dbsync/merge/SetAllowNullToDb.java | 57 ++
.../dbsync/merge/SetAllowNullToModel.java | 43 +
.../cayenne/dbsync/merge/SetColumnTypeToDb.java | 119 +++
.../dbsync/merge/SetColumnTypeToModel.java | 102 +++
.../cayenne/dbsync/merge/SetNotNullToDb.java | 51 ++
.../cayenne/dbsync/merge/SetNotNullToModel.java | 43 +
.../cayenne/dbsync/merge/SetPrimaryKeyToDb.java | 86 ++
.../dbsync/merge/SetPrimaryKeyToModel.java | 78 ++
.../dbsync/merge/SetValueForNullToDb.java | 47 ++
.../dbsync/merge/ValueForNullProvider.java | 42 +
.../merge/factory/DB2MergerTokenFactory.java | 47 ++
.../factory/DefaultMergerTokenFactory.java | 181 ++++
.../merge/factory/DerbyMergerTokenFactory.java | 85 ++
.../factory/FirebirdMergerTokenFactory.java | 91 ++
.../merge/factory/H2MergerTokenFactory.java | 82 ++
.../merge/factory/HSQLMergerTokenFactory.java | 82 ++
.../merge/factory/IngresMergerTokenFactory.java | 224 +++++
.../merge/factory/MergerTokenFactory.java | 88 ++
.../factory/MergerTokenFactoryProvider.java | 36 +
.../merge/factory/MySQLMergerTokenFactory.java | 156 ++++
.../factory/OpenBaseMergerTokenFactory.java | 143 ++++
.../merge/factory/OracleMergerTokenFactory.java | 111 +++
.../factory/PostgresMergerTokenFactory.java | 49 ++
.../factory/SQLServerMergerTokenFactory.java | 112 +++
.../merge/factory/SybaseMergerTokenFactory.java | 166 ++++
.../dbsync/reverse/DbAttributesBaseLoader.java | 107 +++
.../dbsync/reverse/DbAttributesLoader.java | 43 +
.../reverse/DbAttributesPerSchemaLoader.java | 130 +++
.../apache/cayenne/dbsync/reverse/DbLoader.java | 829 ++++++++++++++++++
.../dbsync/reverse/DbLoaderConfiguration.java | 150 ++++
.../dbsync/reverse/DbLoaderDelegate.java | 58 ++
.../cayenne/dbsync/reverse/DbTableLoader.java | 195 +++++
.../dbsync/reverse/DefaultDbLoaderDelegate.java | 59 ++
.../dbsync/reverse/FiltersConfigBuilder.java | 393 +++++++++
.../dbsync/reverse/LoggingDbLoaderDelegate.java | 76 ++
.../reverse/ManyToManyCandidateEntity.java | 142 ++++
.../cayenne/dbsync/reverse/NameFilter.java | 27 +
.../dbsync/reverse/NamePatternMatcher.java | 225 +++++
.../dbsync/reverse/filters/CatalogFilter.java | 62 ++
.../dbsync/reverse/filters/FiltersConfig.java | 81 ++
.../reverse/filters/IncludeTableFilter.java | 71 ++
.../filters/LegacyFilterConfigBridge.java | 150 ++++
.../dbsync/reverse/filters/PatternFilter.java | 169 ++++
.../dbsync/reverse/filters/SchemaFilter.java | 44 +
.../dbsync/reverse/filters/TableFilter.java | 133 +++
.../cayenne/dbsync/reverse/mapper/DbType.java | 194 +++++
.../mapper/DefaultJdbc2JavaTypeMapper.java | 282 +++++++
.../reverse/mapper/Jdbc2JavaTypeMapper.java | 33 +
.../dbsync/merge/AddColumnToModelIT.java | 98 +++
.../dbsync/merge/CreateTableToModelIT.java | 97 +++
.../cayenne/dbsync/merge/DbMergerTest.java | 261 ++++++
.../dbsync/merge/DropColumnToModelIT.java | 235 ++++++
.../dbsync/merge/DropRelationshipToModelIT.java | 188 +++++
.../dbsync/merge/DropTableToModelIT.java | 94 +++
.../dbsync/merge/EntityMergeSupportIT.java | 102 +++
.../apache/cayenne/dbsync/merge/MergeCase.java | 209 +++++
.../cayenne/dbsync/merge/MergerFactoryIT.java | 310 +++++++
.../dbsync/merge/SetAllowNullToDbIT.java | 66 ++
.../cayenne/dbsync/merge/SetNotNullToDbIT.java | 62 ++
.../dbsync/merge/SetPrimaryKeyToDbIT.java | 58 ++
.../cayenne/dbsync/merge/TokensReversTest.java | 89 ++
.../merge/TokensToModelExecutionTest.java | 80 ++
.../cayenne/dbsync/merge/ValueForNullIT.java | 127 +++
.../cayenne/dbsync/merge/builders/Builder.java | 38 +
.../dbsync/merge/builders/DataMapBuilder.java | 128 +++
.../merge/builders/DbAttributeBuilder.java | 115 +++
.../dbsync/merge/builders/DbEntityBuilder.java | 90 ++
.../merge/builders/DbRelationshipBuilder.java | 85 ++
.../dbsync/merge/builders/DefaultBuilder.java | 57 ++
.../merge/builders/ObjAttributeBuilder.java | 67 ++
.../dbsync/merge/builders/ObjEntityBuilder.java | 98 +++
.../dbsync/merge/builders/ObjectMother.java | 70 ++
.../cayenne/dbsync/reverse/DbLoaderIT.java | 430 ++++++++++
.../dbsync/reverse/DbLoaderPartialIT.java | 116 +++
.../reverse/FiltersConfigBuilderTest.java | 391 +++++++++
.../reverse/ManyToManyCandidateEntityTest.java | 113 +++
.../reverse/filters/FiltersConfigTest.java | 93 +++
.../reverse/filters/IncludeFilterTest.java | 34 +
.../reverse/filters/PatternFilterTest.java | 78 ++
.../dbsync/reverse/filters/TableFilterTest.java | 91 ++
.../dbsync/reverse/mapper/DbTypeTest.java | 87 ++
.../apache/cayenne/dbsync/unit/DbSyncCase.java | 57 ++
.../cayenne/dbsync/unit/DbSyncCaseModule.java | 38 +
.../unit/DbSyncServerRuntimeProvider.java | 50 ++
.../cayenne-relationship-optimisation.xml | 4 +
.../reverse/relationship-optimisation.map.xml | 43 +
.../org/apache/cayenne/access/DbLoader.java | 832 -------------------
.../apache/cayenne/access/DbLoaderDelegate.java | 58 --
.../access/loader/DbAttributesBaseLoader.java | 107 ---
.../access/loader/DbAttributesLoader.java | 43 -
.../loader/DbAttributesPerSchemaLoader.java | 130 ---
.../access/loader/DbLoaderConfiguration.java | 150 ----
.../cayenne/access/loader/DbTableLoader.java | 196 -----
.../access/loader/DefaultDbLoaderDelegate.java | 60 --
.../access/loader/LoggingDbLoaderDelegate.java | 76 --
.../loader/ManyToManyCandidateEntity.java | 142 ----
.../cayenne/access/loader/NameFilter.java | 27 -
.../access/loader/NamePatternMatcher.java | 225 -----
.../access/loader/filters/CatalogFilter.java | 62 --
.../access/loader/filters/FiltersConfig.java | 81 --
.../loader/filters/IncludeTableFilter.java | 71 --
.../filters/LegacyFilterConfigBridge.java | 150 ----
.../access/loader/filters/PatternFilter.java | 169 ----
.../access/loader/filters/SchemaFilter.java | 44 -
.../access/loader/filters/TableFilter.java | 133 ---
.../cayenne/access/loader/mapper/DbType.java | 194 -----
.../mapper/DefaultJdbc2JavaTypeMapper.java | 282 -------
.../loader/mapper/Jdbc2JavaTypeMapper.java | 33 -
.../org/apache/cayenne/dba/AutoAdapter.java | 6 -
.../java/org/apache/cayenne/dba/DbAdapter.java | 6 -
.../org/apache/cayenne/dba/JdbcAdapter.java | 14 +-
.../apache/cayenne/dba/PerAdapterProvider.java | 46 +
.../org/apache/cayenne/dba/db2/DB2Adapter.java | 13 +-
.../cayenne/dba/db2/DB2MergerFactory.java | 49 --
.../apache/cayenne/dba/derby/DerbyAdapter.java | 36 +-
.../cayenne/dba/derby/DerbyMergerFactory.java | 86 --
.../cayenne/dba/firebird/FirebirdAdapter.java | 6 +-
.../dba/firebird/FirebirdMergerFactory.java | 91 --
.../org/apache/cayenne/dba/h2/H2Adapter.java | 6 -
.../apache/cayenne/dba/h2/H2MergerFactory.java | 83 --
.../cayenne/dba/hsqldb/HSQLDBAdapter.java | 7 -
.../cayenne/dba/hsqldb/HSQLMergerFactory.java | 83 --
.../cayenne/dba/ingres/IngresAdapter.java | 6 -
.../cayenne/dba/ingres/IngresMergerFactory.java | 226 -----
.../apache/cayenne/dba/mysql/MySQLAdapter.java | 26 +-
.../cayenne/dba/mysql/MySQLMergerFactory.java | 157 ----
.../cayenne/dba/openbase/OpenBaseAdapter.java | 469 +++++------
.../dba/openbase/OpenBaseMergerFactory.java | 144 ----
.../cayenne/dba/oracle/OracleAdapter.java | 25 +-
.../cayenne/dba/oracle/OracleMergerFactory.java | 112 ---
.../cayenne/dba/postgres/PostgresAdapter.java | 6 -
.../dba/postgres/PostgresMergerFactory.java | 50 --
.../cayenne/dba/sqlserver/SQLServerAdapter.java | 6 -
.../dba/sqlserver/SQLServerMergerFactory.java | 114 ---
.../cayenne/dba/sybase/SybaseAdapter.java | 14 +-
.../cayenne/dba/sybase/SybaseMergerFactory.java | 167 ----
.../cayenne/dbimport/FiltersConfigBuilder.java | 383 ---------
.../apache/cayenne/merge/AbstractToDbToken.java | 126 ---
.../cayenne/merge/AbstractToModelToken.java | 122 ---
.../org/apache/cayenne/merge/AddColumnToDb.java | 64 --
.../apache/cayenne/merge/AddColumnToModel.java | 55 --
.../cayenne/merge/AddRelationshipToDb.java | 86 --
.../cayenne/merge/AddRelationshipToModel.java | 95 ---
.../apache/cayenne/merge/CreateTableToDb.java | 65 --
.../cayenne/merge/CreateTableToModel.java | 102 ---
.../java/org/apache/cayenne/merge/DbMerger.java | 405 ---------
.../apache/cayenne/merge/DbMergerConfig.java | 63 --
.../merge/DefaultModelMergeDelegate.java | 89 --
.../merge/DefaultValueForNullProvider.java | 62 --
.../apache/cayenne/merge/DropColumnToDb.java | 51 --
.../apache/cayenne/merge/DropColumnToModel.java | 74 --
.../cayenne/merge/DropRelationshipToDb.java | 71 --
.../cayenne/merge/DropRelationshipToModel.java | 50 --
.../org/apache/cayenne/merge/DropTableToDb.java | 49 --
.../apache/cayenne/merge/DropTableToModel.java | 48 --
.../apache/cayenne/merge/DummyReverseToken.java | 58 --
.../merge/EmptyValueForNullProvider.java | 40 -
.../apache/cayenne/merge/MergeDirection.java | 70 --
.../org/apache/cayenne/merge/MergerContext.java | 118 ---
.../org/apache/cayenne/merge/MergerFactory.java | 142 ----
.../org/apache/cayenne/merge/MergerToken.java | 51 --
.../cayenne/merge/ModelMergeDelegate.java | 65 --
.../cayenne/merge/ProxyModelMergeDelegate.java | 108 ---
.../apache/cayenne/merge/SetAllowNullToDb.java | 56 --
.../cayenne/merge/SetAllowNullToModel.java | 42 -
.../apache/cayenne/merge/SetColumnTypeToDb.java | 119 ---
.../cayenne/merge/SetColumnTypeToModel.java | 101 ---
.../apache/cayenne/merge/SetNotNullToDb.java | 50 --
.../apache/cayenne/merge/SetNotNullToModel.java | 42 -
.../apache/cayenne/merge/SetPrimaryKeyToDb.java | 85 --
.../cayenne/merge/SetPrimaryKeyToModel.java | 77 --
.../cayenne/merge/SetValueForNullToDb.java | 46 -
.../cayenne/merge/ValueForNullProvider.java | 42 -
.../apache/cayenne/util/EntityMergeSupport.java | 520 ------------
.../org/apache/cayenne/access/DbLoaderIT.java | 431 ----------
.../cayenne/access/DbLoaderPartialIT.java | 118 ---
.../loader/ManyToManyCandidateEntityTest.java | 113 ---
.../loader/filters/FiltersConfigTest.java | 93 ---
.../loader/filters/IncludeFilterTest.java | 34 -
.../loader/filters/PatternFilterTest.java | 78 --
.../access/loader/filters/TableFilterTest.java | 91 --
.../access/loader/mapper/DbTypeTest.java | 87 --
.../cayenne/dba/PerAdapterProviderTest.java | 83 ++
.../dbimport/FiltersConfigBuilderTest.java | 382 ---------
.../cayenne/merge/AddColumnToModelIT.java | 98 ---
.../cayenne/merge/CreateTableToModelIT.java | 97 ---
.../org/apache/cayenne/merge/DbMergerTest.java | 261 ------
.../cayenne/merge/DropColumnToModelIT.java | 235 ------
.../merge/DropRelationshipToModelIT.java | 188 -----
.../cayenne/merge/DropTableToModelIT.java | 94 ---
.../org/apache/cayenne/merge/MergeCase.java | 215 -----
.../apache/cayenne/merge/MergerFactoryIT.java | 310 -------
.../cayenne/merge/SetAllowNullToDbIT.java | 66 --
.../apache/cayenne/merge/SetNotNullToDbIT.java | 62 --
.../cayenne/merge/SetPrimaryKeyToDbIT.java | 58 --
.../apache/cayenne/merge/TokensReversTest.java | 88 --
.../cayenne/merge/TokensToModelExecution.java | 83 --
.../apache/cayenne/merge/ValueForNullIT.java | 128 ---
.../apache/cayenne/merge/builders/Builder.java | 38 -
.../cayenne/merge/builders/DataMapBuilder.java | 128 ---
.../merge/builders/DbAttributeBuilder.java | 115 ---
.../cayenne/merge/builders/DbEntityBuilder.java | 90 --
.../merge/builders/DbRelationshipBuilder.java | 85 --
.../cayenne/merge/builders/DefaultBuilder.java | 57 --
.../merge/builders/ObjAttributeBuilder.java | 67 --
.../merge/builders/ObjEntityBuilder.java | 98 ---
.../cayenne/merge/builders/ObjectMother.java | 70 --
.../unit/di/server/ServerRuntimeProvider.java | 13 +-
.../cayenne/util/EntityMergeSupportIT.java | 103 ---
.../cayenne-relationship-optimisation.xml | 4 -
.../loader/relationship-optimisation.map.xml | 43 -
cayenne-tools/pom.xml | 14 +
.../cayenne/gen/ClassGenerationAction.java | 22 +-
.../cayenne/tools/AntDataPortDelegate.java | 10 +-
.../CayenneGeneratorEntityFilterAction.java | 10 +-
.../cayenne/tools/CayenneGeneratorTask.java | 2 +-
.../apache/cayenne/tools/DbGeneratorTask.java | 9 +-
.../apache/cayenne/tools/DbImporterTask.java | 9 +-
.../tools/dbimport/DbImportConfiguration.java | 27 +-
.../dbimport/DbImportDbLoaderDelegate.java | 2 +-
.../cayenne/tools/dbimport/DbImportModule.java | 4 +-
.../tools/dbimport/DefaultDbImportAction.java | 34 +-
.../config/DefaultTypeMapperBuilder.java | 6 +-
.../cayenne/tools/NamePatternMatcherTest.java | 8 +-
.../tools/dbimport/DbImportModuleTest.java | 3 +-
.../dbimport/DefaultDbImportActionTest.java | 40 +-
docs/doc/src/main/resources/RELEASE-NOTES.txt | 1 +
.../java/org/apache/cayenne/modeler/Main.java | 17 +-
.../modeler/action/CreateObjEntityAction.java | 6 +-
.../modeler/action/DbEntitySyncAction.java | 8 +-
.../cayenne/modeler/action/MigrateAction.java | 72 +-
.../modeler/action/ObjEntitySyncAction.java | 13 +-
.../modeler/dialog/db/DbLoaderHelper.java | 16 +-
.../modeler/dialog/db/MergerOptions.java | 67 +-
.../db/MergerTokenSelectorController.java | 40 +-
.../dialog/db/MergerTokenTableModel.java | 6 +-
.../dialog/db/ModelerDbImportAction.java | 6 +-
.../dialog/db/ReverseEngineeringController.java | 17 +-
.../dialog/objentity/EntitySyncController.java | 15 +-
.../cayenne/tools/CayenneGeneratorMojo.java | 2 +-
.../apache/cayenne/tools/DbGeneratorMojo.java | 9 +-
.../apache/cayenne/tools/DbImporterMojo.java | 21 +-
.../tools/DbImporterMojoConfigurationTest.java | 8 +-
pom.xml | 1 +
276 files changed, 14069 insertions(+), 13421 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/assembly/pom.xml
----------------------------------------------------------------------
diff --git a/assembly/pom.xml b/assembly/pom.xml
index 6b7f423..45c042e 100644
--- a/assembly/pom.xml
+++ b/assembly/pom.xml
@@ -50,6 +50,12 @@
<dependency>
<groupId>org.apache.cayenne</groupId>
+ <artifactId>cayenne-dbsync</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.cayenne</groupId>
<artifactId>cayenne-tools</artifactId>
<version>${project.version}</version>
</dependency>
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/assembly/src/main/resources/assemblies/assembly-generic.xml
----------------------------------------------------------------------
diff --git a/assembly/src/main/resources/assemblies/assembly-generic.xml b/assembly/src/main/resources/assemblies/assembly-generic.xml
index 4414219..5eb4a62 100644
--- a/assembly/src/main/resources/assemblies/assembly-generic.xml
+++ b/assembly/src/main/resources/assemblies/assembly-generic.xml
@@ -80,6 +80,7 @@
<include>org.apache.cayenne:cayenne-lifecycle</include>
<include>org.apache.cayenne:cayenne-project</include>
<include>org.apache.cayenne:cayenne-server</include>
+ <include>org.apache.cayenne:cayenne-dbsync</include>
<include>org.apache.cayenne:cayenne-tools</include>
<include>org.apache.cayenne:cayenne-dbcp2</include>
<include>org.apache.cayenne:cayenne-java8</include>
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/assembly/src/main/resources/assemblies/assembly-mac.xml
----------------------------------------------------------------------
diff --git a/assembly/src/main/resources/assemblies/assembly-mac.xml b/assembly/src/main/resources/assemblies/assembly-mac.xml
index 05a4d1f..11e3546 100644
--- a/assembly/src/main/resources/assemblies/assembly-mac.xml
+++ b/assembly/src/main/resources/assemblies/assembly-mac.xml
@@ -80,6 +80,7 @@
<include>org.apache.cayenne:cayenne-lifecycle</include>
<include>org.apache.cayenne:cayenne-project</include>
<include>org.apache.cayenne:cayenne-server</include>
+ <include>org.apache.cayenne:cayenne-dbsync</include>
<include>org.apache.cayenne:cayenne-tools</include>
<include>org.apache.cayenne:cayenne-dbcp2</include>
<include>org.apache.cayenne:cayenne-java8</include>
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/assembly/src/main/resources/assemblies/assembly-windows.xml
----------------------------------------------------------------------
diff --git a/assembly/src/main/resources/assemblies/assembly-windows.xml b/assembly/src/main/resources/assemblies/assembly-windows.xml
index 7401a42..efa451d 100644
--- a/assembly/src/main/resources/assemblies/assembly-windows.xml
+++ b/assembly/src/main/resources/assemblies/assembly-windows.xml
@@ -80,6 +80,7 @@
<include>org.apache.cayenne:cayenne-lifecycle</include>
<include>org.apache.cayenne:cayenne-project</include>
<include>org.apache.cayenne:cayenne-server</include>
+ <include>org.apache.cayenne:cayenne-dbsync</include>
<include>org.apache.cayenne:cayenne-tools</include>
<include>org.apache.cayenne:cayenne-dbcp2</include>
<include>org.apache.cayenne:cayenne-java8</include>
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/pom.xml
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/pom.xml b/cayenne-dbsync/pom.xml
new file mode 100644
index 0000000..5cc1a63
--- /dev/null
+++ b/cayenne-dbsync/pom.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <parent>
+ <artifactId>cayenne-parent</artifactId>
+ <groupId>org.apache.cayenne</groupId>
+ <version>4.0.M4-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>cayenne-dbsync</artifactId>
+ <packaging>jar</packaging>
+ <name>Cayenne Database Synchronization Tools</name>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.cayenne</groupId>
+ <artifactId>cayenne-server</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>xmlunit</groupId>
+ <artifactId>xmlunit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cayenne</groupId>
+ <artifactId>cayenne-server</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.cayenne.build-tools</groupId>
+ <artifactId>cayenne-test-utilities</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <!-- This ensures LICESNE and NOTICE inclusion in all jars -->
+ <plugin>
+ <artifactId>maven-remote-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>process</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <!-- include OSGi stuff -->
+ <configuration>
+ <archive>
+ <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+ </archive>
+ </configuration>
+ <!-- share tests with downstream modules -->
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>bundle-manifest</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>manifest</goal>
+ </goals>
+ <!-- TODO: export package filters. -->
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/CayenneDbSyncModule.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/CayenneDbSyncModule.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/CayenneDbSyncModule.java
new file mode 100644
index 0000000..4fa43b2
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/CayenneDbSyncModule.java
@@ -0,0 +1,82 @@
+package org.apache.cayenne.dbsync;
+
+import org.apache.cayenne.dba.db2.DB2Adapter;
+import org.apache.cayenne.dba.derby.DerbyAdapter;
+import org.apache.cayenne.dba.firebird.FirebirdAdapter;
+import org.apache.cayenne.dba.h2.H2Adapter;
+import org.apache.cayenne.dba.hsqldb.HSQLDBAdapter;
+import org.apache.cayenne.dba.ingres.IngresAdapter;
+import org.apache.cayenne.dba.mysql.MySQLAdapter;
+import org.apache.cayenne.dba.openbase.OpenBaseAdapter;
+import org.apache.cayenne.dba.oracle.Oracle8Adapter;
+import org.apache.cayenne.dba.oracle.OracleAdapter;
+import org.apache.cayenne.dba.postgres.PostgresAdapter;
+import org.apache.cayenne.dba.sqlserver.SQLServerAdapter;
+import org.apache.cayenne.dba.sybase.SybaseAdapter;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider;
+import org.apache.cayenne.dbsync.merge.factory.DB2MergerTokenFactory;
+import org.apache.cayenne.dbsync.merge.factory.DefaultMergerTokenFactory;
+import org.apache.cayenne.dbsync.merge.factory.DerbyMergerTokenFactory;
+import org.apache.cayenne.dbsync.merge.factory.FirebirdMergerTokenFactory;
+import org.apache.cayenne.dbsync.merge.factory.H2MergerTokenFactory;
+import org.apache.cayenne.dbsync.merge.factory.HSQLMergerTokenFactory;
+import org.apache.cayenne.dbsync.merge.factory.IngresMergerTokenFactory;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.dbsync.merge.factory.MySQLMergerTokenFactory;
+import org.apache.cayenne.dbsync.merge.factory.OpenBaseMergerTokenFactory;
+import org.apache.cayenne.dbsync.merge.factory.OracleMergerTokenFactory;
+import org.apache.cayenne.dbsync.merge.factory.PostgresMergerTokenFactory;
+import org.apache.cayenne.dbsync.merge.factory.SQLServerMergerTokenFactory;
+import org.apache.cayenne.dbsync.merge.factory.SybaseMergerTokenFactory;
+import org.apache.cayenne.di.Binder;
+import org.apache.cayenne.di.Module;
+
+/**
+ * @since 4.0
+ */
+public class CayenneDbSyncModule implements Module {
+
+ /**
+ * A DI container key for the Map<String, String> storing properties
+ * used by built-in Cayenne service.
+ */
+ public static final String MERGER_FACTORIES_MAP = "cayenne.dbsync.mergerfactories";
+
+ @Override
+ public void configure(Binder binder) {
+
+ // TODO: explicit binding before inserting into a map will be uneeded soon
+ binder.bind(DB2MergerTokenFactory.class).to(DB2MergerTokenFactory.class);
+ binder.bind(DerbyMergerTokenFactory.class).to(DerbyMergerTokenFactory.class);
+ binder.bind(FirebirdMergerTokenFactory.class).to(FirebirdMergerTokenFactory.class);
+ binder.bind(H2MergerTokenFactory.class).to(H2MergerTokenFactory.class);
+ binder.bind(HSQLMergerTokenFactory.class).to(HSQLMergerTokenFactory.class);
+ binder.bind(IngresMergerTokenFactory.class).to(IngresMergerTokenFactory.class);
+ binder.bind(MySQLMergerTokenFactory.class).to(MySQLMergerTokenFactory.class);
+ binder.bind(OpenBaseMergerTokenFactory.class).to(OpenBaseMergerTokenFactory.class);
+ binder.bind(OracleMergerTokenFactory.class).to(OracleMergerTokenFactory.class);
+ binder.bind(PostgresMergerTokenFactory.class).to(PostgresMergerTokenFactory.class);
+ binder.bind(SQLServerMergerTokenFactory.class).to(SQLServerMergerTokenFactory.class);
+ binder.bind(SybaseMergerTokenFactory.class).to(SybaseMergerTokenFactory.class);
+
+ // default and per adapter merger factories...
+ binder.bind(MergerTokenFactory.class).to(DefaultMergerTokenFactory.class);
+ binder.bindMap(MERGER_FACTORIES_MAP)
+ .put(DB2Adapter.class.getName(), DB2MergerTokenFactory.class)
+ .put(DerbyAdapter.class.getName(), DerbyMergerTokenFactory.class)
+ .put(FirebirdAdapter.class.getName(), FirebirdMergerTokenFactory.class)
+ .put(H2Adapter.class.getName(), H2MergerTokenFactory.class)
+ .put(HSQLDBAdapter.class.getName(), HSQLMergerTokenFactory.class)
+ .put(IngresAdapter.class.getName(), IngresMergerTokenFactory.class)
+ .put(MySQLAdapter.class.getName(), MySQLMergerTokenFactory.class)
+ .put(OpenBaseAdapter.class.getName(), OpenBaseMergerTokenFactory.class)
+ .put(OracleAdapter.class.getName(), OracleMergerTokenFactory.class)
+ .put(Oracle8Adapter.class.getName(), OracleMergerTokenFactory.class)
+ .put(PostgresAdapter.class.getName(), PostgresMergerTokenFactory.class)
+ .put(SQLServerAdapter.class.getName(), SQLServerMergerTokenFactory.class)
+ .put(SybaseAdapter.class.getName(), SybaseMergerTokenFactory.class);
+
+ binder.bind(MergerTokenFactoryProvider.class).to(MergerTokenFactoryProvider.class);
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractToDbToken.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractToDbToken.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractToDbToken.java
new file mode 100644
index 0000000..1cc3092
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractToDbToken.java
@@ -0,0 +1,126 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.log.JdbcEventLogger;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.validation.SimpleValidationFailure;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.List;
+
+/**
+ * Common abstract superclass for all {@link MergerToken}s going from the model
+ * to the database.
+ */
+public abstract class AbstractToDbToken implements MergerToken, Comparable<MergerToken> {
+
+ private final String tokenName;
+
+ protected AbstractToDbToken(String tokenName) {
+ this.tokenName = tokenName;
+ }
+
+ @Override
+ public final String getTokenName() {
+ return tokenName;
+ }
+
+ @Override
+ public final MergeDirection getDirection() {
+ return MergeDirection.TO_DB;
+ }
+
+ @Override
+ public void execute(MergerContext mergerContext) {
+ for (String sql : createSql(mergerContext.getDataNode().getAdapter())) {
+ executeSql(mergerContext, sql);
+ }
+ }
+
+ protected void executeSql(MergerContext mergerContext, String sql) {
+ JdbcEventLogger logger = mergerContext.getDataNode().getJdbcEventLogger();
+ logger.log(sql);
+
+ try (Connection conn = mergerContext.getDataNode().getDataSource().getConnection();) {
+
+ try (Statement st = conn.createStatement();) {
+ st.execute(sql);
+ }
+ } catch (SQLException e) {
+ mergerContext.getValidationResult().addFailure(new SimpleValidationFailure(sql, e.getMessage()));
+ logger.logQueryError(e);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getTokenName() + ' ' + getTokenValue() + ' ' + getDirection();
+ }
+
+ public abstract List<String> createSql(DbAdapter adapter);
+
+ abstract static class Entity extends AbstractToDbToken {
+
+ private DbEntity entity;
+
+ public Entity(String tokenName, DbEntity entity) {
+ super(tokenName);
+ this.entity = entity;
+ }
+
+ public DbEntity getEntity() {
+ return entity;
+ }
+
+ public String getTokenValue() {
+ return getEntity().getName();
+ }
+
+ public int compareTo(MergerToken o) {
+ // default order as tokens are created
+ return 0;
+ }
+
+ }
+
+ abstract static class EntityAndColumn extends Entity {
+
+ private DbAttribute column;
+
+ public EntityAndColumn(String tokenName, DbEntity entity, DbAttribute column) {
+ super(tokenName, entity);
+ this.column = column;
+ }
+
+ public DbAttribute getColumn() {
+ return column;
+ }
+
+ @Override
+ public String getTokenValue() {
+ return getEntity().getName() + "." + getColumn().getName();
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractToModelToken.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractToModelToken.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractToModelToken.java
new file mode 100644
index 0000000..0c4b22e
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractToModelToken.java
@@ -0,0 +1,122 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+
+/**
+ * Common abstract superclass for all {@link MergerToken}s going from the database to the
+ * model.
+ *
+ */
+public abstract class AbstractToModelToken implements MergerToken {
+
+ private final String tokenName;
+
+ protected AbstractToModelToken(String tokenName) {
+ this.tokenName = tokenName;
+ }
+
+ @Override
+ public final String getTokenName() {
+ return tokenName;
+ }
+
+ public final MergeDirection getDirection() {
+ return MergeDirection.TO_MODEL;
+ }
+
+ protected static void remove(ModelMergeDelegate mergerContext, DbRelationship rel, boolean reverse) {
+ if (rel == null) {
+ return;
+ }
+ if (reverse) {
+ remove(mergerContext, rel.getReverseRelationship(), false);
+ }
+
+ DbEntity dbEntity = rel.getSourceEntity();
+ for (ObjEntity objEntity : dbEntity.mappedObjEntities()) {
+ remove(mergerContext, objEntity.getRelationshipForDbRelationship(rel), true);
+ }
+
+ rel.getSourceEntity().removeRelationship(rel.getName());
+ mergerContext.dbRelationshipRemoved(rel);
+ }
+
+ protected static void remove(ModelMergeDelegate mergerContext, ObjRelationship rel, boolean reverse) {
+ if (rel == null) {
+ return;
+ }
+ if (reverse) {
+ remove(mergerContext, rel.getReverseRelationship(), false);
+ }
+ rel.getSourceEntity().removeRelationship(rel.getName());
+ mergerContext.objRelationshipRemoved(rel);
+ }
+
+ @Override
+ public String toString() {
+ return getTokenName() + ' ' + getTokenValue() + ' ' + getDirection();
+ }
+
+ abstract static class Entity extends AbstractToModelToken {
+
+ private final DbEntity entity;
+
+ protected Entity(String tokenName, DbEntity entity) {
+ super(tokenName);
+ this.entity = entity;
+ }
+
+ public DbEntity getEntity() {
+ return entity;
+ }
+
+ public String getTokenValue() {
+ return getEntity().getName();
+ }
+
+ }
+
+ abstract static class EntityAndColumn extends Entity {
+
+ private final DbAttribute column;
+
+ protected EntityAndColumn(String tokenName, DbEntity entity, DbAttribute column) {
+ super(tokenName, entity);
+ this.column = column;
+ }
+
+ public DbAttribute getColumn() {
+ return column;
+ }
+
+ @Override
+ public String getTokenValue() {
+ return getEntity().getName() + "." + getColumn().getName();
+ }
+
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToDb.java
new file mode 100644
index 0000000..977128c
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToDb.java
@@ -0,0 +1,65 @@
+/*
+ * 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.dbsync.merge;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.JdbcAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+public class AddColumnToDb extends AbstractToDbToken.EntityAndColumn {
+
+ public AddColumnToDb(DbEntity entity, DbAttribute column) {
+ super("Add Column", entity, column);
+ }
+
+ /**
+ * append the part of the token before the actual column data type
+ */
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" ADD COLUMN ");
+ sqlBuffer.append(context.quotedName(getColumn()));
+ sqlBuffer.append(" ");
+ }
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuffer sqlBuffer = new StringBuffer();
+ QuotingStrategy context = adapter.getQuotingStrategy();
+ appendPrefix(sqlBuffer, context);
+
+ sqlBuffer.append(JdbcAdapter.getType(adapter, getColumn()));
+ sqlBuffer.append(JdbcAdapter.sizeAndPrecision(adapter, getColumn()));
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return factory.createDropColumnToModel(getEntity(), getColumn());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToModel.java
new file mode 100644
index 0000000..30390ca
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddColumnToModel.java
@@ -0,0 +1,55 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.ObjEntity;
+
+/**
+ * A {@link MergerToken} to add a {@link DbAttribute} to a {@link DbEntity}. The
+ * {@link EntityMergeSupport} will be used to update the mapped {@link ObjEntity}
+ *
+ */
+public class AddColumnToModel extends AbstractToModelToken.EntityAndColumn {
+
+ public AddColumnToModel(DbEntity entity, DbAttribute column) {
+ super("Add Column", entity, column);
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return factory.createDropColumnToDb(getEntity(), getColumn());
+ }
+
+ public void execute(MergerContext mergerContext) {
+ getEntity().addAttribute(getColumn());
+
+ // TODO: use EntityMergeSupport from DbImportConfiguration... otherwise we are ignoring a bunch of
+ // important settings
+
+ EntityMergeSupport entityMergeSupport = new EntityMergeSupport(mergerContext.getDataMap());
+ for(ObjEntity e : getEntity().mappedObjEntities()) {
+ entityMergeSupport.synchronizeOnDbAttributeAdded(e, getColumn());
+ }
+
+ mergerContext.getModelMergeDelegate().dbAttributeAdded(getColumn());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToDb.java
new file mode 100644
index 0000000..5c851a6
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToDb.java
@@ -0,0 +1,87 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.cayenne.access.DbGenerator;
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+
+public class AddRelationshipToDb extends AbstractToDbToken.Entity {
+
+ private DbRelationship rel;
+
+ public AddRelationshipToDb(DbEntity entity, DbRelationship rel) {
+ super("Add foreign key", entity);
+ this.rel = rel;
+ }
+
+ /**
+ * @see DbGenerator#createConstraintsQueries(org.apache.cayenne.map.DbEntity)
+ */
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ // TODO: skip FK to a different DB
+
+ if (this.shouldGenerateFkConstraint()) {
+ String fksql = adapter.createFkConstraint(rel);
+ if (fksql != null) {
+ return Collections.singletonList(fksql);
+ }
+ }
+ return Collections.emptyList();
+ }
+
+ public boolean shouldGenerateFkConstraint() {
+ return !rel.isToMany()
+ && rel.isToPK() // TODO it is not necessary primary key it can be unique index
+ && !rel.isToDependentPK();
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return factory.createDropRelationshipToModel(getEntity(), rel);
+ }
+
+ @Override
+ public String getTokenValue() {
+ if (this.shouldGenerateFkConstraint()) {
+ return rel.getSourceEntity().getName() + "->" + rel.getTargetEntityName();
+ } else {
+ return "Skip. No sql representation.";
+ }
+ }
+
+ public DbRelationship getRelationship() {
+ return rel;
+ }
+
+ @Override
+ public int compareTo(MergerToken o) {
+ // add all AddRelationshipToDb to the end.
+ if (o instanceof AddRelationshipToDb) {
+ return super.compareTo(o);
+ }
+ return 1;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToModel.java
new file mode 100644
index 0000000..f516a3e
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AddRelationshipToModel.java
@@ -0,0 +1,95 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.ObjEntity;
+
+public class AddRelationshipToModel extends AbstractToModelToken.Entity {
+
+ public static final String COMMA_SEPARATOR = ", ";
+ public static final int COMMA_SEPARATOR_LENGTH = COMMA_SEPARATOR.length();
+ private DbRelationship rel;
+
+ public AddRelationshipToModel(DbEntity entity, DbRelationship rel) {
+ super("Add Relationship", entity);
+ this.rel = rel;
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return factory.createDropRelationshipToDb(getEntity(), rel);
+ }
+
+ public void execute(MergerContext mergerContext) {
+ getEntity().addRelationship(rel);
+ // TODO: add reverse relationship as well if it does not exist
+
+ // TODO: use EntityMergeSupport from DbImportConfiguration... otherwise we are ignoring a bunch of
+ // important settings
+
+ EntityMergeSupport entityMergeSupport = new EntityMergeSupport(mergerContext.getDataMap());
+ for(ObjEntity e : getEntity().mappedObjEntities()) {
+ entityMergeSupport.synchronizeOnDbRelationshipAdded(e, rel);
+ }
+
+ mergerContext.getModelMergeDelegate().dbRelationshipAdded(rel);
+ }
+
+ @Override
+ public String getTokenValue() {
+ String attributes = "";
+ if (rel.getJoins().size() == 1) {
+ attributes = rel.getJoins().get(0).getTargetName();
+ } else {
+ for (DbJoin dbJoin : rel.getJoins()) {
+ attributes += dbJoin.getTargetName() + COMMA_SEPARATOR;
+ }
+
+ attributes = "{" + attributes.substring(0, attributes.length() - COMMA_SEPARATOR_LENGTH) + "}";
+ }
+
+ return rel.getName() + " " + rel.getSourceEntity().getName() + "->" + rel.getTargetEntityName() + "." + attributes;
+ }
+
+
+ public static String getTokenValue(DbRelationship rel) {
+ String attributes = "";
+ if (rel.getJoins().size() == 1) {
+ attributes = rel.getJoins().get(0).getTargetName();
+ } else {
+ for (DbJoin dbJoin : rel.getJoins()) {
+ attributes += dbJoin.getTargetName() + COMMA_SEPARATOR;
+ }
+
+ attributes = "{" + attributes.substring(0, attributes.length() - COMMA_SEPARATOR_LENGTH) + "}";
+ }
+
+ return rel.getName() + " " + rel.getSourceEntity().getName() + "->" + rel.getTargetEntityName() + "." + attributes;
+ }
+
+ public DbRelationship getRelationship() {
+ return rel;
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToDb.java
new file mode 100644
index 0000000..9584aaf
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToDb.java
@@ -0,0 +1,66 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.access.DataNode;
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.validation.SimpleValidationFailure;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class CreateTableToDb extends AbstractToDbToken.Entity {
+
+ public CreateTableToDb(DbEntity entity) {
+ super("Create Table", entity);
+ }
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ List<String> sqls = new ArrayList<String>();
+ sqls.addAll(adapter.getPkGenerator().createAutoPkStatements(
+ Collections.singletonList(getEntity())));
+ sqls.add(adapter.createTable(getEntity()));
+ return sqls;
+ }
+
+ @Override
+ public void execute(MergerContext mergerContext) {
+ try {
+ DataNode node = mergerContext.getDataNode();
+ DbAdapter adapter = node.getAdapter();
+ adapter.getPkGenerator().createAutoPk(
+ node,
+ Collections.singletonList(getEntity()));
+ executeSql(mergerContext, adapter.createTable(getEntity()));
+ }
+ catch (Exception e) {
+ mergerContext.getValidationResult().addFailure(
+ new SimpleValidationFailure(this, e.getMessage()));
+ }
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return factory.createDropTableToModel(getEntity());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToModel.java
new file mode 100644
index 0000000..69e18b3
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/CreateTableToModel.java
@@ -0,0 +1,102 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.naming.NameConverter;
+
+/**
+ * A {@link MergerToken} to add a {@link DbEntity} to a {@link DataMap}
+ *
+ */
+public class CreateTableToModel extends AbstractToModelToken.Entity {
+
+ /**
+ * className if {@link ObjEntity} should be generated with a
+ * special class name.
+ * Setting this to <code>null</code>, because by default class name should be generated
+ */
+ private String objEntityClassName = null; //CayenneDataObject.class.getName();
+
+ public CreateTableToModel(DbEntity entity) {
+ super("Create Table", entity);
+ }
+
+ /**
+ * Set the {@link ObjEntity} className if {@link ObjEntity} should be generated with a
+ * special class name. Set to null if the {@link ObjEntity} should be created with a
+ * name based on {@link DataMap#getDefaultPackage()} and {@link ObjEntity#getName()}
+ * <p>
+ * The default value is <code>null</code>
+ */
+ public void setObjEntityClassName(String n) {
+ objEntityClassName = n;
+ }
+
+ public void execute(MergerContext mergerContext) {
+ DataMap map = mergerContext.getDataMap();
+ map.addDbEntity(getEntity());
+
+ // create a ObjEntity
+ String objEntityName = NameConverter.underscoredToJava(getEntity().getName(), true);
+ // this loop will terminate even if no valid name is found
+ // to prevent loader from looping forever (though such case is very unlikely)
+ String baseName = objEntityName;
+ for (int i = 1; i < 1000 && map.getObjEntity(objEntityName) != null; i++) {
+ objEntityName = baseName + i;
+ }
+
+ ObjEntity objEntity = new ObjEntity(objEntityName);
+ objEntity.setDbEntity(getEntity());
+
+ // try to find a class name for the ObjEntity
+ String className = objEntityClassName;
+ if (className == null) {
+ // we should generate a className based on the objEntityName
+ className = map.getNameWithDefaultPackage(objEntityName);
+ }
+
+ objEntity.setClassName(className);
+ objEntity.setSuperClassName(map.getDefaultSuperclass());
+
+ if (map.isClientSupported()) {
+ objEntity.setClientClassName(map.getNameWithDefaultClientPackage(objEntity.getName()));
+ objEntity.setClientSuperClassName(map.getDefaultClientSuperclass());
+ }
+
+ map.addObjEntity(objEntity);
+
+ // presumably there are no other ObjEntities pointing to this DbEntity, so syncing just this one...
+
+ // TODO: use EntityMergeSupport from DbImportConfiguration... otherwise we are ignoring a bunch of
+ // important settings
+ new EntityMergeSupport(map).synchronizeWithDbEntity(objEntity);
+
+ mergerContext.getModelMergeDelegate().dbEntityAdded(getEntity());
+ mergerContext.getModelMergeDelegate().objEntityAdded(objEntity);
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return factory.createDropTableToDb(getEntity());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMerger.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMerger.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMerger.java
new file mode 100644
index 0000000..f7d4346
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMerger.java
@@ -0,0 +1,405 @@
+/*
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.access.DataNode;
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.dbsync.reverse.DbLoader;
+import org.apache.cayenne.dbsync.reverse.DbLoaderConfiguration;
+import org.apache.cayenne.dbsync.reverse.LoggingDbLoaderDelegate;
+import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig;
+import org.apache.cayenne.map.Attribute;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.DetectedDbEntity;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Traverse a {@link DataNode} and a {@link DataMap} and create a group of
+ * {@link MergerToken}s to alter the {@link DataNode} data store to match the
+ * {@link DataMap}.
+ *
+ */
+public class DbMerger {
+
+ private static final Log LOGGER = LogFactory.getLog(DbMerger.class);
+
+ private final MergerTokenFactory factory;
+
+ private final ValueForNullProvider valueForNull;
+
+ public DbMerger(MergerTokenFactory factory) {
+ this(factory, null);
+ }
+
+ public DbMerger(MergerTokenFactory factory, ValueForNullProvider valueForNull) {
+ this.factory = factory;
+ this.valueForNull = valueForNull == null ? new EmptyValueForNullProvider() : valueForNull;
+ }
+
+ /**
+ * Create and return a {@link List} of {@link MergerToken}s to alter the
+ * given {@link DataNode} to match the given {@link DataMap}
+ */
+ public List<MergerToken> createMergeTokens(DataSource dataSource, DbAdapter adapter, DataMap existingDataMap,
+ DbLoaderConfiguration config) {
+ return createMergeTokens(existingDataMap, loadDataMapFromDb(dataSource, adapter, config), config);
+ }
+
+ /**
+ * Create and return a {@link List} of {@link MergerToken}s to alter the
+ * given {@link DataNode} to match the given {@link DataMap}
+ */
+ public List<MergerToken> createMergeTokens(DataMap existing, DataMap loadedFomDb, DbLoaderConfiguration config) {
+
+ loadedFomDb.setQuotingSQLIdentifiers(existing.isQuotingSQLIdentifiers());
+
+ List<MergerToken> tokens = createMergeTokens(filter(existing, config.getFiltersConfig()),
+ loadedFomDb.getDbEntities(), config);
+
+ // sort. use a custom Comparator since only toDb tokens are comparable
+ // by now
+ Collections.sort(tokens, new Comparator<MergerToken>() {
+
+ public int compare(MergerToken o1, MergerToken o2) {
+ if (o1 instanceof AbstractToDbToken && o2 instanceof AbstractToDbToken) {
+
+ return ((AbstractToDbToken) o1).compareTo(o2);
+ }
+ return 0;
+ }
+ });
+
+ return tokens;
+ }
+
+ private Collection<DbEntity> filter(DataMap existing, FiltersConfig filtersConfig) {
+ Collection<DbEntity> existingFiltered = new LinkedList<DbEntity>();
+ for (DbEntity entity : existing.getDbEntities()) {
+ if (filtersConfig.tableFilter(entity.getCatalog(), entity.getSchema()).isIncludeTable(entity.getName()) != null) {
+ existingFiltered.add(entity);
+ }
+ }
+ return existingFiltered;
+ }
+
+ private DataMap loadDataMapFromDb(DataSource dataSource, DbAdapter adapter, DbLoaderConfiguration config) {
+ try (Connection conn = dataSource.getConnection();) {
+
+ return new DbLoader(conn, adapter, new LoggingDbLoaderDelegate(LOGGER)).load(config);
+ } catch (SQLException e) {
+ throw new CayenneRuntimeException("Can't doLoad dataMap from db.", e);
+ }
+ }
+
+ public List<MergerToken> createMergeTokens(Collection<DbEntity> existing, Collection<DbEntity> loadedFromDb,
+ DbLoaderConfiguration config) {
+ Collection<DbEntity> dbEntitiesToDrop = new LinkedList<DbEntity>(loadedFromDb);
+
+ List<MergerToken> tokens = new LinkedList<MergerToken>();
+ for (DbEntity dbEntity : existing) {
+ String tableName = dbEntity.getName();
+
+ // look for table
+ DbEntity detectedEntity = findDbEntity(loadedFromDb, tableName);
+ if (detectedEntity == null) {
+ tokens.add(factory.createCreateTableToDb(dbEntity));
+ // TODO: does this work properly with createReverse?
+ for (DbRelationship rel : dbEntity.getRelationships()) {
+ tokens.add(factory.createAddRelationshipToDb(dbEntity, rel));
+ }
+ continue;
+ }
+
+ dbEntitiesToDrop.remove(detectedEntity);
+
+ tokens.addAll(checkRelationshipsToDrop(dbEntity, detectedEntity));
+ if (!config.isSkipRelationshipsLoading()) {
+ tokens.addAll(checkRelationshipsToAdd(dbEntity, detectedEntity));
+ }
+ tokens.addAll(checkRows(dbEntity, detectedEntity));
+
+ if (!config.isSkipPrimaryKeyLoading()) {
+ MergerToken token = checkPrimaryKeyChange(dbEntity, detectedEntity);
+ if (token != null) {
+ tokens.add(token);
+ }
+ }
+ }
+
+ // drop table
+ // TODO: support drop table. currently, too many tables are marked for
+ // drop
+ for (DbEntity e : dbEntitiesToDrop) {
+ tokens.add(factory.createDropTableToDb(e));
+ for (DbRelationship relationship : e.getRelationships()) {
+ DbEntity detectedEntity = findDbEntity(existing, relationship.getTargetEntityName());
+ if (detectedEntity != null) {
+ tokens.add(factory.createDropRelationshipToDb(detectedEntity, relationship.getReverseRelationship()));
+ }
+ }
+ }
+
+ return tokens;
+ }
+
+ private List<MergerToken> checkRows(DbEntity existing, DbEntity loadedFromDb) {
+ List<MergerToken> tokens = new LinkedList<MergerToken>();
+
+ // columns to drop
+ for (DbAttribute detected : loadedFromDb.getAttributes()) {
+ if (findDbAttribute(existing, detected.getName()) == null) {
+ tokens.add(factory.createDropColumnToDb(existing, detected));
+ }
+ }
+
+ // columns to add or modify
+ for (DbAttribute attr : existing.getAttributes()) {
+ String columnName = attr.getName().toUpperCase();
+
+ DbAttribute detected = findDbAttribute(loadedFromDb, columnName);
+
+ if (detected == null) {
+ tokens.add(factory.createAddColumnToDb(existing, attr));
+ if (attr.isMandatory()) {
+ if (valueForNull.hasValueFor(existing, attr)) {
+ tokens.add(factory.createSetValueForNullToDb(existing, attr, valueForNull));
+ }
+ tokens.add(factory.createSetNotNullToDb(existing, attr));
+ }
+ continue;
+ }
+
+ // check for not null
+ if (attr.isMandatory() != detected.isMandatory()) {
+ if (attr.isMandatory()) {
+ if (valueForNull.hasValueFor(existing, attr)) {
+ tokens.add(factory.createSetValueForNullToDb(existing, attr, valueForNull));
+ }
+ tokens.add(factory.createSetNotNullToDb(existing, attr));
+ } else {
+ tokens.add(factory.createSetAllowNullToDb(existing, attr));
+ }
+ }
+
+ // TODO: check more types than char/varchar
+ // TODO: psql report VARCHAR for text column, not clob
+ switch (detected.getType()) {
+ case Types.VARCHAR:
+ case Types.CHAR:
+ if (attr.getMaxLength() != detected.getMaxLength()) {
+ tokens.add(factory.createSetColumnTypeToDb(existing, detected, attr));
+ }
+ break;
+ }
+ }
+
+ return tokens;
+ }
+
+ private List<MergerToken> checkRelationshipsToDrop(DbEntity dbEntity, DbEntity detectedEntity) {
+ List<MergerToken> tokens = new LinkedList<MergerToken>();
+
+ // relationships to drop
+ for (DbRelationship detected : detectedEntity.getRelationships()) {
+ if (findDbRelationship(dbEntity, detected) == null) {
+
+ // alter detected relationship to match entity and attribute
+ // names.
+ // (case sensitively)
+
+ DbEntity targetEntity = findDbEntity(dbEntity.getDataMap().getDbEntities(),
+ detected.getTargetEntityName());
+ if (targetEntity == null) {
+ continue;
+ }
+
+ detected.setSourceEntity(dbEntity);
+ detected.setTargetEntityName(targetEntity);
+
+ // manipulate the joins to match the DbAttributes in the model
+ for (DbJoin join : detected.getJoins()) {
+ DbAttribute sattr = findDbAttribute(dbEntity, join.getSourceName());
+ if (sattr != null) {
+ join.setSourceName(sattr.getName());
+ }
+ DbAttribute tattr = findDbAttribute(targetEntity, join.getTargetName());
+ if (tattr != null) {
+ join.setTargetName(tattr.getName());
+ }
+ }
+
+ MergerToken token = factory.createDropRelationshipToDb(dbEntity, detected);
+ if (detected.isToMany()) {
+ // default toModel as we can not do drop a toMany in the db.
+ // only
+ // toOne are represented using foreign key
+ token = token.createReverse(factory);
+ }
+ tokens.add(token);
+ }
+ }
+
+ return tokens;
+ }
+
+ private List<MergerToken> checkRelationshipsToAdd(DbEntity dbEntity, DbEntity detectedEntity) {
+
+ List<MergerToken> tokens = new LinkedList<MergerToken>();
+
+ for (DbRelationship rel : dbEntity.getRelationships()) {
+ if (findDbRelationship(detectedEntity, rel) == null) {
+ AddRelationshipToDb token = (AddRelationshipToDb) factory.createAddRelationshipToDb(dbEntity, rel);
+
+ if (token.shouldGenerateFkConstraint()) {
+ // TODO I guess we should add relationship always; in order
+ // to have ability
+ // TODO generate reverse relationship. If it doesn't have
+ // anything to execute it will be passed
+ // TODO through execution without any affect on db
+ tokens.add(token);
+ }
+ }
+ }
+
+ return tokens;
+ }
+
+ private MergerToken checkPrimaryKeyChange(DbEntity dbEntity, DbEntity detectedEntity) {
+ Collection<DbAttribute> primaryKeyOriginal = detectedEntity.getPrimaryKeys();
+ Collection<DbAttribute> primaryKeyNew = dbEntity.getPrimaryKeys();
+
+ String primaryKeyName = null;
+ if (detectedEntity instanceof DetectedDbEntity) {
+ primaryKeyName = ((DetectedDbEntity) detectedEntity).getPrimaryKeyName();
+ }
+
+ if (upperCaseEntityNames(primaryKeyOriginal).equals(upperCaseEntityNames(primaryKeyNew))) {
+ return null;
+ }
+
+ return factory.createSetPrimaryKeyToDb(dbEntity, primaryKeyOriginal, primaryKeyNew, primaryKeyName);
+ }
+
+ private Set<String> upperCaseEntityNames(Collection<? extends Attribute> attrs) {
+ Set<String> names = new HashSet<String>();
+ for (Attribute attr : attrs) {
+ names.add(attr.getName().toUpperCase());
+ }
+ return names;
+ }
+
+ /**
+ * case insensitive search for a {@link DbEntity} in a {@link DataMap} by
+ * name
+ */
+ private DbEntity findDbEntity(Collection<DbEntity> dbEntities, String caseInsensitiveName) {
+ // TODO: create a Map with upper case keys?
+ for (DbEntity e : dbEntities) {
+ if (e.getName().equalsIgnoreCase(caseInsensitiveName)) {
+ return e;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * case insensitive search for a {@link DbAttribute} in a {@link DbEntity}
+ * by name
+ */
+ private DbAttribute findDbAttribute(DbEntity entity, String caseInsensitiveName) {
+ for (DbAttribute a : entity.getAttributes()) {
+ if (a.getName().equalsIgnoreCase(caseInsensitiveName)) {
+ return a;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * search for a {@link DbRelationship} like rel in the given
+ * {@link DbEntity}
+ */
+ private DbRelationship findDbRelationship(DbEntity entity, DbRelationship rel) {
+ for (DbRelationship candidate : entity.getRelationships()) {
+ if (equalDbJoinCollections(candidate.getJoins(), rel.getJoins())) {
+ return candidate;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return true if the two unordered {@link Collection}s of {@link DbJoin}s
+ * are equal. Entity and Attribute names are compared case insensitively.
+ *
+ * TODO complexity n^2; sort both collection and go through them to compare
+ * = 2*n*log(n) + n
+ */
+ private static boolean equalDbJoinCollections(Collection<DbJoin> j1s, Collection<DbJoin> j2s) {
+ if (j1s.size() != j2s.size()) {
+ return false;
+ }
+
+ for (DbJoin j1 : j1s) {
+ if (!havePair(j2s, j1)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static boolean havePair(Collection<DbJoin> j2s, DbJoin j1) {
+ for (DbJoin j2 : j2s) {
+ if (!isNull(j1.getSource()) && !isNull(j1.getTarget()) && !isNull(j2.getSource())
+ && !isNull(j2.getTarget())
+ && j1.getSource().getEntity().getName().equalsIgnoreCase(j2.getSource().getEntity().getName())
+ && j1.getTarget().getEntity().getName().equalsIgnoreCase(j2.getTarget().getEntity().getName())
+ && j1.getSourceName().equalsIgnoreCase(j2.getSourceName())
+ && j1.getTargetName().equalsIgnoreCase(j2.getTargetName())) {
+
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean isNull(DbAttribute attribute) {
+ return attribute == null || attribute.getEntity() == null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMergerConfig.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMergerConfig.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMergerConfig.java
new file mode 100644
index 0000000..1cd80df
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMergerConfig.java
@@ -0,0 +1,63 @@
+/*
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig;
+
+/**
+ * @since 4.0
+ */
+public class DbMergerConfig {
+
+ private FiltersConfig filtersConfig;
+
+ private boolean skipRelationships;
+
+ private boolean skipPrimaryKey;
+
+ public DbMergerConfig(FiltersConfig filtersConfig, boolean skipRelationships, boolean skipPrimaryKey) {
+ this.filtersConfig = filtersConfig;
+ this.skipRelationships = skipRelationships;
+ this.skipPrimaryKey = skipPrimaryKey;
+ }
+
+ public void setSkipRelationships(boolean skipRelationships) {
+ this.skipRelationships = skipRelationships;
+ }
+
+ public boolean isSkipRelationships() {
+ return skipRelationships;
+ }
+
+ public void setSkipPrimaryKey(boolean skipPrimaryKey) {
+ this.skipPrimaryKey = skipPrimaryKey;
+ }
+
+ public boolean isSkipPrimaryKey() {
+ return skipPrimaryKey;
+ }
+
+ public FiltersConfig getFiltersConfig() {
+ return filtersConfig;
+ }
+
+ public void setFiltersConfig(FiltersConfig filtersConfig) {
+ this.filtersConfig = filtersConfig;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DefaultModelMergeDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DefaultModelMergeDelegate.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DefaultModelMergeDelegate.java
new file mode 100644
index 0000000..617aad2
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DefaultModelMergeDelegate.java
@@ -0,0 +1,89 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+
+/**
+ * A default noop implementation of {@link ModelMergeDelegate}.
+ */
+public class DefaultModelMergeDelegate implements ModelMergeDelegate {
+
+ @Override
+ public void dbAttributeAdded(DbAttribute att) {
+ }
+
+ @Override
+ public void dbAttributeModified(DbAttribute att) {
+ }
+
+ @Override
+ public void dbAttributeRemoved(DbAttribute att) {
+ }
+
+ @Override
+ public void dbEntityAdded(DbEntity ent) {
+ }
+
+ @Override
+ public void dbEntityRemoved(DbEntity ent) {
+ }
+
+ @Override
+ public void dbRelationshipAdded(DbRelationship rel) {
+ }
+
+ @Override
+ public void dbRelationshipRemoved(DbRelationship rel) {
+ }
+
+ @Override
+ public void objAttributeAdded(ObjAttribute att) {
+ }
+
+ @Override
+ public void objAttributeModified(ObjAttribute att) {
+ }
+
+ @Override
+ public void objAttributeRemoved(ObjAttribute att) {
+ }
+
+ @Override
+ public void objEntityAdded(ObjEntity ent) {
+ }
+
+ @Override
+ public void objEntityRemoved(ObjEntity ent) {
+ }
+
+ @Override
+ public void objRelationshipAdded(ObjRelationship rel) {
+ }
+
+ @Override
+ public void objRelationshipRemoved(ObjRelationship rel) {
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DefaultValueForNullProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DefaultValueForNullProvider.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DefaultValueForNullProvider.java
new file mode 100644
index 0000000..9d4e0cd
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DefaultValueForNullProvider.java
@@ -0,0 +1,62 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cayenne.access.jdbc.SQLParameterBinding;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+public class DefaultValueForNullProvider implements ValueForNullProvider {
+
+ private Map<String, SQLParameterBinding> values = new HashMap<>();
+
+ public void set(DbEntity entity, DbAttribute column, Object value, int type) {
+ values.put(createKey(entity, column), new SQLParameterBinding(value, type, column
+ .getAttributePrecision()));
+ }
+
+ protected SQLParameterBinding get(DbEntity entity, DbAttribute column) {
+ return values.get(createKey(entity, column));
+ }
+
+ public List<String> createSql(DbEntity entity, DbAttribute column) {
+ SQLParameterBinding value = get(entity, column);
+ if (value == null) {
+ return Collections.emptyList();
+ }
+
+ // TODO: change things so it is possible to use prepared statements here
+ return Collections.singletonList("UPDATE " + entity.getFullyQualifiedName()
+ + " SET " + column.getName() + "='" + value.getValue() + "' WHERE " + column.getName() + " IS NULL");
+ }
+
+ public boolean hasValueFor(DbEntity entity, DbAttribute column) {
+ return values.containsKey(createKey(entity, column));
+ }
+
+ private String createKey(DbEntity entity, DbAttribute attribute) {
+ return (entity.getFullyQualifiedName() + "." + attribute.getName()).toUpperCase();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToDb.java
new file mode 100644
index 0000000..19914f0
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToDb.java
@@ -0,0 +1,52 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+public class DropColumnToDb extends AbstractToDbToken.EntityAndColumn {
+
+ public DropColumnToDb(DbEntity entity, DbAttribute column) {
+ super("Drop Column", entity, column);
+ }
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuilder sqlBuffer = new StringBuilder();
+ QuotingStrategy context = adapter.getQuotingStrategy();
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" DROP COLUMN ");
+ sqlBuffer.append(context.quotedName(getColumn()));
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return factory.createAddColumnToModel(getEntity(), getColumn());
+ }
+
+}
[07/15] cayenne git commit: CAY-2116 Split schema synchronization
code in a separate module
Posted by aa...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/DefaultJdbc2JavaTypeMapper.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/DefaultJdbc2JavaTypeMapper.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/DefaultJdbc2JavaTypeMapper.java
deleted file mode 100644
index de9e02d..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/DefaultJdbc2JavaTypeMapper.java
+++ /dev/null
@@ -1,282 +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.access.loader.mapper;
-
-import org.apache.cayenne.dba.TypesMapping;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.util.Util;
-
-import java.io.Serializable;
-import java.math.BigInteger;
-import java.sql.Types;
-import java.util.Calendar;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-/**
- * @since 4.0.
- */
-public class DefaultJdbc2JavaTypeMapper implements Jdbc2JavaTypeMapper {
-
- // Never use "-1" or any other normal integer, since there
- // is a big chance it is being reserved in java.sql.Types
- public static final int NOT_DEFINED = Integer.MAX_VALUE;
-
- // char constants for Java data types
- public static final String JAVA_LONG = "java.lang.Long";
- public static final String JAVA_BYTES = "byte[]";
- public static final String JAVA_BOOLEAN = "java.lang.Boolean";
- public static final String JAVA_STRING = "java.lang.String";
- public static final String JAVA_SQLDATE = "java.sql.Date";
- public static final String JAVA_UTILDATE = "java.util.Date";
- public static final String JAVA_BIGDECIMAL = "java.math.BigDecimal";
- public static final String JAVA_DOUBLE = "java.lang.Double";
- public static final String JAVA_FLOAT = "java.lang.Float";
- public static final String JAVA_INTEGER = "java.lang.Integer";
- public static final String JAVA_SHORT = "java.lang.Short";
- public static final String JAVA_BYTE = "java.lang.Byte";
- public static final String JAVA_TIME = "java.sql.Time";
- public static final String JAVA_TIMESTAMP = "java.sql.Timestamp";
- public static final String JAVA_BLOB = "java.sql.Blob";
-
- /**
- * Keys: java class names, Values: SQL int type definitions from
- * java.sql.Types
- */
- private final Map<String, Integer> javaSqlEnum = new HashMap<>();
-
- private final Map<DbType, String> mapping = new HashMap<>();
- private final SortedSet<DbType> dbTypes = new TreeSet<>();
-
- private Map<String, String> classToPrimitive;
-
- {
- add(Types.BIGINT, JAVA_LONG);
- add(Types.BINARY, JAVA_BYTES);
- add(Types.BIT, JAVA_BOOLEAN);
- add(Types.BOOLEAN, JAVA_BOOLEAN);
- add(Types.BLOB, JAVA_BYTES);
- add(Types.CLOB, JAVA_STRING);
- add(Types.NCLOB, JAVA_STRING);
- add(Types.SQLXML, JAVA_STRING);
- add(Types.CHAR, JAVA_STRING);
- add(Types.NCHAR, JAVA_STRING);
- add(Types.DATE, JAVA_UTILDATE);
- add(Types.DECIMAL, JAVA_BIGDECIMAL);
- add(Types.DOUBLE, JAVA_DOUBLE);
- add(Types.FLOAT, JAVA_FLOAT);
- add(Types.INTEGER, JAVA_INTEGER);
- add(Types.LONGVARCHAR, JAVA_STRING);
- add(Types.LONGNVARCHAR, JAVA_STRING);
- add(Types.LONGVARBINARY, JAVA_BYTES);
- add(Types.NUMERIC, JAVA_BIGDECIMAL);
- add(Types.REAL, JAVA_FLOAT);
- add(Types.SMALLINT, JAVA_SHORT);
- add(Types.TINYINT, JAVA_SHORT);
- add(Types.TIME, JAVA_UTILDATE);
- add(Types.TIMESTAMP, JAVA_UTILDATE);
- add(Types.VARBINARY, JAVA_BYTES);
- add(Types.VARCHAR, JAVA_STRING);
- add(Types.NVARCHAR, JAVA_STRING);
-
- javaSqlEnum.put(JAVA_LONG, Types.BIGINT);
- javaSqlEnum.put(JAVA_BYTES, Types.BINARY);
- javaSqlEnum.put(JAVA_BOOLEAN, Types.BIT);
- javaSqlEnum.put(JAVA_STRING, Types.VARCHAR);
- javaSqlEnum.put(JAVA_SQLDATE, Types.DATE);
- javaSqlEnum.put(JAVA_UTILDATE, Types.DATE);
- javaSqlEnum.put(JAVA_TIMESTAMP, Types.TIMESTAMP);
- javaSqlEnum.put(JAVA_BIGDECIMAL, Types.DECIMAL);
- javaSqlEnum.put(JAVA_DOUBLE, Types.DOUBLE);
- javaSqlEnum.put(JAVA_FLOAT, Types.FLOAT);
- javaSqlEnum.put(JAVA_INTEGER, Types.INTEGER);
- javaSqlEnum.put(JAVA_SHORT, Types.SMALLINT);
- javaSqlEnum.put(JAVA_BYTE, Types.SMALLINT);
- javaSqlEnum.put(JAVA_TIME, Types.TIME);
- javaSqlEnum.put(JAVA_TIMESTAMP, Types.TIMESTAMP);
-
- // add primitives
- javaSqlEnum.put("byte", Types.TINYINT);
- javaSqlEnum.put("int", Types.INTEGER);
- javaSqlEnum.put("short", Types.SMALLINT);
- javaSqlEnum.put("char", Types.CHAR);
- javaSqlEnum.put("double", Types.DOUBLE);
- javaSqlEnum.put("long", Types.BIGINT);
- javaSqlEnum.put("float", Types.FLOAT);
- javaSqlEnum.put("boolean", Types.BIT);
-
- classToPrimitive = new HashMap<>();
- classToPrimitive.put(Byte.class.getName(), "byte");
- classToPrimitive.put(Long.class.getName(), "long");
- classToPrimitive.put(Double.class.getName(), "double");
- classToPrimitive.put(Boolean.class.getName(), "boolean");
- classToPrimitive.put(Float.class.getName(), "float");
- classToPrimitive.put(Short.class.getName(), "short");
- classToPrimitive.put(Integer.class.getName(), "int");
- }
-
- private Boolean usePrimitives;
-
- /**
- * Returns default java.sql.Types type by the Java type name.
- *
- * @param className
- * Fully qualified Java Class name.
- * @return The SQL type or NOT_DEFINED if no type found.
- */
- public int getJdbcTypeByJava(DbAttribute attribute, String className) {
- if (className == null) {
- return NOT_DEFINED;
- }
-
- Integer type = javaSqlEnum.get(className);
- if (type != null) {
- return type;
- }
-
- // try to load a Java class - some nonstandard mappings may work
- try {
- return getSqlTypeByJava(attribute, Util.getJavaClass(className));
- } catch (Throwable th) {
- return NOT_DEFINED;
- }
- }
-
- public void add(int jdbcType, String java) {
- add(new DbType(TypesMapping.getSqlNameByType(jdbcType)), java);
- }
-
- @Override
- public void add(DbType type, String java) {
- mapping.put(type, java);
- dbTypes.add(type);
- }
-
- /**
- * Guesses a default JDBC type for the Java class.
- *
- * @since 1.1
- */
- protected int getSqlTypeByJava(DbAttribute attribute, Class<?> javaClass) {
- if (javaClass == null) {
- return NOT_DEFINED;
- }
-
- // check standard mapping of class and superclasses
- Class<?> aClass = javaClass;
- while (aClass != null) {
-
- String name;
-
- if (aClass.isArray()) {
- name = aClass.getComponentType().getName() + "[]";
- } else {
- name = aClass.getName();
- }
-
- Object type = javaSqlEnum.get(name);
- if (type != null) {
- return ((Number) type).intValue();
- }
-
- aClass = aClass.getSuperclass();
- }
-
- // check non-standard JDBC types that are still supported by JPA
- if (javaClass.isArray()) {
-
- Class<?> elementType = javaClass.getComponentType();
- if (Character.class.isAssignableFrom(elementType) || Character.TYPE.isAssignableFrom(elementType)) {
- return Types.VARCHAR;
- } else if (Byte.class.isAssignableFrom(elementType) || Byte.TYPE.isAssignableFrom(elementType)) {
- return Types.VARBINARY;
- }
- }
-
- if (Calendar.class.isAssignableFrom(javaClass)) {
- return Types.TIMESTAMP;
- }
-
- if (BigInteger.class.isAssignableFrom(javaClass)) {
- return Types.BIGINT;
- }
-
- if (Serializable.class.isAssignableFrom(javaClass)) {
- // serializable check should be the last one when all other mapping
- // attempts failed
- return Types.VARBINARY;
- }
-
- return NOT_DEFINED;
- }
-
- /**
- * Get the corresponding Java type by its java.sql.Types counterpart. Note
- * that this method should be used as a last resort, with explicit mapping
- * provided by user used as a first choice, as it can only guess how to map
- * certain types, such as NUMERIC, etc.
- *
- * @return Fully qualified Java type name or null if not found.
- */
- @Override
- public String getJavaByJdbcType(DbAttribute attribute, int type) {
- String jdbcType = TypesMapping.getSqlNameByType(type);
- DbType dbType;
- if (attribute != null) {
- dbType = new DbType(jdbcType, attribute.getMaxLength(), attribute.getAttributePrecision(),
- attribute.getScale(), attribute.isMandatory());
- } else {
- dbType = new DbType(jdbcType);
- }
-
- String typeName = getJavaByJdbcType(dbType);
-
- if (usePrimitives != null && usePrimitives) {
- String primitive = classToPrimitive.get(typeName);
- if (primitive != null) {
- return primitive;
- }
- }
-
- return typeName;
- }
-
- public String getJavaByJdbcType(DbType type) {
- for (DbType t : dbTypes) {
- if (t.isCover(type)) {
- // because dbTypes sorted by specificity we will take first and
- // the most specific matching
- // that applicable for attribute
- return mapping.get(t);
- }
- }
-
- return null;
- }
-
- public Boolean getUsePrimitives() {
- return usePrimitives;
- }
-
- public void setUsePrimitives(Boolean usePrimitives) {
- this.usePrimitives = usePrimitives;
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/Jdbc2JavaTypeMapper.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/Jdbc2JavaTypeMapper.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/Jdbc2JavaTypeMapper.java
deleted file mode 100644
index 160dc4e..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/Jdbc2JavaTypeMapper.java
+++ /dev/null
@@ -1,33 +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.access.loader.mapper;
-
-import org.apache.cayenne.map.DbAttribute;
-
-/**
- * @since 4.0.
- */
-public interface Jdbc2JavaTypeMapper {
-
- String getJavaByJdbcType(DbAttribute attribute, int type);
-
- int getJdbcTypeByJava(DbAttribute attribute, String className);
-
- void add(DbType type, String java);
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java
index a8876f6..cb436e6 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/AutoAdapter.java
@@ -33,7 +33,6 @@ import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.merge.MergerFactory;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SelectQuery;
@@ -216,11 +215,6 @@ public class AutoAdapter implements DbAdapter {
}
@Override
- public MergerFactory mergerFactory() {
- return getAdapter().mergerFactory();
- }
-
- @Override
public void createTableAppendColumn(StringBuffer sqlBuffer, DbAttribute column) {
getAdapter().createTableAppendColumn(sqlBuffer, column);
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java
index d72bc31..e89ae4b 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/DbAdapter.java
@@ -29,7 +29,6 @@ import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.merge.MergerFactory;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SelectQuery;
@@ -183,11 +182,6 @@ public interface DbAdapter {
String tableTypeForView();
/**
- * @since 3.0
- */
- MergerFactory mergerFactory();
-
- /**
* Append the column type part of a "create table" to the given
* {@link StringBuffer}
*
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
index 57d3430..979b425 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
@@ -36,8 +36,11 @@ import org.apache.cayenne.configuration.Constants;
import org.apache.cayenne.configuration.RuntimeProperties;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.log.JdbcEventLogger;
-import org.apache.cayenne.map.*;
-import org.apache.cayenne.merge.MergerFactory;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.EntityResolver;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SelectQuery;
@@ -600,13 +603,6 @@ public class JdbcAdapter implements DbAdapter {
}
/**
- * @since 3.0
- */
- public MergerFactory mergerFactory() {
- return new MergerFactory();
- }
-
- /**
* @return
* @since 4.0
*/
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/PerAdapterProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/PerAdapterProvider.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/PerAdapterProvider.java
new file mode 100644
index 0000000..d4b2816
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/PerAdapterProvider.java
@@ -0,0 +1,46 @@
+/*****************************************************************
+ * 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.dba;
+
+import org.apache.cayenne.di.DIRuntimeException;
+
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * An injectable provider that returns a given service in a context of a specific {@link DbAdapter}.
+ * This allows modules to create adapter-specific extensions without altering DbAdapter API.
+ *
+ * @since 4.0
+ */
+public class PerAdapterProvider<T> {
+
+ private Map<String, T> perAdapterValues;
+ private T defaultValue;
+
+ public PerAdapterProvider(Map<String, T> perAdapterValues, T defaultValue) {
+ this.perAdapterValues = Objects.requireNonNull(perAdapterValues);
+ this.defaultValue = Objects.requireNonNull(defaultValue);
+ }
+
+ public T get(DbAdapter adapter) throws DIRuntimeException {
+ T t = perAdapterValues.get(adapter.unwrap().getClass().getName());
+ return t != null ? t : defaultValue;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Adapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Adapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Adapter.java
index f71f655..edf8901 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Adapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Adapter.java
@@ -24,7 +24,12 @@ import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.translator.select.QualifierTranslator;
import org.apache.cayenne.access.translator.select.QueryAssembler;
-import org.apache.cayenne.access.types.*;
+import org.apache.cayenne.access.types.BooleanType;
+import org.apache.cayenne.access.types.ByteArrayType;
+import org.apache.cayenne.access.types.CharType;
+import org.apache.cayenne.access.types.ExtendedType;
+import org.apache.cayenne.access.types.ExtendedTypeFactory;
+import org.apache.cayenne.access.types.ExtendedTypeMap;
import org.apache.cayenne.configuration.Constants;
import org.apache.cayenne.configuration.RuntimeProperties;
import org.apache.cayenne.dba.JdbcAdapter;
@@ -34,7 +39,6 @@ import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.merge.MergerFactory;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.resource.ResourceLocator;
@@ -223,11 +227,6 @@ public class DB2Adapter extends JdbcAdapter {
}
@Override
- public MergerFactory mergerFactory() {
- return new DB2MergerFactory();
- }
-
- @Override
public void bindParameter(
PreparedStatement statement, ParameterBinding binding) throws SQLException, Exception {
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2MergerFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2MergerFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2MergerFactory.java
deleted file mode 100644
index 8ae070d..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2MergerFactory.java
+++ /dev/null
@@ -1,49 +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.dba.db2;
-
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.merge.MergerFactory;
-import org.apache.cayenne.merge.MergerToken;
-import org.apache.cayenne.merge.SetColumnTypeToDb;
-
-
-public class DB2MergerFactory extends MergerFactory {
-
- @Override
- public MergerToken createSetColumnTypeToDb(
- final DbEntity entity,
- DbAttribute columnOriginal,
- final DbAttribute columnNew) {
-
- return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
-
- @Override
- protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(entity));
- sqlBuffer.append(" ALTER COLUMN ");
- sqlBuffer.append(context.quotedName(columnNew));
- sqlBuffer.append(" SET DATA TYPE ");
- }
- };
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyAdapter.java
index 8a3b462..916eb9e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyAdapter.java
@@ -25,7 +25,12 @@ import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
import org.apache.cayenne.access.translator.select.QualifierTranslator;
import org.apache.cayenne.access.translator.select.QueryAssembler;
-import org.apache.cayenne.access.types.*;
+import org.apache.cayenne.access.types.ByteType;
+import org.apache.cayenne.access.types.CharType;
+import org.apache.cayenne.access.types.ExtendedType;
+import org.apache.cayenne.access.types.ExtendedTypeFactory;
+import org.apache.cayenne.access.types.ExtendedTypeMap;
+import org.apache.cayenne.access.types.ShortType;
import org.apache.cayenne.configuration.Constants;
import org.apache.cayenne.configuration.RuntimeProperties;
import org.apache.cayenne.dba.JdbcAdapter;
@@ -33,7 +38,6 @@ import org.apache.cayenne.dba.PkGenerator;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.merge.MergerFactory;
import org.apache.cayenne.resource.ResourceLocator;
import java.sql.PreparedStatement;
@@ -44,14 +48,14 @@ import java.util.List;
/**
* DbAdapter implementation for the <a href="http://db.apache.org/derby/"> Derby RDBMS
* </a>. Sample connection settings to use with Derby are shown below. <h3>Embedded</h3>
- *
+ * <p>
* <pre>
* test-derby.jdbc.url = jdbc:derby:testdb;create=true
* test-derby.jdbc.driver = org.apache.derby.jdbc.EmbeddedDriver
* </pre>
- *
+ * <p>
* <h3>Network Server</h3>
- *
+ * <p>
* <pre>
* derbynet.jdbc.url = jdbc:derby://localhost/cayenne
* derbynet.jdbc.driver = org.apache.derby.jdbc.ClientDriver
@@ -103,7 +107,7 @@ public class DerbyAdapter extends JdbcAdapter {
/**
* Appends SQL for column creation to CREATE TABLE buffer. Only change for Derby is
* that " NULL" is not supported.
- *
+ *
* @since 1.2
*/
@Override
@@ -118,7 +122,6 @@ public class DerbyAdapter extends JdbcAdapter {
}
-
sqlBuffer.append(quotingStrategy.quotedName(column));
sqlBuffer.append(' ');
@@ -168,7 +171,7 @@ public class DerbyAdapter extends JdbcAdapter {
translator.setCaseInsensitive(caseInsensitiveCollations);
return translator;
}
-
+
/**
* @since 3.1
*/
@@ -180,11 +183,6 @@ public class DerbyAdapter extends JdbcAdapter {
}
@Override
- public MergerFactory mergerFactory() {
- return new DerbyMergerFactory();
- }
-
- @Override
public void bindParameter(
PreparedStatement statement,
ParameterBinding binding) throws SQLException, Exception {
@@ -199,10 +197,14 @@ public class DerbyAdapter extends JdbcAdapter {
private int convertNTypes(int sqlType) {
switch (sqlType) {
- case Types.NCHAR: return Types.CHAR;
- case Types.NVARCHAR: return Types.VARCHAR;
- case Types.LONGNVARCHAR: return Types.LONGVARCHAR;
- case Types.NCLOB: return Types.CLOB;
+ case Types.NCHAR:
+ return Types.CHAR;
+ case Types.NVARCHAR:
+ return Types.VARCHAR;
+ case Types.LONGNVARCHAR:
+ return Types.LONGVARCHAR;
+ case Types.NCLOB:
+ return Types.CLOB;
default:
return sqlType;
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyMergerFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyMergerFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyMergerFactory.java
deleted file mode 100644
index 7ce30d4..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyMergerFactory.java
+++ /dev/null
@@ -1,86 +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.dba.derby;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.merge.MergerFactory;
-import org.apache.cayenne.merge.MergerToken;
-import org.apache.cayenne.merge.SetAllowNullToDb;
-import org.apache.cayenne.merge.SetColumnTypeToDb;
-import org.apache.cayenne.merge.SetNotNullToDb;
-
-public class DerbyMergerFactory extends MergerFactory {
-
- @Override
- public MergerToken createSetColumnTypeToDb(
- final DbEntity entity,
- DbAttribute columnOriginal,
- final DbAttribute columnNew) {
-
- return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
-
- @Override
- protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
- // http://db.apache.org/derby/manuals/reference/sqlj26.html
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(entity));
- sqlBuffer.append(" ALTER ");
- sqlBuffer.append(context.quotedName(columnNew));
- sqlBuffer.append(" SET DATA TYPE ");
- }
- };
- }
-
- @Override
- public MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column) {
- return new SetNotNullToDb(entity, column) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- QuotingStrategy context = adapter.getQuotingStrategy();
-
- return Collections.singletonList("ALTER TABLE " + context.quotedFullyQualifiedName(getEntity())
- + " ALTER COLUMN " + context.quotedName(getColumn()) + " NOT NULL");
- }
-
- };
- }
-
- @Override
- public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
- return new SetAllowNullToDb(entity, column) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- QuotingStrategy context = adapter.getQuotingStrategy();
-
- return Collections.singletonList("ALTER TABLE " + context.quotedFullyQualifiedName(getEntity())
- + " ALTER COLUMN " + context.quotedName(getColumn()) + " NULL");
- }
-
- };
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdAdapter.java
index 9146bd5..c88c88f 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdAdapter.java
@@ -76,11 +76,7 @@ public class FirebirdAdapter extends JdbcAdapter {
map.registerType(new CharType(true, false));
}
-
- public FirebirdMergerFactory mergerFactory() {
- return new FirebirdMergerFactory();
- }
-
+
public void createTableAppendColumn(StringBuffer sqlBuffer, DbAttribute column) {
String[] types = externalTypesForJdbcType(column.getType());
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdMergerFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdMergerFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdMergerFactory.java
deleted file mode 100644
index 45f3832..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdMergerFactory.java
+++ /dev/null
@@ -1,91 +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.dba.firebird;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.merge.MergerFactory;
-import org.apache.cayenne.merge.MergerToken;
-import org.apache.cayenne.merge.AddColumnToDb;
-import org.apache.cayenne.merge.DropColumnToDb;
-import org.apache.cayenne.merge.SetNotNullToDb;
-import org.apache.cayenne.merge.SetAllowNullToDb;
-
-public class FirebirdMergerFactory extends MergerFactory {
-
- public MergerToken createDropColumnToDb(DbEntity entity, DbAttribute column) {
- return new DropColumnToDb(entity, column) {
- public List<String> createSql(DbAdapter adapter) {
- QuotingStrategy quoting = adapter.getQuotingStrategy();
- return Collections.singletonList("ALTER TABLE " + quoting.quotedFullyQualifiedName(getEntity())
- + " DROP " + quoting.quotedName(getColumn()));
- }
- };
- }
-
- @Override
- public MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column) {
- return new SetNotNullToDb(entity, column) {
- public List<String> createSql(DbAdapter adapter) {
- QuotingStrategy context = adapter.getQuotingStrategy();
- String entityName = context.quotedFullyQualifiedName(getEntity()) ;
- String columnName = context.quotedName(getColumn());
- // Firebird doesn't support ALTER TABLE table_name ALTER column_name SET NOT NULL
- // but this might be achived by modyfication of system tables
- return Collections.singletonList(String.format("UPDATE RDB$RELATION_FIELDS SET RDB$NULL_FLAG = 1 "+
- "WHERE RDB$FIELD_NAME = '%s' AND RDB$RELATION_NAME = '%s'", columnName, entityName));
- }
- };
- }
-
- @Override
- public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
- return new SetAllowNullToDb(entity, column) {
- public List<String> createSql(DbAdapter adapter) {
- QuotingStrategy context = adapter.getQuotingStrategy();
- String entityName = context.quotedFullyQualifiedName(getEntity()) ;
- String columnName = context.quotedName(getColumn());
- // Firebird doesn't support ALTER TABLE table_name ALTER column_name DROP NOT NULL
- // but this might be achived by modyfication system tables
- return Collections.singletonList(String.format("UPDATE RDB$RELATION_FIELDS SET RDB$NULL_FLAG = NULL "+
- " WHERE RDB$FIELD_NAME = '%s' AND RDB$RELATION_NAME = '%s'", columnName, entityName));
- }
- };
- }
-
-
- public MergerToken createAddColumnToDb(DbEntity entity, DbAttribute column) {
- return new AddColumnToDb(entity, column) {
- protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
- sqlBuffer.append(" ADD ");
- sqlBuffer.append(context.quotedName(getColumn()));
- sqlBuffer.append(" ");
- }
- };
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Adapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Adapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Adapter.java
index 768d466..0d99869 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Adapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Adapter.java
@@ -27,7 +27,6 @@ import org.apache.cayenne.dba.JdbcAdapter;
import org.apache.cayenne.dba.PkGenerator;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.merge.MergerFactory;
import org.apache.cayenne.resource.ResourceLocator;
import java.util.List;
@@ -57,11 +56,6 @@ public class H2Adapter extends JdbcAdapter {
}
@Override
- public MergerFactory mergerFactory() {
- return new H2MergerFactory();
- }
-
- @Override
public void createTableAppendColumn(StringBuffer sqlBuffer, DbAttribute column) {
super.createTableAppendColumn(sqlBuffer, column);
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2MergerFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2MergerFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2MergerFactory.java
deleted file mode 100644
index 6ec19aa..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2MergerFactory.java
+++ /dev/null
@@ -1,83 +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.dba.h2;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.merge.MergerFactory;
-import org.apache.cayenne.merge.MergerToken;
-import org.apache.cayenne.merge.SetAllowNullToDb;
-import org.apache.cayenne.merge.SetColumnTypeToDb;
-import org.apache.cayenne.merge.SetPrimaryKeyToDb;
-
-/**
- * @since 3.0
- */
-public class H2MergerFactory extends MergerFactory {
-
- @Override
- public MergerToken createSetColumnTypeToDb(final DbEntity entity, DbAttribute columnOriginal,
- final DbAttribute columnNew) {
- return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
-
- @Override
- protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(entity));
- sqlBuffer.append(" ALTER ");
- sqlBuffer.append(context.quotedName(columnNew));
- sqlBuffer.append(" ");
- }
- };
- }
-
- @Override
- public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
- return new SetAllowNullToDb(entity, column) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- return Collections.singletonList("ALTER TABLE " + getEntity().getFullyQualifiedName()
- + " ALTER COLUMN " + getColumn().getName() + " SET NULL");
- }
-
- };
- }
-
- @Override
- public MergerToken createSetPrimaryKeyToDb(DbEntity entity, Collection<DbAttribute> primaryKeyOriginal,
- Collection<DbAttribute> primaryKeyNew, String detectedPrimaryKeyName) {
- return new SetPrimaryKeyToDb(entity, primaryKeyOriginal, primaryKeyNew, detectedPrimaryKeyName) {
-
- @Override
- protected void appendDropOriginalPrimaryKeySQL(DbAdapter adapter, List<String> sqls) {
- sqls.add("ALTER TABLE " + adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity())
- + " DROP PRIMARY KEY");
- }
-
- };
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java
index 6cfcaa5..96c5c0b 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java
@@ -33,7 +33,6 @@ import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.DbJoin;
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.merge.MergerFactory;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SelectQuery;
@@ -225,10 +224,4 @@ public class HSQLDBAdapter extends JdbcAdapter {
super.createTableAppendColumn(sqlBuffer, column);
}
}
-
- @Override
- public MergerFactory mergerFactory() {
- return new HSQLMergerFactory();
- }
-
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLMergerFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLMergerFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLMergerFactory.java
deleted file mode 100644
index e972b15..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLMergerFactory.java
+++ /dev/null
@@ -1,83 +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.dba.hsqldb;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.merge.MergerFactory;
-import org.apache.cayenne.merge.MergerToken;
-import org.apache.cayenne.merge.SetAllowNullToDb;
-import org.apache.cayenne.merge.SetColumnTypeToDb;
-import org.apache.cayenne.merge.SetPrimaryKeyToDb;
-
-public class HSQLMergerFactory extends MergerFactory {
-
- @Override
- public MergerToken createSetColumnTypeToDb(final DbEntity entity, DbAttribute columnOriginal,
- final DbAttribute columnNew) {
-
- return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
-
- @Override
- protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(entity));
- sqlBuffer.append(" ALTER ");
- sqlBuffer.append(context.quotedName(columnNew));
- sqlBuffer.append(" ");
- }
- };
- }
-
- @Override
- public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
- return new SetAllowNullToDb(entity, column) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- QuotingStrategy context = adapter.getQuotingStrategy();
-
- return Collections.singletonList("ALTER TABLE " + context.quotedFullyQualifiedName(getEntity())
- + " ALTER COLUMN " + context.quotedName(getColumn()) + " NULL");
- }
-
- };
- }
-
- @Override
- public MergerToken createSetPrimaryKeyToDb(DbEntity entity, Collection<DbAttribute> primaryKeyOriginal,
- Collection<DbAttribute> primaryKeyNew, String detectedPrimaryKeyName) {
- return new SetPrimaryKeyToDb(entity, primaryKeyOriginal, primaryKeyNew, detectedPrimaryKeyName) {
-
- @Override
- protected void appendDropOriginalPrimaryKeySQL(DbAdapter adapter, List<String> sqls) {
- sqls.add("ALTER TABLE " + adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity())
- + " DROP PRIMARY KEY");
- }
-
- };
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresAdapter.java
index d9aee83..dc94bae 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresAdapter.java
@@ -37,7 +37,6 @@ import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.merge.MergerFactory;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SelectQuery;
@@ -121,11 +120,6 @@ public class IngresAdapter extends JdbcAdapter {
}
@Override
- public MergerFactory mergerFactory() {
- return new IngresMergerFactory();
- }
-
- @Override
public void createTableAppendColumn(StringBuffer buf, DbAttribute at) {
String[] types = externalTypesForJdbcType(at.getType());
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresMergerFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresMergerFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresMergerFactory.java
deleted file mode 100644
index f8da652..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/ingres/IngresMergerFactory.java
+++ /dev/null
@@ -1,226 +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.dba.ingres;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.dba.TypesMapping;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbJoin;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.merge.AddRelationshipToDb;
-import org.apache.cayenne.merge.DropColumnToDb;
-import org.apache.cayenne.merge.DropRelationshipToDb;
-import org.apache.cayenne.merge.MergerFactory;
-import org.apache.cayenne.merge.MergerToken;
-import org.apache.cayenne.merge.SetAllowNullToDb;
-import org.apache.cayenne.merge.SetColumnTypeToDb;
-import org.apache.cayenne.merge.SetNotNullToDb;
-
-public class IngresMergerFactory extends MergerFactory {
-
- @Override
- public MergerToken createSetColumnTypeToDb(final DbEntity entity, DbAttribute columnOriginal,
- final DbAttribute columnNew) {
-
- return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
-
- @Override
- protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(entity));
- sqlBuffer.append(" ALTER COLUMN ");
- sqlBuffer.append(context.quotedName(columnNew));
- sqlBuffer.append(" ");
- }
- };
- }
-
- @Override
- public MergerToken createDropColumnToDb(DbEntity entity, DbAttribute column) {
- return new DropColumnToDb(entity, column) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- StringBuilder buf = new StringBuilder();
- QuotingStrategy context = adapter.getQuotingStrategy();
- buf.append("ALTER TABLE ");
- buf.append(context.quotedFullyQualifiedName(getEntity()));
- buf.append(" DROP COLUMN ");
- buf.append(context.quotedName(getColumn()));
- buf.append(" RESTRICT ");
-
- return Collections.singletonList(buf.toString());
- }
-
- };
- }
-
- @Override
- public MergerToken createAddRelationshipToDb(DbEntity entity, final DbRelationship rel) {
- return new AddRelationshipToDb(entity, rel) {
- @Override
- public List<String> createSql(DbAdapter adapter) {
- if (!rel.isToMany() && rel.isToPK() && !rel.isToDependentPK()) {
-
- DbEntity source = (DbEntity) rel.getSourceEntity();
- QuotingStrategy context = adapter.getQuotingStrategy();
- StringBuilder buf = new StringBuilder();
- StringBuilder refBuf = new StringBuilder();
-
- buf.append("ALTER TABLE ");
- buf.append(context.quotedFullyQualifiedName(source));
-
- // requires the ADD CONSTRAINT statement
- buf.append(" ADD CONSTRAINT ");
- String name = "U_" + rel.getSourceEntity().getName() + "_"
- + (long) (System.currentTimeMillis() / (Math.random() * 100000));
-
- buf.append(context.quotedIdentifier(rel.getSourceEntity(), name));
- buf.append(" FOREIGN KEY (");
-
- boolean first = true;
- for (DbJoin join : rel.getJoins()) {
- if (!first) {
- buf.append(", ");
- refBuf.append(", ");
- } else
- first = false;
-
- buf.append(context.quotedSourceName(join));
- refBuf.append(context.quotedTargetName(join));
- }
-
- buf.append(") REFERENCES ");
- buf.append(context.quotedFullyQualifiedName((DbEntity) rel.getTargetEntity()));
- buf.append(" (");
- buf.append(refBuf.toString());
- buf.append(')');
-
- // also make sure we delete dependent FKs
- buf.append(" ON DELETE CASCADE");
-
- String fksql = buf.toString();
-
- if (fksql != null) {
- return Collections.singletonList(fksql);
- }
- }
-
- return Collections.emptyList();
-
- }
- };
- }
-
- @Override
- public MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column) {
- return new SetNotNullToDb(entity, column) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
-
- /*
- * TODO: we generate this query as in ingres db documentation,
- * but unfortunately ingres don't support it
- */
-
- StringBuilder sqlBuffer = new StringBuilder();
-
- QuotingStrategy context = adapter.getQuotingStrategy();
-
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(getEntity().getFullyQualifiedName());
- sqlBuffer.append(" ALTER COLUMN ");
- sqlBuffer.append(context.quotedName(getColumn()));
- sqlBuffer.append(" ");
- sqlBuffer.append(adapter.externalTypesForJdbcType(getColumn().getType())[0]);
-
- if (adapter.typeSupportsLength(getColumn().getType()) && getColumn().getMaxLength() > 0) {
- sqlBuffer.append("(");
- sqlBuffer.append(getColumn().getMaxLength());
- sqlBuffer.append(")");
- }
-
- sqlBuffer.append(" NOT NULL");
-
- return Collections.singletonList(sqlBuffer.toString());
- }
-
- };
- }
-
- @Override
- public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
- return new SetAllowNullToDb(entity, column) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- StringBuilder sqlBuffer = new StringBuilder();
- QuotingStrategy context = adapter.getQuotingStrategy();
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
- sqlBuffer.append(" ALTER COLUMN ");
- sqlBuffer.append(context.quotedName(getColumn()));
- sqlBuffer.append(" ");
- sqlBuffer.append(adapter.externalTypesForJdbcType(getColumn().getType())[0]);
-
- if (adapter.typeSupportsLength(getColumn().getType()) && getColumn().getMaxLength() > 0) {
- sqlBuffer.append("(");
- sqlBuffer.append(getColumn().getMaxLength());
- sqlBuffer.append(")");
- }
-
- sqlBuffer.append(" WITH NULL");
-
- return Collections.singletonList(sqlBuffer.toString());
- }
-
- };
- }
-
- @Override
- public MergerToken createDropRelationshipToDb(final DbEntity entity, DbRelationship rel) {
-
- return new DropRelationshipToDb(entity, rel) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- String fkName = getFkName();
-
- if (fkName == null) {
- return Collections.emptyList();
- }
-
- StringBuilder buf = new StringBuilder();
- buf.append("ALTER TABLE ");
- buf.append(adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity()));
- buf.append(" DROP CONSTRAINT ");
- buf.append(fkName);
- buf.append(" CASCADE ");
-
- return Collections.singletonList(buf.toString());
- }
- };
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java
index 961f653..1ecac8a 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLAdapter.java
@@ -27,16 +27,23 @@ import org.apache.cayenne.access.translator.ejbql.JdbcEJBQLTranslatorFactory;
import org.apache.cayenne.access.translator.select.QualifierTranslator;
import org.apache.cayenne.access.translator.select.QueryAssembler;
import org.apache.cayenne.access.translator.select.SelectTranslator;
-import org.apache.cayenne.access.types.*;
+import org.apache.cayenne.access.types.ByteArrayType;
+import org.apache.cayenne.access.types.CharType;
+import org.apache.cayenne.access.types.ExtendedType;
+import org.apache.cayenne.access.types.ExtendedTypeFactory;
+import org.apache.cayenne.access.types.ExtendedTypeMap;
import org.apache.cayenne.configuration.Constants;
import org.apache.cayenne.configuration.RuntimeProperties;
-import org.apache.cayenne.dba.*;
+import org.apache.cayenne.dba.DefaultQuotingStrategy;
+import org.apache.cayenne.dba.JdbcAdapter;
+import org.apache.cayenne.dba.PkGenerator;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.merge.MergerFactory;
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.query.SelectQuery;
@@ -45,7 +52,13 @@ import org.apache.cayenne.resource.ResourceLocator;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
/**
* DbAdapter implementation for <a href="http://www.mysql.com">MySQL RDBMS</a>.
@@ -378,11 +391,6 @@ public class MySQLAdapter extends JdbcAdapter {
}
}
- @Override
- public MergerFactory mergerFactory() {
- return new MySQLMergerFactory();
- }
-
final class PKComparator implements Comparator<DbAttribute> {
public int compare(DbAttribute a1, DbAttribute a2) {
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLMergerFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLMergerFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLMergerFactory.java
deleted file mode 100644
index 43f4b55..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/mysql/MySQLMergerFactory.java
+++ /dev/null
@@ -1,157 +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.dba.mysql;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.merge.DropRelationshipToDb;
-import org.apache.cayenne.merge.MergerFactory;
-import org.apache.cayenne.merge.MergerToken;
-import org.apache.cayenne.merge.SetAllowNullToDb;
-import org.apache.cayenne.merge.SetColumnTypeToDb;
-import org.apache.cayenne.merge.SetNotNullToDb;
-import org.apache.cayenne.merge.SetPrimaryKeyToDb;
-
-public class MySQLMergerFactory extends MergerFactory {
-
- @Override
- public MergerToken createSetNotNullToDb(
- final DbEntity entity,
- final DbAttribute column) {
- return new SetNotNullToDb(entity, column) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- StringBuffer sqlBuffer = new StringBuffer();
-
- QuotingStrategy context = adapter.getQuotingStrategy();
-
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
- sqlBuffer.append(" CHANGE ");
- sqlBuffer.append(context.quotedName(getColumn()));
- sqlBuffer.append(" ");
- adapter.createTableAppendColumn(sqlBuffer, column);
-
- return Collections.singletonList(sqlBuffer.toString());
- }
-
- };
- }
-
- @Override
- public MergerToken createSetAllowNullToDb(
- final DbEntity entity,
- final DbAttribute column) {
- return new SetAllowNullToDb(entity, column) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- StringBuffer sqlBuffer = new StringBuffer();
-
- QuotingStrategy context = adapter.getQuotingStrategy();
-
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
- sqlBuffer.append(" CHANGE ");
- sqlBuffer.append(context.quotedName(getColumn()));
- sqlBuffer.append(" ");
- adapter.createTableAppendColumn(sqlBuffer, column);
-
- return Collections.singletonList(sqlBuffer.toString());
- }
-
- };
- }
-
- @Override
- public MergerToken createSetColumnTypeToDb(
- final DbEntity entity,
- DbAttribute columnOriginal,
- final DbAttribute columnNew) {
-
- return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
-
- @Override
- protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
- // http://dev.mysql.com/tech-resources/articles/mysql-cluster-50.html
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(entity));
- sqlBuffer.append(" MODIFY ");
- sqlBuffer.append(context.quotedName(columnNew));
- sqlBuffer.append(" ");
- }
-
- };
- }
-
- @Override
- public MergerToken createDropRelationshipToDb(
- final DbEntity entity,
- DbRelationship rel) {
-
- return new DropRelationshipToDb(entity, rel) {
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- String fkName = getFkName();
-
- if (fkName == null) {
- return Collections.emptyList();
- }
- QuotingStrategy context = adapter.getQuotingStrategy();
-
- // http://dev.mysql.com/tech-resources/articles/mysql-cluster-50.html
- return Collections.singletonList("ALTER TABLE " + context.quotedFullyQualifiedName(entity) + " DROP FOREIGN KEY " + fkName);
- }
- };
- }
-
- @Override
- public MergerToken createSetPrimaryKeyToDb(
- DbEntity entity,
- Collection<DbAttribute> primaryKeyOriginal,
- Collection<DbAttribute> primaryKeyNew,
- String detectedPrimaryKeyName) {
- return new SetPrimaryKeyToDb(
- entity,
- primaryKeyOriginal,
- primaryKeyNew,
- detectedPrimaryKeyName) {
-
- @Override
- protected void appendDropOriginalPrimaryKeySQL(
- DbAdapter adapter,
- List<String> sqls) {
- sqls.add("ALTER TABLE "
- + adapter.getQuotingStrategy()
- .quotedFullyQualifiedName(getEntity())
- + " DROP PRIMARY KEY");
- }
-
- };
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseAdapter.java
index c4a50db..a426332 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseAdapter.java
@@ -39,7 +39,6 @@ import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.DbJoin;
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.merge.MergerFactory;
import org.apache.cayenne.query.SelectQuery;
import org.apache.cayenne.resource.ResourceLocator;
@@ -53,251 +52,245 @@ import java.util.List;
/**
* DbAdapter implementation for <a href="http://www.openbase.com">OpenBase</a>.
* Sample connection settings to use with OpenBase are shown below:
- *
+ * <p>
* <pre>
* openbase.jdbc.username = test
* openbase.jdbc.password = secret
* openbase.jdbc.url = jdbc:openbase://serverhostname/cayenne
* openbase.jdbc.driver = com.openbase.jdbc.ObDriver
* </pre>
- *
+ *
* @since 1.1
*/
public class OpenBaseAdapter extends JdbcAdapter {
- public OpenBaseAdapter(@Inject RuntimeProperties runtimeProperties,
- @Inject(Constants.SERVER_DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes,
- @Inject(Constants.SERVER_USER_TYPES_LIST) List<ExtendedType> userExtendedTypes,
- @Inject(Constants.SERVER_TYPE_FACTORIES_LIST) List<ExtendedTypeFactory> extendedTypeFactories,
- @Inject(Constants.SERVER_RESOURCE_LOCATOR) ResourceLocator resourceLocator) {
- super(runtimeProperties, defaultExtendedTypes, userExtendedTypes, extendedTypeFactories, resourceLocator);
-
- // init defaults
- this.setSupportsUniqueConstraints(false);
- }
-
- /**
- * @since 4.0
- */
- @Override
- public SelectTranslator getSelectTranslator(SelectQuery<?> query, EntityResolver entityResolver) {
- return new OpenBaseSelectTranslator(query, this, entityResolver);
- }
-
- @Override
- protected void configureExtendedTypes(ExtendedTypeMap map) {
- super.configureExtendedTypes(map);
-
- // Byte handling doesn't work on read...
- // need special converter
- map.registerType(new OpenBaseByteType());
-
- map.registerType(new OpenBaseCharType());
- }
-
- @Override
- public DbAttribute buildAttribute(String name, String typeName, int type, int size, int scale, boolean allowNulls) {
-
- // OpenBase makes no distinction between CHAR and VARCHAR
- // so lets use VARCHAR, since it seems more generic
- if (type == Types.CHAR) {
- type = Types.VARCHAR;
- }
-
- return super.buildAttribute(name, typeName, type, size, scale, allowNulls);
- }
-
- /**
- * Returns word "go".
- */
- @Override
- public String getBatchTerminator() {
- return "go";
- }
-
- /**
- * Returns null, since views are not yet supported in openbase.
- */
- @Override
- public String tableTypeForView() {
- // TODO: according to OpenBase docs views *ARE* supported.
- return null;
- }
-
- /**
- * Returns OpenBase-specific translator for queries.
- */
- @Override
- public QualifierTranslator getQualifierTranslator(QueryAssembler queryAssembler) {
- return new OpenBaseQualifierTranslator(queryAssembler);
- }
-
- /**
- * Creates and returns a primary key generator. Overrides superclass
- * implementation to return an instance of OpenBasePkGenerator that uses
- * built-in multi-server primary key generation.
- */
- @Override
- protected PkGenerator createPkGenerator() {
- return new OpenBasePkGenerator(this);
- }
-
- /**
- * Returns a SQL string that can be used to create database table
- * corresponding to <code>ent</code> parameter.
- */
- @Override
- public String createTable(DbEntity ent) {
-
- StringBuilder buf = new StringBuilder();
-
- buf.append("CREATE TABLE ");
- buf.append(quotingStrategy.quotedFullyQualifiedName(ent));
- buf.append(" (");
-
- // columns
- Iterator<DbAttribute> it = ent.getAttributes().iterator();
- boolean first = true;
- while (it.hasNext()) {
- if (first) {
- first = false;
- } else {
- buf.append(", ");
- }
-
- DbAttribute at = it.next();
-
- // attribute may not be fully valid, do a simple check
- if (at.getType() == TypesMapping.NOT_DEFINED) {
- throw new CayenneRuntimeException("Undefined type for attribute '" + ent.getFullyQualifiedName() + "."
- + at.getName() + "'.");
- }
-
- String[] types = externalTypesForJdbcType(at.getType());
- if (types == null || types.length == 0) {
- throw new CayenneRuntimeException("Undefined type for attribute '" + ent.getFullyQualifiedName() + "."
- + at.getName() + "': " + at.getType());
- }
-
- String type = types[0];
- buf.append(quotingStrategy.quotedName(at)).append(' ').append(type);
-
- // append size and precision (if applicable)
- if (typeSupportsLength(at.getType())) {
- int len = at.getMaxLength();
- int scale = TypesMapping.isDecimal(at.getType()) ? at.getScale() : -1;
-
- // sanity check
- if (scale > len) {
- scale = -1;
- }
-
- if (len > 0) {
- buf.append('(').append(len);
-
- if (scale >= 0) {
- buf.append(", ").append(scale);
- }
-
- buf.append(')');
- }
- }
-
- if (at.isMandatory()) {
- buf.append(" NOT NULL");
- } else {
- buf.append(" NULL");
- }
- }
-
- buf.append(')');
- return buf.toString();
- }
-
- /**
- * Returns a SQL string that can be used to create a foreign key constraint
- * for the relationship.
- */
- @Override
- public String createFkConstraint(DbRelationship rel) {
- StringBuilder buf = new StringBuilder();
-
- // OpendBase Specifics is that we need to create a constraint going
- // from destination to source for this to work...
-
- DbEntity sourceEntity = (DbEntity) rel.getSourceEntity();
- DbEntity targetEntity = (DbEntity) rel.getTargetEntity();
- String toMany = (!rel.isToMany()) ? "'1'" : "'0'";
-
- // TODO: doesn't seem like OpenBase supports compound joins...
- // need to doublecheck that
-
- int joinsLen = rel.getJoins().size();
- if (joinsLen == 0) {
- throw new CayenneRuntimeException("Relationship has no joins: " + rel.getName());
- } else if (joinsLen > 1) {
- // ignore extra joins
- }
-
- DbJoin join = rel.getJoins().get(0);
-
- buf.append("INSERT INTO _SYS_RELATIONSHIP (").append("dest_table, dest_column, source_table, source_column, ")
- .append("block_delete, cascade_delete, one_to_many, operator, relationshipName").append(") VALUES ('")
- .append(sourceEntity.getFullyQualifiedName()).append("', '").append(join.getSourceName())
- .append("', '").append(targetEntity.getFullyQualifiedName()).append("', '")
- .append(join.getTargetName()).append("', 0, 0, ").append(toMany).append(", '=', '")
- .append(rel.getName()).append("')");
-
- return buf.toString();
- }
-
- // OpenBase JDBC driver has trouble reading "integer" as byte
- // this converter addresses such problem
- static class OpenBaseByteType extends ByteType {
-
- OpenBaseByteType() {
- super(true);
- }
-
- @Override
- public Object materializeObject(ResultSet rs, int index, int type) throws Exception {
-
- // read value as int, and then narrow it down
- int val = rs.getInt(index);
- return (rs.wasNull()) ? null : Byte.valueOf((byte) val);
- }
-
- @Override
- public Object materializeObject(CallableStatement rs, int index, int type) throws Exception {
-
- // read value as int, and then narrow it down
- int val = rs.getInt(index);
- return (rs.wasNull()) ? null : Byte.valueOf((byte) val);
- }
- }
-
- static class OpenBaseCharType extends CharType {
-
- OpenBaseCharType() {
- super(false, true);
- }
-
- @Override
- public void setJdbcObject(PreparedStatement st, Object val, int pos, int type, int precision) throws Exception {
-
- // These to types map to "text"; and when setting "text" as object
- // OB assumes that the object is the actual CLOB... weird
- if (type == Types.CLOB || type == Types.LONGVARCHAR) {
- st.setString(pos, (String) val);
- } else {
- super.setJdbcObject(st, val, pos, type, precision);
- }
- }
- }
-
- @Override
- public MergerFactory mergerFactory() {
- return new OpenBaseMergerFactory();
- }
-
+ public OpenBaseAdapter(@Inject RuntimeProperties runtimeProperties,
+ @Inject(Constants.SERVER_DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes,
+ @Inject(Constants.SERVER_USER_TYPES_LIST) List<ExtendedType> userExtendedTypes,
+ @Inject(Constants.SERVER_TYPE_FACTORIES_LIST) List<ExtendedTypeFactory> extendedTypeFactories,
+ @Inject(Constants.SERVER_RESOURCE_LOCATOR) ResourceLocator resourceLocator) {
+ super(runtimeProperties, defaultExtendedTypes, userExtendedTypes, extendedTypeFactories, resourceLocator);
+
+ // init defaults
+ this.setSupportsUniqueConstraints(false);
+ }
+
+ /**
+ * @since 4.0
+ */
+ @Override
+ public SelectTranslator getSelectTranslator(SelectQuery<?> query, EntityResolver entityResolver) {
+ return new OpenBaseSelectTranslator(query, this, entityResolver);
+ }
+
+ @Override
+ protected void configureExtendedTypes(ExtendedTypeMap map) {
+ super.configureExtendedTypes(map);
+
+ // Byte handling doesn't work on read...
+ // need special converter
+ map.registerType(new OpenBaseByteType());
+
+ map.registerType(new OpenBaseCharType());
+ }
+
+ @Override
+ public DbAttribute buildAttribute(String name, String typeName, int type, int size, int scale, boolean allowNulls) {
+
+ // OpenBase makes no distinction between CHAR and VARCHAR
+ // so lets use VARCHAR, since it seems more generic
+ if (type == Types.CHAR) {
+ type = Types.VARCHAR;
+ }
+
+ return super.buildAttribute(name, typeName, type, size, scale, allowNulls);
+ }
+
+ /**
+ * Returns word "go".
+ */
+ @Override
+ public String getBatchTerminator() {
+ return "go";
+ }
+
+ /**
+ * Returns null, since views are not yet supported in openbase.
+ */
+ @Override
+ public String tableTypeForView() {
+ // TODO: according to OpenBase docs views *ARE* supported.
+ return null;
+ }
+
+ /**
+ * Returns OpenBase-specific translator for queries.
+ */
+ @Override
+ public QualifierTranslator getQualifierTranslator(QueryAssembler queryAssembler) {
+ return new OpenBaseQualifierTranslator(queryAssembler);
+ }
+
+ /**
+ * Creates and returns a primary key generator. Overrides superclass
+ * implementation to return an instance of OpenBasePkGenerator that uses
+ * built-in multi-server primary key generation.
+ */
+ @Override
+ protected PkGenerator createPkGenerator() {
+ return new OpenBasePkGenerator(this);
+ }
+
+ /**
+ * Returns a SQL string that can be used to create database table
+ * corresponding to <code>ent</code> parameter.
+ */
+ @Override
+ public String createTable(DbEntity ent) {
+
+ StringBuilder buf = new StringBuilder();
+
+ buf.append("CREATE TABLE ");
+ buf.append(quotingStrategy.quotedFullyQualifiedName(ent));
+ buf.append(" (");
+
+ // columns
+ Iterator<DbAttribute> it = ent.getAttributes().iterator();
+ boolean first = true;
+ while (it.hasNext()) {
+ if (first) {
+ first = false;
+ } else {
+ buf.append(", ");
+ }
+
+ DbAttribute at = it.next();
+
+ // attribute may not be fully valid, do a simple check
+ if (at.getType() == TypesMapping.NOT_DEFINED) {
+ throw new CayenneRuntimeException("Undefined type for attribute '" + ent.getFullyQualifiedName() + "."
+ + at.getName() + "'.");
+ }
+
+ String[] types = externalTypesForJdbcType(at.getType());
+ if (types == null || types.length == 0) {
+ throw new CayenneRuntimeException("Undefined type for attribute '" + ent.getFullyQualifiedName() + "."
+ + at.getName() + "': " + at.getType());
+ }
+
+ String type = types[0];
+ buf.append(quotingStrategy.quotedName(at)).append(' ').append(type);
+
+ // append size and precision (if applicable)
+ if (typeSupportsLength(at.getType())) {
+ int len = at.getMaxLength();
+ int scale = TypesMapping.isDecimal(at.getType()) ? at.getScale() : -1;
+
+ // sanity check
+ if (scale > len) {
+ scale = -1;
+ }
+
+ if (len > 0) {
+ buf.append('(').append(len);
+
+ if (scale >= 0) {
+ buf.append(", ").append(scale);
+ }
+
+ buf.append(')');
+ }
+ }
+
+ if (at.isMandatory()) {
+ buf.append(" NOT NULL");
+ } else {
+ buf.append(" NULL");
+ }
+ }
+
+ buf.append(')');
+ return buf.toString();
+ }
+
+ /**
+ * Returns a SQL string that can be used to create a foreign key constraint
+ * for the relationship.
+ */
+ @Override
+ public String createFkConstraint(DbRelationship rel) {
+ StringBuilder buf = new StringBuilder();
+
+ // OpendBase Specifics is that we need to create a constraint going
+ // from destination to source for this to work...
+
+ DbEntity sourceEntity = (DbEntity) rel.getSourceEntity();
+ DbEntity targetEntity = (DbEntity) rel.getTargetEntity();
+ String toMany = (!rel.isToMany()) ? "'1'" : "'0'";
+
+ // TODO: doesn't seem like OpenBase supports compound joins...
+ // need to doublecheck that
+
+ int joinsLen = rel.getJoins().size();
+ if (joinsLen == 0) {
+ throw new CayenneRuntimeException("Relationship has no joins: " + rel.getName());
+ } else if (joinsLen > 1) {
+ // ignore extra joins
+ }
+
+ DbJoin join = rel.getJoins().get(0);
+
+ buf.append("INSERT INTO _SYS_RELATIONSHIP (").append("dest_table, dest_column, source_table, source_column, ")
+ .append("block_delete, cascade_delete, one_to_many, operator, relationshipName").append(") VALUES ('")
+ .append(sourceEntity.getFullyQualifiedName()).append("', '").append(join.getSourceName())
+ .append("', '").append(targetEntity.getFullyQualifiedName()).append("', '")
+ .append(join.getTargetName()).append("', 0, 0, ").append(toMany).append(", '=', '")
+ .append(rel.getName()).append("')");
+
+ return buf.toString();
+ }
+
+ // OpenBase JDBC driver has trouble reading "integer" as byte
+ // this converter addresses such problem
+ static class OpenBaseByteType extends ByteType {
+
+ OpenBaseByteType() {
+ super(true);
+ }
+
+ @Override
+ public Object materializeObject(ResultSet rs, int index, int type) throws Exception {
+
+ // read value as int, and then narrow it down
+ int val = rs.getInt(index);
+ return (rs.wasNull()) ? null : Byte.valueOf((byte) val);
+ }
+
+ @Override
+ public Object materializeObject(CallableStatement rs, int index, int type) throws Exception {
+
+ // read value as int, and then narrow it down
+ int val = rs.getInt(index);
+ return (rs.wasNull()) ? null : Byte.valueOf((byte) val);
+ }
+ }
+
+ static class OpenBaseCharType extends CharType {
+
+ OpenBaseCharType() {
+ super(false, true);
+ }
+
+ @Override
+ public void setJdbcObject(PreparedStatement st, Object val, int pos, int type, int precision) throws Exception {
+
+ // These to types map to "text"; and when setting "text" as object
+ // OB assumes that the object is the actual CLOB... weird
+ if (type == Types.CLOB || type == Types.LONGVARCHAR) {
+ st.setString(pos, (String) val);
+ } else {
+ super.setJdbcObject(st, val, pos, type, precision);
+ }
+ }
+ }
}
[11/15] cayenne git commit: CAY-2116 Split schema synchronization
code in a separate module
Posted by aa...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/IncludeTableFilter.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/IncludeTableFilter.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/IncludeTableFilter.java
new file mode 100644
index 0000000..ad68b49
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/IncludeTableFilter.java
@@ -0,0 +1,71 @@
+/*****************************************************************
+ * 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.dbsync.reverse.filters;
+
+import java.util.regex.Pattern;
+
+/**
+* @since 4.0.
+*/
+public class IncludeTableFilter implements Comparable<IncludeTableFilter> {
+ public final Pattern pattern;
+
+ public final PatternFilter columnsFilter;
+
+ public IncludeTableFilter(String pattern) {
+ this(pattern, PatternFilter.INCLUDE_EVERYTHING);
+ }
+
+ public IncludeTableFilter(String pattern, PatternFilter columnsFilter) {
+ this.pattern = PatternFilter.pattern(pattern);
+ this.columnsFilter = columnsFilter;
+ }
+
+ public boolean isIncludeColumn (String name) {
+ return columnsFilter.isInclude(name);
+ }
+
+ @Override
+ public int compareTo(IncludeTableFilter o) {
+ if (pattern == null && o.pattern == null) {
+ return 0;
+ } else if (pattern == null) {
+ return 1;
+ } else if (o.pattern == null) {
+ return -1;
+ } else {
+ return pattern.pattern().compareTo(o.pattern.pattern());
+ }
+
+ }
+
+
+ @Override
+ public String toString() {
+ return toString(new StringBuilder(), "").toString();
+ }
+
+ protected StringBuilder toString(StringBuilder res, String prefix) {
+ res.append(prefix).append("Include: ").append(String.valueOf(pattern)).append(" Columns: ");
+ columnsFilter.toString(res);
+ res.append("\n");
+
+ return res;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/LegacyFilterConfigBridge.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/LegacyFilterConfigBridge.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/LegacyFilterConfigBridge.java
new file mode 100644
index 0000000..b7e66fc
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/LegacyFilterConfigBridge.java
@@ -0,0 +1,150 @@
+/*****************************************************************
+ * 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.dbsync.reverse.filters;
+
+import static org.apache.commons.lang.StringUtils.isBlank;
+
+/**
+ * @since 4.0
+ */
+public class LegacyFilterConfigBridge {
+
+ private String catalog;
+ private String schema;
+
+ private String includeTableFilters;
+ private String includeColumnFilters;
+ private String includeProceduresFilters;
+ private String excludeTableFilters;
+ private String excludeColumnFilters;
+ private String excludeProceduresFilters;
+
+ private boolean loadProcedures;
+
+ public LegacyFilterConfigBridge() {
+ }
+
+ public LegacyFilterConfigBridge catalog(String catalog) {
+ this.catalog = catalog;
+ return this;
+ }
+
+ public String catalog() {
+ return catalog;
+ }
+
+ public LegacyFilterConfigBridge schema(String schema) {
+ this.schema = schema;
+ return this;
+ }
+
+ public String schema() {
+ return schema;
+ }
+
+ public LegacyFilterConfigBridge includeTables(String tableFilters) {
+ if (isBlank(tableFilters)) {
+ return this;
+ }
+
+ this.includeTableFilters = transform(tableFilters);
+ return this;
+ }
+
+ public LegacyFilterConfigBridge includeColumns(String columnFilters) {
+ if (isBlank(columnFilters)) {
+ return this;
+ }
+
+ this.includeColumnFilters = transform(columnFilters);
+ return this;
+ }
+
+ public LegacyFilterConfigBridge includeProcedures(String proceduresFilters) {
+ if (isBlank(proceduresFilters)) {
+ return this;
+ }
+
+ this.includeProceduresFilters = transform(proceduresFilters);
+ return this;
+ }
+
+ public LegacyFilterConfigBridge excludeTables(String tableFilters) {
+ if (isBlank(tableFilters)) {
+ return this;
+ }
+
+ this.excludeTableFilters = transform(tableFilters);
+ return this;
+ }
+
+ public LegacyFilterConfigBridge excludeColumns(String columnFilters) {
+ if (isBlank(columnFilters)) {
+ return this;
+ }
+
+ this.excludeColumnFilters = transform(columnFilters);
+ return this;
+ }
+
+ public LegacyFilterConfigBridge excludeProcedures(String proceduresFilters) {
+ if (isBlank(proceduresFilters)) {
+ return this;
+ }
+
+ this.excludeProceduresFilters = transform(proceduresFilters);
+ return this;
+ }
+
+ private static String transform(String pattern) {
+ return "^" + pattern.replaceAll("[*?]", ".$0") + "$";
+ }
+
+ public void setProceduresFilters(boolean loadProcedures) {
+ this.loadProcedures = loadProcedures;
+ }
+
+ public String getIncludeTableFilters() {
+ return includeTableFilters;
+ }
+
+ public String getIncludeColumnFilters() {
+ return includeColumnFilters;
+ }
+
+ public String getIncludeProceduresFilters() {
+ return includeProceduresFilters;
+ }
+
+ public String getExcludeTableFilters() {
+ return excludeTableFilters;
+ }
+
+ public String getExcludeColumnFilters() {
+ return excludeColumnFilters;
+ }
+
+ public String getExcludeProceduresFilters() {
+ return excludeProceduresFilters;
+ }
+
+ public boolean isLoadProcedures() {
+ return loadProcedures;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilter.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilter.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilter.java
new file mode 100644
index 0000000..4b0bf45
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilter.java
@@ -0,0 +1,169 @@
+/*****************************************************************
+ * 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.dbsync.reverse.filters;
+
+import org.apache.commons.lang.StringUtils;
+
+import java.util.Comparator;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.regex.Pattern;
+
+/**
+ * @since 4.0
+ */
+public class PatternFilter {
+
+ public static final PatternFilter INCLUDE_EVERYTHING = new PatternFilter() {
+
+ @Override
+ public boolean isInclude(String obj) {
+ return true;
+ }
+
+ @Override
+ public StringBuilder toString(StringBuilder res) {
+ return res.append("ALL");
+ }
+ };
+
+ public static final PatternFilter INCLUDE_NOTHING = new PatternFilter() {
+ @Override
+ public boolean isInclude(String obj) {
+ return false;
+ }
+
+ @Override
+ public StringBuilder toString(StringBuilder res) {
+ return res.append("NONE");
+ }
+ };
+
+ public static final Comparator<Pattern> PATTERN_COMPARATOR = new Comparator<Pattern>() {
+ @Override
+ public int compare(Pattern o1, Pattern o2) {
+ if (o1 != null && o2 != null) {
+ return o1.pattern().compareTo(o2.pattern());
+ }
+ else {
+ return -1;
+ }
+ }
+ };
+
+ private final SortedSet<Pattern> includes;
+ private final SortedSet<Pattern> excludes;
+
+ public PatternFilter() {
+ this.includes = new TreeSet<>(PATTERN_COMPARATOR);
+ this.excludes = new TreeSet<>(PATTERN_COMPARATOR);
+ }
+
+ public PatternFilter include(Pattern p) {
+ includes.add(p);
+
+ return this;
+ }
+
+ public PatternFilter exclude(Pattern p) {
+ excludes.add(p);
+
+ return this;
+ }
+
+ public static Pattern pattern(String pattern) {
+ if (pattern == null) {
+ return null;
+ }
+ return Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
+ }
+
+ public PatternFilter include(String p) {
+ return include(pattern(p));
+ }
+
+ public PatternFilter exclude(String p) {
+ return exclude(pattern(p));
+ }
+
+ public boolean isInclude(String obj) {
+ boolean include = includes.isEmpty();
+ for (Pattern p : includes) {
+ if (p != null) {
+ if (p.matcher(obj).matches()) {
+ include = true;
+ break;
+ }
+ }
+ }
+
+ if (!include) {
+ return false;
+ }
+
+ for (Pattern p : excludes) {
+ if (p.matcher(obj).matches()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+
+ PatternFilter filter = (PatternFilter) o;
+ return includes.equals(filter.includes)
+ && excludes.equals(filter.excludes);
+ }
+
+ @Override
+ public int hashCode() {
+ return includes.hashCode();
+ }
+
+ public StringBuilder toString(StringBuilder res) {
+ if (includes.isEmpty()) {
+ // Do nothing.
+ } else if (includes.size() > 1) {
+ res.append("(").append(StringUtils.join(includes, " OR ")).append(")");
+ } else {
+ res.append(includes.first().pattern());
+ }
+
+ if (!excludes.isEmpty()) {
+ res.append(" AND NOT (").append(StringUtils.join(includes, " OR ")).append(")");
+ }
+
+ return res;
+ }
+
+ public boolean isEmpty() {
+ return includes.isEmpty() && excludes.isEmpty();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/SchemaFilter.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/SchemaFilter.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/SchemaFilter.java
new file mode 100644
index 0000000..d486215
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/SchemaFilter.java
@@ -0,0 +1,44 @@
+/*****************************************************************
+ * 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.dbsync.reverse.filters;
+
+/**
+* @since 4.0.
+*/
+public class SchemaFilter {
+ public final String name;
+ public final TableFilter tables;
+ public final PatternFilter procedures;
+
+ public SchemaFilter(String name, TableFilter tables, PatternFilter procedures) {
+ this.name = name;
+ this.tables = tables;
+ this.procedures = procedures;
+ }
+
+ protected StringBuilder toString(StringBuilder res, String prefix) {
+ res.append(prefix).append("Schema: ").append(name).append("\n");
+ tables.toString(res, prefix + " ");
+
+ res.append(prefix).append(" Procedures: ");
+ procedures.toString(res).append("\n");
+
+ return res;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/TableFilter.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/TableFilter.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/TableFilter.java
new file mode 100644
index 0000000..266bbc2
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/TableFilter.java
@@ -0,0 +1,133 @@
+/*****************************************************************
+ * 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.dbsync.reverse.filters;
+
+import org.apache.commons.lang.StringUtils;
+
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.regex.Pattern;
+
+/**
+ * TableFilter contain at least one IncludeTable always
+ *
+ */
+public class TableFilter {
+
+ private final SortedSet<IncludeTableFilter> includes;
+ private final SortedSet<Pattern> excludes;
+
+ /**
+ * Includes can contain only One includetable
+ *
+ * @param includes
+ * @param excludes
+ */
+ public TableFilter(SortedSet<IncludeTableFilter> includes, SortedSet<Pattern> excludes) {
+ if (includes.isEmpty()) {
+ throw new IllegalArgumentException("TableFilter should contain at least one IncludeTableFilter always " +
+ "and it is builder responsibility. If you need table filter without includes, use EmptyTableFilter");
+ }
+
+ this.includes = includes;
+ this.excludes = excludes;
+ }
+
+ /**
+ * Return filter for columns in case we should take this table
+ *
+ * @param tableName
+ * @return
+ */
+ public PatternFilter isIncludeTable(String tableName) {
+ IncludeTableFilter include = null;
+ for (IncludeTableFilter p : includes) {
+ if (p.pattern == null || p.pattern.matcher(tableName).matches()) {
+ include = p;
+ break;
+ }
+ }
+
+ if (include == null) {
+ return null;
+ }
+
+ for (Pattern p : excludes) {
+ if (p != null) {
+ if (p.matcher(tableName).matches()) {
+ return null;
+ }
+ }
+ }
+
+ return include.columnsFilter;
+ }
+
+ public static TableFilter include(String tablePattern) {
+ TreeSet<IncludeTableFilter> includes = new TreeSet<IncludeTableFilter>();
+ includes.add(new IncludeTableFilter(tablePattern == null ? null : tablePattern.replaceAll("%", ".*")));
+
+ return new TableFilter(includes, new TreeSet<Pattern>());
+ }
+
+ public static TableFilter everything() {
+ TreeSet<IncludeTableFilter> includes = new TreeSet<IncludeTableFilter>();
+ includes.add(new IncludeTableFilter(null));
+
+ return new TableFilter(includes, new TreeSet<Pattern>());
+ }
+
+ protected StringBuilder toString(StringBuilder res, String prefix) {
+ res.append(prefix).append("Tables: ").append("\n");
+
+ for (IncludeTableFilter include : includes) {
+ include.toString(res, prefix + " ");
+ }
+
+ if (!excludes.isEmpty()) {
+ res.append(prefix).append(" ").append(StringUtils.join(excludes, " OR ")).append("\n");
+ }
+
+ return res;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof TableFilter)) {
+ return false;
+ }
+
+ TableFilter that = (TableFilter) o;
+
+ return excludes.equals(that.excludes)
+ && includes.equals(that.includes);
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = includes.hashCode();
+ result = 31 * result + excludes.hashCode();
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/mapper/DbType.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/mapper/DbType.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/mapper/DbType.java
new file mode 100644
index 0000000..9f829ea
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/mapper/DbType.java
@@ -0,0 +1,194 @@
+/*****************************************************************
+ * 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.dbsync.reverse.mapper;
+
+import org.apache.cayenne.util.EqualsBuilder;
+import org.apache.cayenne.util.HashCodeBuilder;
+import org.apache.commons.lang.builder.CompareToBuilder;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import static org.apache.commons.lang.StringUtils.isBlank;
+
+/**
+ * @since 4.0
+ */
+public class DbType implements Comparable<DbType> {
+
+ private static final Log LOG = LogFactory.getLog(DbType.class);
+
+ public final String jdbc;
+
+ public final Integer length;
+ public final Integer precision;
+ public final Integer scale;
+ public final Boolean notNull;
+
+ public DbType(String jdbc) {
+ this(jdbc, null, null, null, null);
+ }
+
+ public DbType(String jdbc, Integer length, Integer precision, Integer scale, Boolean notNull) {
+ if (isBlank(jdbc)) {
+ throw new IllegalArgumentException("Jdbc type can't be null");
+ }
+ this.jdbc = jdbc;
+
+ this.length = getValidInt(length);
+ this.precision = getValidInt(precision);
+ this.scale = getValidInt(scale);
+ this.notNull = notNull;
+ }
+
+ public String getJdbc() {
+ return jdbc;
+ }
+
+ public Integer getLength() {
+ return length;
+ }
+
+ public Integer getPrecision() {
+ return precision;
+ }
+
+ public Integer getScale() {
+ return scale;
+ }
+
+ public Boolean getNotNull() {
+ return notNull;
+ }
+
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ if (obj.getClass() != getClass()) {
+ return false;
+ }
+ DbType rhs = (DbType) obj;
+ return new EqualsBuilder()
+ .append(this.jdbc, rhs.jdbc)
+ .append(this.length, rhs.length)
+ .append(this.precision, rhs.precision)
+ .append(this.scale, rhs.scale)
+ .append(this.notNull, rhs.notNull)
+ .isEquals();
+ }
+
+ @Override
+ public int hashCode() {
+ return new HashCodeBuilder()
+ .append(jdbc)
+ .append(length)
+ .append(precision)
+ .append(scale)
+ .append(notNull)
+ .toHashCode();
+ }
+
+
+ @Override
+ public String toString() {
+ String res = jdbc;
+
+ String len = "*";
+ if (isPositive(length)) {
+ len = length.toString();
+ }
+ if (isPositive(precision)) {
+ len = precision.toString();
+ }
+
+ res += " (" + len;
+ if (isPositive(scale)) {
+ res += ", " + scale;
+ }
+ res += ")";
+
+ if (notNull != null && notNull) {
+ res += " NOT NULL";
+ }
+
+ return res;
+ }
+
+ private boolean isPositive(Integer num) {
+ return num != null && num > 0;
+ }
+
+ private Integer getValidInt(Integer num) {
+ if (num == null || num > 0) {
+ return num;
+ }
+
+ LOG.warn("Invalid int value '" + num + "'");
+ return null;
+ }
+
+ /**
+ * Compare by specificity the most specific DbPath should be first in ordered list
+ */
+ @Override
+ public int compareTo(DbType dbType) {
+ return new CompareToBuilder()
+ .append(dbType.jdbc, jdbc)
+ .append(dbType.getSpecificity(), getSpecificity())
+ .append(dbType.length, length)
+ .append(dbType.precision, precision)
+ .append(dbType.scale, scale)
+ .append(dbType.notNull, notNull)
+ .toComparison();
+ }
+
+ private int getSpecificity() {
+ int res = 0;
+ if (isPositive(length)) {
+ res += 100;
+ }
+ if (isPositive(precision)) {
+ res += 100;
+ }
+ if (isPositive(scale)) {
+ res += 10;
+ }
+ if (this.notNull != null) {
+ res += 5;
+ }
+
+ return res;
+ }
+
+ public boolean isCover(DbType type) {
+ return this.jdbc.equals(type.jdbc)
+ && (isCover(length, type.length) || length == null && type.length == null && isCover(precision, type.precision))
+ && isCover(scale, type.scale)
+ && isCover(notNull, type.notNull);
+ }
+
+ private boolean isCover(Object a, Object b) {
+ return a == null || a.equals(b);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/mapper/DefaultJdbc2JavaTypeMapper.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/mapper/DefaultJdbc2JavaTypeMapper.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/mapper/DefaultJdbc2JavaTypeMapper.java
new file mode 100644
index 0000000..0af1690
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/mapper/DefaultJdbc2JavaTypeMapper.java
@@ -0,0 +1,282 @@
+/*****************************************************************
+ * 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.dbsync.reverse.mapper;
+
+import org.apache.cayenne.dba.TypesMapping;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.util.Util;
+
+import java.io.Serializable;
+import java.math.BigInteger;
+import java.sql.Types;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * @since 4.0.
+ */
+public class DefaultJdbc2JavaTypeMapper implements Jdbc2JavaTypeMapper {
+
+ // Never use "-1" or any other normal integer, since there
+ // is a big chance it is being reserved in java.sql.Types
+ public static final int NOT_DEFINED = Integer.MAX_VALUE;
+
+ // char constants for Java data types
+ public static final String JAVA_LONG = "java.lang.Long";
+ public static final String JAVA_BYTES = "byte[]";
+ public static final String JAVA_BOOLEAN = "java.lang.Boolean";
+ public static final String JAVA_STRING = "java.lang.String";
+ public static final String JAVA_SQLDATE = "java.sql.Date";
+ public static final String JAVA_UTILDATE = "java.util.Date";
+ public static final String JAVA_BIGDECIMAL = "java.math.BigDecimal";
+ public static final String JAVA_DOUBLE = "java.lang.Double";
+ public static final String JAVA_FLOAT = "java.lang.Float";
+ public static final String JAVA_INTEGER = "java.lang.Integer";
+ public static final String JAVA_SHORT = "java.lang.Short";
+ public static final String JAVA_BYTE = "java.lang.Byte";
+ public static final String JAVA_TIME = "java.sql.Time";
+ public static final String JAVA_TIMESTAMP = "java.sql.Timestamp";
+ public static final String JAVA_BLOB = "java.sql.Blob";
+
+ /**
+ * Keys: java class names, Values: SQL int type definitions from
+ * java.sql.Types
+ */
+ private final Map<String, Integer> javaSqlEnum = new HashMap<>();
+
+ private final Map<DbType, String> mapping = new HashMap<>();
+ private final SortedSet<DbType> dbTypes = new TreeSet<>();
+
+ private Map<String, String> classToPrimitive;
+
+ {
+ add(Types.BIGINT, JAVA_LONG);
+ add(Types.BINARY, JAVA_BYTES);
+ add(Types.BIT, JAVA_BOOLEAN);
+ add(Types.BOOLEAN, JAVA_BOOLEAN);
+ add(Types.BLOB, JAVA_BYTES);
+ add(Types.CLOB, JAVA_STRING);
+ add(Types.NCLOB, JAVA_STRING);
+ add(Types.SQLXML, JAVA_STRING);
+ add(Types.CHAR, JAVA_STRING);
+ add(Types.NCHAR, JAVA_STRING);
+ add(Types.DATE, JAVA_UTILDATE);
+ add(Types.DECIMAL, JAVA_BIGDECIMAL);
+ add(Types.DOUBLE, JAVA_DOUBLE);
+ add(Types.FLOAT, JAVA_FLOAT);
+ add(Types.INTEGER, JAVA_INTEGER);
+ add(Types.LONGVARCHAR, JAVA_STRING);
+ add(Types.LONGNVARCHAR, JAVA_STRING);
+ add(Types.LONGVARBINARY, JAVA_BYTES);
+ add(Types.NUMERIC, JAVA_BIGDECIMAL);
+ add(Types.REAL, JAVA_FLOAT);
+ add(Types.SMALLINT, JAVA_SHORT);
+ add(Types.TINYINT, JAVA_SHORT);
+ add(Types.TIME, JAVA_UTILDATE);
+ add(Types.TIMESTAMP, JAVA_UTILDATE);
+ add(Types.VARBINARY, JAVA_BYTES);
+ add(Types.VARCHAR, JAVA_STRING);
+ add(Types.NVARCHAR, JAVA_STRING);
+
+ javaSqlEnum.put(JAVA_LONG, Types.BIGINT);
+ javaSqlEnum.put(JAVA_BYTES, Types.BINARY);
+ javaSqlEnum.put(JAVA_BOOLEAN, Types.BIT);
+ javaSqlEnum.put(JAVA_STRING, Types.VARCHAR);
+ javaSqlEnum.put(JAVA_SQLDATE, Types.DATE);
+ javaSqlEnum.put(JAVA_UTILDATE, Types.DATE);
+ javaSqlEnum.put(JAVA_TIMESTAMP, Types.TIMESTAMP);
+ javaSqlEnum.put(JAVA_BIGDECIMAL, Types.DECIMAL);
+ javaSqlEnum.put(JAVA_DOUBLE, Types.DOUBLE);
+ javaSqlEnum.put(JAVA_FLOAT, Types.FLOAT);
+ javaSqlEnum.put(JAVA_INTEGER, Types.INTEGER);
+ javaSqlEnum.put(JAVA_SHORT, Types.SMALLINT);
+ javaSqlEnum.put(JAVA_BYTE, Types.SMALLINT);
+ javaSqlEnum.put(JAVA_TIME, Types.TIME);
+ javaSqlEnum.put(JAVA_TIMESTAMP, Types.TIMESTAMP);
+
+ // add primitives
+ javaSqlEnum.put("byte", Types.TINYINT);
+ javaSqlEnum.put("int", Types.INTEGER);
+ javaSqlEnum.put("short", Types.SMALLINT);
+ javaSqlEnum.put("char", Types.CHAR);
+ javaSqlEnum.put("double", Types.DOUBLE);
+ javaSqlEnum.put("long", Types.BIGINT);
+ javaSqlEnum.put("float", Types.FLOAT);
+ javaSqlEnum.put("boolean", Types.BIT);
+
+ classToPrimitive = new HashMap<>();
+ classToPrimitive.put(Byte.class.getName(), "byte");
+ classToPrimitive.put(Long.class.getName(), "long");
+ classToPrimitive.put(Double.class.getName(), "double");
+ classToPrimitive.put(Boolean.class.getName(), "boolean");
+ classToPrimitive.put(Float.class.getName(), "float");
+ classToPrimitive.put(Short.class.getName(), "short");
+ classToPrimitive.put(Integer.class.getName(), "int");
+ }
+
+ private Boolean usePrimitives;
+
+ /**
+ * Returns default java.sql.Types type by the Java type name.
+ *
+ * @param className
+ * Fully qualified Java Class name.
+ * @return The SQL type or NOT_DEFINED if no type found.
+ */
+ public int getJdbcTypeByJava(DbAttribute attribute, String className) {
+ if (className == null) {
+ return NOT_DEFINED;
+ }
+
+ Integer type = javaSqlEnum.get(className);
+ if (type != null) {
+ return type;
+ }
+
+ // try to load a Java class - some nonstandard mappings may work
+ try {
+ return getSqlTypeByJava(attribute, Util.getJavaClass(className));
+ } catch (Throwable th) {
+ return NOT_DEFINED;
+ }
+ }
+
+ public void add(int jdbcType, String java) {
+ add(new DbType(TypesMapping.getSqlNameByType(jdbcType)), java);
+ }
+
+ @Override
+ public void add(DbType type, String java) {
+ mapping.put(type, java);
+ dbTypes.add(type);
+ }
+
+ /**
+ * Guesses a default JDBC type for the Java class.
+ *
+ * @since 1.1
+ */
+ protected int getSqlTypeByJava(DbAttribute attribute, Class<?> javaClass) {
+ if (javaClass == null) {
+ return NOT_DEFINED;
+ }
+
+ // check standard mapping of class and superclasses
+ Class<?> aClass = javaClass;
+ while (aClass != null) {
+
+ String name;
+
+ if (aClass.isArray()) {
+ name = aClass.getComponentType().getName() + "[]";
+ } else {
+ name = aClass.getName();
+ }
+
+ Object type = javaSqlEnum.get(name);
+ if (type != null) {
+ return ((Number) type).intValue();
+ }
+
+ aClass = aClass.getSuperclass();
+ }
+
+ // check non-standard JDBC types that are still supported by JPA
+ if (javaClass.isArray()) {
+
+ Class<?> elementType = javaClass.getComponentType();
+ if (Character.class.isAssignableFrom(elementType) || Character.TYPE.isAssignableFrom(elementType)) {
+ return Types.VARCHAR;
+ } else if (Byte.class.isAssignableFrom(elementType) || Byte.TYPE.isAssignableFrom(elementType)) {
+ return Types.VARBINARY;
+ }
+ }
+
+ if (Calendar.class.isAssignableFrom(javaClass)) {
+ return Types.TIMESTAMP;
+ }
+
+ if (BigInteger.class.isAssignableFrom(javaClass)) {
+ return Types.BIGINT;
+ }
+
+ if (Serializable.class.isAssignableFrom(javaClass)) {
+ // serializable check should be the last one when all other mapping
+ // attempts failed
+ return Types.VARBINARY;
+ }
+
+ return NOT_DEFINED;
+ }
+
+ /**
+ * Get the corresponding Java type by its java.sql.Types counterpart. Note
+ * that this method should be used as a last resort, with explicit mapping
+ * provided by user used as a first choice, as it can only guess how to map
+ * certain types, such as NUMERIC, etc.
+ *
+ * @return Fully qualified Java type name or null if not found.
+ */
+ @Override
+ public String getJavaByJdbcType(DbAttribute attribute, int type) {
+ String jdbcType = TypesMapping.getSqlNameByType(type);
+ DbType dbType;
+ if (attribute != null) {
+ dbType = new DbType(jdbcType, attribute.getMaxLength(), attribute.getAttributePrecision(),
+ attribute.getScale(), attribute.isMandatory());
+ } else {
+ dbType = new DbType(jdbcType);
+ }
+
+ String typeName = getJavaByJdbcType(dbType);
+
+ if (usePrimitives != null && usePrimitives) {
+ String primitive = classToPrimitive.get(typeName);
+ if (primitive != null) {
+ return primitive;
+ }
+ }
+
+ return typeName;
+ }
+
+ public String getJavaByJdbcType(DbType type) {
+ for (DbType t : dbTypes) {
+ if (t.isCover(type)) {
+ // because dbTypes sorted by specificity we will take first and
+ // the most specific matching
+ // that applicable for attribute
+ return mapping.get(t);
+ }
+ }
+
+ return null;
+ }
+
+ public Boolean getUsePrimitives() {
+ return usePrimitives;
+ }
+
+ public void setUsePrimitives(Boolean usePrimitives) {
+ this.usePrimitives = usePrimitives;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/mapper/Jdbc2JavaTypeMapper.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/mapper/Jdbc2JavaTypeMapper.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/mapper/Jdbc2JavaTypeMapper.java
new file mode 100644
index 0000000..71d86d5
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/mapper/Jdbc2JavaTypeMapper.java
@@ -0,0 +1,33 @@
+/*****************************************************************
+ * 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.dbsync.reverse.mapper;
+
+import org.apache.cayenne.map.DbAttribute;
+
+/**
+ * @since 4.0.
+ */
+public interface Jdbc2JavaTypeMapper {
+
+ String getJavaByJdbcType(DbAttribute attribute, int type);
+
+ int getJdbcTypeByJava(DbAttribute attribute, String className);
+
+ void add(DbType type, String java);
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/AddColumnToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/AddColumnToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/AddColumnToModelIT.java
new file mode 100644
index 0000000..30fa47b
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/AddColumnToModelIT.java
@@ -0,0 +1,98 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Types;
+import java.util.List;
+
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.junit.Test;
+
+public class AddColumnToModelIT extends MergeCase {
+
+ @Test
+ public void testAddColumn() throws Exception {
+ dropTableIfPresent("NEW_TABLE");
+ assertTokensAndExecute(0, 0);
+
+ DbEntity dbEntity = new DbEntity("NEW_TABLE");
+
+ DbAttribute column1 = new DbAttribute("ID", Types.INTEGER, dbEntity);
+ column1.setMandatory(true);
+ column1.setPrimaryKey(true);
+ dbEntity.addAttribute(column1);
+
+ DbAttribute column2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity);
+ column2.setMaxLength(10);
+ column2.setMandatory(false);
+ dbEntity.addAttribute(column2);
+
+ map.addDbEntity(dbEntity);
+
+ assertTokensAndExecute(1, 0);
+ assertTokensAndExecute(0, 0);
+
+ ObjEntity objEntity = new ObjEntity("NewTable");
+ objEntity.setDbEntity(dbEntity);
+ ObjAttribute oatr1 = new ObjAttribute("name");
+ oatr1.setDbAttributePath(column2.getName());
+ oatr1.setType("java.lang.String");
+ objEntity.addAttribute(oatr1);
+ map.addObjEntity(objEntity);
+
+ // remove name column
+ objEntity.removeAttribute(oatr1.getName());
+ dbEntity.removeAttribute(column2.getName());
+ assertNull(objEntity.getAttribute(oatr1.getName()));
+ assertEquals(0, objEntity.getAttributes().size());
+ assertNull(dbEntity.getAttribute(column2.getName()));
+
+ List<MergerToken> tokens = createMergeTokens();
+ assertEquals(1, tokens.size());
+ MergerToken token = tokens.get(0);
+ if (token.getDirection().isToDb()) {
+ token = token.createReverse(mergerFactory());
+ }
+ assertTrue(token instanceof AddColumnToModel);
+ execute(token);
+ assertEquals(1, objEntity.getAttributes().size());
+ assertEquals("java.lang.String", objEntity.getAttributes().iterator()
+ .next().getType());
+
+ // clear up
+ map.removeObjEntity(objEntity.getName(), true);
+ map.removeDbEntity(dbEntity.getName(), true);
+ resolver.refreshMappingCache();
+ assertNull(map.getObjEntity(objEntity.getName()));
+ assertNull(map.getDbEntity(dbEntity.getName()));
+ assertFalse(map.getDbEntities().contains(dbEntity));
+
+ assertTokensAndExecute(1, 0);
+ assertTokensAndExecute(0, 0);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/CreateTableToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/CreateTableToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/CreateTableToModelIT.java
new file mode 100644
index 0000000..bac6402
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/CreateTableToModelIT.java
@@ -0,0 +1,97 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Types;
+import java.util.List;
+
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.ObjEntity;
+import org.junit.Test;
+
+public class CreateTableToModelIT extends MergeCase {
+
+ @Test
+ public void testAddTable() throws Exception {
+ dropTableIfPresent("NEW_TABLE");
+ assertTokensAndExecute(0, 0);
+
+ DbEntity dbEntity = new DbEntity("NEW_TABLE");
+
+ DbAttribute column1 = new DbAttribute("ID", Types.INTEGER, dbEntity);
+ column1.setMandatory(true);
+ column1.setPrimaryKey(true);
+ dbEntity.addAttribute(column1);
+
+ DbAttribute column2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity);
+ column2.setMaxLength(10);
+ column2.setMandatory(false);
+ dbEntity.addAttribute(column2);
+
+ // for the new entity to the db
+ execute(mergerFactory().createCreateTableToDb(dbEntity));
+
+ List<MergerToken> tokens = createMergeTokens();
+ assertEquals(1, tokens.size());
+ MergerToken token = tokens.get(0);
+ if (token.getDirection().isToDb()) {
+ token = token.createReverse(mergerFactory());
+ }
+ assertTrue(token.getClass().getName(), token instanceof CreateTableToModel);
+
+ execute(token);
+
+ ObjEntity objEntity = null;
+ for (ObjEntity candidate : map.getObjEntities()) {
+ if (dbEntity.getName().equalsIgnoreCase(candidate.getDbEntityName())) {
+ objEntity = candidate;
+ break;
+ }
+ }
+ assertNotNull(objEntity);
+
+ assertEquals(objEntity.getClassName(), map.getDefaultPackage() + "." + objEntity.getName());
+ assertEquals(objEntity.getSuperClassName(), map.getDefaultSuperclass());
+ assertEquals(objEntity.getClientClassName(), map.getDefaultClientPackage() + "." + objEntity.getName());
+ assertEquals(objEntity.getClientSuperClassName(), map.getDefaultClientSuperclass());
+
+ assertEquals(1, objEntity.getAttributes().size());
+ assertEquals("java.lang.String", objEntity.getAttributes().iterator().next().getType());
+
+ // clear up
+ // fix psql case issue
+ map.removeDbEntity(objEntity.getDbEntity().getName(), true);
+ map.removeObjEntity(objEntity.getName(), true);
+ map.removeDbEntity(dbEntity.getName(), true);
+ resolver.refreshMappingCache();
+ assertNull(map.getObjEntity(objEntity.getName()));
+ assertNull(map.getDbEntity(dbEntity.getName()));
+ assertFalse(map.getDbEntities().contains(dbEntity));
+
+ assertTokensAndExecute(1, 0);
+ assertTokensAndExecute(0, 0);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DbMergerTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DbMergerTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DbMergerTest.java
new file mode 100644
index 0000000..8cb03dd
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DbMergerTest.java
@@ -0,0 +1,261 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.dbsync.merge.builders.DbEntityBuilder;
+import org.apache.cayenne.dbsync.merge.factory.HSQLMergerTokenFactory;
+import org.apache.cayenne.dbsync.reverse.DbLoaderConfiguration;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbEntity;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.dataMap;
+import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.dbAttr;
+import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.dbEntity;
+import static org.junit.Assert.assertEquals;
+
+public class DbMergerTest {
+
+ @Test
+ public void testEmptyDataMap() throws Exception {
+ assertEquals(0, dbMerger().createMergeTokens(new ArrayList<DbEntity>(0),
+ new ArrayList<DbEntity>(0), new DbLoaderConfiguration()).size());
+ }
+
+ @Test
+ public void testAddTable() throws Exception {
+ DbEntityBuilder dbEntity =
+ dbEntity("table1").attributes(
+ dbAttr("attr01").typeInt()
+ );
+ DataMap existing = dataMap().with(dbEntity).build();
+
+ List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(),
+ new ArrayList<DbEntity>(0), new DbLoaderConfiguration());
+
+ assertEquals(1, tokens.size());
+ assertEquals(factory().createCreateTableToDb(dbEntity.build()).getTokenValue(),
+ tokens.get(0).getTokenValue());
+ }
+
+ @Test
+ public void testRemoveTable() throws Exception {
+ DataMap db = dataMap().with(
+ dbEntity("table1").attributes(
+ dbAttr("attr01").typeInt()
+ )).build();
+
+ List<MergerToken> tokens = dbMerger().createMergeTokens(new ArrayList<DbEntity>(0),
+ db.getDbEntities(), new DbLoaderConfiguration());
+
+ assertEquals(1, tokens.size());
+ assertEquals(factory().createDropTableToDb(db.getDbEntity("table1")).getTokenValue(),
+ tokens.get(0).getTokenValue());
+ }
+
+ @Test
+ public void testAddColumn() throws Exception {
+ DataMap existing = dataMap().with(
+ dbEntity("table1").attributes(
+ dbAttr("attr01").typeInt(),
+ dbAttr("attr02").typeInt()
+ )).build();
+
+ DataMap db = dataMap().with(
+ dbEntity("table1").attributes(
+ dbAttr("attr01").typeInt()
+ )).build();
+
+ List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(),
+ db.getDbEntities(), new DbLoaderConfiguration());
+
+ assertEquals(1, tokens.size());
+
+ DbEntity entity = existing.getDbEntity("table1");
+ assertEquals(factory().createAddColumnToDb(entity, entity.getAttribute("attr02")).getTokenValue(),
+ tokens.get(0).getTokenValue());
+ }
+
+ @Test
+ public void testAddRelationship() throws Exception {
+ DataMap existing = dataMap().with(
+ dbEntity("table1").attributes(
+ dbAttr("attr01").typeInt(),
+ dbAttr("attr02").typeInt()),
+
+ dbEntity("table2").attributes(
+ dbAttr("attr01").typeInt().primaryKey(),
+ dbAttr("attr02").typeInt())
+ ).join("rel", "table1.attr01", "table2.attr01")
+ .build();
+
+ DataMap db = dataMap().with(
+ dbEntity("table1").attributes(
+ dbAttr("attr01").typeInt(),
+ dbAttr("attr02").typeInt()),
+
+ dbEntity("table2").attributes(
+ dbAttr("attr01").typeInt().primaryKey(),
+ dbAttr("attr02").typeInt())
+ )//.join("table1.attr01", "table2.attr01")
+ .build();
+
+
+ List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(),
+ db.getDbEntities(), new DbLoaderConfiguration());
+
+ assertEquals(1, tokens.size());
+
+ DbEntity entity = existing.getDbEntity("table1");
+ assertEquals(factory().createAddRelationshipToDb(entity, entity.getRelationship("rel")).getTokenValue(),
+ tokens.get(0).getTokenValue());
+ }
+
+ @Test
+ public void testAddRelationship1() throws Exception {
+ DataMap existing = dataMap().with(
+ dbEntity("table1").attributes(
+ dbAttr("attr01").typeInt(),
+ dbAttr("attr02").typeInt()),
+
+ dbEntity("table2").attributes(
+ dbAttr("attr01").typeInt().primaryKey(),
+ dbAttr("attr02").typeInt().primaryKey(),
+ dbAttr("attr03").typeInt().primaryKey())
+ ).join("rel", "table1.attr01", "table2.attr01")
+ .join("rel1", "table1.attr01", "table2.attr03")
+ .build();
+
+ DataMap db = dataMap().with(
+ dbEntity("table1").attributes(
+ dbAttr("attr01").typeInt(),
+ dbAttr("attr02").typeInt()),
+
+ dbEntity("table2").attributes(
+ dbAttr("attr01").typeInt().primaryKey(),
+ dbAttr("attr02").typeInt().primaryKey(),
+ dbAttr("attr03").typeInt().primaryKey())
+ ).join("rel", "table1.attr01", "table2.attr02")
+ .join("rel1", "table1.attr01", "table2.attr03")
+ .build();
+
+
+ List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(),
+ db.getDbEntities(), new DbLoaderConfiguration());
+
+ assertEquals(2, tokens.size());
+
+ DbEntity entity = existing.getDbEntity("table1");
+ assertEquals(factory().createDropRelationshipToDb(entity, entity.getRelationship("rel")).getTokenValue(),
+ tokens.get(0).getTokenValue());
+
+ entity = db.getDbEntity("table1");
+ assertEquals(factory().createAddRelationshipToDb(entity, entity.getRelationship("rel")).getTokenValue(),
+ tokens.get(0).getTokenValue());
+ }
+
+ @Test
+ public void testRemoveRelationship() throws Exception {
+ DataMap existing = dataMap().with(
+ dbEntity("table1").attributes(
+ dbAttr("attr01").typeInt(),
+ dbAttr("attr02").typeInt()),
+
+ dbEntity("table2").attributes(
+ dbAttr("attr01").typeInt().primaryKey(),
+ dbAttr("attr02").typeInt())
+ )
+ .build();
+
+ DataMap db = dataMap().with(
+ dbEntity("table1").attributes(
+ dbAttr("attr01").typeInt(),
+ dbAttr("attr02").typeInt()),
+
+ dbEntity("table2").attributes(
+ dbAttr("attr01").typeInt().primaryKey(),
+ dbAttr("attr02").typeInt())
+ ).join("rel", "table1.attr01", "table2.attr01")
+ .build();
+
+
+ List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(), db.getDbEntities(), new DbLoaderConfiguration());
+
+ assertEquals(1, tokens.size());
+
+ DbEntity entity = db.getDbEntity("table1");
+ assertEquals(factory().createDropRelationshipToDb(entity, entity.getRelationship("rel")).getTokenValue(),
+ tokens.get(0).getTokenValue());
+ }
+
+ @Test
+ public void testRemoveColumn() throws Exception {
+ DataMap existing = dataMap().with(
+ dbEntity("table1").attributes(
+ dbAttr("attr01").typeInt()
+ )).build();
+
+ DataMap db = dataMap().with(
+ dbEntity("table1").attributes(
+ dbAttr("attr01").typeInt(),
+ dbAttr("attr02").typeInt()
+ )).build();
+
+ List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(),
+ db.getDbEntities(), new DbLoaderConfiguration());
+
+ assertEquals(1, tokens.size());
+
+ DbEntity entity = db.getDbEntity("table1");
+ assertEquals(factory().createDropColumnToModel(entity, entity.getAttribute("attr02")).getTokenValue(),
+ tokens.get(0).getTokenValue());
+ }
+
+ @Test
+ public void testNoChanges() throws Exception {
+ DataMap dataMap1 = dataMap().with(
+ dbEntity("table1").attributes(
+ dbAttr("attr01").typeInt(),
+ dbAttr("attr02").typeInt(),
+ dbAttr("attr03").typeInt()
+ )).build();
+
+ DataMap dataMap2 = dataMap().with(
+ dbEntity("table1").attributes(
+ dbAttr("attr01").typeInt(),
+ dbAttr("attr02").typeInt(),
+ dbAttr("attr03").typeInt()
+ )).build();
+
+
+ assertEquals(0, dbMerger().createMergeTokens(dataMap1.getDbEntities(),
+ dataMap2.getDbEntities(), new DbLoaderConfiguration()).size());
+ }
+
+ private DbMerger dbMerger() {
+ return new DbMerger(factory());
+ }
+
+ private HSQLMergerTokenFactory factory() {
+ return new HSQLMergerTokenFactory();
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropColumnToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropColumnToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropColumnToModelIT.java
new file mode 100644
index 0000000..f6e0675
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropColumnToModelIT.java
@@ -0,0 +1,235 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.sql.Types;
+import java.util.List;
+
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+import org.junit.Test;
+
+public class DropColumnToModelIT extends MergeCase {
+
+ @Test
+ public void testSimpleColumn() throws Exception {
+ dropTableIfPresent("NEW_TABLE");
+
+ assertTokensAndExecute(0, 0);
+
+ DbEntity dbEntity = new DbEntity("NEW_TABLE");
+
+ DbAttribute column1 = new DbAttribute("ID", Types.INTEGER, dbEntity);
+ column1.setMandatory(true);
+ column1.setPrimaryKey(true);
+ dbEntity.addAttribute(column1);
+
+ DbAttribute column2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity);
+ column2.setMaxLength(10);
+ column2.setMandatory(false);
+ dbEntity.addAttribute(column2);
+
+ map.addDbEntity(dbEntity);
+
+ assertTokensAndExecute(1, 0);
+ assertTokensAndExecute(0, 0);
+
+ ObjEntity objEntity = new ObjEntity("NewTable");
+ objEntity.setDbEntity(dbEntity);
+ ObjAttribute oatr1 = new ObjAttribute("name");
+ oatr1.setDbAttributePath(column2.getName());
+ oatr1.setType("java.lang.String");
+ objEntity.addAttribute(oatr1);
+ map.addObjEntity(objEntity);
+
+ // force drop name column in db
+ MergerToken token = mergerFactory().createDropColumnToDb(dbEntity, column2);
+ execute(token);
+
+ List<MergerToken> tokens = createMergeTokens();
+ assertEquals(1, tokens.size());
+ token = tokens.get(0);
+ if (token.getDirection().isToDb()) {
+ token = token.createReverse(mergerFactory());
+ }
+ assertTrue(token instanceof DropColumnToModel);
+ execute(token);
+ assertNull(dbEntity.getAttribute(column2.getName()));
+ assertNull(objEntity.getAttribute(oatr1.getName()));
+
+ // clear up
+ map.removeObjEntity(objEntity.getName(), true);
+ map.removeDbEntity(dbEntity.getName(), true);
+ resolver.refreshMappingCache();
+ assertNull(map.getObjEntity(objEntity.getName()));
+ assertNull(map.getDbEntity(dbEntity.getName()));
+ assertFalse(map.getDbEntities().contains(dbEntity));
+
+ assertTokensAndExecute(1, 0);
+ assertTokensAndExecute(0, 0);
+ }
+
+ @Test
+ public void testRemoveFKColumnWithoutRelationshipInDb() throws Exception {
+ dropTableIfPresent("NEW_TABLE");
+ dropTableIfPresent("NEW_TABLE2");
+
+ assertTokensAndExecute(0, 0);
+
+ DbEntity dbEntity1 = new DbEntity("NEW_TABLE");
+
+ DbAttribute e1col1 = new DbAttribute("ID", Types.INTEGER, dbEntity1);
+ e1col1.setMandatory(true);
+ e1col1.setPrimaryKey(true);
+ dbEntity1.addAttribute(e1col1);
+
+ DbAttribute e1col2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity1);
+ e1col2.setMaxLength(10);
+ e1col2.setMandatory(false);
+ dbEntity1.addAttribute(e1col2);
+
+ map.addDbEntity(dbEntity1);
+
+ DbEntity dbEntity2 = new DbEntity("NEW_TABLE2");
+ DbAttribute e2col1 = new DbAttribute("ID", Types.INTEGER, dbEntity2);
+ e2col1.setMandatory(true);
+ e2col1.setPrimaryKey(true);
+ dbEntity2.addAttribute(e2col1);
+ DbAttribute e2col2 = new DbAttribute("FK", Types.INTEGER, dbEntity2);
+ dbEntity2.addAttribute(e2col2);
+ DbAttribute e2col3 = new DbAttribute("NAME", Types.VARCHAR, dbEntity2);
+ e2col3.setMaxLength(10);
+ dbEntity2.addAttribute(e2col3);
+
+ map.addDbEntity(dbEntity2);
+
+ assertTokensAndExecute(2, 0);
+ assertTokensAndExecute(0, 0);
+
+ // force drop fk column in db
+ execute(mergerFactory().createDropColumnToDb(dbEntity2, e2col2));
+
+ // create db relationships, but do not sync them to db
+ DbRelationship rel1To2 = new DbRelationship("rel1To2");
+ rel1To2.setSourceEntity(dbEntity1);
+ rel1To2.setTargetEntityName(dbEntity2);
+ rel1To2.setToMany(true);
+ rel1To2.addJoin(new DbJoin(rel1To2, e1col1.getName(), e2col2.getName()));
+ dbEntity1.addRelationship(rel1To2);
+ DbRelationship rel2To1 = new DbRelationship("rel2To1");
+ rel2To1.setSourceEntity(dbEntity2);
+ rel2To1.setTargetEntityName(dbEntity1);
+ rel2To1.setToMany(false);
+ rel2To1.addJoin(new DbJoin(rel2To1, e2col2.getName(), e1col1.getName()));
+ dbEntity2.addRelationship(rel2To1);
+ assertSame(rel1To2, rel2To1.getReverseRelationship());
+ assertSame(rel2To1, rel1To2.getReverseRelationship());
+
+ // create ObjEntities
+ ObjEntity objEntity1 = new ObjEntity("NewTable");
+ objEntity1.setDbEntity(dbEntity1);
+ ObjAttribute oatr1 = new ObjAttribute("name");
+ oatr1.setDbAttributePath(e1col2.getName());
+ oatr1.setType("java.lang.String");
+ objEntity1.addAttribute(oatr1);
+ map.addObjEntity(objEntity1);
+ ObjEntity objEntity2 = new ObjEntity("NewTable2");
+ objEntity2.setDbEntity(dbEntity2);
+ ObjAttribute o2a1 = new ObjAttribute("name");
+ o2a1.setDbAttributePath(e2col3.getName());
+ o2a1.setType("java.lang.String");
+ objEntity2.addAttribute(o2a1);
+ map.addObjEntity(objEntity2);
+
+ // create ObjRelationships
+ assertEquals(0, objEntity1.getRelationships().size());
+ assertEquals(0, objEntity2.getRelationships().size());
+ ObjRelationship objRel1To2 = new ObjRelationship("objRel1To2");
+ objRel1To2.addDbRelationship(rel1To2);
+ objRel1To2.setSourceEntity(objEntity1);
+ objRel1To2.setTargetEntityName(objEntity2);
+ objEntity1.addRelationship(objRel1To2);
+ ObjRelationship objRel2To1 = new ObjRelationship("objRel2To1");
+ objRel2To1.addDbRelationship(rel2To1);
+ objRel2To1.setSourceEntity(objEntity2);
+ objRel2To1.setTargetEntityName(objEntity1);
+ objEntity2.addRelationship(objRel2To1);
+ assertEquals(1, objEntity1.getRelationships().size());
+ assertEquals(1, objEntity2.getRelationships().size());
+ assertSame(objRel1To2, objRel2To1.getReverseRelationship());
+ assertSame(objRel2To1, objRel1To2.getReverseRelationship());
+
+ // try do use the merger to remove the column and relationship in the
+ // model
+ List<MergerToken> tokens = createMergeTokens();
+ assertTokens(tokens, 2, 0);
+ // TODO: reversing the following two tokens should also reverse the
+ // order
+ MergerToken token0 = tokens.get(0).createReverse(mergerFactory());
+ MergerToken token1 = tokens.get(1).createReverse(mergerFactory());
+ if (!(token0 instanceof DropRelationshipToModel && token1 instanceof DropColumnToModel || token1 instanceof DropRelationshipToModel
+ && token0 instanceof DropColumnToModel)) {
+ fail();
+ }
+ // do not execute DropRelationshipToModel, only DropColumnToModel.
+ if (token1 instanceof DropColumnToModel) {
+ execute(token1);
+ } else {
+ execute(token0);
+ }
+
+ // check after merging
+ assertNull(dbEntity2.getAttribute(e2col2.getName()));
+ assertEquals(0, dbEntity1.getRelationships().size());
+ assertEquals(0, dbEntity2.getRelationships().size());
+ assertEquals(0, objEntity1.getRelationships().size());
+ assertEquals(0, objEntity2.getRelationships().size());
+
+ // clear up
+
+ dbEntity1.removeRelationship(rel1To2.getName());
+ dbEntity2.removeRelationship(rel2To1.getName());
+ map.removeObjEntity(objEntity1.getName(), true);
+ map.removeDbEntity(dbEntity1.getName(), true);
+ map.removeObjEntity(objEntity2.getName(), true);
+ map.removeDbEntity(dbEntity2.getName(), true);
+ resolver.refreshMappingCache();
+ assertNull(map.getObjEntity(objEntity1.getName()));
+ assertNull(map.getDbEntity(dbEntity1.getName()));
+ assertNull(map.getObjEntity(objEntity2.getName()));
+ assertNull(map.getDbEntity(dbEntity2.getName()));
+ assertFalse(map.getDbEntities().contains(dbEntity1));
+ assertFalse(map.getDbEntities().contains(dbEntity2));
+
+ assertTokensAndExecute(2, 0);
+ assertTokensAndExecute(0, 0);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModelIT.java
new file mode 100644
index 0000000..cf2ec3d
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModelIT.java
@@ -0,0 +1,188 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.fail;
+
+import java.sql.Types;
+import java.util.List;
+
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+import org.junit.Test;
+
+public class DropRelationshipToModelIT extends MergeCase {
+
+ @Test
+ public void testForeignKey() throws Exception {
+ dropTableIfPresent("NEW_TABLE");
+ dropTableIfPresent("NEW_TABLE2");
+
+ assertTokensAndExecute(0, 0);
+
+ DbEntity dbEntity1 = new DbEntity("NEW_TABLE");
+
+ DbAttribute e1col1 = new DbAttribute("ID", Types.INTEGER, dbEntity1);
+ e1col1.setMandatory(true);
+ e1col1.setPrimaryKey(true);
+ dbEntity1.addAttribute(e1col1);
+
+ DbAttribute e1col2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity1);
+ e1col2.setMaxLength(10);
+ e1col2.setMandatory(false);
+ dbEntity1.addAttribute(e1col2);
+
+ map.addDbEntity(dbEntity1);
+
+ DbEntity dbEntity2 = new DbEntity("NEW_TABLE2");
+ DbAttribute e2col1 = new DbAttribute("ID", Types.INTEGER, dbEntity2);
+ e2col1.setMandatory(true);
+ e2col1.setPrimaryKey(true);
+ dbEntity2.addAttribute(e2col1);
+ DbAttribute e2col2 = new DbAttribute("FK", Types.INTEGER, dbEntity2);
+ dbEntity2.addAttribute(e2col2);
+ DbAttribute e2col3 = new DbAttribute("NAME", Types.VARCHAR, dbEntity2);
+ e2col3.setMaxLength(10);
+ dbEntity2.addAttribute(e2col3);
+
+ map.addDbEntity(dbEntity2);
+
+ // create db relationships
+ DbRelationship rel1To2 = new DbRelationship("rel1To2");
+ rel1To2.setSourceEntity(dbEntity1);
+ rel1To2.setTargetEntityName(dbEntity2);
+ rel1To2.setToMany(true);
+ rel1To2.addJoin(new DbJoin(rel1To2, e1col1.getName(), e2col2.getName()));
+ dbEntity1.addRelationship(rel1To2);
+ DbRelationship rel2To1 = new DbRelationship("rel2To1");
+ rel2To1.setSourceEntity(dbEntity2);
+ rel2To1.setTargetEntityName(dbEntity1);
+ rel2To1.setToMany(false);
+ rel2To1.addJoin(new DbJoin(rel2To1, e2col2.getName(), e1col1.getName()));
+ dbEntity2.addRelationship(rel2To1);
+ assertSame(rel1To2, rel2To1.getReverseRelationship());
+ assertSame(rel2To1, rel1To2.getReverseRelationship());
+
+ assertTokensAndExecute(4, 0);
+ assertTokensAndExecute(0, 0);
+
+ // create ObjEntities
+ ObjEntity objEntity1 = new ObjEntity("NewTable");
+ objEntity1.setDbEntity(dbEntity1);
+ ObjAttribute oatr1 = new ObjAttribute("name");
+ oatr1.setDbAttributePath(e1col2.getName());
+ oatr1.setType("java.lang.String");
+ objEntity1.addAttribute(oatr1);
+ map.addObjEntity(objEntity1);
+ ObjEntity objEntity2 = new ObjEntity("NewTable2");
+ objEntity2.setDbEntity(dbEntity2);
+ ObjAttribute o2a1 = new ObjAttribute("name");
+ o2a1.setDbAttributePath(e2col3.getName());
+ o2a1.setType("java.lang.String");
+ objEntity2.addAttribute(o2a1);
+ map.addObjEntity(objEntity2);
+
+ // create ObjRelationships
+ assertEquals(0, objEntity1.getRelationships().size());
+ assertEquals(0, objEntity2.getRelationships().size());
+ ObjRelationship objRel1To2 = new ObjRelationship("objRel1To2");
+ objRel1To2.addDbRelationship(rel1To2);
+ objRel1To2.setSourceEntity(objEntity1);
+ objRel1To2.setTargetEntityName(objEntity2);
+ objEntity1.addRelationship(objRel1To2);
+ ObjRelationship objRel2To1 = new ObjRelationship("objRel2To1");
+ objRel2To1.addDbRelationship(rel2To1);
+ objRel2To1.setSourceEntity(objEntity2);
+ objRel2To1.setTargetEntityName(objEntity1);
+ objEntity2.addRelationship(objRel2To1);
+ assertEquals(1, objEntity1.getRelationships().size());
+ assertEquals(1, objEntity2.getRelationships().size());
+ assertSame(objRel1To2, objRel2To1.getReverseRelationship());
+ assertSame(objRel2To1, objRel1To2.getReverseRelationship());
+
+ // remove relationship and fk from model, merge to db and read to model
+ dbEntity2.removeRelationship(rel2To1.getName());
+ dbEntity1.removeRelationship(rel1To2.getName());
+ dbEntity2.removeAttribute(e2col2.getName());
+ List<MergerToken> tokens = createMergeTokens();
+ /**
+ * Add Relationship NEW_TABLE->NEW_TABLE2 To Model
+ * Drop Relationship NEW_TABLE2->NEW_TABLE To DB
+ * Drop Column NEW_TABLE2.FK To DB
+ * */
+ assertTokens(tokens, 2, 1);
+ for (MergerToken token : tokens) {
+ if (token.getDirection().isToDb()) {
+ execute(token);
+ }
+ }
+ assertTokensAndExecute(0, 0);
+ dbEntity2.addRelationship(rel2To1);
+ dbEntity1.addRelationship(rel1To2);
+ dbEntity2.addAttribute(e2col2);
+
+ // try do use the merger to remove the relationship in the model
+ tokens = createMergeTokens();
+ assertTokens(tokens, 2, 0);
+ // TODO: reversing the following two tokens should also reverse the
+ // order
+ MergerToken token0 = tokens.get(0).createReverse(mergerFactory());
+ MergerToken token1 = tokens.get(1).createReverse(mergerFactory());
+ if (!(token0 instanceof DropRelationshipToModel && token1 instanceof DropColumnToModel || token1 instanceof DropRelationshipToModel
+ && token0 instanceof DropColumnToModel)) {
+ fail();
+ }
+ execute(token0);
+ execute(token1);
+
+ // check after merging
+ assertNull(dbEntity2.getAttribute(e2col2.getName()));
+ assertEquals(0, dbEntity1.getRelationships().size());
+ assertEquals(0, dbEntity2.getRelationships().size());
+ assertEquals(0, objEntity1.getRelationships().size());
+ assertEquals(0, objEntity2.getRelationships().size());
+
+ // clear up
+ dbEntity1.removeRelationship(rel1To2.getName());
+ dbEntity2.removeRelationship(rel2To1.getName());
+ map.removeObjEntity(objEntity1.getName(), true);
+ map.removeDbEntity(dbEntity1.getName(), true);
+ map.removeObjEntity(objEntity2.getName(), true);
+ map.removeDbEntity(dbEntity2.getName(), true);
+ resolver.refreshMappingCache();
+ assertNull(map.getObjEntity(objEntity1.getName()));
+ assertNull(map.getDbEntity(dbEntity1.getName()));
+ assertNull(map.getObjEntity(objEntity2.getName()));
+ assertNull(map.getDbEntity(dbEntity2.getName()));
+ assertFalse(map.getDbEntities().contains(dbEntity1));
+ assertFalse(map.getDbEntities().contains(dbEntity2));
+
+ assertTokensAndExecute(2, 0);
+ assertTokensAndExecute(0, 0);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropTableToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropTableToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropTableToModelIT.java
new file mode 100644
index 0000000..5b1744a
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DropTableToModelIT.java
@@ -0,0 +1,94 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Types;
+import java.util.List;
+
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.junit.Test;
+
+public class DropTableToModelIT extends MergeCase {
+
+ @Test
+ public void testDropTable() throws Exception {
+ dropTableIfPresent("NEW_TABLE");
+ assertTokensAndExecute(0, 0);
+
+ DbEntity dbEntity = new DbEntity("NEW_TABLE");
+
+ DbAttribute column1 = new DbAttribute("ID", Types.INTEGER, dbEntity);
+ column1.setMandatory(true);
+ column1.setPrimaryKey(true);
+ dbEntity.addAttribute(column1);
+
+ DbAttribute column2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity);
+ column2.setMaxLength(10);
+ column2.setMandatory(false);
+ dbEntity.addAttribute(column2);
+
+ map.addDbEntity(dbEntity);
+
+ assertTokensAndExecute(1, 0);
+ assertTokensAndExecute(0, 0);
+
+ ObjEntity objEntity = new ObjEntity("NewTable");
+ objEntity.setDbEntity(dbEntity);
+ ObjAttribute oatr1 = new ObjAttribute("name");
+ oatr1.setDbAttributePath(column2.getName());
+ oatr1.setType("java.lang.String");
+ objEntity.addAttribute(oatr1);
+ map.addObjEntity(objEntity);
+
+ // force drop table in db
+ MergerToken token = mergerFactory().createDropTableToDb(dbEntity);
+ execute(token);
+
+ List<MergerToken> tokens = createMergeTokens();
+ assertEquals(1, tokens.size());
+ token = tokens.get(0);
+ if (token.getDirection().isToDb()) {
+ token = token.createReverse(mergerFactory());
+ }
+ assertTrue(token instanceof DropTableToModel);
+ execute(token);
+ resolver.refreshMappingCache();
+ assertNull(map.getDbEntity(dbEntity.getName()));
+ assertNull(map.getObjEntity(objEntity.getName()));
+
+ // clear up
+ map.removeObjEntity(objEntity.getName(), true);
+ map.removeDbEntity(dbEntity.getName(), true);
+ resolver.refreshMappingCache();
+ assertNull(map.getObjEntity(objEntity.getName()));
+ assertNull(map.getDbEntity(dbEntity.getName()));
+ assertFalse(map.getDbEntities().contains(dbEntity));
+
+ assertTokensAndExecute(0, 0);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/EntityMergeSupportIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/EntityMergeSupportIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/EntityMergeSupportIT.java
new file mode 100644
index 0000000..d63c6a4
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/EntityMergeSupportIT.java
@@ -0,0 +1,102 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.DeleteRule;
+import org.apache.cayenne.map.ObjEntity;
+import org.junit.Test;
+
+import java.sql.Types;
+import java.util.Arrays;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+public class EntityMergeSupportIT extends MergeCase {
+
+ @Test
+ public void testMerging() {
+ DbEntity dbEntity1 = new DbEntity("NEW_TABLE");
+
+ DbAttribute e1col1 = new DbAttribute("ID", Types.INTEGER, dbEntity1);
+ e1col1.setMandatory(true);
+ e1col1.setPrimaryKey(true);
+ dbEntity1.addAttribute(e1col1);
+
+ DbAttribute e1col2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity1);
+ e1col2.setMaxLength(10);
+ e1col2.setMandatory(false);
+ dbEntity1.addAttribute(e1col2);
+
+ map.addDbEntity(dbEntity1);
+
+ DbEntity dbEntity2 = new DbEntity("NEW_TABLE2");
+ DbAttribute e2col1 = new DbAttribute("ID", Types.INTEGER, dbEntity2);
+ e2col1.setMandatory(true);
+ e2col1.setPrimaryKey(true);
+ dbEntity2.addAttribute(e2col1);
+ DbAttribute e2col2 = new DbAttribute("FK", Types.INTEGER, dbEntity2);
+ dbEntity2.addAttribute(e2col2);
+
+ map.addDbEntity(dbEntity2);
+
+ // create db relationships
+ DbRelationship rel1To2 = new DbRelationship("rel1To2");
+ rel1To2.setSourceEntity(dbEntity1);
+ rel1To2.setTargetEntityName(dbEntity2);
+ rel1To2.setToMany(true);
+ rel1To2.addJoin(new DbJoin(rel1To2, e1col1.getName(), e2col2.getName()));
+ dbEntity1.addRelationship(rel1To2);
+ DbRelationship rel2To1 = new DbRelationship("rel2To1");
+ rel2To1.setSourceEntity(dbEntity2);
+ rel2To1.setTargetEntityName(dbEntity1);
+ rel2To1.setToMany(false);
+ rel2To1.addJoin(new DbJoin(rel2To1, e2col2.getName(), e1col1.getName()));
+ dbEntity2.addRelationship(rel2To1);
+ assertSame(rel1To2, rel2To1.getReverseRelationship());
+ assertSame(rel2To1, rel1To2.getReverseRelationship());
+
+ ObjEntity objEntity1 = new ObjEntity("NewTable");
+ objEntity1.setDbEntity(dbEntity1);
+ map.addObjEntity(objEntity1);
+
+ ObjEntity objEntity2 = new ObjEntity("NewTable2");
+ objEntity2.setDbEntity(dbEntity2);
+ map.addObjEntity(objEntity2);
+
+ assertTrue(new EntityMergeSupport(map).synchronizeWithDbEntities(Arrays.asList(objEntity1, objEntity2)));
+ assertNotNull(objEntity1.getAttribute("name"));
+ assertNotNull(objEntity1.getRelationship("rel1To2"));
+ assertNotNull(objEntity2.getRelationship("rel2To1"));
+
+ assertEquals(objEntity1.getRelationship("rel1To2").getDeleteRule(), DeleteRule.DEFAULT_DELETE_RULE_TO_MANY);
+ assertEquals(objEntity2.getRelationship("rel2To1").getDeleteRule(), DeleteRule.DEFAULT_DELETE_RULE_TO_ONE);
+
+ map.removeObjEntity(objEntity2.getName());
+ map.removeObjEntity(objEntity1.getName());
+ map.removeDbEntity(dbEntity2.getName());
+ map.removeDbEntity(dbEntity1.getName());
+ }
+}
[10/15] cayenne git commit: CAY-2116 Split schema synchronization
code in a separate module
Posted by aa...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java
new file mode 100644
index 0000000..c2357b0
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java
@@ -0,0 +1,209 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.access.DataNode;
+import org.apache.cayenne.configuration.server.ServerRuntime;
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider;
+import org.apache.cayenne.dbsync.reverse.DbLoaderConfiguration;
+import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig;
+import org.apache.cayenne.dbsync.reverse.filters.PatternFilter;
+import org.apache.cayenne.dbsync.reverse.filters.TableFilter;
+import org.apache.cayenne.dbsync.unit.DbSyncCase;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.test.jdbc.DBHelper;
+import org.apache.cayenne.unit.UnitDbAdapter;
+import org.apache.cayenne.unit.di.server.CayenneProjects;
+import org.apache.cayenne.unit.di.server.ServerCaseDataSourceFactory;
+import org.apache.cayenne.unit.di.server.UseServerRuntime;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.Before;
+
+import java.sql.Connection;
+import java.sql.Statement;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
+public abstract class MergeCase extends DbSyncCase {
+
+ @Inject
+ protected EntityResolver resolver;
+ @Inject
+ protected DataNode node;
+ protected DataMap map;
+ private Log logger = LogFactory.getLog(MergeCase.class);
+ @Inject
+ private DBHelper dbHelper;
+ @Inject
+ private ServerRuntime runtime;
+ @Inject
+ private UnitDbAdapter accessStackAdapter;
+ @Inject
+ private ServerCaseDataSourceFactory dataSourceFactory;
+
+ @Override
+ public void cleanUpDB() throws Exception {
+ dbHelper.update("ARTGROUP").set("PARENT_GROUP_ID", null, Types.INTEGER).execute();
+ super.cleanUpDB();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+
+ // this map can't be safely modified in this test, as it is reset by DI
+ // container
+ // on every test
+ map = runtime.getDataDomain().getDataMap("testmap");
+
+ filterDataMap();
+
+ List<MergerToken> tokens = createMergeTokens();
+ execute(tokens);
+
+ assertTokensAndExecute(0, 0);
+ }
+
+ protected DbMerger createMerger() {
+ return createMerger(null);
+ }
+
+ protected DbMerger createMerger(ValueForNullProvider valueForNullProvider) {
+ return new DbMerger(mergerFactory(), valueForNullProvider);
+ }
+
+ protected List<MergerToken> createMergeTokens() {
+ DbLoaderConfiguration loaderConfiguration = new DbLoaderConfiguration();
+ loaderConfiguration.setFiltersConfig(FiltersConfig.create(null, null,
+ TableFilter.include("ARTIST|GALLERY|PAINTING|NEW_TABLE2?"), PatternFilter.INCLUDE_NOTHING));
+
+ return createMerger().createMergeTokens(node.getDataSource(), node.getAdapter(), map, loaderConfiguration);
+ }
+
+ /**
+ * Remote binary pk {@link DbEntity} for {@link DbAdapter} not supporting
+ * that and so on.
+ */
+ private void filterDataMap() {
+ // copied from AbstractAccessStack.dbEntitiesInInsertOrder
+ boolean excludeBinPK = accessStackAdapter.supportsBinaryPK();
+
+ if (!excludeBinPK) {
+ return;
+ }
+
+ List<DbEntity> entitiesToRemove = new ArrayList<DbEntity>();
+
+ for (DbEntity ent : map.getDbEntities()) {
+ for (DbAttribute attr : ent.getAttributes()) {
+ // check for BIN PK or FK to BIN Pk
+ if (attr.getType() == Types.BINARY || attr.getType() == Types.VARBINARY
+ || attr.getType() == Types.LONGVARBINARY) {
+
+ if (attr.isPrimaryKey() || attr.isForeignKey()) {
+ entitiesToRemove.add(ent);
+ break;
+ }
+ }
+ }
+ }
+
+ for (DbEntity e : entitiesToRemove) {
+ map.removeDbEntity(e.getName(), true);
+ }
+ }
+
+ protected void execute(List<MergerToken> tokens) {
+ MergerContext mergerContext = MergerContext.builder(map).dataNode(node).build();
+ for (MergerToken tok : tokens) {
+ tok.execute(mergerContext);
+ }
+ }
+
+ protected void execute(MergerToken token) throws Exception {
+ MergerContext mergerContext = MergerContext.builder(map).dataNode(node).build();
+ token.execute(mergerContext);
+ }
+
+ private void executeSql(String sql) throws Exception {
+
+ try (Connection conn = dataSourceFactory.getSharedDataSource().getConnection();) {
+
+ try (Statement st = conn.createStatement();) {
+ st.execute(sql);
+ }
+ }
+ }
+
+ protected void assertTokens(List<MergerToken> tokens, int expectedToDb, int expectedToModel) {
+ int actualToDb = 0;
+ int actualToModel = 0;
+ for (MergerToken token : tokens) {
+ if (token.getDirection().isToDb()) {
+ actualToDb++;
+ } else if (token.getDirection().isToModel()) {
+ actualToModel++;
+ }
+ }
+
+ assertEquals("tokens to db", expectedToDb, actualToDb);
+ assertEquals("tokens to model", expectedToModel, actualToModel);
+ }
+
+ protected void assertTokensAndExecute(int expectedToDb, int expectedToModel) {
+ List<MergerToken> tokens = createMergeTokens();
+ assertTokens(tokens, expectedToDb, expectedToModel);
+ execute(tokens);
+ }
+
+ protected MergerTokenFactory mergerFactory() {
+ return runtime.getInjector().getInstance(MergerTokenFactoryProvider.class).get(node.getAdapter());
+ }
+
+ protected void dropTableIfPresent(String tableName) throws Exception {
+
+ // must have a dummy datamap for the dummy table for the downstream code
+ // to work
+ DataMap map = new DataMap("dummy");
+ map.setQuotingSQLIdentifiers(map.isQuotingSQLIdentifiers());
+ DbEntity entity = new DbEntity(tableName);
+ map.addDbEntity(entity);
+
+ AbstractToDbToken t = (AbstractToDbToken) mergerFactory().createDropTableToDb(entity);
+
+ for (String sql : t.createSql(node.getAdapter())) {
+
+ try {
+ executeSql(sql);
+ } catch (Exception e) {
+ logger.info("Exception dropping table " + tableName + ", probably abscent..");
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergerFactoryIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergerFactoryIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergerFactoryIT.java
new file mode 100644
index 0000000..1fe7da7
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergerFactoryIT.java
@@ -0,0 +1,310 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.sql.Types;
+
+import org.apache.cayenne.CayenneDataObject;
+import org.apache.cayenne.access.DataContext;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.junit.Test;
+
+public class MergerFactoryIT extends MergeCase {
+
+ @Inject
+ private DataContext context;
+
+ @Test
+ public void testAddAndDropColumnToDb() throws Exception {
+ DbEntity dbEntity = map.getDbEntity("PAINTING");
+ assertNotNull(dbEntity);
+
+ // create and add new column to model and db
+ DbAttribute column = new DbAttribute("NEWCOL1", Types.VARCHAR, dbEntity);
+
+ column.setMandatory(false);
+ column.setMaxLength(10);
+ dbEntity.addAttribute(column);
+ assertTokensAndExecute(1, 0);
+
+ // try merge once more to check that is was merged
+ assertTokensAndExecute(0, 0);
+
+ // remove it from model and db
+ dbEntity.removeAttribute(column.getName());
+ assertTokensAndExecute(1, 0);
+ assertTokensAndExecute(0, 0);
+ }
+
+ @Test
+ public void testChangeVarcharSizeToDb() throws Exception {
+ DbEntity dbEntity = map.getDbEntity("PAINTING");
+ assertNotNull(dbEntity);
+
+ // create and add new column to model and db
+ DbAttribute column = new DbAttribute("NEWCOL2", Types.VARCHAR, dbEntity);
+
+ column.setMandatory(false);
+ column.setMaxLength(10);
+ dbEntity.addAttribute(column);
+ assertTokensAndExecute(1, 0);
+
+ // check that is was merged
+ assertTokensAndExecute(0, 0);
+
+ // change size
+ column.setMaxLength(20);
+
+ // merge to db
+ assertTokensAndExecute(1, 0);
+
+ // check that is was merged
+ assertTokensAndExecute(0, 0);
+
+ // clean up
+ dbEntity.removeAttribute(column.getName());
+ assertTokensAndExecute(1, 0);
+ assertTokensAndExecute(0, 0);
+ }
+
+ @Test
+ public void testMultipleTokensToDb() throws Exception {
+ DbEntity dbEntity = map.getDbEntity("PAINTING");
+ assertNotNull(dbEntity);
+
+ DbAttribute column1 = new DbAttribute("NEWCOL3", Types.VARCHAR, dbEntity);
+ column1.setMandatory(false);
+ column1.setMaxLength(10);
+ dbEntity.addAttribute(column1);
+ DbAttribute column2 = new DbAttribute("NEWCOL4", Types.VARCHAR, dbEntity);
+ column2.setMandatory(false);
+ column2.setMaxLength(10);
+ dbEntity.addAttribute(column2);
+
+ assertTokensAndExecute(2, 0);
+
+ // check that is was merged
+ assertTokensAndExecute(0, 0);
+
+ // change size
+ column1.setMaxLength(20);
+ column2.setMaxLength(30);
+
+ // merge to db
+ assertTokensAndExecute(2, 0);
+
+ // check that is was merged
+ assertTokensAndExecute(0, 0);
+
+ // clean up
+ dbEntity.removeAttribute(column1.getName());
+ dbEntity.removeAttribute(column2.getName());
+ assertTokensAndExecute(2, 0);
+ assertTokensAndExecute(0, 0);
+ }
+
+ @Test
+ public void testAddTableToDb() throws Exception {
+ dropTableIfPresent("NEW_TABLE");
+
+ assertTokensAndExecute(0, 0);
+
+ DbEntity dbEntity = new DbEntity("NEW_TABLE");
+
+ DbAttribute column1 = new DbAttribute("ID", Types.INTEGER, dbEntity);
+ column1.setMandatory(true);
+ column1.setPrimaryKey(true);
+ dbEntity.addAttribute(column1);
+
+ DbAttribute column2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity);
+ column2.setMaxLength(10);
+ column2.setMandatory(false);
+ dbEntity.addAttribute(column2);
+
+ map.addDbEntity(dbEntity);
+
+ assertTokensAndExecute(1, 0);
+ assertTokensAndExecute(0, 0);
+
+ ObjEntity objEntity = new ObjEntity("NewTable");
+ objEntity.setDbEntity(dbEntity);
+ ObjAttribute oatr1 = new ObjAttribute("name");
+ oatr1.setDbAttributePath(column2.getName());
+ oatr1.setType("java.lang.String");
+ objEntity.addAttribute(oatr1);
+ map.addObjEntity(objEntity);
+
+ for (int i = 0; i < 5; i++) {
+ CayenneDataObject dao = (CayenneDataObject) context.newObject(objEntity
+ .getName());
+ dao.writeProperty(oatr1.getName(), "test " + i);
+ }
+ context.commitChanges();
+
+ // clear up
+ map.removeObjEntity(objEntity.getName(), true);
+ map.removeDbEntity(dbEntity.getName(), true);
+ resolver.refreshMappingCache();
+ assertNull(map.getObjEntity(objEntity.getName()));
+ assertNull(map.getDbEntity(dbEntity.getName()));
+ assertFalse(map.getDbEntities().contains(dbEntity));
+
+ assertTokensAndExecute(1, 0);
+ assertTokensAndExecute(0, 0);
+ }
+
+ @Test
+ public void testAddForeignKeyWithTable() throws Exception {
+ dropTableIfPresent("NEW_TABLE");
+
+ assertTokensAndExecute(0, 0);
+
+ DbEntity dbEntity = new DbEntity("NEW_TABLE");
+
+ attr(dbEntity, "ID", Types.INTEGER, true, true);
+ attr(dbEntity, "NAME", Types.VARCHAR, false, false).setMaxLength(10);
+ attr(dbEntity, "ARTIST_ID", Types.BIGINT, false, false);
+
+ map.addDbEntity(dbEntity);
+
+ DbEntity artistDbEntity = map.getDbEntity("ARTIST");
+ assertNotNull(artistDbEntity);
+
+ // relation from new_table to artist
+ DbRelationship r1 = new DbRelationship("toArtistR1");
+ r1.setSourceEntity(dbEntity);
+ r1.setTargetEntityName(artistDbEntity);
+ r1.setToMany(false);
+ r1.addJoin(new DbJoin(r1, "ARTIST_ID", "ARTIST_ID"));
+ dbEntity.addRelationship(r1);
+
+ // relation from artist to new_table
+ DbRelationship r2 = new DbRelationship("toNewTableR2");
+ r2.setSourceEntity(artistDbEntity);
+ r2.setTargetEntityName(dbEntity);
+ r2.setToMany(true);
+ r2.addJoin(new DbJoin(r2, "ARTIST_ID", "ARTIST_ID"));
+ artistDbEntity.addRelationship(r2);
+
+ assertTokensAndExecute(2, 0);
+ assertTokensAndExecute(0, 0);
+
+ // remove relationships
+ dbEntity.removeRelationship(r1.getName());
+ artistDbEntity.removeRelationship(r2.getName());
+ resolver.refreshMappingCache();
+ /*
+ * Db -Rel 'toArtistR1' - NEW_TABLE 1 -> 1 ARTIST"
+r2 = * Db -Rel 'toNewTableR2' - ARTIST 1 -> * NEW_TABLE"
+ * */
+ assertTokensAndExecute(1, 1);
+ assertTokensAndExecute(0, 0);
+
+ // clear up
+ // map.removeObjEntity(objEntity.getName(), true);
+ map.removeDbEntity(dbEntity.getName(), true);
+ resolver.refreshMappingCache();
+ // assertNull(map.getObjEntity(objEntity.getName()));
+ assertNull(map.getDbEntity(dbEntity.getName()));
+ assertFalse(map.getDbEntities().contains(dbEntity));
+
+ assertTokensAndExecute(1, 0);
+ assertTokensAndExecute(0, 0);
+ }
+
+ @Test
+ public void testAddForeignKeyAfterTable() throws Exception {
+ dropTableIfPresent("NEW_TABLE");
+
+ assertTokensAndExecute(0, 0);
+
+ DbEntity dbEntity = new DbEntity("NEW_TABLE");
+ attr(dbEntity, "ID", Types.INTEGER, true, true);
+ attr(dbEntity, "NAME", Types.VARCHAR, false, false).setMaxLength(10);
+ attr(dbEntity, "ARTIST_ID", Types.BIGINT, false, false);
+
+ map.addDbEntity(dbEntity);
+
+ DbEntity artistDbEntity = map.getDbEntity("ARTIST");
+ assertNotNull(artistDbEntity);
+
+ assertTokensAndExecute(1, 0);
+ assertTokensAndExecute(0, 0);
+
+ // relation from new_table to artist
+ DbRelationship r1 = new DbRelationship("toArtistR1");
+ r1.setSourceEntity(dbEntity);
+ r1.setTargetEntityName(artistDbEntity);
+ r1.setToMany(false);
+ r1.addJoin(new DbJoin(r1, "ARTIST_ID", "ARTIST_ID"));
+ dbEntity.addRelationship(r1);
+
+ // relation from artist to new_table
+ DbRelationship r2 = new DbRelationship("toNewTableR2");
+ r2.setSourceEntity(artistDbEntity);
+ r2.setTargetEntityName(dbEntity);
+ r2.setToMany(true);
+ r2.addJoin(new DbJoin(r2, "ARTIST_ID", "ARTIST_ID"));
+ artistDbEntity.addRelationship(r2);
+
+ assertTokensAndExecute(1, 0);
+ assertTokensAndExecute(0, 0);
+
+ // remove relationships
+ dbEntity.removeRelationship(r1.getName());
+ artistDbEntity.removeRelationship(r2.getName());
+ resolver.refreshMappingCache();
+ /*
+ * Add Relationship ARTIST->NEW_TABLE To Model
+ * Drop Relationship NEW_TABLE->ARTIST To DB
+ * */
+ assertTokensAndExecute(1, 1);
+ assertTokensAndExecute(0, 0);
+
+ // clear up
+ // map.removeObjEntity(objEntity.getName(), true);
+ map.removeDbEntity(dbEntity.getName(), true);
+ resolver.refreshMappingCache();
+ // assertNull(map.getObjEntity(objEntity.getName()));
+ assertNull(map.getDbEntity(dbEntity.getName()));
+ assertFalse(map.getDbEntities().contains(dbEntity));
+
+ assertTokensAndExecute(1, 0);
+ assertTokensAndExecute(0, 0);
+ }
+
+ private static DbAttribute attr(DbEntity dbEntity, String name, int type, boolean mandatory, boolean primaryKey) {
+ DbAttribute column1 = new DbAttribute(name, type, dbEntity);
+ column1.setMandatory(mandatory);
+ column1.setPrimaryKey(primaryKey);
+
+ dbEntity.addAttribute(column1);
+ return column1;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/SetAllowNullToDbIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/SetAllowNullToDbIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/SetAllowNullToDbIT.java
new file mode 100644
index 0000000..6391ad0
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/SetAllowNullToDbIT.java
@@ -0,0 +1,66 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.sql.Types;
+
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.junit.Test;
+
+public class SetAllowNullToDbIT extends MergeCase {
+
+ @Test
+ public void test() throws Exception {
+ DbEntity dbEntity = map.getDbEntity("PAINTING");
+ assertNotNull(dbEntity);
+
+ // create and add new column to model and db
+ DbAttribute column = new DbAttribute("NEWCOL2", Types.VARCHAR, dbEntity);
+
+ try {
+
+ column.setMandatory(true);
+ column.setMaxLength(10);
+ dbEntity.addAttribute(column);
+ assertTokensAndExecute(2, 0);
+
+ // check that is was merged
+ assertTokensAndExecute(0, 0);
+
+ // set null
+ column.setMandatory(false);
+
+ // merge to db
+ assertTokensAndExecute(1, 0);
+
+ // check that is was merged
+ assertTokensAndExecute(0, 0);
+
+ // clean up
+ } finally {
+ dbEntity.removeAttribute(column.getName());
+ assertTokensAndExecute(1, 0);
+ assertTokensAndExecute(0, 0);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/SetNotNullToDbIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/SetNotNullToDbIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/SetNotNullToDbIT.java
new file mode 100644
index 0000000..508d0f8
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/SetNotNullToDbIT.java
@@ -0,0 +1,62 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.sql.Types;
+
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.junit.Test;
+
+public class SetNotNullToDbIT extends MergeCase {
+
+ @Test
+ public void test() throws Exception {
+ DbEntity dbEntity = map.getDbEntity("PAINTING");
+ assertNotNull(dbEntity);
+
+ // create and add new column to model and db
+ DbAttribute column = new DbAttribute("NEWCOL2", Types.VARCHAR, dbEntity);
+
+ column.setMandatory(false);
+ column.setMaxLength(10);
+ dbEntity.addAttribute(column);
+ assertTokensAndExecute(1, 0);
+
+ // check that is was merged
+ assertTokensAndExecute(0, 0);
+
+ // set not null
+ column.setMandatory(true);
+
+ // merge to db
+ assertTokensAndExecute(1, 0);
+
+ // check that is was merged
+ assertTokensAndExecute(0, 0);
+
+ // clean up
+ dbEntity.removeAttribute(column.getName());
+ assertTokensAndExecute(1, 0);
+ assertTokensAndExecute(0, 0);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToDbIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToDbIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToDbIT.java
new file mode 100644
index 0000000..3b513e7
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToDbIT.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.dbsync.merge;
+
+import java.sql.Types;
+
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.junit.Test;
+
+public class SetPrimaryKeyToDbIT extends MergeCase {
+
+ @Test
+ public void test() throws Exception {
+ dropTableIfPresent("NEW_TABLE");
+ assertTokensAndExecute(0, 0);
+
+ DbEntity dbEntity1 = new DbEntity("NEW_TABLE");
+
+ DbAttribute e1col1 = new DbAttribute("ID1", Types.INTEGER, dbEntity1);
+ e1col1.setMandatory(true);
+ e1col1.setPrimaryKey(true);
+ dbEntity1.addAttribute(e1col1);
+ map.addDbEntity(dbEntity1);
+
+ assertTokensAndExecute(1, 0);
+ assertTokensAndExecute(0, 0);
+
+ DbAttribute e1col2 = new DbAttribute("ID2", Types.INTEGER, dbEntity1);
+ e1col2.setMandatory(true);
+ dbEntity1.addAttribute(e1col2);
+
+ assertTokensAndExecute(2, 0);
+ assertTokensAndExecute(0, 0);
+
+ e1col1.setPrimaryKey(false);
+ e1col2.setPrimaryKey(true);
+
+ assertTokensAndExecute(1, 0);
+ assertTokensAndExecute(0, 0);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReversTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReversTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReversTest.java
new file mode 100644
index 0000000..b23128c
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensReversTest.java
@@ -0,0 +1,89 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.dbsync.merge.factory.HSQLMergerTokenFactory;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Collections;
+
+import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.dbAttr;
+import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.dbEntity;
+
+/**
+ * @since 4.0.
+ */
+public class TokensReversTest {
+
+ @Test
+ public void testReverses() {
+ DbAttribute attr = dbAttr().build();
+ DbEntity entity = dbEntity().attributes(attr).build();
+ DbRelationship rel = new DbRelationship("rel");
+ rel.setSourceEntity(entity);
+ rel.addJoin(new DbJoin(rel, attr.getName(), "dontKnow"));
+
+ test(factory().createAddColumnToDb(entity, attr));
+ test(factory().createAddColumnToModel(entity, attr));
+ test(factory().createDropColumnToDb(entity, attr));
+ test(factory().createDropColumnToModel(entity, attr));
+
+ test(factory().createAddRelationshipToDb(entity, rel));
+ test(factory().createAddRelationshipToModel(entity, rel));
+ test(factory().createDropRelationshipToDb(entity, rel));
+ test(factory().createDropRelationshipToModel(entity, rel));
+
+ test(factory().createCreateTableToDb(entity));
+ test(factory().createCreateTableToModel(entity));
+ test(factory().createDropTableToDb(entity));
+ test(factory().createDropTableToModel(entity));
+
+ test(factory().createSetAllowNullToDb(entity, attr));
+ test(factory().createSetAllowNullToModel(entity, attr));
+ test(factory().createSetNotNullToDb(entity, attr));
+ test(factory().createSetNotNullToModel(entity, attr));
+
+ DbAttribute attr2 = dbAttr().build();
+ test(factory().createSetColumnTypeToDb(entity, attr, attr2));
+ test(factory().createSetColumnTypeToModel(entity, attr, attr2));
+
+ test(factory().createSetPrimaryKeyToDb(entity, Collections.singleton(attr), Collections.singleton(attr2), "PK"));
+ test(factory().createSetPrimaryKeyToModel(entity, Collections.singleton(attr), Collections.singleton(attr2), "PK"));
+
+ test(factory().createSetValueForNullToDb(entity, attr, new DefaultValueForNullProvider()));
+ }
+
+ private void test(MergerToken token1) {
+ MergerToken token2 = token1.createReverse(factory()).createReverse(factory());
+
+ Assert.assertEquals(token1.getTokenName(), token2.getTokenName());
+ Assert.assertEquals(token1.getTokenValue(), token2.getTokenValue());
+ Assert.assertEquals(token1.getDirection(), token2.getDirection());
+ }
+
+ private MergerTokenFactory factory() {
+ return new HSQLMergerTokenFactory();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensToModelExecutionTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensToModelExecutionTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensToModelExecutionTest.java
new file mode 100644
index 0000000..b9abea1
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/TokensToModelExecutionTest.java
@@ -0,0 +1,80 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.access.DataNode;
+import org.apache.cayenne.dbsync.merge.factory.DefaultMergerTokenFactory;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.junit.Test;
+
+import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.dataMap;
+import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.dbAttr;
+import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.dbEntity;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @since 4.0.
+ */
+public class TokensToModelExecutionTest {
+
+ @Test
+ public void testCreateAndDropTable() throws Exception {
+ DbEntity entity = dbEntity().build();
+
+ DataMap dataMap = dataMap().build();
+ assertTrue(dataMap.getDbEntityMap().isEmpty());
+ assertTrue(dataMap.getObjEntityMap().isEmpty());
+
+ MergerContext context = MergerContext.builder(dataMap).dataNode(new DataNode()).build();
+ new DefaultMergerTokenFactory().createCreateTableToModel(entity).execute(context);
+
+ assertEquals(1, dataMap.getDbEntityMap().size());
+ assertEquals(1, dataMap.getObjEntities().size());
+ assertEquals(entity, dataMap.getDbEntity(entity.getName()));
+
+ new DefaultMergerTokenFactory().createDropTableToModel(entity).execute(context);
+ assertTrue(dataMap.getDbEntityMap().isEmpty());
+ assertTrue(dataMap.getObjEntityMap().isEmpty());
+ }
+
+ @Test
+ public void testCreateAndDropColumn() throws Exception {
+ DbAttribute attr = dbAttr("attr").build();
+ DbEntity entity = dbEntity().build();
+
+ DataMap dataMap = dataMap().with(entity).build();
+ assertEquals(1, dataMap.getDbEntityMap().size());
+ assertTrue(dataMap.getObjEntityMap().isEmpty());
+
+ MergerContext context = MergerContext.builder(dataMap).dataNode(new DataNode()).build();
+ new DefaultMergerTokenFactory().createAddColumnToModel(entity, attr).execute(context);
+
+ assertEquals(1, dataMap.getDbEntityMap().size());
+ assertEquals(1, entity.getAttributes().size());
+ assertEquals(attr, entity.getAttribute(attr.getName()));
+
+ new DefaultMergerTokenFactory().createDropColumnToModel(entity, attr).execute(context);
+ assertEquals(1, dataMap.getDbEntityMap().size());
+ assertTrue(entity.getAttributes().isEmpty());
+ assertTrue(dataMap.getObjEntityMap().isEmpty());
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/ValueForNullIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/ValueForNullIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/ValueForNullIT.java
new file mode 100644
index 0000000..e9910fd
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/ValueForNullIT.java
@@ -0,0 +1,127 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import junit.framework.AssertionFailedError;
+import org.apache.cayenne.DataObject;
+import org.apache.cayenne.Persistent;
+import org.apache.cayenne.access.DataContext;
+import org.apache.cayenne.access.jdbc.SQLParameterBinding;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.query.SelectQuery;
+import org.junit.Test;
+
+import java.sql.Types;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class ValueForNullIT extends MergeCase {
+
+ private static final String DEFAULT_VALUE_STRING = "DEFSTRING";
+
+ @Inject
+ private DataContext context;
+
+ @Test
+ public void test() throws Exception {
+ DbEntity dbEntity = map.getDbEntity("PAINTING");
+ assertNotNull(dbEntity);
+ ObjEntity objEntity = map.getObjEntity("Painting");
+ assertNotNull(objEntity);
+
+ // insert some rows before adding "not null" column
+ final int nrows = 10;
+ for (int i = 0; i < nrows; i++) {
+ DataObject o = (DataObject) context.newObject("Painting");
+ o.writeProperty("paintingTitle", "ptitle" + i);
+ }
+ context.commitChanges();
+
+ // create and add new column to model and db
+ DbAttribute column = new DbAttribute("NEWCOL2", Types.VARCHAR, dbEntity);
+
+ column.setMandatory(false);
+ column.setMaxLength(10);
+ dbEntity.addAttribute(column);
+ assertTrue(dbEntity.getAttributes().contains(column));
+ assertEquals(column, dbEntity.getAttribute(column.getName()));
+ assertTokensAndExecute(1, 0);
+
+ // need obj attr to be able to query
+ ObjAttribute objAttr = new ObjAttribute("newcol2");
+ objAttr.setDbAttributePath(column.getName());
+ objEntity.addAttribute(objAttr);
+
+ // check that is was merged
+ assertTokensAndExecute(0, 0);
+
+ // set not null
+ column.setMandatory(true);
+
+ // merge to db
+ assertTokensAndExecute(2, 0);
+
+ // check that is was merged
+ assertTokensAndExecute(0, 0);
+
+ // check values for null
+ Expression qual = ExpressionFactory.matchExp(objAttr.getName(), DEFAULT_VALUE_STRING);
+ SelectQuery query = new SelectQuery("Painting", qual);
+ List<Persistent> rows = context.performQuery(query);
+ assertEquals(nrows, rows.size());
+
+ // clean up
+ dbEntity.removeAttribute(column.getName());
+ assertTokensAndExecute(1, 0);
+ assertTokensAndExecute(0, 0);
+ }
+
+ @Override
+ protected DbMerger createMerger(final ValueForNullProvider valueForNullProvider) {
+ return super.createMerger(new DefaultValueForNullProvider() {
+
+ @Override
+ protected SQLParameterBinding get(DbEntity entity, DbAttribute column) {
+ int type = column.getType();
+ switch (type) {
+ case Types.VARCHAR:
+ return new SQLParameterBinding(DEFAULT_VALUE_STRING, type, -1);
+ default:
+ throw new AssertionFailedError("should not get here");
+ }
+ }
+
+ @Override
+ public boolean hasValueFor(DbEntity entity, DbAttribute column) {
+ return true;
+ }
+
+ });
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/Builder.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/Builder.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/Builder.java
new file mode 100644
index 0000000..baf8240
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/Builder.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.dbsync.merge.builders;
+
+/**
+ * Base interface for all domain builders
+ *
+ * @since 4.0.
+ */
+public interface Builder<T> {
+
+ /**
+ * Build valid object. If some required data omitted it will be filled with random data.
+ * */
+ T build();
+
+ /**
+ * Build valid object and add some optional fields randomly.
+ * */
+ T random();
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DataMapBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DataMapBuilder.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DataMapBuilder.java
new file mode 100644
index 0000000..a7aa11c
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DataMapBuilder.java
@@ -0,0 +1,128 @@
+/*****************************************************************
+ * 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.dbsync.merge.builders;
+
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.map.ObjEntity;
+
+import java.util.Collections;
+
+/**
+ * @since 4.0.
+ */
+public class DataMapBuilder extends DefaultBuilder<DataMap> {
+
+ public DataMapBuilder() {
+ this(new DataMap());
+ }
+
+ public DataMapBuilder(DataMap dataMap) {
+ super(dataMap);
+ }
+
+ public DataMapBuilder with(DbEntity ... entities) {
+ for (DbEntity entity : entities) {
+ obj.addDbEntity(entity);
+ }
+
+ return this;
+ }
+
+ public DataMapBuilder with(DbEntityBuilder ... entities) {
+ for (DbEntityBuilder entity : entities) {
+ obj.addDbEntity(entity.build());
+ }
+
+ return this;
+ }
+
+ public DataMapBuilder withDbEntities(int count) {
+ for (int i = 0; i < count; i++) {
+ obj.addDbEntity(ObjectMother.dbEntity().random());
+ }
+
+ return this;
+ }
+
+ public DataMapBuilder with(ObjEntity... entities) {
+ for (ObjEntity entity : entities) {
+ obj.addObjEntity(entity);
+ }
+
+ return this;
+ }
+
+ public DataMapBuilder with(ObjEntityBuilder ... entities) {
+ for (ObjEntityBuilder entity : entities) {
+ obj.addObjEntity(entity.build());
+ }
+
+ return this;
+ }
+
+ public DataMapBuilder withObjEntities(int count) {
+ for (int i = 0; i < count; i++) {
+ obj.addObjEntity(ObjectMother.objEntity().random());
+ }
+
+ return this;
+ }
+
+ public DataMapBuilder join(String from, String to) {
+ return join(null, from, to);
+ }
+
+ public DataMapBuilder join(String name, String from, String to) {
+ String[] fromSplit = from.split("\\.");
+ DbEntity fromEntity = obj.getDbEntity(fromSplit[0]);
+ if (fromEntity == null) {
+ throw new IllegalArgumentException("Entity '" + fromSplit[0] + "' is undefined");
+ }
+
+ String[] toSplit = to.split("\\.");
+
+ fromEntity.addRelationship(new DbRelationshipBuilder(name)
+ .from(fromEntity, fromSplit[1])
+ .to(toSplit[0], toSplit[1])
+
+ .build());
+
+ return this;
+ }
+
+ public DataMap build() {
+ if (obj.getNamespace() == null) {
+ obj.setNamespace(new EntityResolver(Collections.singleton(obj)));
+ }
+
+ return obj;
+ }
+
+ @Override
+ public DataMap random() {
+ if (dataFactory.chance(90)) {
+ withDbEntities(dataFactory.getNumberUpTo(10));
+ }
+
+
+ return build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbAttributeBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbAttributeBuilder.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbAttributeBuilder.java
new file mode 100644
index 0000000..2d600f3
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbAttributeBuilder.java
@@ -0,0 +1,115 @@
+/*****************************************************************
+ * 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.dbsync.merge.builders;
+
+import org.apache.cayenne.datafactory.DictionaryValueProvider;
+import org.apache.cayenne.datafactory.ValueProvider;
+import org.apache.cayenne.dba.TypesMapping;
+import org.apache.cayenne.map.DbAttribute;
+
+import static org.apache.commons.lang.StringUtils.isEmpty;
+
+/**
+ * @since 4.0.
+ */
+public class DbAttributeBuilder extends DefaultBuilder<DbAttribute> {
+
+ private static final ValueProvider<String> TYPES_RANDOM = new DictionaryValueProvider<String>(ValueProvider.RANDOM) {
+ @Override
+ protected String[] values() {
+ return TypesMapping.getDatabaseTypes();
+ }
+ };
+
+ public DbAttributeBuilder() {
+ super(new DbAttribute());
+ }
+
+ public DbAttributeBuilder name() {
+ return name(getRandomJavaName());
+ }
+
+ public DbAttributeBuilder name(String name) {
+ obj.setName(name);
+
+ return this;
+ }
+
+ public DbAttributeBuilder type() {
+ return type(TYPES_RANDOM.randomValue());
+ }
+
+ public DbAttributeBuilder type(String item) {
+ obj.setType(TypesMapping.getSqlTypeByName(item));
+
+ return this;
+ }
+
+ public DbAttributeBuilder typeInt() {
+ return type(TypesMapping.SQL_INTEGER);
+ }
+
+ public DbAttributeBuilder typeBigInt() {
+ return type(TypesMapping.SQL_BIGINT);
+ }
+
+ public DbAttributeBuilder typeVarchar(int length) {
+ type(TypesMapping.SQL_VARCHAR);
+ length(length);
+
+ return this;
+ }
+
+ private DbAttributeBuilder length(int length) {
+ obj.setMaxLength(length);
+
+ return this;
+ }
+
+ public DbAttributeBuilder primaryKey() {
+ obj.setPrimaryKey(true);
+
+ return this;
+ }
+
+ public DbAttributeBuilder mandatory() {
+ obj.setMandatory(true);
+
+ return this;
+ }
+
+ @Override
+ public DbAttribute build() {
+ if (isEmpty(obj.getName())) {
+ name();
+ }
+
+ if (obj.getType() == TypesMapping.NOT_DEFINED) {
+ type();
+ }
+
+ return obj;
+ }
+
+ @Override
+ public DbAttribute random() {
+ return build();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbEntityBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbEntityBuilder.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbEntityBuilder.java
new file mode 100644
index 0000000..03f0738
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbEntityBuilder.java
@@ -0,0 +1,90 @@
+/*****************************************************************
+ * 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.dbsync.merge.builders;
+
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * @since 4.0.
+ */
+public class DbEntityBuilder extends DefaultBuilder<DbEntity> {
+
+ public DbEntityBuilder() {
+ super(new DbEntity());
+ }
+
+ public DbEntityBuilder name() {
+ return name(getRandomJavaName());
+ }
+
+ public DbEntityBuilder name(String name) {
+ obj.setName(name);
+
+ return this;
+ }
+
+ public DbEntityBuilder attributes(DbAttribute ... attributes) {
+ for (DbAttribute attribute : attributes) {
+ obj.addAttribute(attribute);
+ }
+
+ return this;
+ }
+
+ public DbEntityBuilder attributes(DbAttributeBuilder ... attributes) {
+ for (DbAttributeBuilder attribute : attributes) {
+ obj.addAttribute(attribute.build());
+ }
+
+ return this;
+ }
+
+ public DbEntityBuilder attributes(int numberUpTo) {
+ for (int i = 0; i < numberUpTo; i++) {
+ try {
+ obj.addAttribute(new DbAttributeBuilder().random());
+ } catch (IllegalArgumentException e) {
+ i--; // try again
+ }
+ }
+
+ return this;
+ }
+
+
+ @Override
+ public DbEntity build() {
+ if (obj.getName() == null) {
+ obj.setName(StringUtils.capitalize(getRandomJavaName()));
+ }
+
+ return obj;
+ }
+
+ @Override
+ public DbEntity random() {
+ if (dataFactory.chance(99)) {
+ attributes(dataFactory.getNumberUpTo(20));
+ }
+
+ return build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbRelationshipBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbRelationshipBuilder.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbRelationshipBuilder.java
new file mode 100644
index 0000000..ae87549
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DbRelationshipBuilder.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.dbsync.merge.builders;
+
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+
+/**
+ * @since 4.0.
+ */
+public class DbRelationshipBuilder extends DefaultBuilder<DbRelationship> {
+
+ private String[] from;
+ private String[] to;
+
+ public DbRelationshipBuilder() {
+ super(new DbRelationship());
+ }
+
+ public DbRelationshipBuilder(String name) {
+ super(new DbRelationship(name));
+ }
+
+ public DbRelationshipBuilder(DbRelationship obj) {
+ super(obj);
+ }
+
+ public DbRelationshipBuilder name() {
+ return name(getRandomJavaName());
+ }
+
+ public DbRelationshipBuilder name(String name) {
+ obj.setName(name);
+
+ return this;
+ }
+
+ public DbRelationshipBuilder from(DbEntity entity, String ... columns) {
+ obj.setSourceEntity(entity);
+ this.from = columns;
+
+ return this;
+ }
+
+ public DbRelationshipBuilder to(String entityName, String ... columns) {
+ obj.setTargetEntityName(entityName);
+ this.to = columns;
+
+ return this;
+ }
+
+ @Override
+ public DbRelationship build() {
+ if (obj.getName() == null) {
+ name();
+ }
+
+ if (from.length != to.length) {
+ throw new IllegalStateException("from and to columns name size mismatch");
+ }
+
+ for (int i = 0; i < from.length; i++) {
+ obj.addJoin(new DbJoin(obj, from[i], to[i]));
+ }
+
+ return obj;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DefaultBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DefaultBuilder.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DefaultBuilder.java
new file mode 100644
index 0000000..559347b
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/DefaultBuilder.java
@@ -0,0 +1,57 @@
+/*****************************************************************
+ * 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.dbsync.merge.builders;
+
+import org.apache.cayenne.datafactory.DataFactory;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * @since 4.0.
+ */
+public abstract class DefaultBuilder<T> implements Builder<T> {
+
+ protected final DataFactory dataFactory;
+ protected final T obj;
+
+
+ protected DefaultBuilder(T obj) {
+ this.dataFactory = new DataFactory();
+ this.obj = obj;
+ }
+
+ public String getRandomJavaName() {
+ int count = dataFactory.getNumberBetween(1, 5);
+ StringBuilder res = new StringBuilder();
+ for (int i = 0; i < count; i++) {
+ res.append(StringUtils.capitalize(dataFactory.getRandomWord()));
+ }
+
+ return StringUtils.uncapitalize(res.toString());
+ }
+
+ @Override
+ public T build() {
+ return obj;
+ }
+
+ @Override
+ public T random() {
+ return build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/ObjAttributeBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/ObjAttributeBuilder.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/ObjAttributeBuilder.java
new file mode 100644
index 0000000..a183c34
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/ObjAttributeBuilder.java
@@ -0,0 +1,67 @@
+/*****************************************************************
+ * 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.dbsync.merge.builders;
+
+import org.apache.cayenne.map.ObjAttribute;
+
+/**
+ * @since 4.0.
+ */
+public class ObjAttributeBuilder extends DefaultBuilder<ObjAttribute> {
+
+ public ObjAttributeBuilder() {
+ super(new ObjAttribute());
+ }
+
+ public ObjAttributeBuilder name() {
+ return name(getRandomJavaName());
+ }
+
+ public ObjAttributeBuilder name(String name) {
+ obj.setName(name);
+
+ return this;
+ }
+
+ public ObjAttributeBuilder type(Class type) {
+ obj.setType(type.getCanonicalName());
+
+ return this;
+ }
+
+ public ObjAttributeBuilder dbPath(String path) {
+ obj.setDbAttributePath(path);
+
+ return this;
+ }
+
+ @Override
+ public ObjAttribute build() {
+ if (obj.getName() == null) {
+ name();
+ }
+
+ return obj;
+ }
+
+ @Override
+ public ObjAttribute random() {
+ return build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/ObjEntityBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/ObjEntityBuilder.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/ObjEntityBuilder.java
new file mode 100644
index 0000000..f2f701c
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/ObjEntityBuilder.java
@@ -0,0 +1,98 @@
+/*****************************************************************
+ * 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.dbsync.merge.builders;
+
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * @since 4.0.
+ */
+public class ObjEntityBuilder extends DefaultBuilder<ObjEntity> {
+
+ public ObjEntityBuilder() {
+ super(new ObjEntity());
+ }
+
+ public ObjEntityBuilder name() {
+ return name(getRandomJavaName());
+ }
+
+ public ObjEntityBuilder name(String name) {
+ obj.setName(name);
+
+ return this;
+ }
+
+ public ObjEntityBuilder attributes(ObjAttribute... attributes) {
+ for (ObjAttribute attribute : attributes) {
+ obj.addAttribute(attribute);
+ }
+
+ return this;
+ }
+
+ public ObjEntityBuilder attributes(ObjAttributeBuilder ... attributes) {
+ for (ObjAttributeBuilder attribute : attributes) {
+ obj.addAttribute(attribute.build());
+ }
+
+ return this;
+ }
+
+ public ObjEntityBuilder attributes(int numberUpTo) {
+ for (int i = 0; i < numberUpTo; i++) {
+ obj.addAttribute(new ObjAttributeBuilder().random());
+ }
+
+ return this;
+ }
+
+
+ @Override
+ public ObjEntity build() {
+ if (obj.getName() == null) {
+ obj.setName(StringUtils.capitalize(getRandomJavaName()));
+ }
+
+ return obj;
+ }
+
+ @Override
+ public ObjEntity random() {
+ if (dataFactory.chance(99)) {
+ attributes(dataFactory.getNumberUpTo(20));
+ }
+
+ return build();
+ }
+
+ public ObjEntityBuilder clazz(String s) {
+ obj.setClassName(s);
+
+ return this;
+ }
+
+ public ObjEntityBuilder dbEntity(String table) {
+ obj.setDbEntityName(table);
+
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/ObjectMother.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/ObjectMother.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/ObjectMother.java
new file mode 100644
index 0000000..0097fe1
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/builders/ObjectMother.java
@@ -0,0 +1,70 @@
+/*****************************************************************
+ * 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.dbsync.merge.builders;
+
+import org.apache.cayenne.map.DataMap;
+
+/**
+ * Factory for test data see pattern definition:
+ * http://martinfowler.com/bliki/ObjectMother.html
+ *
+ * @since 4.0.
+ */
+public class ObjectMother {
+
+ public static DataMapBuilder dataMap() {
+ return new DataMapBuilder();
+ }
+
+ public static DataMapBuilder dataMap(DataMap dataMap) {
+ return new DataMapBuilder(dataMap);
+ }
+
+ public static DbEntityBuilder dbEntity() {
+ return new DbEntityBuilder();
+ }
+
+ public static DbEntityBuilder dbEntity(String name) {
+ return new DbEntityBuilder().name(name);
+ }
+
+ public static ObjEntityBuilder objEntity() {
+ return new ObjEntityBuilder();
+ }
+
+ public static ObjEntityBuilder objEntity(String packageName, String className, String table) {
+ return new ObjEntityBuilder()
+ .name(className)
+ .clazz(packageName + "." + className)
+ .dbEntity(table);
+ }
+
+ public static ObjAttributeBuilder objAttr(String name) {
+ return new ObjAttributeBuilder().name(name);
+ }
+
+ public static DbAttributeBuilder dbAttr(String name) {
+ return dbAttr().name(name);
+ }
+
+ public static DbAttributeBuilder dbAttr() {
+ return new DbAttributeBuilder();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/DbLoaderIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/DbLoaderIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/DbLoaderIT.java
new file mode 100644
index 0000000..a902754
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/DbLoaderIT.java
@@ -0,0 +1,430 @@
+/*****************************************************************
+ * 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.dbsync.reverse;
+
+import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig;
+import org.apache.cayenne.dbsync.reverse.filters.PatternFilter;
+import org.apache.cayenne.dbsync.reverse.filters.TableFilter;
+import org.apache.cayenne.configuration.server.ServerRuntime;
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.TypesMapping;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.map.*;
+import org.apache.cayenne.unit.UnitDbAdapter;
+import org.apache.cayenne.unit.di.server.CayenneProjects;
+import org.apache.cayenne.unit.di.server.ServerCase;
+import org.apache.cayenne.unit.di.server.ServerCaseDataSourceFactory;
+import org.apache.cayenne.unit.di.server.UseServerRuntime;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.sql.Types;
+import java.util.Collection;
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
+public class DbLoaderIT extends ServerCase {
+
+ public static final DbLoaderConfiguration CONFIG = new DbLoaderConfiguration();
+ @Inject
+ private ServerRuntime runtime;
+
+ @Inject
+ private DbAdapter adapter;
+
+ @Inject
+ private ServerCaseDataSourceFactory dataSourceFactory;
+
+ @Inject
+ private UnitDbAdapter accessStackAdapter;
+
+ private DbLoader loader;
+
+ @Before
+ public void setUp() throws Exception {
+ loader = new DbLoader(dataSourceFactory.getSharedDataSource().getConnection(), adapter, null);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ loader.getConnection().close();
+ }
+
+ @Test
+ public void testGetTableTypes() throws Exception {
+
+ List<?> tableTypes = loader.getTableTypes();
+
+ assertNotNull(tableTypes);
+
+ String tableLabel = adapter.tableTypeForTable();
+ if (tableLabel != null) {
+ assertTrue("Missing type for table '" + tableLabel + "' - " + tableTypes, tableTypes.contains(tableLabel));
+ }
+
+ String viewLabel = adapter.tableTypeForView();
+ if (viewLabel != null) {
+ assertTrue("Missing type for view '" + viewLabel + "' - " + tableTypes, tableTypes.contains(viewLabel));
+ }
+ }
+
+ @Test
+ public void testGetTables() throws Exception {
+
+ String tableLabel = adapter.tableTypeForTable();
+
+ List<DetectedDbEntity> tables = loader.createTableLoader(null, null, TableFilter.everything())
+ .getDbEntities(TableFilter.everything(), new String[]{tableLabel});
+
+ assertNotNull(tables);
+
+ boolean foundArtist = false;
+
+ for (DetectedDbEntity table : tables) {
+ if ("ARTIST".equalsIgnoreCase(table.getName())) {
+ foundArtist = true;
+ break;
+ }
+ }
+
+ assertTrue("'ARTIST' is missing from the table list: " + tables, foundArtist);
+ }
+
+ @Test
+ public void testGetTablesWithWrongCatalog() throws Exception {
+
+ DbLoaderConfiguration config = new DbLoaderConfiguration();
+ config.setFiltersConfig(
+ FiltersConfig.create("WRONG", null, TableFilter.everything(), PatternFilter.INCLUDE_NOTHING));
+ List<DetectedDbEntity> tables = loader
+ .createTableLoader("WRONG", null, TableFilter.everything())
+ .getDbEntities(TableFilter.everything(), new String[]{adapter.tableTypeForTable()});
+
+ assertNotNull(tables);
+ assertTrue(tables.isEmpty());
+ }
+
+ @Test
+ public void testGetTablesWithWrongSchema() throws Exception {
+
+ DbLoaderConfiguration config = new DbLoaderConfiguration();
+ config.setFiltersConfig(
+ FiltersConfig.create(null, "WRONG", TableFilter.everything(), PatternFilter.INCLUDE_NOTHING));
+ List<DetectedDbEntity> tables = loader
+ .createTableLoader(null, "WRONG", TableFilter.everything())
+ .getDbEntities(TableFilter.everything(), new String[]{adapter.tableTypeForTable()});
+
+ assertNotNull(tables);
+ assertTrue(tables.isEmpty());
+ }
+
+ @Test
+ public void testLoadWithMeaningfulPK() throws Exception {
+
+ DataMap map = new DataMap();
+ String[] tableLabel = { adapter.tableTypeForTable() };
+
+ loader.setCreatingMeaningfulPK(true);
+
+ List<DbEntity> entities = loader
+ .createTableLoader(null, null, TableFilter.everything())
+ .loadDbEntities(map, CONFIG, tableLabel);
+
+ loader.loadObjEntities(map, CONFIG, entities);
+
+ ObjEntity artist = map.getObjEntity("Artist");
+ assertNotNull(artist);
+
+ ObjAttribute id = artist.getAttribute("artistId");
+ assertNotNull(id);
+ }
+
+ /**
+ * DataMap loading is in one big test method, since breaking it in
+ * individual tests would require multiple reads of metatdata which is
+ * extremely slow on some RDBMS (Sybase).
+ */
+ @Test
+ public void testLoad() throws Exception {
+
+ boolean supportsUnique = runtime.getDataDomain().getDataNodes().iterator().next().getAdapter()
+ .supportsUniqueConstraints();
+ boolean supportsLobs = accessStackAdapter.supportsLobs();
+ boolean supportsFK = accessStackAdapter.supportsFKConstraints();
+
+ DataMap map = new DataMap();
+ map.setDefaultPackage("foo.x");
+
+ String tableLabel = adapter.tableTypeForTable();
+
+ // *** TESTING THIS ***
+ List<DbEntity> entities = loader
+ .createTableLoader(null, null, TableFilter.everything())
+ .loadDbEntities(map, CONFIG, new String[]{adapter.tableTypeForTable()});
+
+
+ assertDbEntities(map);
+
+ if (supportsLobs) {
+ assertLobDbEntities(map);
+ }
+
+ // *** TESTING THIS ***
+ loader.loadDbRelationships(CONFIG, null, null, entities);
+
+ if (supportsFK) {
+ Collection<DbRelationship> rels = getDbEntity(map, "ARTIST").getRelationships();
+ assertNotNull(rels);
+ assertTrue(!rels.isEmpty());
+
+ // test one-to-one
+ rels = getDbEntity(map, "PAINTING").getRelationships();
+ assertNotNull(rels);
+
+ // find relationship to PAINTING_INFO
+ DbRelationship oneToOne = null;
+ for (DbRelationship rel : rels) {
+ if ("PAINTING_INFO".equalsIgnoreCase(rel.getTargetEntityName())) {
+ oneToOne = rel;
+ break;
+ }
+ }
+
+ assertNotNull("No relationship to PAINTING_INFO", oneToOne);
+ assertFalse("Relationship to PAINTING_INFO must be to-one", oneToOne.isToMany());
+ assertTrue("Relationship to PAINTING_INFO must be to-one", oneToOne.isToDependentPK());
+
+ // test UNIQUE only if FK is supported...
+ if (supportsUnique) {
+ assertUniqueConstraintsInRelationships(map);
+ }
+ }
+
+ // *** TESTING THIS ***
+ loader.setCreatingMeaningfulPK(false);
+ loader.loadObjEntities(map, CONFIG, entities);
+
+ assertObjEntities(map);
+
+ // now when the map is loaded, test
+ // various things
+ // selectively check how different types were processed
+ if (accessStackAdapter.supportsColumnTypeReengineering()) {
+ checkTypes(map);
+ }
+ }
+
+ private void assertUniqueConstraintsInRelationships(DataMap map) {
+ // unfortunately JDBC metadata doesn't provide info for UNIQUE
+ // constraints....
+ // cant reengineer them...
+
+ // find rel to TO_ONEFK1
+ /*
+ * Iterator it = getDbEntity(map,
+ * "TO_ONEFK2").getRelationships().iterator(); DbRelationship rel =
+ * (DbRelationship) it.next(); assertEquals("TO_ONEFK1",
+ * rel.getTargetEntityName());
+ * assertFalse("UNIQUE constraint was ignored...", rel.isToMany());
+ */
+ }
+
+ private void assertDbEntities(DataMap map) {
+ DbEntity dae = getDbEntity(map, "ARTIST");
+ assertNotNull("Null 'ARTIST' entity, other DbEntities: " + map.getDbEntityMap(), dae);
+ assertEquals("ARTIST", dae.getName().toUpperCase());
+
+ DbAttribute a = getDbAttribute(dae, "ARTIST_ID");
+ assertNotNull(a);
+ assertTrue(a.isPrimaryKey());
+ assertFalse(a.isGenerated());
+
+ if (adapter.supportsGeneratedKeys()) {
+ DbEntity bag = getDbEntity(map, "GENERATED_COLUMN_TEST");
+ DbAttribute id = getDbAttribute(bag, "GENERATED_COLUMN");
+ assertTrue(id.isPrimaryKey());
+ assertTrue(id.isGenerated());
+ }
+ }
+
+ private void assertObjEntities(DataMap map) {
+
+ boolean supportsLobs = accessStackAdapter.supportsLobs();
+ boolean supportsFK = accessStackAdapter.supportsFKConstraints();
+
+ ObjEntity ae = map.getObjEntity("Artist");
+ assertNotNull(ae);
+ assertEquals("Artist", ae.getName());
+
+ // assert primary key is not an attribute
+ assertNull(ae.getAttribute("artistId"));
+
+ if (supportsLobs) {
+ assertLobObjEntities(map);
+ }
+
+ if (supportsFK) {
+ Collection<?> rels1 = ae.getRelationships();
+ assertNotNull(rels1);
+ assertTrue(rels1.size() > 0);
+ }
+
+ assertEquals("foo.x.Artist", ae.getClassName());
+ }
+
+ private void assertLobDbEntities(DataMap map) {
+ DbEntity blobEnt = getDbEntity(map, "BLOB_TEST");
+ assertNotNull(blobEnt);
+ DbAttribute blobAttr = getDbAttribute(blobEnt, "BLOB_COL");
+ assertNotNull(blobAttr);
+ assertTrue(msgForTypeMismatch(Types.BLOB, blobAttr), Types.BLOB == blobAttr.getType()
+ || Types.LONGVARBINARY == blobAttr.getType());
+
+ DbEntity clobEnt = getDbEntity(map, "CLOB_TEST");
+ assertNotNull(clobEnt);
+ DbAttribute clobAttr = getDbAttribute(clobEnt, "CLOB_COL");
+ assertNotNull(clobAttr);
+ assertTrue(msgForTypeMismatch(Types.CLOB, clobAttr), Types.CLOB == clobAttr.getType()
+ || Types.LONGVARCHAR == clobAttr.getType());
+
+/*
+ DbEntity nclobEnt = getDbEntity(map, "NCLOB_TEST");
+ assertNotNull(nclobEnt);
+ DbAttribute nclobAttr = getDbAttribute(nclobEnt, "NCLOB_COL");
+ assertNotNull(nclobAttr);
+ assertTrue(msgForTypeMismatch(Types.NCLOB, nclobAttr), Types.NCLOB == nclobAttr.getType()
+ || Types.LONGVARCHAR == nclobAttr.getType());
+*/
+ }
+
+ private void assertLobObjEntities(DataMap map) {
+ ObjEntity blobEnt = map.getObjEntity("BlobTest");
+ assertNotNull(blobEnt);
+ // BLOBs should be mapped as byte[]
+ ObjAttribute blobAttr = blobEnt.getAttribute("blobCol");
+ assertNotNull("BlobTest.blobCol failed to doLoad", blobAttr);
+ assertEquals("byte[]", blobAttr.getType());
+
+
+ ObjEntity clobEnt = map.getObjEntity("ClobTest");
+ assertNotNull(clobEnt);
+ // CLOBs should be mapped as Strings by default
+ ObjAttribute clobAttr = clobEnt.getAttribute("clobCol");
+ assertNotNull(clobAttr);
+ assertEquals(String.class.getName(), clobAttr.getType());
+
+
+ ObjEntity nclobEnt = map.getObjEntity("NclobTest");
+ assertNotNull(nclobEnt);
+ // CLOBs should be mapped as Strings by default
+ ObjAttribute nclobAttr = nclobEnt.getAttribute("nclobCol");
+ assertNotNull(nclobAttr);
+ assertEquals(String.class.getName(), nclobAttr.getType());
+ }
+
+ private DbEntity getDbEntity(DataMap map, String name) {
+ DbEntity de = map.getDbEntity(name);
+ // sometimes table names get converted to lowercase
+ if (de == null) {
+ de = map.getDbEntity(name.toLowerCase());
+ }
+
+ return de;
+ }
+
+ private DbAttribute getDbAttribute(DbEntity ent, String name) {
+ DbAttribute da = ent.getAttribute(name);
+ // sometimes table names get converted to lowercase
+ if (da == null) {
+ da = ent.getAttribute(name.toLowerCase());
+ }
+
+ return da;
+ }
+
+ private DataMap originalMap() {
+ return runtime.getDataDomain().getDataNodes().iterator().next().getDataMaps().iterator().next();
+ }
+
+ /**
+ * Selectively check how different types were processed.
+ */
+ public void checkTypes(DataMap map) {
+ DbEntity dbe = getDbEntity(map, "PAINTING");
+ DbEntity floatTest = getDbEntity(map, "FLOAT_TEST");
+ DbEntity smallintTest = getDbEntity(map, "SMALLINT_TEST");
+ DbAttribute integerAttr = getDbAttribute(dbe, "PAINTING_ID");
+ DbAttribute decimalAttr = getDbAttribute(dbe, "ESTIMATED_PRICE");
+ DbAttribute varcharAttr = getDbAttribute(dbe, "PAINTING_TITLE");
+ DbAttribute floatAttr = getDbAttribute(floatTest, "FLOAT_COL");
+ DbAttribute smallintAttr = getDbAttribute(smallintTest, "SMALLINT_COL");
+
+ // check decimal
+ assertTrue(msgForTypeMismatch(Types.DECIMAL, decimalAttr), Types.DECIMAL == decimalAttr.getType()
+ || Types.NUMERIC == decimalAttr.getType());
+ assertEquals(2, decimalAttr.getScale());
+
+ // check varchar
+ assertEquals(msgForTypeMismatch(Types.VARCHAR, varcharAttr), Types.VARCHAR, varcharAttr.getType());
+ assertEquals(255, varcharAttr.getMaxLength());
+ // check integer
+ assertEquals(msgForTypeMismatch(Types.INTEGER, integerAttr), Types.INTEGER, integerAttr.getType());
+ // check float
+ assertTrue(msgForTypeMismatch(Types.FLOAT, floatAttr), Types.FLOAT == floatAttr.getType()
+ || Types.DOUBLE == floatAttr.getType() || Types.REAL == floatAttr.getType());
+
+ // check smallint
+ assertTrue(msgForTypeMismatch(Types.SMALLINT, smallintAttr), Types.SMALLINT == smallintAttr.getType()
+ || Types.INTEGER == smallintAttr.getType());
+ }
+
+ public void checkAllDBEntities(DataMap map) {
+
+ for (DbEntity origEnt : originalMap().getDbEntities()) {
+ DbEntity newEnt = map.getDbEntity(origEnt.getName());
+ for (DbAttribute origAttr : origEnt.getAttributes()) {
+ DbAttribute newAttr = newEnt.getAttribute(origAttr.getName());
+ assertNotNull("No matching DbAttribute for '" + origAttr.getName(), newAttr);
+ assertEquals(msgForTypeMismatch(origAttr, newAttr), origAttr.getType(), newAttr.getType());
+ // length and precision doesn't have to be the same
+ // it must be greater or equal
+ assertTrue(origAttr.getMaxLength() <= newAttr.getMaxLength());
+ assertTrue(origAttr.getScale() <= newAttr.getScale());
+ }
+ }
+ }
+
+ private static String msgForTypeMismatch(DbAttribute origAttr, DbAttribute newAttr) {
+ return msgForTypeMismatch(origAttr.getType(), newAttr);
+ }
+
+ private static String msgForTypeMismatch(int origType, DbAttribute newAttr) {
+ String nt = TypesMapping.getSqlNameByType(newAttr.getType());
+ String ot = TypesMapping.getSqlNameByType(origType);
+ return attrMismatch(newAttr.getName(), "expected type: <" + ot + ">, but was <" + nt + ">");
+ }
+
+ private static String attrMismatch(String attrName, String msg) {
+ return "[Error loading attribute '" + attrName + "': " + msg + "]";
+ }
+}
[03/15] cayenne git commit: CAY-2116 Split schema synchronization
code in a separate module
Posted by aa...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/dbimport/FiltersConfigBuilderTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/dbimport/FiltersConfigBuilderTest.java b/cayenne-server/src/test/java/org/apache/cayenne/dbimport/FiltersConfigBuilderTest.java
deleted file mode 100644
index 9a94618..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/dbimport/FiltersConfigBuilderTest.java
+++ /dev/null
@@ -1,382 +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.dbimport;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class FiltersConfigBuilderTest {
-
- @Test
- public void testCompact_01() {
- ReverseEngineering engineering = new ReverseEngineering();
- engineering.addIncludeTable(new IncludeTable("table1"));
- engineering.addIncludeTable(new IncludeTable("table2"));
- engineering.addIncludeTable(new IncludeTable("table3"));
-
- engineering.addIncludeColumn(new IncludeColumn("includeColumn"));
-
- FiltersConfigBuilder builder = new FiltersConfigBuilder(engineering);
- builder.compact();
- assertEquals(
- "ReverseEngineering: \n" +
- " Catalog: null\n" +
- " Schema: null\n" +
- " IncludeTable: table1\n" +
- " IncludeColumn: includeColumn\n" +
- " IncludeTable: table2\n" +
- " IncludeColumn: includeColumn\n" +
- " IncludeTable: table3\n" +
- " IncludeColumn: includeColumn\n", engineering.toString());
- }
-
- @Test
- public void testCompact_02() {
- ReverseEngineering engineering = new ReverseEngineering();
- engineering.addCatalog(new Catalog("catalogName"));
- engineering.addSchema(new Schema("schemaName01"));
- engineering.addSchema(new Schema("schemaName02"));
-
- engineering.addIncludeTable(new IncludeTable("table1"));
- engineering.addExcludeTable(new ExcludeTable("table2"));
-
- engineering.addIncludeColumn(new IncludeColumn("includeColumn"));
-
- FiltersConfigBuilder builder = new FiltersConfigBuilder(engineering);
- builder.compact();
- assertEquals(
- "ReverseEngineering: \n" +
- " Catalog: catalogName\n" +
- " Schema: schemaName01\n" +
- " IncludeTable: table1\n" +
- " IncludeColumn: includeColumn\n" +
- " ExcludeTable: table2\n" +
- " Schema: schemaName02\n" +
- " IncludeTable: table1\n" +
- " IncludeColumn: includeColumn\n" +
- " ExcludeTable: table2\n", engineering.toString());
- }
-
- @Test
- public void testCompact_03() {
- ReverseEngineering engineering = new ReverseEngineering();
- engineering.addCatalog(new Catalog("APP1"));
- engineering.addCatalog(new Catalog("APP2"));
-
- engineering.addExcludeTable(new ExcludeTable("SYS_.*"));
- engineering.addExcludeColumn(new ExcludeColumn("calculated_.*"));
-
- FiltersConfigBuilder builder = new FiltersConfigBuilder(engineering);
- builder.compact();
- assertEquals(
- "ReverseEngineering: \n" +
- " Catalog: APP1\n" +
- " Schema: null\n" +
- " IncludeTable: null\n" +
- " ExcludeColumn: calculated_.*\n" +
- " ExcludeTable: SYS_.*\n" +
- " Catalog: APP2\n" +
- " Schema: null\n" +
- " IncludeTable: null\n" +
- " ExcludeColumn: calculated_.*\n" +
- " ExcludeTable: SYS_.*\n", engineering.toString());
- }
-
- @Test
- public void testCompact_04() {
- ReverseEngineering engineering = new ReverseEngineering();
- engineering.addSchema(new Schema("s"));
-
- FiltersConfigBuilder builder = new FiltersConfigBuilder(engineering);
- builder.compact();
- assertEquals(
- "ReverseEngineering: \n" +
- " Catalog: null\n" +
- " Schema: s\n" +
- " IncludeTable: null\n", engineering.toString());
- }
-
- @Test
- public void testCompact_full() {
- ReverseEngineering engineering = new ReverseEngineering();
- Catalog cat01 = new Catalog("cat_01");
-
- Schema sch01 = new Schema("sch_01");
-
- sch01.addIncludeTable(includeTable("t1", "c11", "c12"));
- sch01.addExcludeTable(new ExcludeTable("t2"));
- sch01.addIncludeProcedure(new IncludeProcedure("p1"));
- sch01.addExcludeProcedure(new ExcludeProcedure("p2"));
- sch01.addIncludeColumn(new IncludeColumn("c_x1"));
- sch01.addExcludeColumn(new ExcludeColumn("c_x2"));
-
- cat01.addSchema(sch01);
-
- cat01.addIncludeTable(includeTable("t3", "c31", "c32"));
- cat01.addExcludeTable(new ExcludeTable("t4"));
- cat01.addIncludeProcedure(new IncludeProcedure("p3"));
- cat01.addExcludeProcedure(new ExcludeProcedure("p4"));
- cat01.addIncludeColumn(new IncludeColumn("c_xx1"));
- cat01.addExcludeColumn(new ExcludeColumn("c_xx2"));
-
- engineering.addCatalog(cat01);
-
- Schema sch02 = new Schema("sch_02");
-
- sch02.addIncludeTable(includeTable("t5", "c51", "c52"));
- sch02.addExcludeTable(new ExcludeTable("t6"));
- sch02.addIncludeProcedure(new IncludeProcedure("p5"));
- sch02.addExcludeProcedure(new ExcludeProcedure("p6"));
- sch02.addIncludeColumn(new IncludeColumn("c2_x1"));
- sch02.addExcludeColumn(new ExcludeColumn("c2_x2"));
-
- engineering.addSchema(sch02);
-
- engineering.addIncludeTable(includeTable("t7", "c71", "c72"));
- engineering.addExcludeTable(new ExcludeTable("t8"));
- engineering.addIncludeProcedure(new IncludeProcedure("p7"));
- engineering.addExcludeProcedure(new ExcludeProcedure("p8"));
- engineering.addIncludeColumn(new IncludeColumn("c_xxx1"));
- engineering.addExcludeColumn(new ExcludeColumn("c_xxx2"));
-
- FiltersConfigBuilder builder = new FiltersConfigBuilder(engineering);
- assertEquals("Original ReverseEngineering should be",
- "ReverseEngineering: \n" +
- " Catalog: cat_01\n" +
- " Schema: sch_01\n" +
- " IncludeTable: t1\n" +
- " IncludeColumn: c11\n" +
- " ExcludeColumn: c12\n" +
- " ExcludeTable: t2\n" +
- " IncludeColumn: c_x1\n" +
- " ExcludeColumn: c_x2\n" +
- " IncludeProcedure: p1\n" +
- " ExcludeProcedure: p2\n" +
- " IncludeTable: t3\n" +
- " IncludeColumn: c31\n" +
- " ExcludeColumn: c32\n" +
- " ExcludeTable: t4\n" +
- " IncludeColumn: c_xx1\n" +
- " ExcludeColumn: c_xx2\n" +
- " IncludeProcedure: p3\n" +
- " ExcludeProcedure: p4\n" +
- " Schema: sch_02\n" +
- " IncludeTable: t5\n" +
- " IncludeColumn: c51\n" +
- " ExcludeColumn: c52\n" +
- " ExcludeTable: t6\n" +
- " IncludeColumn: c2_x1\n" +
- " ExcludeColumn: c2_x2\n" +
- " IncludeProcedure: p5\n" +
- " ExcludeProcedure: p6\n" +
- " IncludeTable: t7\n" +
- " IncludeColumn: c71\n" +
- " ExcludeColumn: c72\n" +
- " ExcludeTable: t8\n" +
- " IncludeColumn: c_xxx1\n" +
- " ExcludeColumn: c_xxx2\n" +
- " IncludeProcedure: p7\n" +
- " ExcludeProcedure: p8\n", engineering.toString());
-
-
- builder.compact();
- assertEquals(
- "ReverseEngineering: \n" +
- " Catalog: cat_01\n" +
- " Schema: sch_01\n" +
- " IncludeTable: t1\n" +
- " IncludeColumn: c11\n" +
- " IncludeColumn: c_xxx1\n" +
- " IncludeColumn: c_xx1\n" +
- " IncludeColumn: c_x1\n" +
- " ExcludeColumn: c12\n" +
- " ExcludeColumn: c_xxx2\n" +
- " ExcludeColumn: c_xx2\n" +
- " ExcludeColumn: c_x2\n" +
- " IncludeTable: t7\n" +
- " IncludeColumn: c71\n" +
- " IncludeColumn: c_xxx1\n" +
- " ExcludeColumn: c72\n" +
- " ExcludeColumn: c_xxx2\n" +
- " IncludeTable: t3\n" +
- " IncludeColumn: c31\n" +
- " IncludeColumn: c_xxx1\n" +
- " IncludeColumn: c_xx1\n" +
- " ExcludeColumn: c32\n" +
- " ExcludeColumn: c_xxx2\n" +
- " ExcludeColumn: c_xx2\n" +
- " ExcludeTable: t2\n" +
- " ExcludeTable: t8\n" +
- " ExcludeTable: t4\n" +
- " IncludeProcedure: p1\n" +
- " IncludeProcedure: p7\n" +
- " IncludeProcedure: p3\n" +
- " ExcludeProcedure: p2\n" +
- " ExcludeProcedure: p8\n" +
- " ExcludeProcedure: p4\n" +
- " Schema: sch_02\n" +
- " IncludeTable: t5\n" +
- " IncludeColumn: c51\n" +
- " IncludeColumn: c_xxx1\n" +
- " IncludeColumn: c2_x1\n" +
- " ExcludeColumn: c52\n" +
- " ExcludeColumn: c_xxx2\n" +
- " ExcludeColumn: c2_x2\n" +
- " IncludeTable: t7\n" +
- " IncludeColumn: c71\n" +
- " IncludeColumn: c_xxx1\n" +
- " ExcludeColumn: c72\n" +
- " ExcludeColumn: c_xxx2\n" +
- " ExcludeTable: t6\n" +
- " ExcludeTable: t8\n" +
- " IncludeProcedure: p5\n" +
- " IncludeProcedure: p7\n" +
- " ExcludeProcedure: p6\n" +
- " ExcludeProcedure: p8\n", engineering.toString());
- }
-
- protected IncludeTable includeTable(String name, String incCol, String excCol) {
- IncludeTable incTable01 = new IncludeTable(name);
- incTable01.addIncludeColumn(new IncludeColumn(incCol));
- incTable01.addExcludeColumn(new ExcludeColumn(excCol));
- return incTable01;
- }
-
- /*@Test
- public void testEmptyDbEntitiesFilters() throws Exception {
- ReverseEngineering engineering = new ReverseEngineering();
- FiltersConfig executions = new FiltersConfigBuilder(engineering).filtersConfig();
-
- assertEquals("If nothing was configured we have to import everything. Filter %/%/% true/true/true",
- new FiltersConfig(eFilters(path(), TRUE, TRUE, NULL)),
- executions);
- }
-
- @Test
- public void testOnlyOneCatalogDbEntitiesFilters() throws Exception {
- ReverseEngineering engineering = new ReverseEngineering();
- engineering.addCatalog(new Catalog("catalog_01"));
- FiltersConfig executions = new FiltersConfigBuilder(engineering).filtersConfig();
-
-
- assertEquals(new FiltersConfig(eFilters(path("catalog_01", null), TRUE, TRUE, NULL)),
- executions);
- }
-
- @Test
- public void testCatalogDbEntitiesFilters() throws Exception {
- ReverseEngineering engineering = new ReverseEngineering();
- engineering.addCatalog(new Catalog("catalog_01"));
- engineering.addCatalog(new Catalog("catalog_02").schema(new Schema("schema_01")));
- engineering.addCatalog(new Catalog("catalog_02").schema(new Schema("schema_02")));
- engineering.addCatalog(new Catalog("catalog_02").schema(new Schema("schema_03")));
- engineering.addCatalog(new Catalog("catalog_03").schema(new Schema("schema_01")));
- engineering.addCatalog(new Catalog("catalog_03").schema(new Schema("schema_01")));
- engineering.addCatalog(new Catalog("catalog_03").schema(new Schema("schema_01")));
- engineering.addCatalog(new Catalog("catalog_03").schema(new Schema("schema_01")));
- FiltersConfig executions = new FiltersConfigBuilder(engineering).filtersConfig();
-
-
- assertEquals(new FiltersConfig(
- eFilters(path("catalog_01", null), TRUE, TRUE, NULL),
- eFilters(path("catalog_02", "schema_01"), TRUE, TRUE, NULL),
- eFilters(path("catalog_02", "schema_02"), TRUE, TRUE, NULL),
- eFilters(path("catalog_02", "schema_03"), TRUE, TRUE, NULL),
- eFilters(path("catalog_03", "schema_01"), TRUE, TRUE, NULL)
- ),
- executions);
- }
-
- @Test
- public void testSchemaDbEntitiesFilters() throws Exception {
- ReverseEngineering engineering = new ReverseEngineering();
- engineering.addSchema(new Schema("schema_01"));
- engineering.addSchema(new Schema("schema_02"));
- engineering.addSchema(new Schema("schema_03"));
- FiltersConfig executions = new FiltersConfigBuilder(engineering).filtersConfig();
-
-
- assertEquals(new FiltersConfig(
- eFilters(path(null, "schema_01"), TRUE, TRUE, NULL),
- eFilters(path(null, "schema_02"), TRUE, TRUE, NULL),
- eFilters(path(null, "schema_03"), TRUE, TRUE, NULL)
- ),
- executions);
- }
-
- @Test
- public void testFiltersDbEntitiesFilters() throws Exception {
- ReverseEngineering engineering = new ReverseEngineering();
- engineering.addIncludeTable(new IncludeTable("IncludeTable"));
- engineering.addIncludeColumn(new IncludeColumn("IncludeColumn"));
- engineering.addIncludeProcedure(new IncludeProcedure("IncludeProcedure"));
- engineering.addExcludeTable(new ExcludeTable("ExcludeTable"));
- engineering.addExcludeColumn(new ExcludeColumn("ExcludeColumn"));
- engineering.addExcludeProcedure(new ExcludeProcedure("ExcludeProcedure"));
-
- FiltersConfig executions = new FiltersConfigBuilder(engineering).filtersConfig();
-
- assertEquals(new FiltersConfig(
- eFilters(path(),
- list(include("IncludeTable"), exclude("ExcludeTable")),
- list(include("IncludeColumn"), exclude("ExcludeColumn")),
- list(include("IncludeProcedure"), exclude("ExcludeProcedure"))),
- eFilters(path(null, null, "IncludeTable"), NULL, TRUE, NULL)
- ),
- executions);
- }
-
- @Test
- public void testComplexConfiguration() throws Exception {
- IncludeTable table = new IncludeTable("table");
- table.addIncludeColumn(new IncludeColumn("column"));
-
- Schema schema = new Schema("schema");
- schema.addIncludeTable(table);
-
- Catalog catalog = new Catalog("catalog");
- catalog.addSchema(schema);
-
- ReverseEngineering engineering = new ReverseEngineering();
- engineering.addCatalog(catalog);
-
- FiltersConfig executions = new FiltersConfigBuilder(engineering).filtersConfig();
-
- assertEquals(new FiltersConfig(
- eFilters(path("catalog", "schema"), include("table"), NULL, NULL),
- eFilters(path("catalog", "schema", "table"), NULL, include("column"), NULL)
- ),
- executions);
- }
-
- @Test
- public void testAddNull() throws Exception {
- FiltersConfigBuilder builder = new FiltersConfigBuilder(new ReverseEngineering());
- DbPath path = new DbPath();
- builder.add(new EntityFilters(path, NULL, NULL, NULL));
- builder.add(new EntityFilters(path, NULL, NULL, NULL));
- builder.add(new EntityFilters(path, NULL, NULL, NULL));
- builder.add(new EntityFilters(path, NULL, NULL, NULL));
-
- EntityFilters filter = builder.filtersConfig().filter(path);
- assertFalse(filter.isEmpty());
- }*/
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/AddColumnToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/AddColumnToModelIT.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/AddColumnToModelIT.java
deleted file mode 100644
index db60769..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/AddColumnToModelIT.java
+++ /dev/null
@@ -1,98 +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.merge;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.sql.Types;
-import java.util.List;
-
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.ObjAttribute;
-import org.apache.cayenne.map.ObjEntity;
-import org.junit.Test;
-
-public class AddColumnToModelIT extends MergeCase {
-
- @Test
- public void testAddColumn() throws Exception {
- dropTableIfPresent("NEW_TABLE");
- assertTokensAndExecute(0, 0);
-
- DbEntity dbEntity = new DbEntity("NEW_TABLE");
-
- DbAttribute column1 = new DbAttribute("ID", Types.INTEGER, dbEntity);
- column1.setMandatory(true);
- column1.setPrimaryKey(true);
- dbEntity.addAttribute(column1);
-
- DbAttribute column2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity);
- column2.setMaxLength(10);
- column2.setMandatory(false);
- dbEntity.addAttribute(column2);
-
- map.addDbEntity(dbEntity);
-
- assertTokensAndExecute(1, 0);
- assertTokensAndExecute(0, 0);
-
- ObjEntity objEntity = new ObjEntity("NewTable");
- objEntity.setDbEntity(dbEntity);
- ObjAttribute oatr1 = new ObjAttribute("name");
- oatr1.setDbAttributePath(column2.getName());
- oatr1.setType("java.lang.String");
- objEntity.addAttribute(oatr1);
- map.addObjEntity(objEntity);
-
- // remove name column
- objEntity.removeAttribute(oatr1.getName());
- dbEntity.removeAttribute(column2.getName());
- assertNull(objEntity.getAttribute(oatr1.getName()));
- assertEquals(0, objEntity.getAttributes().size());
- assertNull(dbEntity.getAttribute(column2.getName()));
-
- List<MergerToken> tokens = createMergeTokens();
- assertEquals(1, tokens.size());
- MergerToken token = tokens.get(0);
- if (token.getDirection().isToDb()) {
- token = token.createReverse(mergerFactory());
- }
- assertTrue(token instanceof AddColumnToModel);
- execute(token);
- assertEquals(1, objEntity.getAttributes().size());
- assertEquals("java.lang.String", objEntity.getAttributes().iterator()
- .next().getType());
-
- // clear up
- map.removeObjEntity(objEntity.getName(), true);
- map.removeDbEntity(dbEntity.getName(), true);
- resolver.refreshMappingCache();
- assertNull(map.getObjEntity(objEntity.getName()));
- assertNull(map.getDbEntity(dbEntity.getName()));
- assertFalse(map.getDbEntities().contains(dbEntity));
-
- assertTokensAndExecute(1, 0);
- assertTokensAndExecute(0, 0);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/CreateTableToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/CreateTableToModelIT.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/CreateTableToModelIT.java
deleted file mode 100644
index 3d14c1d..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/CreateTableToModelIT.java
+++ /dev/null
@@ -1,97 +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.merge;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.sql.Types;
-import java.util.List;
-
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.ObjEntity;
-import org.junit.Test;
-
-public class CreateTableToModelIT extends MergeCase {
-
- @Test
- public void testAddTable() throws Exception {
- dropTableIfPresent("NEW_TABLE");
- assertTokensAndExecute(0, 0);
-
- DbEntity dbEntity = new DbEntity("NEW_TABLE");
-
- DbAttribute column1 = new DbAttribute("ID", Types.INTEGER, dbEntity);
- column1.setMandatory(true);
- column1.setPrimaryKey(true);
- dbEntity.addAttribute(column1);
-
- DbAttribute column2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity);
- column2.setMaxLength(10);
- column2.setMandatory(false);
- dbEntity.addAttribute(column2);
-
- // for the new entity to the db
- execute(mergerFactory().createCreateTableToDb(dbEntity));
-
- List<MergerToken> tokens = createMergeTokens();
- assertEquals(1, tokens.size());
- MergerToken token = tokens.get(0);
- if (token.getDirection().isToDb()) {
- token = token.createReverse(mergerFactory());
- }
- assertTrue(token.getClass().getName(), token instanceof CreateTableToModel);
-
- execute(token);
-
- ObjEntity objEntity = null;
- for (ObjEntity candidate : map.getObjEntities()) {
- if (dbEntity.getName().equalsIgnoreCase(candidate.getDbEntityName())) {
- objEntity = candidate;
- break;
- }
- }
- assertNotNull(objEntity);
-
- assertEquals(objEntity.getClassName(), map.getDefaultPackage() + "." + objEntity.getName());
- assertEquals(objEntity.getSuperClassName(), map.getDefaultSuperclass());
- assertEquals(objEntity.getClientClassName(), map.getDefaultClientPackage() + "." + objEntity.getName());
- assertEquals(objEntity.getClientSuperClassName(), map.getDefaultClientSuperclass());
-
- assertEquals(1, objEntity.getAttributes().size());
- assertEquals("java.lang.String", objEntity.getAttributes().iterator().next().getType());
-
- // clear up
- // fix psql case issue
- map.removeDbEntity(objEntity.getDbEntity().getName(), true);
- map.removeObjEntity(objEntity.getName(), true);
- map.removeDbEntity(dbEntity.getName(), true);
- resolver.refreshMappingCache();
- assertNull(map.getObjEntity(objEntity.getName()));
- assertNull(map.getDbEntity(dbEntity.getName()));
- assertFalse(map.getDbEntities().contains(dbEntity));
-
- assertTokensAndExecute(1, 0);
- assertTokensAndExecute(0, 0);
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/DbMergerTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/DbMergerTest.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/DbMergerTest.java
deleted file mode 100644
index 894129d..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/DbMergerTest.java
+++ /dev/null
@@ -1,261 +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.merge;
-
-import org.apache.cayenne.access.loader.DbLoaderConfiguration;
-import org.apache.cayenne.dba.hsqldb.HSQLMergerFactory;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.merge.builders.DbEntityBuilder;
-import org.junit.Test;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.apache.cayenne.merge.builders.ObjectMother.dataMap;
-import static org.apache.cayenne.merge.builders.ObjectMother.dbAttr;
-import static org.apache.cayenne.merge.builders.ObjectMother.dbEntity;
-import static org.junit.Assert.assertEquals;
-
-public class DbMergerTest {
-
- @Test
- public void testEmptyDataMap() throws Exception {
- assertEquals(0, dbMerger().createMergeTokens(new ArrayList<DbEntity>(0),
- new ArrayList<DbEntity>(0), new DbLoaderConfiguration()).size());
- }
-
- @Test
- public void testAddTable() throws Exception {
- DbEntityBuilder dbEntity =
- dbEntity("table1").attributes(
- dbAttr("attr01").typeInt()
- );
- DataMap existing = dataMap().with(dbEntity).build();
-
- List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(),
- new ArrayList<DbEntity>(0), new DbLoaderConfiguration());
-
- assertEquals(1, tokens.size());
- assertEquals(factory().createCreateTableToDb(dbEntity.build()).getTokenValue(),
- tokens.get(0).getTokenValue());
- }
-
- @Test
- public void testRemoveTable() throws Exception {
- DataMap db = dataMap().with(
- dbEntity("table1").attributes(
- dbAttr("attr01").typeInt()
- )).build();
-
- List<MergerToken> tokens = dbMerger().createMergeTokens(new ArrayList<DbEntity>(0),
- db.getDbEntities(), new DbLoaderConfiguration());
-
- assertEquals(1, tokens.size());
- assertEquals(factory().createDropTableToDb(db.getDbEntity("table1")).getTokenValue(),
- tokens.get(0).getTokenValue());
- }
-
- @Test
- public void testAddColumn() throws Exception {
- DataMap existing = dataMap().with(
- dbEntity("table1").attributes(
- dbAttr("attr01").typeInt(),
- dbAttr("attr02").typeInt()
- )).build();
-
- DataMap db = dataMap().with(
- dbEntity("table1").attributes(
- dbAttr("attr01").typeInt()
- )).build();
-
- List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(),
- db.getDbEntities(), new DbLoaderConfiguration());
-
- assertEquals(1, tokens.size());
-
- DbEntity entity = existing.getDbEntity("table1");
- assertEquals(factory().createAddColumnToDb(entity, entity.getAttribute("attr02")).getTokenValue(),
- tokens.get(0).getTokenValue());
- }
-
- @Test
- public void testAddRelationship() throws Exception {
- DataMap existing = dataMap().with(
- dbEntity("table1").attributes(
- dbAttr("attr01").typeInt(),
- dbAttr("attr02").typeInt()),
-
- dbEntity("table2").attributes(
- dbAttr("attr01").typeInt().primaryKey(),
- dbAttr("attr02").typeInt())
- ).join("rel", "table1.attr01", "table2.attr01")
- .build();
-
- DataMap db = dataMap().with(
- dbEntity("table1").attributes(
- dbAttr("attr01").typeInt(),
- dbAttr("attr02").typeInt()),
-
- dbEntity("table2").attributes(
- dbAttr("attr01").typeInt().primaryKey(),
- dbAttr("attr02").typeInt())
- )//.join("table1.attr01", "table2.attr01")
- .build();
-
-
- List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(),
- db.getDbEntities(), new DbLoaderConfiguration());
-
- assertEquals(1, tokens.size());
-
- DbEntity entity = existing.getDbEntity("table1");
- assertEquals(factory().createAddRelationshipToDb(entity, entity.getRelationship("rel")).getTokenValue(),
- tokens.get(0).getTokenValue());
- }
-
- @Test
- public void testAddRelationship1() throws Exception {
- DataMap existing = dataMap().with(
- dbEntity("table1").attributes(
- dbAttr("attr01").typeInt(),
- dbAttr("attr02").typeInt()),
-
- dbEntity("table2").attributes(
- dbAttr("attr01").typeInt().primaryKey(),
- dbAttr("attr02").typeInt().primaryKey(),
- dbAttr("attr03").typeInt().primaryKey())
- ).join("rel", "table1.attr01", "table2.attr01")
- .join("rel1", "table1.attr01", "table2.attr03")
- .build();
-
- DataMap db = dataMap().with(
- dbEntity("table1").attributes(
- dbAttr("attr01").typeInt(),
- dbAttr("attr02").typeInt()),
-
- dbEntity("table2").attributes(
- dbAttr("attr01").typeInt().primaryKey(),
- dbAttr("attr02").typeInt().primaryKey(),
- dbAttr("attr03").typeInt().primaryKey())
- ).join("rel", "table1.attr01", "table2.attr02")
- .join("rel1", "table1.attr01", "table2.attr03")
- .build();
-
-
- List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(),
- db.getDbEntities(), new DbLoaderConfiguration());
-
- assertEquals(2, tokens.size());
-
- DbEntity entity = existing.getDbEntity("table1");
- assertEquals(factory().createDropRelationshipToDb(entity, entity.getRelationship("rel")).getTokenValue(),
- tokens.get(0).getTokenValue());
-
- entity = db.getDbEntity("table1");
- assertEquals(factory().createAddRelationshipToDb(entity, entity.getRelationship("rel")).getTokenValue(),
- tokens.get(0).getTokenValue());
- }
-
- @Test
- public void testRemoveRelationship() throws Exception {
- DataMap existing = dataMap().with(
- dbEntity("table1").attributes(
- dbAttr("attr01").typeInt(),
- dbAttr("attr02").typeInt()),
-
- dbEntity("table2").attributes(
- dbAttr("attr01").typeInt().primaryKey(),
- dbAttr("attr02").typeInt())
- )
- .build();
-
- DataMap db = dataMap().with(
- dbEntity("table1").attributes(
- dbAttr("attr01").typeInt(),
- dbAttr("attr02").typeInt()),
-
- dbEntity("table2").attributes(
- dbAttr("attr01").typeInt().primaryKey(),
- dbAttr("attr02").typeInt())
- ).join("rel", "table1.attr01", "table2.attr01")
- .build();
-
-
- List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(), db.getDbEntities(), new DbLoaderConfiguration());
-
- assertEquals(1, tokens.size());
-
- DbEntity entity = db.getDbEntity("table1");
- assertEquals(factory().createDropRelationshipToDb(entity, entity.getRelationship("rel")).getTokenValue(),
- tokens.get(0).getTokenValue());
- }
-
- @Test
- public void testRemoveColumn() throws Exception {
- DataMap existing = dataMap().with(
- dbEntity("table1").attributes(
- dbAttr("attr01").typeInt()
- )).build();
-
- DataMap db = dataMap().with(
- dbEntity("table1").attributes(
- dbAttr("attr01").typeInt(),
- dbAttr("attr02").typeInt()
- )).build();
-
- List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(),
- db.getDbEntities(), new DbLoaderConfiguration());
-
- assertEquals(1, tokens.size());
-
- DbEntity entity = db.getDbEntity("table1");
- assertEquals(factory().createDropColumnToModel(entity, entity.getAttribute("attr02")).getTokenValue(),
- tokens.get(0).getTokenValue());
- }
-
- @Test
- public void testNoChanges() throws Exception {
- DataMap dataMap1 = dataMap().with(
- dbEntity("table1").attributes(
- dbAttr("attr01").typeInt(),
- dbAttr("attr02").typeInt(),
- dbAttr("attr03").typeInt()
- )).build();
-
- DataMap dataMap2 = dataMap().with(
- dbEntity("table1").attributes(
- dbAttr("attr01").typeInt(),
- dbAttr("attr02").typeInt(),
- dbAttr("attr03").typeInt()
- )).build();
-
-
- assertEquals(0, dbMerger().createMergeTokens(dataMap1.getDbEntities(),
- dataMap2.getDbEntities(), new DbLoaderConfiguration()).size());
- }
-
- private DbMerger dbMerger() {
- return new DbMerger(factory());
- }
-
- private HSQLMergerFactory factory() {
- return new HSQLMergerFactory();
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/DropColumnToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/DropColumnToModelIT.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/DropColumnToModelIT.java
deleted file mode 100644
index 9005e79..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/DropColumnToModelIT.java
+++ /dev/null
@@ -1,235 +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.merge;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.sql.Types;
-import java.util.List;
-
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbJoin;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.ObjAttribute;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.map.ObjRelationship;
-import org.junit.Test;
-
-public class DropColumnToModelIT extends MergeCase {
-
- @Test
- public void testSimpleColumn() throws Exception {
- dropTableIfPresent("NEW_TABLE");
-
- assertTokensAndExecute(0, 0);
-
- DbEntity dbEntity = new DbEntity("NEW_TABLE");
-
- DbAttribute column1 = new DbAttribute("ID", Types.INTEGER, dbEntity);
- column1.setMandatory(true);
- column1.setPrimaryKey(true);
- dbEntity.addAttribute(column1);
-
- DbAttribute column2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity);
- column2.setMaxLength(10);
- column2.setMandatory(false);
- dbEntity.addAttribute(column2);
-
- map.addDbEntity(dbEntity);
-
- assertTokensAndExecute(1, 0);
- assertTokensAndExecute(0, 0);
-
- ObjEntity objEntity = new ObjEntity("NewTable");
- objEntity.setDbEntity(dbEntity);
- ObjAttribute oatr1 = new ObjAttribute("name");
- oatr1.setDbAttributePath(column2.getName());
- oatr1.setType("java.lang.String");
- objEntity.addAttribute(oatr1);
- map.addObjEntity(objEntity);
-
- // force drop name column in db
- MergerToken token = mergerFactory().createDropColumnToDb(dbEntity, column2);
- execute(token);
-
- List<MergerToken> tokens = createMergeTokens();
- assertEquals(1, tokens.size());
- token = tokens.get(0);
- if (token.getDirection().isToDb()) {
- token = token.createReverse(mergerFactory());
- }
- assertTrue(token instanceof DropColumnToModel);
- execute(token);
- assertNull(dbEntity.getAttribute(column2.getName()));
- assertNull(objEntity.getAttribute(oatr1.getName()));
-
- // clear up
- map.removeObjEntity(objEntity.getName(), true);
- map.removeDbEntity(dbEntity.getName(), true);
- resolver.refreshMappingCache();
- assertNull(map.getObjEntity(objEntity.getName()));
- assertNull(map.getDbEntity(dbEntity.getName()));
- assertFalse(map.getDbEntities().contains(dbEntity));
-
- assertTokensAndExecute(1, 0);
- assertTokensAndExecute(0, 0);
- }
-
- @Test
- public void testRemoveFKColumnWithoutRelationshipInDb() throws Exception {
- dropTableIfPresent("NEW_TABLE");
- dropTableIfPresent("NEW_TABLE2");
-
- assertTokensAndExecute(0, 0);
-
- DbEntity dbEntity1 = new DbEntity("NEW_TABLE");
-
- DbAttribute e1col1 = new DbAttribute("ID", Types.INTEGER, dbEntity1);
- e1col1.setMandatory(true);
- e1col1.setPrimaryKey(true);
- dbEntity1.addAttribute(e1col1);
-
- DbAttribute e1col2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity1);
- e1col2.setMaxLength(10);
- e1col2.setMandatory(false);
- dbEntity1.addAttribute(e1col2);
-
- map.addDbEntity(dbEntity1);
-
- DbEntity dbEntity2 = new DbEntity("NEW_TABLE2");
- DbAttribute e2col1 = new DbAttribute("ID", Types.INTEGER, dbEntity2);
- e2col1.setMandatory(true);
- e2col1.setPrimaryKey(true);
- dbEntity2.addAttribute(e2col1);
- DbAttribute e2col2 = new DbAttribute("FK", Types.INTEGER, dbEntity2);
- dbEntity2.addAttribute(e2col2);
- DbAttribute e2col3 = new DbAttribute("NAME", Types.VARCHAR, dbEntity2);
- e2col3.setMaxLength(10);
- dbEntity2.addAttribute(e2col3);
-
- map.addDbEntity(dbEntity2);
-
- assertTokensAndExecute(2, 0);
- assertTokensAndExecute(0, 0);
-
- // force drop fk column in db
- execute(mergerFactory().createDropColumnToDb(dbEntity2, e2col2));
-
- // create db relationships, but do not sync them to db
- DbRelationship rel1To2 = new DbRelationship("rel1To2");
- rel1To2.setSourceEntity(dbEntity1);
- rel1To2.setTargetEntityName(dbEntity2);
- rel1To2.setToMany(true);
- rel1To2.addJoin(new DbJoin(rel1To2, e1col1.getName(), e2col2.getName()));
- dbEntity1.addRelationship(rel1To2);
- DbRelationship rel2To1 = new DbRelationship("rel2To1");
- rel2To1.setSourceEntity(dbEntity2);
- rel2To1.setTargetEntityName(dbEntity1);
- rel2To1.setToMany(false);
- rel2To1.addJoin(new DbJoin(rel2To1, e2col2.getName(), e1col1.getName()));
- dbEntity2.addRelationship(rel2To1);
- assertSame(rel1To2, rel2To1.getReverseRelationship());
- assertSame(rel2To1, rel1To2.getReverseRelationship());
-
- // create ObjEntities
- ObjEntity objEntity1 = new ObjEntity("NewTable");
- objEntity1.setDbEntity(dbEntity1);
- ObjAttribute oatr1 = new ObjAttribute("name");
- oatr1.setDbAttributePath(e1col2.getName());
- oatr1.setType("java.lang.String");
- objEntity1.addAttribute(oatr1);
- map.addObjEntity(objEntity1);
- ObjEntity objEntity2 = new ObjEntity("NewTable2");
- objEntity2.setDbEntity(dbEntity2);
- ObjAttribute o2a1 = new ObjAttribute("name");
- o2a1.setDbAttributePath(e2col3.getName());
- o2a1.setType("java.lang.String");
- objEntity2.addAttribute(o2a1);
- map.addObjEntity(objEntity2);
-
- // create ObjRelationships
- assertEquals(0, objEntity1.getRelationships().size());
- assertEquals(0, objEntity2.getRelationships().size());
- ObjRelationship objRel1To2 = new ObjRelationship("objRel1To2");
- objRel1To2.addDbRelationship(rel1To2);
- objRel1To2.setSourceEntity(objEntity1);
- objRel1To2.setTargetEntityName(objEntity2);
- objEntity1.addRelationship(objRel1To2);
- ObjRelationship objRel2To1 = new ObjRelationship("objRel2To1");
- objRel2To1.addDbRelationship(rel2To1);
- objRel2To1.setSourceEntity(objEntity2);
- objRel2To1.setTargetEntityName(objEntity1);
- objEntity2.addRelationship(objRel2To1);
- assertEquals(1, objEntity1.getRelationships().size());
- assertEquals(1, objEntity2.getRelationships().size());
- assertSame(objRel1To2, objRel2To1.getReverseRelationship());
- assertSame(objRel2To1, objRel1To2.getReverseRelationship());
-
- // try do use the merger to remove the column and relationship in the
- // model
- List<MergerToken> tokens = createMergeTokens();
- assertTokens(tokens, 2, 0);
- // TODO: reversing the following two tokens should also reverse the
- // order
- MergerToken token0 = tokens.get(0).createReverse(mergerFactory());
- MergerToken token1 = tokens.get(1).createReverse(mergerFactory());
- if (!(token0 instanceof DropRelationshipToModel && token1 instanceof DropColumnToModel || token1 instanceof DropRelationshipToModel
- && token0 instanceof DropColumnToModel)) {
- fail();
- }
- // do not execute DropRelationshipToModel, only DropColumnToModel.
- if (token1 instanceof DropColumnToModel) {
- execute(token1);
- } else {
- execute(token0);
- }
-
- // check after merging
- assertNull(dbEntity2.getAttribute(e2col2.getName()));
- assertEquals(0, dbEntity1.getRelationships().size());
- assertEquals(0, dbEntity2.getRelationships().size());
- assertEquals(0, objEntity1.getRelationships().size());
- assertEquals(0, objEntity2.getRelationships().size());
-
- // clear up
-
- dbEntity1.removeRelationship(rel1To2.getName());
- dbEntity2.removeRelationship(rel2To1.getName());
- map.removeObjEntity(objEntity1.getName(), true);
- map.removeDbEntity(dbEntity1.getName(), true);
- map.removeObjEntity(objEntity2.getName(), true);
- map.removeDbEntity(dbEntity2.getName(), true);
- resolver.refreshMappingCache();
- assertNull(map.getObjEntity(objEntity1.getName()));
- assertNull(map.getDbEntity(dbEntity1.getName()));
- assertNull(map.getObjEntity(objEntity2.getName()));
- assertNull(map.getDbEntity(dbEntity2.getName()));
- assertFalse(map.getDbEntities().contains(dbEntity1));
- assertFalse(map.getDbEntities().contains(dbEntity2));
-
- assertTokensAndExecute(2, 0);
- assertTokensAndExecute(0, 0);
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java
deleted file mode 100644
index 4610fcd..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java
+++ /dev/null
@@ -1,188 +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.merge;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.fail;
-
-import java.sql.Types;
-import java.util.List;
-
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbJoin;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.ObjAttribute;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.map.ObjRelationship;
-import org.junit.Test;
-
-public class DropRelationshipToModelIT extends MergeCase {
-
- @Test
- public void testForeignKey() throws Exception {
- dropTableIfPresent("NEW_TABLE");
- dropTableIfPresent("NEW_TABLE2");
-
- assertTokensAndExecute(0, 0);
-
- DbEntity dbEntity1 = new DbEntity("NEW_TABLE");
-
- DbAttribute e1col1 = new DbAttribute("ID", Types.INTEGER, dbEntity1);
- e1col1.setMandatory(true);
- e1col1.setPrimaryKey(true);
- dbEntity1.addAttribute(e1col1);
-
- DbAttribute e1col2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity1);
- e1col2.setMaxLength(10);
- e1col2.setMandatory(false);
- dbEntity1.addAttribute(e1col2);
-
- map.addDbEntity(dbEntity1);
-
- DbEntity dbEntity2 = new DbEntity("NEW_TABLE2");
- DbAttribute e2col1 = new DbAttribute("ID", Types.INTEGER, dbEntity2);
- e2col1.setMandatory(true);
- e2col1.setPrimaryKey(true);
- dbEntity2.addAttribute(e2col1);
- DbAttribute e2col2 = new DbAttribute("FK", Types.INTEGER, dbEntity2);
- dbEntity2.addAttribute(e2col2);
- DbAttribute e2col3 = new DbAttribute("NAME", Types.VARCHAR, dbEntity2);
- e2col3.setMaxLength(10);
- dbEntity2.addAttribute(e2col3);
-
- map.addDbEntity(dbEntity2);
-
- // create db relationships
- DbRelationship rel1To2 = new DbRelationship("rel1To2");
- rel1To2.setSourceEntity(dbEntity1);
- rel1To2.setTargetEntityName(dbEntity2);
- rel1To2.setToMany(true);
- rel1To2.addJoin(new DbJoin(rel1To2, e1col1.getName(), e2col2.getName()));
- dbEntity1.addRelationship(rel1To2);
- DbRelationship rel2To1 = new DbRelationship("rel2To1");
- rel2To1.setSourceEntity(dbEntity2);
- rel2To1.setTargetEntityName(dbEntity1);
- rel2To1.setToMany(false);
- rel2To1.addJoin(new DbJoin(rel2To1, e2col2.getName(), e1col1.getName()));
- dbEntity2.addRelationship(rel2To1);
- assertSame(rel1To2, rel2To1.getReverseRelationship());
- assertSame(rel2To1, rel1To2.getReverseRelationship());
-
- assertTokensAndExecute(4, 0);
- assertTokensAndExecute(0, 0);
-
- // create ObjEntities
- ObjEntity objEntity1 = new ObjEntity("NewTable");
- objEntity1.setDbEntity(dbEntity1);
- ObjAttribute oatr1 = new ObjAttribute("name");
- oatr1.setDbAttributePath(e1col2.getName());
- oatr1.setType("java.lang.String");
- objEntity1.addAttribute(oatr1);
- map.addObjEntity(objEntity1);
- ObjEntity objEntity2 = new ObjEntity("NewTable2");
- objEntity2.setDbEntity(dbEntity2);
- ObjAttribute o2a1 = new ObjAttribute("name");
- o2a1.setDbAttributePath(e2col3.getName());
- o2a1.setType("java.lang.String");
- objEntity2.addAttribute(o2a1);
- map.addObjEntity(objEntity2);
-
- // create ObjRelationships
- assertEquals(0, objEntity1.getRelationships().size());
- assertEquals(0, objEntity2.getRelationships().size());
- ObjRelationship objRel1To2 = new ObjRelationship("objRel1To2");
- objRel1To2.addDbRelationship(rel1To2);
- objRel1To2.setSourceEntity(objEntity1);
- objRel1To2.setTargetEntityName(objEntity2);
- objEntity1.addRelationship(objRel1To2);
- ObjRelationship objRel2To1 = new ObjRelationship("objRel2To1");
- objRel2To1.addDbRelationship(rel2To1);
- objRel2To1.setSourceEntity(objEntity2);
- objRel2To1.setTargetEntityName(objEntity1);
- objEntity2.addRelationship(objRel2To1);
- assertEquals(1, objEntity1.getRelationships().size());
- assertEquals(1, objEntity2.getRelationships().size());
- assertSame(objRel1To2, objRel2To1.getReverseRelationship());
- assertSame(objRel2To1, objRel1To2.getReverseRelationship());
-
- // remove relationship and fk from model, merge to db and read to model
- dbEntity2.removeRelationship(rel2To1.getName());
- dbEntity1.removeRelationship(rel1To2.getName());
- dbEntity2.removeAttribute(e2col2.getName());
- List<MergerToken> tokens = createMergeTokens();
- /**
- * Add Relationship NEW_TABLE->NEW_TABLE2 To Model
- * Drop Relationship NEW_TABLE2->NEW_TABLE To DB
- * Drop Column NEW_TABLE2.FK To DB
- * */
- assertTokens(tokens, 2, 1);
- for (MergerToken token : tokens) {
- if (token.getDirection().isToDb()) {
- execute(token);
- }
- }
- assertTokensAndExecute(0, 0);
- dbEntity2.addRelationship(rel2To1);
- dbEntity1.addRelationship(rel1To2);
- dbEntity2.addAttribute(e2col2);
-
- // try do use the merger to remove the relationship in the model
- tokens = createMergeTokens();
- assertTokens(tokens, 2, 0);
- // TODO: reversing the following two tokens should also reverse the
- // order
- MergerToken token0 = tokens.get(0).createReverse(mergerFactory());
- MergerToken token1 = tokens.get(1).createReverse(mergerFactory());
- if (!(token0 instanceof DropRelationshipToModel && token1 instanceof DropColumnToModel || token1 instanceof DropRelationshipToModel
- && token0 instanceof DropColumnToModel)) {
- fail();
- }
- execute(token0);
- execute(token1);
-
- // check after merging
- assertNull(dbEntity2.getAttribute(e2col2.getName()));
- assertEquals(0, dbEntity1.getRelationships().size());
- assertEquals(0, dbEntity2.getRelationships().size());
- assertEquals(0, objEntity1.getRelationships().size());
- assertEquals(0, objEntity2.getRelationships().size());
-
- // clear up
- dbEntity1.removeRelationship(rel1To2.getName());
- dbEntity2.removeRelationship(rel2To1.getName());
- map.removeObjEntity(objEntity1.getName(), true);
- map.removeDbEntity(dbEntity1.getName(), true);
- map.removeObjEntity(objEntity2.getName(), true);
- map.removeDbEntity(dbEntity2.getName(), true);
- resolver.refreshMappingCache();
- assertNull(map.getObjEntity(objEntity1.getName()));
- assertNull(map.getDbEntity(dbEntity1.getName()));
- assertNull(map.getObjEntity(objEntity2.getName()));
- assertNull(map.getDbEntity(dbEntity2.getName()));
- assertFalse(map.getDbEntities().contains(dbEntity1));
- assertFalse(map.getDbEntities().contains(dbEntity2));
-
- assertTokensAndExecute(2, 0);
- assertTokensAndExecute(0, 0);
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/DropTableToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/DropTableToModelIT.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/DropTableToModelIT.java
deleted file mode 100644
index ddf5a49..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/DropTableToModelIT.java
+++ /dev/null
@@ -1,94 +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.merge;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.sql.Types;
-import java.util.List;
-
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.ObjAttribute;
-import org.apache.cayenne.map.ObjEntity;
-import org.junit.Test;
-
-public class DropTableToModelIT extends MergeCase {
-
- @Test
- public void testDropTable() throws Exception {
- dropTableIfPresent("NEW_TABLE");
- assertTokensAndExecute(0, 0);
-
- DbEntity dbEntity = new DbEntity("NEW_TABLE");
-
- DbAttribute column1 = new DbAttribute("ID", Types.INTEGER, dbEntity);
- column1.setMandatory(true);
- column1.setPrimaryKey(true);
- dbEntity.addAttribute(column1);
-
- DbAttribute column2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity);
- column2.setMaxLength(10);
- column2.setMandatory(false);
- dbEntity.addAttribute(column2);
-
- map.addDbEntity(dbEntity);
-
- assertTokensAndExecute(1, 0);
- assertTokensAndExecute(0, 0);
-
- ObjEntity objEntity = new ObjEntity("NewTable");
- objEntity.setDbEntity(dbEntity);
- ObjAttribute oatr1 = new ObjAttribute("name");
- oatr1.setDbAttributePath(column2.getName());
- oatr1.setType("java.lang.String");
- objEntity.addAttribute(oatr1);
- map.addObjEntity(objEntity);
-
- // force drop table in db
- MergerToken token = mergerFactory().createDropTableToDb(dbEntity);
- execute(token);
-
- List<MergerToken> tokens = createMergeTokens();
- assertEquals(1, tokens.size());
- token = tokens.get(0);
- if (token.getDirection().isToDb()) {
- token = token.createReverse(mergerFactory());
- }
- assertTrue(token instanceof DropTableToModel);
- execute(token);
- resolver.refreshMappingCache();
- assertNull(map.getDbEntity(dbEntity.getName()));
- assertNull(map.getObjEntity(objEntity.getName()));
-
- // clear up
- map.removeObjEntity(objEntity.getName(), true);
- map.removeDbEntity(dbEntity.getName(), true);
- resolver.refreshMappingCache();
- assertNull(map.getObjEntity(objEntity.getName()));
- assertNull(map.getDbEntity(dbEntity.getName()));
- assertFalse(map.getDbEntities().contains(dbEntity));
-
- assertTokensAndExecute(0, 0);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/MergeCase.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/MergeCase.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/MergeCase.java
deleted file mode 100644
index dfbffa9..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/MergeCase.java
+++ /dev/null
@@ -1,215 +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.merge;
-
-import org.apache.cayenne.access.DataNode;
-import org.apache.cayenne.access.loader.DbLoaderConfiguration;
-import org.apache.cayenne.access.loader.filters.FiltersConfig;
-import org.apache.cayenne.access.loader.filters.PatternFilter;
-import org.apache.cayenne.access.loader.filters.TableFilter;
-import org.apache.cayenne.configuration.server.ServerRuntime;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.test.jdbc.DBHelper;
-import org.apache.cayenne.unit.UnitDbAdapter;
-import org.apache.cayenne.unit.di.server.CayenneProjects;
-import org.apache.cayenne.unit.di.server.ServerCase;
-import org.apache.cayenne.unit.di.server.ServerCaseDataSourceFactory;
-import org.apache.cayenne.unit.di.server.UseServerRuntime;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.junit.Before;
-
-import java.sql.Connection;
-import java.sql.Statement;
-import java.sql.Types;
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-
-@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
-public abstract class MergeCase extends ServerCase {
-
- private Log logger = LogFactory.getLog(MergeCase.class);
-
- @Inject
- private DBHelper dbHelper;
-
- @Inject
- private ServerRuntime runtime;
-
- @Inject
- private UnitDbAdapter accessStackAdapter;
-
- @Inject
- private ServerCaseDataSourceFactory dataSourceFactory;
-
- @Inject
- protected EntityResolver resolver;
-
- @Inject
- protected DataNode node;
-
- protected DataMap map;
-
- @Override
- public void cleanUpDB() throws Exception {
- dbHelper.update("ARTGROUP").set("PARENT_GROUP_ID", null, Types.INTEGER).execute();
- super.cleanUpDB();
- }
-
- @Before
- public void setUp() throws Exception {
-
- // this map can't be safely modified in this test, as it is reset by DI
- // container
- // on every test
- map = runtime.getDataDomain().getDataMap("testmap");
-
- filterDataMap();
-
- List<MergerToken> tokens = createMergeTokens();
- execute(tokens);
-
- assertTokensAndExecute(0, 0);
- }
-
- protected DbMerger createMerger(MergerFactory mergerFactory) {
- return createMerger(mergerFactory, null);
- }
-
- protected DbMerger createMerger(MergerFactory mergerFactory, ValueForNullProvider valueForNullProvider) {
- return new DbMerger(mergerFactory, valueForNullProvider);
- }
-
- protected List<MergerToken> createMergeTokens() {
- DbLoaderConfiguration loaderConfiguration = new DbLoaderConfiguration();
- loaderConfiguration.setFiltersConfig(FiltersConfig.create(null, null,
- TableFilter.include("ARTIST|GALLERY|PAINTING|NEW_TABLE2?"), PatternFilter.INCLUDE_NOTHING));
-
- return createMerger(node.getAdapter().mergerFactory()).createMergeTokens(node.getDataSource(),
- node.getAdapter(), map, loaderConfiguration);
- }
-
- /**
- * Remote binary pk {@link DbEntity} for {@link DbAdapter} not supporting
- * that and so on.
- */
- private void filterDataMap() {
- // copied from AbstractAccessStack.dbEntitiesInInsertOrder
- boolean excludeBinPK = accessStackAdapter.supportsBinaryPK();
-
- if (!excludeBinPK) {
- return;
- }
-
- List<DbEntity> entitiesToRemove = new ArrayList<DbEntity>();
-
- for (DbEntity ent : map.getDbEntities()) {
- for (DbAttribute attr : ent.getAttributes()) {
- // check for BIN PK or FK to BIN Pk
- if (attr.getType() == Types.BINARY || attr.getType() == Types.VARBINARY
- || attr.getType() == Types.LONGVARBINARY) {
-
- if (attr.isPrimaryKey() || attr.isForeignKey()) {
- entitiesToRemove.add(ent);
- break;
- }
- }
- }
- }
-
- for (DbEntity e : entitiesToRemove) {
- map.removeDbEntity(e.getName(), true);
- }
- }
-
- protected void execute(List<MergerToken> tokens) {
- MergerContext mergerContext = MergerContext.builder(map).dataNode(node).build();
- for (MergerToken tok : tokens) {
- tok.execute(mergerContext);
- }
- }
-
- protected void execute(MergerToken token) throws Exception {
- MergerContext mergerContext = MergerContext.builder(map).dataNode(node).build();
- token.execute(mergerContext);
- }
-
- private void executeSql(String sql) throws Exception {
-
- try (Connection conn = dataSourceFactory.getSharedDataSource().getConnection();) {
-
- try (Statement st = conn.createStatement();) {
- st.execute(sql);
- }
- }
- }
-
- protected void assertTokens(List<MergerToken> tokens, int expectedToDb, int expectedToModel) {
- int actualToDb = 0;
- int actualToModel = 0;
- for (MergerToken token : tokens) {
- if (token.getDirection().isToDb()) {
- actualToDb++;
- } else if (token.getDirection().isToModel()) {
- actualToModel++;
- }
- }
-
- assertEquals("tokens to db", expectedToDb, actualToDb);
- assertEquals("tokens to model", expectedToModel, actualToModel);
- }
-
- protected void assertTokensAndExecute(int expectedToDb, int expectedToModel) {
- List<MergerToken> tokens = createMergeTokens();
- assertTokens(tokens, expectedToDb, expectedToModel);
- execute(tokens);
- }
-
- protected MergerFactory mergerFactory() {
- return node.getAdapter().mergerFactory();
- }
-
- protected void dropTableIfPresent(String tableName) throws Exception {
-
- // must have a dummy datamap for the dummy table for the downstream code
- // to work
- DataMap map = new DataMap("dummy");
- map.setQuotingSQLIdentifiers(map.isQuotingSQLIdentifiers());
- DbEntity entity = new DbEntity(tableName);
- map.addDbEntity(entity);
-
- AbstractToDbToken t = (AbstractToDbToken) mergerFactory().createDropTableToDb(entity);
-
- for (String sql : t.createSql(node.getAdapter())) {
-
- try {
- executeSql(sql);
- } catch (Exception e) {
- logger.info("Exception dropping table " + tableName + ", probably abscent..");
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java
deleted file mode 100644
index 5c4c51b..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java
+++ /dev/null
@@ -1,310 +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.merge;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import java.sql.Types;
-
-import org.apache.cayenne.CayenneDataObject;
-import org.apache.cayenne.access.DataContext;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbJoin;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.ObjAttribute;
-import org.apache.cayenne.map.ObjEntity;
-import org.junit.Test;
-
-public class MergerFactoryIT extends MergeCase {
-
- @Inject
- private DataContext context;
-
- @Test
- public void testAddAndDropColumnToDb() throws Exception {
- DbEntity dbEntity = map.getDbEntity("PAINTING");
- assertNotNull(dbEntity);
-
- // create and add new column to model and db
- DbAttribute column = new DbAttribute("NEWCOL1", Types.VARCHAR, dbEntity);
-
- column.setMandatory(false);
- column.setMaxLength(10);
- dbEntity.addAttribute(column);
- assertTokensAndExecute(1, 0);
-
- // try merge once more to check that is was merged
- assertTokensAndExecute(0, 0);
-
- // remove it from model and db
- dbEntity.removeAttribute(column.getName());
- assertTokensAndExecute(1, 0);
- assertTokensAndExecute(0, 0);
- }
-
- @Test
- public void testChangeVarcharSizeToDb() throws Exception {
- DbEntity dbEntity = map.getDbEntity("PAINTING");
- assertNotNull(dbEntity);
-
- // create and add new column to model and db
- DbAttribute column = new DbAttribute("NEWCOL2", Types.VARCHAR, dbEntity);
-
- column.setMandatory(false);
- column.setMaxLength(10);
- dbEntity.addAttribute(column);
- assertTokensAndExecute(1, 0);
-
- // check that is was merged
- assertTokensAndExecute(0, 0);
-
- // change size
- column.setMaxLength(20);
-
- // merge to db
- assertTokensAndExecute(1, 0);
-
- // check that is was merged
- assertTokensAndExecute(0, 0);
-
- // clean up
- dbEntity.removeAttribute(column.getName());
- assertTokensAndExecute(1, 0);
- assertTokensAndExecute(0, 0);
- }
-
- @Test
- public void testMultipleTokensToDb() throws Exception {
- DbEntity dbEntity = map.getDbEntity("PAINTING");
- assertNotNull(dbEntity);
-
- DbAttribute column1 = new DbAttribute("NEWCOL3", Types.VARCHAR, dbEntity);
- column1.setMandatory(false);
- column1.setMaxLength(10);
- dbEntity.addAttribute(column1);
- DbAttribute column2 = new DbAttribute("NEWCOL4", Types.VARCHAR, dbEntity);
- column2.setMandatory(false);
- column2.setMaxLength(10);
- dbEntity.addAttribute(column2);
-
- assertTokensAndExecute(2, 0);
-
- // check that is was merged
- assertTokensAndExecute(0, 0);
-
- // change size
- column1.setMaxLength(20);
- column2.setMaxLength(30);
-
- // merge to db
- assertTokensAndExecute(2, 0);
-
- // check that is was merged
- assertTokensAndExecute(0, 0);
-
- // clean up
- dbEntity.removeAttribute(column1.getName());
- dbEntity.removeAttribute(column2.getName());
- assertTokensAndExecute(2, 0);
- assertTokensAndExecute(0, 0);
- }
-
- @Test
- public void testAddTableToDb() throws Exception {
- dropTableIfPresent("NEW_TABLE");
-
- assertTokensAndExecute(0, 0);
-
- DbEntity dbEntity = new DbEntity("NEW_TABLE");
-
- DbAttribute column1 = new DbAttribute("ID", Types.INTEGER, dbEntity);
- column1.setMandatory(true);
- column1.setPrimaryKey(true);
- dbEntity.addAttribute(column1);
-
- DbAttribute column2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity);
- column2.setMaxLength(10);
- column2.setMandatory(false);
- dbEntity.addAttribute(column2);
-
- map.addDbEntity(dbEntity);
-
- assertTokensAndExecute(1, 0);
- assertTokensAndExecute(0, 0);
-
- ObjEntity objEntity = new ObjEntity("NewTable");
- objEntity.setDbEntity(dbEntity);
- ObjAttribute oatr1 = new ObjAttribute("name");
- oatr1.setDbAttributePath(column2.getName());
- oatr1.setType("java.lang.String");
- objEntity.addAttribute(oatr1);
- map.addObjEntity(objEntity);
-
- for (int i = 0; i < 5; i++) {
- CayenneDataObject dao = (CayenneDataObject) context.newObject(objEntity
- .getName());
- dao.writeProperty(oatr1.getName(), "test " + i);
- }
- context.commitChanges();
-
- // clear up
- map.removeObjEntity(objEntity.getName(), true);
- map.removeDbEntity(dbEntity.getName(), true);
- resolver.refreshMappingCache();
- assertNull(map.getObjEntity(objEntity.getName()));
- assertNull(map.getDbEntity(dbEntity.getName()));
- assertFalse(map.getDbEntities().contains(dbEntity));
-
- assertTokensAndExecute(1, 0);
- assertTokensAndExecute(0, 0);
- }
-
- @Test
- public void testAddForeignKeyWithTable() throws Exception {
- dropTableIfPresent("NEW_TABLE");
-
- assertTokensAndExecute(0, 0);
-
- DbEntity dbEntity = new DbEntity("NEW_TABLE");
-
- attr(dbEntity, "ID", Types.INTEGER, true, true);
- attr(dbEntity, "NAME", Types.VARCHAR, false, false).setMaxLength(10);
- attr(dbEntity, "ARTIST_ID", Types.BIGINT, false, false);
-
- map.addDbEntity(dbEntity);
-
- DbEntity artistDbEntity = map.getDbEntity("ARTIST");
- assertNotNull(artistDbEntity);
-
- // relation from new_table to artist
- DbRelationship r1 = new DbRelationship("toArtistR1");
- r1.setSourceEntity(dbEntity);
- r1.setTargetEntityName(artistDbEntity);
- r1.setToMany(false);
- r1.addJoin(new DbJoin(r1, "ARTIST_ID", "ARTIST_ID"));
- dbEntity.addRelationship(r1);
-
- // relation from artist to new_table
- DbRelationship r2 = new DbRelationship("toNewTableR2");
- r2.setSourceEntity(artistDbEntity);
- r2.setTargetEntityName(dbEntity);
- r2.setToMany(true);
- r2.addJoin(new DbJoin(r2, "ARTIST_ID", "ARTIST_ID"));
- artistDbEntity.addRelationship(r2);
-
- assertTokensAndExecute(2, 0);
- assertTokensAndExecute(0, 0);
-
- // remove relationships
- dbEntity.removeRelationship(r1.getName());
- artistDbEntity.removeRelationship(r2.getName());
- resolver.refreshMappingCache();
- /*
- * Db -Rel 'toArtistR1' - NEW_TABLE 1 -> 1 ARTIST"
-r2 = * Db -Rel 'toNewTableR2' - ARTIST 1 -> * NEW_TABLE"
- * */
- assertTokensAndExecute(1, 1);
- assertTokensAndExecute(0, 0);
-
- // clear up
- // map.removeObjEntity(objEntity.getName(), true);
- map.removeDbEntity(dbEntity.getName(), true);
- resolver.refreshMappingCache();
- // assertNull(map.getObjEntity(objEntity.getName()));
- assertNull(map.getDbEntity(dbEntity.getName()));
- assertFalse(map.getDbEntities().contains(dbEntity));
-
- assertTokensAndExecute(1, 0);
- assertTokensAndExecute(0, 0);
- }
-
- @Test
- public void testAddForeignKeyAfterTable() throws Exception {
- dropTableIfPresent("NEW_TABLE");
-
- assertTokensAndExecute(0, 0);
-
- DbEntity dbEntity = new DbEntity("NEW_TABLE");
- attr(dbEntity, "ID", Types.INTEGER, true, true);
- attr(dbEntity, "NAME", Types.VARCHAR, false, false).setMaxLength(10);
- attr(dbEntity, "ARTIST_ID", Types.BIGINT, false, false);
-
- map.addDbEntity(dbEntity);
-
- DbEntity artistDbEntity = map.getDbEntity("ARTIST");
- assertNotNull(artistDbEntity);
-
- assertTokensAndExecute(1, 0);
- assertTokensAndExecute(0, 0);
-
- // relation from new_table to artist
- DbRelationship r1 = new DbRelationship("toArtistR1");
- r1.setSourceEntity(dbEntity);
- r1.setTargetEntityName(artistDbEntity);
- r1.setToMany(false);
- r1.addJoin(new DbJoin(r1, "ARTIST_ID", "ARTIST_ID"));
- dbEntity.addRelationship(r1);
-
- // relation from artist to new_table
- DbRelationship r2 = new DbRelationship("toNewTableR2");
- r2.setSourceEntity(artistDbEntity);
- r2.setTargetEntityName(dbEntity);
- r2.setToMany(true);
- r2.addJoin(new DbJoin(r2, "ARTIST_ID", "ARTIST_ID"));
- artistDbEntity.addRelationship(r2);
-
- assertTokensAndExecute(1, 0);
- assertTokensAndExecute(0, 0);
-
- // remove relationships
- dbEntity.removeRelationship(r1.getName());
- artistDbEntity.removeRelationship(r2.getName());
- resolver.refreshMappingCache();
- /*
- * Add Relationship ARTIST->NEW_TABLE To Model
- * Drop Relationship NEW_TABLE->ARTIST To DB
- * */
- assertTokensAndExecute(1, 1);
- assertTokensAndExecute(0, 0);
-
- // clear up
- // map.removeObjEntity(objEntity.getName(), true);
- map.removeDbEntity(dbEntity.getName(), true);
- resolver.refreshMappingCache();
- // assertNull(map.getObjEntity(objEntity.getName()));
- assertNull(map.getDbEntity(dbEntity.getName()));
- assertFalse(map.getDbEntities().contains(dbEntity));
-
- assertTokensAndExecute(1, 0);
- assertTokensAndExecute(0, 0);
- }
-
- private static DbAttribute attr(DbEntity dbEntity, String name, int type, boolean mandatory, boolean primaryKey) {
- DbAttribute column1 = new DbAttribute(name, type, dbEntity);
- column1.setMandatory(mandatory);
- column1.setPrimaryKey(primaryKey);
-
- dbEntity.addAttribute(column1);
- return column1;
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/SetAllowNullToDbIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/SetAllowNullToDbIT.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/SetAllowNullToDbIT.java
deleted file mode 100644
index 580b38a..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/SetAllowNullToDbIT.java
+++ /dev/null
@@ -1,66 +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.merge;
-
-import static org.junit.Assert.assertNotNull;
-
-import java.sql.Types;
-
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.junit.Test;
-
-public class SetAllowNullToDbIT extends MergeCase {
-
- @Test
- public void test() throws Exception {
- DbEntity dbEntity = map.getDbEntity("PAINTING");
- assertNotNull(dbEntity);
-
- // create and add new column to model and db
- DbAttribute column = new DbAttribute("NEWCOL2", Types.VARCHAR, dbEntity);
-
- try {
-
- column.setMandatory(true);
- column.setMaxLength(10);
- dbEntity.addAttribute(column);
- assertTokensAndExecute(2, 0);
-
- // check that is was merged
- assertTokensAndExecute(0, 0);
-
- // set null
- column.setMandatory(false);
-
- // merge to db
- assertTokensAndExecute(1, 0);
-
- // check that is was merged
- assertTokensAndExecute(0, 0);
-
- // clean up
- } finally {
- dbEntity.removeAttribute(column.getName());
- assertTokensAndExecute(1, 0);
- assertTokensAndExecute(0, 0);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/SetNotNullToDbIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/SetNotNullToDbIT.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/SetNotNullToDbIT.java
deleted file mode 100644
index f78c77f..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/SetNotNullToDbIT.java
+++ /dev/null
@@ -1,62 +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.merge;
-
-import static org.junit.Assert.assertNotNull;
-
-import java.sql.Types;
-
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.junit.Test;
-
-public class SetNotNullToDbIT extends MergeCase {
-
- @Test
- public void test() throws Exception {
- DbEntity dbEntity = map.getDbEntity("PAINTING");
- assertNotNull(dbEntity);
-
- // create and add new column to model and db
- DbAttribute column = new DbAttribute("NEWCOL2", Types.VARCHAR, dbEntity);
-
- column.setMandatory(false);
- column.setMaxLength(10);
- dbEntity.addAttribute(column);
- assertTokensAndExecute(1, 0);
-
- // check that is was merged
- assertTokensAndExecute(0, 0);
-
- // set not null
- column.setMandatory(true);
-
- // merge to db
- assertTokensAndExecute(1, 0);
-
- // check that is was merged
- assertTokensAndExecute(0, 0);
-
- // clean up
- dbEntity.removeAttribute(column.getName());
- assertTokensAndExecute(1, 0);
- assertTokensAndExecute(0, 0);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/SetPrimaryKeyToDbIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/SetPrimaryKeyToDbIT.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/SetPrimaryKeyToDbIT.java
deleted file mode 100644
index 3003b07..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/SetPrimaryKeyToDbIT.java
+++ /dev/null
@@ -1,58 +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.merge;
-
-import java.sql.Types;
-
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.junit.Test;
-
-public class SetPrimaryKeyToDbIT extends MergeCase {
-
- @Test
- public void test() throws Exception {
- dropTableIfPresent("NEW_TABLE");
- assertTokensAndExecute(0, 0);
-
- DbEntity dbEntity1 = new DbEntity("NEW_TABLE");
-
- DbAttribute e1col1 = new DbAttribute("ID1", Types.INTEGER, dbEntity1);
- e1col1.setMandatory(true);
- e1col1.setPrimaryKey(true);
- dbEntity1.addAttribute(e1col1);
- map.addDbEntity(dbEntity1);
-
- assertTokensAndExecute(1, 0);
- assertTokensAndExecute(0, 0);
-
- DbAttribute e1col2 = new DbAttribute("ID2", Types.INTEGER, dbEntity1);
- e1col2.setMandatory(true);
- dbEntity1.addAttribute(e1col2);
-
- assertTokensAndExecute(2, 0);
- assertTokensAndExecute(0, 0);
-
- e1col1.setPrimaryKey(false);
- e1col2.setPrimaryKey(true);
-
- assertTokensAndExecute(1, 0);
- assertTokensAndExecute(0, 0);
- }
-}
[09/15] cayenne git commit: CAY-2116 Split schema synchronization
code in a separate module
Posted by aa...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/DbLoaderPartialIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/DbLoaderPartialIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/DbLoaderPartialIT.java
new file mode 100644
index 0000000..5490ef9
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/DbLoaderPartialIT.java
@@ -0,0 +1,116 @@
+/*****************************************************************
+ * 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.dbsync.reverse;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.unit.di.server.CayenneProjects;
+import org.apache.cayenne.unit.di.server.ServerCase;
+import org.apache.cayenne.unit.di.server.ServerCaseDataSourceFactory;
+import org.apache.cayenne.unit.di.server.UseServerRuntime;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Collection;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
+public class DbLoaderPartialIT extends ServerCase {
+
+ @Inject
+ private DbAdapter adapter;
+
+ @Inject
+ private ServerCaseDataSourceFactory dataSourceFactory;
+
+ private DbLoader loader;
+
+ @Before
+ public void setUp() throws Exception {
+ loader = new DbLoader(
+ dataSourceFactory.getSharedDataSource().getConnection(),
+ adapter,
+ new DefaultDbLoaderDelegate());
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ loader.getConnection().close();
+ }
+
+ /**
+ * Tests that FKs are properly loaded when the relationship source is not loaded. See
+ * CAY-479. This test will perform two reverse engineers. The second reverse engineer
+ * will skip two tables that share relationships with PAINTING. Relationships in
+ * ARTIST and GALLERY should remain unmodified, and all PAINTING relationships should
+ * be loaded.
+ */
+ @Test
+ public void testPartialLoad() throws Exception {
+
+ DataMap map = new DataMap();
+ String tableLabel = adapter.tableTypeForTable();
+
+ loader.loadDataMapFromDB(null, "%", new String[] {tableLabel}, map);
+
+ Collection<?> rels = getDbEntity(map, "ARTIST").getRelationships();
+ assertNotNull(rels);
+ int artistRels = rels.size();
+
+ rels = getDbEntity(map, "GALLERY").getRelationships();
+ assertNotNull(rels);
+ int galleryRels = rels.size();
+
+ rels = getDbEntity(map, "PAINTING").getRelationships();
+ assertNotNull(rels);
+ int paintingRels = rels.size();
+
+ loader.loadDataMapFromDB(null, "%", new String[] {
+ tableLabel
+ }, map);
+
+ rels = getDbEntity(map, "ARTIST").getRelationships();
+ assertNotNull(rels);
+ assertEquals(artistRels, rels.size());
+
+ rels = getDbEntity(map, "GALLERY").getRelationships();
+ assertNotNull(rels);
+ assertEquals(galleryRels, rels.size());
+
+ rels = getDbEntity(map, "PAINTING").getRelationships();
+ assertNotNull(rels);
+ assertEquals(paintingRels, rels.size());
+ }
+
+ private DbEntity getDbEntity(DataMap map, String name) {
+ DbEntity de = map.getDbEntity(name);
+ // sometimes table names get converted to lowercase
+ if (de == null) {
+ de = map.getDbEntity(name.toLowerCase());
+ }
+
+ return de;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/FiltersConfigBuilderTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/FiltersConfigBuilderTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/FiltersConfigBuilderTest.java
new file mode 100644
index 0000000..6d945a5
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/FiltersConfigBuilderTest.java
@@ -0,0 +1,391 @@
+/*
+ * 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.dbsync.reverse;
+
+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.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.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class FiltersConfigBuilderTest {
+
+ @Test
+ public void testCompact_01() {
+ ReverseEngineering engineering = new ReverseEngineering();
+ engineering.addIncludeTable(new IncludeTable("table1"));
+ engineering.addIncludeTable(new IncludeTable("table2"));
+ engineering.addIncludeTable(new IncludeTable("table3"));
+
+ engineering.addIncludeColumn(new IncludeColumn("includeColumn"));
+
+ FiltersConfigBuilder builder = new FiltersConfigBuilder(engineering);
+ builder.compact();
+ assertEquals(
+ "ReverseEngineering: \n" +
+ " Catalog: null\n" +
+ " Schema: null\n" +
+ " IncludeTable: table1\n" +
+ " IncludeColumn: includeColumn\n" +
+ " IncludeTable: table2\n" +
+ " IncludeColumn: includeColumn\n" +
+ " IncludeTable: table3\n" +
+ " IncludeColumn: includeColumn\n", engineering.toString());
+ }
+
+ @Test
+ public void testCompact_02() {
+ ReverseEngineering engineering = new ReverseEngineering();
+ engineering.addCatalog(new Catalog("catalogName"));
+ engineering.addSchema(new Schema("schemaName01"));
+ engineering.addSchema(new Schema("schemaName02"));
+
+ engineering.addIncludeTable(new IncludeTable("table1"));
+ engineering.addExcludeTable(new ExcludeTable("table2"));
+
+ engineering.addIncludeColumn(new IncludeColumn("includeColumn"));
+
+ FiltersConfigBuilder builder = new FiltersConfigBuilder(engineering);
+ builder.compact();
+ assertEquals(
+ "ReverseEngineering: \n" +
+ " Catalog: catalogName\n" +
+ " Schema: schemaName01\n" +
+ " IncludeTable: table1\n" +
+ " IncludeColumn: includeColumn\n" +
+ " ExcludeTable: table2\n" +
+ " Schema: schemaName02\n" +
+ " IncludeTable: table1\n" +
+ " IncludeColumn: includeColumn\n" +
+ " ExcludeTable: table2\n", engineering.toString());
+ }
+
+ @Test
+ public void testCompact_03() {
+ ReverseEngineering engineering = new ReverseEngineering();
+ engineering.addCatalog(new Catalog("APP1"));
+ engineering.addCatalog(new Catalog("APP2"));
+
+ engineering.addExcludeTable(new ExcludeTable("SYS_.*"));
+ engineering.addExcludeColumn(new ExcludeColumn("calculated_.*"));
+
+ FiltersConfigBuilder builder = new FiltersConfigBuilder(engineering);
+ builder.compact();
+ assertEquals(
+ "ReverseEngineering: \n" +
+ " Catalog: APP1\n" +
+ " Schema: null\n" +
+ " IncludeTable: null\n" +
+ " ExcludeColumn: calculated_.*\n" +
+ " ExcludeTable: SYS_.*\n" +
+ " Catalog: APP2\n" +
+ " Schema: null\n" +
+ " IncludeTable: null\n" +
+ " ExcludeColumn: calculated_.*\n" +
+ " ExcludeTable: SYS_.*\n", engineering.toString());
+ }
+
+ @Test
+ public void testCompact_04() {
+ ReverseEngineering engineering = new ReverseEngineering();
+ engineering.addSchema(new Schema("s"));
+
+ FiltersConfigBuilder builder = new FiltersConfigBuilder(engineering);
+ builder.compact();
+ assertEquals(
+ "ReverseEngineering: \n" +
+ " Catalog: null\n" +
+ " Schema: s\n" +
+ " IncludeTable: null\n", engineering.toString());
+ }
+
+ @Test
+ public void testCompact_full() {
+ ReverseEngineering engineering = new ReverseEngineering();
+ Catalog cat01 = new Catalog("cat_01");
+
+ Schema sch01 = new Schema("sch_01");
+
+ sch01.addIncludeTable(includeTable("t1", "c11", "c12"));
+ sch01.addExcludeTable(new ExcludeTable("t2"));
+ sch01.addIncludeProcedure(new IncludeProcedure("p1"));
+ sch01.addExcludeProcedure(new ExcludeProcedure("p2"));
+ sch01.addIncludeColumn(new IncludeColumn("c_x1"));
+ sch01.addExcludeColumn(new ExcludeColumn("c_x2"));
+
+ cat01.addSchema(sch01);
+
+ cat01.addIncludeTable(includeTable("t3", "c31", "c32"));
+ cat01.addExcludeTable(new ExcludeTable("t4"));
+ cat01.addIncludeProcedure(new IncludeProcedure("p3"));
+ cat01.addExcludeProcedure(new ExcludeProcedure("p4"));
+ cat01.addIncludeColumn(new IncludeColumn("c_xx1"));
+ cat01.addExcludeColumn(new ExcludeColumn("c_xx2"));
+
+ engineering.addCatalog(cat01);
+
+ Schema sch02 = new Schema("sch_02");
+
+ sch02.addIncludeTable(includeTable("t5", "c51", "c52"));
+ sch02.addExcludeTable(new ExcludeTable("t6"));
+ sch02.addIncludeProcedure(new IncludeProcedure("p5"));
+ sch02.addExcludeProcedure(new ExcludeProcedure("p6"));
+ sch02.addIncludeColumn(new IncludeColumn("c2_x1"));
+ sch02.addExcludeColumn(new ExcludeColumn("c2_x2"));
+
+ engineering.addSchema(sch02);
+
+ engineering.addIncludeTable(includeTable("t7", "c71", "c72"));
+ engineering.addExcludeTable(new ExcludeTable("t8"));
+ engineering.addIncludeProcedure(new IncludeProcedure("p7"));
+ engineering.addExcludeProcedure(new ExcludeProcedure("p8"));
+ engineering.addIncludeColumn(new IncludeColumn("c_xxx1"));
+ engineering.addExcludeColumn(new ExcludeColumn("c_xxx2"));
+
+ FiltersConfigBuilder builder = new FiltersConfigBuilder(engineering);
+ assertEquals("Original ReverseEngineering should be",
+ "ReverseEngineering: \n" +
+ " Catalog: cat_01\n" +
+ " Schema: sch_01\n" +
+ " IncludeTable: t1\n" +
+ " IncludeColumn: c11\n" +
+ " ExcludeColumn: c12\n" +
+ " ExcludeTable: t2\n" +
+ " IncludeColumn: c_x1\n" +
+ " ExcludeColumn: c_x2\n" +
+ " IncludeProcedure: p1\n" +
+ " ExcludeProcedure: p2\n" +
+ " IncludeTable: t3\n" +
+ " IncludeColumn: c31\n" +
+ " ExcludeColumn: c32\n" +
+ " ExcludeTable: t4\n" +
+ " IncludeColumn: c_xx1\n" +
+ " ExcludeColumn: c_xx2\n" +
+ " IncludeProcedure: p3\n" +
+ " ExcludeProcedure: p4\n" +
+ " Schema: sch_02\n" +
+ " IncludeTable: t5\n" +
+ " IncludeColumn: c51\n" +
+ " ExcludeColumn: c52\n" +
+ " ExcludeTable: t6\n" +
+ " IncludeColumn: c2_x1\n" +
+ " ExcludeColumn: c2_x2\n" +
+ " IncludeProcedure: p5\n" +
+ " ExcludeProcedure: p6\n" +
+ " IncludeTable: t7\n" +
+ " IncludeColumn: c71\n" +
+ " ExcludeColumn: c72\n" +
+ " ExcludeTable: t8\n" +
+ " IncludeColumn: c_xxx1\n" +
+ " ExcludeColumn: c_xxx2\n" +
+ " IncludeProcedure: p7\n" +
+ " ExcludeProcedure: p8\n", engineering.toString());
+
+
+ builder.compact();
+ assertEquals(
+ "ReverseEngineering: \n" +
+ " Catalog: cat_01\n" +
+ " Schema: sch_01\n" +
+ " IncludeTable: t1\n" +
+ " IncludeColumn: c11\n" +
+ " IncludeColumn: c_xxx1\n" +
+ " IncludeColumn: c_xx1\n" +
+ " IncludeColumn: c_x1\n" +
+ " ExcludeColumn: c12\n" +
+ " ExcludeColumn: c_xxx2\n" +
+ " ExcludeColumn: c_xx2\n" +
+ " ExcludeColumn: c_x2\n" +
+ " IncludeTable: t7\n" +
+ " IncludeColumn: c71\n" +
+ " IncludeColumn: c_xxx1\n" +
+ " ExcludeColumn: c72\n" +
+ " ExcludeColumn: c_xxx2\n" +
+ " IncludeTable: t3\n" +
+ " IncludeColumn: c31\n" +
+ " IncludeColumn: c_xxx1\n" +
+ " IncludeColumn: c_xx1\n" +
+ " ExcludeColumn: c32\n" +
+ " ExcludeColumn: c_xxx2\n" +
+ " ExcludeColumn: c_xx2\n" +
+ " ExcludeTable: t2\n" +
+ " ExcludeTable: t8\n" +
+ " ExcludeTable: t4\n" +
+ " IncludeProcedure: p1\n" +
+ " IncludeProcedure: p7\n" +
+ " IncludeProcedure: p3\n" +
+ " ExcludeProcedure: p2\n" +
+ " ExcludeProcedure: p8\n" +
+ " ExcludeProcedure: p4\n" +
+ " Schema: sch_02\n" +
+ " IncludeTable: t5\n" +
+ " IncludeColumn: c51\n" +
+ " IncludeColumn: c_xxx1\n" +
+ " IncludeColumn: c2_x1\n" +
+ " ExcludeColumn: c52\n" +
+ " ExcludeColumn: c_xxx2\n" +
+ " ExcludeColumn: c2_x2\n" +
+ " IncludeTable: t7\n" +
+ " IncludeColumn: c71\n" +
+ " IncludeColumn: c_xxx1\n" +
+ " ExcludeColumn: c72\n" +
+ " ExcludeColumn: c_xxx2\n" +
+ " ExcludeTable: t6\n" +
+ " ExcludeTable: t8\n" +
+ " IncludeProcedure: p5\n" +
+ " IncludeProcedure: p7\n" +
+ " ExcludeProcedure: p6\n" +
+ " ExcludeProcedure: p8\n", engineering.toString());
+ }
+
+ protected IncludeTable includeTable(String name, String incCol, String excCol) {
+ IncludeTable incTable01 = new IncludeTable(name);
+ incTable01.addIncludeColumn(new IncludeColumn(incCol));
+ incTable01.addExcludeColumn(new ExcludeColumn(excCol));
+ return incTable01;
+ }
+
+ /*@Test
+ public void testEmptyDbEntitiesFilters() throws Exception {
+ ReverseEngineering engineering = new ReverseEngineering();
+ FiltersConfig executions = new FiltersConfigBuilder(engineering).filtersConfig();
+
+ assertEquals("If nothing was configured we have to import everything. Filter %/%/% true/true/true",
+ new FiltersConfig(eFilters(path(), TRUE, TRUE, NULL)),
+ executions);
+ }
+
+ @Test
+ public void testOnlyOneCatalogDbEntitiesFilters() throws Exception {
+ ReverseEngineering engineering = new ReverseEngineering();
+ engineering.addCatalog(new Catalog("catalog_01"));
+ FiltersConfig executions = new FiltersConfigBuilder(engineering).filtersConfig();
+
+
+ assertEquals(new FiltersConfig(eFilters(path("catalog_01", null), TRUE, TRUE, NULL)),
+ executions);
+ }
+
+ @Test
+ public void testCatalogDbEntitiesFilters() throws Exception {
+ ReverseEngineering engineering = new ReverseEngineering();
+ engineering.addCatalog(new Catalog("catalog_01"));
+ engineering.addCatalog(new Catalog("catalog_02").schema(new Schema("schema_01")));
+ engineering.addCatalog(new Catalog("catalog_02").schema(new Schema("schema_02")));
+ engineering.addCatalog(new Catalog("catalog_02").schema(new Schema("schema_03")));
+ engineering.addCatalog(new Catalog("catalog_03").schema(new Schema("schema_01")));
+ engineering.addCatalog(new Catalog("catalog_03").schema(new Schema("schema_01")));
+ engineering.addCatalog(new Catalog("catalog_03").schema(new Schema("schema_01")));
+ engineering.addCatalog(new Catalog("catalog_03").schema(new Schema("schema_01")));
+ FiltersConfig executions = new FiltersConfigBuilder(engineering).filtersConfig();
+
+
+ assertEquals(new FiltersConfig(
+ eFilters(path("catalog_01", null), TRUE, TRUE, NULL),
+ eFilters(path("catalog_02", "schema_01"), TRUE, TRUE, NULL),
+ eFilters(path("catalog_02", "schema_02"), TRUE, TRUE, NULL),
+ eFilters(path("catalog_02", "schema_03"), TRUE, TRUE, NULL),
+ eFilters(path("catalog_03", "schema_01"), TRUE, TRUE, NULL)
+ ),
+ executions);
+ }
+
+ @Test
+ public void testSchemaDbEntitiesFilters() throws Exception {
+ ReverseEngineering engineering = new ReverseEngineering();
+ engineering.addSchema(new Schema("schema_01"));
+ engineering.addSchema(new Schema("schema_02"));
+ engineering.addSchema(new Schema("schema_03"));
+ FiltersConfig executions = new FiltersConfigBuilder(engineering).filtersConfig();
+
+
+ assertEquals(new FiltersConfig(
+ eFilters(path(null, "schema_01"), TRUE, TRUE, NULL),
+ eFilters(path(null, "schema_02"), TRUE, TRUE, NULL),
+ eFilters(path(null, "schema_03"), TRUE, TRUE, NULL)
+ ),
+ executions);
+ }
+
+ @Test
+ public void testFiltersDbEntitiesFilters() throws Exception {
+ ReverseEngineering engineering = new ReverseEngineering();
+ engineering.addIncludeTable(new IncludeTable("IncludeTable"));
+ engineering.addIncludeColumn(new IncludeColumn("IncludeColumn"));
+ engineering.addIncludeProcedure(new IncludeProcedure("IncludeProcedure"));
+ engineering.addExcludeTable(new ExcludeTable("ExcludeTable"));
+ engineering.addExcludeColumn(new ExcludeColumn("ExcludeColumn"));
+ engineering.addExcludeProcedure(new ExcludeProcedure("ExcludeProcedure"));
+
+ FiltersConfig executions = new FiltersConfigBuilder(engineering).filtersConfig();
+
+ assertEquals(new FiltersConfig(
+ eFilters(path(),
+ list(include("IncludeTable"), exclude("ExcludeTable")),
+ list(include("IncludeColumn"), exclude("ExcludeColumn")),
+ list(include("IncludeProcedure"), exclude("ExcludeProcedure"))),
+ eFilters(path(null, null, "IncludeTable"), NULL, TRUE, NULL)
+ ),
+ executions);
+ }
+
+ @Test
+ public void testComplexConfiguration() throws Exception {
+ IncludeTable table = new IncludeTable("table");
+ table.addIncludeColumn(new IncludeColumn("column"));
+
+ Schema schema = new Schema("schema");
+ schema.addIncludeTable(table);
+
+ Catalog catalog = new Catalog("catalog");
+ catalog.addSchema(schema);
+
+ ReverseEngineering engineering = new ReverseEngineering();
+ engineering.addCatalog(catalog);
+
+ FiltersConfig executions = new FiltersConfigBuilder(engineering).filtersConfig();
+
+ assertEquals(new FiltersConfig(
+ eFilters(path("catalog", "schema"), include("table"), NULL, NULL),
+ eFilters(path("catalog", "schema", "table"), NULL, include("column"), NULL)
+ ),
+ executions);
+ }
+
+ @Test
+ public void testAddNull() throws Exception {
+ FiltersConfigBuilder builder = new FiltersConfigBuilder(new ReverseEngineering());
+ DbPath path = new DbPath();
+ builder.add(new EntityFilters(path, NULL, NULL, NULL));
+ builder.add(new EntityFilters(path, NULL, NULL, NULL));
+ builder.add(new EntityFilters(path, NULL, NULL, NULL));
+ builder.add(new EntityFilters(path, NULL, NULL, NULL));
+
+ EntityFilters filter = builder.filtersConfig().filter(path);
+ assertFalse(filter.isEmpty());
+ }*/
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/ManyToManyCandidateEntityTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/ManyToManyCandidateEntityTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/ManyToManyCandidateEntityTest.java
new file mode 100644
index 0000000..edecdfc
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/ManyToManyCandidateEntityTest.java
@@ -0,0 +1,113 @@
+/*****************************************************************
+ * 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.dbsync.reverse;
+
+import org.apache.cayenne.configuration.ConfigurationNameMapper;
+import org.apache.cayenne.configuration.ConfigurationTree;
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.configuration.DataMapLoader;
+import org.apache.cayenne.configuration.DefaultConfigurationNameMapper;
+import org.apache.cayenne.configuration.XMLDataChannelDescriptorLoader;
+import org.apache.cayenne.configuration.XMLDataMapLoader;
+import org.apache.cayenne.di.AdhocObjectFactory;
+import org.apache.cayenne.di.Binder;
+import org.apache.cayenne.di.ClassLoaderManager;
+import org.apache.cayenne.di.DIBootstrap;
+import org.apache.cayenne.di.Injector;
+import org.apache.cayenne.di.Module;
+import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory;
+import org.apache.cayenne.di.spi.DefaultClassLoaderManager;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.Relationship;
+import org.apache.cayenne.map.naming.LegacyNameGenerator;
+import org.apache.cayenne.resource.URLResource;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.net.URL;
+import java.util.ArrayList;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+public class ManyToManyCandidateEntityTest {
+
+ private DataMap map;
+
+ @Before
+ public void setUp() throws Exception {
+ Module testModule = new Module() {
+
+ public void configure(Binder binder) {
+ binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class);
+ binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
+ binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
+ binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
+ }
+ };
+
+ Injector injector = DIBootstrap.createInjector(testModule);
+
+ // create and initialize loader instance to test
+ XMLDataChannelDescriptorLoader loader = new XMLDataChannelDescriptorLoader();
+ injector.injectMembers(loader);
+
+ String testConfigName = "relationship-optimisation";
+ URL url = getClass().getResource("cayenne-" + testConfigName + ".xml");
+
+ ConfigurationTree<DataChannelDescriptor> tree = loader.load(new URLResource(url));
+
+ map = tree.getRootNode().getDataMap(testConfigName);
+ }
+
+ @Test
+ public void testMatchingForManyToManyEntity() throws Exception {
+ ObjEntity manyToManyEntity = map.getObjEntity("Table1Table2");
+
+ assertNotNull(ManyToManyCandidateEntity.build(manyToManyEntity));
+ }
+
+ @Test
+ public void testMatchingForNotManyToManyEntity() throws Exception {
+ ObjEntity entity = map.getObjEntity("Table1");
+
+ assertNull(ManyToManyCandidateEntity.build(entity));
+ }
+
+ @Test
+ public void testOptimisationForManyToManyEntity() {
+ ObjEntity manyToManyEntity = map.getObjEntity("Table1Table2");
+
+ ManyToManyCandidateEntity.build(manyToManyEntity).optimizeRelationships(new LegacyNameGenerator());
+
+ ObjEntity table1Entity = map.getObjEntity("Table1");
+ ObjEntity table2Entity = map.getObjEntity("Table2");
+
+ assertEquals(1, table1Entity.getRelationships().size());
+ assertEquals(table2Entity, new ArrayList<Relationship>(table1Entity.getRelationships()).get(0)
+ .getTargetEntity());
+
+ assertEquals(1, table2Entity.getRelationships().size());
+ assertEquals(table1Entity, new ArrayList<Relationship>(table2Entity.getRelationships()).get(0)
+ .getTargetEntity());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigTest.java
new file mode 100644
index 0000000..5a27558
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigTest.java
@@ -0,0 +1,93 @@
+/*****************************************************************
+ * 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.dbsync.reverse.filters;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.regex.Pattern;
+
+public class FiltersConfigTest extends TestCase {
+
+ public void testToString_01() {
+ FiltersConfig config = FiltersConfig.create(null, null,
+ TableFilter.everything(), PatternFilter.INCLUDE_EVERYTHING);
+
+ assertEquals("Catalog: null\n" +
+ " Schema: null\n" +
+ " Tables: \n" +
+ " Include: null Columns: ALL\n" +
+ " Procedures: ALL\n", config.toString());
+ }
+
+ public void testToString_02() {
+ FiltersConfig config = new FiltersConfig(
+ new CatalogFilter("catalog_01",
+ new SchemaFilter("schema_11", TableFilter.everything(), PatternFilter.INCLUDE_EVERYTHING)),
+ new CatalogFilter("catalog_02",
+ new SchemaFilter("schema_21", TableFilter.everything(), PatternFilter.INCLUDE_NOTHING),
+ new SchemaFilter("schema_22",
+ new TableFilter(
+ includes(new IncludeTableFilter(null, PatternFilter.INCLUDE_NOTHING)),
+ excludes("aaa")),
+ PatternFilter.INCLUDE_NOTHING),
+ new SchemaFilter("schema_23", TableFilter.include("include"), PatternFilter.INCLUDE_NOTHING)
+ )
+ );
+
+ assertEquals("Catalog: catalog_01\n" +
+ " Schema: schema_11\n" +
+ " Tables: \n" +
+ " Include: null Columns: ALL\n" +
+ " Procedures: ALL\n" +
+ "Catalog: catalog_02\n" +
+ " Schema: schema_21\n" +
+ " Tables: \n" +
+ " Include: null Columns: ALL\n" +
+ " Procedures: NONE\n" +
+ " Schema: schema_22\n" +
+ " Tables: \n" +
+ " Include: null Columns: NONE\n" +
+ " aaa\n" +
+ " Procedures: NONE\n" +
+ " Schema: schema_23\n" +
+ " Tables: \n" +
+ " Include: include Columns: ALL\n" +
+ " Procedures: NONE\n", config.toString());
+ }
+
+ private SortedSet<Pattern> excludes(String ... p) {
+ SortedSet<Pattern> patterns = new TreeSet<Pattern>(PatternFilter.PATTERN_COMPARATOR);
+ for (String pattern : p) {
+ patterns.add(PatternFilter.pattern(pattern));
+ }
+ return patterns;
+ }
+
+ protected SortedSet<IncludeTableFilter> includes(IncludeTableFilter ... filters) {
+ SortedSet<IncludeTableFilter> includeTableFilters = new TreeSet<IncludeTableFilter>();
+ Collections.addAll(includeTableFilters, filters);
+
+ return includeTableFilters;
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/IncludeFilterTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/IncludeFilterTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/IncludeFilterTest.java
new file mode 100644
index 0000000..df9312f
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/IncludeFilterTest.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.dbsync.reverse.filters;
+
+import org.junit.Test;
+
+public class IncludeFilterTest {
+
+ @Test
+ public void testIsInclude() throws Exception {
+// IncludeFilter filter = new IncludeFilter(pattern("^v_.*$"));
+// assertTrue(filter.isInclude("v_new_view"));
+// assertFalse(filter.isInclude("new_view"));
+// assertFalse(filter.isInclude("view"));
+// assertFalse(filter.isInclude("girl"));
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilterTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilterTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilterTest.java
new file mode 100644
index 0000000..73739ec
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilterTest.java
@@ -0,0 +1,78 @@
+/*****************************************************************
+ * 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.dbsync.reverse.filters;
+
+import junit.framework.TestCase;
+
+public class PatternFilterTest extends TestCase {
+
+ public void testInclude() throws Exception {
+ PatternFilter filter = new PatternFilter()
+ .include("aaa")
+ .include("bbb");
+
+ assertTrue(filter.isInclude("aaa"));
+ assertTrue(filter.isInclude("bbb"));
+ assertFalse(filter.isInclude("aaaa"));
+ assertFalse(filter.isInclude("aa"));
+ assertFalse(filter.isInclude("abb"));
+
+ filter = new PatternFilter().include("^v_.*$");
+ assertTrue(filter.isInclude("v_new_view"));
+ assertFalse(filter.isInclude("new_view"));
+ assertFalse(filter.isInclude("view"));
+ assertFalse(filter.isInclude("girl"));
+ }
+
+ public void testExclude() throws Exception {
+ PatternFilter filter = new PatternFilter()
+ .exclude("aaa")
+ .exclude("bbb");
+
+ assertFalse(filter.isInclude("aaa"));
+ assertFalse(filter.isInclude("bbb"));
+ assertTrue(filter.isInclude("aaaa"));
+ assertTrue(filter.isInclude("aa"));
+ assertTrue(filter.isInclude("abb"));
+ }
+
+ public void testIncludeExclude() throws Exception {
+ PatternFilter filter = new PatternFilter()
+ .include("aa.*")
+ .exclude("aaa");
+
+ assertFalse(filter.isInclude("aaa"));
+ assertFalse(filter.isInclude("bbb"));
+ assertTrue(filter.isInclude("aaaa"));
+ assertTrue(filter.isInclude("aa"));
+ assertFalse(filter.isInclude("abb"));
+ }
+
+ public void testIncludeAllFilter() {
+ assertTrue(PatternFilter.INCLUDE_EVERYTHING.isInclude("qwe"));
+ assertTrue(PatternFilter.INCLUDE_EVERYTHING.isInclude(""));
+ assertTrue(PatternFilter.INCLUDE_EVERYTHING.isInclude(null));
+ }
+
+ public void testIncludeNoneFilter() {
+ assertFalse(PatternFilter.INCLUDE_NOTHING.isInclude("qwe"));
+ assertFalse(PatternFilter.INCLUDE_NOTHING.isInclude(""));
+ assertFalse(PatternFilter.INCLUDE_NOTHING.isInclude(null));
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/TableFilterTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/TableFilterTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/TableFilterTest.java
new file mode 100644
index 0000000..979b20f
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/TableFilterTest.java
@@ -0,0 +1,91 @@
+/*****************************************************************
+ * 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.dbsync.reverse.filters;
+
+import junit.framework.TestCase;
+
+import java.util.TreeSet;
+import java.util.regex.Pattern;
+
+public class TableFilterTest extends TestCase {
+
+ public void testIncludeEverything() {
+ TableFilter filter = TableFilter.everything();
+
+ assertNotNull(filter.isIncludeTable("table"));
+ assertNotNull(filter.isIncludeTable("aaaa"));
+ assertNotNull(filter.isIncludeTable(""));
+ assertNotNull(filter.isIncludeTable("alex"));
+ }
+
+ public void testInclude() {
+ TreeSet<IncludeTableFilter> includes = new TreeSet<IncludeTableFilter>();
+ includes.add(new IncludeTableFilter("aaa"));
+ includes.add(new IncludeTableFilter("bb"));
+
+ TableFilter filter = new TableFilter(includes, new TreeSet<Pattern>(PatternFilter.PATTERN_COMPARATOR));
+
+ assertNotNull(filter.isIncludeTable("aaa"));
+ assertNull(filter.isIncludeTable("aa"));
+ assertNull(filter.isIncludeTable("aaaa"));
+
+ assertNotNull(filter.isIncludeTable("bb"));
+ assertNull(filter.isIncludeTable(""));
+ assertNull(filter.isIncludeTable("bbbb"));
+ }
+
+
+ public void testExclude() {
+ TreeSet<Pattern> excludes = new TreeSet<Pattern>(PatternFilter.PATTERN_COMPARATOR);
+ excludes.add(Pattern.compile("aaa"));
+ excludes.add(Pattern.compile("bb"));
+
+ TreeSet<IncludeTableFilter> includes = new TreeSet<IncludeTableFilter>();
+ includes.add(new IncludeTableFilter(null, PatternFilter.INCLUDE_EVERYTHING));
+
+ TableFilter filter = new TableFilter(includes, excludes);
+
+ assertNull(filter.isIncludeTable("aaa"));
+ assertNotNull(filter.isIncludeTable("aa"));
+ assertNotNull(filter.isIncludeTable("aaaa"));
+
+ assertNull(filter.isIncludeTable("bb"));
+ assertNotNull(filter.isIncludeTable(""));
+ assertNotNull(filter.isIncludeTable("bbbb"));
+ }
+
+ public void testIncludeExclude() {
+ TreeSet<Pattern> excludes = new TreeSet<Pattern>(PatternFilter.PATTERN_COMPARATOR);
+ excludes.add(Pattern.compile("aaa"));
+ excludes.add(Pattern.compile("bb"));
+
+ TreeSet<IncludeTableFilter> includes = new TreeSet<IncludeTableFilter>();
+ includes.add(new IncludeTableFilter("aa.*"));
+
+ TableFilter filter = new TableFilter(includes, excludes);
+
+ assertNull(filter.isIncludeTable("aaa"));
+ assertNotNull(filter.isIncludeTable("aa"));
+ assertNotNull(filter.isIncludeTable("aaaa"));
+
+ assertNull(filter.isIncludeTable("bb"));
+ assertNull(filter.isIncludeTable(""));
+ assertNull(filter.isIncludeTable("bbbb"));
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/mapper/DbTypeTest.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/mapper/DbTypeTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/mapper/DbTypeTest.java
new file mode 100644
index 0000000..f2cb475
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/mapper/DbTypeTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.dbsync.reverse.mapper;
+
+import org.junit.Test;
+
+import java.util.Iterator;
+import java.util.TreeSet;
+
+import static org.junit.Assert.*;
+
+public class DbTypeTest {
+
+ @Test
+ public void testCompareTo() throws Exception {
+ TreeSet<DbType> set = new TreeSet<DbType>();
+ set.add(new DbType("type-01", null, null, null, null));
+ set.add(new DbType("type-02", null, null, null, null));
+ set.add(new DbType("type-02", 1, null, null, null));
+ set.add(new DbType("type-02", 2, null, null, null));
+ set.add(new DbType("type-02", 2, null, null, true));
+ set.add(new DbType("type-02", 2, null, null, false));
+ set.add(new DbType("type-02", 2, null, 5, null));
+ set.add(new DbType("type-02", 2, null, 5, false));
+ set.add(new DbType("type-02", 2, null, 5, true));
+ set.add(new DbType("type-02", null, 8, 5, true));
+ set.add(new DbType("type-02", null, 9, 5, true));
+
+ Iterator<DbType> iterator = set.iterator();
+ assertEquals(new DbType("type-02", 2, null, 5, true), iterator.next());
+ assertEquals(new DbType("type-02", 2, null, 5, false), iterator.next());
+ assertEquals(new DbType("type-02", null, 9, 5, true), iterator.next());
+ assertEquals(new DbType("type-02", null, 8, 5, true), iterator.next());
+ assertEquals(new DbType("type-02", 2, null, 5, null), iterator.next());
+ assertEquals(new DbType("type-02", 2, null, null, true), iterator.next());
+ assertEquals(new DbType("type-02", 2, null, null, false), iterator.next());
+ assertEquals(new DbType("type-02", 2, null, null, null), iterator.next());
+ assertEquals(new DbType("type-02", 1, null, null, null), iterator.next());
+ assertEquals(new DbType("type-02", null, null, null, null), iterator.next());
+ assertEquals(new DbType("type-01", null, null, null, null), iterator.next());
+ }
+
+ @Test
+ public void testCover() throws Exception {
+ DbType typeJava = new DbType("java");
+ assertTrue(typeJava.isCover(typeJava));
+ assertTrue(typeJava.isCover(new DbType("java", 1, 1, 1, null)));
+ assertTrue(typeJava.isCover(new DbType("java", 1, null, null, null)));
+ assertTrue(typeJava.isCover(new DbType("java", null, 1, null, null)));
+ assertTrue(typeJava.isCover(new DbType("java", null, null, 1, null)));
+ assertTrue(typeJava.isCover(new DbType("java", null, null, null, true)));
+ assertTrue(typeJava.isCover(new DbType("java", null, null, null, false)));
+ assertFalse(typeJava.isCover(new DbType("java1", null, null, null, null)));
+
+ DbType typeWithLength = new DbType("java", 1, null, null, null);
+ assertTrue(typeWithLength.isCover(typeWithLength));
+ assertTrue(typeWithLength.isCover(new DbType("java", 1, null, 1, null)));
+ assertTrue(typeWithLength.isCover(new DbType("java", 1, null, 1, true)));
+ assertTrue(typeWithLength.isCover(new DbType("java", 1, null, null, true)));
+ assertTrue(typeWithLength.isCover(new DbType("java", 1, 1, null, true)));
+ assertFalse(typeWithLength.isCover(new DbType("java", 2, null, null, null)));
+ assertFalse(typeWithLength.isCover(new DbType("java", null, null, null, true)));
+ assertFalse(typeWithLength.isCover(new DbType("java1", 2, null, null, null)));
+
+ DbType typeWithLengthAndNotNull = new DbType("java", 1, null, null, true);
+ assertTrue(typeWithLength.isCover(typeWithLengthAndNotNull));
+ assertTrue(typeWithLength.isCover(new DbType("java", 1, null, 1, true)));
+ assertTrue(typeWithLength.isCover(new DbType("java", 1, 1, 1, true)));
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/unit/DbSyncCase.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/unit/DbSyncCase.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/unit/DbSyncCase.java
new file mode 100644
index 0000000..f52a1b9
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/unit/DbSyncCase.java
@@ -0,0 +1,57 @@
+/*****************************************************************
+ * 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.dbsync.unit;
+
+import org.apache.cayenne.di.DIBootstrap;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.di.Injector;
+import org.apache.cayenne.di.spi.DefaultScope;
+import org.apache.cayenne.unit.di.DICase;
+import org.apache.cayenne.unit.di.server.DBCleaner;
+import org.apache.cayenne.unit.di.server.SchemaBuilder;
+import org.apache.cayenne.unit.di.server.ServerCaseModule;
+import org.junit.Before;
+
+
+public class DbSyncCase extends DICase {
+
+ private static final Injector injector;
+
+ static {
+ DefaultScope testScope = new DefaultScope();
+ injector = DIBootstrap.createInjector(
+ new ServerCaseModule(testScope),
+ new DbSyncCaseModule(testScope));
+
+ injector.getInstance(SchemaBuilder.class).rebuildSchema();
+ }
+
+ @Inject
+ private DBCleaner dbCleaner;
+
+ @Before
+ public void cleanUpDB() throws Exception {
+ dbCleaner.clean();
+ }
+
+ @Override
+ protected Injector getUnitTestInjector() {
+ return injector;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/unit/DbSyncCaseModule.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/unit/DbSyncCaseModule.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/unit/DbSyncCaseModule.java
new file mode 100644
index 0000000..369cffb
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/unit/DbSyncCaseModule.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.dbsync.unit;
+
+import org.apache.cayenne.configuration.server.ServerRuntime;
+import org.apache.cayenne.di.Binder;
+import org.apache.cayenne.di.Module;
+import org.apache.cayenne.di.spi.DefaultScope;
+
+public class DbSyncCaseModule implements Module {
+ protected DefaultScope testScope;
+
+ public DbSyncCaseModule(DefaultScope testScope) {
+ this.testScope = testScope;
+ }
+
+ @Override
+ public void configure(Binder binder) {
+ binder.bind(ServerRuntime.class).toProvider(DbSyncServerRuntimeProvider.class).in(
+ testScope);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/unit/DbSyncServerRuntimeProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/unit/DbSyncServerRuntimeProvider.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/unit/DbSyncServerRuntimeProvider.java
new file mode 100644
index 0000000..34454d7
--- /dev/null
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/unit/DbSyncServerRuntimeProvider.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.dbsync.unit;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dbsync.CayenneDbSyncModule;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.di.Module;
+import org.apache.cayenne.di.Provider;
+import org.apache.cayenne.unit.UnitDbAdapter;
+import org.apache.cayenne.unit.di.server.ServerCaseDataSourceFactory;
+import org.apache.cayenne.unit.di.server.ServerCaseProperties;
+import org.apache.cayenne.unit.di.server.ServerRuntimeProvider;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class DbSyncServerRuntimeProvider extends ServerRuntimeProvider {
+
+ public DbSyncServerRuntimeProvider(@Inject ServerCaseDataSourceFactory dataSourceFactory,
+ @Inject ServerCaseProperties properties,
+ @Inject Provider<DbAdapter> dbAdapterProvider,
+ @Inject UnitDbAdapter unitDbAdapter) {
+ super(dataSourceFactory, properties, dbAdapterProvider, unitDbAdapter);
+ }
+
+ @Override
+ protected Collection<? extends Module> getExtraModules() {
+ Collection<Module> modules = new ArrayList<>();
+ modules.addAll(super.getExtraModules());
+ modules.add(new CayenneDbSyncModule());
+ return modules;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/cayenne-relationship-optimisation.xml
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/cayenne-relationship-optimisation.xml b/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/cayenne-relationship-optimisation.xml
new file mode 100644
index 0000000..d4fea49
--- /dev/null
+++ b/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/cayenne-relationship-optimisation.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<domain project-version="6">
+ <map name="relationship-optimisation"/>
+</domain>
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/relationship-optimisation.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/relationship-optimisation.map.xml b/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/relationship-optimisation.map.xml
new file mode 100644
index 0000000..e68645f
--- /dev/null
+++ b/cayenne-dbsync/src/test/resources/org/apache/cayenne/dbsync/reverse/relationship-optimisation.map.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<data-map xmlns="http://cayenne.apache.org/schema/3.0/modelMap"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://cayenne.apache.org/schema/3.0/modelMap http://cayenne.apache.org/schema/3.0/modelMap.xsd"
+ project-version="6">
+ <property name="defaultPackage" value="com.objectstyle"/>
+ <db-entity name="table1" catalog="many_to_many_test">
+ <db-attribute name="id1" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
+ <db-attribute name="table1col" type="VARCHAR" length="45"/>
+ </db-entity>
+ <db-entity name="table1_table2" catalog="many_to_many_test">
+ <db-attribute name="fk1" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
+ <db-attribute name="fk2" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
+ </db-entity>
+ <db-entity name="table2" catalog="many_to_many_test">
+ <db-attribute name="id2" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
+ <db-attribute name="table2col" type="VARCHAR" length="45"/>
+ </db-entity>
+ <obj-entity name="Table1" className="com.objectstyle.Table1" dbEntityName="table1">
+ <obj-attribute name="table1col" type="java.lang.String" db-attribute-path="table1col"/>
+ </obj-entity>
+ <obj-entity name="Table1Table2" className="com.objectstyle.Table1Table2" dbEntityName="table1_table2">
+ </obj-entity>
+ <obj-entity name="Table2" className="com.objectstyle.Table2" dbEntityName="table2">
+ <obj-attribute name="table2col" type="java.lang.String" db-attribute-path="table2col"/>
+ </obj-entity>
+ <db-relationship name="table1Table2Array" source="table1" target="table1_table2" toDependentPK="true" toMany="true">
+ <db-attribute-pair source="id1" target="fk1"/>
+ </db-relationship>
+ <db-relationship name="toTable1" source="table1_table2" target="table1" toMany="false">
+ <db-attribute-pair source="fk1" target="id1"/>
+ </db-relationship>
+ <db-relationship name="toTable2" source="table1_table2" target="table2" toMany="false">
+ <db-attribute-pair source="fk2" target="id2"/>
+ </db-relationship>
+ <db-relationship name="table1Table2Array" source="table2" target="table1_table2" toDependentPK="true" toMany="true">
+ <db-attribute-pair source="id2" target="fk2"/>
+ </db-relationship>
+ <obj-relationship name="table1Table2Array" source="Table1" target="Table1Table2" deleteRule="Deny" db-relationship-path="table1Table2Array"/>
+ <obj-relationship name="toTable1" source="Table1Table2" target="Table1" deleteRule="Nullify" db-relationship-path="toTable1"/>
+ <obj-relationship name="toTable2" source="Table1Table2" target="Table2" deleteRule="Nullify" db-relationship-path="toTable2"/>
+ <obj-relationship name="table1Table2Array" source="Table2" target="Table1Table2" deleteRule="Deny" db-relationship-path="table1Table2Array"/>
+</data-map>
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
----------------------------------------------------------------------
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
deleted file mode 100644
index 67477dd..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
+++ /dev/null
@@ -1,832 +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.access;
-
-import java.sql.Connection;
-import java.sql.DatabaseMetaData;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-
-import org.apache.cayenne.access.loader.DbAttributesPerSchemaLoader;
-import org.apache.cayenne.access.loader.DbLoaderConfiguration;
-import org.apache.cayenne.access.loader.DbTableLoader;
-import org.apache.cayenne.access.loader.DefaultDbLoaderDelegate;
-import org.apache.cayenne.access.loader.ManyToManyCandidateEntity;
-import org.apache.cayenne.access.loader.filters.CatalogFilter;
-import org.apache.cayenne.access.loader.filters.FiltersConfig;
-import org.apache.cayenne.access.loader.filters.PatternFilter;
-import org.apache.cayenne.access.loader.filters.SchemaFilter;
-import org.apache.cayenne.access.loader.filters.TableFilter;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.TypesMapping;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbJoin;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.DbRelationshipDetected;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.map.Procedure;
-import org.apache.cayenne.map.ProcedureParameter;
-import org.apache.cayenne.map.naming.DefaultUniqueNameGenerator;
-import org.apache.cayenne.map.naming.ExportedKey;
-import org.apache.cayenne.map.naming.LegacyNameGenerator;
-import org.apache.cayenne.map.naming.NameCheckers;
-import org.apache.cayenne.map.naming.ObjectNameGenerator;
-import org.apache.cayenne.util.EntityMergeSupport;
-import org.apache.cayenne.util.EqualsBuilder;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Utility class that does reverse engineering of the database. It can create
- * DataMaps using database meta data obtained via JDBC driver.
- */
-public class DbLoader {
-
- private static final Log LOGGER = LogFactory.getLog(DbLoader.class);
-
- public static final String WILDCARD = "%";
- public static final String WILDCARD_PATTERN = ".*";
-
- private final Connection connection;
- private final DbAdapter adapter;
- private final DbLoaderDelegate delegate;
-
- private boolean creatingMeaningfulPK;
-
- private DatabaseMetaData metaData;
-
- /**
- * Strategy for choosing names for entities, attributes and relationships
- */
- private ObjectNameGenerator nameGenerator;
-
- /**
- * Creates new DbLoader.
- */
- public DbLoader(Connection connection, DbAdapter adapter, DbLoaderDelegate delegate) {
- this(connection, adapter, delegate, new LegacyNameGenerator());
- }
-
- /**
- * Creates new DbLoader with specified naming strategy.
- *
- * @since 3.0
- */
- public DbLoader(Connection connection, DbAdapter adapter, DbLoaderDelegate delegate, ObjectNameGenerator strategy) {
- this.adapter = adapter;
- this.connection = connection;
- this.delegate = delegate == null ? new DefaultDbLoaderDelegate() : delegate;
-
- setNameGenerator(strategy);
- }
-
- /**
- * Returns DatabaseMetaData object associated with this DbLoader.
- */
- private DatabaseMetaData getMetaData() throws SQLException {
- if (metaData == null) {
- metaData = connection.getMetaData();
- }
- 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
- */
- public void setCreatingMeaningfulPK(boolean creatingMeaningfulPK) {
- this.creatingMeaningfulPK = creatingMeaningfulPK;
- }
-
- /**
- * Returns true if the generator should map all primary key columns as
- * ObjAttributes.
- *
- * @since 3.0
- */
- public boolean isCreatingMeaningfulPK() {
- return creatingMeaningfulPK;
- }
-
- /**
- * Returns database connection used by this DbLoader.
- *
- * @since 3.0
- */
- public Connection getConnection() {
- return connection;
- }
-
- /**
- * Returns DbAdapter associated with this DbLoader.
- *
- * @since 1.1
- */
- public DbAdapter getAdapter() {
- return adapter;
- }
-
- /**
- * Retrieves catalogs for the database associated with this DbLoader.
- *
- * @return List with the catalog names, empty Array if none found.
- */
- public List<String> getCatalogs() throws SQLException {
- try (ResultSet rs = getMetaData().getCatalogs()) {
- return getStrings(rs);
- }
- }
-
- /**
- * Retrieves the schemas for the database.
- *
- * @return List with the schema names, empty Array if none found.
- */
- public List<String> getSchemas() throws SQLException {
-
- try (ResultSet rs = getMetaData().getSchemas()) {
- return getStrings(rs);
- }
- }
-
- private static List<String> getStrings(ResultSet rs) throws SQLException {
- List<String> strings = new ArrayList<String>();
-
- while (rs.next()) {
- strings.add(rs.getString(1));
- }
-
- return strings;
- }
-
- /**
- * Returns all the table types for the given database. Types may be such as
- * Typical types are "TABLE", "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
- * "LOCAL TEMPORARY", "ALIAS", "SYNONYM"., etc.
- *
- * @return List of Strings, empty array if nothing found.
- */
- public List<String> getTableTypes() throws SQLException {
- List<String> types = new ArrayList<String>();
-
- try (ResultSet rs = getMetaData().getTableTypes();) {
- while (rs.next()) {
- types.add(rs.getString("TABLE_TYPE").trim());
- }
- }
-
- return types;
- }
-
- /**
- * Creates an ObjEntity for each DbEntity in the map.
- */
- public Collection<ObjEntity> loadObjEntities(DataMap map, DbLoaderConfiguration config,
- Collection<DbEntity> entities) {
- Collection<ObjEntity> loadedEntities = DbLoader.loadObjEntities(map, config, entities, nameGenerator);
-
- createEntityMerger(map).synchronizeWithDbEntities(loadedEntities);
-
- return loadedEntities;
- }
-
- public static Collection<ObjEntity> loadObjEntities(DataMap map, DbLoaderConfiguration config,
- Collection<DbEntity> entities, ObjectNameGenerator nameGenerator) {
- if (entities.isEmpty()) {
- return Collections.emptyList();
- }
-
- Collection<ObjEntity> loadedEntities = new ArrayList<ObjEntity>(entities.size());
-
- // doLoad empty ObjEntities for all the tables
- for (DbEntity dbEntity : entities) {
-
- // check if there are existing entities
-
- // TODO: performance. This is an O(n^2) search and it shows on
- // YourKit profiles. Pre-cache mapped entities perhaps (?)
- Collection<ObjEntity> existing = map.getMappedEntities(dbEntity);
- if (!existing.isEmpty()) {
- loadedEntities.addAll(existing);
- continue;
- }
-
- String objEntityName = DefaultUniqueNameGenerator.generate(NameCheckers.objEntity, map,
- nameGenerator.createObjEntityName(dbEntity));
-
- ObjEntity objEntity = new ObjEntity(objEntityName);
- objEntity.setDbEntity(dbEntity);
- objEntity.setClassName(config.getGenericClassName() != null ? config.getGenericClassName() : map
- .getNameWithDefaultPackage(objEntity.getName()));
-
- map.addObjEntity(objEntity);
- loadedEntities.add(objEntity);
- }
-
- return loadedEntities;
- }
-
- /**
- * @since 4.0
- */
- protected EntityMergeSupport createEntityMerger(DataMap map) {
- return new EntityMergeSupport(map, nameGenerator, !creatingMeaningfulPK);
- }
-
- protected void loadDbRelationships(DbLoaderConfiguration config, String catalog, String schema,
- List<DbEntity> tables) throws SQLException {
- if (config.isSkipRelationshipsLoading()) {
- return;
- }
-
- // Get all the foreign keys referencing this table
- Map<String, DbEntity> tablesMap = new HashMap<>();
- for (DbEntity table : tables) {
- tablesMap.put(table.getName(), table);
- }
-
- Map<String, Set<ExportedKey>> keys = loadExportedKeys(config, catalog, schema, tablesMap);
- for (Map.Entry<String, Set<ExportedKey>> entry : keys.entrySet()) {
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("Process keys for: " + entry.getKey());
- }
-
- Set<ExportedKey> exportedKeys = entry.getValue();
- ExportedKey key = exportedKeys.iterator().next();
- if (key == null) {
- throw new IllegalStateException();
- }
-
- DbEntity pkEntity = tablesMap.get(key.getPKTableName());
- if (pkEntity == null) {
- skipRelationLog(key, key.getPKTableName());
- continue;
- }
-
- DbEntity fkEntity = tablesMap.get(key.getFKTableName());
- if (fkEntity == null) {
- skipRelationLog(key, key.getFKTableName());
- continue;
- }
-
- if (!new EqualsBuilder().append(pkEntity.getCatalog(), key.pkCatalog)
- .append(pkEntity.getSchema(), key.pkSchema).append(fkEntity.getCatalog(), key.fkCatalog)
- .append(fkEntity.getSchema(), key.fkSchema).isEquals()) {
-
- LOGGER.info("Skip relation: '" + key + "' because it related to objects from other catalog/schema");
- LOGGER.info(" relation primary key: '" + key.pkCatalog + "." + key.pkSchema + "'");
- LOGGER.info(" primary key entity: '" + pkEntity.getCatalog() + "." + pkEntity.getSchema() + "'");
- LOGGER.info(" relation foreign key: '" + key.fkCatalog + "." + key.fkSchema + "'");
- LOGGER.info(" foreign key entity: '" + fkEntity.getCatalog() + "." + fkEntity.getSchema() + "'");
- continue;
- }
-
- // forwardRelationship is a reference from table with primary key
- DbRelationship forwardRelationship = new DbRelationship(generateName(pkEntity, key, true));
- forwardRelationship.setSourceEntity(pkEntity);
- forwardRelationship.setTargetEntityName(fkEntity);
-
- // forwardRelationship is a reference from table with foreign key,
- // it is what exactly we load from db
- DbRelationshipDetected reverseRelationship = new DbRelationshipDetected(generateName(fkEntity, key, false));
- reverseRelationship.setFkName(key.getFKName());
- reverseRelationship.setSourceEntity(fkEntity);
- reverseRelationship.setTargetEntityName(pkEntity);
- reverseRelationship.setToMany(false);
-
- createAndAppendJoins(exportedKeys, pkEntity, fkEntity, forwardRelationship, reverseRelationship);
-
- boolean toDependentPK = isToDependentPK(forwardRelationship);
- forwardRelationship.setToDependentPK(toDependentPK);
-
- boolean isOneToOne = toDependentPK
- && fkEntity.getPrimaryKeys().size() == forwardRelationship.getJoins().size();
-
- forwardRelationship.setToMany(!isOneToOne);
- forwardRelationship.setName(generateName(pkEntity, key, !isOneToOne));
-
- if (delegate.dbRelationshipLoaded(fkEntity, reverseRelationship)) {
- fkEntity.addRelationship(reverseRelationship);
- }
- if (delegate.dbRelationshipLoaded(pkEntity, forwardRelationship)) {
- pkEntity.addRelationship(forwardRelationship);
- }
- }
- }
-
- private boolean isToDependentPK(DbRelationship forwardRelationship) {
- for (DbJoin dbJoin : forwardRelationship.getJoins()) {
- if (!dbJoin.getTarget().isPrimaryKey()) {
- return false;
- }
- }
-
- return true;
- }
-
- private void createAndAppendJoins(Set<ExportedKey> exportedKeys, DbEntity pkEntity, DbEntity fkEntity,
- DbRelationship forwardRelationship, DbRelationshipDetected reverseRelationship) {
- for (ExportedKey exportedKey : exportedKeys) {
- // Create and append joins
- String pkName = exportedKey.getPKColumnName();
- String fkName = exportedKey.getFKColumnName();
-
- // skip invalid joins...
- DbAttribute pkAtt = pkEntity.getAttribute(pkName);
- if (pkAtt == null) {
- LOGGER.info("no attribute for declared primary key: " + pkName);
- continue;
- }
-
- DbAttribute fkAtt = fkEntity.getAttribute(fkName);
- if (fkAtt == null) {
- LOGGER.info("no attribute for declared foreign key: " + fkName);
- continue;
- }
-
- forwardRelationship.addJoin(new DbJoin(forwardRelationship, pkName, fkName));
- reverseRelationship.addJoin(new DbJoin(reverseRelationship, fkName, pkName));
- }
- }
-
- private Map<String, Set<ExportedKey>> loadExportedKeys(DbLoaderConfiguration config, String catalog, String schema,
- Map<String, DbEntity> tables) throws SQLException {
- Map<String, Set<ExportedKey>> keys = new HashMap<>();
-
- for (DbEntity dbEntity : tables.values()) {
- if (!delegate.dbRelationship(dbEntity)) {
- continue;
- }
-
- ResultSet rs;
- try {
- rs = getMetaData().getExportedKeys(catalog, schema, dbEntity.getName());
- } catch (SQLException cay182Ex) {
- // Sybase-specific - the line above blows on VIEWS, see CAY-182.
- LOGGER.info(
- "Error getting relationships for '" + catalog + "." + schema + "', ignoring. "
- + cay182Ex.getMessage(), cay182Ex);
- return new HashMap<>();
- }
-
- try {
- while (rs.next()) {
- ExportedKey key = ExportedKey.extractData(rs);
-
- DbEntity fkEntity = tables.get(key.getFKTableName());
- if (fkEntity == null) {
- skipRelationLog(key, key.getFKTableName());
- continue;
- }
-
- if (config.getFiltersConfig().tableFilter(fkEntity.getCatalog(), fkEntity.getSchema())
- .isIncludeTable(fkEntity.getName()) == null) {
- continue;
- }
-
- Set<ExportedKey> exportedKeys = keys.get(key.getStrKey());
- if (exportedKeys == null) {
- exportedKeys = new TreeSet<ExportedKey>();
-
- keys.put(key.getStrKey(), exportedKeys);
- }
- exportedKeys.add(key);
- }
-
- } finally {
- rs.close();
- }
- }
- return keys;
- }
-
- private void skipRelationLog(ExportedKey key, String tableName) {
- // if (LOGGER.isDebugEnabled()) {
- LOGGER.info("Skip relation: '" + key + "' because table '" + tableName + "' not found");
- // }
- }
-
- private String generateName(DbEntity entity, ExportedKey key, boolean toMany) {
- String forwardPreferredName = nameGenerator.createDbRelationshipName(key, toMany);
- return DefaultUniqueNameGenerator.generate(NameCheckers.dbRelationship, entity, forwardPreferredName);
- }
-
- /**
- * Flattens many-to-many relationships in the generated model.
- */
- public static void flattenManyToManyRelationships(DataMap map, Collection<ObjEntity> loadedObjEntities,
- ObjectNameGenerator objectNameGenerator) {
- if (loadedObjEntities.isEmpty()) {
- return;
- }
- Collection<ObjEntity> entitiesForDelete = new LinkedList<ObjEntity>();
-
- for (ObjEntity curEntity : loadedObjEntities) {
- ManyToManyCandidateEntity entity = ManyToManyCandidateEntity.build(curEntity);
-
- if (entity != null) {
- entity.optimizeRelationships(objectNameGenerator);
- entitiesForDelete.add(curEntity);
- }
- }
-
- // remove needed entities
- for (ObjEntity curDeleteEntity : entitiesForDelete) {
- map.removeObjEntity(curDeleteEntity.getName(), true);
- }
- loadedObjEntities.removeAll(entitiesForDelete);
- }
-
- private void fireObjEntitiesAddedEvents(Collection<ObjEntity> loadedObjEntities) {
- for (ObjEntity curEntity : loadedObjEntities) {
- // notify delegate
- if (delegate != null) {
- delegate.objEntityAdded(curEntity);
- }
- }
- }
-
- /**
- * By default we want to load Tables and Views for mo types
- *
- * @see DbLoader#getTableTypes()
- * @since 4.0
- */
- public String[] getDefaultTableTypes() {
- List<String> list = new ArrayList<String>(2);
-
- String viewType = adapter.tableTypeForView();
- if (viewType != null) {
- list.add(viewType);
- }
-
- String tableType = adapter.tableTypeForTable();
- if (tableType != null) {
- list.add(tableType);
- }
-
- return list.toArray(new String[list.size()]);
- }
-
- /**
- * Performs database reverse engineering and generates DataMap that contains
- * default mapping of the tables and views. By default will include regular
- * tables and views.
- *
- * @since 1.0.7
- * @deprecated since 4.0 use
- * {@link #load(org.apache.cayenne.map.DataMap, DbLoaderConfiguration)}
- * method that supports catalogs.
- */
- @Deprecated
- public DataMap loadDataMapFromDB(String schemaPattern, String tablePattern, DataMap dataMap) throws SQLException {
-
- DbLoaderConfiguration configuration = new DbLoaderConfiguration();
- configuration.setFiltersConfig(FiltersConfig.create(null, schemaPattern, TableFilter.include(tablePattern),
- PatternFilter.INCLUDE_NOTHING));
-
- load(dataMap, configuration);
- return dataMap;
- }
-
- /**
- * Performs database reverse engineering and generates DataMap object that
- * contains default mapping of the tables and views. Allows to limit types
- * of tables to read.
- *
- * @deprecated since 4.0 use
- * {@link #load(org.apache.cayenne.map.DataMap, DbLoaderConfiguration)}
- * method that supports catalogs.
- */
- @Deprecated
- public DataMap loadDataMapFromDB(String schemaPattern, String tablePattern, String[] tableTypes, DataMap dataMap)
- throws SQLException {
- dataMap.clear();
-
- DbLoaderConfiguration config = new DbLoaderConfiguration();
- config.setFiltersConfig(FiltersConfig.create(null, schemaPattern, TableFilter.include(tablePattern),
- PatternFilter.INCLUDE_NOTHING));
- config.setTableTypes(tableTypes);
-
- load(dataMap, config);
- return dataMap;
- }
-
- /**
- * Performs database reverse engineering based on the specified config and
- * fills the specified DataMap object with DB and object mapping info.
- *
- * @since 4.0
- */
- 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();
- }
-
- for (CatalogFilter catalog : config.getFiltersConfig().catalogs) {
- for (SchemaFilter schema : catalog.schemas) {
-
- List<DbEntity> entities = createTableLoader(catalog.name, schema.name, schema.tables).loadDbEntities(
- dataMap, config, types);
-
- if (entities != null) {
- loadDbRelationships(config, catalog.name, schema.name, entities);
-
- prepareObjLayer(dataMap, config, entities);
- }
- }
- }
- }
-
- protected DbTableLoader createTableLoader(String catalog, String schema, TableFilter filter) throws SQLException {
- return new DbTableLoader(catalog, schema, getMetaData(), delegate, new DbAttributesPerSchemaLoader(catalog,
- schema, getMetaData(), adapter, filter));
- }
-
- public void prepareObjLayer(DataMap dataMap, DbLoaderConfiguration config, Collection<DbEntity> entities) {
- Collection<ObjEntity> loadedObjEntities = loadObjEntities(dataMap, config, entities);
- flattenManyToManyRelationships(dataMap, loadedObjEntities, getNameGenerator());
- fireObjEntitiesAddedEvents(loadedObjEntities);
- }
-
- /**
- * Performs database reverse engineering to match the specified catalog,
- * schema, table name and table type patterns and fills the specified
- * DataMap object with DB and object mapping info.
- *
- * @since 4.0
- */
- public DataMap load(DbLoaderConfiguration config) throws SQLException {
-
- DataMap dataMap = new DataMap();
- load(dataMap, config);
- loadProcedures(dataMap, config);
-
- return dataMap;
- }
-
- /**
- * Loads database stored procedures into the DataMap.
- * <p>
- * <i>As of 1.1 there is no boolean property or delegate method to make
- * procedure loading optional or to implement custom merging logic, so
- * currently this method is NOT CALLED from "loadDataMapFromDB" and should
- * be invoked explicitly by the user. </i>
- * </p>
- *
- * @since 1.1
- * @deprecated since 4.0 use loadProcedures(DataMap, String, String, String)
- * that supports "catalog" pattern.
- */
- @Deprecated
- public void loadProceduresFromDB(String schemaPattern, String namePattern, DataMap dataMap) throws SQLException {
- DbLoaderConfiguration configuration = new DbLoaderConfiguration();
- configuration.setFiltersConfig(FiltersConfig.create(null, schemaPattern, TableFilter.everything(),
- new PatternFilter().include(namePattern)));
-
- loadProcedures(dataMap, configuration);
- }
-
- /**
- * Loads database stored procedures into the DataMap.
- * <p>
- * <i>As of 1.1 there is no boolean property or delegate method to make
- * procedure loading optional or to implement custom merging logic, so
- * currently this method is NOT CALLED from "loadDataMapFromDB" and should
- * be invoked explicitly by the user. </i>
- * </p>
- *
- * @since 4.0
- */
- public Map<String, Procedure> loadProcedures(DataMap dataMap, DbLoaderConfiguration config) throws SQLException {
-
- Map<String, Procedure> procedures = loadProcedures(config);
- if (procedures.isEmpty()) {
- return procedures;
- }
-
- loadProceduresColumns(config, procedures);
-
- for (Procedure procedure : procedures.values()) {
- dataMap.addProcedure(procedure);
- }
-
- return procedures;
- }
-
- private void loadProceduresColumns(DbLoaderConfiguration config, Map<String, Procedure> procedures)
- throws SQLException {
-
- for (CatalogFilter catalog : config.getFiltersConfig().catalogs) {
- for (SchemaFilter schema : catalog.schemas) {
- loadProceduresColumns(procedures, catalog.name, schema.name);
- }
- }
- }
-
- private void loadProceduresColumns(Map<String, Procedure> procedures, String catalog, String schema)
- throws SQLException {
-
- try (ResultSet columnsRS = getMetaData().getProcedureColumns(catalog, schema, null, null);) {
- while (columnsRS.next()) {
-
- String s = columnsRS.getString("PROCEDURE_SCHEM");
- String name = columnsRS.getString("PROCEDURE_NAME");
- String key = (s == null ? "" : s + '.') + name;
- Procedure procedure = procedures.get(key);
- if (procedure == null) {
- continue;
- }
-
- ProcedureParameter column = loadProcedureParams(columnsRS, key, procedure);
- if (column == null) {
- continue;
- }
- procedure.addCallParameter(column);
- }
- }
- }
-
- private ProcedureParameter loadProcedureParams(ResultSet columnsRS, String key, Procedure procedure)
- throws SQLException {
- String columnName = columnsRS.getString("COLUMN_NAME");
-
- // skip ResultSet columns, as they are not described in Cayenne
- // procedures yet...
- short type = columnsRS.getShort("COLUMN_TYPE");
- if (type == DatabaseMetaData.procedureColumnResult) {
- LOGGER.debug("skipping ResultSet column: " + key + "." + columnName);
- }
-
- if (columnName == null) {
- if (type == DatabaseMetaData.procedureColumnReturn) {
- LOGGER.debug("null column name, assuming result column: " + key);
- columnName = "_return_value";
- procedure.setReturningValue(true);
- } else {
- LOGGER.info("invalid null column name, skipping column : " + key);
- return null;
- }
- }
-
- int columnType = columnsRS.getInt("DATA_TYPE");
-
- // ignore precision of non-decimal columns
- int decimalDigits = -1;
- if (TypesMapping.isDecimal(columnType)) {
- decimalDigits = columnsRS.getShort("SCALE");
- if (columnsRS.wasNull()) {
- decimalDigits = -1;
- }
- }
-
- ProcedureParameter column = new ProcedureParameter(columnName);
- int direction = getDirection(type);
- if (direction != -1) {
- column.setDirection(direction);
- }
-
- column.setType(columnType);
- column.setMaxLength(columnsRS.getInt("LENGTH"));
- column.setPrecision(decimalDigits);
-
- column.setProcedure(procedure);
- return column;
- }
-
- private static int getDirection(short type) {
- switch (type) {
- case DatabaseMetaData.procedureColumnIn:
- return ProcedureParameter.IN_PARAMETER;
- case DatabaseMetaData.procedureColumnInOut:
- return ProcedureParameter.IN_OUT_PARAMETER;
- case DatabaseMetaData.procedureColumnOut:
- return ProcedureParameter.OUT_PARAMETER;
- default:
- return -1;
- }
- }
-
- private Map<String, Procedure> loadProcedures(DbLoaderConfiguration config) throws SQLException {
- Map<String, Procedure> procedures = new HashMap<>();
-
- FiltersConfig filters = config.getFiltersConfig();
- for (CatalogFilter catalog : filters.catalogs) {
- for (SchemaFilter schema : catalog.schemas) {
- if (filters.proceduresFilter(catalog.name, schema.name).isEmpty()) {
- continue;
- }
-
- procedures.putAll(loadProcedures(filters, catalog.name, schema.name));
- }
- }
-
- return procedures;
- }
-
- private Map<String, Procedure> loadProcedures(FiltersConfig filters, String catalog, String schema)
- throws SQLException {
- Map<String, Procedure> procedures = new HashMap<>();
- // get procedures
-
- try (ResultSet rs = getMetaData().getProcedures(catalog, schema, WILDCARD);) {
- while (rs.next()) {
-
- String name = rs.getString("PROCEDURE_NAME");
- Procedure procedure = new Procedure(name);
- procedure.setCatalog(rs.getString("PROCEDURE_CAT"));
- procedure.setSchema(rs.getString("PROCEDURE_SCHEM"));
-
- if (!filters.proceduresFilter(procedure.getCatalog(), procedure.getSchema()).isInclude(
- procedure.getName())) {
- LOGGER.info("skipping Cayenne PK procedure: " + name);
- continue;
- }
-
- switch (rs.getShort("PROCEDURE_TYPE")) {
- case DatabaseMetaData.procedureNoResult:
- case DatabaseMetaData.procedureResultUnknown:
- procedure.setReturningValue(false);
- break;
- case DatabaseMetaData.procedureReturnsResult:
- procedure.setReturningValue(true);
- break;
- }
-
- procedures.put(procedure.getFullyQualifiedName(), procedure);
- }
- }
- return procedures;
- }
-
- /**
- * Sets new naming strategy for reverse engineering
- *
- * @since 3.0
- */
- public void setNameGenerator(ObjectNameGenerator strategy) {
- if (strategy == null) {
- LOGGER.warn("Attempt to set null into NameGenerator. LegacyNameGenerator will be used.");
- this.nameGenerator = new LegacyNameGenerator();
- } else {
- this.nameGenerator = strategy;
- }
- }
-
- /**
- * @return naming strategy for reverse engineering
- * @since 3.0
- */
- public ObjectNameGenerator getNameGenerator() {
- return nameGenerator;
- }
-}
\ No newline at end of file
[02/15] cayenne git commit: CAY-2116 Split schema synchronization
code in a separate module
Posted by aa...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/TokensReversTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/TokensReversTest.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/TokensReversTest.java
deleted file mode 100644
index e13531e..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/TokensReversTest.java
+++ /dev/null
@@ -1,88 +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.merge;
-
-import org.apache.cayenne.dba.hsqldb.HSQLMergerFactory;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbJoin;
-import org.apache.cayenne.map.DbRelationship;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.Collections;
-
-import static org.apache.cayenne.merge.builders.ObjectMother.dbAttr;
-import static org.apache.cayenne.merge.builders.ObjectMother.dbEntity;
-
-/**
- * @since 4.0.
- */
-public class TokensReversTest {
-
- @Test
- public void testReverses() {
- DbAttribute attr = dbAttr().build();
- DbEntity entity = dbEntity().attributes(attr).build();
- DbRelationship rel = new DbRelationship("rel");
- rel.setSourceEntity(entity);
- rel.addJoin(new DbJoin(rel, attr.getName(), "dontKnow"));
-
- test(factory().createAddColumnToDb(entity, attr));
- test(factory().createAddColumnToModel(entity, attr));
- test(factory().createDropColumnToDb(entity, attr));
- test(factory().createDropColumnToModel(entity, attr));
-
- test(factory().createAddRelationshipToDb(entity, rel));
- test(factory().createAddRelationshipToModel(entity, rel));
- test(factory().createDropRelationshipToDb(entity, rel));
- test(factory().createDropRelationshipToModel(entity, rel));
-
- test(factory().createCreateTableToDb(entity));
- test(factory().createCreateTableToModel(entity));
- test(factory().createDropTableToDb(entity));
- test(factory().createDropTableToModel(entity));
-
- test(factory().createSetAllowNullToDb(entity, attr));
- test(factory().createSetAllowNullToModel(entity, attr));
- test(factory().createSetNotNullToDb(entity, attr));
- test(factory().createSetNotNullToModel(entity, attr));
-
- DbAttribute attr2 = dbAttr().build();
- test(factory().createSetColumnTypeToDb(entity, attr, attr2));
- test(factory().createSetColumnTypeToModel(entity, attr, attr2));
-
- test(factory().createSetPrimaryKeyToDb(entity, Collections.singleton(attr), Collections.singleton(attr2), "PK"));
- test(factory().createSetPrimaryKeyToModel(entity, Collections.singleton(attr), Collections.singleton(attr2), "PK"));
-
- test(factory().createSetValueForNullToDb(entity, attr, new DefaultValueForNullProvider()));
- }
-
- private void test(MergerToken token1) {
- MergerToken token2 = token1.createReverse(factory()).createReverse(factory());
-
- Assert.assertEquals(token1.getTokenName(), token2.getTokenName());
- Assert.assertEquals(token1.getTokenValue(), token2.getTokenValue());
- Assert.assertEquals(token1.getDirection(), token2.getDirection());
- }
-
- private MergerFactory factory() {
- return new HSQLMergerFactory();
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/TokensToModelExecution.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/TokensToModelExecution.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/TokensToModelExecution.java
deleted file mode 100644
index 094914b..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/TokensToModelExecution.java
+++ /dev/null
@@ -1,83 +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.merge;
-
-import org.apache.cayenne.access.DataNode;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.junit.Test;
-
-import static org.apache.cayenne.merge.builders.ObjectMother.dataMap;
-import static org.apache.cayenne.merge.builders.ObjectMother.dbAttr;
-import static org.apache.cayenne.merge.builders.ObjectMother.dbEntity;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-/**
- * @since 4.0.
- */
-public class TokensToModelExecution {
-
- @Test
- public void testCreateAndDropTable() throws Exception {
- DbEntity entity = dbEntity().build();
-
- DataMap dataMap = dataMap().build();
- assertTrue(dataMap.getDbEntityMap().isEmpty());
- assertTrue(dataMap.getObjEntityMap().isEmpty());
-
- MergerContext context = MergerContext.builder(dataMap).dataNode(new DataNode()).build();
- factory().createCreateTableToModel(entity).execute(context);
-
- assertEquals(1, dataMap.getDbEntityMap().size());
- assertEquals(1, dataMap.getObjEntities().size());
- assertEquals(entity, dataMap.getDbEntity(entity.getName()));
-
- factory().createDropTableToModel(entity).execute(context);
- assertTrue(dataMap.getDbEntityMap().isEmpty());
- assertTrue(dataMap.getObjEntityMap().isEmpty());
- }
-
- @Test
- public void testCreateAndDropColumn() throws Exception {
- DbAttribute attr = dbAttr("attr").build();
- DbEntity entity = dbEntity().build();
-
- DataMap dataMap = dataMap().with(entity).build();
- assertEquals(1, dataMap.getDbEntityMap().size());
- assertTrue(dataMap.getObjEntityMap().isEmpty());
-
- MergerContext context = MergerContext.builder(dataMap).dataNode(new DataNode()).build();
- factory().createAddColumnToModel(entity, attr).execute(context);
-
- assertEquals(1, dataMap.getDbEntityMap().size());
- assertEquals(1, entity.getAttributes().size());
- assertEquals(attr, entity.getAttribute(attr.getName()));
-
- factory().createDropColumnToModel(entity, attr).execute(context);
- assertEquals(1, dataMap.getDbEntityMap().size());
- assertTrue(entity.getAttributes().isEmpty());
- assertTrue(dataMap.getObjEntityMap().isEmpty());
- }
-
- private MergerFactory factory() {
- return new MergerFactory();
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/ValueForNullIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/ValueForNullIT.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/ValueForNullIT.java
deleted file mode 100644
index fb43eb3..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/ValueForNullIT.java
+++ /dev/null
@@ -1,128 +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.merge;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.sql.Types;
-import java.util.List;
-
-import junit.framework.AssertionFailedError;
-
-import org.apache.cayenne.DataObject;
-import org.apache.cayenne.Persistent;
-import org.apache.cayenne.access.DataContext;
-import org.apache.cayenne.access.jdbc.SQLParameterBinding;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.exp.Expression;
-import org.apache.cayenne.exp.ExpressionFactory;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.ObjAttribute;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.query.SelectQuery;
-import org.junit.Test;
-
-public class ValueForNullIT extends MergeCase {
-
- private static final String DEFAULT_VALUE_STRING = "DEFSTRING";
-
- @Inject
- private DataContext context;
-
- @Test
- public void test() throws Exception {
- DbEntity dbEntity = map.getDbEntity("PAINTING");
- assertNotNull(dbEntity);
- ObjEntity objEntity = map.getObjEntity("Painting");
- assertNotNull(objEntity);
-
- // insert some rows before adding "not null" column
- final int nrows = 10;
- for (int i = 0; i < nrows; i++) {
- DataObject o = (DataObject) context.newObject("Painting");
- o.writeProperty("paintingTitle", "ptitle" + i);
- }
- context.commitChanges();
-
- // create and add new column to model and db
- DbAttribute column = new DbAttribute("NEWCOL2", Types.VARCHAR, dbEntity);
-
- column.setMandatory(false);
- column.setMaxLength(10);
- dbEntity.addAttribute(column);
- assertTrue(dbEntity.getAttributes().contains(column));
- assertEquals(column, dbEntity.getAttribute(column.getName()));
- assertTokensAndExecute(1, 0);
-
- // need obj attr to be able to query
- ObjAttribute objAttr = new ObjAttribute("newcol2");
- objAttr.setDbAttributePath(column.getName());
- objEntity.addAttribute(objAttr);
-
- // check that is was merged
- assertTokensAndExecute(0, 0);
-
- // set not null
- column.setMandatory(true);
-
- // merge to db
- assertTokensAndExecute(2, 0);
-
- // check that is was merged
- assertTokensAndExecute(0, 0);
-
- // check values for null
- Expression qual = ExpressionFactory.matchExp(objAttr.getName(), DEFAULT_VALUE_STRING);
- SelectQuery query = new SelectQuery("Painting", qual);
- List<Persistent> rows = context.performQuery(query);
- assertEquals(nrows, rows.size());
-
- // clean up
- dbEntity.removeAttribute(column.getName());
- assertTokensAndExecute(1, 0);
- assertTokensAndExecute(0, 0);
- }
-
- @Override
- protected DbMerger createMerger(MergerFactory mergerFactory, final ValueForNullProvider valueForNullProvider) {
- return super.createMerger(mergerFactory, new DefaultValueForNullProvider() {
-
- @Override
- protected SQLParameterBinding get(DbEntity entity, DbAttribute column) {
- int type = column.getType();
- switch (type) {
- case Types.VARCHAR:
- return new SQLParameterBinding(DEFAULT_VALUE_STRING, type, -1);
- default:
- throw new AssertionFailedError("should not get here");
- }
- }
-
- @Override
- public boolean hasValueFor(DbEntity entity, DbAttribute column) {
- return true;
- }
-
- });
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/Builder.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/Builder.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/Builder.java
deleted file mode 100644
index fd379c7..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/Builder.java
+++ /dev/null
@@ -1,38 +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.merge.builders;
-
-/**
- * Base interface for all domain builders
- *
- * @since 4.0.
- */
-public interface Builder<T> {
-
- /**
- * Build valid object. If some required data omitted it will be filled with random data.
- * */
- T build();
-
- /**
- * Build valid object and add some optional fields randomly.
- * */
- T random();
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DataMapBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DataMapBuilder.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DataMapBuilder.java
deleted file mode 100644
index 662ba2a..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DataMapBuilder.java
+++ /dev/null
@@ -1,128 +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.merge.builders;
-
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.map.ObjEntity;
-
-import java.util.Collections;
-
-/**
- * @since 4.0.
- */
-public class DataMapBuilder extends DefaultBuilder<DataMap> {
-
- public DataMapBuilder() {
- this(new DataMap());
- }
-
- public DataMapBuilder(DataMap dataMap) {
- super(dataMap);
- }
-
- public DataMapBuilder with(DbEntity ... entities) {
- for (DbEntity entity : entities) {
- obj.addDbEntity(entity);
- }
-
- return this;
- }
-
- public DataMapBuilder with(DbEntityBuilder ... entities) {
- for (DbEntityBuilder entity : entities) {
- obj.addDbEntity(entity.build());
- }
-
- return this;
- }
-
- public DataMapBuilder withDbEntities(int count) {
- for (int i = 0; i < count; i++) {
- obj.addDbEntity(ObjectMother.dbEntity().random());
- }
-
- return this;
- }
-
- public DataMapBuilder with(ObjEntity... entities) {
- for (ObjEntity entity : entities) {
- obj.addObjEntity(entity);
- }
-
- return this;
- }
-
- public DataMapBuilder with(ObjEntityBuilder ... entities) {
- for (ObjEntityBuilder entity : entities) {
- obj.addObjEntity(entity.build());
- }
-
- return this;
- }
-
- public DataMapBuilder withObjEntities(int count) {
- for (int i = 0; i < count; i++) {
- obj.addObjEntity(ObjectMother.objEntity().random());
- }
-
- return this;
- }
-
- public DataMapBuilder join(String from, String to) {
- return join(null, from, to);
- }
-
- public DataMapBuilder join(String name, String from, String to) {
- String[] fromSplit = from.split("\\.");
- DbEntity fromEntity = obj.getDbEntity(fromSplit[0]);
- if (fromEntity == null) {
- throw new IllegalArgumentException("Entity '" + fromSplit[0] + "' is undefined");
- }
-
- String[] toSplit = to.split("\\.");
-
- fromEntity.addRelationship(new DbRelationshipBuilder(name)
- .from(fromEntity, fromSplit[1])
- .to(toSplit[0], toSplit[1])
-
- .build());
-
- return this;
- }
-
- public DataMap build() {
- if (obj.getNamespace() == null) {
- obj.setNamespace(new EntityResolver(Collections.singleton(obj)));
- }
-
- return obj;
- }
-
- @Override
- public DataMap random() {
- if (dataFactory.chance(90)) {
- withDbEntities(dataFactory.getNumberUpTo(10));
- }
-
-
- return build();
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DbAttributeBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DbAttributeBuilder.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DbAttributeBuilder.java
deleted file mode 100644
index 1682b50..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DbAttributeBuilder.java
+++ /dev/null
@@ -1,115 +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.merge.builders;
-
-import org.apache.cayenne.datafactory.DictionaryValueProvider;
-import org.apache.cayenne.datafactory.ValueProvider;
-import org.apache.cayenne.dba.TypesMapping;
-import org.apache.cayenne.map.DbAttribute;
-
-import static org.apache.commons.lang.StringUtils.isEmpty;
-
-/**
- * @since 4.0.
- */
-public class DbAttributeBuilder extends DefaultBuilder<DbAttribute> {
-
- private static final ValueProvider<String> TYPES_RANDOM = new DictionaryValueProvider<String>(ValueProvider.RANDOM) {
- @Override
- protected String[] values() {
- return TypesMapping.getDatabaseTypes();
- }
- };
-
- public DbAttributeBuilder() {
- super(new DbAttribute());
- }
-
- public DbAttributeBuilder name() {
- return name(getRandomJavaName());
- }
-
- public DbAttributeBuilder name(String name) {
- obj.setName(name);
-
- return this;
- }
-
- public DbAttributeBuilder type() {
- return type(TYPES_RANDOM.randomValue());
- }
-
- public DbAttributeBuilder type(String item) {
- obj.setType(TypesMapping.getSqlTypeByName(item));
-
- return this;
- }
-
- public DbAttributeBuilder typeInt() {
- return type(TypesMapping.SQL_INTEGER);
- }
-
- public DbAttributeBuilder typeBigInt() {
- return type(TypesMapping.SQL_BIGINT);
- }
-
- public DbAttributeBuilder typeVarchar(int length) {
- type(TypesMapping.SQL_VARCHAR);
- length(length);
-
- return this;
- }
-
- private DbAttributeBuilder length(int length) {
- obj.setMaxLength(length);
-
- return this;
- }
-
- public DbAttributeBuilder primaryKey() {
- obj.setPrimaryKey(true);
-
- return this;
- }
-
- public DbAttributeBuilder mandatory() {
- obj.setMandatory(true);
-
- return this;
- }
-
- @Override
- public DbAttribute build() {
- if (isEmpty(obj.getName())) {
- name();
- }
-
- if (obj.getType() == TypesMapping.NOT_DEFINED) {
- type();
- }
-
- return obj;
- }
-
- @Override
- public DbAttribute random() {
- return build();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DbEntityBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DbEntityBuilder.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DbEntityBuilder.java
deleted file mode 100644
index 9cbd456..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DbEntityBuilder.java
+++ /dev/null
@@ -1,90 +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.merge.builders;
-
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.commons.lang.StringUtils;
-
-/**
- * @since 4.0.
- */
-public class DbEntityBuilder extends DefaultBuilder<DbEntity> {
-
- public DbEntityBuilder() {
- super(new DbEntity());
- }
-
- public DbEntityBuilder name() {
- return name(getRandomJavaName());
- }
-
- public DbEntityBuilder name(String name) {
- obj.setName(name);
-
- return this;
- }
-
- public DbEntityBuilder attributes(DbAttribute ... attributes) {
- for (DbAttribute attribute : attributes) {
- obj.addAttribute(attribute);
- }
-
- return this;
- }
-
- public DbEntityBuilder attributes(DbAttributeBuilder ... attributes) {
- for (DbAttributeBuilder attribute : attributes) {
- obj.addAttribute(attribute.build());
- }
-
- return this;
- }
-
- public DbEntityBuilder attributes(int numberUpTo) {
- for (int i = 0; i < numberUpTo; i++) {
- try {
- obj.addAttribute(new DbAttributeBuilder().random());
- } catch (IllegalArgumentException e) {
- i--; // try again
- }
- }
-
- return this;
- }
-
-
- @Override
- public DbEntity build() {
- if (obj.getName() == null) {
- obj.setName(StringUtils.capitalize(getRandomJavaName()));
- }
-
- return obj;
- }
-
- @Override
- public DbEntity random() {
- if (dataFactory.chance(99)) {
- attributes(dataFactory.getNumberUpTo(20));
- }
-
- return build();
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DbRelationshipBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DbRelationshipBuilder.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DbRelationshipBuilder.java
deleted file mode 100644
index 2bf5dba..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DbRelationshipBuilder.java
+++ /dev/null
@@ -1,85 +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.merge.builders;
-
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbJoin;
-import org.apache.cayenne.map.DbRelationship;
-
-/**
- * @since 4.0.
- */
-public class DbRelationshipBuilder extends DefaultBuilder<DbRelationship> {
-
- private String[] from;
- private String[] to;
-
- public DbRelationshipBuilder() {
- super(new DbRelationship());
- }
-
- public DbRelationshipBuilder(String name) {
- super(new DbRelationship(name));
- }
-
- public DbRelationshipBuilder(DbRelationship obj) {
- super(obj);
- }
-
- public DbRelationshipBuilder name() {
- return name(getRandomJavaName());
- }
-
- public DbRelationshipBuilder name(String name) {
- obj.setName(name);
-
- return this;
- }
-
- public DbRelationshipBuilder from(DbEntity entity, String ... columns) {
- obj.setSourceEntity(entity);
- this.from = columns;
-
- return this;
- }
-
- public DbRelationshipBuilder to(String entityName, String ... columns) {
- obj.setTargetEntityName(entityName);
- this.to = columns;
-
- return this;
- }
-
- @Override
- public DbRelationship build() {
- if (obj.getName() == null) {
- name();
- }
-
- if (from.length != to.length) {
- throw new IllegalStateException("from and to columns name size mismatch");
- }
-
- for (int i = 0; i < from.length; i++) {
- obj.addJoin(new DbJoin(obj, from[i], to[i]));
- }
-
- return obj;
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DefaultBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DefaultBuilder.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DefaultBuilder.java
deleted file mode 100644
index 5e9cea2..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DefaultBuilder.java
+++ /dev/null
@@ -1,57 +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.merge.builders;
-
-import org.apache.cayenne.datafactory.DataFactory;
-import org.apache.commons.lang.StringUtils;
-
-/**
- * @since 4.0.
- */
-public abstract class DefaultBuilder<T> implements Builder<T> {
-
- protected final DataFactory dataFactory;
- protected final T obj;
-
-
- protected DefaultBuilder(T obj) {
- this.dataFactory = new DataFactory();
- this.obj = obj;
- }
-
- public String getRandomJavaName() {
- int count = dataFactory.getNumberBetween(1, 5);
- StringBuilder res = new StringBuilder();
- for (int i = 0; i < count; i++) {
- res.append(StringUtils.capitalize(dataFactory.getRandomWord()));
- }
-
- return StringUtils.uncapitalize(res.toString());
- }
-
- @Override
- public T build() {
- return obj;
- }
-
- @Override
- public T random() {
- return build();
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/ObjAttributeBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/ObjAttributeBuilder.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/ObjAttributeBuilder.java
deleted file mode 100644
index 6a74936..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/ObjAttributeBuilder.java
+++ /dev/null
@@ -1,67 +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.merge.builders;
-
-import org.apache.cayenne.map.ObjAttribute;
-
-/**
- * @since 4.0.
- */
-public class ObjAttributeBuilder extends DefaultBuilder<ObjAttribute> {
-
- public ObjAttributeBuilder() {
- super(new ObjAttribute());
- }
-
- public ObjAttributeBuilder name() {
- return name(getRandomJavaName());
- }
-
- public ObjAttributeBuilder name(String name) {
- obj.setName(name);
-
- return this;
- }
-
- public ObjAttributeBuilder type(Class type) {
- obj.setType(type.getCanonicalName());
-
- return this;
- }
-
- public ObjAttributeBuilder dbPath(String path) {
- obj.setDbAttributePath(path);
-
- return this;
- }
-
- @Override
- public ObjAttribute build() {
- if (obj.getName() == null) {
- name();
- }
-
- return obj;
- }
-
- @Override
- public ObjAttribute random() {
- return build();
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/ObjEntityBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/ObjEntityBuilder.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/ObjEntityBuilder.java
deleted file mode 100644
index dc78b29..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/ObjEntityBuilder.java
+++ /dev/null
@@ -1,98 +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.merge.builders;
-
-import org.apache.cayenne.map.ObjAttribute;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.commons.lang.StringUtils;
-
-/**
- * @since 4.0.
- */
-public class ObjEntityBuilder extends DefaultBuilder<ObjEntity> {
-
- public ObjEntityBuilder() {
- super(new ObjEntity());
- }
-
- public ObjEntityBuilder name() {
- return name(getRandomJavaName());
- }
-
- public ObjEntityBuilder name(String name) {
- obj.setName(name);
-
- return this;
- }
-
- public ObjEntityBuilder attributes(ObjAttribute... attributes) {
- for (ObjAttribute attribute : attributes) {
- obj.addAttribute(attribute);
- }
-
- return this;
- }
-
- public ObjEntityBuilder attributes(ObjAttributeBuilder ... attributes) {
- for (ObjAttributeBuilder attribute : attributes) {
- obj.addAttribute(attribute.build());
- }
-
- return this;
- }
-
- public ObjEntityBuilder attributes(int numberUpTo) {
- for (int i = 0; i < numberUpTo; i++) {
- obj.addAttribute(new ObjAttributeBuilder().random());
- }
-
- return this;
- }
-
-
- @Override
- public ObjEntity build() {
- if (obj.getName() == null) {
- obj.setName(StringUtils.capitalize(getRandomJavaName()));
- }
-
- return obj;
- }
-
- @Override
- public ObjEntity random() {
- if (dataFactory.chance(99)) {
- attributes(dataFactory.getNumberUpTo(20));
- }
-
- return build();
- }
-
- public ObjEntityBuilder clazz(String s) {
- obj.setClassName(s);
-
- return this;
- }
-
- public ObjEntityBuilder dbEntity(String table) {
- obj.setDbEntityName(table);
-
- return this;
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/ObjectMother.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/ObjectMother.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/ObjectMother.java
deleted file mode 100644
index 76ed761..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/ObjectMother.java
+++ /dev/null
@@ -1,70 +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.merge.builders;
-
-import org.apache.cayenne.map.DataMap;
-
-/**
- * Factory for test data see pattern definition:
- * http://martinfowler.com/bliki/ObjectMother.html
- *
- * @since 4.0.
- */
-public class ObjectMother {
-
- public static DataMapBuilder dataMap() {
- return new DataMapBuilder();
- }
-
- public static DataMapBuilder dataMap(DataMap dataMap) {
- return new DataMapBuilder(dataMap);
- }
-
- public static DbEntityBuilder dbEntity() {
- return new DbEntityBuilder();
- }
-
- public static DbEntityBuilder dbEntity(String name) {
- return new DbEntityBuilder().name(name);
- }
-
- public static ObjEntityBuilder objEntity() {
- return new ObjEntityBuilder();
- }
-
- public static ObjEntityBuilder objEntity(String packageName, String className, String table) {
- return new ObjEntityBuilder()
- .name(className)
- .clazz(packageName + "." + className)
- .dbEntity(table);
- }
-
- public static ObjAttributeBuilder objAttr(String name) {
- return new ObjAttributeBuilder().name(name);
- }
-
- public static DbAttributeBuilder dbAttr(String name) {
- return dbAttr().name(name);
- }
-
- public static DbAttributeBuilder dbAttr() {
- return new DbAttributeBuilder();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerRuntimeProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerRuntimeProvider.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerRuntimeProvider.java
index 29820e0..79c02cf 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerRuntimeProvider.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerRuntimeProvider.java
@@ -29,6 +29,9 @@ import org.apache.cayenne.di.Module;
import org.apache.cayenne.di.Provider;
import org.apache.cayenne.unit.UnitDbAdapter;
+import java.util.Collection;
+import java.util.Collections;
+
public class ServerRuntimeProvider implements Provider<ServerRuntime> {
private ServerCaseProperties properties;
@@ -48,6 +51,7 @@ public class ServerRuntimeProvider implements Provider<ServerRuntime> {
this.unitDbAdapter = unitDbAdapter;
}
+ @Override
public ServerRuntime get() throws ConfigurationException {
String configurationLocation = properties.getConfigurationLocation();
@@ -56,11 +60,18 @@ public class ServerRuntimeProvider implements Provider<ServerRuntime> {
+ "annotate your test case with @UseServerRuntime");
}
- return new ServerRuntime(configurationLocation, new ServerExtraModule());
+ Collection<? extends Module> modules = getExtraModules();
+
+ return new ServerRuntime(configurationLocation, modules.toArray(new Module[modules.size()]));
+ }
+
+ protected Collection<? extends Module> getExtraModules() {
+ return Collections.singleton(new ServerExtraModule());
}
class ServerExtraModule implements Module {
+ @Override
public void configure(Binder binder) {
// these are the objects overriding standard ServerModule definitions or
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/util/EntityMergeSupportIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/util/EntityMergeSupportIT.java b/cayenne-server/src/test/java/org/apache/cayenne/util/EntityMergeSupportIT.java
deleted file mode 100644
index e3f1bc3..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/util/EntityMergeSupportIT.java
+++ /dev/null
@@ -1,103 +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.util;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-
-import java.sql.Types;
-import java.util.Arrays;
-
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbJoin;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.DeleteRule;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.merge.MergeCase;
-import org.junit.Test;
-
-public class EntityMergeSupportIT extends MergeCase {
-
- @Test
- public void testMerging() {
- DbEntity dbEntity1 = new DbEntity("NEW_TABLE");
-
- DbAttribute e1col1 = new DbAttribute("ID", Types.INTEGER, dbEntity1);
- e1col1.setMandatory(true);
- e1col1.setPrimaryKey(true);
- dbEntity1.addAttribute(e1col1);
-
- DbAttribute e1col2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity1);
- e1col2.setMaxLength(10);
- e1col2.setMandatory(false);
- dbEntity1.addAttribute(e1col2);
-
- map.addDbEntity(dbEntity1);
-
- DbEntity dbEntity2 = new DbEntity("NEW_TABLE2");
- DbAttribute e2col1 = new DbAttribute("ID", Types.INTEGER, dbEntity2);
- e2col1.setMandatory(true);
- e2col1.setPrimaryKey(true);
- dbEntity2.addAttribute(e2col1);
- DbAttribute e2col2 = new DbAttribute("FK", Types.INTEGER, dbEntity2);
- dbEntity2.addAttribute(e2col2);
-
- map.addDbEntity(dbEntity2);
-
- // create db relationships
- DbRelationship rel1To2 = new DbRelationship("rel1To2");
- rel1To2.setSourceEntity(dbEntity1);
- rel1To2.setTargetEntityName(dbEntity2);
- rel1To2.setToMany(true);
- rel1To2.addJoin(new DbJoin(rel1To2, e1col1.getName(), e2col2.getName()));
- dbEntity1.addRelationship(rel1To2);
- DbRelationship rel2To1 = new DbRelationship("rel2To1");
- rel2To1.setSourceEntity(dbEntity2);
- rel2To1.setTargetEntityName(dbEntity1);
- rel2To1.setToMany(false);
- rel2To1.addJoin(new DbJoin(rel2To1, e2col2.getName(), e1col1.getName()));
- dbEntity2.addRelationship(rel2To1);
- assertSame(rel1To2, rel2To1.getReverseRelationship());
- assertSame(rel2To1, rel1To2.getReverseRelationship());
-
- ObjEntity objEntity1 = new ObjEntity("NewTable");
- objEntity1.setDbEntity(dbEntity1);
- map.addObjEntity(objEntity1);
-
- ObjEntity objEntity2 = new ObjEntity("NewTable2");
- objEntity2.setDbEntity(dbEntity2);
- map.addObjEntity(objEntity2);
-
- assertTrue(new EntityMergeSupport(map).synchronizeWithDbEntities(Arrays.asList(objEntity1, objEntity2)));
- assertNotNull(objEntity1.getAttribute("name"));
- assertNotNull(objEntity1.getRelationship("rel1To2"));
- assertNotNull(objEntity2.getRelationship("rel2To1"));
-
- assertEquals(objEntity1.getRelationship("rel1To2").getDeleteRule(), DeleteRule.DEFAULT_DELETE_RULE_TO_MANY);
- assertEquals(objEntity2.getRelationship("rel2To1").getDeleteRule(), DeleteRule.DEFAULT_DELETE_RULE_TO_ONE);
-
- map.removeObjEntity(objEntity2.getName());
- map.removeObjEntity(objEntity1.getName());
- map.removeDbEntity(dbEntity2.getName());
- map.removeDbEntity(dbEntity1.getName());
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/resources/org/apache/cayenne/access/loader/cayenne-relationship-optimisation.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/access/loader/cayenne-relationship-optimisation.xml b/cayenne-server/src/test/resources/org/apache/cayenne/access/loader/cayenne-relationship-optimisation.xml
deleted file mode 100644
index d4fea49..0000000
--- a/cayenne-server/src/test/resources/org/apache/cayenne/access/loader/cayenne-relationship-optimisation.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<domain project-version="6">
- <map name="relationship-optimisation"/>
-</domain>
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/resources/org/apache/cayenne/access/loader/relationship-optimisation.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/resources/org/apache/cayenne/access/loader/relationship-optimisation.map.xml b/cayenne-server/src/test/resources/org/apache/cayenne/access/loader/relationship-optimisation.map.xml
deleted file mode 100644
index e68645f..0000000
--- a/cayenne-server/src/test/resources/org/apache/cayenne/access/loader/relationship-optimisation.map.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<data-map xmlns="http://cayenne.apache.org/schema/3.0/modelMap"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://cayenne.apache.org/schema/3.0/modelMap http://cayenne.apache.org/schema/3.0/modelMap.xsd"
- project-version="6">
- <property name="defaultPackage" value="com.objectstyle"/>
- <db-entity name="table1" catalog="many_to_many_test">
- <db-attribute name="id1" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
- <db-attribute name="table1col" type="VARCHAR" length="45"/>
- </db-entity>
- <db-entity name="table1_table2" catalog="many_to_many_test">
- <db-attribute name="fk1" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
- <db-attribute name="fk2" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
- </db-entity>
- <db-entity name="table2" catalog="many_to_many_test">
- <db-attribute name="id2" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
- <db-attribute name="table2col" type="VARCHAR" length="45"/>
- </db-entity>
- <obj-entity name="Table1" className="com.objectstyle.Table1" dbEntityName="table1">
- <obj-attribute name="table1col" type="java.lang.String" db-attribute-path="table1col"/>
- </obj-entity>
- <obj-entity name="Table1Table2" className="com.objectstyle.Table1Table2" dbEntityName="table1_table2">
- </obj-entity>
- <obj-entity name="Table2" className="com.objectstyle.Table2" dbEntityName="table2">
- <obj-attribute name="table2col" type="java.lang.String" db-attribute-path="table2col"/>
- </obj-entity>
- <db-relationship name="table1Table2Array" source="table1" target="table1_table2" toDependentPK="true" toMany="true">
- <db-attribute-pair source="id1" target="fk1"/>
- </db-relationship>
- <db-relationship name="toTable1" source="table1_table2" target="table1" toMany="false">
- <db-attribute-pair source="fk1" target="id1"/>
- </db-relationship>
- <db-relationship name="toTable2" source="table1_table2" target="table2" toMany="false">
- <db-attribute-pair source="fk2" target="id2"/>
- </db-relationship>
- <db-relationship name="table1Table2Array" source="table2" target="table1_table2" toDependentPK="true" toMany="true">
- <db-attribute-pair source="id2" target="fk2"/>
- </db-relationship>
- <obj-relationship name="table1Table2Array" source="Table1" target="Table1Table2" deleteRule="Deny" db-relationship-path="table1Table2Array"/>
- <obj-relationship name="toTable1" source="Table1Table2" target="Table1" deleteRule="Nullify" db-relationship-path="toTable1"/>
- <obj-relationship name="toTable2" source="Table1Table2" target="Table2" deleteRule="Nullify" db-relationship-path="toTable2"/>
- <obj-relationship name="table1Table2Array" source="Table2" target="Table1Table2" deleteRule="Deny" db-relationship-path="table1Table2Array"/>
-</data-map>
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-tools/pom.xml
----------------------------------------------------------------------
diff --git a/cayenne-tools/pom.xml b/cayenne-tools/pom.xml
index 581c7df..15816c5 100644
--- a/cayenne-tools/pom.xml
+++ b/cayenne-tools/pom.xml
@@ -42,6 +42,13 @@
<scope>test</scope>
<type>test-jar</type>
</dependency>
+ <dependency>
+ <groupId>org.apache.cayenne</groupId>
+ <artifactId>cayenne-dbsync</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
<dependency>
<groupId>org.apache.cayenne.build-tools</groupId>
@@ -94,6 +101,13 @@
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.cayenne</groupId>
+ <artifactId>cayenne-dbsync</artifactId>
+ <version>${project.version}</version>
+ <scope>compile</scope>
+ </dependency>
+
<dependency>
<groupId>foundrylogic.vpp</groupId>
<artifactId>vpp</artifactId>
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-tools/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java b/cayenne-tools/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java
index f7471a6..e8b6b76 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java
@@ -18,18 +18,8 @@
****************************************************************/
package org.apache.cayenne.gen;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-
import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.access.loader.NamePatternMatcher;
+import org.apache.cayenne.dbsync.reverse.NamePatternMatcher;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.Embeddable;
import org.apache.cayenne.map.ObjEntity;
@@ -41,6 +31,16 @@ import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.log.NullLogSystem;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
public class ClassGenerationAction {
static final String TEMPLATES_DIR_NAME = "templates/v1_2/";
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-tools/src/main/java/org/apache/cayenne/tools/AntDataPortDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/AntDataPortDelegate.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/AntDataPortDelegate.java
index 828d744..3e98829 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/AntDataPortDelegate.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/AntDataPortDelegate.java
@@ -19,19 +19,19 @@
package org.apache.cayenne.tools;
-import java.util.Iterator;
-import java.util.List;
-import java.util.regex.Pattern;
-
import org.apache.cayenne.access.DataPort;
import org.apache.cayenne.access.DataPortDelegate;
-import org.apache.cayenne.access.loader.NamePatternMatcher;
+import org.apache.cayenne.dbsync.reverse.NamePatternMatcher;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.query.Query;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
+import java.util.Iterator;
+import java.util.List;
+import java.util.regex.Pattern;
+
/**
* DataPortDelegate implementation that works in the context of Ant DataPortTask
* task execution, performing entity filtering and logging functions.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEntityFilterAction.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEntityFilterAction.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEntityFilterAction.java
index 49329a7..08a39df 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEntityFilterAction.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEntityFilterAction.java
@@ -18,16 +18,16 @@
****************************************************************/
package org.apache.cayenne.tools;
+import org.apache.cayenne.dbsync.reverse.NameFilter;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.Embeddable;
+import org.apache.cayenne.map.ObjEntity;
+
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
-import org.apache.cayenne.access.loader.NameFilter;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.Embeddable;
-import org.apache.cayenne.map.ObjEntity;
-
/**
* Performs entity filtering to build a collection of entities that should be used in
* class generation.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
index 6ed29cb..6edcd6c 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
@@ -19,7 +19,7 @@
package org.apache.cayenne.tools;
import foundrylogic.vpp.VPPConfig;
-import org.apache.cayenne.access.loader.NamePatternMatcher;
+import org.apache.cayenne.dbsync.reverse.NamePatternMatcher;
import org.apache.cayenne.gen.ArtifactsGenerationMode;
import org.apache.cayenne.gen.ClassGenerationAction;
import org.apache.cayenne.gen.ClientClassGenerationAction;
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbGeneratorTask.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbGeneratorTask.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbGeneratorTask.java
index 5e0ab99..faa3653 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbGeneratorTask.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbGeneratorTask.java
@@ -19,12 +19,10 @@
package org.apache.cayenne.tools;
-import java.sql.Driver;
-import java.util.Collections;
-
import org.apache.cayenne.access.DbGenerator;
import org.apache.cayenne.datasource.DriverDataSource;
import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dbsync.CayenneDbSyncModule;
import org.apache.cayenne.di.DIBootstrap;
import org.apache.cayenne.di.Injector;
import org.apache.cayenne.log.NoopJdbcEventLogger;
@@ -36,6 +34,9 @@ import org.apache.commons.logging.Log;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
+import java.sql.Driver;
+import java.util.Collections;
+
/**
* An Ant Task that is a frontend to Cayenne DbGenerator allowing schema
* generation from DataMap using Ant.
@@ -68,7 +69,7 @@ public class DbGeneratorTask extends CayenneTask {
validateAttributes();
ClassLoader loader = null;
- Injector injector = DIBootstrap.createInjector(new ToolsModule(logger));
+ Injector injector = DIBootstrap.createInjector(new CayenneDbSyncModule(), new ToolsModule(logger));
try {
loader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(DbGeneratorTask.class.getClassLoader());
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-tools/src/main/java/org/apache/cayenne/tools/DbImporterTask.java
----------------------------------------------------------------------
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 e4fa545..f1797f1 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
@@ -18,7 +18,6 @@
****************************************************************/
package org.apache.cayenne.tools;
-import org.apache.cayenne.access.loader.filters.LegacyFilterConfigBridge;
import org.apache.cayenne.configuration.ConfigurationNameMapper;
import org.apache.cayenne.configuration.DataNodeDescriptor;
import org.apache.cayenne.configuration.XMLDataMapLoader;
@@ -32,12 +31,14 @@ import org.apache.cayenne.dbimport.DefaultReverseEngineeringLoader;
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.dbsync.CayenneDbSyncModule;
+import org.apache.cayenne.dbsync.reverse.FiltersConfigBuilder;
+import org.apache.cayenne.dbsync.reverse.filters.LegacyFilterConfigBridge;
import org.apache.cayenne.di.DIBootstrap;
import org.apache.cayenne.di.Injector;
import org.apache.cayenne.map.DataMap;
@@ -91,7 +92,7 @@ public class DbImporterTask extends Task {
config.setTableTypes(reverseEngineering.getTableTypes());
if (isReverseEngineeringDefined) {
- Injector injector = DIBootstrap.createInjector(new ToolsModule(logger), new DbImportModule());
+ Injector injector = DIBootstrap.createInjector(new CayenneDbSyncModule(), new ToolsModule(logger), new DbImportModule());
validateDbImportConfiguration(config, injector);
@@ -120,7 +121,7 @@ public class DbImporterTask extends Task {
XMLDataMapLoader xmlDataMapLoader = new XMLDataMapLoader();
DataMap dataMap = xmlDataMapLoader.load(resource);
if (dataMap.getReverseEngineering() != null) {
- Injector injector = DIBootstrap.createInjector(new ToolsModule(logger), new DbImportModule());
+ Injector injector = DIBootstrap.createInjector(new CayenneDbSyncModule(), new ToolsModule(logger), new DbImportModule());
try {
ConfigurationNameMapper nameMapper = injector.getInstance(ConfigurationNameMapper.class);
String reverseEngineeringLocation = nameMapper.configurationLocation(ReverseEngineering.class, dataMap.getReverseEngineering().getName());
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportConfiguration.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportConfiguration.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportConfiguration.java
index 0914fb5..e69905a 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportConfiguration.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportConfiguration.java
@@ -19,28 +19,28 @@
package org.apache.cayenne.tools.dbimport;
import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.access.DbLoader;
-import org.apache.cayenne.access.loader.DbLoaderConfiguration;
-import org.apache.cayenne.access.DbLoaderDelegate;
-import org.apache.cayenne.access.loader.DefaultDbLoaderDelegate;
-import org.apache.cayenne.access.loader.LoggingDbLoaderDelegate;
-import org.apache.cayenne.access.loader.NameFilter;
-import org.apache.cayenne.access.loader.filters.CatalogFilter;
-import org.apache.cayenne.access.loader.filters.FiltersConfig;
import org.apache.cayenne.configuration.DataNodeDescriptor;
import org.apache.cayenne.conn.DataSourceInfo;
import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dbsync.merge.DbMergerConfig;
+import org.apache.cayenne.dbsync.merge.DefaultModelMergeDelegate;
+import org.apache.cayenne.dbsync.merge.EntityMergeSupport;
+import org.apache.cayenne.dbsync.merge.ModelMergeDelegate;
+import org.apache.cayenne.dbsync.reverse.DbLoader;
+import org.apache.cayenne.dbsync.reverse.DbLoaderConfiguration;
+import org.apache.cayenne.dbsync.reverse.DbLoaderDelegate;
+import org.apache.cayenne.dbsync.reverse.DefaultDbLoaderDelegate;
+import org.apache.cayenne.dbsync.reverse.LoggingDbLoaderDelegate;
+import org.apache.cayenne.dbsync.reverse.NameFilter;
+import org.apache.cayenne.dbsync.reverse.NamePatternMatcher;
+import org.apache.cayenne.dbsync.reverse.filters.CatalogFilter;
+import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.EntityResolver;
import org.apache.cayenne.map.naming.LegacyNameGenerator;
import org.apache.cayenne.map.naming.ObjectNameGenerator;
-import org.apache.cayenne.merge.DbMergerConfig;
-import org.apache.cayenne.merge.DefaultModelMergeDelegate;
-import org.apache.cayenne.merge.ModelMergeDelegate;
import org.apache.cayenne.resource.URLResource;
-import org.apache.cayenne.access.loader.NamePatternMatcher;
-import org.apache.cayenne.util.EntityMergeSupport;
import org.apache.commons.logging.Log;
import java.io.File;
@@ -48,7 +48,6 @@ import java.io.IOException;
import java.net.MalformedURLException;
import java.sql.Connection;
import java.util.Collections;
-import java.util.List;
import static org.apache.commons.lang.StringUtils.isNotEmpty;
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegate.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegate.java
index 7772b73..bc6abab 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegate.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegate.java
@@ -19,7 +19,7 @@
package org.apache.cayenne.tools.dbimport;
-import org.apache.cayenne.access.loader.DefaultDbLoaderDelegate;
+import org.apache.cayenne.dbsync.reverse.DefaultDbLoaderDelegate;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.ObjEntity;
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportModule.java
----------------------------------------------------------------------
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 18cc197..754071e 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
@@ -29,8 +29,8 @@ import org.apache.cayenne.tools.configuration.ToolsModule;
/**
* A DI module that bootstraps {@link DbImportAction}. Should be used in
- * conjunction with {@link ToolsModule}.
- *
+ * conjunction with {@link ToolsModule} and {@link org.apache.cayenne.dbsync.CayenneDbSyncModule}.
+ *
* @since 4.0
*/
public class DbImportModule implements Module {
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DefaultDbImportAction.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DefaultDbImportAction.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DefaultDbImportAction.java
index c51300f..d344946 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DefaultDbImportAction.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DefaultDbImportAction.java
@@ -18,26 +18,27 @@
*/
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.dbsync.merge.AbstractToModelToken;
+import org.apache.cayenne.dbsync.merge.AddRelationshipToDb;
+import org.apache.cayenne.dbsync.merge.DbMerger;
+import org.apache.cayenne.dbsync.merge.MergerContext;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.ModelMergeDelegate;
+import org.apache.cayenne.dbsync.merge.ProxyModelMergeDelegate;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.dbsync.reverse.DbLoader;
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.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;
@@ -73,17 +74,20 @@ public class DefaultDbImportAction implements DbImportAction {
private final DataSourceFactory dataSourceFactory;
private final DbAdapterFactory adapterFactory;
private final MapLoader mapLoader;
+ private final MergerTokenFactoryProvider mergerTokenFactoryProvider;
public DefaultDbImportAction(@Inject Log logger,
@Inject ProjectSaver projectSaver,
@Inject DataSourceFactory dataSourceFactory,
@Inject DbAdapterFactory adapterFactory,
- @Inject MapLoader mapLoader) {
+ @Inject MapLoader mapLoader,
+ @Inject MergerTokenFactoryProvider mergerTokenFactoryProvider) {
this.logger = logger;
this.projectSaver = projectSaver;
this.dataSourceFactory = dataSourceFactory;
this.adapterFactory = adapterFactory;
this.mapLoader = mapLoader;
+ this.mergerTokenFactoryProvider = mergerTokenFactoryProvider;
}
protected static List<MergerToken> sort(List<MergerToken> reverse) {
@@ -135,9 +139,9 @@ public class DefaultDbImportAction implements DbImportAction {
saveLoaded(config.initializeDataMap(loadedFomDb));
} else {
- MergerFactory mergerFactory = adapter.mergerFactory();
+ MergerTokenFactory mergerTokenFactory = mergerTokenFactoryProvider.get(adapter);
- List<MergerToken> mergeTokens = new DbMerger(mergerFactory)
+ List<MergerToken> mergeTokens = new DbMerger(mergerTokenFactory)
.createMergeTokens(existing, loadedFomDb, config.getDbLoaderConfig());
if (mergeTokens.isEmpty()) {
logger.info("");
@@ -157,7 +161,7 @@ public class DefaultDbImportAction implements DbImportAction {
super.objEntityAdded(ent);
}
- }, existing, log(sort(reverse(mergerFactory, mergeTokens))));
+ }, existing, log(sort(reverse(mergerTokenFactory, mergeTokens))));
DbLoader.flattenManyToManyRelationships(executed, loadedObjEntities, config.getNameGenerator());
relationshipsSanity(executed);
@@ -207,14 +211,14 @@ public class DefaultDbImportAction implements DbImportAction {
}
private List<MergerToken> reverse(
- MergerFactory mergerFactory,
+ MergerTokenFactory mergerTokenFactory,
Iterable<MergerToken> mergeTokens) throws IOException {
List<MergerToken> tokens = new LinkedList<>();
for (MergerToken token : mergeTokens) {
if (token instanceof AbstractToModelToken) {
continue;
}
- tokens.add(token.createReverse(mergerFactory));
+ tokens.add(token.createReverse(mergerTokenFactory));
}
return tokens;
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/DefaultTypeMapperBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/DefaultTypeMapperBuilder.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/DefaultTypeMapperBuilder.java
index 52fc3d0..c8cab3a 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/DefaultTypeMapperBuilder.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/config/DefaultTypeMapperBuilder.java
@@ -18,9 +18,9 @@
****************************************************************/
package org.apache.cayenne.tools.dbimport.config;
-import org.apache.cayenne.access.loader.mapper.DbType;
-import org.apache.cayenne.access.loader.mapper.DefaultJdbc2JavaTypeMapper;
-import org.apache.cayenne.access.loader.mapper.Jdbc2JavaTypeMapper;
+import org.apache.cayenne.dbsync.reverse.mapper.DbType;
+import org.apache.cayenne.dbsync.reverse.mapper.DefaultJdbc2JavaTypeMapper;
+import org.apache.cayenne.dbsync.reverse.mapper.Jdbc2JavaTypeMapper;
import org.apache.commons.lang.ClassUtils;
import org.apache.commons.logging.Log;
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-tools/src/test/java/org/apache/cayenne/tools/NamePatternMatcherTest.java
----------------------------------------------------------------------
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 161f44e..3482843 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
@@ -19,12 +19,12 @@
package org.apache.cayenne.tools;
-import static org.apache.cayenne.access.loader.NamePatternMatcher.replaceWildcardInStringWithString;
-import static org.junit.Assert.assertEquals;
-
-import org.apache.cayenne.access.loader.NamePatternMatcher;
+import org.apache.cayenne.dbsync.reverse.NamePatternMatcher;
import org.junit.Test;
+import static org.apache.cayenne.dbsync.reverse.NamePatternMatcher.replaceWildcardInStringWithString;
+import static org.junit.Assert.assertEquals;
+
public class NamePatternMatcherTest {
/**
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportModuleTest.java
----------------------------------------------------------------------
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 62b65ea..1e34d4e 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
@@ -18,6 +18,7 @@
****************************************************************/
package org.apache.cayenne.tools.dbimport;
+import org.apache.cayenne.dbsync.CayenneDbSyncModule;
import org.apache.cayenne.di.DIBootstrap;
import org.apache.cayenne.di.Injector;
import org.apache.cayenne.tools.configuration.ToolsModule;
@@ -33,7 +34,7 @@ public class DbImportModuleTest {
public void testModuleContents() {
Log log = mock(Log.class);
- Injector i = DIBootstrap.createInjector(new ToolsModule(log), new DbImportModule());
+ Injector i = DIBootstrap.createInjector(new CayenneDbSyncModule(), new ToolsModule(log), new DbImportModule());
assertTrue(i.getInstance(DbImportAction.class) instanceof DbImportAction);
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DefaultDbImportActionTest.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DefaultDbImportActionTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DefaultDbImportActionTest.java
index 474b827..5a7c357 100644
--- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DefaultDbImportActionTest.java
+++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DefaultDbImportActionTest.java
@@ -19,26 +19,28 @@
package org.apache.cayenne.tools.dbimport;
import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.access.DbLoader;
-import org.apache.cayenne.access.DbLoaderDelegate;
-import org.apache.cayenne.access.loader.DbLoaderConfiguration;
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.dbsync.CayenneDbSyncModule;
+import org.apache.cayenne.dbsync.merge.AddColumnToDb;
+import org.apache.cayenne.dbsync.merge.AddRelationshipToDb;
+import org.apache.cayenne.dbsync.merge.CreateTableToDb;
+import org.apache.cayenne.dbsync.merge.CreateTableToModel;
+import org.apache.cayenne.dbsync.merge.DefaultModelMergeDelegate;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.builders.DataMapBuilder;
+import org.apache.cayenne.dbsync.merge.factory.DefaultMergerTokenFactory;
+import org.apache.cayenne.dbsync.reverse.DbLoader;
+import org.apache.cayenne.dbsync.reverse.DbLoaderConfiguration;
+import org.apache.cayenne.dbsync.reverse.DbLoaderDelegate;
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.MapLoader;
-import org.apache.cayenne.merge.AddColumnToDb;
-import org.apache.cayenne.merge.AddRelationshipToDb;
-import org.apache.cayenne.merge.CreateTableToDb;
-import org.apache.cayenne.merge.CreateTableToModel;
-import org.apache.cayenne.merge.DefaultModelMergeDelegate;
-import org.apache.cayenne.merge.MergerFactory;
-import org.apache.cayenne.merge.MergerToken;
-import org.apache.cayenne.merge.builders.DataMapBuilder;
import org.apache.cayenne.project.FileProjectSaver;
import org.apache.cayenne.project.Project;
import org.apache.cayenne.resource.URLResource;
@@ -57,10 +59,10 @@ 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.apache.cayenne.dbsync.merge.builders.ObjectMother.dbAttr;
+import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.dbEntity;
+import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.objAttr;
+import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.objEntity;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -287,7 +289,6 @@ public class DefaultDbImportActionTest {
private DefaultDbImportAction 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);
@@ -296,13 +297,16 @@ public class DefaultDbImportActionTest {
DataSource mock = mock(DataSource.class);
when(dataSourceFactory.getDataSource(any(DataNodeDescriptor.class))).thenReturn(mock);
- return new DefaultDbImportAction(log, projectSaver, dataSourceFactory, adapterFactory, mapLoader);
+ MergerTokenFactoryProvider mergerTokenFactoryProvider = mock(MergerTokenFactoryProvider.class);
+ when(mergerTokenFactoryProvider.get(any(DbAdapter.class))).thenReturn(new DefaultMergerTokenFactory());
+
+ return new DefaultDbImportAction(log, projectSaver, dataSourceFactory, adapterFactory, mapLoader, mergerTokenFactoryProvider);
}
@Test
public void testSaveLoaded() throws Exception {
Log log = mock(Log.class);
- Injector i = DIBootstrap.createInjector(new ToolsModule(log), new DbImportModule());
+ Injector i = DIBootstrap.createInjector(new CayenneDbSyncModule(), new ToolsModule(log), new DbImportModule());
DefaultDbImportAction action = (DefaultDbImportAction) i.getInstance(DbImportAction.class);
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/docs/doc/src/main/resources/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --git a/docs/doc/src/main/resources/RELEASE-NOTES.txt b/docs/doc/src/main/resources/RELEASE-NOTES.txt
index aa04b5f..fcd7155 100644
--- a/docs/doc/src/main/resources/RELEASE-NOTES.txt
+++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt
@@ -32,6 +32,7 @@ CAY-2107 cayenne-crypto: Lazy initialization of crypto subsystem
CAY-2111 Unbind transaction object from the current thread for iterated queries
CAY-2112 Expose callback for "performInTransaction"
CAY-2113 cdbimport: Reverse-engineering reinstates previously ignored columns
+CAY-2116 Split schema synchronization code in a separate module
Bug Fixes:
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Main.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Main.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Main.java
index 80f8748..838f736 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Main.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Main.java
@@ -19,15 +19,8 @@
package org.apache.cayenne.modeler;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.prefs.Preferences;
-
-import javax.swing.SwingUtilities;
-
import org.apache.cayenne.configuration.server.ServerModule;
+import org.apache.cayenne.dbsync.CayenneDbSyncModule;
import org.apache.cayenne.di.DIBootstrap;
import org.apache.cayenne.di.Injector;
import org.apache.cayenne.di.Module;
@@ -39,6 +32,13 @@ import org.apache.cayenne.project.CayenneProjectModule;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import javax.swing.*;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.prefs.Preferences;
+
/**
* Main class responsible for starting CayenneModeler.
*/
@@ -105,6 +105,7 @@ public class Main {
protected Collection<Module> appendModules(Collection<Module> modules) {
modules.add(new ServerModule("CayenneModeler"));
modules.add(new CayenneProjectModule());
+ modules.add(new CayenneDbSyncModule());
modules.add(new CayenneModelerModule());
return modules;
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateObjEntityAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateObjEntityAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateObjEntityAction.java
index 7381886..a4f54fc 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateObjEntityAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/CreateObjEntityAction.java
@@ -19,10 +19,9 @@
package org.apache.cayenne.modeler.action;
-import java.awt.event.ActionEvent;
-
import org.apache.cayenne.configuration.ConfigurationNode;
import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.dbsync.merge.EntityMergeSupport;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.ObjEntity;
@@ -37,7 +36,8 @@ import org.apache.cayenne.modeler.event.EntityDisplayEvent;
import org.apache.cayenne.modeler.undo.CreateObjEntityUndoableEdit;
import org.apache.cayenne.modeler.util.CayenneAction;
import org.apache.cayenne.util.DeleteRuleUpdater;
-import org.apache.cayenne.util.EntityMergeSupport;
+
+import java.awt.event.ActionEvent;
public class CreateObjEntityAction extends CayenneAction {
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DbEntitySyncAction.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DbEntitySyncAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DbEntitySyncAction.java
index aec4a2d..65294b5 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DbEntitySyncAction.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/action/DbEntitySyncAction.java
@@ -19,10 +19,8 @@
package org.apache.cayenne.modeler.action;
-import java.awt.event.ActionEvent;
-import java.util.Iterator;
-
import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.dbsync.merge.EntityMergeSupport;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.event.EntityEvent;
@@ -32,7 +30,9 @@ import org.apache.cayenne.modeler.ProjectController;
import org.apache.cayenne.modeler.dialog.objentity.EntitySyncController;
import org.apache.cayenne.modeler.undo.DbEntitySyncUndoableEdit;
import org.apache.cayenne.modeler.util.CayenneAction;
-import org.apache.cayenne.util.EntityMergeSupport;
+
+import java.awt.event.ActionEvent;
+import java.util.Iterator;
/**
* Action that synchronizes all ObjEntities with the current state of the
[05/15] cayenne git commit: CAY-2116 Split schema synchronization
code in a separate module
Posted by aa...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/DbMerger.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/DbMerger.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/DbMerger.java
deleted file mode 100644
index 3070cf1..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/DbMerger.java
+++ /dev/null
@@ -1,405 +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.merge;
-
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.sql.Types;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-
-import javax.sql.DataSource;
-
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.access.DataNode;
-import org.apache.cayenne.access.DbLoader;
-import org.apache.cayenne.access.loader.DbLoaderConfiguration;
-import org.apache.cayenne.access.loader.LoggingDbLoaderDelegate;
-import org.apache.cayenne.access.loader.filters.FiltersConfig;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.map.Attribute;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbJoin;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.DetectedDbEntity;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Traverse a {@link DataNode} and a {@link DataMap} and create a group of
- * {@link MergerToken}s to alter the {@link DataNode} data store to match the
- * {@link DataMap}.
- *
- */
-public class DbMerger {
-
- private static final Log LOGGER = LogFactory.getLog(DbMerger.class);
-
- private final MergerFactory factory;
-
- private final ValueForNullProvider valueForNull;
-
- public DbMerger(MergerFactory factory) {
- this(factory, null);
- }
-
- public DbMerger(MergerFactory factory, ValueForNullProvider valueForNull) {
- this.factory = factory;
- this.valueForNull = valueForNull == null ? new EmptyValueForNullProvider() : valueForNull;
- }
-
- /**
- * Create and return a {@link List} of {@link MergerToken}s to alter the
- * given {@link DataNode} to match the given {@link DataMap}
- */
- public List<MergerToken> createMergeTokens(DataSource dataSource, DbAdapter adapter, DataMap existingDataMap,
- DbLoaderConfiguration config) {
- return createMergeTokens(existingDataMap, loadDataMapFromDb(dataSource, adapter, config), config);
- }
-
- /**
- * Create and return a {@link List} of {@link MergerToken}s to alter the
- * given {@link DataNode} to match the given {@link DataMap}
- */
- public List<MergerToken> createMergeTokens(DataMap existing, DataMap loadedFomDb, DbLoaderConfiguration config) {
-
- loadedFomDb.setQuotingSQLIdentifiers(existing.isQuotingSQLIdentifiers());
-
- List<MergerToken> tokens = createMergeTokens(filter(existing, config.getFiltersConfig()),
- loadedFomDb.getDbEntities(), config);
-
- // sort. use a custom Comparator since only toDb tokens are comparable
- // by now
- Collections.sort(tokens, new Comparator<MergerToken>() {
-
- public int compare(MergerToken o1, MergerToken o2) {
- if (o1 instanceof AbstractToDbToken && o2 instanceof AbstractToDbToken) {
-
- return ((AbstractToDbToken) o1).compareTo(o2);
- }
- return 0;
- }
- });
-
- return tokens;
- }
-
- private Collection<DbEntity> filter(DataMap existing, FiltersConfig filtersConfig) {
- Collection<DbEntity> existingFiltered = new LinkedList<DbEntity>();
- for (DbEntity entity : existing.getDbEntities()) {
- if (filtersConfig.tableFilter(entity.getCatalog(), entity.getSchema()).isIncludeTable(entity.getName()) != null) {
- existingFiltered.add(entity);
- }
- }
- return existingFiltered;
- }
-
- private DataMap loadDataMapFromDb(DataSource dataSource, DbAdapter adapter, DbLoaderConfiguration config) {
- try (Connection conn = dataSource.getConnection();) {
-
- return new DbLoader(conn, adapter, new LoggingDbLoaderDelegate(LOGGER)).load(config);
- } catch (SQLException e) {
- throw new CayenneRuntimeException("Can't doLoad dataMap from db.", e);
- }
- }
-
- public List<MergerToken> createMergeTokens(Collection<DbEntity> existing, Collection<DbEntity> loadedFromDb,
- DbLoaderConfiguration config) {
- Collection<DbEntity> dbEntitiesToDrop = new LinkedList<DbEntity>(loadedFromDb);
-
- List<MergerToken> tokens = new LinkedList<MergerToken>();
- for (DbEntity dbEntity : existing) {
- String tableName = dbEntity.getName();
-
- // look for table
- DbEntity detectedEntity = findDbEntity(loadedFromDb, tableName);
- if (detectedEntity == null) {
- tokens.add(factory.createCreateTableToDb(dbEntity));
- // TODO: does this work properly with createReverse?
- for (DbRelationship rel : dbEntity.getRelationships()) {
- tokens.add(factory.createAddRelationshipToDb(dbEntity, rel));
- }
- continue;
- }
-
- dbEntitiesToDrop.remove(detectedEntity);
-
- tokens.addAll(checkRelationshipsToDrop(dbEntity, detectedEntity));
- if (!config.isSkipRelationshipsLoading()) {
- tokens.addAll(checkRelationshipsToAdd(dbEntity, detectedEntity));
- }
- tokens.addAll(checkRows(dbEntity, detectedEntity));
-
- if (!config.isSkipPrimaryKeyLoading()) {
- MergerToken token = checkPrimaryKeyChange(dbEntity, detectedEntity);
- if (token != null) {
- tokens.add(token);
- }
- }
- }
-
- // drop table
- // TODO: support drop table. currently, too many tables are marked for
- // drop
- for (DbEntity e : dbEntitiesToDrop) {
- tokens.add(factory.createDropTableToDb(e));
- for (DbRelationship relationship : e.getRelationships()) {
- DbEntity detectedEntity = findDbEntity(existing, relationship.getTargetEntityName());
- if (detectedEntity != null) {
- tokens.add(factory.createDropRelationshipToDb(detectedEntity, relationship.getReverseRelationship()));
- }
- }
- }
-
- return tokens;
- }
-
- private List<MergerToken> checkRows(DbEntity existing, DbEntity loadedFromDb) {
- List<MergerToken> tokens = new LinkedList<MergerToken>();
-
- // columns to drop
- for (DbAttribute detected : loadedFromDb.getAttributes()) {
- if (findDbAttribute(existing, detected.getName()) == null) {
- tokens.add(factory.createDropColumnToDb(existing, detected));
- }
- }
-
- // columns to add or modify
- for (DbAttribute attr : existing.getAttributes()) {
- String columnName = attr.getName().toUpperCase();
-
- DbAttribute detected = findDbAttribute(loadedFromDb, columnName);
-
- if (detected == null) {
- tokens.add(factory.createAddColumnToDb(existing, attr));
- if (attr.isMandatory()) {
- if (valueForNull.hasValueFor(existing, attr)) {
- tokens.add(factory.createSetValueForNullToDb(existing, attr, valueForNull));
- }
- tokens.add(factory.createSetNotNullToDb(existing, attr));
- }
- continue;
- }
-
- // check for not null
- if (attr.isMandatory() != detected.isMandatory()) {
- if (attr.isMandatory()) {
- if (valueForNull.hasValueFor(existing, attr)) {
- tokens.add(factory.createSetValueForNullToDb(existing, attr, valueForNull));
- }
- tokens.add(factory.createSetNotNullToDb(existing, attr));
- } else {
- tokens.add(factory.createSetAllowNullToDb(existing, attr));
- }
- }
-
- // TODO: check more types than char/varchar
- // TODO: psql report VARCHAR for text column, not clob
- switch (detected.getType()) {
- case Types.VARCHAR:
- case Types.CHAR:
- if (attr.getMaxLength() != detected.getMaxLength()) {
- tokens.add(factory.createSetColumnTypeToDb(existing, detected, attr));
- }
- break;
- }
- }
-
- return tokens;
- }
-
- private List<MergerToken> checkRelationshipsToDrop(DbEntity dbEntity, DbEntity detectedEntity) {
- List<MergerToken> tokens = new LinkedList<MergerToken>();
-
- // relationships to drop
- for (DbRelationship detected : detectedEntity.getRelationships()) {
- if (findDbRelationship(dbEntity, detected) == null) {
-
- // alter detected relationship to match entity and attribute
- // names.
- // (case sensitively)
-
- DbEntity targetEntity = findDbEntity(dbEntity.getDataMap().getDbEntities(),
- detected.getTargetEntityName());
- if (targetEntity == null) {
- continue;
- }
-
- detected.setSourceEntity(dbEntity);
- detected.setTargetEntityName(targetEntity);
-
- // manipulate the joins to match the DbAttributes in the model
- for (DbJoin join : detected.getJoins()) {
- DbAttribute sattr = findDbAttribute(dbEntity, join.getSourceName());
- if (sattr != null) {
- join.setSourceName(sattr.getName());
- }
- DbAttribute tattr = findDbAttribute(targetEntity, join.getTargetName());
- if (tattr != null) {
- join.setTargetName(tattr.getName());
- }
- }
-
- MergerToken token = factory.createDropRelationshipToDb(dbEntity, detected);
- if (detected.isToMany()) {
- // default toModel as we can not do drop a toMany in the db.
- // only
- // toOne are represented using foreign key
- token = token.createReverse(factory);
- }
- tokens.add(token);
- }
- }
-
- return tokens;
- }
-
- private List<MergerToken> checkRelationshipsToAdd(DbEntity dbEntity, DbEntity detectedEntity) {
-
- List<MergerToken> tokens = new LinkedList<MergerToken>();
-
- for (DbRelationship rel : dbEntity.getRelationships()) {
- if (findDbRelationship(detectedEntity, rel) == null) {
- AddRelationshipToDb token = (AddRelationshipToDb) factory.createAddRelationshipToDb(dbEntity, rel);
-
- if (token.shouldGenerateFkConstraint()) {
- // TODO I guess we should add relationship always; in order
- // to have ability
- // TODO generate reverse relationship. If it doesn't have
- // anything to execute it will be passed
- // TODO through execution without any affect on db
- tokens.add(token);
- }
- }
- }
-
- return tokens;
- }
-
- private MergerToken checkPrimaryKeyChange(DbEntity dbEntity, DbEntity detectedEntity) {
- Collection<DbAttribute> primaryKeyOriginal = detectedEntity.getPrimaryKeys();
- Collection<DbAttribute> primaryKeyNew = dbEntity.getPrimaryKeys();
-
- String primaryKeyName = null;
- if (detectedEntity instanceof DetectedDbEntity) {
- primaryKeyName = ((DetectedDbEntity) detectedEntity).getPrimaryKeyName();
- }
-
- if (upperCaseEntityNames(primaryKeyOriginal).equals(upperCaseEntityNames(primaryKeyNew))) {
- return null;
- }
-
- return factory.createSetPrimaryKeyToDb(dbEntity, primaryKeyOriginal, primaryKeyNew, primaryKeyName);
- }
-
- private Set<String> upperCaseEntityNames(Collection<? extends Attribute> attrs) {
- Set<String> names = new HashSet<String>();
- for (Attribute attr : attrs) {
- names.add(attr.getName().toUpperCase());
- }
- return names;
- }
-
- /**
- * case insensitive search for a {@link DbEntity} in a {@link DataMap} by
- * name
- */
- private DbEntity findDbEntity(Collection<DbEntity> dbEntities, String caseInsensitiveName) {
- // TODO: create a Map with upper case keys?
- for (DbEntity e : dbEntities) {
- if (e.getName().equalsIgnoreCase(caseInsensitiveName)) {
- return e;
- }
- }
- return null;
- }
-
- /**
- * case insensitive search for a {@link DbAttribute} in a {@link DbEntity}
- * by name
- */
- private DbAttribute findDbAttribute(DbEntity entity, String caseInsensitiveName) {
- for (DbAttribute a : entity.getAttributes()) {
- if (a.getName().equalsIgnoreCase(caseInsensitiveName)) {
- return a;
- }
- }
- return null;
- }
-
- /**
- * search for a {@link DbRelationship} like rel in the given
- * {@link DbEntity}
- */
- private DbRelationship findDbRelationship(DbEntity entity, DbRelationship rel) {
- for (DbRelationship candidate : entity.getRelationships()) {
- if (equalDbJoinCollections(candidate.getJoins(), rel.getJoins())) {
- return candidate;
- }
- }
- return null;
- }
-
- /**
- * Return true if the two unordered {@link Collection}s of {@link DbJoin}s
- * are equal. Entity and Attribute names are compared case insensitively.
- *
- * TODO complexity n^2; sort both collection and go through them to compare
- * = 2*n*log(n) + n
- */
- private static boolean equalDbJoinCollections(Collection<DbJoin> j1s, Collection<DbJoin> j2s) {
- if (j1s.size() != j2s.size()) {
- return false;
- }
-
- for (DbJoin j1 : j1s) {
- if (!havePair(j2s, j1)) {
- return false;
- }
- }
-
- return true;
- }
-
- private static boolean havePair(Collection<DbJoin> j2s, DbJoin j1) {
- for (DbJoin j2 : j2s) {
- if (!isNull(j1.getSource()) && !isNull(j1.getTarget()) && !isNull(j2.getSource())
- && !isNull(j2.getTarget())
- && j1.getSource().getEntity().getName().equalsIgnoreCase(j2.getSource().getEntity().getName())
- && j1.getTarget().getEntity().getName().equalsIgnoreCase(j2.getTarget().getEntity().getName())
- && j1.getSourceName().equalsIgnoreCase(j2.getSourceName())
- && j1.getTargetName().equalsIgnoreCase(j2.getTargetName())) {
-
- return true;
- }
- }
- return false;
- }
-
- private static boolean isNull(DbAttribute attribute) {
- return attribute == null || attribute.getEntity() == null;
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/DbMergerConfig.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/DbMergerConfig.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/DbMergerConfig.java
deleted file mode 100644
index e8df4b8..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/DbMergerConfig.java
+++ /dev/null
@@ -1,63 +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.merge;
-
-import org.apache.cayenne.access.loader.filters.FiltersConfig;
-
-/**
- * @since 4.0
- */
-public class DbMergerConfig {
-
- private FiltersConfig filtersConfig;
-
- private boolean skipRelationships;
-
- private boolean skipPrimaryKey;
-
- public DbMergerConfig(FiltersConfig filtersConfig, boolean skipRelationships, boolean skipPrimaryKey) {
- this.filtersConfig = filtersConfig;
- this.skipRelationships = skipRelationships;
- this.skipPrimaryKey = skipPrimaryKey;
- }
-
- public void setSkipRelationships(boolean skipRelationships) {
- this.skipRelationships = skipRelationships;
- }
-
- public boolean isSkipRelationships() {
- return skipRelationships;
- }
-
- public void setSkipPrimaryKey(boolean skipPrimaryKey) {
- this.skipPrimaryKey = skipPrimaryKey;
- }
-
- public boolean isSkipPrimaryKey() {
- return skipPrimaryKey;
- }
-
- public FiltersConfig getFiltersConfig() {
- return filtersConfig;
- }
-
- public void setFiltersConfig(FiltersConfig filtersConfig) {
- this.filtersConfig = filtersConfig;
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/DefaultModelMergeDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/DefaultModelMergeDelegate.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/DefaultModelMergeDelegate.java
deleted file mode 100644
index e457f31..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/DefaultModelMergeDelegate.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.merge;
-
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.ObjAttribute;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.map.ObjRelationship;
-
-/**
- * A default noop implementation of {@link ModelMergeDelegate}.
- */
-public class DefaultModelMergeDelegate implements ModelMergeDelegate {
-
- @Override
- public void dbAttributeAdded(DbAttribute att) {
- }
-
- @Override
- public void dbAttributeModified(DbAttribute att) {
- }
-
- @Override
- public void dbAttributeRemoved(DbAttribute att) {
- }
-
- @Override
- public void dbEntityAdded(DbEntity ent) {
- }
-
- @Override
- public void dbEntityRemoved(DbEntity ent) {
- }
-
- @Override
- public void dbRelationshipAdded(DbRelationship rel) {
- }
-
- @Override
- public void dbRelationshipRemoved(DbRelationship rel) {
- }
-
- @Override
- public void objAttributeAdded(ObjAttribute att) {
- }
-
- @Override
- public void objAttributeModified(ObjAttribute att) {
- }
-
- @Override
- public void objAttributeRemoved(ObjAttribute att) {
- }
-
- @Override
- public void objEntityAdded(ObjEntity ent) {
- }
-
- @Override
- public void objEntityRemoved(ObjEntity ent) {
- }
-
- @Override
- public void objRelationshipAdded(ObjRelationship rel) {
- }
-
- @Override
- public void objRelationshipRemoved(ObjRelationship rel) {
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/DefaultValueForNullProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/DefaultValueForNullProvider.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/DefaultValueForNullProvider.java
deleted file mode 100644
index f17f0fc..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/DefaultValueForNullProvider.java
+++ /dev/null
@@ -1,62 +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.merge;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.cayenne.access.jdbc.SQLParameterBinding;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-
-public class DefaultValueForNullProvider implements ValueForNullProvider {
-
- private Map<String, SQLParameterBinding> values = new HashMap<>();
-
- public void set(DbEntity entity, DbAttribute column, Object value, int type) {
- values.put(createKey(entity, column), new SQLParameterBinding(value, type, column
- .getAttributePrecision()));
- }
-
- protected SQLParameterBinding get(DbEntity entity, DbAttribute column) {
- return values.get(createKey(entity, column));
- }
-
- public List<String> createSql(DbEntity entity, DbAttribute column) {
- SQLParameterBinding value = get(entity, column);
- if (value == null) {
- return Collections.emptyList();
- }
-
- // TODO: change things so it is possible to use prepared statements here
- return Collections.singletonList("UPDATE " + entity.getFullyQualifiedName()
- + " SET " + column.getName() + "='" + value.getValue() + "' WHERE " + column.getName() + " IS NULL");
- }
-
- public boolean hasValueFor(DbEntity entity, DbAttribute column) {
- return values.containsKey(createKey(entity, column));
- }
-
- private String createKey(DbEntity entity, DbAttribute attribute) {
- return (entity.getFullyQualifiedName() + "." + attribute.getName()).toUpperCase();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/DropColumnToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/DropColumnToDb.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/DropColumnToDb.java
deleted file mode 100644
index 5cb0a05..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/DropColumnToDb.java
+++ /dev/null
@@ -1,51 +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.merge;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-
-public class DropColumnToDb extends AbstractToDbToken.EntityAndColumn {
-
- public DropColumnToDb(DbEntity entity, DbAttribute column) {
- super("Drop Column", entity, column);
- }
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- StringBuilder sqlBuffer = new StringBuilder();
- QuotingStrategy context = adapter.getQuotingStrategy();
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
- sqlBuffer.append(" DROP COLUMN ");
- sqlBuffer.append(context.quotedName(getColumn()));
-
- return Collections.singletonList(sqlBuffer.toString());
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return factory.createAddColumnToModel(getEntity(), getColumn());
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/DropColumnToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/DropColumnToModel.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/DropColumnToModel.java
deleted file mode 100644
index 37fb728..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/DropColumnToModel.java
+++ /dev/null
@@ -1,74 +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.merge;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbJoin;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.ObjAttribute;
-import org.apache.cayenne.map.ObjEntity;
-
-/**
- * A {@link MergerToken} to remove a {@link DbAttribute} from a {@link DbEntity}.
- *
- */
-public class DropColumnToModel extends AbstractToModelToken.EntityAndColumn {
-
- public DropColumnToModel(DbEntity entity, DbAttribute column) {
- super("Drop Column", entity, column);
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return factory.createAddColumnToDb(getEntity(), getColumn());
- }
-
- public void execute(MergerContext mergerContext) {
-
- // remove relationships mapped to column. duplicate List to prevent
- // ConcurrentModificationException
- List<DbRelationship> dbRelationships = new ArrayList<DbRelationship>(getEntity()
- .getRelationships());
- for (DbRelationship dbRelationship : dbRelationships) {
- for (DbJoin join : dbRelationship.getJoins()) {
- if (join.getSource() == getColumn() || join.getTarget() == getColumn()) {
- remove(mergerContext.getModelMergeDelegate(), dbRelationship, true);
- }
- }
- }
-
- // remove ObjAttribute mapped to same column
- for (ObjEntity objEntity : getEntity().mappedObjEntities()) {
- ObjAttribute objAttribute = objEntity.getAttributeForDbAttribute(getColumn());
- if (objAttribute != null) {
- objEntity.removeAttribute(objAttribute.getName());
- mergerContext.getModelMergeDelegate().objAttributeRemoved(objAttribute);
- }
-
- }
-
- // remove DbAttribute
- getEntity().removeAttribute(getColumn().getName());
-
- mergerContext.getModelMergeDelegate().dbAttributeRemoved(getColumn());
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/DropRelationshipToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/DropRelationshipToDb.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/DropRelationshipToDb.java
deleted file mode 100644
index 618aab3..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/DropRelationshipToDb.java
+++ /dev/null
@@ -1,71 +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.merge;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.DbRelationshipDetected;
-
-public class DropRelationshipToDb extends AbstractToDbToken.Entity {
-
- private DbRelationship rel;
-
- public DropRelationshipToDb(DbEntity entity, DbRelationship rel) {
- super("Drop foreign key", entity);
- this.rel = rel;
- }
-
- public String getFkName() {
- if (rel instanceof DbRelationshipDetected) {
- return ((DbRelationshipDetected) rel).getFkName();
- }
- return null;
- }
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- String fkName = getFkName();
- if (fkName == null) {
- return Collections.emptyList();
- }
-
- QuotingStrategy context = adapter.getQuotingStrategy();
- return Collections.singletonList(
- "ALTER TABLE " + context.quotedFullyQualifiedName(getEntity()) + " DROP CONSTRAINT " + fkName);
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return factory.createAddRelationshipToModel(getEntity(), rel);
- }
-
- @Override
- public String getTokenValue() {
- return rel.getSourceEntity().getName() + "->" + rel.getTargetEntityName();
- }
-
- public DbRelationship getRelationship() {
- return rel;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/DropRelationshipToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/DropRelationshipToModel.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/DropRelationshipToModel.java
deleted file mode 100644
index ee9359f..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/DropRelationshipToModel.java
+++ /dev/null
@@ -1,50 +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.merge;
-
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbRelationship;
-
-public class DropRelationshipToModel extends AbstractToModelToken.Entity {
-
- private final DbRelationship rel;
-
- public DropRelationshipToModel(DbEntity entity, DbRelationship rel) {
- super("Drop db-relationship ", entity);
- this.rel = rel;
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return factory.createAddRelationshipToDb(getEntity(), rel);
- }
-
- public void execute(MergerContext mergerContext) {
- remove(mergerContext.getModelMergeDelegate(), rel, true);
- }
-
- @Override
- public String getTokenValue() {
- return AddRelationshipToModel.getTokenValue(rel);
- }
-
- public DbRelationship getRelationship() {
- return rel;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/DropTableToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/DropTableToDb.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/DropTableToDb.java
deleted file mode 100644
index d0904e6..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/DropTableToDb.java
+++ /dev/null
@@ -1,49 +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.merge;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.map.DbEntity;
-
-public class DropTableToDb extends AbstractToDbToken.Entity {
-
- public DropTableToDb(DbEntity entity) {
- super("Drop Table", entity);
- }
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- List<String> sqls = new ArrayList<String>();
- // TODO: fix. some adapters drop the complete AUTO_PK_SUPPORT here
- /*
- sqls.addAll(adapter.getPkGenerator().dropAutoPkStatements(
- Collections.singletonList(entity)));
- */
- sqls.addAll(adapter.dropTableStatements(getEntity()));
- return sqls;
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return factory.createCreateTableToModel(getEntity());
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/DropTableToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/DropTableToModel.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/DropTableToModel.java
deleted file mode 100644
index 55fde14..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/DropTableToModel.java
+++ /dev/null
@@ -1,48 +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.merge;
-
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.ObjEntity;
-
-/**
- * A {@link MergerToken} to remove a {@link DbEntity} from a {@link DataMap}. Any
- * {@link ObjEntity} mapped to the {@link DbEntity} will also be removed.
- *
- */
-public class DropTableToModel extends AbstractToModelToken.Entity {
-
- public DropTableToModel(DbEntity entity) {
- super("Drop Table", entity);
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return factory.createCreateTableToDb(getEntity());
- }
-
- public void execute(MergerContext mergerContext) {
- for (ObjEntity objEntity : getEntity().mappedObjEntities()) {
- objEntity.getDataMap().removeObjEntity(objEntity.getName(), true);
- mergerContext.getModelMergeDelegate().objEntityRemoved(objEntity);
- }
- getEntity().getDataMap().removeDbEntity(getEntity().getName(), true);
- mergerContext.getModelMergeDelegate().dbEntityRemoved(getEntity());
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/DummyReverseToken.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/DummyReverseToken.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/DummyReverseToken.java
deleted file mode 100644
index b99cc97..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/DummyReverseToken.java
+++ /dev/null
@@ -1,58 +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.merge;
-
-/**
- * The reverse of a {@link MergerToken} that can not be reversed.. This will not execute
- * any thing, but {@link #createReverse(MergerFactory)} will get back the reverse that
- * this was made from.
- */
-class DummyReverseToken implements MergerToken {
-
- private MergerToken reverse;
-
- public DummyReverseToken(MergerToken reverse) {
- this.reverse = reverse;
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return reverse;
- }
-
- public void execute(MergerContext mergerContext) {
- // can not execute
- }
-
- public MergeDirection getDirection() {
- return reverse.getDirection().reverseDirection();
- }
-
- public String getTokenName() {
- return "Can not execute the reverse of " + reverse.getTokenName();
- }
-
- public String getTokenValue() {
- return reverse.getTokenValue();
- }
-
- public boolean isReversible() {
- return true;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/EmptyValueForNullProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/EmptyValueForNullProvider.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/EmptyValueForNullProvider.java
deleted file mode 100644
index 88fb9f4..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/EmptyValueForNullProvider.java
+++ /dev/null
@@ -1,40 +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.merge;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-
-/**
- * A dummy {@link ValueForNullProvider} that are not able to provide any values
- */
-class EmptyValueForNullProvider implements ValueForNullProvider {
-
- public List<String> createSql(DbEntity entity, DbAttribute column) {
- return Collections.emptyList();
- }
-
- public boolean hasValueFor(DbEntity entity, DbAttribute column) {
- return false;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/MergeDirection.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/MergeDirection.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/MergeDirection.java
deleted file mode 100644
index d0a95c5..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/MergeDirection.java
+++ /dev/null
@@ -1,70 +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.merge;
-
-/**
- * Represent a merge direction that can be either from the model to the db or from the db to the model.
- */
-public enum MergeDirection {
-
- /**
- * TO_DB Token means that changes was made in object model and should be reflected at DB
- */
- TO_DB("To DB"),
-
- /**
- * TO_MODEL Token represent database changes that should be allayed to object model
- */
- TO_MODEL("To Model");
-
- private String name;
-
- MergeDirection(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- public boolean isToDb() {
- return (this == TO_DB);
- }
-
- public boolean isToModel() {
- return (this == TO_MODEL);
- }
-
- @Override
- public String toString() {
- return getName();
- }
-
- public MergeDirection reverseDirection() {
- switch (this) {
- case TO_DB:
- return TO_MODEL;
- case TO_MODEL:
- return TO_DB;
- default:
- throw new IllegalStateException("Invalid direction: " + this);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/MergerContext.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/MergerContext.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/MergerContext.java
deleted file mode 100644
index f592ebe..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/MergerContext.java
+++ /dev/null
@@ -1,118 +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.merge;
-
-import org.apache.cayenne.access.DataNode;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.validation.ValidationResult;
-
-import javax.sql.DataSource;
-import java.util.Objects;
-
-/**
- * An object passed as an argument to {@link MergerToken#execute(MergerContext)}s that a
- * {@link MergerToken} can do its work.
- */
-public class MergerContext {
-
- private DataMap dataMap;
- private DataNode dataNode;
- private ValidationResult validationResult;
- private ModelMergeDelegate delegate;
-
- protected MergerContext() {
- }
-
- public static Builder builder(DataMap dataMap) {
- return new Builder().dataMap(dataMap);
- }
-
- /**
- * @deprecated since 4.0 use {@link #getDataNode()} and its {@link DataNode#getAdapter()} method.
- */
- @Deprecated
- public DbAdapter getAdapter() {
- return getDataNode().getAdapter();
- }
-
- /**
- * Returns the DataMap that is the target of a the merge operation.
- *
- * @return the DataMap that is the target of a the merge operation.
- */
- public DataMap getDataMap() {
- return dataMap;
- }
-
- public DataNode getDataNode() {
- return dataNode;
- }
-
- public ValidationResult getValidationResult() {
- return validationResult;
- }
-
- /**
- * Returns a callback object that is invoked as the merge proceeds through tokens, modifying the DataMap.
- *
- * @return a callback object that is invoked as the merge proceeds through tokens, modifying the DataMap.
- */
- public ModelMergeDelegate getModelMergeDelegate() {
- return delegate;
- }
-
- public static class Builder {
-
- private MergerContext context;
-
- private Builder() {
- this.context = new MergerContext();
- this.context.validationResult = new ValidationResult();
- this.context.delegate = new DefaultModelMergeDelegate();
- this.context.dataNode = new DataNode();
- }
-
- public MergerContext build() {
- return context;
- }
-
- public Builder delegate(ModelMergeDelegate delegate) {
- context.delegate = Objects.requireNonNull(delegate);
- return this;
- }
-
- public Builder dataNode(DataNode dataNode) {
- this.context.dataNode = Objects.requireNonNull(dataNode);
- return this;
- }
-
- public Builder syntheticDataNode(DataSource dataSource, DbAdapter adapter) {
- DataNode dataNode = new DataNode();
- dataNode.setDataSource(dataSource);
- dataNode.setAdapter(adapter);
- return dataNode(dataNode);
- }
-
- public Builder dataMap(DataMap dataMap) {
- context.dataMap = Objects.requireNonNull(dataMap);
- return this;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/MergerFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/MergerFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/MergerFactory.java
deleted file mode 100644
index 92e064b..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/MergerFactory.java
+++ /dev/null
@@ -1,142 +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.merge;
-
-import java.util.Collection;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbRelationship;
-
-/**
- * All {@link MergerToken}s should be created from a {@link MergerFactory} obtained from
- * {@link DbAdapter#mergerFactory()} so that the {@link DbAdapter} are able to provide
- * {@link MergerToken} subclasses.
- *
- * @see DbAdapter#mergerFactory()
- */
-public class MergerFactory {
-
- public MergerToken createCreateTableToModel(DbEntity entity) {
- return new CreateTableToModel(entity);
- }
-
- public MergerToken createCreateTableToDb(DbEntity entity) {
- return new CreateTableToDb(entity);
- }
-
- public MergerToken createDropTableToModel(DbEntity entity) {
- return new DropTableToModel(entity);
- }
-
- public MergerToken createDropTableToDb(DbEntity entity) {
- return new DropTableToDb(entity);
- }
-
- public MergerToken createAddColumnToModel(DbEntity entity, DbAttribute column) {
- return new AddColumnToModel(entity, column);
- }
-
- public MergerToken createAddColumnToDb(DbEntity entity, DbAttribute column) {
- return new AddColumnToDb(entity, column);
- }
-
- public MergerToken createDropColumnToModel(DbEntity entity, DbAttribute column) {
- return new DropColumnToModel(entity, column);
- }
-
- public MergerToken createDropColumnToDb(DbEntity entity, DbAttribute column) {
- return new DropColumnToDb(entity, column);
- }
-
- public MergerToken createSetNotNullToModel(DbEntity entity, DbAttribute column) {
- return new SetNotNullToModel(entity, column);
- }
-
- public MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column) {
- return new SetNotNullToDb(entity, column);
- }
-
- public MergerToken createSetAllowNullToModel(DbEntity entity, DbAttribute column) {
- return new SetAllowNullToModel(entity, column);
- }
-
- public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
- return new SetAllowNullToDb(entity, column);
- }
-
- public MergerToken createSetValueForNullToDb(DbEntity entity, DbAttribute column, ValueForNullProvider valueForNullProvider){
- return new SetValueForNullToDb(entity, column, valueForNullProvider);
- }
-
- public MergerToken createSetColumnTypeToModel(
- DbEntity entity,
- DbAttribute columnOriginal,
- DbAttribute columnNew) {
- return new SetColumnTypeToModel(entity, columnOriginal, columnNew);
- }
-
- public MergerToken createSetColumnTypeToDb(
- DbEntity entity,
- DbAttribute columnOriginal,
- DbAttribute columnNew) {
- return new SetColumnTypeToDb(entity, columnOriginal, columnNew);
- }
-
- public MergerToken createAddRelationshipToDb(DbEntity entity, DbRelationship rel) {
- return new AddRelationshipToDb(entity, rel);
- }
-
- public MergerToken createAddRelationshipToModel(DbEntity entity, DbRelationship rel) {
- return new AddRelationshipToModel(entity, rel);
- }
-
- public MergerToken createDropRelationshipToDb(DbEntity entity, DbRelationship rel) {
- return new DropRelationshipToDb(entity, rel);
- }
-
- public MergerToken createDropRelationshipToModel(DbEntity entity, DbRelationship rel) {
- return new DropRelationshipToModel(entity, rel);
- }
-
- public MergerToken createSetPrimaryKeyToDb(
- DbEntity entity,
- Collection<DbAttribute> primaryKeyOriginal,
- Collection<DbAttribute> primaryKeyNew,
- String detectedPrimaryKeyName) {
- return new SetPrimaryKeyToDb(
- entity,
- primaryKeyOriginal,
- primaryKeyNew,
- detectedPrimaryKeyName);
- }
-
- public MergerToken createSetPrimaryKeyToModel(
- DbEntity entity,
- Collection<DbAttribute> primaryKeyOriginal,
- Collection<DbAttribute> primaryKeyNew,
- String detectedPrimaryKeyName) {
- return new SetPrimaryKeyToModel(
- entity,
- primaryKeyOriginal,
- primaryKeyNew,
- detectedPrimaryKeyName);
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/MergerToken.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/MergerToken.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/MergerToken.java
deleted file mode 100644
index 99af419..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/MergerToken.java
+++ /dev/null
@@ -1,51 +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.merge;
-
-/**
- * Represents a minimal atomic synchronization operation between database and Cayenne model.
- */
-public interface MergerToken {
-
- String getTokenName();
-
- String getTokenValue();
-
- /**
- * The direction of this token. One of {@link MergeDirection#TO_DB} or
- * {@link MergeDirection#TO_MODEL}
- */
- MergeDirection getDirection();
-
- /**
- * Create a complimentary token with the reverse direction. AddColumn in one direction becomes
- * DropColumn in the other direction.
- * <p>
- * Not all tokens are reversible.
- */
- MergerToken createReverse(MergerFactory factory);
-
- /**
- * Executes synchronization operation.
- *
- * @param mergerContext operation context.
- */
- void execute(MergerContext mergerContext);
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/ModelMergeDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/ModelMergeDelegate.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/ModelMergeDelegate.java
deleted file mode 100644
index f003752..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/ModelMergeDelegate.java
+++ /dev/null
@@ -1,65 +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.merge;
-
-import org.apache.cayenne.access.DbLoaderDelegate;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.ObjAttribute;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.map.ObjRelationship;
-
-/**
- * A interface used to tell about modifications performed on the model by
- * {@link MergerToken} with {@link MergeDirection#TO_MODEL}
- *
- * @see DbLoaderDelegate
- */
-public interface ModelMergeDelegate {
-
- public void dbEntityAdded(DbEntity ent);
-
- public void dbEntityRemoved(DbEntity ent);
-
- public void objEntityAdded(ObjEntity ent);
-
- public void objEntityRemoved(ObjEntity ent);
-
- public void dbAttributeAdded(DbAttribute att);
-
- public void dbAttributeRemoved(DbAttribute att);
-
- public void dbAttributeModified(DbAttribute att);
-
- public void objAttributeAdded(ObjAttribute att);
-
- public void objAttributeRemoved(ObjAttribute att);
-
- public void objAttributeModified(ObjAttribute att);
-
- public void dbRelationshipAdded(DbRelationship rel);
-
- public void dbRelationshipRemoved(DbRelationship rel);
-
- public void objRelationshipAdded(ObjRelationship rel);
-
- public void objRelationshipRemoved(ObjRelationship rel);
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/ProxyModelMergeDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/ProxyModelMergeDelegate.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/ProxyModelMergeDelegate.java
deleted file mode 100644
index ad6a4a9..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/ProxyModelMergeDelegate.java
+++ /dev/null
@@ -1,108 +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.merge;
-
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.ObjAttribute;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.map.ObjRelationship;
-
-/**
- * @since 4.0
- */
-public class ProxyModelMergeDelegate implements ModelMergeDelegate {
-
- private final ModelMergeDelegate delegate;
-
- public ProxyModelMergeDelegate(ModelMergeDelegate delegate) {
- this.delegate = delegate;
- }
-
- @Override
- public void dbEntityAdded(DbEntity ent) {
- delegate.dbEntityAdded(ent);
- }
-
- @Override
- public void dbEntityRemoved(DbEntity ent) {
- delegate.dbEntityRemoved(ent);
- }
-
- @Override
- public void objEntityAdded(ObjEntity ent) {
- delegate.objEntityAdded(ent);
- }
-
- @Override
- public void objEntityRemoved(ObjEntity ent) {
- delegate.objEntityRemoved(ent);
- }
-
- @Override
- public void dbAttributeAdded(DbAttribute att) {
- delegate.dbAttributeAdded(att);
- }
-
- @Override
- public void dbAttributeRemoved(DbAttribute att) {
- delegate.dbAttributeRemoved(att);
- }
-
- @Override
- public void dbAttributeModified(DbAttribute att) {
- delegate.dbAttributeModified(att);
- }
-
- @Override
- public void objAttributeAdded(ObjAttribute att) {
- delegate.objAttributeAdded(att);
- }
-
- @Override
- public void objAttributeRemoved(ObjAttribute att) {
- delegate.objAttributeRemoved(att);
- }
-
- @Override
- public void objAttributeModified(ObjAttribute att) {
- delegate.objAttributeModified(att);
- }
-
- @Override
- public void dbRelationshipAdded(DbRelationship rel) {
- delegate.dbRelationshipAdded(rel);
- }
-
- @Override
- public void dbRelationshipRemoved(DbRelationship rel) {
- delegate.dbRelationshipRemoved(rel);
- }
-
- @Override
- public void objRelationshipAdded(ObjRelationship rel) {
- delegate.objRelationshipAdded(rel);
- }
-
- @Override
- public void objRelationshipRemoved(ObjRelationship rel) {
- delegate.objRelationshipRemoved(rel);
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/SetAllowNullToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/SetAllowNullToDb.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/SetAllowNullToDb.java
deleted file mode 100644
index 07f677c..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/SetAllowNullToDb.java
+++ /dev/null
@@ -1,56 +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.merge;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-
-/**
- * A {@link MergerToken} to add a "allow null" clause to a column.
- *
- */
-public class SetAllowNullToDb extends AbstractToDbToken.EntityAndColumn {
-
- public SetAllowNullToDb(DbEntity entity, DbAttribute column) {
- super("Set Allow Null", entity, column);
- }
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- StringBuilder sqlBuffer = new StringBuilder();
- QuotingStrategy context = adapter.getQuotingStrategy();
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
- sqlBuffer.append(" ALTER COLUMN ");
- sqlBuffer.append(context.quotedName(getColumn()));
- sqlBuffer.append(" DROP NOT NULL");
-
- return Collections.singletonList(sqlBuffer.toString());
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return factory.createSetNotNullToModel(getEntity(), getColumn());
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/SetAllowNullToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/SetAllowNullToModel.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/SetAllowNullToModel.java
deleted file mode 100644
index 049240d..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/SetAllowNullToModel.java
+++ /dev/null
@@ -1,42 +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.merge;
-
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-
-/**
- * A {@link MergerToken} to set the mandatory field of a {@link DbAttribute} to false
- *
- */
-public class SetAllowNullToModel extends AbstractToModelToken.EntityAndColumn {
-
- public SetAllowNullToModel(DbEntity entity, DbAttribute column) {
- super("Set Allow Null", entity, column);
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return factory.createSetNotNullToDb(getEntity(), getColumn());
- }
-
- public void execute(MergerContext mergerContext) {
- getColumn().setMandatory(false);
- mergerContext.getModelMergeDelegate().dbAttributeModified(getColumn());
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/SetColumnTypeToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/SetColumnTypeToDb.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/SetColumnTypeToDb.java
deleted file mode 100644
index 466a9d9..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/SetColumnTypeToDb.java
+++ /dev/null
@@ -1,119 +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.merge;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.JdbcAdapter;
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.dba.TypesMapping;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-
-/**
- * An {@link MergerToken} to use to set type, length and precision.
- */
-public class SetColumnTypeToDb extends AbstractToDbToken.Entity {
-
- private DbAttribute columnOriginal;
- private DbAttribute columnNew;
-
- public SetColumnTypeToDb(DbEntity entity, DbAttribute columnOriginal, DbAttribute columnNew) {
- super("Set Column Type", entity);
- this.columnOriginal = columnOriginal;
- this.columnNew = columnNew;
- }
-
- /**
- * append the part of the token before the actual column data type
- * @param context
- */
- protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
- sqlBuffer.append("ALTER TABLE ");
- sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
- sqlBuffer.append(" ALTER ");
- sqlBuffer.append(context.quotedName(columnNew));
- sqlBuffer.append(" TYPE ");
- }
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- StringBuffer sqlBuffer = new StringBuffer();
- appendPrefix(sqlBuffer, adapter.getQuotingStrategy());
-
- sqlBuffer.append(JdbcAdapter.getType(adapter, columnNew));
- sqlBuffer.append(JdbcAdapter.sizeAndPrecision(adapter, columnNew));
-
- return Collections.singletonList(sqlBuffer.toString());
- }
-
- @Override
- public String getTokenValue() {
- StringBuilder sb = new StringBuilder();
- sb.append(getEntity().getName());
- sb.append(".");
- sb.append(columnNew.getName());
-
- if (columnOriginal.getType() != columnNew.getType()) {
- sb.append(" type: ");
- sb.append(TypesMapping.getSqlNameByType(columnOriginal.getType()));
- sb.append(" -> ");
- sb.append(TypesMapping.getSqlNameByType(columnNew.getType()));
- }
-
- if (columnOriginal.getMaxLength() != columnNew.getMaxLength()) {
- sb.append(" maxLength: ");
- sb.append(columnOriginal.getMaxLength());
- sb.append(" -> ");
- sb.append(columnNew.getMaxLength());
- }
-
- if (columnOriginal.getAttributePrecision() != columnNew.getAttributePrecision()) {
- sb.append(" precision: ");
- sb.append(columnOriginal.getAttributePrecision());
- sb.append(" -> ");
- sb.append(columnNew.getAttributePrecision());
- }
-
- if (columnOriginal.getScale() != columnNew.getScale()) {
- sb.append(" scale: ");
- sb.append(columnOriginal.getScale());
- sb.append(" -> ");
- sb.append(columnNew.getScale());
- }
-
- return sb.toString();
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return factory.createSetColumnTypeToModel(getEntity(), columnNew, columnOriginal);
- }
-
- public DbAttribute getColumnOriginal() {
- return columnOriginal;
- }
-
- public DbAttribute getColumnNew() {
- return columnNew;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/SetColumnTypeToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/SetColumnTypeToModel.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/SetColumnTypeToModel.java
deleted file mode 100644
index 784bc53..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/SetColumnTypeToModel.java
+++ /dev/null
@@ -1,101 +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.merge;
-
-import org.apache.cayenne.dba.TypesMapping;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-
-/**
- * A {@link MergerToken} that modifies one original {@link DbAttribute} to match another
- * new {@link DbAttribute}s type, maxLength and precision. The name and mandatory fields
- * are not modified by this token.
- *
- */
-public class SetColumnTypeToModel extends AbstractToModelToken.Entity {
-
- private DbAttribute columnOriginal;
- private DbAttribute columnNew;
-
- public SetColumnTypeToModel(DbEntity entity, DbAttribute columnOriginal,
- DbAttribute columnNew) {
- super("Set Column Type", entity);
- this.columnOriginal = columnOriginal;
- this.columnNew = columnNew;
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return factory.createSetColumnTypeToDb(getEntity(), columnNew, columnOriginal);
- }
-
- public void execute(MergerContext mergerContext) {
- columnOriginal.setType(columnNew.getType());
- columnOriginal.setMaxLength(columnNew.getMaxLength());
- columnOriginal.setAttributePrecision(columnNew.getAttributePrecision());
- columnOriginal.setScale(columnNew.getScale());
- mergerContext.getModelMergeDelegate().dbAttributeModified(columnOriginal);
- }
-
- @Override
- public String getTokenValue() {
- StringBuilder sb = new StringBuilder();
- sb.append(getEntity().getName());
- sb.append(".");
- sb.append(columnNew.getName());
-
- if (columnOriginal.getType() != columnNew.getType()) {
- sb.append(" type: ");
- sb.append(TypesMapping.getSqlNameByType(columnOriginal.getType()));
- sb.append(" -> ");
- sb.append(TypesMapping.getSqlNameByType(columnNew.getType()));
- }
-
- if (columnOriginal.getMaxLength() != columnNew.getMaxLength()) {
- sb.append(" maxLength: ");
- sb.append(columnOriginal.getMaxLength());
- sb.append(" -> ");
- sb.append(columnNew.getMaxLength());
- }
-
- if (columnOriginal.getAttributePrecision() != columnNew.getAttributePrecision()) {
- sb.append(" precision: ");
- sb.append(columnOriginal.getAttributePrecision());
- sb.append(" -> ");
- sb.append(columnNew.getAttributePrecision());
- }
-
- if (columnOriginal.getScale() != columnNew.getScale()) {
- sb.append(" scale: ");
- sb.append(columnOriginal.getScale());
- sb.append(" -> ");
- sb.append(columnNew.getScale());
- }
-
- return sb.toString();
- }
-
- public DbAttribute getColumnOriginal() {
- return columnOriginal;
- }
-
- public DbAttribute getColumnNew() {
- return columnNew;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/SetNotNullToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/SetNotNullToDb.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/SetNotNullToDb.java
deleted file mode 100644
index 60b5ad5..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/SetNotNullToDb.java
+++ /dev/null
@@ -1,50 +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.merge;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-
-/**
- * A {@link MergerToken} to add a "not null" clause to a column.
- */
-public class SetNotNullToDb extends AbstractToDbToken.EntityAndColumn {
-
- public SetNotNullToDb(DbEntity entity, DbAttribute column) {
- super("Set Not Null", entity, column);
- }
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- QuotingStrategy context = adapter.getQuotingStrategy();
-
- return Collections.singletonList("ALTER TABLE " + context.quotedFullyQualifiedName(getEntity())
- + " ALTER COLUMN " + context.quotedName(getColumn()) + " SET NOT NULL");
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return factory.createSetAllowNullToModel(getEntity(), getColumn());
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/SetNotNullToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/SetNotNullToModel.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/SetNotNullToModel.java
deleted file mode 100644
index 767f9e5..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/SetNotNullToModel.java
+++ /dev/null
@@ -1,42 +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.merge;
-
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-
-/**
- * A {@link MergerToken} to set the mandatory field of a {@link DbAttribute} to true
- *
- */
-public class SetNotNullToModel extends AbstractToModelToken.EntityAndColumn {
-
- public SetNotNullToModel(DbEntity entity, DbAttribute column) {
- super("Set Not Null", entity, column);
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return factory.createSetAllowNullToDb(getEntity(), getColumn());
- }
-
- public void execute(MergerContext mergerContext) {
- getColumn().setMandatory(true);
- mergerContext.getModelMergeDelegate().dbAttributeModified(getColumn());
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/SetPrimaryKeyToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/SetPrimaryKeyToDb.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/SetPrimaryKeyToDb.java
deleted file mode 100644
index 8f467fa..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/SetPrimaryKeyToDb.java
+++ /dev/null
@@ -1,85 +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.merge;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.QuotingStrategy;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-
-public class SetPrimaryKeyToDb extends AbstractToDbToken.Entity {
-
- private Collection<DbAttribute> primaryKeyOriginal;
- private Collection<DbAttribute> primaryKeyNew;
- private String detectedPrimaryKeyName;
-
- public SetPrimaryKeyToDb(DbEntity entity, Collection<DbAttribute> primaryKeyOriginal,
- Collection<DbAttribute> primaryKeyNew, String detectedPrimaryKeyName) {
- super("Set Primary Key", entity);
-
- this.primaryKeyOriginal = primaryKeyOriginal;
- this.primaryKeyNew = primaryKeyNew;
- this.detectedPrimaryKeyName = detectedPrimaryKeyName;
- }
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- List<String> sqls = new ArrayList<String>();
- if (!primaryKeyOriginal.isEmpty()) {
- appendDropOriginalPrimaryKeySQL(adapter, sqls);
- }
- appendAddNewPrimaryKeySQL(adapter, sqls);
- return sqls;
- }
-
- protected void appendDropOriginalPrimaryKeySQL(DbAdapter adapter, List<String> sqls) {
- if (detectedPrimaryKeyName == null) {
- return;
- }
- sqls.add("ALTER TABLE " + adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity())
- + " DROP CONSTRAINT " + detectedPrimaryKeyName);
- }
-
- protected void appendAddNewPrimaryKeySQL(DbAdapter adapter, List<String> sqls) {
- QuotingStrategy quotingStrategy = adapter.getQuotingStrategy();
-
- StringBuilder sql = new StringBuilder();
- sql.append("ALTER TABLE ");
- sql.append(quotingStrategy.quotedFullyQualifiedName(getEntity()));
- sql.append(" ADD PRIMARY KEY (");
- for (Iterator<DbAttribute> it = primaryKeyNew.iterator(); it.hasNext();) {
- sql.append(quotingStrategy.quotedName(it.next()));
- if (it.hasNext()) {
- sql.append(", ");
- }
- }
- sql.append(")");
- sqls.add(sql.toString());
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return factory.createSetPrimaryKeyToModel(getEntity(), primaryKeyNew, primaryKeyOriginal,
- detectedPrimaryKeyName);
- }
-}
[12/15] cayenne git commit: CAY-2116 Split schema synchronization
code in a separate module
Posted by aa...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbLoader.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbLoader.java
new file mode 100644
index 0000000..a6f286a
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbLoader.java
@@ -0,0 +1,829 @@
+/*****************************************************************
+ * 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.dbsync.reverse;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.TypesMapping;
+import org.apache.cayenne.dbsync.reverse.filters.CatalogFilter;
+import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig;
+import org.apache.cayenne.dbsync.reverse.filters.PatternFilter;
+import org.apache.cayenne.dbsync.reverse.filters.SchemaFilter;
+import org.apache.cayenne.dbsync.reverse.filters.TableFilter;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.DbRelationshipDetected;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.map.ProcedureParameter;
+import org.apache.cayenne.map.naming.DefaultUniqueNameGenerator;
+import org.apache.cayenne.map.naming.ExportedKey;
+import org.apache.cayenne.map.naming.LegacyNameGenerator;
+import org.apache.cayenne.map.naming.NameCheckers;
+import org.apache.cayenne.map.naming.ObjectNameGenerator;
+import org.apache.cayenne.dbsync.merge.EntityMergeSupport;
+import org.apache.cayenne.util.EqualsBuilder;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * Performs reverse engineering of the database. It can create
+ * DataMaps using database meta data obtained via JDBC driver.
+ *
+ * @since 4.0
+ */
+public class DbLoader {
+
+ private static final Log LOGGER = LogFactory.getLog(DbLoader.class);
+
+ public static final String WILDCARD = "%";
+ public static final String WILDCARD_PATTERN = ".*";
+
+ private final Connection connection;
+ private final DbAdapter adapter;
+ private final DbLoaderDelegate delegate;
+
+ private boolean creatingMeaningfulPK;
+
+ private DatabaseMetaData metaData;
+
+ /**
+ * Strategy for choosing names for entities, attributes and relationships
+ */
+ private ObjectNameGenerator nameGenerator;
+
+ /**
+ * Creates new DbLoader.
+ */
+ public DbLoader(Connection connection, DbAdapter adapter, DbLoaderDelegate delegate) {
+ this(connection, adapter, delegate, new LegacyNameGenerator());
+ }
+
+ /**
+ * Creates new DbLoader with specified naming strategy.
+ *
+ * @since 3.0
+ */
+ public DbLoader(Connection connection, DbAdapter adapter, DbLoaderDelegate delegate, ObjectNameGenerator strategy) {
+ this.adapter = adapter;
+ this.connection = connection;
+ this.delegate = delegate == null ? new DefaultDbLoaderDelegate() : delegate;
+
+ setNameGenerator(strategy);
+ }
+
+ /**
+ * Returns DatabaseMetaData object associated with this DbLoader.
+ */
+ private DatabaseMetaData getMetaData() throws SQLException {
+ if (metaData == null) {
+ metaData = connection.getMetaData();
+ }
+ 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
+ */
+ public void setCreatingMeaningfulPK(boolean creatingMeaningfulPK) {
+ this.creatingMeaningfulPK = creatingMeaningfulPK;
+ }
+
+ /**
+ * Returns true if the generator should map all primary key columns as
+ * ObjAttributes.
+ *
+ * @since 3.0
+ */
+ public boolean isCreatingMeaningfulPK() {
+ return creatingMeaningfulPK;
+ }
+
+ /**
+ * Returns database connection used by this DbLoader.
+ *
+ * @since 3.0
+ */
+ public Connection getConnection() {
+ return connection;
+ }
+
+ /**
+ * Returns DbAdapter associated with this DbLoader.
+ *
+ * @since 1.1
+ */
+ public DbAdapter getAdapter() {
+ return adapter;
+ }
+
+ /**
+ * Retrieves catalogs for the database associated with this DbLoader.
+ *
+ * @return List with the catalog names, empty Array if none found.
+ */
+ public List<String> getCatalogs() throws SQLException {
+ try (ResultSet rs = getMetaData().getCatalogs()) {
+ return getStrings(rs);
+ }
+ }
+
+ /**
+ * Retrieves the schemas for the database.
+ *
+ * @return List with the schema names, empty Array if none found.
+ */
+ public List<String> getSchemas() throws SQLException {
+
+ try (ResultSet rs = getMetaData().getSchemas()) {
+ return getStrings(rs);
+ }
+ }
+
+ private static List<String> getStrings(ResultSet rs) throws SQLException {
+ List<String> strings = new ArrayList<String>();
+
+ while (rs.next()) {
+ strings.add(rs.getString(1));
+ }
+
+ return strings;
+ }
+
+ /**
+ * Returns all the table types for the given database. Types may be such as
+ * Typical types are "TABLE", "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
+ * "LOCAL TEMPORARY", "ALIAS", "SYNONYM"., etc.
+ *
+ * @return List of Strings, empty array if nothing found.
+ */
+ public List<String> getTableTypes() throws SQLException {
+ List<String> types = new ArrayList<String>();
+
+ try (ResultSet rs = getMetaData().getTableTypes();) {
+ while (rs.next()) {
+ types.add(rs.getString("TABLE_TYPE").trim());
+ }
+ }
+
+ return types;
+ }
+
+ /**
+ * Creates an ObjEntity for each DbEntity in the map.
+ */
+ public Collection<ObjEntity> loadObjEntities(DataMap map, DbLoaderConfiguration config,
+ Collection<DbEntity> entities) {
+ Collection<ObjEntity> loadedEntities = DbLoader.loadObjEntities(map, config, entities, nameGenerator);
+
+ createEntityMerger(map).synchronizeWithDbEntities(loadedEntities);
+
+ return loadedEntities;
+ }
+
+ public static Collection<ObjEntity> loadObjEntities(DataMap map, DbLoaderConfiguration config,
+ Collection<DbEntity> entities, ObjectNameGenerator nameGenerator) {
+ if (entities.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ Collection<ObjEntity> loadedEntities = new ArrayList<ObjEntity>(entities.size());
+
+ // doLoad empty ObjEntities for all the tables
+ for (DbEntity dbEntity : entities) {
+
+ // check if there are existing entities
+
+ // TODO: performance. This is an O(n^2) search and it shows on
+ // YourKit profiles. Pre-cache mapped entities perhaps (?)
+ Collection<ObjEntity> existing = map.getMappedEntities(dbEntity);
+ if (!existing.isEmpty()) {
+ loadedEntities.addAll(existing);
+ continue;
+ }
+
+ String objEntityName = DefaultUniqueNameGenerator.generate(NameCheckers.objEntity, map,
+ nameGenerator.createObjEntityName(dbEntity));
+
+ ObjEntity objEntity = new ObjEntity(objEntityName);
+ objEntity.setDbEntity(dbEntity);
+ objEntity.setClassName(config.getGenericClassName() != null ? config.getGenericClassName() : map
+ .getNameWithDefaultPackage(objEntity.getName()));
+
+ map.addObjEntity(objEntity);
+ loadedEntities.add(objEntity);
+ }
+
+ return loadedEntities;
+ }
+
+ /**
+ * @since 4.0
+ */
+ protected EntityMergeSupport createEntityMerger(DataMap map) {
+ return new EntityMergeSupport(map, nameGenerator, !creatingMeaningfulPK);
+ }
+
+ protected void loadDbRelationships(DbLoaderConfiguration config, String catalog, String schema,
+ List<DbEntity> tables) throws SQLException {
+ if (config.isSkipRelationshipsLoading()) {
+ return;
+ }
+
+ // Get all the foreign keys referencing this table
+ Map<String, DbEntity> tablesMap = new HashMap<>();
+ for (DbEntity table : tables) {
+ tablesMap.put(table.getName(), table);
+ }
+
+ Map<String, Set<ExportedKey>> keys = loadExportedKeys(config, catalog, schema, tablesMap);
+ for (Map.Entry<String, Set<ExportedKey>> entry : keys.entrySet()) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Process keys for: " + entry.getKey());
+ }
+
+ Set<ExportedKey> exportedKeys = entry.getValue();
+ ExportedKey key = exportedKeys.iterator().next();
+ if (key == null) {
+ throw new IllegalStateException();
+ }
+
+ DbEntity pkEntity = tablesMap.get(key.getPKTableName());
+ if (pkEntity == null) {
+ skipRelationLog(key, key.getPKTableName());
+ continue;
+ }
+
+ DbEntity fkEntity = tablesMap.get(key.getFKTableName());
+ if (fkEntity == null) {
+ skipRelationLog(key, key.getFKTableName());
+ continue;
+ }
+
+ if (!new EqualsBuilder().append(pkEntity.getCatalog(), key.pkCatalog)
+ .append(pkEntity.getSchema(), key.pkSchema).append(fkEntity.getCatalog(), key.fkCatalog)
+ .append(fkEntity.getSchema(), key.fkSchema).isEquals()) {
+
+ LOGGER.info("Skip relation: '" + key + "' because it related to objects from other catalog/schema");
+ LOGGER.info(" relation primary key: '" + key.pkCatalog + "." + key.pkSchema + "'");
+ LOGGER.info(" primary key entity: '" + pkEntity.getCatalog() + "." + pkEntity.getSchema() + "'");
+ LOGGER.info(" relation foreign key: '" + key.fkCatalog + "." + key.fkSchema + "'");
+ LOGGER.info(" foreign key entity: '" + fkEntity.getCatalog() + "." + fkEntity.getSchema() + "'");
+ continue;
+ }
+
+ // forwardRelationship is a reference from table with primary key
+ DbRelationship forwardRelationship = new DbRelationship(generateName(pkEntity, key, true));
+ forwardRelationship.setSourceEntity(pkEntity);
+ forwardRelationship.setTargetEntityName(fkEntity);
+
+ // forwardRelationship is a reference from table with foreign key,
+ // it is what exactly we load from db
+ DbRelationshipDetected reverseRelationship = new DbRelationshipDetected(generateName(fkEntity, key, false));
+ reverseRelationship.setFkName(key.getFKName());
+ reverseRelationship.setSourceEntity(fkEntity);
+ reverseRelationship.setTargetEntityName(pkEntity);
+ reverseRelationship.setToMany(false);
+
+ createAndAppendJoins(exportedKeys, pkEntity, fkEntity, forwardRelationship, reverseRelationship);
+
+ boolean toDependentPK = isToDependentPK(forwardRelationship);
+ forwardRelationship.setToDependentPK(toDependentPK);
+
+ boolean isOneToOne = toDependentPK
+ && fkEntity.getPrimaryKeys().size() == forwardRelationship.getJoins().size();
+
+ forwardRelationship.setToMany(!isOneToOne);
+ forwardRelationship.setName(generateName(pkEntity, key, !isOneToOne));
+
+ if (delegate.dbRelationshipLoaded(fkEntity, reverseRelationship)) {
+ fkEntity.addRelationship(reverseRelationship);
+ }
+ if (delegate.dbRelationshipLoaded(pkEntity, forwardRelationship)) {
+ pkEntity.addRelationship(forwardRelationship);
+ }
+ }
+ }
+
+ private boolean isToDependentPK(DbRelationship forwardRelationship) {
+ for (DbJoin dbJoin : forwardRelationship.getJoins()) {
+ if (!dbJoin.getTarget().isPrimaryKey()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private void createAndAppendJoins(Set<ExportedKey> exportedKeys, DbEntity pkEntity, DbEntity fkEntity,
+ DbRelationship forwardRelationship, DbRelationshipDetected reverseRelationship) {
+ for (ExportedKey exportedKey : exportedKeys) {
+ // Create and append joins
+ String pkName = exportedKey.getPKColumnName();
+ String fkName = exportedKey.getFKColumnName();
+
+ // skip invalid joins...
+ DbAttribute pkAtt = pkEntity.getAttribute(pkName);
+ if (pkAtt == null) {
+ LOGGER.info("no attribute for declared primary key: " + pkName);
+ continue;
+ }
+
+ DbAttribute fkAtt = fkEntity.getAttribute(fkName);
+ if (fkAtt == null) {
+ LOGGER.info("no attribute for declared foreign key: " + fkName);
+ continue;
+ }
+
+ forwardRelationship.addJoin(new DbJoin(forwardRelationship, pkName, fkName));
+ reverseRelationship.addJoin(new DbJoin(reverseRelationship, fkName, pkName));
+ }
+ }
+
+ private Map<String, Set<ExportedKey>> loadExportedKeys(DbLoaderConfiguration config, String catalog, String schema,
+ Map<String, DbEntity> tables) throws SQLException {
+ Map<String, Set<ExportedKey>> keys = new HashMap<>();
+
+ for (DbEntity dbEntity : tables.values()) {
+ if (!delegate.dbRelationship(dbEntity)) {
+ continue;
+ }
+
+ ResultSet rs;
+ try {
+ rs = getMetaData().getExportedKeys(catalog, schema, dbEntity.getName());
+ } catch (SQLException cay182Ex) {
+ // Sybase-specific - the line above blows on VIEWS, see CAY-182.
+ LOGGER.info(
+ "Error getting relationships for '" + catalog + "." + schema + "', ignoring. "
+ + cay182Ex.getMessage(), cay182Ex);
+ return new HashMap<>();
+ }
+
+ try {
+ while (rs.next()) {
+ ExportedKey key = ExportedKey.extractData(rs);
+
+ DbEntity fkEntity = tables.get(key.getFKTableName());
+ if (fkEntity == null) {
+ skipRelationLog(key, key.getFKTableName());
+ continue;
+ }
+
+ if (config.getFiltersConfig().tableFilter(fkEntity.getCatalog(), fkEntity.getSchema())
+ .isIncludeTable(fkEntity.getName()) == null) {
+ continue;
+ }
+
+ Set<ExportedKey> exportedKeys = keys.get(key.getStrKey());
+ if (exportedKeys == null) {
+ exportedKeys = new TreeSet<ExportedKey>();
+
+ keys.put(key.getStrKey(), exportedKeys);
+ }
+ exportedKeys.add(key);
+ }
+
+ } finally {
+ rs.close();
+ }
+ }
+ return keys;
+ }
+
+ private void skipRelationLog(ExportedKey key, String tableName) {
+ // if (LOGGER.isDebugEnabled()) {
+ LOGGER.info("Skip relation: '" + key + "' because table '" + tableName + "' not found");
+ // }
+ }
+
+ private String generateName(DbEntity entity, ExportedKey key, boolean toMany) {
+ String forwardPreferredName = nameGenerator.createDbRelationshipName(key, toMany);
+ return DefaultUniqueNameGenerator.generate(NameCheckers.dbRelationship, entity, forwardPreferredName);
+ }
+
+ /**
+ * Flattens many-to-many relationships in the generated model.
+ */
+ public static void flattenManyToManyRelationships(DataMap map, Collection<ObjEntity> loadedObjEntities,
+ ObjectNameGenerator objectNameGenerator) {
+ if (loadedObjEntities.isEmpty()) {
+ return;
+ }
+ Collection<ObjEntity> entitiesForDelete = new LinkedList<ObjEntity>();
+
+ for (ObjEntity curEntity : loadedObjEntities) {
+ ManyToManyCandidateEntity entity = ManyToManyCandidateEntity.build(curEntity);
+
+ if (entity != null) {
+ entity.optimizeRelationships(objectNameGenerator);
+ entitiesForDelete.add(curEntity);
+ }
+ }
+
+ // remove needed entities
+ for (ObjEntity curDeleteEntity : entitiesForDelete) {
+ map.removeObjEntity(curDeleteEntity.getName(), true);
+ }
+ loadedObjEntities.removeAll(entitiesForDelete);
+ }
+
+ private void fireObjEntitiesAddedEvents(Collection<ObjEntity> loadedObjEntities) {
+ for (ObjEntity curEntity : loadedObjEntities) {
+ // notify delegate
+ if (delegate != null) {
+ delegate.objEntityAdded(curEntity);
+ }
+ }
+ }
+
+ /**
+ * By default we want to load Tables and Views for mo types
+ *
+ * @see DbLoader#getTableTypes()
+ * @since 4.0
+ */
+ public String[] getDefaultTableTypes() {
+ List<String> list = new ArrayList<String>(2);
+
+ String viewType = adapter.tableTypeForView();
+ if (viewType != null) {
+ list.add(viewType);
+ }
+
+ String tableType = adapter.tableTypeForTable();
+ if (tableType != null) {
+ list.add(tableType);
+ }
+
+ return list.toArray(new String[list.size()]);
+ }
+
+ /**
+ * Performs database reverse engineering and generates DataMap that contains
+ * default mapping of the tables and views. By default will include regular
+ * tables and views.
+ *
+ * @since 1.0.7
+ * @deprecated since 4.0 use
+ * {@link #load(DataMap, DbLoaderConfiguration)}
+ * method that supports catalogs.
+ */
+ @Deprecated
+ public DataMap loadDataMapFromDB(String schemaPattern, String tablePattern, DataMap dataMap) throws SQLException {
+
+ DbLoaderConfiguration configuration = new DbLoaderConfiguration();
+ configuration.setFiltersConfig(FiltersConfig.create(null, schemaPattern, TableFilter.include(tablePattern),
+ PatternFilter.INCLUDE_NOTHING));
+
+ load(dataMap, configuration);
+ return dataMap;
+ }
+
+ /**
+ * Performs database reverse engineering and generates DataMap object that
+ * contains default mapping of the tables and views. Allows to limit types
+ * of tables to read.
+ *
+ * @deprecated since 4.0 use
+ * {@link #load(DataMap, DbLoaderConfiguration)}
+ * method that supports catalogs.
+ */
+ @Deprecated
+ public DataMap loadDataMapFromDB(String schemaPattern, String tablePattern, String[] tableTypes, DataMap dataMap)
+ throws SQLException {
+ dataMap.clear();
+
+ DbLoaderConfiguration config = new DbLoaderConfiguration();
+ config.setFiltersConfig(FiltersConfig.create(null, schemaPattern, TableFilter.include(tablePattern),
+ PatternFilter.INCLUDE_NOTHING));
+ config.setTableTypes(tableTypes);
+
+ load(dataMap, config);
+ return dataMap;
+ }
+
+ /**
+ * Performs database reverse engineering based on the specified config and
+ * fills the specified DataMap object with DB and object mapping info.
+ *
+ * @since 4.0
+ */
+ 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();
+ }
+
+ for (CatalogFilter catalog : config.getFiltersConfig().catalogs) {
+ for (SchemaFilter schema : catalog.schemas) {
+
+ List<DbEntity> entities = createTableLoader(catalog.name, schema.name, schema.tables).loadDbEntities(
+ dataMap, config, types);
+
+ if (entities != null) {
+ loadDbRelationships(config, catalog.name, schema.name, entities);
+
+ prepareObjLayer(dataMap, config, entities);
+ }
+ }
+ }
+ }
+
+ protected DbTableLoader createTableLoader(String catalog, String schema, TableFilter filter) throws SQLException {
+ return new DbTableLoader(catalog, schema, getMetaData(), delegate, new DbAttributesPerSchemaLoader(catalog,
+ schema, getMetaData(), adapter, filter));
+ }
+
+ public void prepareObjLayer(DataMap dataMap, DbLoaderConfiguration config, Collection<DbEntity> entities) {
+ Collection<ObjEntity> loadedObjEntities = loadObjEntities(dataMap, config, entities);
+ flattenManyToManyRelationships(dataMap, loadedObjEntities, getNameGenerator());
+ fireObjEntitiesAddedEvents(loadedObjEntities);
+ }
+
+ /**
+ * Performs database reverse engineering to match the specified catalog,
+ * schema, table name and table type patterns and fills the specified
+ * DataMap object with DB and object mapping info.
+ *
+ * @since 4.0
+ */
+ public DataMap load(DbLoaderConfiguration config) throws SQLException {
+
+ DataMap dataMap = new DataMap();
+ load(dataMap, config);
+ loadProcedures(dataMap, config);
+
+ return dataMap;
+ }
+
+ /**
+ * Loads database stored procedures into the DataMap.
+ * <p>
+ * <i>As of 1.1 there is no boolean property or delegate method to make
+ * procedure loading optional or to implement custom merging logic, so
+ * currently this method is NOT CALLED from "loadDataMapFromDB" and should
+ * be invoked explicitly by the user. </i>
+ * </p>
+ *
+ * @since 1.1
+ * @deprecated since 4.0 use loadProcedures(DataMap, String, String, String)
+ * that supports "catalog" pattern.
+ */
+ @Deprecated
+ public void loadProceduresFromDB(String schemaPattern, String namePattern, DataMap dataMap) throws SQLException {
+ DbLoaderConfiguration configuration = new DbLoaderConfiguration();
+ configuration.setFiltersConfig(FiltersConfig.create(null, schemaPattern, TableFilter.everything(),
+ new PatternFilter().include(namePattern)));
+
+ loadProcedures(dataMap, configuration);
+ }
+
+ /**
+ * Loads database stored procedures into the DataMap.
+ * <p>
+ * <i>As of 1.1 there is no boolean property or delegate method to make
+ * procedure loading optional or to implement custom merging logic, so
+ * currently this method is NOT CALLED from "loadDataMapFromDB" and should
+ * be invoked explicitly by the user. </i>
+ * </p>
+ *
+ * @since 4.0
+ */
+ public Map<String, Procedure> loadProcedures(DataMap dataMap, DbLoaderConfiguration config) throws SQLException {
+
+ Map<String, Procedure> procedures = loadProcedures(config);
+ if (procedures.isEmpty()) {
+ return procedures;
+ }
+
+ loadProceduresColumns(config, procedures);
+
+ for (Procedure procedure : procedures.values()) {
+ dataMap.addProcedure(procedure);
+ }
+
+ return procedures;
+ }
+
+ private void loadProceduresColumns(DbLoaderConfiguration config, Map<String, Procedure> procedures)
+ throws SQLException {
+
+ for (CatalogFilter catalog : config.getFiltersConfig().catalogs) {
+ for (SchemaFilter schema : catalog.schemas) {
+ loadProceduresColumns(procedures, catalog.name, schema.name);
+ }
+ }
+ }
+
+ private void loadProceduresColumns(Map<String, Procedure> procedures, String catalog, String schema)
+ throws SQLException {
+
+ try (ResultSet columnsRS = getMetaData().getProcedureColumns(catalog, schema, null, null);) {
+ while (columnsRS.next()) {
+
+ String s = columnsRS.getString("PROCEDURE_SCHEM");
+ String name = columnsRS.getString("PROCEDURE_NAME");
+ String key = (s == null ? "" : s + '.') + name;
+ Procedure procedure = procedures.get(key);
+ if (procedure == null) {
+ continue;
+ }
+
+ ProcedureParameter column = loadProcedureParams(columnsRS, key, procedure);
+ if (column == null) {
+ continue;
+ }
+ procedure.addCallParameter(column);
+ }
+ }
+ }
+
+ private ProcedureParameter loadProcedureParams(ResultSet columnsRS, String key, Procedure procedure)
+ throws SQLException {
+ String columnName = columnsRS.getString("COLUMN_NAME");
+
+ // skip ResultSet columns, as they are not described in Cayenne
+ // procedures yet...
+ short type = columnsRS.getShort("COLUMN_TYPE");
+ if (type == DatabaseMetaData.procedureColumnResult) {
+ LOGGER.debug("skipping ResultSet column: " + key + "." + columnName);
+ }
+
+ if (columnName == null) {
+ if (type == DatabaseMetaData.procedureColumnReturn) {
+ LOGGER.debug("null column name, assuming result column: " + key);
+ columnName = "_return_value";
+ procedure.setReturningValue(true);
+ } else {
+ LOGGER.info("invalid null column name, skipping column : " + key);
+ return null;
+ }
+ }
+
+ int columnType = columnsRS.getInt("DATA_TYPE");
+
+ // ignore precision of non-decimal columns
+ int decimalDigits = -1;
+ if (TypesMapping.isDecimal(columnType)) {
+ decimalDigits = columnsRS.getShort("SCALE");
+ if (columnsRS.wasNull()) {
+ decimalDigits = -1;
+ }
+ }
+
+ ProcedureParameter column = new ProcedureParameter(columnName);
+ int direction = getDirection(type);
+ if (direction != -1) {
+ column.setDirection(direction);
+ }
+
+ column.setType(columnType);
+ column.setMaxLength(columnsRS.getInt("LENGTH"));
+ column.setPrecision(decimalDigits);
+
+ column.setProcedure(procedure);
+ return column;
+ }
+
+ private static int getDirection(short type) {
+ switch (type) {
+ case DatabaseMetaData.procedureColumnIn:
+ return ProcedureParameter.IN_PARAMETER;
+ case DatabaseMetaData.procedureColumnInOut:
+ return ProcedureParameter.IN_OUT_PARAMETER;
+ case DatabaseMetaData.procedureColumnOut:
+ return ProcedureParameter.OUT_PARAMETER;
+ default:
+ return -1;
+ }
+ }
+
+ private Map<String, Procedure> loadProcedures(DbLoaderConfiguration config) throws SQLException {
+ Map<String, Procedure> procedures = new HashMap<>();
+
+ FiltersConfig filters = config.getFiltersConfig();
+ for (CatalogFilter catalog : filters.catalogs) {
+ for (SchemaFilter schema : catalog.schemas) {
+ if (filters.proceduresFilter(catalog.name, schema.name).isEmpty()) {
+ continue;
+ }
+
+ procedures.putAll(loadProcedures(filters, catalog.name, schema.name));
+ }
+ }
+
+ return procedures;
+ }
+
+ private Map<String, Procedure> loadProcedures(FiltersConfig filters, String catalog, String schema)
+ throws SQLException {
+ Map<String, Procedure> procedures = new HashMap<>();
+ // get procedures
+
+ try (ResultSet rs = getMetaData().getProcedures(catalog, schema, WILDCARD);) {
+ while (rs.next()) {
+
+ String name = rs.getString("PROCEDURE_NAME");
+ Procedure procedure = new Procedure(name);
+ procedure.setCatalog(rs.getString("PROCEDURE_CAT"));
+ procedure.setSchema(rs.getString("PROCEDURE_SCHEM"));
+
+ if (!filters.proceduresFilter(procedure.getCatalog(), procedure.getSchema()).isInclude(
+ procedure.getName())) {
+ LOGGER.info("skipping Cayenne PK procedure: " + name);
+ continue;
+ }
+
+ switch (rs.getShort("PROCEDURE_TYPE")) {
+ case DatabaseMetaData.procedureNoResult:
+ case DatabaseMetaData.procedureResultUnknown:
+ procedure.setReturningValue(false);
+ break;
+ case DatabaseMetaData.procedureReturnsResult:
+ procedure.setReturningValue(true);
+ break;
+ }
+
+ procedures.put(procedure.getFullyQualifiedName(), procedure);
+ }
+ }
+ return procedures;
+ }
+
+ /**
+ * Sets new naming strategy for reverse engineering
+ *
+ * @since 3.0
+ */
+ public void setNameGenerator(ObjectNameGenerator strategy) {
+ if (strategy == null) {
+ LOGGER.warn("Attempt to set null into NameGenerator. LegacyNameGenerator will be used.");
+ this.nameGenerator = new LegacyNameGenerator();
+ } else {
+ this.nameGenerator = strategy;
+ }
+ }
+
+ /**
+ * @return naming strategy for reverse engineering
+ * @since 3.0
+ */
+ public ObjectNameGenerator getNameGenerator() {
+ return nameGenerator;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbLoaderConfiguration.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbLoaderConfiguration.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbLoaderConfiguration.java
new file mode 100644
index 0000000..e5421fe
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbLoaderConfiguration.java
@@ -0,0 +1,150 @@
+/*****************************************************************
+ * 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.dbsync.reverse;
+
+import org.apache.cayenne.dbsync.reverse.filters.TableFilter;
+import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig;
+import org.apache.cayenne.dbsync.reverse.filters.PatternFilter;
+
+/**
+ * @since 4.0
+ */
+public class DbLoaderConfiguration {
+
+ /**
+ * Returns a name of a generic class that should be used for all
+ * ObjEntities. The most common generic class is
+ * {@link org.apache.cayenne.CayenneDataObject}. If generic class name is
+ * null (which is the default), DbLoader will assign each entity a unique
+ * class name derived from the table name.
+ *
+ */
+ private String genericClassName;
+
+/*
+ // TODO: Andrus, 10/29/2005 - this type of filtering should be delegated to adapter
+ TODO by default should skip name.startsWith("BIN$")
+
+ private NameFilter tableFilter = NamePatternMatcher.build(null, null, "BIN$");
+
+ private NameFilter columnFilter;
+
+ private NameFilter proceduresFilter = new NameFilter() {
+ private final Collection<String> excludedProcedures = Arrays.asList(
+ "auto_pk_for_table",
+ "auto_pk_for_table;1" // the last name is some Mac OS X Sybase artifact
+ );
+
+ @Override
+ public boolean isIncluded(String string) {
+ return !excludedProcedures.contains(string);
+ }
+ };
+*/
+
+
+ /**
+ * Java class implementing org.apache.cayenne.map.naming.NamingStrategy.
+ * This is used to specify how ObjEntities will be mapped from the imported
+ * DB schema.
+ */
+ private String namingStrategy;
+
+ private Boolean skipRelationshipsLoading;
+
+ private Boolean skipPrimaryKeyLoading;
+
+ private String[] tableTypes;
+
+ private FiltersConfig filtersConfig;
+
+ public String getGenericClassName() {
+ return genericClassName;
+ }
+
+ public void setGenericClassName(String genericClassName) {
+ this.genericClassName = genericClassName;
+ }
+
+ public String[] getTableTypes() {
+ return tableTypes;
+ }
+
+ public void setTableTypes(String[] tableTypes) {
+ this.tableTypes = tableTypes;
+ }
+
+ public String getNamingStrategy() {
+ return namingStrategy;
+ }
+
+ public void setNamingStrategy(String namingStrategy) {
+ this.namingStrategy = namingStrategy;
+ }
+
+ public FiltersConfig getFiltersConfig() {
+ if (filtersConfig == null) {
+ // this case is used often in tests where config not initialized properly
+ return FiltersConfig.create(null, null, TableFilter.everything(), PatternFilter.INCLUDE_NOTHING);
+ }
+ return filtersConfig;
+ }
+
+ public void setFiltersConfig(FiltersConfig filtersConfig) {
+ this.filtersConfig = filtersConfig;
+ }
+
+ public boolean isSkipRelationshipsLoading() {
+ return skipRelationshipsLoading != null && skipRelationshipsLoading;
+ }
+
+ public Boolean getSkipRelationshipsLoading() {
+ return skipRelationshipsLoading;
+ }
+
+ public void setSkipRelationshipsLoading(Boolean skipRelationshipsLoading) {
+ this.skipRelationshipsLoading = skipRelationshipsLoading;
+ }
+
+ public void setSkipPrimaryKeyLoading(Boolean skipPrimaryKeyLoading) {
+ this.skipPrimaryKeyLoading = skipPrimaryKeyLoading;
+ }
+
+ public boolean getSkipPrimaryKeyLoading() {
+ return skipPrimaryKeyLoading;
+ }
+
+ public boolean isSkipPrimaryKeyLoading() {
+ return skipPrimaryKeyLoading != null && skipPrimaryKeyLoading;
+ }
+
+ @Override
+ public String toString() {
+ String res = "EntitiesFilters: " + getFiltersConfig();
+ if (isSkipRelationshipsLoading()) {
+ res += "\n Skip Loading Relationships! \n";
+ }
+
+ if (isSkipPrimaryKeyLoading()) {
+ res += "\n Skip Loading PrimaryKeys! \n";
+ }
+
+ return res;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbLoaderDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbLoaderDelegate.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbLoaderDelegate.java
new file mode 100644
index 0000000..35a61fb
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbLoaderDelegate.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.dbsync.reverse;
+
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.ObjEntity;
+
+/**
+ * DbLoaderDelegate defines API that allows to control the behavior of DbLoader
+ * during the database reverse-engineering. Delegate is also notified of the
+ * progress of reverse-engineering.
+ */
+public interface DbLoaderDelegate {
+
+ void dbEntityAdded(DbEntity entity);
+
+ void dbEntityRemoved(DbEntity entity);
+
+ /**
+ * Called before relationship loading for db-entity
+ * @param entity
+ *
+ * @return true in case you want process relationships for this entity
+ * false otherwise
+ */
+ boolean dbRelationship(DbEntity entity);
+
+ /**
+ * Called before relationship will be added into db-entity but after it was loaded from db
+ * @param entity
+ *
+ * @return true in case you want add this relationship into entity
+ * false otherwise
+ */
+ boolean dbRelationshipLoaded(DbEntity entity, DbRelationship relationship);
+
+ void objEntityAdded(ObjEntity entity);
+
+ void objEntityRemoved(ObjEntity entity);
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbTableLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbTableLoader.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbTableLoader.java
new file mode 100644
index 0000000..0d12e64
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbTableLoader.java
@@ -0,0 +1,195 @@
+/*****************************************************************
+ * 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.dbsync.reverse;
+
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.cayenne.dbsync.reverse.filters.PatternFilter;
+import org.apache.cayenne.dbsync.reverse.filters.TableFilter;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DetectedDbEntity;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * @since 4.0
+ */
+public class DbTableLoader {
+
+ private static final Log LOGGER = LogFactory.getLog(DbTableLoader.class);
+
+ private static final String WILDCARD = "%";
+
+ private final String catalog;
+ private final String schema;
+
+ private final DatabaseMetaData metaData;
+ private final DbLoaderDelegate delegate;
+
+ private final DbAttributesLoader attributesLoader;
+
+ public DbTableLoader(String catalog, String schema, DatabaseMetaData metaData, DbLoaderDelegate delegate,
+ DbAttributesLoader attributesLoader) {
+ this.catalog = catalog;
+ this.schema = schema;
+ this.metaData = metaData;
+ this.delegate = delegate;
+
+ this.attributesLoader = attributesLoader;
+ }
+
+ /**
+ * Returns all tables for given combination of the criteria. Tables returned
+ * as DbEntities without any attributes or relationships.
+ *
+ * @param types
+ * The types of table names to retrieve, null returns all types.
+ * @return
+ * @since 4.0
+ */
+ public List<DetectedDbEntity> getDbEntities(TableFilter filters, String[] types) throws SQLException {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Read tables: catalog=" + catalog + ", schema=" + schema + ", types=" + Arrays.toString(types));
+ }
+
+ List<DetectedDbEntity> tables = new LinkedList<DetectedDbEntity>();
+ try (ResultSet rs = metaData.getTables(catalog, schema, WILDCARD, types);) {
+ while (rs.next()) {
+ // Oracle 9i and newer has a nifty recycle bin feature... but we
+ // don't
+ // want dropped tables to be included here; in fact they may
+ // even result
+ // in errors on reverse engineering as their names have special
+ // chars like
+ // "/", etc. So skip them all together
+
+ String name = rs.getString("TABLE_NAME");
+ if (name == null) {
+ continue;
+ }
+
+ DetectedDbEntity table = new DetectedDbEntity(name);
+
+ String catalog = rs.getString("TABLE_CAT");
+ table.setCatalog(catalog);
+
+ String schema = rs.getString("TABLE_SCHEM");
+ table.setSchema(schema);
+ if (!(this.catalog == null || this.catalog.equals(catalog))
+ || !(this.schema == null || this.schema.equals(schema))) {
+
+ LOGGER.error(catalog + "." + schema + "." + name + " wrongly loaded for catalog/schema : "
+ + this.catalog + "." + this.schema);
+
+ continue;
+ }
+
+ PatternFilter includeTable = filters.isIncludeTable(table.getName());
+ if (includeTable != null) {
+ tables.add(table);
+ }
+ }
+ }
+ return tables;
+ }
+
+ /**
+ * Loads dbEntities for the specified tables.
+ *
+ * @param config
+ * @param types
+ */
+ public List<DbEntity> loadDbEntities(DataMap map, DbLoaderConfiguration config, String[] types) throws SQLException {
+ /** List of db entities to process. */
+
+ List<DetectedDbEntity> tables = getDbEntities(config.getFiltersConfig().tableFilter(catalog, schema), types);
+
+ List<DbEntity> dbEntities = new ArrayList<DbEntity>();
+ for (DbEntity dbEntity : tables) {
+ DbEntity oldEnt = map.getDbEntity(dbEntity.getName());
+ if (oldEnt != null) {
+ Collection<ObjEntity> oldObjEnt = map.getMappedEntities(oldEnt);
+ if (!oldObjEnt.isEmpty()) {
+ for (ObjEntity objEntity : oldObjEnt) {
+ LOGGER.debug("Delete ObjEntity: " + objEntity.getName());
+ map.removeObjEntity(objEntity.getName(), true);
+ delegate.objEntityRemoved(objEntity);
+ }
+ }
+
+ LOGGER.debug("Overwrite DbEntity: " + oldEnt.getName());
+ map.removeDbEntity(oldEnt.getName(), true);
+ delegate.dbEntityRemoved(oldEnt);
+ }
+
+ map.addDbEntity(dbEntity);
+
+ delegate.dbEntityAdded(dbEntity);
+
+ // delegate might have thrown this entity out... so check if it is
+ // still
+ // around before continuing processing
+ if (map.getDbEntity(dbEntity.getName()) == dbEntity) {
+ dbEntities.add(dbEntity);
+ attributesLoader.loadDbAttributes(dbEntity);
+ if (!config.isSkipPrimaryKeyLoading()) {
+ loadPrimaryKey(dbEntity);
+ }
+ }
+ }
+
+ return dbEntities;
+ }
+
+ private void loadPrimaryKey(DbEntity dbEntity) throws SQLException {
+
+ try (ResultSet rs = metaData.getPrimaryKeys(dbEntity.getCatalog(), dbEntity.getSchema(), dbEntity.getName());) {
+ while (rs.next()) {
+ String columnName = rs.getString("COLUMN_NAME");
+ DbAttribute attribute = dbEntity.getAttribute(columnName);
+
+ if (attribute != null) {
+ attribute.setPrimaryKey(true);
+ } else {
+ // why an attribute might be null is not quiet clear
+ // but there is a bug report 731406 indicating that it is
+ // possible
+ // so just print the warning, and ignore
+ LOGGER.warn("Can't locate attribute for primary key: " + columnName);
+ }
+
+ String pkName = rs.getString("PK_NAME");
+ if (pkName != null && dbEntity instanceof DetectedDbEntity) {
+ ((DetectedDbEntity) dbEntity).setPrimaryKeyName(pkName);
+ }
+
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DefaultDbLoaderDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DefaultDbLoaderDelegate.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DefaultDbLoaderDelegate.java
new file mode 100644
index 0000000..b39fd5f
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DefaultDbLoaderDelegate.java
@@ -0,0 +1,59 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * 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.dbsync.reverse;
+
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.ObjEntity;
+
+/**
+ * @since 4.0.
+ */
+public class DefaultDbLoaderDelegate implements DbLoaderDelegate {
+
+ @Override
+ public void dbEntityAdded(DbEntity entity) {
+
+ }
+
+ @Override
+ public void dbEntityRemoved(DbEntity entity) {
+
+ }
+
+ @Override
+ public boolean dbRelationship(DbEntity entity) {
+ return true;
+ }
+
+ @Override
+ public boolean dbRelationshipLoaded(DbEntity entity, DbRelationship relationship) {
+ return true;
+ }
+
+ @Override
+ public void objEntityAdded(ObjEntity entity) {
+
+ }
+
+ @Override
+ public void objEntityRemoved(ObjEntity entity) {
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/FiltersConfigBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/FiltersConfigBuilder.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/FiltersConfigBuilder.java
new file mode 100644
index 0000000..390d91a
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/FiltersConfigBuilder.java
@@ -0,0 +1,393 @@
+/*****************************************************************
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.dbsync.reverse;
+
+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.IncludeColumn;
+import org.apache.cayenne.dbimport.IncludeProcedure;
+import org.apache.cayenne.dbimport.IncludeTable;
+import org.apache.cayenne.dbimport.PatternParam;
+import org.apache.cayenne.dbimport.ReverseEngineering;
+import org.apache.cayenne.dbimport.Schema;
+import org.apache.cayenne.dbsync.reverse.filters.LegacyFilterConfigBridge;
+import org.apache.cayenne.dbsync.reverse.filters.CatalogFilter;
+import org.apache.cayenne.dbsync.reverse.filters.IncludeTableFilter;
+import org.apache.cayenne.dbsync.reverse.filters.SchemaFilter;
+import org.apache.cayenne.dbsync.reverse.filters.TableFilter;
+import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig;
+import org.apache.cayenne.dbsync.reverse.filters.PatternFilter;
+
+import java.util.*;
+import java.util.regex.Pattern;
+
+import static org.apache.commons.lang.StringUtils.isBlank;
+
+/**
+ * @since 4.0.
+ */
+public final class FiltersConfigBuilder {
+
+ private final ReverseEngineering engineering;
+
+ public FiltersConfigBuilder(ReverseEngineering engineering) {
+ this.engineering = engineering;
+ }
+
+ public FiltersConfig filtersConfig() {
+ compact();
+
+ return new FiltersConfig(transformCatalogs(engineering.getCatalogs()));
+ }
+
+ private CatalogFilter[] transformCatalogs(Collection<Catalog> catalogs) {
+ CatalogFilter[] catalogFilters = new CatalogFilter[catalogs.size()];
+ int i = 0;
+ for (Catalog catalog : catalogs) {
+ catalogFilters[i] = new CatalogFilter(catalog.getName(), transformSchemas(catalog.getSchemas()));
+ i++;
+ }
+
+ return catalogFilters;
+ }
+
+ private SchemaFilter[] transformSchemas(Collection<Schema> schemas) {
+ SchemaFilter[] schemaFilters = new SchemaFilter[schemas.size()];
+ int i = 0;
+ for (Schema schema : schemas) {
+ schemaFilters[i] = new SchemaFilter(schema.getName(),
+ new TableFilter(transformIncludeTable(schema.getIncludeTables()),
+ transformExcludeTable(schema.getExcludeTables())),
+ transform(schema.getIncludeProcedures(), schema.getExcludeProcedures()));
+ i++;
+ }
+
+ return schemaFilters;
+ }
+
+ private SortedSet<Pattern> transformExcludeTable(Collection<ExcludeTable> excludeTables) {
+ SortedSet<Pattern> res = new TreeSet<Pattern>(PatternFilter.PATTERN_COMPARATOR);
+ for (ExcludeTable exclude : excludeTables) {
+ res.add(PatternFilter.pattern(exclude.getPattern()));
+ }
+ return res;
+ }
+
+ private SortedSet<IncludeTableFilter> transformIncludeTable(Collection<IncludeTable> includeTables) {
+ SortedSet<IncludeTableFilter> includeTableFilters = new TreeSet<IncludeTableFilter>();
+ for (IncludeTable includeTable : includeTables) {
+ includeTableFilters.add(new IncludeTableFilter(includeTable.getPattern(),
+ transform(includeTable.getIncludeColumns(), includeTable.getExcludeColumns())));
+ }
+
+ return includeTableFilters;
+ }
+
+ private PatternFilter transform(Collection<? extends PatternParam> include,
+ Collection<? extends PatternParam> exclude) {
+ PatternFilter filter = new PatternFilter();
+
+ for (PatternParam patternParam : include) {
+ filter.include(patternParam.getPattern());
+ }
+
+ for (PatternParam patternParam : exclude) {
+ filter.exclude(patternParam.getPattern());
+ }
+
+ return filter;
+
+ }
+
+ /**
+ * Goal of this method transform ReverseEngineering config into more regular form
+ * From
+ * ReverseEngineering
+ * Catalog
+ * Schema
+ * IncludeTable
+ * IncludeColumn
+ * ExcludeColumn
+ * ExcludeTable
+ * IncludeProcedures
+ * ExcludeProcedures
+ * IncludeColumn
+ * ExcludeColumn
+ * IncludeTable
+ * IncludeColumn
+ * ExcludeColumn
+ * ExcludeTable
+ * IncludeProcedures
+ * ExcludeProcedures
+ * IncludeColumn
+ * ExcludeColumn
+ * Schema
+ * IncludeTable
+ * IncludeColumn
+ * ExcludeColumn
+ * ExcludeTable
+ * IncludeProcedures
+ * ExcludeProcedures
+ * IncludeColumn
+ * ExcludeColumn
+ * IncludeTable
+ * IncludeColumn
+ * ExcludeColumn
+ * ExcludeTable
+ * IncludeProcedures
+ * ExcludeProcedures
+ * IncludeColumn
+ * ExcludeColumn
+ *
+ * Into
+ * ReverseEngineering
+ * Catalog
+ * Schema
+ * IncludeTable
+ * IncludeColumn
+ * ExcludeColumn
+ * ExcludeTable
+ * IncludeProcedures
+ * ExcludeProcedures
+ *
+ *
+ * */
+ public void compact() {
+ addEmptyElements();
+
+ compactColumnFilters();
+ compactTableFilter();
+ compactProcedureFilter();
+ compactSchemas();
+ }
+
+ private void compactSchemas() {
+ for (Catalog catalog : engineering.getCatalogs()) {
+ catalog.getSchemas().addAll(engineering.getSchemas());
+ }
+ engineering.setSchemas(null);
+ }
+
+ private void compactProcedureFilter() {
+ Collection<IncludeProcedure> engIncludeProcedures = engineering.getIncludeProcedures();
+ Collection<ExcludeProcedure> engExcludeProcedures = engineering.getExcludeProcedures();
+
+ engineering.setIncludeProcedures(null);
+ engineering.setExcludeProcedures(null);
+
+ for (Catalog catalog : engineering.getCatalogs()) {
+ Collection<IncludeProcedure> catalogIncludeProcedures = catalog.getIncludeProcedures();
+ Collection<ExcludeProcedure> catalogExcludeProcedures = catalog.getExcludeProcedures();
+
+ catalog.setIncludeProcedures(null);
+ catalog.setExcludeProcedures(null);
+
+ for (Schema schema : catalog.getSchemas()) {
+ if (engIncludeProcedures != null) {
+ schema.getIncludeProcedures().addAll(engIncludeProcedures);
+ schema.getIncludeProcedures().addAll(catalogIncludeProcedures);
+ }
+ if (engExcludeProcedures != null) {
+ schema.getExcludeProcedures().addAll(engExcludeProcedures);
+ schema.getExcludeProcedures().addAll(catalogExcludeProcedures);
+ }
+ }
+ }
+
+ for (Schema schema : engineering.getSchemas()) {
+ schema.getIncludeProcedures().addAll(engIncludeProcedures);
+ schema.getExcludeProcedures().addAll(engExcludeProcedures);
+ }
+ }
+
+ private void compactTableFilter() {
+ Collection<IncludeTable> engIncludeTables = engineering.getIncludeTables();
+ Collection<ExcludeTable> engExcludeTables = engineering.getExcludeTables();
+
+ engineering.setIncludeTables(null);
+ engineering.setExcludeTables(null);
+
+ for (Catalog catalog : engineering.getCatalogs()) {
+ Collection<IncludeTable> catalogIncludeTables = catalog.getIncludeTables();
+ Collection<ExcludeTable> catalogExcludeTables = catalog.getExcludeTables();
+
+ catalog.setIncludeTables(null);
+ catalog.setExcludeTables(null);
+
+ for (Schema schema : catalog.getSchemas()) {
+ if (engIncludeTables != null) {
+ schema.getIncludeTables().addAll(engIncludeTables);
+ schema.getIncludeTables().addAll(catalogIncludeTables);
+ }
+ if (engExcludeTables != null) {
+ schema.getExcludeTables().addAll(engExcludeTables);
+ schema.getExcludeTables().addAll(catalogExcludeTables);
+ }
+ }
+ }
+
+ for (Schema schema : engineering.getSchemas()) {
+ schema.getIncludeTables().addAll(engIncludeTables);
+ schema.getExcludeTables().addAll(engExcludeTables);
+ }
+ }
+
+ private void compactColumnFilters() {
+ Collection<IncludeColumn> engIncludeColumns = engineering.getIncludeColumns();
+ Collection<ExcludeColumn> engExcludeColumns = engineering.getExcludeColumns();
+
+ engineering.setIncludeColumns(null);
+ engineering.setExcludeColumns(null);
+
+ for (Catalog catalog : engineering.getCatalogs()) {
+ Collection<IncludeColumn> catalogIncludeColumns = catalog.getIncludeColumns();
+ Collection<ExcludeColumn> catalogExcludeColumns = catalog.getExcludeColumns();
+
+ catalog.setIncludeColumns(null);
+ catalog.setExcludeColumns(null);
+
+ for (Schema schema : catalog.getSchemas()) {
+ Collection<IncludeColumn> schemaIncludeColumns = schema.getIncludeColumns();
+ Collection<ExcludeColumn> schemaExcludeColumns = schema.getExcludeColumns();
+
+ schema.setIncludeColumns(null);
+ schema.setExcludeColumns(null);
+
+ 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.getExcludeColumns().addAll(engExcludeColumns);
+ includeTable.getExcludeColumns().addAll(catalogExcludeColumns);
+ }
+ }
+ }
+
+ for (Schema schema : engineering.getSchemas()) {
+ Collection<IncludeColumn> schemaIncludeColumns = schema.getIncludeColumns();
+ Collection<ExcludeColumn> schemaExcludeColumns = schema.getExcludeColumns();
+
+ schema.setIncludeColumns(null);
+ schema.setExcludeColumns(null);
+
+ for (IncludeTable includeTable : schema.getIncludeTables()) {
+ includeTable.getIncludeColumns().addAll(engIncludeColumns);
+ includeTable.getIncludeColumns().addAll(schemaIncludeColumns);
+
+ includeTable.getExcludeColumns().addAll(engExcludeColumns);
+ includeTable.getExcludeColumns().addAll(schemaExcludeColumns);
+ }
+ }
+
+ if (engineering.getIncludeTables() != null) {
+ for (IncludeTable includeTable : engineering.getIncludeTables()) {
+ includeTable.getIncludeColumns().addAll(engIncludeColumns);
+ includeTable.getExcludeColumns().addAll(engExcludeColumns);
+ }
+ }
+ }
+
+ private void addEmptyElements() {
+ if (engineering.getCatalogs().isEmpty()) {
+ engineering.addCatalog(new Catalog());
+ }
+
+ for (Catalog catalog : engineering.getCatalogs()) {
+ if (catalog.getSchemas().isEmpty()
+ && engineering.getSchemas().isEmpty()) {
+ catalog.addSchema(new Schema());
+ }
+
+ for (Schema schema : catalog.getSchemas()) {
+ if (schema.getIncludeTables().isEmpty()
+ && catalog.getIncludeTables().isEmpty()
+ && engineering.getIncludeTables().isEmpty()) {
+
+ schema.addIncludeTable(new IncludeTable());
+ }
+ }
+ }
+
+ if (engineering.getSchemas() == null) {
+ engineering.setSchemas(new LinkedList<Schema>());
+ }
+
+ for (Schema schema : engineering.getSchemas()) {
+ if (schema.getIncludeTables().isEmpty()
+ && engineering.getIncludeTables().isEmpty()) {
+
+ schema.addIncludeTable(new IncludeTable());
+ }
+ }
+ }
+
+ public FiltersConfigBuilder add(LegacyFilterConfigBridge build) {
+ if (!isBlank(build.catalog())) {
+ engineering.addCatalog(new Catalog(build.catalog()));
+ }
+
+ if (!isBlank(build.schema())) {
+ engineering.addSchema(new Schema(build.schema()));
+ }
+
+ if (!isBlank(build.getIncludeTableFilters())) {
+ engineering.addIncludeTable(new IncludeTable(build.getIncludeTableFilters()));
+ }
+ if (!isBlank(build.getExcludeTableFilters())) {
+ engineering.addExcludeTable(new ExcludeTable(build.getExcludeTableFilters()));
+ }
+
+ if (!isBlank(build.getIncludeColumnFilters())) {
+ engineering.addIncludeColumn(new IncludeColumn(build.getIncludeColumnFilters()));
+ }
+ if (!isBlank(build.getExcludeColumnFilters())) {
+ engineering.addExcludeColumn(new ExcludeColumn(build.getExcludeColumnFilters()));
+ }
+
+ if (build.isLoadProcedures()) {
+ if (!isBlank(build.getIncludeProceduresFilters())) {
+ engineering.addIncludeProcedure(new IncludeProcedure(build.getIncludeProceduresFilters()));
+ }
+ if (!isBlank(build.getExcludeProceduresFilters())) {
+ engineering.addExcludeProcedure(new ExcludeProcedure(build.getExcludeProceduresFilters()));
+ }
+ }
+
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/LoggingDbLoaderDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/LoggingDbLoaderDelegate.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/LoggingDbLoaderDelegate.java
new file mode 100644
index 0000000..3777ccc
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/LoggingDbLoaderDelegate.java
@@ -0,0 +1,76 @@
+/*
+ * 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.dbsync.reverse;
+
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.commons.logging.Log;
+
+/**
+ * @since 4.0
+ */
+public class LoggingDbLoaderDelegate extends DefaultDbLoaderDelegate {
+
+ private final Log logger;
+
+ public LoggingDbLoaderDelegate(Log logger) {
+ this.logger = logger;
+ }
+
+ @Override
+ public void dbEntityAdded(DbEntity entity) {
+ logger.info(" Table: " + entity.getFullyQualifiedName());
+ }
+
+ @Override
+ public void dbEntityRemoved(DbEntity entity) {
+ logger.info(" Table removed: " + entity.getFullyQualifiedName());
+ }
+
+ @Override
+ public boolean dbRelationship(DbEntity entity) {
+ if (logger.isDebugEnabled()) {
+ logger.debug(" Relationships for " + entity.getFullyQualifiedName());
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean dbRelationshipLoaded(DbEntity entity, DbRelationship relationship) {
+ logger.info(" " + relationship);
+
+ return true;
+ }
+
+ @Override
+ public void objEntityAdded(ObjEntity entity) {
+ if (logger.isDebugEnabled()) {
+ logger.debug(" Class: " + entity.getName());
+ }
+ }
+
+ @Override
+ public void objEntityRemoved(ObjEntity entity) {
+ if (logger.isDebugEnabled()) {
+ logger.debug(" Class removed: " + entity.getName());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/ManyToManyCandidateEntity.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/ManyToManyCandidateEntity.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/ManyToManyCandidateEntity.java
new file mode 100644
index 0000000..9666e08
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/ManyToManyCandidateEntity.java
@@ -0,0 +1,142 @@
+/*****************************************************************
+ * 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.dbsync.reverse;
+
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+import org.apache.cayenne.map.naming.DefaultUniqueNameGenerator;
+import org.apache.cayenne.map.naming.ExportedKey;
+import org.apache.cayenne.map.naming.NameCheckers;
+import org.apache.cayenne.map.naming.ObjectNameGenerator;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Class represent ObjEntity that may be optimized using flattened relationships
+ * as many to many table
+ */
+public class ManyToManyCandidateEntity {
+
+ private static final Log LOG = LogFactory.getLog(ManyToManyCandidateEntity.class);
+
+ private final ObjEntity joinEntity;
+
+ private final DbRelationship dbRel1;
+ private final DbRelationship dbRel2;
+
+ private final ObjEntity entity1;
+ private final ObjEntity entity2;
+
+ private final DbRelationship reverseRelationship1;
+ private final DbRelationship reverseRelationship2;
+
+ private ManyToManyCandidateEntity(ObjEntity entityValue, List<ObjRelationship> relationships) {
+ joinEntity = entityValue;
+
+ ObjRelationship rel1 = relationships.get(0);
+ ObjRelationship rel2 = relationships.get(1);
+
+ dbRel1 = rel1.getDbRelationships().get(0);
+ dbRel2 = rel2.getDbRelationships().get(0);
+
+ reverseRelationship1 = dbRel1.getReverseRelationship();
+ reverseRelationship2 = dbRel2.getReverseRelationship();
+
+ entity1 = rel1.getTargetEntity();
+ entity2 = rel2.getTargetEntity();
+ }
+
+ /**
+ * Method check - if current entity represent many to many temporary table
+ * @return true if current entity is represent many to many table; otherwise returns false
+ */
+ public static ManyToManyCandidateEntity build(ObjEntity joinEntity) {
+ ArrayList<ObjRelationship> relationships = new ArrayList<ObjRelationship>(joinEntity.getRelationships());
+ if (relationships.size() != 2 || (relationships.get(0).getDbRelationships().isEmpty() || relationships.get(1).getDbRelationships().isEmpty())) {
+ return null;
+ }
+
+ ManyToManyCandidateEntity candidateEntity = new ManyToManyCandidateEntity(joinEntity, relationships);
+ if (candidateEntity.isManyToMany()) {
+ return candidateEntity;
+ }
+
+ return null;
+ }
+
+ private boolean isManyToMany() {
+ boolean isNotHaveAttributes = joinEntity.getAttributes().size() == 0;
+
+ return isNotHaveAttributes
+ && reverseRelationship1 != null && reverseRelationship1.isToDependentPK()
+ && reverseRelationship2 != null && reverseRelationship2.isToDependentPK()
+ && entity1 != null && entity2 != null;
+ }
+
+ private void addFlattenedRelationship(ObjectNameGenerator nameGenerator, ObjEntity srcEntity, ObjEntity dstEntity,
+ DbRelationship rel1, DbRelationship rel2) {
+
+ if (rel1.getSourceAttributes().isEmpty() && rel2.getTargetAttributes().isEmpty()) {
+ LOG.warn("Wrong call ManyToManyCandidateEntity.addFlattenedRelationship(... , " + srcEntity.getName()
+ + ", " + dstEntity.getName() + ", ...)");
+
+ return;
+ }
+
+ ExportedKey key = new ExportedKey(
+ rel1.getSourceEntity().getName(),
+ rel1.getSourceAttributes().iterator().next().getName(),
+ null,
+ rel2.getTargetEntity().getName(),
+ rel2.getTargetAttributes().iterator().next().getName(),
+ null,
+ (short) 1);
+
+ ObjRelationship newRelationship = new ObjRelationship();
+ newRelationship.setName(DefaultUniqueNameGenerator.generate(NameCheckers.objRelationship, srcEntity,
+ nameGenerator.createDbRelationshipName(key, true)));
+
+ newRelationship.setSourceEntity(srcEntity);
+ newRelationship.setTargetEntityName(dstEntity);
+
+ newRelationship.addDbRelationship(rel1);
+ newRelationship.addDbRelationship(rel2);
+
+ srcEntity.addRelationship(newRelationship);
+ }
+
+ /**
+ * Method make direct relationships between 2 entities and remove relationships to
+ * many to many entity
+ *
+ * @param nameGenerator
+ */
+ public void optimizeRelationships(ObjectNameGenerator nameGenerator) {
+ entity1.removeRelationship(reverseRelationship1.getName());
+ entity2.removeRelationship(reverseRelationship2.getName());
+
+ addFlattenedRelationship(nameGenerator, entity1, entity2, reverseRelationship1, dbRel2);
+ addFlattenedRelationship(nameGenerator, entity2, entity1, reverseRelationship2, dbRel1);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/NameFilter.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/NameFilter.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/NameFilter.java
new file mode 100644
index 0000000..89b8330
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/NameFilter.java
@@ -0,0 +1,27 @@
+/*****************************************************************
+ * 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.dbsync.reverse;
+
+/**
+ * @since 4.0.
+ */
+public interface NameFilter {
+
+ boolean isIncluded(String string);
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/NamePatternMatcher.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/NamePatternMatcher.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/NamePatternMatcher.java
new file mode 100644
index 0000000..cb9faad
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/NamePatternMatcher.java
@@ -0,0 +1,225 @@
+/*****************************************************************
+ * 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.dbsync.reverse;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import org.apache.cayenne.util.CayenneMapEntry;
+import org.apache.commons.logging.Log;
+
+/**
+ * Provides name pattern matching functionality.
+ *
+ * @since 1.2
+ */
+public class NamePatternMatcher implements NameFilter {
+
+ private static final String[] EMPTY_ARRAY = new String[0];
+ private static final Pattern COMMA = Pattern.compile(",");
+
+ private final Pattern[] itemIncludeFilters;
+ private final Pattern[] itemExcludeFilters;
+
+ public static NamePatternMatcher build(Log logger, String includePattern, String excludePattern) {
+ return new NamePatternMatcher(createPatterns(logger, includePattern), createPatterns(logger, excludePattern));
+ }
+
+ public NamePatternMatcher(Pattern[] itemIncludeFilters, Pattern[] itemExcludeFilters) {
+ this.itemIncludeFilters = itemIncludeFilters;
+ this.itemExcludeFilters = itemExcludeFilters;
+ }
+
+ /**
+ * Applies preconfigured list of filters to the list, removing entities that do not
+ * pass the filter.
+ *
+ * @deprecated since 3.0 still used by AntDataPortDelegate, which itself should
+ * probably be deprecated
+ */
+ @Deprecated
+ public List<?> filter(List<?> items) {
+ if (items == null || items.isEmpty()) {
+ return items;
+ }
+
+ if (itemIncludeFilters.length == 0 && itemExcludeFilters.length == 0) {
+ return items;
+ }
+
+ Iterator<?> it = items.iterator();
+ while (it.hasNext()) {
+ CayenneMapEntry entity = (CayenneMapEntry) it.next();
+
+ if (!passedIncludeFilter(entity.getName())) {
+ it.remove();
+ continue;
+ }
+
+ if (!passedExcludeFilter(entity.getName())) {
+ it.remove();
+ }
+ }
+
+ return items;
+ }
+
+ /**
+ * Returns an array of Patterns. Takes a comma-separated list of patterns, attempting
+ * to convert them to the java.util.regex.Pattern syntax. E.g.
+ * <p>
+ * <code>"billing_*,user?"</code> will become an array of two expressions:
+ * <p>
+ * <code>^billing_.*$</code><br>
+ * <code>^user.?$</code><br>
+ */
+ public static Pattern[] createPatterns(Log logger, String patternString) {
+ if (patternString == null) {
+ return new Pattern[0];
+ }
+ String[] patternStrings = tokenizePattern(patternString);
+ List<Pattern> patterns = new ArrayList<Pattern>(patternStrings.length);
+
+ for (String patternString1 : patternStrings) {
+
+ // test the pattern
+ try {
+ patterns.add(Pattern.compile(patternString1));
+ } catch (PatternSyntaxException e) {
+
+ if (logger != null) {
+ logger.warn("Ignoring invalid pattern [" + patternString1 + "], reason: " + e.getMessage());
+ }
+ }
+ }
+
+ return patterns.toArray(new Pattern[patterns.size()]);
+ }
+
+ /**
+ * Returns an array of valid regular expressions. Takes a comma-separated list of
+ * patterns, attempting to convert them to the java.util.regex.Pattern syntax. E.g.
+ * <p>
+ * <code>"billing_*,user?"</code> will become an array of two expressions:
+ * <p>
+ * <code>^billing_.*$</code><br>
+ * <code>^user.?$</code><br>
+ */
+ public static String[] tokenizePattern(String pattern) {
+ if (pattern == null || pattern.isEmpty()) {
+ return EMPTY_ARRAY;
+ }
+
+ String[] patterns = COMMA.split(pattern);
+ if (patterns.length == 0) {
+ return EMPTY_ARRAY;
+ }
+
+ for (int i = 0; i < patterns.length; i++) {
+ // convert * into regex syntax
+ // e.g. abc*x becomes ^abc.*x$
+ // or abc?x becomes ^abc.?x$
+ patterns[i] = "^" + patterns[i].replaceAll("[*?]", ".$0") + "$";
+ }
+
+ return patterns;
+ }
+
+ /**
+ * Returns true if a given object property satisfies the include/exclude patterns.
+ *
+ * @since 3.0
+ */
+ @Override
+ public boolean isIncluded(String string) {
+ return passedIncludeFilter(string) && passedExcludeFilter(string);
+ }
+
+ /**
+ * Returns true if an object matches any one of the "include" patterns, or if there is
+ * no "include" patterns defined.
+ *
+ * @since 3.0
+ */
+ private boolean passedIncludeFilter(String item) {
+ if (itemIncludeFilters.length == 0) {
+ return true;
+ }
+
+ for (Pattern itemIncludeFilter : itemIncludeFilters) {
+ if (itemIncludeFilter.matcher(item).find()) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns true if an object does not match any one of the "exclude" patterns, or if
+ * there is no "exclude" patterns defined.
+ *
+ * @since 3.0
+ */
+ private boolean passedExcludeFilter(String item) {
+ if (itemExcludeFilters.length == 0) {
+ return true;
+ }
+
+ for (Pattern itemExcludeFilter : itemExcludeFilters) {
+ if (itemExcludeFilter.matcher(item).find()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static String replaceWildcardInStringWithString(
+ String wildcard,
+ String pattern,
+ String replacement) {
+
+ if (pattern == null || wildcard == null) {
+ return pattern;
+ }
+
+ StringBuilder buffer = new StringBuilder();
+ int lastPos = 0;
+ int wildCardPos = pattern.indexOf(wildcard);
+ while (wildCardPos != -1) {
+ if (lastPos != wildCardPos) {
+ buffer.append(pattern.substring(lastPos, wildCardPos));
+ }
+ buffer.append(replacement);
+ lastPos += wildCardPos + wildcard.length();
+ wildCardPos = pattern.indexOf(wildcard, lastPos);
+ }
+
+ if (lastPos < pattern.length()) {
+ buffer.append(pattern.substring(lastPos));
+ }
+
+ return buffer.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/CatalogFilter.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/CatalogFilter.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/CatalogFilter.java
new file mode 100644
index 0000000..46feb9d
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/CatalogFilter.java
@@ -0,0 +1,62 @@
+/*****************************************************************
+ * 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.dbsync.reverse.filters;
+
+import java.util.Arrays;
+
+/**
+* @since 4.0.
+*/
+public class CatalogFilter {
+ public final String name;
+ public final SchemaFilter[] schemas;
+
+ public CatalogFilter(String name, SchemaFilter... schemas) {
+ if (schemas == null || schemas.length == 0) {
+ throw new IllegalArgumentException("schemas(" + Arrays.toString(schemas) + ") can't be null or empty");
+ }
+
+ this.name = name;
+ this.schemas = schemas;
+ }
+
+ public SchemaFilter getSchema(String schema) {
+ for (SchemaFilter schemaFilter : schemas) {
+ if (schemaFilter.name == null || schemaFilter.name.equals(schema)) {
+ return schemaFilter;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return toString(new StringBuilder(), "").toString();
+ }
+
+ public StringBuilder toString(StringBuilder res, String prefix) {
+ res.append(prefix).append("Catalog: ").append(name).append("\n");
+ for (SchemaFilter schema : schemas) {
+ schema.toString(res, prefix + " ");
+ }
+
+ return res;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfig.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfig.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfig.java
new file mode 100644
index 0000000..48a2e62
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfig.java
@@ -0,0 +1,81 @@
+/*****************************************************************
+ * 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.dbsync.reverse.filters;
+
+import java.util.Arrays;
+
+/**
+ * @since 4.0.
+ */
+public class FiltersConfig {
+
+ public final CatalogFilter[] catalogs;
+
+ public FiltersConfig(CatalogFilter ... catalogs) {
+ if (catalogs == null || catalogs.length == 0) {
+ throw new IllegalArgumentException("catalogs(" + Arrays.toString(catalogs) + ") can't be null or empty");
+ }
+
+ this.catalogs = catalogs;
+ }
+
+ public PatternFilter proceduresFilter(String catalog, String schema) {
+ return getSchemaFilter(catalog, schema).procedures;
+ }
+
+ public TableFilter tableFilter(String catalog, String schema) {
+ return getSchemaFilter(catalog, schema).tables;
+ }
+
+ protected SchemaFilter getSchemaFilter(String catalog, String schema) {
+ CatalogFilter catalogFilter = getCatalog(catalog);
+ if (catalogFilter == null) {
+ return null;
+ }
+
+ return catalogFilter.getSchema(schema);
+ }
+
+ protected CatalogFilter getCatalog(String catalog) {
+ for (CatalogFilter catalogFilter : catalogs) {
+ if (catalogFilter.name == null || catalogFilter.name.equals(catalog)) {
+ return catalogFilter;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ for (CatalogFilter catalog : catalogs) {
+ catalog.toString(builder, "");
+ }
+
+ return builder.toString();
+ }
+
+ public static FiltersConfig create(String catalog, String schema, TableFilter tableFilter, PatternFilter procedures) {
+ return new FiltersConfig(
+ new CatalogFilter(catalog,
+ new SchemaFilter(schema, tableFilter, procedures)));
+ }
+}
[04/15] cayenne git commit: CAY-2116 Split schema synchronization
code in a separate module
Posted by aa...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/SetPrimaryKeyToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/SetPrimaryKeyToModel.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/SetPrimaryKeyToModel.java
deleted file mode 100644
index 10ec4fe..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/SetPrimaryKeyToModel.java
+++ /dev/null
@@ -1,77 +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.merge;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.event.AttributeEvent;
-
-public class SetPrimaryKeyToModel extends AbstractToModelToken.Entity {
-
- private Collection<DbAttribute> primaryKeyOriginal;
- private Collection<DbAttribute> primaryKeyNew;
- private String detectedPrimaryKeyName;
- private Set<String> primaryKeyNewAttributeNames = new HashSet<String>();
-
- public SetPrimaryKeyToModel(DbEntity entity,
- Collection<DbAttribute> primaryKeyOriginal,
- Collection<DbAttribute> primaryKeyNew, String detectedPrimaryKeyName) {
- super("Set Primary Key", entity);
-
- this.primaryKeyOriginal = primaryKeyOriginal;
- this.primaryKeyNew = primaryKeyNew;
- this.detectedPrimaryKeyName = detectedPrimaryKeyName;
-
- for (DbAttribute attr : primaryKeyNew) {
- primaryKeyNewAttributeNames.add(attr.getName().toUpperCase());
- }
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return factory.createSetPrimaryKeyToDb(
- getEntity(),
- primaryKeyNew,
- primaryKeyOriginal,
- detectedPrimaryKeyName);
- }
-
- public void execute(MergerContext mergerContext) {
- DbEntity e = getEntity();
-
- for (DbAttribute attr : e.getAttributes()) {
-
- boolean wasPrimaryKey = attr.isPrimaryKey();
- boolean willBePrimaryKey = primaryKeyNewAttributeNames.contains(attr
- .getName()
- .toUpperCase());
-
- if (wasPrimaryKey != willBePrimaryKey) {
- attr.setPrimaryKey(willBePrimaryKey);
- e.dbAttributeChanged(new AttributeEvent(this, attr, e));
- mergerContext.getModelMergeDelegate().dbAttributeModified(attr);
- }
-
- }
-
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/SetValueForNullToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/SetValueForNullToDb.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/SetValueForNullToDb.java
deleted file mode 100644
index 1991154..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/SetValueForNullToDb.java
+++ /dev/null
@@ -1,46 +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.merge;
-
-import java.util.List;
-
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-
-
-public class SetValueForNullToDb extends AbstractToDbToken.EntityAndColumn {
-
- private ValueForNullProvider valueForNullProvider;
-
- public SetValueForNullToDb(DbEntity entity, DbAttribute column, ValueForNullProvider valueForNullProvider) {
- super("Set value for null", entity, column);
- this.valueForNullProvider = valueForNullProvider;
- }
-
- @Override
- public List<String> createSql(DbAdapter adapter) {
- return valueForNullProvider.createSql(getEntity(), getColumn());
- }
-
- public MergerToken createReverse(MergerFactory factory) {
- return new DummyReverseToken(this);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/merge/ValueForNullProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/ValueForNullProvider.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/ValueForNullProvider.java
deleted file mode 100644
index ff147eb..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/ValueForNullProvider.java
+++ /dev/null
@@ -1,42 +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.merge;
-
-import java.util.List;
-
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-
-/**
- * Class that will be used to set value for null on not
- * null columns
- */
-public interface ValueForNullProvider {
-
- /**
- * @return true if there exist a value that should be inserted for null values
- */
- public boolean hasValueFor(DbEntity entity, DbAttribute column);
-
- /**
- * @return a {@link List} of sql to set value for null
- */
- public List<String> createSql(DbEntity entity, DbAttribute column);
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/main/java/org/apache/cayenne/util/EntityMergeSupport.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/util/EntityMergeSupport.java b/cayenne-server/src/main/java/org/apache/cayenne/util/EntityMergeSupport.java
deleted file mode 100644
index 7c12600..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/util/EntityMergeSupport.java
+++ /dev/null
@@ -1,520 +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.util;
-
-import org.apache.cayenne.dba.TypesMapping;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.map.DbJoin;
-import org.apache.cayenne.map.DbRelationship;
-import org.apache.cayenne.map.Entity;
-import org.apache.cayenne.map.ObjAttribute;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.map.ObjRelationship;
-import org.apache.cayenne.map.naming.DefaultUniqueNameGenerator;
-import org.apache.cayenne.map.naming.LegacyNameGenerator;
-import org.apache.cayenne.map.naming.NameCheckers;
-import org.apache.cayenne.map.naming.ObjectNameGenerator;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Implements methods for entity merging.
- */
-public class EntityMergeSupport {
-
- private static final Log LOG = LogFactory.getLog(EntityMergeSupport.class);
-
- private static final Map<String, String> CLASS_TO_PRIMITIVE;
-
- static {
- CLASS_TO_PRIMITIVE = new HashMap<>();
- CLASS_TO_PRIMITIVE.put(Byte.class.getName(), "byte");
- CLASS_TO_PRIMITIVE.put(Long.class.getName(), "long");
- CLASS_TO_PRIMITIVE.put(Double.class.getName(), "double");
- CLASS_TO_PRIMITIVE.put(Boolean.class.getName(), "boolean");
- CLASS_TO_PRIMITIVE.put(Float.class.getName(), "float");
- CLASS_TO_PRIMITIVE.put(Short.class.getName(), "short");
- CLASS_TO_PRIMITIVE.put(Integer.class.getName(), "int");
- }
-
- private final DataMap map;
- /**
- * Strategy for choosing names for entities, attributes and relationships
- */
- private final ObjectNameGenerator nameGenerator;
- /**
- * Listeners of merge process.
- */
- private final List<EntityMergeListener> listeners = new ArrayList<EntityMergeListener>();
- protected boolean removeMeaningfulFKs;
- protected boolean removeMeaningfulPKs;
- protected boolean usePrimitives;
-
- public EntityMergeSupport(DataMap map) {
- this(map, new LegacyNameGenerator(), true);
- }
-
- /**
- * @since 3.0
- */
- public EntityMergeSupport(DataMap map, ObjectNameGenerator nameGenerator, boolean removeMeaningfulPKs) {
- this.map = map;
- this.nameGenerator = nameGenerator;
- this.removeMeaningfulFKs = true;
- this.removeMeaningfulPKs = removeMeaningfulPKs;
-
- /**
- * Adding a listener, so that all created ObjRelationships would have
- * default delete rule
- */
- addEntityMergeListener(DeleteRuleUpdater.getEntityMergeListener());
- }
-
- /**
- * Updates each one of the collection of ObjEntities, adding attributes and
- * relationships based on the current state of its DbEntity.
- *
- * @return true if any ObjEntity has changed as a result of synchronization.
- * @since 1.2 changed signature to use Collection instead of List.
- */
- public boolean synchronizeWithDbEntities(Iterable<ObjEntity> objEntities) {
- boolean changed = false;
- for (ObjEntity nextEntity : objEntities) {
- if (synchronizeWithDbEntity(nextEntity)) {
- changed = true;
- }
- }
-
- return changed;
- }
-
- /**
- * @since 4.0
- */
- protected boolean removePK(DbEntity dbEntity) {
- return removeMeaningfulPKs;
- }
-
- /**
- * @since 4.0
- */
- protected boolean removeFK(DbEntity dbEntity) {
- return removeMeaningfulFKs;
- }
-
- /**
- * Updates ObjEntity attributes and relationships based on the current state
- * of its DbEntity.
- *
- * @return true if the ObjEntity has changed as a result of synchronization.
- */
- public boolean synchronizeWithDbEntity(ObjEntity entity) {
-
- if (entity == null) {
- return false;
- }
-
- DbEntity dbEntity = entity.getDbEntity();
- if (dbEntity == null) {
- return false;
- }
-
- boolean changed = false;
-
- // synchronization on DataMap is some (weak) protection
- // against simultaneous modification of the map (like double-clicking on sync button)
- synchronized (map) {
-
- if (removeFK(dbEntity)) {
- changed = getRidOfAttributesThatAreNowSrcAttributesForRelationships(entity);
- }
-
- changed |= addMissingAttributes(entity);
- changed |= addMissingRelationships(entity);
- }
-
- return changed;
- }
-
- /**
- * @since 4.0
- */
- public boolean synchronizeOnDbAttributeAdded(ObjEntity entity, DbAttribute dbAttribute) {
-
- Collection<DbRelationship> incomingRels = getIncomingRelationships(dbAttribute.getEntity());
- if (isMissingFromObjEntity(entity, dbAttribute, incomingRels)) {
- addMissingAttribute(entity, dbAttribute);
- return true;
- }
-
- return false;
- }
-
- /**
- * @since 4.0
- */
- public boolean synchronizeOnDbRelationshipAdded(ObjEntity entity, DbRelationship dbRelationship) {
-
- if (isMissingFromObjEntity(entity, dbRelationship)) {
- addMissingRelationship(entity, dbRelationship);
- }
-
- return true;
- }
-
- private boolean addMissingRelationships(ObjEntity entity) {
- List<DbRelationship> relationshipsToAdd = getRelationshipsToAdd(entity);
- if (relationshipsToAdd.isEmpty()) {
- return false;
- }
-
- for (DbRelationship dr : relationshipsToAdd) {
- addMissingRelationship(entity, dr);
- }
-
- return true;
- }
-
- private boolean createObjRelationship(ObjEntity entity, DbRelationship dr, String targetEntityName) {
- String relationshipName = nameGenerator.createObjRelationshipName(dr);
- relationshipName = DefaultUniqueNameGenerator.generate(NameCheckers.objRelationship, entity, relationshipName);
-
- ObjRelationship or = new ObjRelationship(relationshipName);
- or.addDbRelationship(dr);
- Map<String, ObjEntity> objEntities = entity.getDataMap().getSubclassesForObjEntity(entity);
-
- boolean hasFlattingAttributes = false;
- boolean needGeneratedEntity = true;
-
- if (objEntities.containsKey(targetEntityName)) {
- needGeneratedEntity = false;
- }
-
- for (ObjEntity subObjEntity : objEntities.values()) {
- for (ObjAttribute objAttribute : subObjEntity.getAttributes()) {
- String path = objAttribute.getDbAttributePath();
- if (path != null) {
- if (path.startsWith(or.getDbRelationshipPath())) {
- hasFlattingAttributes = true;
- break;
- }
- }
- }
- }
-
- if (!hasFlattingAttributes) {
- if (needGeneratedEntity) {
- or.setTargetEntityName(targetEntityName);
- or.setSourceEntity(entity);
- }
-
- entity.addRelationship(or);
- fireRelationshipAdded(or);
- }
-
- return needGeneratedEntity;
- }
-
- private boolean addMissingAttributes(ObjEntity entity) {
- boolean changed = false;
-
- for (DbAttribute da : getAttributesToAdd(entity)) {
- addMissingAttribute(entity, da);
- changed = true;
- }
- return changed;
- }
-
- private void addMissingRelationship(ObjEntity entity, DbRelationship dbRelationship) {
- DbEntity targetEntity = dbRelationship.getTargetEntity();
-
- Collection<ObjEntity> mappedObjEntities = map.getMappedEntities(targetEntity);
- if (!mappedObjEntities.isEmpty()) {
- for (Entity mappedTarget : mappedObjEntities) {
- createObjRelationship(entity, dbRelationship, mappedTarget.getName());
- }
- } else {
-
- if (targetEntity == null) {
- targetEntity = new DbEntity(dbRelationship.getTargetEntityName());
- }
-
- if (dbRelationship.getTargetEntityName() != null) {
- boolean needGeneratedEntity = createObjRelationship(entity, dbRelationship,
- nameGenerator.createObjEntityName(targetEntity));
- if (needGeneratedEntity) {
- LOG.warn("Can't find ObjEntity for " + dbRelationship.getTargetEntityName());
- LOG.warn("Db Relationship (" + dbRelationship + ") will have GUESSED Obj Relationship reflection. ");
- }
- }
- }
- }
-
- private void addMissingAttribute(ObjEntity entity, DbAttribute da) {
- String attrName = DefaultUniqueNameGenerator.generate(NameCheckers.objAttribute, entity,
- nameGenerator.createObjAttributeName(da));
-
- String type = TypesMapping.getJavaBySqlType(da.getType());
- if (usePrimitives) {
- String primitive = CLASS_TO_PRIMITIVE.get(type);
- if (primitive != null) {
- type = primitive;
- }
- }
-
- ObjAttribute oa = new ObjAttribute(attrName, type, entity);
- oa.setDbAttributePath(da.getName());
- entity.addAttribute(oa);
- fireAttributeAdded(oa);
- }
-
- private boolean getRidOfAttributesThatAreNowSrcAttributesForRelationships(ObjEntity entity) {
- boolean changed = false;
- for (DbAttribute da : getMeaningfulFKs(entity)) {
- ObjAttribute oa = entity.getAttributeForDbAttribute(da);
- while (oa != null) {
- String attrName = oa.getName();
- entity.removeAttribute(attrName);
- changed = true;
- oa = entity.getAttributeForDbAttribute(da);
- }
- }
- return changed;
- }
-
- /**
- * Returns a list of DbAttributes that are mapped to foreign keys.
- *
- * @since 1.2
- */
- public Collection<DbAttribute> getMeaningfulFKs(ObjEntity objEntity) {
- List<DbAttribute> fks = new ArrayList<DbAttribute>(2);
-
- for (ObjAttribute property : objEntity.getAttributes()) {
- DbAttribute column = property.getDbAttribute();
-
- // check if adding it makes sense at all
- if (column != null && column.isForeignKey()) {
- fks.add(column);
- }
- }
-
- return fks;
- }
-
- /**
- * Returns a list of attributes that exist in the DbEntity, but are missing
- * from the ObjEntity.
- */
- protected List<DbAttribute> getAttributesToAdd(ObjEntity objEntity) {
- DbEntity dbEntity = objEntity.getDbEntity();
-
- List<DbAttribute> missing = new ArrayList<DbAttribute>();
- Collection<DbRelationship> incomingRels = getIncomingRelationships(dbEntity);
-
- for (DbAttribute dba : dbEntity.getAttributes()) {
-
- if (isMissingFromObjEntity(objEntity, dba, incomingRels)) {
- missing.add(dba);
- }
- }
-
- return missing;
- }
-
- protected boolean isMissingFromObjEntity(ObjEntity entity, DbAttribute dbAttribute, Collection<DbRelationship> incomingRels) {
-
- if (dbAttribute.getName() == null || entity.getAttributeForDbAttribute(dbAttribute) != null) {
- return false;
- }
-
- boolean removeMeaningfulPKs = removePK(dbAttribute.getEntity());
- if (removeMeaningfulPKs && dbAttribute.isPrimaryKey()) {
- return false;
- }
-
- // check FK's
- boolean isFK = false;
- Iterator<DbRelationship> rit = dbAttribute.getEntity().getRelationships().iterator();
- while (!isFK && rit.hasNext()) {
- DbRelationship rel = rit.next();
- for (DbJoin join : rel.getJoins()) {
- if (join.getSource() == dbAttribute) {
- isFK = true;
- break;
- }
- }
- }
-
- if (!removeMeaningfulPKs) {
- if (!dbAttribute.isPrimaryKey() && isFK) {
- return false;
- }
- } else {
- if (isFK) {
- return false;
- }
- }
-
- // check incoming relationships
- rit = incomingRels.iterator();
- while (!isFK && rit.hasNext()) {
- DbRelationship rel = rit.next();
- for (DbJoin join : rel.getJoins()) {
- if (join.getTarget() == dbAttribute) {
- isFK = true;
- break;
- }
- }
- }
-
- if (!removeMeaningfulPKs) {
- if (!dbAttribute.isPrimaryKey() && isFK) {
- return false;
- }
- } else {
- if (isFK) {
- return false;
- }
- }
-
- return true;
- }
-
- protected boolean isMissingFromObjEntity(ObjEntity entity, DbRelationship dbRelationship) {
- return dbRelationship.getName() != null && entity.getRelationshipForDbRelationship(dbRelationship) == null;
- }
-
- private Collection<DbRelationship> getIncomingRelationships(DbEntity entity) {
- Collection<DbRelationship> incoming = new ArrayList<DbRelationship>();
-
- for (DbEntity nextEntity : entity.getDataMap().getDbEntities()) {
- for (DbRelationship relationship : nextEntity.getRelationships()) {
-
- // TODO: PERFORMANCE 'getTargetEntity' is generally slow, called
- // in this iterator it is showing (e.g. in YourKit profiles)..
- // perhaps use cheaper 'getTargetEntityName()' or even better -
- // pre-cache all relationships by target entity to avoid O(n)
- // search ?
- // (need to profile to prove the difference)
- if (entity == relationship.getTargetEntity()) {
- incoming.add(relationship);
- }
- }
- }
-
- return incoming;
- }
-
- protected List<DbRelationship> getRelationshipsToAdd(ObjEntity objEntity) {
- List<DbRelationship> missing = new ArrayList<DbRelationship>();
- for (DbRelationship dbRel : objEntity.getDbEntity().getRelationships()) {
- if (isMissingFromObjEntity(objEntity, dbRel)) {
- missing.add(dbRel);
- }
- }
-
- return missing;
- }
-
- /**
- * @since 1.2
- */
- public boolean isRemoveMeaningfulFKs() {
- return removeMeaningfulFKs;
- }
-
- /**
- * @since 1.2
- */
- public void setRemoveMeaningfulFKs(boolean removeMeaningfulFKs) {
- this.removeMeaningfulFKs = removeMeaningfulFKs;
- }
-
- /**
- * Registers new EntityMergeListener
- */
- public void addEntityMergeListener(EntityMergeListener listener) {
- listeners.add(listener);
- }
-
- /**
- * Unregisters an EntityMergeListener
- */
- public void removeEntityMergeListener(EntityMergeListener listener) {
- listeners.remove(listener);
- }
-
- /**
- * Returns registered listeners
- */
- public EntityMergeListener[] getEntityMergeListeners() {
- return listeners.toArray(new EntityMergeListener[listeners.size()]);
- }
-
- /**
- * Notifies all listeners that an ObjAttribute was added
- */
- protected void fireAttributeAdded(ObjAttribute attr) {
- for (EntityMergeListener listener : listeners) {
- listener.objAttributeAdded(attr);
- }
- }
-
- /**
- * Notifies all listeners that an ObjRelationship was added
- */
- protected void fireRelationshipAdded(ObjRelationship rel) {
- for (EntityMergeListener listener : listeners) {
- listener.objRelationshipAdded(rel);
- }
- }
-
- /**
- * @return naming strategy for reverse engineering
- */
- public ObjectNameGenerator getNameGenerator() {
- return nameGenerator;
- }
-
- /**
- * @since 4.0
- */
- public boolean isUsePrimitives() {
- return usePrimitives;
- }
-
- /**
- * @param usePrimitives
- * @since 4.0
- */
- public void setUsePrimitives(boolean usePrimitives) {
- this.usePrimitives = usePrimitives;
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderIT.java
deleted file mode 100644
index 6d9a682..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderIT.java
+++ /dev/null
@@ -1,431 +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.access;
-
-import org.apache.cayenne.access.loader.DbLoaderConfiguration;
-import org.apache.cayenne.access.loader.filters.FiltersConfig;
-import org.apache.cayenne.access.loader.filters.PatternFilter;
-import org.apache.cayenne.access.loader.filters.TableFilter;
-import org.apache.cayenne.configuration.server.ServerRuntime;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.dba.TypesMapping;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.map.*;
-import org.apache.cayenne.unit.UnitDbAdapter;
-import org.apache.cayenne.unit.di.server.CayenneProjects;
-import org.apache.cayenne.unit.di.server.ServerCase;
-import org.apache.cayenne.unit.di.server.ServerCaseDataSourceFactory;
-import org.apache.cayenne.unit.di.server.UseServerRuntime;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.sql.Types;
-import java.util.Collection;
-import java.util.List;
-
-import static org.junit.Assert.*;
-
-@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
-public class DbLoaderIT extends ServerCase {
-
- public static final DbLoaderConfiguration CONFIG = new DbLoaderConfiguration();
- @Inject
- private ServerRuntime runtime;
-
- @Inject
- private DbAdapter adapter;
-
- @Inject
- private ServerCaseDataSourceFactory dataSourceFactory;
-
- @Inject
- private UnitDbAdapter accessStackAdapter;
-
- private DbLoader loader;
-
- @Before
- public void setUp() throws Exception {
- loader = new DbLoader(dataSourceFactory.getSharedDataSource().getConnection(), adapter, null);
- }
-
- @After
- public void tearDown() throws Exception {
- loader.getConnection().close();
- }
-
- @Test
- public void testGetTableTypes() throws Exception {
-
- List<?> tableTypes = loader.getTableTypes();
-
- assertNotNull(tableTypes);
-
- String tableLabel = adapter.tableTypeForTable();
- if (tableLabel != null) {
- assertTrue("Missing type for table '" + tableLabel + "' - " + tableTypes, tableTypes.contains(tableLabel));
- }
-
- String viewLabel = adapter.tableTypeForView();
- if (viewLabel != null) {
- assertTrue("Missing type for view '" + viewLabel + "' - " + tableTypes, tableTypes.contains(viewLabel));
- }
- }
-
- @Test
- public void testGetTables() throws Exception {
-
- String tableLabel = adapter.tableTypeForTable();
-
- List<DetectedDbEntity> tables = loader.createTableLoader(null, null, TableFilter.everything())
- .getDbEntities(TableFilter.everything(), new String[]{tableLabel});
-
- assertNotNull(tables);
-
- boolean foundArtist = false;
-
- for (DetectedDbEntity table : tables) {
- if ("ARTIST".equalsIgnoreCase(table.getName())) {
- foundArtist = true;
- break;
- }
- }
-
- assertTrue("'ARTIST' is missing from the table list: " + tables, foundArtist);
- }
-
- @Test
- public void testGetTablesWithWrongCatalog() throws Exception {
-
- DbLoaderConfiguration config = new DbLoaderConfiguration();
- config.setFiltersConfig(
- FiltersConfig.create("WRONG", null, TableFilter.everything(), PatternFilter.INCLUDE_NOTHING));
- List<DetectedDbEntity> tables = loader
- .createTableLoader("WRONG", null, TableFilter.everything())
- .getDbEntities(TableFilter.everything(), new String[]{adapter.tableTypeForTable()});
-
- assertNotNull(tables);
- assertTrue(tables.isEmpty());
- }
-
- @Test
- public void testGetTablesWithWrongSchema() throws Exception {
-
- DbLoaderConfiguration config = new DbLoaderConfiguration();
- config.setFiltersConfig(
- FiltersConfig.create(null, "WRONG", TableFilter.everything(), PatternFilter.INCLUDE_NOTHING));
- List<DetectedDbEntity> tables = loader
- .createTableLoader(null, "WRONG", TableFilter.everything())
- .getDbEntities(TableFilter.everything(), new String[]{adapter.tableTypeForTable()});
-
- assertNotNull(tables);
- assertTrue(tables.isEmpty());
- }
-
- @Test
- public void testLoadWithMeaningfulPK() throws Exception {
-
- DataMap map = new DataMap();
- String[] tableLabel = { adapter.tableTypeForTable() };
-
- loader.setCreatingMeaningfulPK(true);
-
- List<DbEntity> entities = loader
- .createTableLoader(null, null, TableFilter.everything())
- .loadDbEntities(map, CONFIG, tableLabel);
-
- loader.loadObjEntities(map, CONFIG, entities);
-
- ObjEntity artist = map.getObjEntity("Artist");
- assertNotNull(artist);
-
- ObjAttribute id = artist.getAttribute("artistId");
- assertNotNull(id);
- }
-
- /**
- * DataMap loading is in one big test method, since breaking it in
- * individual tests would require multiple reads of metatdata which is
- * extremely slow on some RDBMS (Sybase).
- */
- @Test
- public void testLoad() throws Exception {
-
- boolean supportsUnique = runtime.getDataDomain().getDataNodes().iterator().next().getAdapter()
- .supportsUniqueConstraints();
- boolean supportsLobs = accessStackAdapter.supportsLobs();
- boolean supportsFK = accessStackAdapter.supportsFKConstraints();
-
- DataMap map = new DataMap();
- map.setDefaultPackage("foo.x");
-
- String tableLabel = adapter.tableTypeForTable();
-
- // *** TESTING THIS ***
- List<DbEntity> entities = loader
- .createTableLoader(null, null, TableFilter.everything())
- .loadDbEntities(map, CONFIG, new String[]{adapter.tableTypeForTable()});
-
-
- assertDbEntities(map);
-
- if (supportsLobs) {
- assertLobDbEntities(map);
- }
-
- // *** TESTING THIS ***
- loader.loadDbRelationships(CONFIG, null, null, entities);
-
- if (supportsFK) {
- Collection<DbRelationship> rels = getDbEntity(map, "ARTIST").getRelationships();
- assertNotNull(rels);
- assertTrue(!rels.isEmpty());
-
- // test one-to-one
- rels = getDbEntity(map, "PAINTING").getRelationships();
- assertNotNull(rels);
-
- // find relationship to PAINTING_INFO
- DbRelationship oneToOne = null;
- for (DbRelationship rel : rels) {
- if ("PAINTING_INFO".equalsIgnoreCase(rel.getTargetEntityName())) {
- oneToOne = rel;
- break;
- }
- }
-
- assertNotNull("No relationship to PAINTING_INFO", oneToOne);
- assertFalse("Relationship to PAINTING_INFO must be to-one", oneToOne.isToMany());
- assertTrue("Relationship to PAINTING_INFO must be to-one", oneToOne.isToDependentPK());
-
- // test UNIQUE only if FK is supported...
- if (supportsUnique) {
- assertUniqueConstraintsInRelationships(map);
- }
- }
-
- // *** TESTING THIS ***
- loader.setCreatingMeaningfulPK(false);
- loader.loadObjEntities(map, CONFIG, entities);
-
- assertObjEntities(map);
-
- // now when the map is loaded, test
- // various things
- // selectively check how different types were processed
- if (accessStackAdapter.supportsColumnTypeReengineering()) {
- checkTypes(map);
- }
- }
-
- private void assertUniqueConstraintsInRelationships(DataMap map) {
- // unfortunately JDBC metadata doesn't provide info for UNIQUE
- // constraints....
- // cant reengineer them...
-
- // find rel to TO_ONEFK1
- /*
- * Iterator it = getDbEntity(map,
- * "TO_ONEFK2").getRelationships().iterator(); DbRelationship rel =
- * (DbRelationship) it.next(); assertEquals("TO_ONEFK1",
- * rel.getTargetEntityName());
- * assertFalse("UNIQUE constraint was ignored...", rel.isToMany());
- */
- }
-
- private void assertDbEntities(DataMap map) {
- DbEntity dae = getDbEntity(map, "ARTIST");
- assertNotNull("Null 'ARTIST' entity, other DbEntities: " + map.getDbEntityMap(), dae);
- assertEquals("ARTIST", dae.getName().toUpperCase());
-
- DbAttribute a = getDbAttribute(dae, "ARTIST_ID");
- assertNotNull(a);
- assertTrue(a.isPrimaryKey());
- assertFalse(a.isGenerated());
-
- if (adapter.supportsGeneratedKeys()) {
- DbEntity bag = getDbEntity(map, "GENERATED_COLUMN_TEST");
- DbAttribute id = getDbAttribute(bag, "GENERATED_COLUMN");
- assertTrue(id.isPrimaryKey());
- assertTrue(id.isGenerated());
- }
- }
-
- private void assertObjEntities(DataMap map) {
-
- boolean supportsLobs = accessStackAdapter.supportsLobs();
- boolean supportsFK = accessStackAdapter.supportsFKConstraints();
-
- ObjEntity ae = map.getObjEntity("Artist");
- assertNotNull(ae);
- assertEquals("Artist", ae.getName());
-
- // assert primary key is not an attribute
- assertNull(ae.getAttribute("artistId"));
-
- if (supportsLobs) {
- assertLobObjEntities(map);
- }
-
- if (supportsFK) {
- Collection<?> rels1 = ae.getRelationships();
- assertNotNull(rels1);
- assertTrue(rels1.size() > 0);
- }
-
- assertEquals("foo.x.Artist", ae.getClassName());
- }
-
- private void assertLobDbEntities(DataMap map) {
- DbEntity blobEnt = getDbEntity(map, "BLOB_TEST");
- assertNotNull(blobEnt);
- DbAttribute blobAttr = getDbAttribute(blobEnt, "BLOB_COL");
- assertNotNull(blobAttr);
- assertTrue(msgForTypeMismatch(Types.BLOB, blobAttr), Types.BLOB == blobAttr.getType()
- || Types.LONGVARBINARY == blobAttr.getType());
-
- DbEntity clobEnt = getDbEntity(map, "CLOB_TEST");
- assertNotNull(clobEnt);
- DbAttribute clobAttr = getDbAttribute(clobEnt, "CLOB_COL");
- assertNotNull(clobAttr);
- assertTrue(msgForTypeMismatch(Types.CLOB, clobAttr), Types.CLOB == clobAttr.getType()
- || Types.LONGVARCHAR == clobAttr.getType());
-
-/*
- DbEntity nclobEnt = getDbEntity(map, "NCLOB_TEST");
- assertNotNull(nclobEnt);
- DbAttribute nclobAttr = getDbAttribute(nclobEnt, "NCLOB_COL");
- assertNotNull(nclobAttr);
- assertTrue(msgForTypeMismatch(Types.NCLOB, nclobAttr), Types.NCLOB == nclobAttr.getType()
- || Types.LONGVARCHAR == nclobAttr.getType());
-*/
- }
-
- private void assertLobObjEntities(DataMap map) {
- ObjEntity blobEnt = map.getObjEntity("BlobTest");
- assertNotNull(blobEnt);
- // BLOBs should be mapped as byte[]
- ObjAttribute blobAttr = blobEnt.getAttribute("blobCol");
- assertNotNull("BlobTest.blobCol failed to doLoad", blobAttr);
- assertEquals("byte[]", blobAttr.getType());
-
-
- ObjEntity clobEnt = map.getObjEntity("ClobTest");
- assertNotNull(clobEnt);
- // CLOBs should be mapped as Strings by default
- ObjAttribute clobAttr = clobEnt.getAttribute("clobCol");
- assertNotNull(clobAttr);
- assertEquals(String.class.getName(), clobAttr.getType());
-
-
- ObjEntity nclobEnt = map.getObjEntity("NclobTest");
- assertNotNull(nclobEnt);
- // CLOBs should be mapped as Strings by default
- ObjAttribute nclobAttr = nclobEnt.getAttribute("nclobCol");
- assertNotNull(nclobAttr);
- assertEquals(String.class.getName(), nclobAttr.getType());
- }
-
- private DbEntity getDbEntity(DataMap map, String name) {
- DbEntity de = map.getDbEntity(name);
- // sometimes table names get converted to lowercase
- if (de == null) {
- de = map.getDbEntity(name.toLowerCase());
- }
-
- return de;
- }
-
- private DbAttribute getDbAttribute(DbEntity ent, String name) {
- DbAttribute da = ent.getAttribute(name);
- // sometimes table names get converted to lowercase
- if (da == null) {
- da = ent.getAttribute(name.toLowerCase());
- }
-
- return da;
- }
-
- private DataMap originalMap() {
- return runtime.getDataDomain().getDataNodes().iterator().next().getDataMaps().iterator().next();
- }
-
- /**
- * Selectively check how different types were processed.
- */
- public void checkTypes(DataMap map) {
- DbEntity dbe = getDbEntity(map, "PAINTING");
- DbEntity floatTest = getDbEntity(map, "FLOAT_TEST");
- DbEntity smallintTest = getDbEntity(map, "SMALLINT_TEST");
- DbAttribute integerAttr = getDbAttribute(dbe, "PAINTING_ID");
- DbAttribute decimalAttr = getDbAttribute(dbe, "ESTIMATED_PRICE");
- DbAttribute varcharAttr = getDbAttribute(dbe, "PAINTING_TITLE");
- DbAttribute floatAttr = getDbAttribute(floatTest, "FLOAT_COL");
- DbAttribute smallintAttr = getDbAttribute(smallintTest, "SMALLINT_COL");
-
- // check decimal
- assertTrue(msgForTypeMismatch(Types.DECIMAL, decimalAttr), Types.DECIMAL == decimalAttr.getType()
- || Types.NUMERIC == decimalAttr.getType());
- assertEquals(2, decimalAttr.getScale());
-
- // check varchar
- assertEquals(msgForTypeMismatch(Types.VARCHAR, varcharAttr), Types.VARCHAR, varcharAttr.getType());
- assertEquals(255, varcharAttr.getMaxLength());
- // check integer
- assertEquals(msgForTypeMismatch(Types.INTEGER, integerAttr), Types.INTEGER, integerAttr.getType());
- // check float
- assertTrue(msgForTypeMismatch(Types.FLOAT, floatAttr), Types.FLOAT == floatAttr.getType()
- || Types.DOUBLE == floatAttr.getType() || Types.REAL == floatAttr.getType());
-
- // check smallint
- assertTrue(msgForTypeMismatch(Types.SMALLINT, smallintAttr), Types.SMALLINT == smallintAttr.getType()
- || Types.INTEGER == smallintAttr.getType());
- }
-
- public void checkAllDBEntities(DataMap map) {
-
- for (DbEntity origEnt : originalMap().getDbEntities()) {
- DbEntity newEnt = map.getDbEntity(origEnt.getName());
- for (DbAttribute origAttr : origEnt.getAttributes()) {
- DbAttribute newAttr = newEnt.getAttribute(origAttr.getName());
- assertNotNull("No matching DbAttribute for '" + origAttr.getName(), newAttr);
- assertEquals(msgForTypeMismatch(origAttr, newAttr), origAttr.getType(), newAttr.getType());
- // length and precision doesn't have to be the same
- // it must be greater or equal
- assertTrue(origAttr.getMaxLength() <= newAttr.getMaxLength());
- assertTrue(origAttr.getScale() <= newAttr.getScale());
- }
- }
- }
-
- private static String msgForTypeMismatch(DbAttribute origAttr, DbAttribute newAttr) {
- return msgForTypeMismatch(origAttr.getType(), newAttr);
- }
-
- private static String msgForTypeMismatch(int origType, DbAttribute newAttr) {
- String nt = TypesMapping.getSqlNameByType(newAttr.getType());
- String ot = TypesMapping.getSqlNameByType(origType);
- return attrMismatch(newAttr.getName(), "expected type: <" + ot + ">, but was <" + nt + ">");
- }
-
- private static String attrMismatch(String attrName, String msg) {
- return "[Error loading attribute '" + attrName + "': " + msg + "]";
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderPartialIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderPartialIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderPartialIT.java
deleted file mode 100644
index 7514b99..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderPartialIT.java
+++ /dev/null
@@ -1,118 +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.access;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import java.util.Collection;
-
-import org.apache.cayenne.CayenneException;
-import org.apache.cayenne.access.loader.DefaultDbLoaderDelegate;
-import org.apache.cayenne.dba.DbAdapter;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.unit.di.server.CayenneProjects;
-import org.apache.cayenne.unit.di.server.ServerCase;
-import org.apache.cayenne.unit.di.server.ServerCaseDataSourceFactory;
-import org.apache.cayenne.unit.di.server.UseServerRuntime;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
-public class DbLoaderPartialIT extends ServerCase {
-
- @Inject
- private DbAdapter adapter;
-
- @Inject
- private ServerCaseDataSourceFactory dataSourceFactory;
-
- private DbLoader loader;
-
- @Before
- public void setUp() throws Exception {
- loader = new DbLoader(
- dataSourceFactory.getSharedDataSource().getConnection(),
- adapter,
- new DefaultDbLoaderDelegate());
- }
-
- @After
- public void tearDown() throws Exception {
- loader.getConnection().close();
- }
-
- /**
- * Tests that FKs are properly loaded when the relationship source is not loaded. See
- * CAY-479. This test will perform two reverse engineers. The second reverse engineer
- * will skip two tables that share relationships with PAINTING. Relationships in
- * ARTIST and GALLERY should remain unmodified, and all PAINTING relationships should
- * be loaded.
- */
- @Test
- public void testPartialLoad() throws Exception {
-
- DataMap map = new DataMap();
- String tableLabel = adapter.tableTypeForTable();
-
- loader.loadDataMapFromDB(null, "%", new String[] {tableLabel}, map);
-
- Collection<?> rels = getDbEntity(map, "ARTIST").getRelationships();
- assertNotNull(rels);
- int artistRels = rels.size();
-
- rels = getDbEntity(map, "GALLERY").getRelationships();
- assertNotNull(rels);
- int galleryRels = rels.size();
-
- rels = getDbEntity(map, "PAINTING").getRelationships();
- assertNotNull(rels);
- int paintingRels = rels.size();
-
- loader.loadDataMapFromDB(null, "%", new String[] {
- tableLabel
- }, map);
-
- rels = getDbEntity(map, "ARTIST").getRelationships();
- assertNotNull(rels);
- assertEquals(artistRels, rels.size());
-
- rels = getDbEntity(map, "GALLERY").getRelationships();
- assertNotNull(rels);
- assertEquals(galleryRels, rels.size());
-
- rels = getDbEntity(map, "PAINTING").getRelationships();
- assertNotNull(rels);
- assertEquals(paintingRels, rels.size());
- }
-
- private DbEntity getDbEntity(DataMap map, String name) {
- DbEntity de = map.getDbEntity(name);
- // sometimes table names get converted to lowercase
- if (de == null) {
- de = map.getDbEntity(name.toLowerCase());
- }
-
- return de;
- }
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntityTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntityTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntityTest.java
deleted file mode 100644
index ad4238f..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntityTest.java
+++ /dev/null
@@ -1,113 +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.access.loader;
-
-import org.apache.cayenne.configuration.ConfigurationNameMapper;
-import org.apache.cayenne.configuration.ConfigurationTree;
-import org.apache.cayenne.configuration.DataChannelDescriptor;
-import org.apache.cayenne.configuration.DataMapLoader;
-import org.apache.cayenne.configuration.DefaultConfigurationNameMapper;
-import org.apache.cayenne.configuration.XMLDataChannelDescriptorLoader;
-import org.apache.cayenne.configuration.XMLDataMapLoader;
-import org.apache.cayenne.di.AdhocObjectFactory;
-import org.apache.cayenne.di.Binder;
-import org.apache.cayenne.di.ClassLoaderManager;
-import org.apache.cayenne.di.DIBootstrap;
-import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.di.Module;
-import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory;
-import org.apache.cayenne.di.spi.DefaultClassLoaderManager;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.map.Relationship;
-import org.apache.cayenne.map.naming.LegacyNameGenerator;
-import org.apache.cayenne.resource.URLResource;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.net.URL;
-import java.util.ArrayList;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-public class ManyToManyCandidateEntityTest {
-
- private DataMap map;
-
- @Before
- public void setUp() throws Exception {
- Module testModule = new Module() {
-
- public void configure(Binder binder) {
- binder.bind(ClassLoaderManager.class).to(DefaultClassLoaderManager.class);
- binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class);
- binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
- binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class);
- }
- };
-
- Injector injector = DIBootstrap.createInjector(testModule);
-
- // create and initialize loader instance to test
- XMLDataChannelDescriptorLoader loader = new XMLDataChannelDescriptorLoader();
- injector.injectMembers(loader);
-
- String testConfigName = "relationship-optimisation";
- URL url = getClass().getResource("cayenne-" + testConfigName + ".xml");
-
- ConfigurationTree<DataChannelDescriptor> tree = loader.load(new URLResource(url));
-
- map = tree.getRootNode().getDataMap(testConfigName);
- }
-
- @Test
- public void testMatchingForManyToManyEntity() throws Exception {
- ObjEntity manyToManyEntity = map.getObjEntity("Table1Table2");
-
- assertNotNull(ManyToManyCandidateEntity.build(manyToManyEntity));
- }
-
- @Test
- public void testMatchingForNotManyToManyEntity() throws Exception {
- ObjEntity entity = map.getObjEntity("Table1");
-
- assertNull(ManyToManyCandidateEntity.build(entity));
- }
-
- @Test
- public void testOptimisationForManyToManyEntity() {
- ObjEntity manyToManyEntity = map.getObjEntity("Table1Table2");
-
- ManyToManyCandidateEntity.build(manyToManyEntity).optimizeRelationships(new LegacyNameGenerator());
-
- ObjEntity table1Entity = map.getObjEntity("Table1");
- ObjEntity table2Entity = map.getObjEntity("Table2");
-
- assertEquals(1, table1Entity.getRelationships().size());
- assertEquals(table2Entity, new ArrayList<Relationship>(table1Entity.getRelationships()).get(0)
- .getTargetEntity());
-
- assertEquals(1, table2Entity.getRelationships().size());
- assertEquals(table1Entity, new ArrayList<Relationship>(table2Entity.getRelationships()).get(0)
- .getTargetEntity());
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/FiltersConfigTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/FiltersConfigTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/FiltersConfigTest.java
deleted file mode 100644
index a43f890..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/FiltersConfigTest.java
+++ /dev/null
@@ -1,93 +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.access.loader.filters;
-
-import junit.framework.TestCase;
-
-import java.util.Collections;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import java.util.regex.Pattern;
-
-public class FiltersConfigTest extends TestCase {
-
- public void testToString_01() {
- FiltersConfig config = FiltersConfig.create(null, null,
- TableFilter.everything(), PatternFilter.INCLUDE_EVERYTHING);
-
- assertEquals("Catalog: null\n" +
- " Schema: null\n" +
- " Tables: \n" +
- " Include: null Columns: ALL\n" +
- " Procedures: ALL\n", config.toString());
- }
-
- public void testToString_02() {
- FiltersConfig config = new FiltersConfig(
- new CatalogFilter("catalog_01",
- new SchemaFilter("schema_11", TableFilter.everything(), PatternFilter.INCLUDE_EVERYTHING)),
- new CatalogFilter("catalog_02",
- new SchemaFilter("schema_21", TableFilter.everything(), PatternFilter.INCLUDE_NOTHING),
- new SchemaFilter("schema_22",
- new TableFilter(
- includes(new IncludeTableFilter(null, PatternFilter.INCLUDE_NOTHING)),
- excludes("aaa")),
- PatternFilter.INCLUDE_NOTHING),
- new SchemaFilter("schema_23", TableFilter.include("include"), PatternFilter.INCLUDE_NOTHING)
- )
- );
-
- assertEquals("Catalog: catalog_01\n" +
- " Schema: schema_11\n" +
- " Tables: \n" +
- " Include: null Columns: ALL\n" +
- " Procedures: ALL\n" +
- "Catalog: catalog_02\n" +
- " Schema: schema_21\n" +
- " Tables: \n" +
- " Include: null Columns: ALL\n" +
- " Procedures: NONE\n" +
- " Schema: schema_22\n" +
- " Tables: \n" +
- " Include: null Columns: NONE\n" +
- " aaa\n" +
- " Procedures: NONE\n" +
- " Schema: schema_23\n" +
- " Tables: \n" +
- " Include: include Columns: ALL\n" +
- " Procedures: NONE\n", config.toString());
- }
-
- private SortedSet<Pattern> excludes(String ... p) {
- SortedSet<Pattern> patterns = new TreeSet<Pattern>(PatternFilter.PATTERN_COMPARATOR);
- for (String pattern : p) {
- patterns.add(PatternFilter.pattern(pattern));
- }
- return patterns;
- }
-
- protected SortedSet<IncludeTableFilter> includes(IncludeTableFilter ... filters) {
- SortedSet<IncludeTableFilter> includeTableFilters = new TreeSet<IncludeTableFilter>();
- Collections.addAll(includeTableFilters, filters);
-
- return includeTableFilters;
- }
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/IncludeFilterTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/IncludeFilterTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/IncludeFilterTest.java
deleted file mode 100644
index c8cbe5b..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/IncludeFilterTest.java
+++ /dev/null
@@ -1,34 +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.access.loader.filters;
-
-import org.junit.Test;
-
-public class IncludeFilterTest {
-
- @Test
- public void testIsInclude() throws Exception {
-// IncludeFilter filter = new IncludeFilter(pattern("^v_.*$"));
-// assertTrue(filter.isInclude("v_new_view"));
-// assertFalse(filter.isInclude("new_view"));
-// assertFalse(filter.isInclude("view"));
-// assertFalse(filter.isInclude("girl"));
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/PatternFilterTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/PatternFilterTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/PatternFilterTest.java
deleted file mode 100644
index 5bd07d4..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/PatternFilterTest.java
+++ /dev/null
@@ -1,78 +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.access.loader.filters;
-
-import junit.framework.TestCase;
-
-public class PatternFilterTest extends TestCase {
-
- public void testInclude() throws Exception {
- PatternFilter filter = new PatternFilter()
- .include("aaa")
- .include("bbb");
-
- assertTrue(filter.isInclude("aaa"));
- assertTrue(filter.isInclude("bbb"));
- assertFalse(filter.isInclude("aaaa"));
- assertFalse(filter.isInclude("aa"));
- assertFalse(filter.isInclude("abb"));
-
- filter = new PatternFilter().include("^v_.*$");
- assertTrue(filter.isInclude("v_new_view"));
- assertFalse(filter.isInclude("new_view"));
- assertFalse(filter.isInclude("view"));
- assertFalse(filter.isInclude("girl"));
- }
-
- public void testExclude() throws Exception {
- PatternFilter filter = new PatternFilter()
- .exclude("aaa")
- .exclude("bbb");
-
- assertFalse(filter.isInclude("aaa"));
- assertFalse(filter.isInclude("bbb"));
- assertTrue(filter.isInclude("aaaa"));
- assertTrue(filter.isInclude("aa"));
- assertTrue(filter.isInclude("abb"));
- }
-
- public void testIncludeExclude() throws Exception {
- PatternFilter filter = new PatternFilter()
- .include("aa.*")
- .exclude("aaa");
-
- assertFalse(filter.isInclude("aaa"));
- assertFalse(filter.isInclude("bbb"));
- assertTrue(filter.isInclude("aaaa"));
- assertTrue(filter.isInclude("aa"));
- assertFalse(filter.isInclude("abb"));
- }
-
- public void testIncludeAllFilter() {
- assertTrue(PatternFilter.INCLUDE_EVERYTHING.isInclude("qwe"));
- assertTrue(PatternFilter.INCLUDE_EVERYTHING.isInclude(""));
- assertTrue(PatternFilter.INCLUDE_EVERYTHING.isInclude(null));
- }
-
- public void testIncludeNoneFilter() {
- assertFalse(PatternFilter.INCLUDE_NOTHING.isInclude("qwe"));
- assertFalse(PatternFilter.INCLUDE_NOTHING.isInclude(""));
- assertFalse(PatternFilter.INCLUDE_NOTHING.isInclude(null));
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/TableFilterTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/TableFilterTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/TableFilterTest.java
deleted file mode 100644
index 4fad476..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/TableFilterTest.java
+++ /dev/null
@@ -1,91 +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.access.loader.filters;
-
-import junit.framework.TestCase;
-
-import java.util.TreeSet;
-import java.util.regex.Pattern;
-
-public class TableFilterTest extends TestCase {
-
- public void testIncludeEverything() {
- TableFilter filter = TableFilter.everything();
-
- assertNotNull(filter.isIncludeTable("table"));
- assertNotNull(filter.isIncludeTable("aaaa"));
- assertNotNull(filter.isIncludeTable(""));
- assertNotNull(filter.isIncludeTable("alex"));
- }
-
- public void testInclude() {
- TreeSet<IncludeTableFilter> includes = new TreeSet<IncludeTableFilter>();
- includes.add(new IncludeTableFilter("aaa"));
- includes.add(new IncludeTableFilter("bb"));
-
- TableFilter filter = new TableFilter(includes, new TreeSet<Pattern>(PatternFilter.PATTERN_COMPARATOR));
-
- assertNotNull(filter.isIncludeTable("aaa"));
- assertNull(filter.isIncludeTable("aa"));
- assertNull(filter.isIncludeTable("aaaa"));
-
- assertNotNull(filter.isIncludeTable("bb"));
- assertNull(filter.isIncludeTable(""));
- assertNull(filter.isIncludeTable("bbbb"));
- }
-
-
- public void testExclude() {
- TreeSet<Pattern> excludes = new TreeSet<Pattern>(PatternFilter.PATTERN_COMPARATOR);
- excludes.add(Pattern.compile("aaa"));
- excludes.add(Pattern.compile("bb"));
-
- TreeSet<IncludeTableFilter> includes = new TreeSet<IncludeTableFilter>();
- includes.add(new IncludeTableFilter(null, PatternFilter.INCLUDE_EVERYTHING));
-
- TableFilter filter = new TableFilter(includes, excludes);
-
- assertNull(filter.isIncludeTable("aaa"));
- assertNotNull(filter.isIncludeTable("aa"));
- assertNotNull(filter.isIncludeTable("aaaa"));
-
- assertNull(filter.isIncludeTable("bb"));
- assertNotNull(filter.isIncludeTable(""));
- assertNotNull(filter.isIncludeTable("bbbb"));
- }
-
- public void testIncludeExclude() {
- TreeSet<Pattern> excludes = new TreeSet<Pattern>(PatternFilter.PATTERN_COMPARATOR);
- excludes.add(Pattern.compile("aaa"));
- excludes.add(Pattern.compile("bb"));
-
- TreeSet<IncludeTableFilter> includes = new TreeSet<IncludeTableFilter>();
- includes.add(new IncludeTableFilter("aa.*"));
-
- TableFilter filter = new TableFilter(includes, excludes);
-
- assertNull(filter.isIncludeTable("aaa"));
- assertNotNull(filter.isIncludeTable("aa"));
- assertNotNull(filter.isIncludeTable("aaaa"));
-
- assertNull(filter.isIncludeTable("bb"));
- assertNull(filter.isIncludeTable(""));
- assertNull(filter.isIncludeTable("bbbb"));
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/access/loader/mapper/DbTypeTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/loader/mapper/DbTypeTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/loader/mapper/DbTypeTest.java
deleted file mode 100644
index 8b2e8d4..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/loader/mapper/DbTypeTest.java
+++ /dev/null
@@ -1,87 +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.access.loader.mapper;
-
-import org.junit.Test;
-
-import java.util.Iterator;
-import java.util.TreeSet;
-
-import static org.junit.Assert.*;
-
-public class DbTypeTest {
-
- @Test
- public void testCompareTo() throws Exception {
- TreeSet<DbType> set = new TreeSet<DbType>();
- set.add(new DbType("type-01", null, null, null, null));
- set.add(new DbType("type-02", null, null, null, null));
- set.add(new DbType("type-02", 1, null, null, null));
- set.add(new DbType("type-02", 2, null, null, null));
- set.add(new DbType("type-02", 2, null, null, true));
- set.add(new DbType("type-02", 2, null, null, false));
- set.add(new DbType("type-02", 2, null, 5, null));
- set.add(new DbType("type-02", 2, null, 5, false));
- set.add(new DbType("type-02", 2, null, 5, true));
- set.add(new DbType("type-02", null, 8, 5, true));
- set.add(new DbType("type-02", null, 9, 5, true));
-
- Iterator<DbType> iterator = set.iterator();
- assertEquals(new DbType("type-02", 2, null, 5, true), iterator.next());
- assertEquals(new DbType("type-02", 2, null, 5, false), iterator.next());
- assertEquals(new DbType("type-02", null, 9, 5, true), iterator.next());
- assertEquals(new DbType("type-02", null, 8, 5, true), iterator.next());
- assertEquals(new DbType("type-02", 2, null, 5, null), iterator.next());
- assertEquals(new DbType("type-02", 2, null, null, true), iterator.next());
- assertEquals(new DbType("type-02", 2, null, null, false), iterator.next());
- assertEquals(new DbType("type-02", 2, null, null, null), iterator.next());
- assertEquals(new DbType("type-02", 1, null, null, null), iterator.next());
- assertEquals(new DbType("type-02", null, null, null, null), iterator.next());
- assertEquals(new DbType("type-01", null, null, null, null), iterator.next());
- }
-
- @Test
- public void testCover() throws Exception {
- DbType typeJava = new DbType("java");
- assertTrue(typeJava.isCover(typeJava));
- assertTrue(typeJava.isCover(new DbType("java", 1, 1, 1, null)));
- assertTrue(typeJava.isCover(new DbType("java", 1, null, null, null)));
- assertTrue(typeJava.isCover(new DbType("java", null, 1, null, null)));
- assertTrue(typeJava.isCover(new DbType("java", null, null, 1, null)));
- assertTrue(typeJava.isCover(new DbType("java", null, null, null, true)));
- assertTrue(typeJava.isCover(new DbType("java", null, null, null, false)));
- assertFalse(typeJava.isCover(new DbType("java1", null, null, null, null)));
-
- DbType typeWithLength = new DbType("java", 1, null, null, null);
- assertTrue(typeWithLength.isCover(typeWithLength));
- assertTrue(typeWithLength.isCover(new DbType("java", 1, null, 1, null)));
- assertTrue(typeWithLength.isCover(new DbType("java", 1, null, 1, true)));
- assertTrue(typeWithLength.isCover(new DbType("java", 1, null, null, true)));
- assertTrue(typeWithLength.isCover(new DbType("java", 1, 1, null, true)));
- assertFalse(typeWithLength.isCover(new DbType("java", 2, null, null, null)));
- assertFalse(typeWithLength.isCover(new DbType("java", null, null, null, true)));
- assertFalse(typeWithLength.isCover(new DbType("java1", 2, null, null, null)));
-
- DbType typeWithLengthAndNotNull = new DbType("java", 1, null, null, true);
- assertTrue(typeWithLength.isCover(typeWithLengthAndNotNull));
- assertTrue(typeWithLength.isCover(new DbType("java", 1, null, 1, true)));
- assertTrue(typeWithLength.isCover(new DbType("java", 1, 1, 1, true)));
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-server/src/test/java/org/apache/cayenne/dba/PerAdapterProviderTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/dba/PerAdapterProviderTest.java b/cayenne-server/src/test/java/org/apache/cayenne/dba/PerAdapterProviderTest.java
new file mode 100644
index 0000000..fb2ebcb
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/dba/PerAdapterProviderTest.java
@@ -0,0 +1,83 @@
+/*****************************************************************
+ * 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.dba;
+
+import org.apache.cayenne.access.types.ExtendedType;
+import org.apache.cayenne.access.types.ExtendedTypeFactory;
+import org.apache.cayenne.configuration.RuntimeProperties;
+import org.apache.cayenne.dba.derby.DerbyAdapter;
+import org.apache.cayenne.dba.oracle.OracleAdapter;
+import org.apache.cayenne.di.DIRuntimeException;
+import org.apache.cayenne.di.Provider;
+import org.apache.cayenne.di.spi.DefaultClassLoaderManager;
+import org.apache.cayenne.log.CommonsJdbcEventLogger;
+import org.apache.cayenne.resource.ClassLoaderResourceLocator;
+import org.apache.cayenne.resource.ResourceLocator;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+
+public class PerAdapterProviderTest {
+
+ private OracleAdapter oracleAdapter;
+ private DerbyAdapter derbyAdapter;
+ private AutoAdapter autoDerbyAdapter;
+
+ @Before
+ public void before() {
+
+ ResourceLocator locator = new ClassLoaderResourceLocator(new DefaultClassLoaderManager());
+ RuntimeProperties runtimeProperties = mock(RuntimeProperties.class);
+
+ this.oracleAdapter = new OracleAdapter(runtimeProperties,
+ Collections.<ExtendedType>emptyList(),
+ Collections.<ExtendedType>emptyList(),
+ Collections.<ExtendedTypeFactory>emptyList(),
+ locator);
+
+ this.derbyAdapter = new DerbyAdapter(runtimeProperties,
+ Collections.<ExtendedType>emptyList(),
+ Collections.<ExtendedType>emptyList(),
+ Collections.<ExtendedTypeFactory>emptyList(),
+ locator);
+
+ this.autoDerbyAdapter = new AutoAdapter(new Provider<DbAdapter>() {
+ @Override
+ public DbAdapter get() throws DIRuntimeException {
+ return derbyAdapter;
+ }
+ }, new CommonsJdbcEventLogger(runtimeProperties));
+ }
+
+ @Test
+ public void testGet() {
+
+ Map<String, String> map = Collections.singletonMap(DerbyAdapter.class.getName(), "x");
+ PerAdapterProvider<String> provider = new PerAdapterProvider<>(map, "default");
+
+ assertEquals("default", provider.get(oracleAdapter));
+ assertEquals("x", provider.get(derbyAdapter));
+ assertEquals("x", provider.get(autoDerbyAdapter));
+ }
+}
[14/15] cayenne git commit: CAY-2116 Split schema synchronization
code in a separate module
Posted by aa...@apache.org.
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToModel.java
new file mode 100644
index 0000000..ceb03bc
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropColumnToModel.java
@@ -0,0 +1,75 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+
+/**
+ * A {@link MergerToken} to remove a {@link DbAttribute} from a {@link DbEntity}.
+ *
+ */
+public class DropColumnToModel extends AbstractToModelToken.EntityAndColumn {
+
+ public DropColumnToModel(DbEntity entity, DbAttribute column) {
+ super("Drop Column", entity, column);
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return factory.createAddColumnToDb(getEntity(), getColumn());
+ }
+
+ public void execute(MergerContext mergerContext) {
+
+ // remove relationships mapped to column. duplicate List to prevent
+ // ConcurrentModificationException
+ List<DbRelationship> dbRelationships = new ArrayList<DbRelationship>(getEntity()
+ .getRelationships());
+ for (DbRelationship dbRelationship : dbRelationships) {
+ for (DbJoin join : dbRelationship.getJoins()) {
+ if (join.getSource() == getColumn() || join.getTarget() == getColumn()) {
+ remove(mergerContext.getModelMergeDelegate(), dbRelationship, true);
+ }
+ }
+ }
+
+ // remove ObjAttribute mapped to same column
+ for (ObjEntity objEntity : getEntity().mappedObjEntities()) {
+ ObjAttribute objAttribute = objEntity.getAttributeForDbAttribute(getColumn());
+ if (objAttribute != null) {
+ objEntity.removeAttribute(objAttribute.getName());
+ mergerContext.getModelMergeDelegate().objAttributeRemoved(objAttribute);
+ }
+
+ }
+
+ // remove DbAttribute
+ getEntity().removeAttribute(getColumn().getName());
+
+ mergerContext.getModelMergeDelegate().dbAttributeRemoved(getColumn());
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.java
new file mode 100644
index 0000000..238a44a
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToDb.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.dbsync.merge;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.DbRelationshipDetected;
+
+public class DropRelationshipToDb extends AbstractToDbToken.Entity {
+
+ private DbRelationship rel;
+
+ public DropRelationshipToDb(DbEntity entity, DbRelationship rel) {
+ super("Drop foreign key", entity);
+ this.rel = rel;
+ }
+
+ public String getFkName() {
+ if (rel instanceof DbRelationshipDetected) {
+ return ((DbRelationshipDetected) rel).getFkName();
+ }
+ return null;
+ }
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ String fkName = getFkName();
+ if (fkName == null) {
+ return Collections.emptyList();
+ }
+
+ QuotingStrategy context = adapter.getQuotingStrategy();
+ return Collections.singletonList(
+ "ALTER TABLE " + context.quotedFullyQualifiedName(getEntity()) + " DROP CONSTRAINT " + fkName);
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return factory.createAddRelationshipToModel(getEntity(), rel);
+ }
+
+ @Override
+ public String getTokenValue() {
+ return rel.getSourceEntity().getName() + "->" + rel.getTargetEntityName();
+ }
+
+ public DbRelationship getRelationship() {
+ return rel;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModel.java
new file mode 100644
index 0000000..686df6e
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropRelationshipToModel.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.dbsync.merge;
+
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+
+public class DropRelationshipToModel extends AbstractToModelToken.Entity {
+
+ private final DbRelationship rel;
+
+ public DropRelationshipToModel(DbEntity entity, DbRelationship rel) {
+ super("Drop db-relationship ", entity);
+ this.rel = rel;
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return factory.createAddRelationshipToDb(getEntity(), rel);
+ }
+
+ public void execute(MergerContext mergerContext) {
+ remove(mergerContext.getModelMergeDelegate(), rel, true);
+ }
+
+ @Override
+ public String getTokenValue() {
+ return AddRelationshipToModel.getTokenValue(rel);
+ }
+
+ public DbRelationship getRelationship() {
+ return rel;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToDb.java
new file mode 100644
index 0000000..6b76646
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToDb.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.dbsync.merge;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DbEntity;
+
+public class DropTableToDb extends AbstractToDbToken.Entity {
+
+ public DropTableToDb(DbEntity entity) {
+ super("Drop Table", entity);
+ }
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ List<String> sqls = new ArrayList<String>();
+ // TODO: fix. some adapters drop the complete AUTO_PK_SUPPORT here
+ /*
+ sqls.addAll(adapter.getPkGenerator().dropAutoPkStatements(
+ Collections.singletonList(entity)));
+ */
+ sqls.addAll(adapter.dropTableStatements(getEntity()));
+ return sqls;
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return factory.createCreateTableToModel(getEntity());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToModel.java
new file mode 100644
index 0000000..7a47f37
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DropTableToModel.java
@@ -0,0 +1,49 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.ObjEntity;
+
+/**
+ * A {@link MergerToken} to remove a {@link DbEntity} from a {@link DataMap}. Any
+ * {@link ObjEntity} mapped to the {@link DbEntity} will also be removed.
+ *
+ */
+public class DropTableToModel extends AbstractToModelToken.Entity {
+
+ public DropTableToModel(DbEntity entity) {
+ super("Drop Table", entity);
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return factory.createCreateTableToDb(getEntity());
+ }
+
+ public void execute(MergerContext mergerContext) {
+ for (ObjEntity objEntity : getEntity().mappedObjEntities()) {
+ objEntity.getDataMap().removeObjEntity(objEntity.getName(), true);
+ mergerContext.getModelMergeDelegate().objEntityRemoved(objEntity);
+ }
+ getEntity().getDataMap().removeDbEntity(getEntity().getName(), true);
+ mergerContext.getModelMergeDelegate().dbEntityRemoved(getEntity());
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DummyReverseToken.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DummyReverseToken.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DummyReverseToken.java
new file mode 100644
index 0000000..54b779b
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DummyReverseToken.java
@@ -0,0 +1,60 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+
+/**
+ * The reverse of a {@link MergerToken} that can not be reversed.. This will not execute
+ * any thing, but {@link #createReverse(MergerTokenFactory)} will get back the reverse that
+ * this was made from.
+ */
+class DummyReverseToken implements MergerToken {
+
+ private MergerToken reverse;
+
+ public DummyReverseToken(MergerToken reverse) {
+ this.reverse = reverse;
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return reverse;
+ }
+
+ public void execute(MergerContext mergerContext) {
+ // can not execute
+ }
+
+ public MergeDirection getDirection() {
+ return reverse.getDirection().reverseDirection();
+ }
+
+ public String getTokenName() {
+ return "Can not execute the reverse of " + reverse.getTokenName();
+ }
+
+ public String getTokenValue() {
+ return reverse.getTokenValue();
+ }
+
+ public boolean isReversible() {
+ return true;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EmptyValueForNullProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EmptyValueForNullProvider.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EmptyValueForNullProvider.java
new file mode 100644
index 0000000..a484655
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EmptyValueForNullProvider.java
@@ -0,0 +1,40 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+/**
+ * A dummy {@link ValueForNullProvider} that are not able to provide any values
+ */
+class EmptyValueForNullProvider implements ValueForNullProvider {
+
+ public List<String> createSql(DbEntity entity, DbAttribute column) {
+ return Collections.emptyList();
+ }
+
+ public boolean hasValueFor(DbEntity entity, DbAttribute column) {
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EntityMergeSupport.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EntityMergeSupport.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EntityMergeSupport.java
new file mode 100644
index 0000000..8aea02a
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EntityMergeSupport.java
@@ -0,0 +1,522 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.dba.TypesMapping;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.Entity;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+import org.apache.cayenne.map.naming.DefaultUniqueNameGenerator;
+import org.apache.cayenne.map.naming.LegacyNameGenerator;
+import org.apache.cayenne.map.naming.NameCheckers;
+import org.apache.cayenne.map.naming.ObjectNameGenerator;
+import org.apache.cayenne.util.DeleteRuleUpdater;
+import org.apache.cayenne.util.EntityMergeListener;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Implements methods for entity merging.
+ */
+public class EntityMergeSupport {
+
+ private static final Log LOG = LogFactory.getLog(EntityMergeSupport.class);
+
+ private static final Map<String, String> CLASS_TO_PRIMITIVE;
+
+ static {
+ CLASS_TO_PRIMITIVE = new HashMap<>();
+ CLASS_TO_PRIMITIVE.put(Byte.class.getName(), "byte");
+ CLASS_TO_PRIMITIVE.put(Long.class.getName(), "long");
+ CLASS_TO_PRIMITIVE.put(Double.class.getName(), "double");
+ CLASS_TO_PRIMITIVE.put(Boolean.class.getName(), "boolean");
+ CLASS_TO_PRIMITIVE.put(Float.class.getName(), "float");
+ CLASS_TO_PRIMITIVE.put(Short.class.getName(), "short");
+ CLASS_TO_PRIMITIVE.put(Integer.class.getName(), "int");
+ }
+
+ private final DataMap map;
+ /**
+ * Strategy for choosing names for entities, attributes and relationships
+ */
+ private final ObjectNameGenerator nameGenerator;
+ /**
+ * Listeners of merge process.
+ */
+ private final List<EntityMergeListener> listeners = new ArrayList<EntityMergeListener>();
+ protected boolean removeMeaningfulFKs;
+ protected boolean removeMeaningfulPKs;
+ protected boolean usePrimitives;
+
+ public EntityMergeSupport(DataMap map) {
+ this(map, new LegacyNameGenerator(), true);
+ }
+
+ /**
+ * @since 3.0
+ */
+ public EntityMergeSupport(DataMap map, ObjectNameGenerator nameGenerator, boolean removeMeaningfulPKs) {
+ this.map = map;
+ this.nameGenerator = nameGenerator;
+ this.removeMeaningfulFKs = true;
+ this.removeMeaningfulPKs = removeMeaningfulPKs;
+
+ /**
+ * Adding a listener, so that all created ObjRelationships would have
+ * default delete rule
+ */
+ addEntityMergeListener(DeleteRuleUpdater.getEntityMergeListener());
+ }
+
+ /**
+ * Updates each one of the collection of ObjEntities, adding attributes and
+ * relationships based on the current state of its DbEntity.
+ *
+ * @return true if any ObjEntity has changed as a result of synchronization.
+ * @since 1.2 changed signature to use Collection instead of List.
+ */
+ public boolean synchronizeWithDbEntities(Iterable<ObjEntity> objEntities) {
+ boolean changed = false;
+ for (ObjEntity nextEntity : objEntities) {
+ if (synchronizeWithDbEntity(nextEntity)) {
+ changed = true;
+ }
+ }
+
+ return changed;
+ }
+
+ /**
+ * @since 4.0
+ */
+ protected boolean removePK(DbEntity dbEntity) {
+ return removeMeaningfulPKs;
+ }
+
+ /**
+ * @since 4.0
+ */
+ protected boolean removeFK(DbEntity dbEntity) {
+ return removeMeaningfulFKs;
+ }
+
+ /**
+ * Updates ObjEntity attributes and relationships based on the current state
+ * of its DbEntity.
+ *
+ * @return true if the ObjEntity has changed as a result of synchronization.
+ */
+ public boolean synchronizeWithDbEntity(ObjEntity entity) {
+
+ if (entity == null) {
+ return false;
+ }
+
+ DbEntity dbEntity = entity.getDbEntity();
+ if (dbEntity == null) {
+ return false;
+ }
+
+ boolean changed = false;
+
+ // synchronization on DataMap is some (weak) protection
+ // against simultaneous modification of the map (like double-clicking on sync button)
+ synchronized (map) {
+
+ if (removeFK(dbEntity)) {
+ changed = getRidOfAttributesThatAreNowSrcAttributesForRelationships(entity);
+ }
+
+ changed |= addMissingAttributes(entity);
+ changed |= addMissingRelationships(entity);
+ }
+
+ return changed;
+ }
+
+ /**
+ * @since 4.0
+ */
+ public boolean synchronizeOnDbAttributeAdded(ObjEntity entity, DbAttribute dbAttribute) {
+
+ Collection<DbRelationship> incomingRels = getIncomingRelationships(dbAttribute.getEntity());
+ if (isMissingFromObjEntity(entity, dbAttribute, incomingRels)) {
+ addMissingAttribute(entity, dbAttribute);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @since 4.0
+ */
+ public boolean synchronizeOnDbRelationshipAdded(ObjEntity entity, DbRelationship dbRelationship) {
+
+ if (isMissingFromObjEntity(entity, dbRelationship)) {
+ addMissingRelationship(entity, dbRelationship);
+ }
+
+ return true;
+ }
+
+ private boolean addMissingRelationships(ObjEntity entity) {
+ List<DbRelationship> relationshipsToAdd = getRelationshipsToAdd(entity);
+ if (relationshipsToAdd.isEmpty()) {
+ return false;
+ }
+
+ for (DbRelationship dr : relationshipsToAdd) {
+ addMissingRelationship(entity, dr);
+ }
+
+ return true;
+ }
+
+ private boolean createObjRelationship(ObjEntity entity, DbRelationship dr, String targetEntityName) {
+ String relationshipName = nameGenerator.createObjRelationshipName(dr);
+ relationshipName = DefaultUniqueNameGenerator.generate(NameCheckers.objRelationship, entity, relationshipName);
+
+ ObjRelationship or = new ObjRelationship(relationshipName);
+ or.addDbRelationship(dr);
+ Map<String, ObjEntity> objEntities = entity.getDataMap().getSubclassesForObjEntity(entity);
+
+ boolean hasFlattingAttributes = false;
+ boolean needGeneratedEntity = true;
+
+ if (objEntities.containsKey(targetEntityName)) {
+ needGeneratedEntity = false;
+ }
+
+ for (ObjEntity subObjEntity : objEntities.values()) {
+ for (ObjAttribute objAttribute : subObjEntity.getAttributes()) {
+ String path = objAttribute.getDbAttributePath();
+ if (path != null) {
+ if (path.startsWith(or.getDbRelationshipPath())) {
+ hasFlattingAttributes = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!hasFlattingAttributes) {
+ if (needGeneratedEntity) {
+ or.setTargetEntityName(targetEntityName);
+ or.setSourceEntity(entity);
+ }
+
+ entity.addRelationship(or);
+ fireRelationshipAdded(or);
+ }
+
+ return needGeneratedEntity;
+ }
+
+ private boolean addMissingAttributes(ObjEntity entity) {
+ boolean changed = false;
+
+ for (DbAttribute da : getAttributesToAdd(entity)) {
+ addMissingAttribute(entity, da);
+ changed = true;
+ }
+ return changed;
+ }
+
+ private void addMissingRelationship(ObjEntity entity, DbRelationship dbRelationship) {
+ DbEntity targetEntity = dbRelationship.getTargetEntity();
+
+ Collection<ObjEntity> mappedObjEntities = map.getMappedEntities(targetEntity);
+ if (!mappedObjEntities.isEmpty()) {
+ for (Entity mappedTarget : mappedObjEntities) {
+ createObjRelationship(entity, dbRelationship, mappedTarget.getName());
+ }
+ } else {
+
+ if (targetEntity == null) {
+ targetEntity = new DbEntity(dbRelationship.getTargetEntityName());
+ }
+
+ if (dbRelationship.getTargetEntityName() != null) {
+ boolean needGeneratedEntity = createObjRelationship(entity, dbRelationship,
+ nameGenerator.createObjEntityName(targetEntity));
+ if (needGeneratedEntity) {
+ LOG.warn("Can't find ObjEntity for " + dbRelationship.getTargetEntityName());
+ LOG.warn("Db Relationship (" + dbRelationship + ") will have GUESSED Obj Relationship reflection. ");
+ }
+ }
+ }
+ }
+
+ private void addMissingAttribute(ObjEntity entity, DbAttribute da) {
+ String attrName = DefaultUniqueNameGenerator.generate(NameCheckers.objAttribute, entity,
+ nameGenerator.createObjAttributeName(da));
+
+ String type = TypesMapping.getJavaBySqlType(da.getType());
+ if (usePrimitives) {
+ String primitive = CLASS_TO_PRIMITIVE.get(type);
+ if (primitive != null) {
+ type = primitive;
+ }
+ }
+
+ ObjAttribute oa = new ObjAttribute(attrName, type, entity);
+ oa.setDbAttributePath(da.getName());
+ entity.addAttribute(oa);
+ fireAttributeAdded(oa);
+ }
+
+ private boolean getRidOfAttributesThatAreNowSrcAttributesForRelationships(ObjEntity entity) {
+ boolean changed = false;
+ for (DbAttribute da : getMeaningfulFKs(entity)) {
+ ObjAttribute oa = entity.getAttributeForDbAttribute(da);
+ while (oa != null) {
+ String attrName = oa.getName();
+ entity.removeAttribute(attrName);
+ changed = true;
+ oa = entity.getAttributeForDbAttribute(da);
+ }
+ }
+ return changed;
+ }
+
+ /**
+ * Returns a list of DbAttributes that are mapped to foreign keys.
+ *
+ * @since 1.2
+ */
+ public Collection<DbAttribute> getMeaningfulFKs(ObjEntity objEntity) {
+ List<DbAttribute> fks = new ArrayList<DbAttribute>(2);
+
+ for (ObjAttribute property : objEntity.getAttributes()) {
+ DbAttribute column = property.getDbAttribute();
+
+ // check if adding it makes sense at all
+ if (column != null && column.isForeignKey()) {
+ fks.add(column);
+ }
+ }
+
+ return fks;
+ }
+
+ /**
+ * Returns a list of attributes that exist in the DbEntity, but are missing
+ * from the ObjEntity.
+ */
+ protected List<DbAttribute> getAttributesToAdd(ObjEntity objEntity) {
+ DbEntity dbEntity = objEntity.getDbEntity();
+
+ List<DbAttribute> missing = new ArrayList<DbAttribute>();
+ Collection<DbRelationship> incomingRels = getIncomingRelationships(dbEntity);
+
+ for (DbAttribute dba : dbEntity.getAttributes()) {
+
+ if (isMissingFromObjEntity(objEntity, dba, incomingRels)) {
+ missing.add(dba);
+ }
+ }
+
+ return missing;
+ }
+
+ protected boolean isMissingFromObjEntity(ObjEntity entity, DbAttribute dbAttribute, Collection<DbRelationship> incomingRels) {
+
+ if (dbAttribute.getName() == null || entity.getAttributeForDbAttribute(dbAttribute) != null) {
+ return false;
+ }
+
+ boolean removeMeaningfulPKs = removePK(dbAttribute.getEntity());
+ if (removeMeaningfulPKs && dbAttribute.isPrimaryKey()) {
+ return false;
+ }
+
+ // check FK's
+ boolean isFK = false;
+ Iterator<DbRelationship> rit = dbAttribute.getEntity().getRelationships().iterator();
+ while (!isFK && rit.hasNext()) {
+ DbRelationship rel = rit.next();
+ for (DbJoin join : rel.getJoins()) {
+ if (join.getSource() == dbAttribute) {
+ isFK = true;
+ break;
+ }
+ }
+ }
+
+ if (!removeMeaningfulPKs) {
+ if (!dbAttribute.isPrimaryKey() && isFK) {
+ return false;
+ }
+ } else {
+ if (isFK) {
+ return false;
+ }
+ }
+
+ // check incoming relationships
+ rit = incomingRels.iterator();
+ while (!isFK && rit.hasNext()) {
+ DbRelationship rel = rit.next();
+ for (DbJoin join : rel.getJoins()) {
+ if (join.getTarget() == dbAttribute) {
+ isFK = true;
+ break;
+ }
+ }
+ }
+
+ if (!removeMeaningfulPKs) {
+ if (!dbAttribute.isPrimaryKey() && isFK) {
+ return false;
+ }
+ } else {
+ if (isFK) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ protected boolean isMissingFromObjEntity(ObjEntity entity, DbRelationship dbRelationship) {
+ return dbRelationship.getName() != null && entity.getRelationshipForDbRelationship(dbRelationship) == null;
+ }
+
+ private Collection<DbRelationship> getIncomingRelationships(DbEntity entity) {
+ Collection<DbRelationship> incoming = new ArrayList<DbRelationship>();
+
+ for (DbEntity nextEntity : entity.getDataMap().getDbEntities()) {
+ for (DbRelationship relationship : nextEntity.getRelationships()) {
+
+ // TODO: PERFORMANCE 'getTargetEntity' is generally slow, called
+ // in this iterator it is showing (e.g. in YourKit profiles)..
+ // perhaps use cheaper 'getTargetEntityName()' or even better -
+ // pre-cache all relationships by target entity to avoid O(n)
+ // search ?
+ // (need to profile to prove the difference)
+ if (entity == relationship.getTargetEntity()) {
+ incoming.add(relationship);
+ }
+ }
+ }
+
+ return incoming;
+ }
+
+ protected List<DbRelationship> getRelationshipsToAdd(ObjEntity objEntity) {
+ List<DbRelationship> missing = new ArrayList<DbRelationship>();
+ for (DbRelationship dbRel : objEntity.getDbEntity().getRelationships()) {
+ if (isMissingFromObjEntity(objEntity, dbRel)) {
+ missing.add(dbRel);
+ }
+ }
+
+ return missing;
+ }
+
+ /**
+ * @since 1.2
+ */
+ public boolean isRemoveMeaningfulFKs() {
+ return removeMeaningfulFKs;
+ }
+
+ /**
+ * @since 1.2
+ */
+ public void setRemoveMeaningfulFKs(boolean removeMeaningfulFKs) {
+ this.removeMeaningfulFKs = removeMeaningfulFKs;
+ }
+
+ /**
+ * Registers new EntityMergeListener
+ */
+ public void addEntityMergeListener(EntityMergeListener listener) {
+ listeners.add(listener);
+ }
+
+ /**
+ * Unregisters an EntityMergeListener
+ */
+ public void removeEntityMergeListener(EntityMergeListener listener) {
+ listeners.remove(listener);
+ }
+
+ /**
+ * Returns registered listeners
+ */
+ public EntityMergeListener[] getEntityMergeListeners() {
+ return listeners.toArray(new EntityMergeListener[listeners.size()]);
+ }
+
+ /**
+ * Notifies all listeners that an ObjAttribute was added
+ */
+ protected void fireAttributeAdded(ObjAttribute attr) {
+ for (EntityMergeListener listener : listeners) {
+ listener.objAttributeAdded(attr);
+ }
+ }
+
+ /**
+ * Notifies all listeners that an ObjRelationship was added
+ */
+ protected void fireRelationshipAdded(ObjRelationship rel) {
+ for (EntityMergeListener listener : listeners) {
+ listener.objRelationshipAdded(rel);
+ }
+ }
+
+ /**
+ * @return naming strategy for reverse engineering
+ */
+ public ObjectNameGenerator getNameGenerator() {
+ return nameGenerator;
+ }
+
+ /**
+ * @since 4.0
+ */
+ public boolean isUsePrimitives() {
+ return usePrimitives;
+ }
+
+ /**
+ * @param usePrimitives
+ * @since 4.0
+ */
+ public void setUsePrimitives(boolean usePrimitives) {
+ this.usePrimitives = usePrimitives;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergeDirection.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergeDirection.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergeDirection.java
new file mode 100644
index 0000000..4ac25e4
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergeDirection.java
@@ -0,0 +1,70 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+/**
+ * Represent a merge direction that can be either from the model to the db or from the db to the model.
+ */
+public enum MergeDirection {
+
+ /**
+ * TO_DB Token means that changes was made in object model and should be reflected at DB
+ */
+ TO_DB("To DB"),
+
+ /**
+ * TO_MODEL Token represent database changes that should be allayed to object model
+ */
+ TO_MODEL("To Model");
+
+ private String name;
+
+ MergeDirection(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public boolean isToDb() {
+ return (this == TO_DB);
+ }
+
+ public boolean isToModel() {
+ return (this == TO_MODEL);
+ }
+
+ @Override
+ public String toString() {
+ return getName();
+ }
+
+ public MergeDirection reverseDirection() {
+ switch (this) {
+ case TO_DB:
+ return TO_MODEL;
+ case TO_MODEL:
+ return TO_DB;
+ default:
+ throw new IllegalStateException("Invalid direction: " + this);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerContext.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerContext.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerContext.java
new file mode 100644
index 0000000..772de97
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerContext.java
@@ -0,0 +1,118 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.access.DataNode;
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.validation.ValidationResult;
+
+import javax.sql.DataSource;
+import java.util.Objects;
+
+/**
+ * An object passed as an argument to {@link MergerToken#execute(MergerContext)}s that a
+ * {@link MergerToken} can do its work.
+ */
+public class MergerContext {
+
+ private DataMap dataMap;
+ private DataNode dataNode;
+ private ValidationResult validationResult;
+ private ModelMergeDelegate delegate;
+
+ protected MergerContext() {
+ }
+
+ public static Builder builder(DataMap dataMap) {
+ return new Builder().dataMap(dataMap);
+ }
+
+ /**
+ * @deprecated since 4.0 use {@link #getDataNode()} and its {@link DataNode#getAdapter()} method.
+ */
+ @Deprecated
+ public DbAdapter getAdapter() {
+ return getDataNode().getAdapter();
+ }
+
+ /**
+ * Returns the DataMap that is the target of a the merge operation.
+ *
+ * @return the DataMap that is the target of a the merge operation.
+ */
+ public DataMap getDataMap() {
+ return dataMap;
+ }
+
+ public DataNode getDataNode() {
+ return dataNode;
+ }
+
+ public ValidationResult getValidationResult() {
+ return validationResult;
+ }
+
+ /**
+ * Returns a callback object that is invoked as the merge proceeds through tokens, modifying the DataMap.
+ *
+ * @return a callback object that is invoked as the merge proceeds through tokens, modifying the DataMap.
+ */
+ public ModelMergeDelegate getModelMergeDelegate() {
+ return delegate;
+ }
+
+ public static class Builder {
+
+ private MergerContext context;
+
+ private Builder() {
+ this.context = new MergerContext();
+ this.context.validationResult = new ValidationResult();
+ this.context.delegate = new DefaultModelMergeDelegate();
+ this.context.dataNode = new DataNode();
+ }
+
+ public MergerContext build() {
+ return context;
+ }
+
+ public Builder delegate(ModelMergeDelegate delegate) {
+ context.delegate = Objects.requireNonNull(delegate);
+ return this;
+ }
+
+ public Builder dataNode(DataNode dataNode) {
+ this.context.dataNode = Objects.requireNonNull(dataNode);
+ return this;
+ }
+
+ public Builder syntheticDataNode(DataSource dataSource, DbAdapter adapter) {
+ DataNode dataNode = new DataNode();
+ dataNode.setDataSource(dataSource);
+ dataNode.setAdapter(adapter);
+ return dataNode(dataNode);
+ }
+
+ public Builder dataMap(DataMap dataMap) {
+ context.dataMap = Objects.requireNonNull(dataMap);
+ return this;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerToken.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerToken.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerToken.java
new file mode 100644
index 0000000..5359b62
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerToken.java
@@ -0,0 +1,53 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+
+/**
+ * Represents a minimal atomic synchronization operation between database and Cayenne model.
+ */
+public interface MergerToken {
+
+ String getTokenName();
+
+ String getTokenValue();
+
+ /**
+ * The direction of this token. One of {@link MergeDirection#TO_DB} or
+ * {@link MergeDirection#TO_MODEL}
+ */
+ MergeDirection getDirection();
+
+ /**
+ * Create a complimentary token with the reverse direction. AddColumn in one direction becomes
+ * DropColumn in the other direction.
+ * <p>
+ * Not all tokens are reversible.
+ */
+ MergerToken createReverse(MergerTokenFactory factory);
+
+ /**
+ * Executes synchronization operation.
+ *
+ * @param mergerContext operation context.
+ */
+ void execute(MergerContext mergerContext);
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ModelMergeDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ModelMergeDelegate.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ModelMergeDelegate.java
new file mode 100644
index 0000000..13f6ea5
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ModelMergeDelegate.java
@@ -0,0 +1,62 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+
+/**
+ * A interface used to tell about modifications performed on the model by
+ * {@link MergerToken} with {@link MergeDirection#TO_MODEL}
+ */
+public interface ModelMergeDelegate {
+
+ public void dbEntityAdded(DbEntity ent);
+
+ public void dbEntityRemoved(DbEntity ent);
+
+ public void objEntityAdded(ObjEntity ent);
+
+ public void objEntityRemoved(ObjEntity ent);
+
+ public void dbAttributeAdded(DbAttribute att);
+
+ public void dbAttributeRemoved(DbAttribute att);
+
+ public void dbAttributeModified(DbAttribute att);
+
+ public void objAttributeAdded(ObjAttribute att);
+
+ public void objAttributeRemoved(ObjAttribute att);
+
+ public void objAttributeModified(ObjAttribute att);
+
+ public void dbRelationshipAdded(DbRelationship rel);
+
+ public void dbRelationshipRemoved(DbRelationship rel);
+
+ public void objRelationshipAdded(ObjRelationship rel);
+
+ public void objRelationshipRemoved(ObjRelationship rel);
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ProxyModelMergeDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ProxyModelMergeDelegate.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ProxyModelMergeDelegate.java
new file mode 100644
index 0000000..ba12824
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ProxyModelMergeDelegate.java
@@ -0,0 +1,108 @@
+/*
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+
+/**
+ * @since 4.0
+ */
+public class ProxyModelMergeDelegate implements ModelMergeDelegate {
+
+ private final ModelMergeDelegate delegate;
+
+ public ProxyModelMergeDelegate(ModelMergeDelegate delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public void dbEntityAdded(DbEntity ent) {
+ delegate.dbEntityAdded(ent);
+ }
+
+ @Override
+ public void dbEntityRemoved(DbEntity ent) {
+ delegate.dbEntityRemoved(ent);
+ }
+
+ @Override
+ public void objEntityAdded(ObjEntity ent) {
+ delegate.objEntityAdded(ent);
+ }
+
+ @Override
+ public void objEntityRemoved(ObjEntity ent) {
+ delegate.objEntityRemoved(ent);
+ }
+
+ @Override
+ public void dbAttributeAdded(DbAttribute att) {
+ delegate.dbAttributeAdded(att);
+ }
+
+ @Override
+ public void dbAttributeRemoved(DbAttribute att) {
+ delegate.dbAttributeRemoved(att);
+ }
+
+ @Override
+ public void dbAttributeModified(DbAttribute att) {
+ delegate.dbAttributeModified(att);
+ }
+
+ @Override
+ public void objAttributeAdded(ObjAttribute att) {
+ delegate.objAttributeAdded(att);
+ }
+
+ @Override
+ public void objAttributeRemoved(ObjAttribute att) {
+ delegate.objAttributeRemoved(att);
+ }
+
+ @Override
+ public void objAttributeModified(ObjAttribute att) {
+ delegate.objAttributeModified(att);
+ }
+
+ @Override
+ public void dbRelationshipAdded(DbRelationship rel) {
+ delegate.dbRelationshipAdded(rel);
+ }
+
+ @Override
+ public void dbRelationshipRemoved(DbRelationship rel) {
+ delegate.dbRelationshipRemoved(rel);
+ }
+
+ @Override
+ public void objRelationshipAdded(ObjRelationship rel) {
+ delegate.objRelationshipAdded(rel);
+ }
+
+ @Override
+ public void objRelationshipRemoved(ObjRelationship rel) {
+ delegate.objRelationshipRemoved(rel);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToDb.java
new file mode 100644
index 0000000..c69fb6f
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToDb.java
@@ -0,0 +1,57 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+/**
+ * A {@link MergerToken} to add a "allow null" clause to a column.
+ *
+ */
+public class SetAllowNullToDb extends AbstractToDbToken.EntityAndColumn {
+
+ public SetAllowNullToDb(DbEntity entity, DbAttribute column) {
+ super("Set Allow Null", entity, column);
+ }
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuilder sqlBuffer = new StringBuilder();
+ QuotingStrategy context = adapter.getQuotingStrategy();
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" ALTER COLUMN ");
+ sqlBuffer.append(context.quotedName(getColumn()));
+ sqlBuffer.append(" DROP NOT NULL");
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return factory.createSetNotNullToModel(getEntity(), getColumn());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToModel.java
new file mode 100644
index 0000000..71a0937
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetAllowNullToModel.java
@@ -0,0 +1,43 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+/**
+ * A {@link MergerToken} to set the mandatory field of a {@link DbAttribute} to false
+ *
+ */
+public class SetAllowNullToModel extends AbstractToModelToken.EntityAndColumn {
+
+ public SetAllowNullToModel(DbEntity entity, DbAttribute column) {
+ super("Set Allow Null", entity, column);
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return factory.createSetNotNullToDb(getEntity(), getColumn());
+ }
+
+ public void execute(MergerContext mergerContext) {
+ getColumn().setMandatory(false);
+ mergerContext.getModelMergeDelegate().dbAttributeModified(getColumn());
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToDb.java
new file mode 100644
index 0000000..74a0034
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToDb.java
@@ -0,0 +1,119 @@
+/*
+ * 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.dbsync.merge;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.JdbcAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dba.TypesMapping;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+/**
+ * An {@link MergerToken} to use to set type, length and precision.
+ */
+public class SetColumnTypeToDb extends AbstractToDbToken.Entity {
+
+ private DbAttribute columnOriginal;
+ private DbAttribute columnNew;
+
+ public SetColumnTypeToDb(DbEntity entity, DbAttribute columnOriginal, DbAttribute columnNew) {
+ super("Set Column Type", entity);
+ this.columnOriginal = columnOriginal;
+ this.columnNew = columnNew;
+ }
+
+ /**
+ * append the part of the token before the actual column data type
+ * @param context
+ */
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" ALTER ");
+ sqlBuffer.append(context.quotedName(columnNew));
+ sqlBuffer.append(" TYPE ");
+ }
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuffer sqlBuffer = new StringBuffer();
+ appendPrefix(sqlBuffer, adapter.getQuotingStrategy());
+
+ sqlBuffer.append(JdbcAdapter.getType(adapter, columnNew));
+ sqlBuffer.append(JdbcAdapter.sizeAndPrecision(adapter, columnNew));
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ @Override
+ public String getTokenValue() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(getEntity().getName());
+ sb.append(".");
+ sb.append(columnNew.getName());
+
+ if (columnOriginal.getType() != columnNew.getType()) {
+ sb.append(" type: ");
+ sb.append(TypesMapping.getSqlNameByType(columnOriginal.getType()));
+ sb.append(" -> ");
+ sb.append(TypesMapping.getSqlNameByType(columnNew.getType()));
+ }
+
+ if (columnOriginal.getMaxLength() != columnNew.getMaxLength()) {
+ sb.append(" maxLength: ");
+ sb.append(columnOriginal.getMaxLength());
+ sb.append(" -> ");
+ sb.append(columnNew.getMaxLength());
+ }
+
+ if (columnOriginal.getAttributePrecision() != columnNew.getAttributePrecision()) {
+ sb.append(" precision: ");
+ sb.append(columnOriginal.getAttributePrecision());
+ sb.append(" -> ");
+ sb.append(columnNew.getAttributePrecision());
+ }
+
+ if (columnOriginal.getScale() != columnNew.getScale()) {
+ sb.append(" scale: ");
+ sb.append(columnOriginal.getScale());
+ sb.append(" -> ");
+ sb.append(columnNew.getScale());
+ }
+
+ return sb.toString();
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return factory.createSetColumnTypeToModel(getEntity(), columnNew, columnOriginal);
+ }
+
+ public DbAttribute getColumnOriginal() {
+ return columnOriginal;
+ }
+
+ public DbAttribute getColumnNew() {
+ return columnNew;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToModel.java
new file mode 100644
index 0000000..262c3a6
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetColumnTypeToModel.java
@@ -0,0 +1,102 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.dba.TypesMapping;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+/**
+ * A {@link MergerToken} that modifies one original {@link DbAttribute} to match another
+ * new {@link DbAttribute}s type, maxLength and precision. The name and mandatory fields
+ * are not modified by this token.
+ *
+ */
+public class SetColumnTypeToModel extends AbstractToModelToken.Entity {
+
+ private DbAttribute columnOriginal;
+ private DbAttribute columnNew;
+
+ public SetColumnTypeToModel(DbEntity entity, DbAttribute columnOriginal,
+ DbAttribute columnNew) {
+ super("Set Column Type", entity);
+ this.columnOriginal = columnOriginal;
+ this.columnNew = columnNew;
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return factory.createSetColumnTypeToDb(getEntity(), columnNew, columnOriginal);
+ }
+
+ public void execute(MergerContext mergerContext) {
+ columnOriginal.setType(columnNew.getType());
+ columnOriginal.setMaxLength(columnNew.getMaxLength());
+ columnOriginal.setAttributePrecision(columnNew.getAttributePrecision());
+ columnOriginal.setScale(columnNew.getScale());
+ mergerContext.getModelMergeDelegate().dbAttributeModified(columnOriginal);
+ }
+
+ @Override
+ public String getTokenValue() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(getEntity().getName());
+ sb.append(".");
+ sb.append(columnNew.getName());
+
+ if (columnOriginal.getType() != columnNew.getType()) {
+ sb.append(" type: ");
+ sb.append(TypesMapping.getSqlNameByType(columnOriginal.getType()));
+ sb.append(" -> ");
+ sb.append(TypesMapping.getSqlNameByType(columnNew.getType()));
+ }
+
+ if (columnOriginal.getMaxLength() != columnNew.getMaxLength()) {
+ sb.append(" maxLength: ");
+ sb.append(columnOriginal.getMaxLength());
+ sb.append(" -> ");
+ sb.append(columnNew.getMaxLength());
+ }
+
+ if (columnOriginal.getAttributePrecision() != columnNew.getAttributePrecision()) {
+ sb.append(" precision: ");
+ sb.append(columnOriginal.getAttributePrecision());
+ sb.append(" -> ");
+ sb.append(columnNew.getAttributePrecision());
+ }
+
+ if (columnOriginal.getScale() != columnNew.getScale()) {
+ sb.append(" scale: ");
+ sb.append(columnOriginal.getScale());
+ sb.append(" -> ");
+ sb.append(columnNew.getScale());
+ }
+
+ return sb.toString();
+ }
+
+ public DbAttribute getColumnOriginal() {
+ return columnOriginal;
+ }
+
+ public DbAttribute getColumnNew() {
+ return columnNew;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToDb.java
new file mode 100644
index 0000000..169ea34
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToDb.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.dbsync.merge;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+/**
+ * A {@link MergerToken} to add a "not null" clause to a column.
+ */
+public class SetNotNullToDb extends AbstractToDbToken.EntityAndColumn {
+
+ public SetNotNullToDb(DbEntity entity, DbAttribute column) {
+ super("Set Not Null", entity, column);
+ }
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ QuotingStrategy context = adapter.getQuotingStrategy();
+
+ return Collections.singletonList("ALTER TABLE " + context.quotedFullyQualifiedName(getEntity())
+ + " ALTER COLUMN " + context.quotedName(getColumn()) + " SET NOT NULL");
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return factory.createSetAllowNullToModel(getEntity(), getColumn());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToModel.java
new file mode 100644
index 0000000..9ae95b5
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetNotNullToModel.java
@@ -0,0 +1,43 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+/**
+ * A {@link MergerToken} to set the mandatory field of a {@link DbAttribute} to true
+ *
+ */
+public class SetNotNullToModel extends AbstractToModelToken.EntityAndColumn {
+
+ public SetNotNullToModel(DbEntity entity, DbAttribute column) {
+ super("Set Not Null", entity, column);
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return factory.createSetAllowNullToDb(getEntity(), getColumn());
+ }
+
+ public void execute(MergerContext mergerContext) {
+ getColumn().setMandatory(true);
+ mergerContext.getModelMergeDelegate().dbAttributeModified(getColumn());
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToDb.java
new file mode 100644
index 0000000..8161b87
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToDb.java
@@ -0,0 +1,86 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+public class SetPrimaryKeyToDb extends AbstractToDbToken.Entity {
+
+ private Collection<DbAttribute> primaryKeyOriginal;
+ private Collection<DbAttribute> primaryKeyNew;
+ private String detectedPrimaryKeyName;
+
+ public SetPrimaryKeyToDb(DbEntity entity, Collection<DbAttribute> primaryKeyOriginal,
+ Collection<DbAttribute> primaryKeyNew, String detectedPrimaryKeyName) {
+ super("Set Primary Key", entity);
+
+ this.primaryKeyOriginal = primaryKeyOriginal;
+ this.primaryKeyNew = primaryKeyNew;
+ this.detectedPrimaryKeyName = detectedPrimaryKeyName;
+ }
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ List<String> sqls = new ArrayList<String>();
+ if (!primaryKeyOriginal.isEmpty()) {
+ appendDropOriginalPrimaryKeySQL(adapter, sqls);
+ }
+ appendAddNewPrimaryKeySQL(adapter, sqls);
+ return sqls;
+ }
+
+ protected void appendDropOriginalPrimaryKeySQL(DbAdapter adapter, List<String> sqls) {
+ if (detectedPrimaryKeyName == null) {
+ return;
+ }
+ sqls.add("ALTER TABLE " + adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity())
+ + " DROP CONSTRAINT " + detectedPrimaryKeyName);
+ }
+
+ protected void appendAddNewPrimaryKeySQL(DbAdapter adapter, List<String> sqls) {
+ QuotingStrategy quotingStrategy = adapter.getQuotingStrategy();
+
+ StringBuilder sql = new StringBuilder();
+ sql.append("ALTER TABLE ");
+ sql.append(quotingStrategy.quotedFullyQualifiedName(getEntity()));
+ sql.append(" ADD PRIMARY KEY (");
+ for (Iterator<DbAttribute> it = primaryKeyNew.iterator(); it.hasNext();) {
+ sql.append(quotingStrategy.quotedName(it.next()));
+ if (it.hasNext()) {
+ sql.append(", ");
+ }
+ }
+ sql.append(")");
+ sqls.add(sql.toString());
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return factory.createSetPrimaryKeyToModel(getEntity(), primaryKeyNew, primaryKeyOriginal,
+ detectedPrimaryKeyName);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToModel.java
new file mode 100644
index 0000000..6785a2f
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetPrimaryKeyToModel.java
@@ -0,0 +1,78 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.event.AttributeEvent;
+
+public class SetPrimaryKeyToModel extends AbstractToModelToken.Entity {
+
+ private Collection<DbAttribute> primaryKeyOriginal;
+ private Collection<DbAttribute> primaryKeyNew;
+ private String detectedPrimaryKeyName;
+ private Set<String> primaryKeyNewAttributeNames = new HashSet<String>();
+
+ public SetPrimaryKeyToModel(DbEntity entity,
+ Collection<DbAttribute> primaryKeyOriginal,
+ Collection<DbAttribute> primaryKeyNew, String detectedPrimaryKeyName) {
+ super("Set Primary Key", entity);
+
+ this.primaryKeyOriginal = primaryKeyOriginal;
+ this.primaryKeyNew = primaryKeyNew;
+ this.detectedPrimaryKeyName = detectedPrimaryKeyName;
+
+ for (DbAttribute attr : primaryKeyNew) {
+ primaryKeyNewAttributeNames.add(attr.getName().toUpperCase());
+ }
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return factory.createSetPrimaryKeyToDb(
+ getEntity(),
+ primaryKeyNew,
+ primaryKeyOriginal,
+ detectedPrimaryKeyName);
+ }
+
+ public void execute(MergerContext mergerContext) {
+ DbEntity e = getEntity();
+
+ for (DbAttribute attr : e.getAttributes()) {
+
+ boolean wasPrimaryKey = attr.isPrimaryKey();
+ boolean willBePrimaryKey = primaryKeyNewAttributeNames.contains(attr
+ .getName()
+ .toUpperCase());
+
+ if (wasPrimaryKey != willBePrimaryKey) {
+ attr.setPrimaryKey(willBePrimaryKey);
+ e.dbAttributeChanged(new AttributeEvent(this, attr, e));
+ mergerContext.getModelMergeDelegate().dbAttributeModified(attr);
+ }
+
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetValueForNullToDb.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetValueForNullToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetValueForNullToDb.java
new file mode 100644
index 0000000..1ffdd49
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/SetValueForNullToDb.java
@@ -0,0 +1,47 @@
+/*****************************************************************
+ * 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.dbsync.merge;
+
+import java.util.List;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+
+public class SetValueForNullToDb extends AbstractToDbToken.EntityAndColumn {
+
+ private ValueForNullProvider valueForNullProvider;
+
+ public SetValueForNullToDb(DbEntity entity, DbAttribute column, ValueForNullProvider valueForNullProvider) {
+ super("Set value for null", entity, column);
+ this.valueForNullProvider = valueForNullProvider;
+ }
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ return valueForNullProvider.createSql(getEntity(), getColumn());
+ }
+
+ public MergerToken createReverse(MergerTokenFactory factory) {
+ return new DummyReverseToken(this);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ValueForNullProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ValueForNullProvider.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ValueForNullProvider.java
new file mode 100644
index 0000000..a07efff
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ValueForNullProvider.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.dbsync.merge;
+
+import java.util.List;
+
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+/**
+ * Class that will be used to set value for null on not
+ * null columns
+ */
+public interface ValueForNullProvider {
+
+ /**
+ * @return true if there exist a value that should be inserted for null values
+ */
+ public boolean hasValueFor(DbEntity entity, DbAttribute column);
+
+ /**
+ * @return a {@link List} of sql to set value for null
+ */
+ public List<String> createSql(DbEntity entity, DbAttribute column);
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DB2MergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DB2MergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DB2MergerTokenFactory.java
new file mode 100644
index 0000000..586a5cd
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DB2MergerTokenFactory.java
@@ -0,0 +1,47 @@
+/*****************************************************************
+ * 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.dbsync.merge.factory;
+
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+public class DB2MergerTokenFactory extends DefaultMergerTokenFactory {
+
+ @Override
+ public MergerToken createSetColumnTypeToDb(
+ final DbEntity entity,
+ DbAttribute columnOriginal,
+ final DbAttribute columnNew) {
+
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" ALTER COLUMN ");
+ sqlBuffer.append(context.quotedName(columnNew));
+ sqlBuffer.append(" SET DATA TYPE ");
+ }
+ };
+ }
+}