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/10/03 12:29:43 UTC
[1/2] cayenne git commit: CAY-2115 DbLoader - allow loading DataMap
without Obj layer
Repository: cayenne
Updated Branches:
refs/heads/master e8e2f733c -> ac04c11b0
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ac04c11b/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 0680e5c..ce2193e 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
@@ -1,21 +1,21 @@
-/*****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ****************************************************************/
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
package org.apache.cayenne.modeler.dialog.objentity;
@@ -66,16 +66,14 @@ public class EntitySyncController extends CayenneController {
namingStrategy = NameGeneratorPreferences.getInstance().createNamingStrategy(application);
} catch (Throwable e) {
namingStrategy = NameGeneratorPreferences.defaultNameGenerator();
-
- // TODO log exception
}
- EntityMergeSupport merger = new EntityMergeSupport(dbEntity.getDataMap(), namingStrategy, true);
+ EntityMergeSupport merger = new EntityMergeSupport(namingStrategy, true, true);
// see if we need to remove meaningful attributes...
for (ObjEntity entity : entities) {
if (!merger.getMeaningfulFKs(entity).isEmpty()) {
- return configureMerger(merger);
+ return confirmMeaningfulFKs(namingStrategy);
}
}
@@ -83,19 +81,20 @@ public class EntitySyncController extends CayenneController {
}
/**
- * Displays a nerger config dialog, returning a merger configured by the user. Returns
+ * Displays merger config dialog, returning a merger configured by the user. Returns
* null if the dialog was canceled.
*/
- protected EntityMergeSupport configureMerger(final EntityMergeSupport merger) {
+ protected EntityMergeSupport confirmMeaningfulFKs(ObjectNameGenerator namingStrategy) {
- final boolean[] cancel = new boolean[1];
+ final boolean[] cancel = {false};
+ final boolean[] removeFKs = {true};
view = new EntitySyncDialog();
view.getUpdateButton().addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
- merger.setRemoveMeaningfulFKs(view.getRemoveFKs().isSelected());
+ removeFKs[0] = view.getRemoveFKs().isSelected();
view.dispose();
}
});
@@ -114,7 +113,7 @@ public class EntitySyncController extends CayenneController {
makeCloseableOnEscape();
view.setVisible(true);
- return cancel[0] ? null : merger;
+ return cancel[0] ? null : new EntityMergeSupport(namingStrategy, true, removeFKs[0]);
}
@Override
@@ -124,7 +123,7 @@ public class EntitySyncController extends CayenneController {
protected Collection<ObjEntity> getObjEntities() {
return objEntity == null ? dbEntity.getDataMap().getMappedEntities(dbEntity)
- : Collections.singleton(objEntity);
+ : Collections.singleton(objEntity);
}
}
[2/2] cayenne git commit: CAY-2115 DbLoader - allow loading DataMap
without Obj layer
Posted by aa...@apache.org.
CAY-2115 DbLoader - allow loading DataMap without Obj layer
* refactoring EntityMergeSupport
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/ac04c11b
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/ac04c11b
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/ac04c11b
Branch: refs/heads/master
Commit: ac04c11b09f6f314765e5848c864390175548745
Parents: e8e2f73
Author: Andrus Adamchik <an...@objectstyle.com>
Authored: Mon Oct 3 14:04:40 2016 +0300
Committer: Andrus Adamchik <an...@objectstyle.com>
Committed: Mon Oct 3 15:25:50 2016 +0300
----------------------------------------------------------------------
.../apache/cayenne/dbsync/merge/DbMerger.java | 704 ++++++++++---------
.../dbsync/merge/EntityMergeSupport.java | 117 ++-
.../cayenne/dbsync/merge/MergerContext.java | 5 +-
.../cayenne/dbsync/reverse/db/DbLoader.java | 88 +--
.../dbsync/merge/EntityMergeSupportIT.java | 2 +-
.../cayenne/dbsync/reverse/db/DbLoaderIT.java | 47 +-
.../tools/dbimport/DbImportConfiguration.java | 21 +-
.../tools/dbimport/DefaultDbImportAction.java | 1 +
.../dbimport/DefaultDbImportActionTest.java | 251 +++----
.../modeler/action/CreateObjEntityAction.java | 35 +-
.../modeler/action/DbEntitySyncAction.java | 2 +-
.../cayenne/modeler/action/MigrateAction.java | 6 +-
.../modeler/dialog/db/DbLoaderHelper.java | 20 +-
.../modeler/dialog/db/ModelerDbLoader.java | 7 +-
.../dialog/objentity/EntitySyncController.java | 51 +-
15 files changed, 668 insertions(+), 689 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ac04c11b/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
index 41ff7c8..f89dd00 100644
--- 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
@@ -22,6 +22,7 @@ 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.naming.DefaultObjectNameGenerator;
import org.apache.cayenne.dbsync.reverse.db.DbLoader;
import org.apache.cayenne.dbsync.reverse.db.DbLoaderConfiguration;
import org.apache.cayenne.dbsync.reverse.db.LoggingDbLoaderDelegate;
@@ -52,354 +53,363 @@ 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;
- }
+ 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;
+ }
+
+ /**
+ * Return true if the two unordered {@link Collection}s of {@link DbJoin}s
+ * are equal. Entity and Attribute names are compared case insensitively.
+ * <p>
+ * 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;
+ }
+
+ /**
+ * 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;
+ }
+
+ protected EntityMergeSupport createEntityMergeSupport() {
+ return new EntityMergeSupport(new DefaultObjectNameGenerator(), true, true);
+ }
+
+ private DataMap loadDataMapFromDb(DataSource dataSource, DbAdapter adapter, DbLoaderConfiguration config) {
+
+
+ try (Connection conn = dataSource.getConnection();) {
+
+ return new DbLoader(conn,
+ adapter,
+ new LoggingDbLoaderDelegate(LOGGER),
+ createEntityMergeSupport()).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;
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ac04c11b/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
index 11f2ac4..bf54dcc 100644
--- 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
@@ -48,7 +48,7 @@ import java.util.Map;
*/
public class EntityMergeSupport {
- private static final Log LOG = LogFactory.getLog(EntityMergeSupport.class);
+ private static final Log LOGGER = LogFactory.getLog(EntityMergeSupport.class);
private static final Map<String, String> CLASS_TO_PRIMITIVE;
@@ -63,41 +63,36 @@ public class EntityMergeSupport {
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;
-
- /**
- * @since 3.0
- */
- public EntityMergeSupport(DataMap map, ObjectNameGenerator nameGenerator, boolean removeMeaningfulPKs) {
- this.map = map;
+ private final List<EntityMergeListener> listeners;
+ protected boolean removingMeaningfulFKs;
+ protected boolean removingMeaningfulPKs;
+ protected boolean usingPrimitives;
+
+ public EntityMergeSupport(ObjectNameGenerator nameGenerator, boolean removingMeaningfulPKs, boolean removingMeaningfulFKs) {
+ this.listeners = new ArrayList<>();
this.nameGenerator = nameGenerator;
- this.removeMeaningfulFKs = true;
- this.removeMeaningfulPKs = removeMeaningfulPKs;
+ this.removingMeaningfulFKs = removingMeaningfulFKs;
+ this.removingMeaningfulPKs = removingMeaningfulPKs;
- /**
- * Adding a listener, so that all created ObjRelationships would have
- * default delete rule
- */
+ // will ensure that all created ObjRelationships would have
+ // default delete rule
addEntityMergeListener(DeleteRuleUpdater.getEntityMergeListener());
}
+ public boolean isRemovingMeaningfulFKs() {
+ return removingMeaningfulFKs;
+ }
+
+ public boolean isRemovingMeaningfulPKs() {
+ return removingMeaningfulPKs;
+ }
+
/**
* 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;
@@ -114,14 +109,14 @@ public class EntityMergeSupport {
* @since 4.0
*/
protected boolean removePK(DbEntity dbEntity) {
- return removeMeaningfulPKs;
+ return removingMeaningfulPKs;
}
/**
* @since 4.0
*/
protected boolean removeFK(DbEntity dbEntity) {
- return removeMeaningfulFKs;
+ return removingMeaningfulFKs;
}
/**
@@ -143,18 +138,13 @@ public class EntityMergeSupport {
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);
+ if (removeFK(dbEntity)) {
+ changed = getRidOfAttributesThatAreNowSrcAttributesForRelationships(entity);
}
+ changed |= addMissingAttributes(entity);
+ changed |= addMissingRelationships(entity);
+
return changed;
}
@@ -249,15 +239,14 @@ public class EntityMergeSupport {
}
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 {
+ // getting DataMap from DbRelationship's source entity. This is the only object in our arguments that
+ // is guaranteed to be a part of the map....
+ DataMap dataMap = dbRelationship.getSourceEntity().getDataMap();
+ DbEntity targetEntity = dbRelationship.getTargetEntity();
+ Collection<ObjEntity> mappedObjEntities = dataMap.getMappedEntities(targetEntity);
+ if (mappedObjEntities.isEmpty()) {
if (targetEntity == null) {
targetEntity = new DbEntity(dbRelationship.getTargetEntityName());
}
@@ -266,10 +255,14 @@ public class EntityMergeSupport {
boolean needGeneratedEntity = createObjRelationship(entity, dbRelationship,
nameGenerator.objEntityName(targetEntity));
if (needGeneratedEntity) {
- LOG.warn("Can't find ObjEntity for " + dbRelationship.getTargetEntityName());
- LOG.warn("Db Relationship (" + dbRelationship + ") will have GUESSED Obj Relationship reflection. ");
+ LOGGER.warn("Can't find ObjEntity for " + dbRelationship.getTargetEntityName());
+ LOGGER.warn("Db Relationship (" + dbRelationship + ") will have GUESSED Obj Relationship reflection. ");
}
}
+ } else {
+ for (Entity mappedTarget : mappedObjEntities) {
+ createObjRelationship(entity, dbRelationship, mappedTarget.getName());
+ }
}
}
@@ -281,7 +274,7 @@ public class EntityMergeSupport {
oa.setEntity(entity);
String type = TypesMapping.getJavaBySqlType(da.getType());
- if (usePrimitives) {
+ if (usingPrimitives) {
String primitive = CLASS_TO_PRIMITIVE.get(type);
if (primitive != null) {
type = primitive;
@@ -313,7 +306,7 @@ public class EntityMergeSupport {
* @since 1.2
*/
public Collection<DbAttribute> getMeaningfulFKs(ObjEntity objEntity) {
- List<DbAttribute> fks = new ArrayList<DbAttribute>(2);
+ List<DbAttribute> fks = new ArrayList<>(2);
for (ObjAttribute property : objEntity.getAttributes()) {
DbAttribute column = property.getDbAttribute();
@@ -334,7 +327,7 @@ public class EntityMergeSupport {
protected List<DbAttribute> getAttributesToAdd(ObjEntity objEntity) {
DbEntity dbEntity = objEntity.getDbEntity();
- List<DbAttribute> missing = new ArrayList<DbAttribute>();
+ List<DbAttribute> missing = new ArrayList<>();
Collection<DbRelationship> incomingRels = getIncomingRelationships(dbEntity);
for (DbAttribute dba : dbEntity.getAttributes()) {
@@ -443,20 +436,6 @@ public class EntityMergeSupport {
}
/**
- * @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) {
@@ -496,7 +475,7 @@ public class EntityMergeSupport {
}
/**
- * @return naming strategy for reverse engineering
+ * @return a strategy for naming object layer artifacts based on their DB names.
*/
public ObjectNameGenerator getNameGenerator() {
return nameGenerator;
@@ -505,15 +484,15 @@ public class EntityMergeSupport {
/**
* @since 4.0
*/
- public boolean isUsePrimitives() {
- return usePrimitives;
+ public boolean isUsingPrimitives() {
+ return usingPrimitives;
}
/**
- * @param usePrimitives
+ * @param usingPrimitives
* @since 4.0
*/
- public void setUsePrimitives(boolean usePrimitives) {
- this.usePrimitives = usePrimitives;
+ public void setUsingPrimitives(boolean usingPrimitives) {
+ this.usingPrimitives = usingPrimitives;
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ac04c11b/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
index 77f9e61..57eab3e 100644
--- 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
@@ -135,9 +135,8 @@ public class MergerContext {
}
public Builder nameGenerator(ObjectNameGenerator nameGenerator) {
- context.entityMergeSupport = new EntityMergeSupport(context.getDataMap(),
- Objects.requireNonNull(nameGenerator),
- true); // should the last argument also be a part of the builder?
+ // should the last argument also be a part of the builder?
+ context.entityMergeSupport = new EntityMergeSupport(Objects.requireNonNull(nameGenerator), true, true);
return this;
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ac04c11b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/DbLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/DbLoader.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/DbLoader.java
index 888d6d4..7220b97 100644
--- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/DbLoader.java
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/db/DbLoader.java
@@ -22,12 +22,11 @@ import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.dbsync.merge.EntityMergeSupport;
import org.apache.cayenne.dbsync.naming.NameBuilder;
+import org.apache.cayenne.dbsync.naming.ObjectNameGenerator;
import org.apache.cayenne.dbsync.reverse.filters.CatalogFilter;
import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig;
import org.apache.cayenne.dbsync.reverse.filters.SchemaFilter;
import org.apache.cayenne.dbsync.reverse.filters.TableFilter;
-import org.apache.cayenne.dbsync.naming.LegacyObjectNameGenerator;
-import org.apache.cayenne.dbsync.naming.ObjectNameGenerator;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
@@ -51,6 +50,7 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
@@ -70,38 +70,18 @@ public class DbLoader {
private final DbAdapter adapter;
private final DbLoaderDelegate delegate;
- private boolean creatingMeaningfulPK;
-
- /**
- * Strategy for choosing names for entities, attributes and relationships
- */
- private ObjectNameGenerator nameGenerator;
-
+ private EntityMergeSupport entityMergeSupport;
private DatabaseMetaData metaData;
-
- /**
- * Creates new DbLoader.
- */
- public DbLoader(Connection connection, DbAdapter adapter, DbLoaderDelegate delegate) {
- this(connection, adapter, delegate, new LegacyObjectNameGenerator());
- }
-
- /**
- * 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;
+ public DbLoader(Connection connection, DbAdapter adapter, DbLoaderDelegate delegate, EntityMergeSupport entityMergeSupport) {
+ this.adapter = Objects.requireNonNull(adapter);
+ this.connection = Objects.requireNonNull(connection);
+ this.entityMergeSupport = Objects.requireNonNull(entityMergeSupport);
this.delegate = delegate == null ? new DefaultDbLoaderDelegate() : delegate;
-
- setNameGenerator(strategy);
}
private static List<String> getStrings(ResultSet rs) throws SQLException {
- List<String> strings = new ArrayList<String>();
+ List<String> strings = new ArrayList<>();
while (rs.next()) {
strings.add(rs.getString(1));
@@ -110,8 +90,12 @@ public class DbLoader {
return strings;
}
- private static Collection<ObjEntity> loadObjEntities(DataMap map, DbLoaderConfiguration config,
- Collection<DbEntity> entities, ObjectNameGenerator nameGenerator) {
+ private static Collection<ObjEntity> loadObjEntities(
+ DataMap map,
+ DbLoaderConfiguration config,
+ Collection<DbEntity> entities,
+ ObjectNameGenerator nameGenerator) {
+
if (entities.isEmpty()) {
return Collections.emptyList();
}
@@ -156,7 +140,7 @@ public class DbLoader {
if (loadedObjEntities.isEmpty()) {
return;
}
- Collection<ObjEntity> entitiesForDelete = new LinkedList<ObjEntity>();
+ Collection<ObjEntity> entitiesForDelete = new LinkedList<>();
for (ObjEntity curEntity : loadedObjEntities) {
ManyToManyCandidateEntity entity = ManyToManyCandidateEntity.build(curEntity);
@@ -218,13 +202,6 @@ public class DbLoader {
}
/**
- * @since 3.0
- */
- public void setCreatingMeaningfulPK(boolean creatingMeaningfulPK) {
- this.creatingMeaningfulPK = creatingMeaningfulPK;
- }
-
- /**
* Retrieves catalogs for the database associated with this DbLoader.
*
* @return List with the catalog names, empty Array if none found.
@@ -252,19 +229,14 @@ public class DbLoader {
*/
Collection<ObjEntity> loadObjEntities(DataMap map, DbLoaderConfiguration config,
Collection<DbEntity> entities) {
- Collection<ObjEntity> loadedEntities = DbLoader.loadObjEntities(map, config, entities, nameGenerator);
+ Collection<ObjEntity> loadedEntities = DbLoader
+ .loadObjEntities(map, config, entities, entityMergeSupport.getNameGenerator());
- createEntityMerger(map).synchronizeWithDbEntities(loadedEntities);
+ entityMergeSupport.synchronizeWithDbEntities(loadedEntities);
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 {
@@ -278,6 +250,8 @@ public class DbLoader {
tablesMap.put(table.getName(), table);
}
+ ObjectNameGenerator nameGenerator = entityMergeSupport.getNameGenerator();
+
Map<String, Set<ExportedKey>> keys = loadExportedKeys(config, catalog, schema, tablesMap);
for (Map.Entry<String, Set<ExportedKey>> entry : keys.entrySet()) {
if (LOGGER.isDebugEnabled()) {
@@ -352,9 +326,9 @@ public class DbLoader {
// TODO: can we avoid resetting the name twice? Do we need a placeholder name above?
forwardRelationship.setName(NameBuilder
- .builder(forwardRelationship, pkEntity)
- .baseName(nameGenerator.dbRelationshipName(key, !isOneToOne))
- .name());
+ .builder(forwardRelationship, pkEntity)
+ .baseName(nameGenerator.dbRelationshipName(key, !isOneToOne))
+ .name());
if (delegate.dbRelationshipLoaded(fkEntity, reverseRelationship)) {
fkEntity.addRelationship(reverseRelationship);
@@ -519,7 +493,7 @@ public class DbLoader {
private void prepareObjLayer(DataMap dataMap, DbLoaderConfiguration config, Collection<DbEntity> entities) {
Collection<ObjEntity> loadedObjEntities = loadObjEntities(dataMap, config, entities);
- flattenManyToManyRelationships(dataMap, loadedObjEntities, nameGenerator);
+ flattenManyToManyRelationships(dataMap, loadedObjEntities, entityMergeSupport.getNameGenerator());
fireObjEntitiesAddedEvents(loadedObjEntities);
}
@@ -697,18 +671,4 @@ public class DbLoader {
}
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. LegacyObjectNameGenerator will be used.");
- this.nameGenerator = new LegacyObjectNameGenerator();
- } else {
- this.nameGenerator = strategy;
- }
- }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ac04c11b/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
index 8d304da..bc24100 100644
--- 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
@@ -87,7 +87,7 @@ public class EntityMergeSupportIT extends MergeCase {
objEntity2.setDbEntity(dbEntity2);
map.addObjEntity(objEntity2);
- assertTrue(new EntityMergeSupport(map, new DefaultObjectNameGenerator(), true)
+ assertTrue(new EntityMergeSupport(new DefaultObjectNameGenerator(), true, true)
.synchronizeWithDbEntities(Arrays.asList(objEntity1, objEntity2)));
assertNotNull(objEntity1.getAttribute("name"));
assertNotNull(objEntity1.getRelationship("rel1To2"));
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ac04c11b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/db/DbLoaderIT.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/db/DbLoaderIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/db/DbLoaderIT.java
index 930d696..fe46391 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/db/DbLoaderIT.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/db/DbLoaderIT.java
@@ -19,16 +19,22 @@
package org.apache.cayenne.dbsync.reverse.db;
-import org.apache.cayenne.dbsync.reverse.db.DbLoader;
-import org.apache.cayenne.dbsync.reverse.db.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.configuration.server.ServerRuntime;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.TypesMapping;
+import org.apache.cayenne.dbsync.merge.EntityMergeSupport;
+import org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator;
+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.di.Inject;
-import org.apache.cayenne.map.*;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.DetectedDbEntity;
+import org.apache.cayenne.map.ObjAttribute;
+import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.unit.UnitDbAdapter;
import org.apache.cayenne.unit.di.server.CayenneProjects;
import org.apache.cayenne.unit.di.server.ServerCase;
@@ -43,7 +49,11 @@ import java.sql.Types;
import java.util.Collection;
import java.util.List;
-import static org.junit.Assert.*;
+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;
@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
public class DbLoaderIT extends ServerCase {
@@ -61,8 +71,6 @@ public class DbLoaderIT extends ServerCase {
@Inject
private UnitDbAdapter accessStackAdapter;
- private DbLoader loader;
-
private Connection connection;
private static String msgForTypeMismatch(DbAttribute origAttr, DbAttribute newAttr) {
@@ -82,7 +90,14 @@ public class DbLoaderIT extends ServerCase {
@Before
public void before() throws Exception {
this.connection = dataSourceFactory.getSharedDataSource().getConnection();
- this.loader = new DbLoader(connection, adapter, null);
+ }
+
+ private DbLoader createDbLoader(boolean meaningfulPK, boolean meaningfulFK) {
+ EntityMergeSupport emSupport = new EntityMergeSupport(new DefaultObjectNameGenerator(),
+ !meaningfulPK,
+ !meaningfulFK);
+
+ return new DbLoader(connection, adapter, null, emSupport);
}
@After
@@ -95,6 +110,8 @@ public class DbLoaderIT extends ServerCase {
String tableLabel = adapter.tableTypeForTable();
+ DbLoader loader = createDbLoader(false, false);
+
List<DetectedDbEntity> tables = loader.createTableLoader(null, null, TableFilter.everything())
.getDbEntities(TableFilter.everything(), new String[]{tableLabel});
@@ -115,6 +132,8 @@ public class DbLoaderIT extends ServerCase {
@Test
public void testGetTablesWithWrongCatalog() throws Exception {
+ DbLoader loader = createDbLoader(false, false);
+
DbLoaderConfiguration config = new DbLoaderConfiguration();
config.setFiltersConfig(
FiltersConfig.create("WRONG", null, TableFilter.everything(), PatternFilter.INCLUDE_NOTHING));
@@ -129,6 +148,8 @@ public class DbLoaderIT extends ServerCase {
@Test
public void testGetTablesWithWrongSchema() throws Exception {
+ DbLoader loader = createDbLoader(false, false);
+
DbLoaderConfiguration config = new DbLoaderConfiguration();
config.setFiltersConfig(
FiltersConfig.create(null, "WRONG", TableFilter.everything(), PatternFilter.INCLUDE_NOTHING));
@@ -143,11 +164,11 @@ public class DbLoaderIT extends ServerCase {
@Test
public void testLoadWithMeaningfulPK() throws Exception {
+ DbLoader loader = createDbLoader(true, false);
+
DataMap map = new DataMap();
String[] tableLabel = {adapter.tableTypeForTable()};
- loader.setCreatingMeaningfulPK(true);
-
List<DbEntity> entities = loader
.createTableLoader(null, null, TableFilter.everything())
.loadDbEntities(map, CONFIG, tableLabel);
@@ -168,6 +189,7 @@ public class DbLoaderIT extends ServerCase {
*/
@Test
public void testLoad() throws Exception {
+ DbLoader loader = createDbLoader(false, false);
boolean supportsUnique = runtime.getDataDomain().getDataNodes().iterator().next().getAdapter()
.supportsUniqueConstraints();
@@ -223,7 +245,6 @@ public class DbLoaderIT extends ServerCase {
}
// *** TESTING THIS ***
- loader.setCreatingMeaningfulPK(false);
loader.loadObjEntities(map, CONFIG, entities);
assertObjEntities(map);
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ac04c11b/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 b5c2fa7..c371ee6 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
@@ -146,27 +146,16 @@ public class DbImportConfiguration {
final NameFilter meaningfulPkFilter = NamePatternMatcher.build(logger, getMeaningfulPkTables(),
getMeaningfulPkTables() != null ? null : "*");
- DbLoader loader = new DbLoader(connection, adapter, loaderDelegate) {
+ EntityMergeSupport emSupport = new EntityMergeSupport(getNameGenerator(), true, true) {
@Override
- protected EntityMergeSupport createEntityMerger(DataMap map) {
- EntityMergeSupport emSupport = new EntityMergeSupport(map, DbImportConfiguration.this.getNameGenerator(), true) {
-
- @Override
- protected boolean removePK(DbEntity dbEntity) {
- return !meaningfulPkFilter.isIncluded(dbEntity.getName());
- }
- };
-
- emSupport.setUsePrimitives(DbImportConfiguration.this.isUsePrimitives());
- return emSupport;
+ protected boolean removePK(DbEntity dbEntity) {
+ return !meaningfulPkFilter.isIncluded(dbEntity.getName());
}
};
-
- loader.setNameGenerator(getNameGenerator());
-
- return loader;
+ emSupport.setUsingPrimitives(isUsePrimitives());
+ return new DbLoader(connection, adapter, loaderDelegate, emSupport);
}
public ObjectNameGenerator getNameGenerator() {
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ac04c11b/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 8f5ef79..6ec486e 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
@@ -110,6 +110,7 @@ public class DefaultDbImportAction implements DbImportAction {
return reverse;
}
+ @Override
public void execute(DbImportConfiguration config) throws Exception {
if (logger.isDebugEnabled()) {
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ac04c11b/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 98842a3..affe74e 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
@@ -29,6 +29,7 @@ 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.EntityMergeSupport;
import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider;
import org.apache.cayenne.dbsync.merge.MergerToken;
import org.apache.cayenne.dbsync.merge.builders.DataMapBuilder;
@@ -48,6 +49,7 @@ import org.apache.cayenne.resource.URLResource;
import org.apache.cayenne.tools.configuration.ToolsModule;
import org.apache.cayenne.util.Util;
import org.apache.commons.logging.Log;
+import org.junit.Before;
import org.junit.Test;
import org.xml.sax.InputSource;
@@ -87,32 +89,45 @@ public class DefaultDbImportActionTest {
return true;
}
- @Override
- public boolean canRead() {
- return true;
- }
- };
+ @Override
+ public boolean canRead() {
+ return true;
+ }
+ };
+
+ private DbAdapter mockAdapter;
+ private Connection mockConnection;
+ private DbLoaderDelegate mockDelegate;
+ private EntityMergeSupport mockEmSupport;
+
+ @Before
+ public void before() {
+ mockAdapter = mock(DbAdapter.class);
+ mockConnection = mock(Connection.class);
+ mockDelegate = mock(DbLoaderDelegate.class);
+ mockEmSupport = mock(EntityMergeSupport.class);
+ }
- @Test
- public void testNewDataMapImport() throws Exception {
+ @Test
+ public void testNewDataMapImport() throws Exception {
- DbLoader dbLoader = new DbLoader(null, null, null) {
- @Override
- public void load(DataMap dataMap, DbLoaderConfiguration config) throws SQLException {
- new DataMapBuilder(dataMap).withDbEntities(2).build();
- }
- };
+ DbLoader dbLoader = new DbLoader(mockConnection, mockAdapter, mockDelegate, mockEmSupport) {
+ @Override
+ public void load(DataMap dataMap, DbLoaderConfiguration config) throws SQLException {
+ new DataMapBuilder(dataMap).withDbEntities(2).build();
+ }
+ };
DbImportConfiguration params = mock(DbImportConfiguration.class);
when(params.createLoader(any(DbAdapter.class), any(Connection.class), any(DbLoaderDelegate.class)))
.thenReturn(dbLoader);
- when(params.createDataMap()).thenReturn(new DataMap("testImport"));
- when(params.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate());
- when(params.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration());
+ when(params.createDataMap()).thenReturn(new DataMap("testImport"));
+ when(params.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate());
+ when(params.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration());
- final DataMap DATA_MAP = new DataMap();
- when(params.initializeDataMap(any(DataMap.class))).thenReturn(DATA_MAP);
+ final DataMap DATA_MAP = new DataMap();
+ when(params.initializeDataMap(any(DataMap.class))).thenReturn(DATA_MAP);
final boolean[] haveWeTriedToSave = {false};
DefaultDbImportAction action = buildDbImportAction(new FileProjectSaver() {
@@ -120,19 +135,19 @@ public class DefaultDbImportActionTest {
public void save(Project project) {
haveWeTriedToSave[0] = true;
- // Validation phase
- assertEquals(DATA_MAP, project.getRootNode());
- }
- }, null);
+ // Validation phase
+ assertEquals(DATA_MAP, project.getRootNode());
+ }
+ }, null);
- action.execute(params);
+ action.execute(params);
- assertTrue("We should try to save.", haveWeTriedToSave[0]);
- }
+ assertTrue("We should try to save.", haveWeTriedToSave[0]);
+ }
@Test
public void testImportWithFieldChanged() throws Exception {
- DbLoader dbLoader = new DbLoader(null, null, null) {
+ DbLoader dbLoader = new DbLoader(mockConnection, mockAdapter, mockDelegate, mockEmSupport) {
@Override
public void load(DataMap dataMap, DbLoaderConfiguration config) throws SQLException {
new DataMapBuilder(dataMap).with(
@@ -146,17 +161,17 @@ public class DefaultDbImportActionTest {
objAttr("name").type(String.class).dbPath("NAME")
));
}
- };
+ };
DbImportConfiguration params = mock(DbImportConfiguration.class);
when(params.createLoader(any(DbAdapter.class), any(Connection.class), any(DbLoaderDelegate.class)))
.thenReturn(dbLoader);
- when(params.createDataMap()).thenReturn(new DataMap("testImport"));
- when(params.getDataMapFile()).thenReturn(FILE_STUB);
- when(params.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate());
- when(params.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration());
- when(params.getNameGenerator()).thenReturn(new DefaultObjectNameGenerator());
+ when(params.createDataMap()).thenReturn(new DataMap("testImport"));
+ when(params.getDataMapFile()).thenReturn(FILE_STUB);
+ when(params.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate());
+ when(params.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration());
+ when(params.getNameGenerator()).thenReturn(new DefaultObjectNameGenerator());
final boolean[] haveWeTriedToSave = {false};
DefaultDbImportAction action = buildDbImportAction(new FileProjectSaver() {
@@ -164,17 +179,17 @@ public class DefaultDbImportActionTest {
public void save(Project project) {
haveWeTriedToSave[0] = true;
- // Validation phase
- DataMap rootNode = (DataMap) project.getRootNode();
- assertEquals(1, rootNode.getObjEntities().size());
- assertEquals(1, rootNode.getDbEntityMap().size());
+ // Validation phase
+ DataMap rootNode = (DataMap) project.getRootNode();
+ assertEquals(1, rootNode.getObjEntities().size());
+ assertEquals(1, rootNode.getDbEntityMap().size());
- DbEntity entity = rootNode.getDbEntity("ARTGROUP");
- assertNotNull(entity);
- assertEquals(4, entity.getAttributes().size());
- assertNotNull(entity.getAttribute("NAME_01"));
- }
- }, new MapLoader() {
+ DbEntity entity = rootNode.getDbEntity("ARTGROUP");
+ assertNotNull(entity);
+ assertEquals(4, entity.getAttributes().size());
+ assertNotNull(entity.getAttribute("NAME_01"));
+ }
+ }, new MapLoader() {
@Override
public synchronized DataMap loadDataMap(InputSource src) throws CayenneRuntimeException {
@@ -190,14 +205,14 @@ public class DefaultDbImportActionTest {
}
});
- action.execute(params);
+ action.execute(params);
- assertTrue("We should try to save.", haveWeTriedToSave[0]);
- }
+ assertTrue("We should try to save.", haveWeTriedToSave[0]);
+ }
@Test
public void testImportWithoutChanges() throws Exception {
- DbLoader dbLoader = new DbLoader(null, null, null) {
+ DbLoader dbLoader = new DbLoader(mockConnection, mockAdapter, mockDelegate, mockEmSupport) {
@Override
public void load(DataMap dataMap, DbLoaderConfiguration config) throws SQLException {
new DataMapBuilder(dataMap).with(
@@ -205,23 +220,23 @@ public class DefaultDbImportActionTest {
dbAttr("NAME").typeVarchar(100).mandatory()
));
}
- };
+ };
DbImportConfiguration params = mock(DbImportConfiguration.class);
when(params.createLoader(any(DbAdapter.class), any(Connection.class), any(DbLoaderDelegate.class)))
.thenReturn(dbLoader);
- when(params.createDataMap()).thenReturn(new DataMap("testImport"));
- when(params.getDataMapFile()).thenReturn(FILE_STUB);
- when(params.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate());
- when(params.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration());
+ when(params.createDataMap()).thenReturn(new DataMap("testImport"));
+ when(params.getDataMapFile()).thenReturn(FILE_STUB);
+ when(params.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate());
+ when(params.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration());
- Log log = mock(Log.class);
- when(log.isDebugEnabled()).thenReturn(false);
- when(log.isInfoEnabled()).thenReturn(false);
+ Log log = mock(Log.class);
+ when(log.isDebugEnabled()).thenReturn(false);
+ when(log.isInfoEnabled()).thenReturn(false);
- FileProjectSaver projectSaver = mock(FileProjectSaver.class);
- doNothing().when(projectSaver).save(any(Project.class));
+ FileProjectSaver projectSaver = mock(FileProjectSaver.class);
+ doNothing().when(projectSaver).save(any(Project.class));
MapLoader mapLoader = mock(MapLoader.class);
stub(mapLoader.loadDataMap(any(InputSource.class))).toReturn(new DataMapBuilder().with(
@@ -231,108 +246,108 @@ public class DefaultDbImportActionTest {
DefaultDbImportAction action = buildDbImportAction(log, projectSaver, mapLoader);
- action.execute(params);
+ action.execute(params);
- verify(projectSaver, never()).save(any(Project.class));
- verify(mapLoader, times(1)).loadDataMap(any(InputSource.class));
- }
+ verify(projectSaver, never()).save(any(Project.class));
+ verify(mapLoader, times(1)).loadDataMap(any(InputSource.class));
+ }
- @Test
- public void testImportWithDbError() throws Exception {
- DbLoader dbLoader = mock(DbLoader.class);
- doThrow(new SQLException()).when(dbLoader).load(any(DataMap.class), any(DbLoaderConfiguration.class));
+ @Test
+ public void testImportWithDbError() throws Exception {
+ DbLoader dbLoader = mock(DbLoader.class);
+ doThrow(new SQLException()).when(dbLoader).load(any(DataMap.class), any(DbLoaderConfiguration.class));
DbImportConfiguration params = mock(DbImportConfiguration.class);
when(params.createLoader(any(DbAdapter.class), any(Connection.class), any(DbLoaderDelegate.class)))
.thenReturn(dbLoader);
- FileProjectSaver projectSaver = mock(FileProjectSaver.class);
- doNothing().when(projectSaver).save(any(Project.class));
+ FileProjectSaver projectSaver = mock(FileProjectSaver.class);
+ doNothing().when(projectSaver).save(any(Project.class));
- MapLoader mapLoader = mock(MapLoader.class);
- when(mapLoader.loadDataMap(any(InputSource.class))).thenReturn(null);
+ MapLoader mapLoader = mock(MapLoader.class);
+ when(mapLoader.loadDataMap(any(InputSource.class))).thenReturn(null);
DefaultDbImportAction action = buildDbImportAction(projectSaver, mapLoader);
- try {
- action.execute(params);
- fail();
- } catch (SQLException e) {
- // expected
- }
+ try {
+ action.execute(params);
+ fail();
+ } catch (SQLException e) {
+ // expected
+ }
- verify(projectSaver, never()).save(any(Project.class));
- verify(mapLoader, never()).loadDataMap(any(InputSource.class));
- }
+ verify(projectSaver, never()).save(any(Project.class));
+ verify(mapLoader, never()).loadDataMap(any(InputSource.class));
+ }
private DefaultDbImportAction buildDbImportAction(FileProjectSaver projectSaver, MapLoader mapLoader) throws Exception {
Log log = mock(Log.class);
when(log.isDebugEnabled()).thenReturn(true);
when(log.isInfoEnabled()).thenReturn(true);
- return buildDbImportAction(log, projectSaver, mapLoader);
- }
+ return buildDbImportAction(log, projectSaver, mapLoader);
+ }
private DefaultDbImportAction buildDbImportAction(Log log, FileProjectSaver projectSaver, MapLoader mapLoader) throws Exception {
DbAdapter dbAdapter = mock(DbAdapter.class);
- DbAdapterFactory adapterFactory = mock(DbAdapterFactory.class);
- when(adapterFactory.createAdapter(any(DataNodeDescriptor.class), any(DataSource.class))).thenReturn(dbAdapter);
+ DbAdapterFactory adapterFactory = mock(DbAdapterFactory.class);
+ when(adapterFactory.createAdapter(any(DataNodeDescriptor.class), any(DataSource.class))).thenReturn(dbAdapter);
- DataSourceFactory dataSourceFactory = mock(DataSourceFactory.class);
- DataSource mock = mock(DataSource.class);
- when(dataSourceFactory.getDataSource(any(DataNodeDescriptor.class))).thenReturn(mock);
+ DataSourceFactory dataSourceFactory = mock(DataSourceFactory.class);
+ DataSource mock = mock(DataSource.class);
+ when(dataSourceFactory.getDataSource(any(DataNodeDescriptor.class))).thenReturn(mock);
- MergerTokenFactoryProvider mergerTokenFactoryProvider = mock(MergerTokenFactoryProvider.class);
- when(mergerTokenFactoryProvider.get(any(DbAdapter.class))).thenReturn(new DefaultMergerTokenFactory());
+ 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 CayenneDbSyncModule(), new ToolsModule(log), new DbImportModule());
+ @Test
+ public void testSaveLoaded() throws Exception {
+ Log log = mock(Log.class);
+ Injector i = DIBootstrap.createInjector(new CayenneDbSyncModule(), new ToolsModule(log), new DbImportModule());
DefaultDbImportAction action = (DefaultDbImportAction) i.getInstance(DbImportAction.class);
- String packagePath = getClass().getPackage().getName().replace('.', '/');
- URL packageUrl = getClass().getClassLoader().getResource(packagePath);
- assertNotNull(packageUrl);
- URL outUrl = new URL(packageUrl, "dbimport/testSaveLoaded1.map.xml");
+ String packagePath = getClass().getPackage().getName().replace('.', '/');
+ URL packageUrl = getClass().getClassLoader().getResource(packagePath);
+ assertNotNull(packageUrl);
+ URL outUrl = new URL(packageUrl, "dbimport/testSaveLoaded1.map.xml");
- File out = new File(outUrl.toURI());
- out.delete();
- assertFalse(out.isFile());
+ File out = new File(outUrl.toURI());
+ out.delete();
+ assertFalse(out.isFile());
- DataMap map = new DataMap("testSaveLoaded1");
- map.setConfigurationSource(new URLResource(outUrl));
+ DataMap map = new DataMap("testSaveLoaded1");
+ map.setConfigurationSource(new URLResource(outUrl));
- action.saveLoaded(map);
+ action.saveLoaded(map);
- assertTrue(out.isFile());
+ assertTrue(out.isFile());
- String contents = Util.stringFromFile(out);
- assertTrue("Has no project version saved", contents.contains("project-version=\""));
- }
+ String contents = Util.stringFromFile(out);
+ assertTrue("Has no project version saved", contents.contains("project-version=\""));
+ }
- @Test
- public void testMergeTokensSorting() {
- LinkedList<MergerToken> tokens = new LinkedList<MergerToken>();
- tokens.add(new AddColumnToDb(null, null));
- tokens.add(new AddRelationshipToDb(null, null));
- tokens.add(new CreateTableToDb(null));
- tokens.add(new CreateTableToModel(null));
+ @Test
+ public void testMergeTokensSorting() {
+ LinkedList<MergerToken> tokens = new LinkedList<MergerToken>();
+ tokens.add(new AddColumnToDb(null, null));
+ tokens.add(new AddRelationshipToDb(null, null));
+ tokens.add(new CreateTableToDb(null));
+ tokens.add(new CreateTableToModel(null));
assertEquals(asList("AddColumnToDb", "CreateTableToDb", "CreateTableToModel", "AddRelationshipToDb"),
toClasses(DefaultDbImportAction.sort(tokens)));
}
- private List<String> toClasses(List<MergerToken> sort) {
- LinkedList<String> res = new LinkedList<String>();
- for (MergerToken mergerToken : sort) {
- res.add(mergerToken.getClass().getSimpleName());
- }
- return res;
- }
+ private List<String> toClasses(List<MergerToken> sort) {
+ LinkedList<String> res = new LinkedList<String>();
+ for (MergerToken mergerToken : sort) {
+ res.add(mergerToken.getClass().getSimpleName());
+ }
+ return res;
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ac04c11b/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 b5a95d7..af43556 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
@@ -1,22 +1,21 @@
-/*****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ****************************************************************/
-
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
package org.apache.cayenne.modeler.action;
import org.apache.cayenne.configuration.ConfigurationNode;
@@ -113,7 +112,7 @@ public class CreateObjEntityAction extends CayenneAction {
dataMap.addObjEntity(entity);
// perform the merge
- EntityMergeSupport merger = new EntityMergeSupport(dataMap, new DefaultObjectNameGenerator(), true);
+ EntityMergeSupport merger = new EntityMergeSupport(new DefaultObjectNameGenerator(), true, true);
merger.addEntityMergeListener(DeleteRuleUpdater.getEntityMergeListener());
merger.synchronizeWithDbEntity(entity);
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ac04c11b/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 65294b5..5a5f346 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
@@ -89,7 +89,7 @@ public class DbEntitySyncAction extends CayenneAction {
merger.addEntityMergeListener(listener);
- if (merger.isRemoveMeaningfulFKs()) {
+ if (merger.isRemovingMeaningfulFKs()) {
undoableEdit.addEdit(undoableEdit.new MeaningfulFKsUndoableEdit(entity, merger
.getMeaningfulFKs(entity)));
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ac04c11b/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 b8e7383..a629477 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
@@ -20,7 +20,9 @@
package org.apache.cayenne.modeler.action;
import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dbsync.merge.EntityMergeSupport;
import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider;
+import org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator;
import org.apache.cayenne.dbsync.reverse.db.DbLoader;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.modeler.Application;
@@ -105,6 +107,8 @@ public class MigrateAction extends DBWizardAction {
.makeAdapter(getApplication().getClassLoadingService());
DataSource dataSource = connectWizard.getConnectionInfo()
.makeDataSource(getApplication().getClassLoadingService());
- return new DbLoader(dataSource.getConnection(), dbAdapter, null).loadSchemas();
+
+ EntityMergeSupport emSupport = new EntityMergeSupport(new DefaultObjectNameGenerator(), true, true);
+ return new DbLoader(dataSource.getConnection(), dbAdapter, null, emSupport).loadSchemas();
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ac04c11b/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 7ee114c..5a3bbfb 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
@@ -62,10 +62,11 @@ import java.util.List;
public class DbLoaderHelper {
// TODO: this is a temp hack... need to delegate to DbAdapter, or
- // configurable in
- // preferences...
+ // configurable in preferences...
private static final Collection<String> EXCLUDED_TABLES = Arrays.asList("AUTO_PK_SUPPORT", "auto_pk_support");
- private static Log logObj = LogFactory.getLog(DbLoaderHelper.class);
+
+ private static Log LOGGER = LogFactory.getLog(DbLoaderHelper.class);
+
protected boolean stoppingReverseEngineering;
protected boolean existingMap;
@@ -91,7 +92,7 @@ public class DbLoaderHelper {
try {
this.dbCatalog = connection.getCatalog();
} catch (SQLException e) {
- logObj.warn("Error getting catalog.", e);
+ LOGGER.warn("Error getting catalog.", e);
}
this.adapter = adapter;
this.reverseEngineering = reverseEngineering;
@@ -105,7 +106,7 @@ public class DbLoaderHelper {
try {
this.dbCatalog = connection.getCatalog();
} catch (SQLException e) {
- logObj.warn("Error getting catalog.", e);
+ LOGGER.warn("Error getting catalog.", e);
}
try {
this.loader = config.createLoader(adapter, connection, new LoaderDelegate());
@@ -152,15 +153,12 @@ public class DbLoaderHelper {
return;
}
- this.loader.setCreatingMeaningfulPK(true);
-
LongRunningTask loadDataMapTask = new LoadDataMapTask(Application.getFrame(), "Reengineering DB");
loadDataMapTask.startAndWait();
-
}
protected void processException(final Throwable th, final String message) {
- logObj.info("Exception on reverse engineering", Util.unwindException(th));
+ LOGGER.info("Exception on reverse engineering", Util.unwindException(th));
SwingUtilities.invokeLater(new Runnable() {
public void run() {
@@ -369,11 +367,11 @@ public class DbLoaderHelper {
config.getDbLoaderConfig().setFiltersConfig(filtersConfigBuilder.build());
- ModelerDbImportAction importAction = new ModelerDbImportAction(logObj, DbLoaderHelper.this);
+ ModelerDbImportAction importAction = new ModelerDbImportAction(LOGGER, DbLoaderHelper.this);
// 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 injector = DIBootstrap.createInjector(new CayenneDbSyncModule(), new ToolsModule(LOGGER), new DbImportModule());
injector.injectMembers(importAction);
try {
importAction.execute(config);
http://git-wip-us.apache.org/repos/asf/cayenne/blob/ac04c11b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ModelerDbLoader.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ModelerDbLoader.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ModelerDbLoader.java
index 6ca30af..4a5f53e 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ModelerDbLoader.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/ModelerDbLoader.java
@@ -18,6 +18,8 @@
****************************************************************/
package org.apache.cayenne.modeler.dialog.db;
+import org.apache.cayenne.dbsync.merge.EntityMergeSupport;
+import org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator;
import org.apache.cayenne.dbsync.reverse.db.DbLoader;
import org.apache.cayenne.dbsync.reverse.db.DbLoaderConfiguration;
import org.apache.cayenne.dbsync.reverse.db.DefaultDbLoaderDelegate;
@@ -52,7 +54,10 @@ class ModelerDbLoader extends DbLoader {
private ReverseEngineeringController reverseEngineeringController;
public ModelerDbLoader(ReverseEngineeringController reverseEngineeringController, TreeEditor treeEditor, Connection connection) {
- super(connection, reverseEngineeringController.adapter, new DefaultDbLoaderDelegate());
+ super(connection,
+ reverseEngineeringController.adapter,
+ new DefaultDbLoaderDelegate(),
+ new EntityMergeSupport(new DefaultObjectNameGenerator(), true, true));
this.treeEditor = treeEditor;
this.reverseEngineeringController = reverseEngineeringController;
}