Repository: cayenne Updated Branches: refs/heads/master 28f24e37d -> 3e3f0f5f6
fix cdbimport relationships loading Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/78bacdc6 Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/78bacdc6 Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/78bacdc6 Branch: refs/heads/master Commit: 78bacdc661fd1a76825d3b654e49ab0785e3cc0f Parents: 667331f Author: kolonitsky <alex.kolonit...@gmail.com> Authored: Tue Feb 10 01:55:04 2015 +0300 Committer: kolonitsky <alex.kolonit...@gmail.com> Committed: Tue Feb 10 01:55:04 2015 +0300 ---------------------------------------------------------------------- .../loader/ManyToManyCandidateEntity.java | 6 +- .../org/apache/cayenne/map/ObjRelationship.java | 2 + .../cayenne/merge/AddRelationshipToDb.java | 8 +- .../cayenne/merge/AddRelationshipToModel.java | 38 ++++++- .../cayenne/merge/DropRelationshipToDb.java | 2 +- .../cayenne/merge/DropRelationshipToModel.java | 4 +- .../cayenne/merge/ProxyModelMergeDelegate.java | 108 +++++++++++++++++++ .../merge/builders/DbAttributeBuilder.java | 4 + .../cayenne/tools/dbimport/DbImportAction.java | 85 ++++++++++----- .../tools/dbimport/DbImportActionTest.java | 30 ++++++ 10 files changed, 248 insertions(+), 39 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cayenne/blob/78bacdc6/cayenne-server/src/main/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntity.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntity.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntity.java index e51d936..b1d96f9 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntity.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntity.java @@ -88,9 +88,9 @@ public class ManyToManyCandidateEntity { boolean isNotHaveAttributes = joinEntity.getAttributes().size() == 0; return isNotHaveAttributes - && reverseRelationship1.isToDependentPK() - && reverseRelationship2.isToDependentPK() - && !entity1.equals(entity2); + && reverseRelationship1 != null && reverseRelationship1.isToDependentPK() + && reverseRelationship2 != null && reverseRelationship2.isToDependentPK() + && entity1 != null && entity2 != null && !entity1.equals(entity2); } private void addFlattenedRelationship(ObjectNameGenerator nameGenerator, ObjEntity srcEntity, ObjEntity dstEntity, http://git-wip-us.apache.org/repos/asf/cayenne/blob/78bacdc6/cayenne-server/src/main/java/org/apache/cayenne/map/ObjRelationship.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/ObjRelationship.java b/cayenne-server/src/main/java/org/apache/cayenne/map/ObjRelationship.java index adcbb69..1e99f51 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/map/ObjRelationship.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/map/ObjRelationship.java @@ -725,6 +725,8 @@ public class ObjRelationship extends Relationship implements ConfigurationNode { @Override public String toString() { return new ToStringBuilder(this).append("name", getName()) + .append("sourceEntityName", getSourceEntity().getName()) + .append("targetEntityName", getTargetEntityName()) .append("dbRelationshipPath", getDbRelationshipPath()).toString(); } http://git-wip-us.apache.org/repos/asf/cayenne/blob/78bacdc6/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToDb.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToDb.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToDb.java index d39d4df..dbd65d8 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToDb.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToDb.java @@ -31,7 +31,7 @@ public class AddRelationshipToDb extends AbstractToDbToken.Entity { private DbRelationship rel; public AddRelationshipToDb(DbEntity entity, DbRelationship rel) { - super("Add Relationship", entity); + super("Add foreign key", entity); this.rel = rel; } @@ -63,7 +63,11 @@ public class AddRelationshipToDb extends AbstractToDbToken.Entity { @Override public String getTokenValue() { - return rel.getSourceEntity().getName() + "->" + rel.getTargetEntityName(); + if (this.shouldGenerateFkConstraint()) { + return rel.getSourceEntity().getName() + "->" + rel.getTargetEntityName(); + } else { + return "Skip. No sql representation."; + } } public DbRelationship getRelationship() { http://git-wip-us.apache.org/repos/asf/cayenne/blob/78bacdc6/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToModel.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToModel.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToModel.java index 78d7e8a..5e05b52 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToModel.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/merge/AddRelationshipToModel.java @@ -19,10 +19,15 @@ package org.apache.cayenne.merge; import org.apache.cayenne.map.DbEntity; +import org.apache.cayenne.map.DbJoin; import org.apache.cayenne.map.DbRelationship; +import static org.apache.cayenne.util.Util.join; + public class AddRelationshipToModel extends AbstractToModelToken.Entity { + public static final String COMMA_SEPARATOR = ", "; + public static final int COMMA_SEPARATOR_LENGTH = COMMA_SEPARATOR.length(); private DbRelationship rel; public AddRelationshipToModel(DbEntity entity, DbRelationship rel) { @@ -43,11 +48,40 @@ public class AddRelationshipToModel extends AbstractToModelToken.Entity { @Override public String getTokenValue() { - return rel.getSourceEntity().getName() + "->" + rel.getTargetEntityName(); + String attributes = ""; + if (rel.getJoins().size() == 1) { + attributes = rel.getJoins().get(0).getTargetName(); + } else { + for (DbJoin dbJoin : rel.getJoins()) { + attributes += dbJoin.getTargetName() + COMMA_SEPARATOR; + } + + attributes = "{" + attributes.substring(0, attributes.length() - COMMA_SEPARATOR_LENGTH) + "}"; + } + + return rel.getName() + " " + rel.getSourceEntity().getName() + "->" + rel.getTargetEntityName() + "." + attributes; } - + + + public static String getTokenValue(DbRelationship rel) { + String attributes = ""; + if (rel.getJoins().size() == 1) { + attributes = rel.getJoins().get(0).getTargetName(); + } else { + for (DbJoin dbJoin : rel.getJoins()) { + attributes += dbJoin.getTargetName() + COMMA_SEPARATOR; + } + + attributes = "{" + attributes.substring(0, attributes.length() - COMMA_SEPARATOR_LENGTH) + "}"; + } + + return rel.getName() + " " + rel.getSourceEntity().getName() + "->" + rel.getTargetEntityName() + "." + attributes; + } + public DbRelationship getRelationship() { return rel; } + + } http://git-wip-us.apache.org/repos/asf/cayenne/blob/78bacdc6/cayenne-server/src/main/java/org/apache/cayenne/merge/DropRelationshipToDb.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/DropRelationshipToDb.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/DropRelationshipToDb.java index 96f7687..618aab3 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/merge/DropRelationshipToDb.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/merge/DropRelationshipToDb.java @@ -32,7 +32,7 @@ public class DropRelationshipToDb extends AbstractToDbToken.Entity { private DbRelationship rel; public DropRelationshipToDb(DbEntity entity, DbRelationship rel) { - super("Drop Relationship", entity); + super("Drop foreign key", entity); this.rel = rel; } http://git-wip-us.apache.org/repos/asf/cayenne/blob/78bacdc6/cayenne-server/src/main/java/org/apache/cayenne/merge/DropRelationshipToModel.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/DropRelationshipToModel.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/DropRelationshipToModel.java index 95ccd15..ee9359f 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/merge/DropRelationshipToModel.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/merge/DropRelationshipToModel.java @@ -26,7 +26,7 @@ public class DropRelationshipToModel extends AbstractToModelToken.Entity { private final DbRelationship rel; public DropRelationshipToModel(DbEntity entity, DbRelationship rel) { - super("Drop Relationship", entity); + super("Drop db-relationship ", entity); this.rel = rel; } @@ -40,7 +40,7 @@ public class DropRelationshipToModel extends AbstractToModelToken.Entity { @Override public String getTokenValue() { - return rel.getSourceEntity().getName() + "->" + rel.getTargetEntityName(); + return AddRelationshipToModel.getTokenValue(rel); } public DbRelationship getRelationship() { http://git-wip-us.apache.org/repos/asf/cayenne/blob/78bacdc6/cayenne-server/src/main/java/org/apache/cayenne/merge/ProxyModelMergeDelegate.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/ProxyModelMergeDelegate.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/ProxyModelMergeDelegate.java new file mode 100644 index 0000000..ad6a4a9 --- /dev/null +++ b/cayenne-server/src/main/java/org/apache/cayenne/merge/ProxyModelMergeDelegate.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cayenne.merge; + +import org.apache.cayenne.map.DbAttribute; +import org.apache.cayenne.map.DbEntity; +import org.apache.cayenne.map.DbRelationship; +import org.apache.cayenne.map.ObjAttribute; +import org.apache.cayenne.map.ObjEntity; +import org.apache.cayenne.map.ObjRelationship; + +/** + * @since 4.0 + */ +public class ProxyModelMergeDelegate implements ModelMergeDelegate { + + private final ModelMergeDelegate delegate; + + public ProxyModelMergeDelegate(ModelMergeDelegate delegate) { + this.delegate = delegate; + } + + @Override + public void dbEntityAdded(DbEntity ent) { + delegate.dbEntityAdded(ent); + } + + @Override + public void dbEntityRemoved(DbEntity ent) { + delegate.dbEntityRemoved(ent); + } + + @Override + public void objEntityAdded(ObjEntity ent) { + delegate.objEntityAdded(ent); + } + + @Override + public void objEntityRemoved(ObjEntity ent) { + delegate.objEntityRemoved(ent); + } + + @Override + public void dbAttributeAdded(DbAttribute att) { + delegate.dbAttributeAdded(att); + } + + @Override + public void dbAttributeRemoved(DbAttribute att) { + delegate.dbAttributeRemoved(att); + } + + @Override + public void dbAttributeModified(DbAttribute att) { + delegate.dbAttributeModified(att); + } + + @Override + public void objAttributeAdded(ObjAttribute att) { + delegate.objAttributeAdded(att); + } + + @Override + public void objAttributeRemoved(ObjAttribute att) { + delegate.objAttributeRemoved(att); + } + + @Override + public void objAttributeModified(ObjAttribute att) { + delegate.objAttributeModified(att); + } + + @Override + public void dbRelationshipAdded(DbRelationship rel) { + delegate.dbRelationshipAdded(rel); + } + + @Override + public void dbRelationshipRemoved(DbRelationship rel) { + delegate.dbRelationshipRemoved(rel); + } + + @Override + public void objRelationshipAdded(ObjRelationship rel) { + delegate.objRelationshipAdded(rel); + } + + @Override + public void objRelationshipRemoved(ObjRelationship rel) { + delegate.objRelationshipRemoved(rel); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/78bacdc6/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DbAttributeBuilder.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DbAttributeBuilder.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DbAttributeBuilder.java index 79be3ce..38f2b9b 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DbAttributeBuilder.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/merge/builders/DbAttributeBuilder.java @@ -56,6 +56,10 @@ public class DbAttributeBuilder extends DefaultBuilder<DbAttribute> { return type(TypesMapping.SQL_INTEGER); } + public DbAttributeBuilder typeBigInt() { + return type(TypesMapping.SQL_BIGINT); + } + public DbAttributeBuilder typeVarchar(int length) { type(TypesMapping.SQL_VARCHAR); length(length); http://git-wip-us.apache.org/repos/asf/cayenne/blob/78bacdc6/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java ---------------------------------------------------------------------- diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java index 1036221..fb55dd3 100644 --- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java +++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java @@ -7,23 +7,11 @@ import org.apache.cayenne.configuration.server.DataSourceFactory; import org.apache.cayenne.configuration.server.DbAdapterFactory; import org.apache.cayenne.dba.DbAdapter; import org.apache.cayenne.di.Inject; -import org.apache.cayenne.map.DataMap; -import org.apache.cayenne.map.DbEntity; -import org.apache.cayenne.map.EntityResolver; -import org.apache.cayenne.map.MapLoader; -import org.apache.cayenne.map.ObjEntity; -import org.apache.cayenne.map.naming.ObjectNameGenerator; -import org.apache.cayenne.merge.DbMerger; -import org.apache.cayenne.merge.DropTableToDb; -import org.apache.cayenne.merge.ExecutingMergerContext; -import org.apache.cayenne.merge.MergerContext; -import org.apache.cayenne.merge.MergerFactory; -import org.apache.cayenne.merge.MergerToken; -import org.apache.cayenne.merge.ModelMergeDelegate; +import org.apache.cayenne.map.*; +import org.apache.cayenne.merge.*; import org.apache.cayenne.project.Project; import org.apache.cayenne.project.ProjectSaver; import org.apache.cayenne.resource.URLResource; -import org.apache.cayenne.util.EntityMergeSupport; import org.apache.cayenne.validation.SimpleValidationFailure; import org.apache.cayenne.validation.ValidationFailure; import org.apache.cayenne.validation.ValidationResult; @@ -35,11 +23,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.sql.Connection; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; +import java.util.*; import static org.apache.commons.lang.StringUtils.isBlank; @@ -91,6 +75,11 @@ public class DbImportAction { DataMap existing = loadExistingDataMap(config.getDataMapFile()); if (existing == null) { + logger.info(""); + File file = config.getDataMapFile(); + logger.info("Map file does not exist. Loaded db model will be saved into '" + + (file == null ? "null" : file.getAbsolutePath() + "'")); + saveLoaded(config.initializeDataMap(loadedFomDb)); } else { MergerFactory mergerFactory = adapter.mergerFactory(); @@ -107,27 +96,62 @@ public class DbImportAction { existing.setDefaultPackage(config.getDefaultPackage()); } + final Collection<ObjEntity> loadedObjEntities = new LinkedList<ObjEntity>(); + DataMap executed = execute(new ProxyModelMergeDelegate(config.createMergeDelegate()) { + @Override + public void objEntityAdded(ObjEntity ent) { + loadedObjEntities.add(ent); + super.objEntityAdded(ent); + } - DataMap executed = execute(config.createMergeDelegate(), existing, log(reverse(mergerFactory, mergeTokens))); + }, existing, log(sort(reverse(mergerFactory, mergeTokens)))); - // TODO DbLoader shouldn't do by it self it should separate processor - ObjectNameGenerator nameGenerator = config.getNameGenerator(); - Collection<ObjEntity> loadedObjEntities = new LinkedList<ObjEntity>(); - for (MergerToken mergeToken : mergeTokens) { - if (mergeToken instanceof DropTableToDb) { - loadedObjEntities.addAll(executed.getMappedEntities(((DropTableToDb) mergeToken).getEntity())); - } - } + DbLoader.flattenManyToManyRelationships(executed, loadedObjEntities, config.getNameGenerator()); + + relationshipsSanity(executed); - DbLoader.flattenManyToManyRelationships(executed, loadedObjEntities, nameGenerator); saveLoaded(executed); } } + private void relationshipsSanity(DataMap executed) { + // obj relationships sanity + for (ObjEntity objEntity : executed.getObjEntities()) { + for (ObjRelationship objRelationship : objEntity.getRelationships()) { + if (objRelationship.getSourceEntity() == null + || objRelationship.getTargetEntity() == null) { + logger.error("Incorrect obj relationship: " + objRelationship); + objEntity.removeRelationship(objRelationship.getName()); + } + } + } + } + + protected static List<MergerToken> sort(List<MergerToken> reverse) { + Collections.sort(reverse, new Comparator<MergerToken>() { + @Override + public int compare(MergerToken o1, MergerToken o2) { + if (o1 instanceof AddRelationshipToDb + && o2 instanceof AddRelationshipToDb) { + return 0; + } + + return o1 instanceof AddRelationshipToDb ? 1 : -1; + } + }); + + return reverse; + } + private Collection<MergerToken> log(List<MergerToken> tokens) { logger.info(""); + if (tokens.isEmpty()) { + logger.info("Detected changes: No changes to import."); + return tokens; + } + logger.info("Detected changes: "); for (MergerToken token : tokens) { logger.info(String.format(" %-20s %s", token.getTokenName(), token.getTokenValue())); @@ -152,6 +176,9 @@ public class DbImportAction { private List<MergerToken> reverse(MergerFactory mergerFactory, Iterable<MergerToken> mergeTokens) throws IOException { List<MergerToken> tokens = new LinkedList<MergerToken>(); for (MergerToken token : mergeTokens) { + if (token instanceof AbstractToModelToken) { + continue; + } tokens.add(token.createReverse(mergerFactory)); } return tokens; http://git-wip-us.apache.org/repos/asf/cayenne/blob/78bacdc6/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportActionTest.java ---------------------------------------------------------------------- diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportActionTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportActionTest.java index a2fb0f1..9e39c28 100644 --- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportActionTest.java +++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportActionTest.java @@ -18,6 +18,7 @@ */ package org.apache.cayenne.tools.dbimport; +import static java.util.Arrays.asList; import static org.apache.cayenne.merge.builders.ObjectMother.dbAttr; import static org.apache.cayenne.merge.builders.ObjectMother.dbEntity; import static org.apache.cayenne.merge.builders.ObjectMother.objAttr; @@ -41,6 +42,9 @@ import java.io.File; import java.net.URL; import java.sql.Connection; import java.sql.SQLException; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; import javax.sql.DataSource; @@ -57,14 +61,20 @@ import org.apache.cayenne.di.Injector; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.map.DbEntity; import org.apache.cayenne.map.MapLoader; +import org.apache.cayenne.merge.AddColumnToDb; +import org.apache.cayenne.merge.AddRelationshipToDb; +import org.apache.cayenne.merge.CreateTableToDb; +import org.apache.cayenne.merge.CreateTableToModel; import org.apache.cayenne.merge.DefaultModelMergeDelegate; import org.apache.cayenne.merge.MergerFactory; +import org.apache.cayenne.merge.MergerToken; import org.apache.cayenne.merge.builders.DataMapBuilder; import org.apache.cayenne.project.FileProjectSaver; import org.apache.cayenne.project.Project; import org.apache.cayenne.resource.URLResource; import org.apache.cayenne.tools.configuration.ToolsModule; import org.apache.cayenne.util.Util; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.junit.Test; import org.xml.sax.InputSource; @@ -318,4 +328,24 @@ public class DbImportActionTest { 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)); + + assertEquals(asList("CreateTableToModel", "CreateTableToDb", "AddColumnToDb", "AddRelationshipToDb"), + toClasses(DbImportAction.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; + } }