CAY-2115 DbLoader - allow loading DataMap without Obj layer * refactoring DbMerger... removing dependency on DbLoaderConfiguration using own builder instead
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/a811b44e Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/a811b44e Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/a811b44e Branch: refs/heads/master Commit: a811b44e5cfdc8b659f0f8a493150ff40a45a07a Parents: d6aa914 Author: Andrus Adamchik <and...@objectstyle.com> Authored: Mon Oct 3 18:49:03 2016 +0300 Committer: Andrus Adamchik <and...@objectstyle.com> Committed: Mon Oct 3 20:09:05 2016 +0300 ---------------------------------------------------------------------- .../apache/cayenne/dbsync/merge/DbMerger.java | 117 ++++++++++---- .../cayenne/dbsync/merge/DbMergerConfig.java | 63 -------- .../dbsync/merge/DefaultModelMergeDelegate.java | 32 ++-- .../dbsync/merge/EmptyValueForNullProvider.java | 4 +- .../dbsync/merge/ModelMergeDelegate.java | 28 ++-- .../cayenne/dbsync/merge/DbMergerTest.java | 29 ++-- .../apache/cayenne/dbsync/merge/MergeCase.java | 19 ++- .../cayenne/dbsync/merge/ValueForNullIT.java | 161 +++++++++---------- .../tools/dbimport/DbImportConfiguration.java | 14 +- .../tools/dbimport/DefaultDbImportAction.java | 16 +- .../modeler/dialog/db/MergerOptions.java | 15 +- 11 files changed, 236 insertions(+), 262 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cayenne/blob/a811b44e/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 605b6af..b3d7119 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 @@ -20,8 +20,9 @@ package org.apache.cayenne.dbsync.merge; import org.apache.cayenne.access.DataNode; import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory; -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.map.Attribute; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.map.DbAttribute; @@ -41,18 +42,26 @@ import java.util.Objects; 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}. + * Wraps an algorithm to traverse a {@link DataMap} and create a group of {@link MergerToken}s that can be used to + * synchronize data store and Cayenne model. */ public class DbMerger { - private final MergerTokenFactory factory; - private final ValueForNullProvider valueForNull; + private MergerTokenFactory tokenFactory; + private ValueForNullProvider valueForNull; + private boolean skipRelationshipsTokens; + private boolean skipPKTokens; + private FiltersConfig filters; - public DbMerger(MergerTokenFactory factory, ValueForNullProvider valueForNull) { - this.factory = Objects.requireNonNull(factory); - this.valueForNull = Objects.requireNonNull(valueForNull); + private DbMerger() { + } + + public static Builder builder(MergerTokenFactory tokenFactory) { + return new Builder(tokenFactory); + } + + public static DbMerger build(MergerTokenFactory tokenFactory) { + return builder(tokenFactory).build(); } /** @@ -99,12 +108,11 @@ public class DbMerger { * 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) { + public List<MergerToken> createMergeTokens(DataMap existing, DataMap loadedFomDb) { loadedFomDb.setQuotingSQLIdentifiers(existing.isQuotingSQLIdentifiers()); - List<MergerToken> tokens = createMergeTokens(filter(existing, config.getFiltersConfig()), - loadedFomDb.getDbEntities(), config); + List<MergerToken> tokens = createMergeTokens(filter(existing, filters), loadedFomDb.getDbEntities()); // sort. use a custom Comparator since only toDb tokens are comparable // by now @@ -123,7 +131,7 @@ public class DbMerger { } private Collection<DbEntity> filter(DataMap existing, FiltersConfig filtersConfig) { - Collection<DbEntity> existingFiltered = new LinkedList<DbEntity>(); + Collection<DbEntity> existingFiltered = new LinkedList<>(); for (DbEntity entity : existing.getDbEntities()) { if (filtersConfig.tableFilter(entity.getCatalog(), entity.getSchema()).isIncludeTable(entity.getName()) != null) { existingFiltered.add(entity); @@ -132,9 +140,7 @@ public class DbMerger { return existingFiltered; } - protected List<MergerToken> createMergeTokens(Collection<DbEntity> existing, - Collection<DbEntity> loadedFromDb, - DbLoaderConfiguration config) { + protected List<MergerToken> createMergeTokens(Collection<DbEntity> existing, Collection<DbEntity> loadedFromDb) { Collection<DbEntity> dbEntitiesToDrop = new LinkedList<>(loadedFromDb); List<MergerToken> tokens = new LinkedList<>(); @@ -144,10 +150,10 @@ public class DbMerger { // look for table DbEntity detectedEntity = findDbEntity(loadedFromDb, tableName); if (detectedEntity == null) { - tokens.add(factory.createCreateTableToDb(dbEntity)); + tokens.add(tokenFactory.createCreateTableToDb(dbEntity)); // TODO: does this work properly with createReverse? for (DbRelationship rel : dbEntity.getRelationships()) { - tokens.add(factory.createAddRelationshipToDb(dbEntity, rel)); + tokens.add(tokenFactory.createAddRelationshipToDb(dbEntity, rel)); } continue; } @@ -155,12 +161,12 @@ public class DbMerger { dbEntitiesToDrop.remove(detectedEntity); tokens.addAll(checkRelationshipsToDrop(dbEntity, detectedEntity)); - if (!config.isSkipRelationshipsLoading()) { + if (!skipRelationshipsTokens) { tokens.addAll(checkRelationshipsToAdd(dbEntity, detectedEntity)); } tokens.addAll(checkRows(dbEntity, detectedEntity)); - if (!config.isSkipPrimaryKeyLoading()) { + if (!skipPKTokens) { MergerToken token = checkPrimaryKeyChange(dbEntity, detectedEntity); if (token != null) { tokens.add(token); @@ -172,11 +178,11 @@ public class DbMerger { // TODO: support drop table. currently, too many tables are marked for // drop for (DbEntity e : dbEntitiesToDrop) { - tokens.add(factory.createDropTableToDb(e)); + tokens.add(tokenFactory.createDropTableToDb(e)); for (DbRelationship relationship : e.getRelationships()) { DbEntity detectedEntity = findDbEntity(existing, relationship.getTargetEntityName()); if (detectedEntity != null) { - tokens.add(factory.createDropRelationshipToDb(detectedEntity, relationship.getReverseRelationship())); + tokens.add(tokenFactory.createDropRelationshipToDb(detectedEntity, relationship.getReverseRelationship())); } } } @@ -190,7 +196,7 @@ public class DbMerger { // columns to drop for (DbAttribute detected : loadedFromDb.getAttributes()) { if (findDbAttribute(existing, detected.getName()) == null) { - tokens.add(factory.createDropColumnToDb(existing, detected)); + tokens.add(tokenFactory.createDropColumnToDb(existing, detected)); } } @@ -201,12 +207,12 @@ public class DbMerger { DbAttribute detected = findDbAttribute(loadedFromDb, columnName); if (detected == null) { - tokens.add(factory.createAddColumnToDb(existing, attr)); + tokens.add(tokenFactory.createAddColumnToDb(existing, attr)); if (attr.isMandatory()) { if (valueForNull.hasValueFor(existing, attr)) { - tokens.add(factory.createSetValueForNullToDb(existing, attr, valueForNull)); + tokens.add(tokenFactory.createSetValueForNullToDb(existing, attr, valueForNull)); } - tokens.add(factory.createSetNotNullToDb(existing, attr)); + tokens.add(tokenFactory.createSetNotNullToDb(existing, attr)); } continue; } @@ -215,11 +221,11 @@ public class DbMerger { if (attr.isMandatory() != detected.isMandatory()) { if (attr.isMandatory()) { if (valueForNull.hasValueFor(existing, attr)) { - tokens.add(factory.createSetValueForNullToDb(existing, attr, valueForNull)); + tokens.add(tokenFactory.createSetValueForNullToDb(existing, attr, valueForNull)); } - tokens.add(factory.createSetNotNullToDb(existing, attr)); + tokens.add(tokenFactory.createSetNotNullToDb(existing, attr)); } else { - tokens.add(factory.createSetAllowNullToDb(existing, attr)); + tokens.add(tokenFactory.createSetAllowNullToDb(existing, attr)); } } @@ -229,7 +235,7 @@ public class DbMerger { case Types.VARCHAR: case Types.CHAR: if (attr.getMaxLength() != detected.getMaxLength()) { - tokens.add(factory.createSetColumnTypeToDb(existing, detected, attr)); + tokens.add(tokenFactory.createSetColumnTypeToDb(existing, detected, attr)); } break; } @@ -270,12 +276,12 @@ public class DbMerger { } } - MergerToken token = factory.createDropRelationshipToDb(dbEntity, detected); + MergerToken token = tokenFactory.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); + token = token.createReverse(tokenFactory); } tokens.add(token); } @@ -290,7 +296,7 @@ public class DbMerger { for (DbRelationship rel : dbEntity.getRelationships()) { if (findDbRelationship(detectedEntity, rel) == null) { - AddRelationshipToDb token = (AddRelationshipToDb) factory.createAddRelationshipToDb(dbEntity, rel); + AddRelationshipToDb token = (AddRelationshipToDb) tokenFactory.createAddRelationshipToDb(dbEntity, rel); if (token.shouldGenerateFkConstraint()) { // TODO I guess we should add relationship always; in order @@ -319,7 +325,7 @@ public class DbMerger { return null; } - return factory.createSetPrimaryKeyToDb(dbEntity, primaryKeyOriginal, primaryKeyNew, primaryKeyName); + return tokenFactory.createSetPrimaryKeyToDb(dbEntity, primaryKeyOriginal, primaryKeyNew, primaryKeyName); } private Set<String> upperCaseEntityNames(Collection<? extends Attribute> attrs) { @@ -369,4 +375,47 @@ public class DbMerger { } return null; } + + public static class Builder { + private DbMerger merger; + + private Builder(MergerTokenFactory tokenFactory) { + this.merger = new DbMerger(); + this.merger.tokenFactory = Objects.requireNonNull(tokenFactory); + } + + public DbMerger build() { + + if (merger.valueForNull == null) { + merger.valueForNull = new EmptyValueForNullProvider(); + } + + if(merger.filters == null) { + // default: match all tables, no stored procedures + merger.filters = FiltersConfig.create(null, null, TableFilter.everything(), PatternFilter.INCLUDE_NOTHING); + } + + return merger; + } + + public Builder valueForNullProvider(ValueForNullProvider provider) { + merger.valueForNull = provider; + return this; + } + + public Builder skipRelationshipsTokens(boolean flag) { + merger.skipRelationshipsTokens = flag; + return this; + } + + public Builder skipPKTokens(boolean flag) { + merger.skipPKTokens = flag; + return this; + } + + public Builder filters(FiltersConfig filters) { + merger.filters = Objects.requireNonNull(filters); + return this; + } + } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/a811b44e/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMergerConfig.java ---------------------------------------------------------------------- diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMergerConfig.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMergerConfig.java deleted file mode 100644 index 1cd80df..0000000 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbMergerConfig.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.cayenne.dbsync.merge; - -import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig; - -/** - * @since 4.0 - */ -public class DbMergerConfig { - - private FiltersConfig filtersConfig; - - private boolean skipRelationships; - - private boolean skipPrimaryKey; - - public DbMergerConfig(FiltersConfig filtersConfig, boolean skipRelationships, boolean skipPrimaryKey) { - this.filtersConfig = filtersConfig; - this.skipRelationships = skipRelationships; - this.skipPrimaryKey = skipPrimaryKey; - } - - public void setSkipRelationships(boolean skipRelationships) { - this.skipRelationships = skipRelationships; - } - - public boolean isSkipRelationships() { - return skipRelationships; - } - - public void setSkipPrimaryKey(boolean skipPrimaryKey) { - this.skipPrimaryKey = skipPrimaryKey; - } - - public boolean isSkipPrimaryKey() { - return skipPrimaryKey; - } - - public FiltersConfig getFiltersConfig() { - return filtersConfig; - } - - public void setFiltersConfig(FiltersConfig filtersConfig) { - this.filtersConfig = filtersConfig; - } -} http://git-wip-us.apache.org/repos/asf/cayenne/blob/a811b44e/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DefaultModelMergeDelegate.java ---------------------------------------------------------------------- diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DefaultModelMergeDelegate.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DefaultModelMergeDelegate.java index 617aad2..816729d 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DefaultModelMergeDelegate.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DefaultModelMergeDelegate.java @@ -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.dbsync.merge; import org.apache.cayenne.map.DbAttribute; http://git-wip-us.apache.org/repos/asf/cayenne/blob/a811b44e/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EmptyValueForNullProvider.java ---------------------------------------------------------------------- diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EmptyValueForNullProvider.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EmptyValueForNullProvider.java index 84a396b..ceaa7a3 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EmptyValueForNullProvider.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/EmptyValueForNullProvider.java @@ -26,10 +26,8 @@ import java.util.List; /** * A dummy {@link ValueForNullProvider} that are not able to provide any values. - * - * @since 4.0 */ -public class EmptyValueForNullProvider implements ValueForNullProvider { +class EmptyValueForNullProvider implements ValueForNullProvider { public List<String> createSql(DbEntity entity, DbAttribute column) { return Collections.emptyList(); http://git-wip-us.apache.org/repos/asf/cayenne/blob/a811b44e/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ModelMergeDelegate.java ---------------------------------------------------------------------- diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ModelMergeDelegate.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ModelMergeDelegate.java index 13f6ea5..ac63d93 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ModelMergeDelegate.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ModelMergeDelegate.java @@ -31,32 +31,32 @@ import org.apache.cayenne.map.ObjRelationship; */ public interface ModelMergeDelegate { - public void dbEntityAdded(DbEntity ent); + void dbEntityAdded(DbEntity ent); - public void dbEntityRemoved(DbEntity ent); + void dbEntityRemoved(DbEntity ent); - public void objEntityAdded(ObjEntity ent); + void objEntityAdded(ObjEntity ent); - public void objEntityRemoved(ObjEntity ent); + void objEntityRemoved(ObjEntity ent); - public void dbAttributeAdded(DbAttribute att); + void dbAttributeAdded(DbAttribute att); - public void dbAttributeRemoved(DbAttribute att); + void dbAttributeRemoved(DbAttribute att); - public void dbAttributeModified(DbAttribute att); + void dbAttributeModified(DbAttribute att); - public void objAttributeAdded(ObjAttribute att); + void objAttributeAdded(ObjAttribute att); - public void objAttributeRemoved(ObjAttribute att); + void objAttributeRemoved(ObjAttribute att); - public void objAttributeModified(ObjAttribute att); + void objAttributeModified(ObjAttribute att); - public void dbRelationshipAdded(DbRelationship rel); + void dbRelationshipAdded(DbRelationship rel); - public void dbRelationshipRemoved(DbRelationship rel); + void dbRelationshipRemoved(DbRelationship rel); - public void objRelationshipAdded(ObjRelationship rel); + void objRelationshipAdded(ObjRelationship rel); - public void objRelationshipRemoved(ObjRelationship rel); + void objRelationshipRemoved(ObjRelationship rel); } http://git-wip-us.apache.org/repos/asf/cayenne/blob/a811b44e/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DbMergerTest.java ---------------------------------------------------------------------- diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DbMergerTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DbMergerTest.java index ea6be7d..62aa013 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DbMergerTest.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DbMergerTest.java @@ -20,7 +20,6 @@ package org.apache.cayenne.dbsync.merge; import org.apache.cayenne.dbsync.merge.builders.DbEntityBuilder; import org.apache.cayenne.dbsync.merge.factory.HSQLMergerTokenFactory; -import org.apache.cayenne.dbsync.reverse.db.DbLoaderConfiguration; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.map.DbEntity; import org.junit.Test; @@ -37,8 +36,7 @@ public class DbMergerTest { @Test public void testEmptyDataMap() throws Exception { - assertEquals(0, dbMerger().createMergeTokens(new ArrayList<DbEntity>(0), - new ArrayList<DbEntity>(0), new DbLoaderConfiguration()).size()); + assertEquals(0, dbMerger().createMergeTokens(new ArrayList<DbEntity>(0), new ArrayList<DbEntity>(0)).size()); } @Test @@ -49,8 +47,7 @@ public class DbMergerTest { ); DataMap existing = dataMap().with(dbEntity).build(); - List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(), - new ArrayList<DbEntity>(0), new DbLoaderConfiguration()); + List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(), new ArrayList<DbEntity>(0)); assertEquals(1, tokens.size()); assertEquals(factory().createCreateTableToDb(dbEntity.build()).getTokenValue(), @@ -64,8 +61,7 @@ public class DbMergerTest { dbAttr("attr01").typeInt() )).build(); - List<MergerToken> tokens = dbMerger().createMergeTokens(new ArrayList<DbEntity>(0), - db.getDbEntities(), new DbLoaderConfiguration()); + List<MergerToken> tokens = dbMerger().createMergeTokens(new ArrayList<DbEntity>(0), db.getDbEntities()); assertEquals(1, tokens.size()); assertEquals(factory().createDropTableToDb(db.getDbEntity("table1")).getTokenValue(), @@ -85,8 +81,7 @@ public class DbMergerTest { dbAttr("attr01").typeInt() )).build(); - List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(), - db.getDbEntities(), new DbLoaderConfiguration()); + List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(), db.getDbEntities()); assertEquals(1, tokens.size()); @@ -120,8 +115,7 @@ public class DbMergerTest { .build(); - List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(), - db.getDbEntities(), new DbLoaderConfiguration()); + List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(), db.getDbEntities()); assertEquals(1, tokens.size()); @@ -159,8 +153,7 @@ public class DbMergerTest { .build(); - List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(), - db.getDbEntities(), new DbLoaderConfiguration()); + List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(), db.getDbEntities()); assertEquals(2, tokens.size()); @@ -198,7 +191,7 @@ public class DbMergerTest { .build(); - List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(), db.getDbEntities(), new DbLoaderConfiguration()); + List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(), db.getDbEntities()); assertEquals(1, tokens.size()); @@ -220,8 +213,7 @@ public class DbMergerTest { dbAttr("attr02").typeInt() )).build(); - List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(), - db.getDbEntities(), new DbLoaderConfiguration()); + List<MergerToken> tokens = dbMerger().createMergeTokens(existing.getDbEntities(), db.getDbEntities()); assertEquals(1, tokens.size()); @@ -247,12 +239,11 @@ public class DbMergerTest { )).build(); - assertEquals(0, dbMerger().createMergeTokens(dataMap1.getDbEntities(), - dataMap2.getDbEntities(), new DbLoaderConfiguration()).size()); + assertEquals(0, dbMerger().createMergeTokens(dataMap1.getDbEntities(), dataMap2.getDbEntities()).size()); } private DbMerger dbMerger() { - return new DbMerger(factory(), new EmptyValueForNullProvider()); + return DbMerger.build(factory()); } private HSQLMergerTokenFactory factory() { http://git-wip-us.apache.org/repos/asf/cayenne/blob/a811b44e/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java ---------------------------------------------------------------------- diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java index 7706c2f..afdcb01 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java @@ -95,22 +95,21 @@ public abstract class MergeCase extends DbSyncCase { assertTokensAndExecute(0, 0); } - protected DbMerger createMerger() { - return createMerger(null); - } - - protected DbMerger createMerger(ValueForNullProvider valueForNullProvider) { - return new DbMerger(mergerFactory(), valueForNullProvider); + protected DbMerger.Builder merger() { + return DbMerger.builder(mergerFactory()); } protected List<MergerToken> createMergeTokens() { + + FiltersConfig filters = FiltersConfig.create(null, null, + TableFilter.include("ARTIST|GALLERY|PAINTING|NEW_TABLE2?"), PatternFilter.INCLUDE_NOTHING); + DbLoaderConfiguration loaderConfiguration = new DbLoaderConfiguration(); - loaderConfiguration.setFiltersConfig(FiltersConfig.create(null, null, - TableFilter.include("ARTIST|GALLERY|PAINTING|NEW_TABLE2?"), PatternFilter.INCLUDE_NOTHING)); + loaderConfiguration.setFiltersConfig(filters); DataMap dbImport; try (Connection conn = node.getDataSource().getConnection();) { - dbImport = new DbLoader(conn, + dbImport = new DbLoader(conn, node.getAdapter(), new LoggingDbLoaderDelegate(LogFactory.getLog(DbLoader.class)), new EntityMergeSupport(new DefaultObjectNameGenerator(), true, true)) @@ -120,7 +119,7 @@ public abstract class MergeCase extends DbSyncCase { throw new CayenneRuntimeException("Can't doLoad dataMap from db.", e); } - return createMerger().createMergeTokens(map, dbImport, loaderConfiguration); + return merger().filters(filters).build().createMergeTokens(map, dbImport); } /** http://git-wip-us.apache.org/repos/asf/cayenne/blob/a811b44e/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/ValueForNullIT.java ---------------------------------------------------------------------- diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/ValueForNullIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/ValueForNullIT.java index e9910fd..c88b601 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/ValueForNullIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/ValueForNullIT.java @@ -42,86 +42,85 @@ import static org.junit.Assert.assertTrue; public class ValueForNullIT extends MergeCase { - private static final String DEFAULT_VALUE_STRING = "DEFSTRING"; - - @Inject - private DataContext context; - - @Test - public void test() throws Exception { - DbEntity dbEntity = map.getDbEntity("PAINTING"); - assertNotNull(dbEntity); - ObjEntity objEntity = map.getObjEntity("Painting"); - assertNotNull(objEntity); - - // insert some rows before adding "not null" column - final int nrows = 10; - for (int i = 0; i < nrows; i++) { - DataObject o = (DataObject) context.newObject("Painting"); - o.writeProperty("paintingTitle", "ptitle" + i); - } - context.commitChanges(); - - // create and add new column to model and db - DbAttribute column = new DbAttribute("NEWCOL2", Types.VARCHAR, dbEntity); - - column.setMandatory(false); - column.setMaxLength(10); - dbEntity.addAttribute(column); - assertTrue(dbEntity.getAttributes().contains(column)); - assertEquals(column, dbEntity.getAttribute(column.getName())); - assertTokensAndExecute(1, 0); - - // need obj attr to be able to query - ObjAttribute objAttr = new ObjAttribute("newcol2"); - objAttr.setDbAttributePath(column.getName()); - objEntity.addAttribute(objAttr); - - // check that is was merged - assertTokensAndExecute(0, 0); - - // set not null - column.setMandatory(true); - - // merge to db - assertTokensAndExecute(2, 0); - - // check that is was merged - assertTokensAndExecute(0, 0); - - // check values for null - Expression qual = ExpressionFactory.matchExp(objAttr.getName(), DEFAULT_VALUE_STRING); - SelectQuery query = new SelectQuery("Painting", qual); - List<Persistent> rows = context.performQuery(query); - assertEquals(nrows, rows.size()); - - // clean up - dbEntity.removeAttribute(column.getName()); - assertTokensAndExecute(1, 0); - assertTokensAndExecute(0, 0); - } - - @Override - protected DbMerger createMerger(final ValueForNullProvider valueForNullProvider) { - return super.createMerger(new DefaultValueForNullProvider() { - - @Override - protected SQLParameterBinding get(DbEntity entity, DbAttribute column) { - int type = column.getType(); - switch (type) { - case Types.VARCHAR: - return new SQLParameterBinding(DEFAULT_VALUE_STRING, type, -1); - default: - throw new AssertionFailedError("should not get here"); - } - } - - @Override - public boolean hasValueFor(DbEntity entity, DbAttribute column) { - return true; - } - - }); - } + private static final String DEFAULT_VALUE_STRING = "DEFSTRING"; + + @Inject + private DataContext context; + + @Test + public void test() throws Exception { + DbEntity dbEntity = map.getDbEntity("PAINTING"); + assertNotNull(dbEntity); + ObjEntity objEntity = map.getObjEntity("Painting"); + assertNotNull(objEntity); + + // insert some rows before adding "not null" column + final int nrows = 10; + for (int i = 0; i < nrows; i++) { + DataObject o = (DataObject) context.newObject("Painting"); + o.writeProperty("paintingTitle", "ptitle" + i); + } + context.commitChanges(); + + // create and add new column to model and db + DbAttribute column = new DbAttribute("NEWCOL2", Types.VARCHAR, dbEntity); + + column.setMandatory(false); + column.setMaxLength(10); + dbEntity.addAttribute(column); + assertTrue(dbEntity.getAttributes().contains(column)); + assertEquals(column, dbEntity.getAttribute(column.getName())); + assertTokensAndExecute(1, 0); + + // need obj attr to be able to query + ObjAttribute objAttr = new ObjAttribute("newcol2"); + objAttr.setDbAttributePath(column.getName()); + objEntity.addAttribute(objAttr); + + // check that is was merged + assertTokensAndExecute(0, 0); + + // set not null + column.setMandatory(true); + + // merge to db + assertTokensAndExecute(2, 0); + + // check that is was merged + assertTokensAndExecute(0, 0); + + // check values for null + Expression qual = ExpressionFactory.matchExp(objAttr.getName(), DEFAULT_VALUE_STRING); + SelectQuery query = new SelectQuery("Painting", qual); + List<Persistent> rows = context.performQuery(query); + assertEquals(nrows, rows.size()); + + // clean up + dbEntity.removeAttribute(column.getName()); + assertTokensAndExecute(1, 0); + assertTokensAndExecute(0, 0); + } + + @Override + protected DbMerger.Builder merger() { + return super.merger().valueForNullProvider(new DefaultValueForNullProvider() { + + @Override + protected SQLParameterBinding get(DbEntity entity, DbAttribute column) { + int type = column.getType(); + switch (type) { + case Types.VARCHAR: + return new SQLParameterBinding(DEFAULT_VALUE_STRING, type, -1); + default: + throw new AssertionFailedError("should not get here"); + } + } + + @Override + public boolean hasValueFor(DbEntity entity, DbAttribute column) { + return true; + } + }); + } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/a811b44e/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 c371ee6..eda833c 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 @@ -22,10 +22,11 @@ import org.apache.cayenne.CayenneRuntimeException; import org.apache.cayenne.configuration.DataNodeDescriptor; import org.apache.cayenne.conn.DataSourceInfo; import org.apache.cayenne.dba.DbAdapter; -import org.apache.cayenne.dbsync.merge.DbMergerConfig; import org.apache.cayenne.dbsync.merge.DefaultModelMergeDelegate; import org.apache.cayenne.dbsync.merge.EntityMergeSupport; import org.apache.cayenne.dbsync.merge.ModelMergeDelegate; +import org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator; +import org.apache.cayenne.dbsync.naming.ObjectNameGenerator; import org.apache.cayenne.dbsync.reverse.NameFilter; import org.apache.cayenne.dbsync.reverse.NamePatternMatcher; import org.apache.cayenne.dbsync.reverse.db.DbLoader; @@ -35,8 +36,6 @@ import org.apache.cayenne.dbsync.reverse.db.DefaultDbLoaderDelegate; import org.apache.cayenne.dbsync.reverse.db.LoggingDbLoaderDelegate; import org.apache.cayenne.dbsync.reverse.filters.CatalogFilter; import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig; -import org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator; -import org.apache.cayenne.dbsync.naming.ObjectNameGenerator; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.map.DbEntity; import org.apache.cayenne.map.EntityResolver; @@ -49,7 +48,6 @@ import java.net.MalformedURLException; import java.sql.Connection; import java.util.Collections; - /** * @since 4.0 */ @@ -314,12 +312,4 @@ public class DbImportConfiguration { public void setTableTypes(String[] tableTypes) { dbLoaderConfiguration.setTableTypes(tableTypes); } - - public DbMergerConfig getDbMergerConfig() { - return new DbMergerConfig( - getDbLoaderConfig().getFiltersConfig(), - getDbLoaderConfig().getSkipRelationshipsLoading(), - getDbLoaderConfig().getSkipPrimaryKeyLoading() - ); - } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/a811b44e/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 fd40673..9118d34 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 @@ -26,15 +26,15 @@ import org.apache.cayenne.dba.DbAdapter; import org.apache.cayenne.dbsync.merge.AbstractToModelToken; import org.apache.cayenne.dbsync.merge.AddRelationshipToDb; import org.apache.cayenne.dbsync.merge.DbMerger; -import org.apache.cayenne.dbsync.merge.EmptyValueForNullProvider; import org.apache.cayenne.dbsync.merge.MergerContext; -import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider; import org.apache.cayenne.dbsync.merge.MergerToken; import org.apache.cayenne.dbsync.merge.ModelMergeDelegate; import org.apache.cayenne.dbsync.merge.ProxyModelMergeDelegate; import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory; -import org.apache.cayenne.dbsync.reverse.db.DbLoader; +import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider; import org.apache.cayenne.dbsync.naming.ObjectNameGenerator; +import org.apache.cayenne.dbsync.reverse.db.DbLoader; +import org.apache.cayenne.dbsync.reverse.db.DbLoaderConfiguration; import org.apache.cayenne.di.Inject; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.map.EntityResolver; @@ -144,8 +144,14 @@ public class DefaultDbImportAction implements DbImportAction { } else { MergerTokenFactory mergerTokenFactory = mergerTokenFactoryProvider.get(adapter); - List<MergerToken> mergeTokens = new DbMerger(mergerTokenFactory, new EmptyValueForNullProvider()) - .createMergeTokens(existing, loadedFomDb, config.getDbLoaderConfig()); + DbLoaderConfiguration loaderConfig = config.getDbLoaderConfig(); + List<MergerToken> mergeTokens = DbMerger.builder(mergerTokenFactory) + .filters(loaderConfig.getFiltersConfig()) + .skipPKTokens(loaderConfig.isSkipPrimaryKeyLoading()) + .skipRelationshipsTokens(loaderConfig.isSkipRelationshipsLoading()) + .build() + .createMergeTokens(existing, loadedFomDb); + if (mergeTokens.isEmpty()) { logger.info(""); logger.info("Detected changes: No changes to import."); http://git-wip-us.apache.org/repos/asf/cayenne/blob/a811b44e/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java ---------------------------------------------------------------------- diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java index b00aed8..41a9e43 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/MergerOptions.java @@ -25,7 +25,6 @@ import org.apache.cayenne.configuration.DataNodeDescriptor; import org.apache.cayenne.dba.JdbcAdapter; import org.apache.cayenne.dbsync.merge.AbstractToDbToken; import org.apache.cayenne.dbsync.merge.DbMerger; -import org.apache.cayenne.dbsync.merge.EmptyValueForNullProvider; import org.apache.cayenne.dbsync.merge.EntityMergeSupport; import org.apache.cayenne.dbsync.merge.MergeDirection; import org.apache.cayenne.dbsync.merge.MergerContext; @@ -165,12 +164,18 @@ public class MergerOptions extends CayenneController { adapter = (JdbcAdapter) connectionInfo.makeAdapter(getApplication().getClassLoadingService()); MergerTokenFactory mergerTokenFactory = mergerTokenFactoryProvider.get(adapter); - tokens.setMergerTokenFactory(mergerTokenFactory); - DbMerger merger = new DbMerger(mergerTokenFactory, new EmptyValueForNullProvider()); + + + FiltersConfig filters = FiltersConfig.create(null, defaultSchema, TableFilter.everything(), + PatternFilter.INCLUDE_NOTHING); + + DbMerger merger = DbMerger.builder(mergerTokenFactory) + .filters(filters) + .build(); DbLoaderConfiguration config = new DbLoaderConfiguration(); - config.setFiltersConfig(FiltersConfig.create(null, defaultSchema, TableFilter.everything(), PatternFilter.INCLUDE_NOTHING)); + config.setFiltersConfig(filters); DataSource dataSource = connectionInfo.makeDataSource(getApplication().getClassLoadingService()); @@ -186,7 +191,7 @@ public class MergerOptions extends CayenneController { throw new CayenneRuntimeException("Can't doLoad dataMap from db.", e); } - tokens.setTokens(merger.createMergeTokens(dataMap, dbImport, config)); + tokens.setTokens(merger.createMergeTokens(dataMap, dbImport)); } catch (Exception ex) { reportError("Error loading adapter", ex); }