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 <[email protected]> Authored: Mon Oct 3 14:04:40 2016 +0300 Committer: Andrus Adamchik <[email protected]> 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; }
