You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2016/09/28 15:04:49 UTC

[2/2] cayenne git commit: CAY-2113 cdbimport: Reverse-engineering reinstates previously ignored columns

CAY-2113 cdbimport: Reverse-engineering reinstates previously ignored columns

* fixing...


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/f7f33b55
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/f7f33b55
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/f7f33b55

Branch: refs/heads/master
Commit: f7f33b5570dc704d88322e2ac08bda677050a174
Parents: d58f722
Author: Andrus Adamchik <an...@objectstyle.com>
Authored: Wed Sep 28 16:45:56 2016 +0300
Committer: Andrus Adamchik <an...@objectstyle.com>
Committed: Wed Sep 28 18:02:35 2016 +0300

----------------------------------------------------------------------
 .../cayenne/merge/AbstractToModelToken.java     |   7 -
 .../apache/cayenne/merge/AddColumnToModel.java  |  10 +-
 .../cayenne/merge/AddRelationshipToModel.java   |  14 +-
 .../cayenne/merge/CreateTableToModel.java       |  10 +-
 .../apache/cayenne/util/EntityMergeSupport.java | 277 +++++++++++--------
 docs/doc/src/main/resources/RELEASE-NOTES.txt   |   1 +
 6 files changed, 186 insertions(+), 133 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/f7f33b55/cayenne-server/src/main/java/org/apache/cayenne/merge/AbstractToModelToken.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/AbstractToModelToken.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/AbstractToModelToken.java
index e2ca05f..49b680b 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/AbstractToModelToken.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/merge/AbstractToModelToken.java
@@ -23,7 +23,6 @@ import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbRelationship;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.ObjRelationship;
-import org.apache.cayenne.util.EntityMergeSupport;
 
 /**
  * Common abstract superclass for all {@link MergerToken}s going from the database to the
@@ -47,12 +46,6 @@ public abstract class AbstractToModelToken implements MergerToken {
         return MergeDirection.TO_MODEL;
     }
 
-    protected void synchronizeWithObjEntity(DbEntity entity) {
-        for (ObjEntity objEntity : entity.mappedObjEntities()) {
-            new EntityMergeSupport(objEntity.getDataMap()).synchronizeWithDbEntity(objEntity);
-        }
-    }
-
     protected static void remove(ModelMergeDelegate mergerContext, DbRelationship rel, boolean reverse) {
         if (rel == null) {
             return;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f7f33b55/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToModel.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToModel.java
index 283241c..9e96928 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToModel.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/merge/AddColumnToModel.java
@@ -40,7 +40,15 @@ public class AddColumnToModel extends AbstractToModelToken.EntityAndColumn {
 
     public void execute(MergerContext mergerContext) {
         getEntity().addAttribute(getColumn());
-        synchronizeWithObjEntity(getEntity());
+
+        // TODO: use EntityMergeSupport from DbImportConfiguration... otherwise we are ignoring a bunch of
+        // important settings
+
+        EntityMergeSupport entityMergeSupport =  new EntityMergeSupport(mergerContext.getDataMap());
+        for(ObjEntity e : getEntity().mappedObjEntities()) {
+            entityMergeSupport.synchronizeOnDbAttributeAdded(e, getColumn());
+        }
+
         mergerContext.getModelMergeDelegate().dbAttributeAdded(getColumn());
     }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f7f33b55/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 5e05b52..42d7329 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
@@ -21,8 +21,8 @@ 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;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.util.EntityMergeSupport;
 
 public class AddRelationshipToModel extends AbstractToModelToken.Entity {
 
@@ -42,7 +42,15 @@ public class AddRelationshipToModel extends AbstractToModelToken.Entity {
     public void execute(MergerContext mergerContext) {
         getEntity().addRelationship(rel);
         // TODO: add reverse relationship as well if it does not exist
-        synchronizeWithObjEntity(getEntity());
+
+        // TODO: use EntityMergeSupport from DbImportConfiguration... otherwise we are ignoring a bunch of
+        // important settings
+
+        EntityMergeSupport entityMergeSupport =  new EntityMergeSupport(mergerContext.getDataMap());
+        for(ObjEntity e : getEntity().mappedObjEntities()) {
+            entityMergeSupport.synchronizeOnDbRelationshipAdded(e, rel);
+        }
+
         mergerContext.getModelMergeDelegate().dbRelationshipAdded(rel);
     }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f7f33b55/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToModel.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToModel.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToModel.java
index 61a266a..cdd6009 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToModel.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/merge/CreateTableToModel.java
@@ -22,7 +22,7 @@ import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.naming.NameConverter;
-import org.apache.cayenne.util.Util;
+import org.apache.cayenne.util.EntityMergeSupport;
 
 /**
  * A {@link MergerToken} to add a {@link DbEntity} to a {@link DataMap}
@@ -85,8 +85,12 @@ public class CreateTableToModel extends AbstractToModelToken.Entity {
         
         map.addObjEntity(objEntity);
 
-        synchronizeWithObjEntity(getEntity());
-        
+        // presumably there are no other ObjEntities pointing to this DbEntity, so syncing just this one...
+
+        // TODO: use EntityMergeSupport from DbImportConfiguration... otherwise we are ignoring a bunch of
+        // important settings
+        new EntityMergeSupport(map).synchronizeWithDbEntity(objEntity);
+
         mergerContext.getModelMergeDelegate().dbEntityAdded(getEntity());
         mergerContext.getModelMergeDelegate().objEntityAdded(objEntity);
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f7f33b55/cayenne-server/src/main/java/org/apache/cayenne/util/EntityMergeSupport.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/util/EntityMergeSupport.java b/cayenne-server/src/main/java/org/apache/cayenne/util/EntityMergeSupport.java
index 5bcccce..7c12600 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/util/EntityMergeSupport.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/util/EntityMergeSupport.java
@@ -19,13 +19,6 @@
 
 package org.apache.cayenne.util;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
 import org.apache.cayenne.dba.TypesMapping;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.map.DbAttribute;
@@ -36,13 +29,20 @@ import org.apache.cayenne.map.Entity;
 import org.apache.cayenne.map.ObjAttribute;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.map.ObjRelationship;
-import org.apache.cayenne.map.naming.LegacyNameGenerator;
 import org.apache.cayenne.map.naming.DefaultUniqueNameGenerator;
+import org.apache.cayenne.map.naming.LegacyNameGenerator;
 import org.apache.cayenne.map.naming.NameCheckers;
 import org.apache.cayenne.map.naming.ObjectNameGenerator;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
 /**
  * Implements methods for entity merging.
  */
@@ -64,20 +64,17 @@ public class EntityMergeSupport {
     }
 
     private final DataMap map;
-
-    protected boolean removeMeaningfulFKs;
-    protected boolean removeMeaningfulPKs;
-    protected boolean usePrimitives;
-
     /**
      * Strategy for choosing names for entities, attributes and relationships
      */
     private final ObjectNameGenerator nameGenerator;
-
     /**
      * Listeners of merge process.
      */
     private final List<EntityMergeListener> listeners = new ArrayList<EntityMergeListener>();
+    protected boolean removeMeaningfulFKs;
+    protected boolean removeMeaningfulPKs;
+    protected boolean usePrimitives;
 
     public EntityMergeSupport(DataMap map) {
         this(map, new LegacyNameGenerator(), true);
@@ -102,7 +99,7 @@ public class EntityMergeSupport {
     /**
      * 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.
      */
@@ -134,7 +131,7 @@ public class EntityMergeSupport {
     /**
      * Updates ObjEntity attributes and relationships based on the current state
      * of its DbEntity.
-     * 
+     *
      * @return true if the ObjEntity has changed as a result of synchronization.
      */
     public boolean synchronizeWithDbEntity(ObjEntity entity) {
@@ -165,6 +162,32 @@ public class EntityMergeSupport {
         return changed;
     }
 
+    /**
+     * @since 4.0
+     */
+    public boolean synchronizeOnDbAttributeAdded(ObjEntity entity, DbAttribute dbAttribute) {
+
+        Collection<DbRelationship> incomingRels = getIncomingRelationships(dbAttribute.getEntity());
+        if (isMissingFromObjEntity(entity, dbAttribute, incomingRels)) {
+            addMissingAttribute(entity, dbAttribute);
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * @since 4.0
+     */
+    public boolean synchronizeOnDbRelationshipAdded(ObjEntity entity, DbRelationship dbRelationship) {
+
+        if (isMissingFromObjEntity(entity, dbRelationship)) {
+            addMissingRelationship(entity, dbRelationship);
+        }
+
+        return true;
+    }
+
     private boolean addMissingRelationships(ObjEntity entity) {
         List<DbRelationship> relationshipsToAdd = getRelationshipsToAdd(entity);
         if (relationshipsToAdd.isEmpty()) {
@@ -172,26 +195,9 @@ public class EntityMergeSupport {
         }
 
         for (DbRelationship dr : relationshipsToAdd) {
-            DbEntity targetEntity = dr.getTargetEntity();
-
-            Collection<ObjEntity> mappedObjEntities = map.getMappedEntities(targetEntity);
-            if (!mappedObjEntities.isEmpty()) {
-                for (Entity mappedTarget : mappedObjEntities) {
-                    createObjRelationship(entity, dr, mappedTarget.getName());
-                }
-            } else {
-                if (targetEntity == null) {
-                    targetEntity = new DbEntity(dr.getTargetEntityName());
-                }
-                if (dr.getTargetEntityName() != null) {
-                    boolean needGeneratedEntity = createObjRelationship(entity, dr, nameGenerator.createObjEntityName(targetEntity));
-                    if (needGeneratedEntity) {
-                        LOG.warn("Can't find ObjEntity for " + dr.getTargetEntityName());
-                        LOG.warn("Db Relationship (" + dr + ") will have GUESSED Obj Relationship reflection. ");
-                    }
-                }
-            }
+            addMissingRelationship(entity, dr);
         }
+
         return true;
     }
 
@@ -237,26 +243,55 @@ public class EntityMergeSupport {
 
     private boolean addMissingAttributes(ObjEntity entity) {
         boolean changed = false;
+
         for (DbAttribute da : getAttributesToAdd(entity)) {
+            addMissingAttribute(entity, da);
+            changed = true;
+        }
+        return changed;
+    }
 
-            String attrName = DefaultUniqueNameGenerator.generate(NameCheckers.objAttribute, entity,
-                    nameGenerator.createObjAttributeName(da));
+    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 {
 
-            String type = TypesMapping.getJavaBySqlType(da.getType());
-            if (usePrimitives) {
-                String primitive = CLASS_TO_PRIMITIVE.get(type);
-                if (primitive != null) {
-                    type = primitive;
+            if (targetEntity == null) {
+                targetEntity = new DbEntity(dbRelationship.getTargetEntityName());
+            }
+
+            if (dbRelationship.getTargetEntityName() != null) {
+                boolean needGeneratedEntity = createObjRelationship(entity, dbRelationship,
+                        nameGenerator.createObjEntityName(targetEntity));
+                if (needGeneratedEntity) {
+                    LOG.warn("Can't find ObjEntity for " + dbRelationship.getTargetEntityName());
+                    LOG.warn("Db Relationship (" + dbRelationship + ") will have GUESSED Obj Relationship reflection. ");
                 }
             }
+        }
+    }
 
-            ObjAttribute oa = new ObjAttribute(attrName, type, entity);
-            oa.setDbAttributePath(da.getName());
-            entity.addAttribute(oa);
-            fireAttributeAdded(oa);
-            changed = true;
+    private void addMissingAttribute(ObjEntity entity, DbAttribute da) {
+        String attrName = DefaultUniqueNameGenerator.generate(NameCheckers.objAttribute, entity,
+                nameGenerator.createObjAttributeName(da));
+
+        String type = TypesMapping.getJavaBySqlType(da.getType());
+        if (usePrimitives) {
+            String primitive = CLASS_TO_PRIMITIVE.get(type);
+            if (primitive != null) {
+                type = primitive;
+            }
         }
-        return changed;
+
+        ObjAttribute oa = new ObjAttribute(attrName, type, entity);
+        oa.setDbAttributePath(da.getName());
+        entity.addAttribute(oa);
+        fireAttributeAdded(oa);
     }
 
     private boolean getRidOfAttributesThatAreNowSrcAttributesForRelationships(ObjEntity entity) {
@@ -275,7 +310,7 @@ public class EntityMergeSupport {
 
     /**
      * Returns a list of DbAttributes that are mapped to foreign keys.
-     * 
+     *
      * @since 1.2
      */
     public Collection<DbAttribute> getMeaningfulFKs(ObjEntity objEntity) {
@@ -301,102 +336,106 @@ public class EntityMergeSupport {
         DbEntity dbEntity = objEntity.getDbEntity();
 
         List<DbAttribute> missing = new ArrayList<DbAttribute>();
-
-        Collection<DbRelationship> rels = dbEntity.getRelationships();
         Collection<DbRelationship> incomingRels = getIncomingRelationships(dbEntity);
 
         for (DbAttribute dba : dbEntity.getAttributes()) {
 
-            if (dba.getName() == null || objEntity.getAttributeForDbAttribute(dba) != null) {
-                continue;
+            if (isMissingFromObjEntity(objEntity, dba, incomingRels)) {
+                missing.add(dba);
             }
+        }
 
-            boolean removeMeaningfulPKs = removePK(dbEntity);
-            if (removeMeaningfulPKs && dba.isPrimaryKey()) {
-                continue;
-            }
+        return missing;
+    }
 
-            // check FK's
-            boolean isFK = false;
-            Iterator<DbRelationship> rit = rels.iterator();
-            while (!isFK && rit.hasNext()) {
-                DbRelationship rel = rit.next();
-                for (DbJoin join : rel.getJoins()) {
-                    if (join.getSource() == dba) {
-                        isFK = true;
-                        break;
-                    }
-                }
-            }
+    protected boolean isMissingFromObjEntity(ObjEntity entity, DbAttribute dbAttribute, Collection<DbRelationship> incomingRels) {
 
-            if (!removeMeaningfulPKs) {
-                if (!dba.isPrimaryKey() && isFK) {
-                    continue;
-                }
-            } else {
-                if (isFK) {
-                    continue;
+        if (dbAttribute.getName() == null || entity.getAttributeForDbAttribute(dbAttribute) != null) {
+            return false;
+        }
+
+        boolean removeMeaningfulPKs = removePK(dbAttribute.getEntity());
+        if (removeMeaningfulPKs && dbAttribute.isPrimaryKey()) {
+            return false;
+        }
+
+        // check FK's
+        boolean isFK = false;
+        Iterator<DbRelationship> rit = dbAttribute.getEntity().getRelationships().iterator();
+        while (!isFK && rit.hasNext()) {
+            DbRelationship rel = rit.next();
+            for (DbJoin join : rel.getJoins()) {
+                if (join.getSource() == dbAttribute) {
+                    isFK = true;
+                    break;
                 }
             }
+        }
 
-            // check incoming relationships
-            rit = incomingRels.iterator();
-            while (!isFK && rit.hasNext()) {
-                DbRelationship rel = rit.next();
-                for (DbJoin join : rel.getJoins()) {
-                    if (join.getTarget() == dba) {
-                        isFK = true;
-                        break;
-                    }
-                }
+        if (!removeMeaningfulPKs) {
+            if (!dbAttribute.isPrimaryKey() && isFK) {
+                return false;
             }
+        } else {
+            if (isFK) {
+                return false;
+            }
+        }
 
-            if (!removeMeaningfulPKs) {
-                if (!dba.isPrimaryKey() && isFK) {
-                    continue;
-                }
-            } else {
-                if (isFK) {
-                    continue;
+        // check incoming relationships
+        rit = incomingRels.iterator();
+        while (!isFK && rit.hasNext()) {
+            DbRelationship rel = rit.next();
+            for (DbJoin join : rel.getJoins()) {
+                if (join.getTarget() == dbAttribute) {
+                    isFK = true;
+                    break;
                 }
             }
+        }
 
-            missing.add(dba);
+        if (!removeMeaningfulPKs) {
+            if (!dbAttribute.isPrimaryKey() && isFK) {
+                return false;
+            }
+        } else {
+            if (isFK) {
+                return false;
+            }
         }
 
-        return missing;
+        return true;
     }
 
-	private Collection<DbRelationship> getIncomingRelationships(DbEntity entity) {
-		Collection<DbRelationship> incoming = new ArrayList<DbRelationship>();
+    protected boolean isMissingFromObjEntity(ObjEntity entity, DbRelationship dbRelationship) {
+        return dbRelationship.getName() != null && entity.getRelationshipForDbRelationship(dbRelationship) == null;
+    }
 
-		for (DbEntity nextEntity : entity.getDataMap().getDbEntities()) {
-			for (DbRelationship relationship : nextEntity.getRelationships()) {
+    private Collection<DbRelationship> getIncomingRelationships(DbEntity entity) {
+        Collection<DbRelationship> incoming = new ArrayList<DbRelationship>();
 
-				// TODO: PERFORMANCE 'getTargetEntity' is generally slow, called
-				// in this iterator it is showing (e.g. in YourKit profiles)..
-				// perhaps use cheaper 'getTargetEntityName()' or even better -
-				// pre-cache all relationships by target entity to avoid O(n)
-				// search ?
-				// (need to profile to prove the difference)
-				if (entity == relationship.getTargetEntity()) {
-					incoming.add(relationship);
-				}
-			}
-		}
+        for (DbEntity nextEntity : entity.getDataMap().getDbEntities()) {
+            for (DbRelationship relationship : nextEntity.getRelationships()) {
 
-		return incoming;
-	}
+                // TODO: PERFORMANCE 'getTargetEntity' is generally slow, called
+                // in this iterator it is showing (e.g. in YourKit profiles)..
+                // perhaps use cheaper 'getTargetEntityName()' or even better -
+                // pre-cache all relationships by target entity to avoid O(n)
+                // search ?
+                // (need to profile to prove the difference)
+                if (entity == relationship.getTargetEntity()) {
+                    incoming.add(relationship);
+                }
+            }
+        }
+
+        return incoming;
+    }
 
     protected List<DbRelationship> getRelationshipsToAdd(ObjEntity objEntity) {
         List<DbRelationship> missing = new ArrayList<DbRelationship>();
         for (DbRelationship dbRel : objEntity.getDbEntity().getRelationships()) {
-            // check if adding it makes sense at all
-            if (dbRel.getName() == null) {
-                continue;
-            }
-
-            if (objEntity.getRelationshipForDbRelationship(dbRel) == null) {
+            if (isMissingFromObjEntity(objEntity, dbRel)) {
                 missing.add(dbRel);
             }
         }
@@ -472,8 +511,8 @@ public class EntityMergeSupport {
     }
 
     /**
-     * @since 4.0
      * @param usePrimitives
+     * @since 4.0
      */
     public void setUsePrimitives(boolean usePrimitives) {
         this.usePrimitives = usePrimitives;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/f7f33b55/docs/doc/src/main/resources/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --git a/docs/doc/src/main/resources/RELEASE-NOTES.txt b/docs/doc/src/main/resources/RELEASE-NOTES.txt
index d6af992..aa04b5f 100644
--- a/docs/doc/src/main/resources/RELEASE-NOTES.txt
+++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt
@@ -31,6 +31,7 @@ CAY-2106 cayenne-crypto: allow DI contribution of type converters inside ValueTr
 CAY-2107 cayenne-crypto: Lazy initialization of crypto subsystem
 CAY-2111 Unbind transaction object from the current thread for iterated queries
 CAY-2112 Expose callback for "performInTransaction"
+CAY-2113 cdbimport: Reverse-engineering reinstates previously ignored columns
 
 Bug Fixes: