cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aadamc...@apache.org
Subject [1/4] cayenne git commit: fix relationships loading
Date Sat, 17 Jan 2015 08:05:43 GMT
Repository: cayenne
Updated Branches:
  refs/heads/master 44642ea58 -> c8ff4355f


fix relationships loading


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

Branch: refs/heads/master
Commit: aaafe117143e256a7b48692485b22c9d10538477
Parents: 44642ea
Author: alexkolonitsky <Alex.Kolonitsky@gmail.com>
Authored: Thu Jan 8 20:49:26 2015 +0300
Committer: alexkolonitsky <Alex.Kolonitsky@gmail.com>
Committed: Thu Jan 8 20:49:26 2015 +0300

----------------------------------------------------------------------
 .../org/apache/cayenne/access/DbLoader.java     |  69 ++++-----
 .../access/loader/LoggingDbLoaderDelegate.java  |  20 +--
 .../org/apache/cayenne/map/DbRelationship.java  |  40 ++++--
 .../org/apache/cayenne/map/Relationship.java    |   6 +-
 .../apache/cayenne/map/naming/ExportedKey.java  |  18 ++-
 .../merge/DropRelationshipToModelIT.java        |   7 +-
 .../apache/cayenne/merge/MergerFactoryIT.java   |  13 +-
 cayenne-tools/pom.xml                           |   5 +
 .../cayenne/tools/CayenneGeneratorTask.java     |  11 +-
 .../cayenne/tools/dbimport/DbImportAction.java  |  30 ++--
 .../dbimport/DbImportDbLoaderDelegate.java      |   1 -
 .../src/main/resources/reverseEngineering.xsd   | 139 +++++++++++++++++++
 .../cayenne/tools/DbImporterMojoTest.java       |   4 +
 .../cayenne/tools/dbimport/testOneToOne-pom.xml |  39 ++++++
 .../tools/dbimport/testOneToOne.map.xml-result  |  58 ++++++++
 .../cayenne/tools/dbimport/testOneToOne.sql     |  24 ++++
 16 files changed, 400 insertions(+), 84 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
index 864e4f0..f86692f 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
@@ -49,14 +49,12 @@ import org.apache.commons.logging.LogFactory;
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -325,9 +323,8 @@ public class DbLoader {
 
             loadDbAttributes(config.getFiltersConfig(), tablesMap.getKey(), tablesMap.getValue());
 
-            if (!config.isSkipPrimaryKeyLoading()) {
-                getPrimaryKeyForTable(tablesMap.getValue());
-            }
+            // get primary keys for each table and store it in dbEntity
+            getPrimaryKeyForTable(tablesMap.getValue());
         }
 
         return dbEntityList;
@@ -366,8 +363,6 @@ public class DbLoader {
         ResultSet rs = getMetaData().getColumns(path.catalog, path.schema, WILDCARD, WILDCARD);
 
         try {
-            Set<String> columns = new HashSet<String>();
-
             while (rs.next()) {
                 // for a reason not quiet apparent to me, Oracle sometimes
                 // returns duplicate record sets for the same table, messing up table
@@ -382,7 +377,7 @@ public class DbLoader {
                     continue;
                 }
 
-                DbAttribute attr = loadDbAttribute(columns, rs);
+                DbAttribute attr = loadDbAttribute(rs);
                 attr.setEntity(dbEntity);
                 Filter<DbAttribute> filter = filters.filter(new DbPath(dbEntity.getCatalog(),
dbEntity.getSchema(), dbEntity.getName())).columnFilter();
                 if (!filter.isInclude(attr)) {
@@ -404,14 +399,7 @@ public class DbLoader {
         }
     }
 
-    private DbAttribute loadDbAttribute(Set<String> columns, ResultSet rs) throws SQLException
{
-        if (columns.isEmpty()) {
-            ResultSetMetaData rsMetaData = rs.getMetaData();
-            for (int i = 1; i <= rsMetaData.getColumnCount(); i++) {
-                columns.add(rsMetaData.getColumnLabel(i));
-            }
-        }
-
+    private DbAttribute loadDbAttribute(ResultSet rs) throws SQLException {
         // gets attribute's (column's) information
         int columnType = rs.getInt("DATA_TYPE");
 
@@ -433,7 +421,11 @@ public class DbLoader {
                 decimalDigits,
                 rs.getBoolean("NULLABLE"));
 
-        if (columns.contains("IS_AUTOINCREMENT")) {
+        if (adapter.supportsGeneratedKeys()) {
+
+            // TODO: this actually throws on some drivers... need to
+            // ensure that 'supportsGeneratedKeys' check is enough
+            // to prevent an exception here.
             String autoIncrement = rs.getString("IS_AUTOINCREMENT");
             if ("YES".equals(autoIncrement)) {
                 attr.setGenerated(true);
@@ -443,7 +435,8 @@ public class DbLoader {
     }
 
     /**
-     * Creates an ObjEntity for each DbEntity in the map.
+     * Creates an ObjEntity for each DbEntity in the map. ObjEntities are
+     * created empty without
      */
     protected Collection<ObjEntity> loadObjEntities(DataMap map, DbLoaderConfiguration
config, Collection<DbEntity> entities) {
         if (entities.isEmpty()) {
@@ -518,28 +511,29 @@ public class DbLoader {
                     continue;
                 }
 
+                // forwardRelationship is a reference from table with primary key
                 DbRelationship forwardRelationship = new DbRelationship(generateName(pkEntity,
key, true));
                 forwardRelationship.setSourceEntity(pkEntity);
                 forwardRelationship.setTargetEntity(fkEntity);
 
+                // forwardRelationship is a reference from table with foreign key, it is
what exactly we load from db
                 DbRelationshipDetected reverseRelationship = new DbRelationshipDetected(generateName(fkEntity,
key, false));
                 reverseRelationship.setFkName(key.getFKName());
                 reverseRelationship.setSourceEntity(fkEntity);
                 reverseRelationship.setTargetEntity(pkEntity);
                 reverseRelationship.setToMany(false);
-                if (delegate.dbRelationshipLoaded(fkEntity, reverseRelationship)) {
-                    fkEntity.addRelationship(reverseRelationship);
-                }
 
-                boolean toPK = createAndAppendJoins(exportedKeys, pkEntity, fkEntity, forwardRelationship,
reverseRelationship);
+                createAndAppendJoins(exportedKeys, pkEntity, fkEntity, forwardRelationship,
reverseRelationship);
 
-                forwardRelationship.setToDependentPK(toPK);
-
-                boolean isOneToOne = toPK && fkEntity.getPrimaryKeys().size()
-                        == forwardRelationship.getJoins().size();
+                boolean isOneToOne = isOneToOne(fkEntity, forwardRelationship);
 
+                forwardRelationship.setToDependentPK(isOneToOne);
                 forwardRelationship.setToMany(!isOneToOne);
                 forwardRelationship.setName(generateName(pkEntity, key, !isOneToOne));
+
+                if (delegate.dbRelationshipLoaded(fkEntity, reverseRelationship)) {
+                    fkEntity.addRelationship(reverseRelationship);
+                }
                 if (delegate.dbRelationshipLoaded(pkEntity, forwardRelationship)) {
                     pkEntity.addRelationship(forwardRelationship);
                 }
@@ -547,8 +541,21 @@ public class DbLoader {
         }
     }
 
-    private boolean createAndAppendJoins(Set<ExportedKey> exportedKeys, DbEntity pkEntity,
DbEntity fkEntity, DbRelationship forwardRelationship, DbRelationshipDetected reverseRelationship)
{
-        boolean toPK = true;
+    private boolean isOneToOne(DbEntity fkEntity, DbRelationship forwardRelationship) {
+        if (fkEntity.getPrimaryKeys().size() != forwardRelationship.getJoins().size()) {
+            return false;
+        }
+
+        for (DbJoin dbJoin : forwardRelationship.getJoins()) {
+            if (!dbJoin.getTarget().isPrimaryKey()) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    private void createAndAppendJoins(Set<ExportedKey> exportedKeys, DbEntity pkEntity,
DbEntity fkEntity, DbRelationship forwardRelationship, DbRelationshipDetected reverseRelationship)
{
         for (ExportedKey exportedKey : exportedKeys) {
             // Create and append joins
             String pkName = exportedKey.getPKColumnName();
@@ -569,12 +576,7 @@ public class DbLoader {
 
             forwardRelationship.addJoin(new DbJoin(forwardRelationship, pkName, fkName));
             reverseRelationship.addJoin(new DbJoin(reverseRelationship, fkName, pkName));
-
-            if (!pkAtt.isPrimaryKey()) {
-                toPK = false;
-            }
         }
-        return toPK;
     }
 
     private Map<String, Set<ExportedKey>> loadExportedKeys(DbLoaderConfiguration
config, DbPath dbPath, Map<String, DbEntity> tables) throws SQLException {
@@ -760,6 +762,7 @@ public class DbLoader {
      * @since 4.0
      */
     public void load(DataMap dataMap, DbLoaderConfiguration config) throws SQLException {
+        LOGGER.info("Schema loading...");
 
         Map<DbPath, Map<String, DbEntity>> tables = getTables(config, config.getTableTypes());
         List<DbEntity> entities = loadDbEntities(dataMap, config, tables);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-server/src/main/java/org/apache/cayenne/access/loader/LoggingDbLoaderDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/LoggingDbLoaderDelegate.java
b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/LoggingDbLoaderDelegate.java
index d5e69f4..8c77a87 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/LoggingDbLoaderDelegate.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/LoggingDbLoaderDelegate.java
@@ -36,37 +36,41 @@ public class LoggingDbLoaderDelegate extends DefaultDbLoaderDelegate {
 
     @Override
     public void dbEntityAdded(DbEntity entity) {
-        logger.info("Add dbEntity: " + entity.getFullyQualifiedName());
+        logger.info("  Table: " + entity.getFullyQualifiedName());
     }
 
     @Override
     public void dbEntityRemoved(DbEntity entity) {
-        logger.info("Del dbEntity: " + entity.getFullyQualifiedName());
+        logger.info("  Table removed: " + entity.getFullyQualifiedName());
     }
 
     @Override
     public boolean dbRelationship(DbEntity entity) {
-        logger.info("    Relationships for " + entity.getFullyQualifiedName());
+        if (logger.isDebugEnabled()) {
+            logger.debug("    Relationships for " + entity.getFullyQualifiedName());
+        }
 
         return true;
     }
 
     @Override
     public boolean dbRelationshipLoaded(DbEntity entity, DbRelationship relationship) {
-        if (logger.isDebugEnabled()) {
-            logger.debug("    Relationship : " + entity.getName() + "; " + relationship.toString());
-        }
+        logger.info("    " + relationship);
 
         return true;
     }
 
     @Override
     public void objEntityAdded(ObjEntity entity) {
-        logger.info("Add objEntity: " + entity.getName());
+        if (logger.isDebugEnabled()) {
+            logger.debug("  Class: " + entity.getName());
+        }
     }
 
     @Override
     public void objEntityRemoved(ObjEntity entity) {
-        logger.info("Del objEntity: " + entity.getName());
+        if (logger.isDebugEnabled()) {
+            logger.debug("  Class removed: " + entity.getName());
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java b/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java
index 5234ff4..12bfbf9 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/DbRelationship.java
@@ -33,6 +33,7 @@ import org.apache.cayenne.util.Util;
 import org.apache.cayenne.util.XMLEncoder;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.Transformer;
+import org.apache.commons.lang.StringUtils;
 
 /**
  * A DbRelationship is a descriptor of a database inter-table relationship based
@@ -40,17 +41,18 @@ import org.apache.commons.collections.Transformer;
  */
 public class DbRelationship extends Relationship implements ConfigurationNode {
 
-    // The columns through which the join is implemented.
+    /**
+     * The columns through which the join is implemented.
+     */
     protected List<DbJoin> joins = new ArrayList<DbJoin>(2);
 
-    // Is relationship from source to target points to dependent primary
-    // key (primary key column of destination table that is also a FK to the
-    // source
-    // column)
+    /**
+     * Is relationship from source to target points to dependent primary key (primary key
column of destination table
+     * that is also a FK to the source column)
+     */
     protected boolean toDependentPK;
 
     public DbRelationship() {
-        super();
     }
 
     public DbRelationship(String name) {
@@ -122,7 +124,7 @@ public class DbRelationship extends Relationship implements ConfigurationNode
{
      */
     public Collection<DbAttribute> getTargetAttributes() {
         if (joins.size() == 0) {
-            return Collections.EMPTY_LIST;
+            return Collections.emptyList();
         }
 
         return CollectionUtils.collect(joins, JoinTransformers.targetExtractor);
@@ -135,7 +137,7 @@ public class DbRelationship extends Relationship implements ConfigurationNode
{
      */
     public Collection<DbAttribute> getSourceAttributes() {
         if (joins.size() == 0) {
-            return Collections.EMPTY_LIST;
+            return Collections.emptyList();
         }
 
         return CollectionUtils.collect(joins, JoinTransformers.sourceExtractor);
@@ -148,7 +150,7 @@ public class DbRelationship extends Relationship implements ConfigurationNode
{
      * @since 1.0.5
      */
     public DbRelationship createReverseRelationship() {
-        DbEntity targetEntity = (DbEntity) getTargetEntity();
+        DbEntity targetEntity = getTargetEntity();
 
         DbRelationship reverse = new DbRelationship();
         reverse.setSourceEntity(targetEntity);
@@ -535,4 +537,24 @@ public class DbRelationship extends Relationship implements ConfigurationNode
{
                     && Util.nullSafeEquals(j.targetName, this.targetName);
         }
     }
+
+    @Override
+    public String toString() {
+        String res = "Db Relationship : " + (toMany ? "toMany" : "toOne ");
+
+        String sourceEntityName = getSourceEntityName();
+        String targetEntityName = getTargetEntityName();
+        for (DbJoin join : joins) {
+            res += " (" + sourceEntityName + "." + join.getSourceName() + ", " + targetEntityName
+ "." + join.getTargetName() + ")";
+        }
+
+        return res;
+    }
+
+    public String getSourceEntityName() {
+        if (this.sourceEntity == null) {
+            return null;
+        }
+        return this.sourceEntity.name;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-server/src/main/java/org/apache/cayenne/map/Relationship.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/Relationship.java b/cayenne-server/src/main/java/org/apache/cayenne/map/Relationship.java
index 1c34172..ecc0f80 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/Relationship.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/Relationship.java
@@ -159,9 +159,9 @@ public abstract class Relationship implements CayenneMapEntry, XMLSerializable,
      */
     @Override
     public String toString() {
-        return new ToStringBuilder(this).append("name", getName()).append(
-                "toMany",
-                isToMany()).toString();
+        return new ToStringBuilder(this)
+                .append("name", getName())
+                .append("toMany", isToMany()).toString();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-server/src/main/java/org/apache/cayenne/map/naming/ExportedKey.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/naming/ExportedKey.java b/cayenne-server/src/main/java/org/apache/cayenne/map/naming/ExportedKey.java
index 42697fe..ab8229f 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/naming/ExportedKey.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/naming/ExportedKey.java
@@ -28,6 +28,19 @@ import java.sql.SQLException;
 /**
  * ExportedKey is an representation of relationship between two tables 
  * in database. It can be used for creating names for relationships
+ *
+ * Example:
+ *  Table A with primary key ID
+ *  Table B with primary key ID and foreign key A_ID
+ *
+ *  In that case ExportedKey will be:
+ *      pkTable:  A
+ *      pkColumn: A.ID
+ *      fkTable:  B
+ *      fkColumn: B.A_ID
+ *      fkName:   name of foreign key
+ *      pkName:
+ *      keySeq: TODO
  * 
  */
 public class ExportedKey implements Comparable {
@@ -200,11 +213,10 @@ public class ExportedKey implements Comparable {
 
     @Override
     public String toString() {
-        return getStrKey() + " # " + keySeq
-                + "(" + pkColumn + " <- " + fkColumn + ")";
+        return getStrKey() + " # " + keySeq;
     }
 
     public String getStrKey() {
-        return pkTable + "." + pkName + " <- " + fkTable + "." + fkName;
+        return pkTable + "." + pkColumn + " <- " + fkTable + "." + fkColumn;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java
b/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java
index e235109..3505971 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java
@@ -130,7 +130,12 @@ public class DropRelationshipToModelIT extends MergeCase {
         dbEntity1.removeRelationship(rel1To2.getName());
         dbEntity2.removeAttribute(e2col2.getName());
         List<MergerToken> tokens = createMergeTokens();
-        assertTokens(tokens, 3, 0);
+        /**
+         * Add Relationship NEW_TABLE->NEW_TABLE2 To Model
+         * Drop Relationship NEW_TABLE2->NEW_TABLE To DB
+         * Drop Column NEW_TABLE2.FK To DB
+         * */
+        assertTokens(tokens, 2, 1);
         for (MergerToken token : tokens) {
             if (token.getDirection().isToDb()) {
                 execute(token);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java
index 409f1c9..e1db050 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java
@@ -219,8 +219,11 @@ public class MergerFactoryIT extends MergeCase {
         dbEntity.removeRelationship(r1.getName());
         artistDbEntity.removeRelationship(r2.getName());
         resolver.refreshMappingCache();
-        assertTokensAndExecute(2, 0);
-//        assertTokensAndExecute(1, 1);
+        /*
+         * Db -Rel 'toArtistR1' - NEW_TABLE 1 -> 1 ARTIST"
+r2 =     * Db -Rel 'toNewTableR2' - ARTIST 1 -> * NEW_TABLE"
+         * */
+        assertTokensAndExecute(1, 1);
         assertTokensAndExecute(0, 0);
 
         // clear up
@@ -277,7 +280,11 @@ public class MergerFactoryIT extends MergeCase {
         dbEntity.removeRelationship(r1.getName());
         artistDbEntity.removeRelationship(r2.getName());
         resolver.refreshMappingCache();
-        assertTokensAndExecute(2, 0);
+        /*
+        * Add Relationship ARTIST->NEW_TABLE To Model
+        * Drop Relationship NEW_TABLE->ARTIST To DB
+        * */
+        assertTokensAndExecute(1, 1);
         assertTokensAndExecute(0, 0);
 
         // clear up

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-tools/pom.xml
----------------------------------------------------------------------
diff --git a/cayenne-tools/pom.xml b/cayenne-tools/pom.xml
index a97dd13..630c92d 100644
--- a/cayenne-tools/pom.xml
+++ b/cayenne-tools/pom.xml
@@ -165,6 +165,11 @@
             <plugin>
                 <artifactId>maven-pmd-plugin</artifactId>
             </plugin>
+            <plugin>
+                <groupId>xsddoc</groupId>
+                <artifactId>maven-xsddoc-plugin</artifactId>
+                <version>1.0</version>
+            </plugin>
         </plugins>
 	</build>
 </project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
b/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
index dcd36e6..26ae00d 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/CayenneGeneratorTask.java
@@ -73,16 +73,9 @@ public class CayenneGeneratorTask extends CayenneTask {
     }
 
     protected ClassGenerationAction createGeneratorAction() {
-        ClassGenerationAction action;
-        if (client) {
-            action = new ClientClassGenerationAction();
-            action.setContext(getVppContext());
-        }
-        else {
-            action = new ClassGenerationAction();
-            action.setContext(getVppContext());
-        }
+        ClassGenerationAction action = client ? new ClientClassGenerationAction() : new ClassGenerationAction();
 
+        action.setContext(getVppContext());
         action.setDestDir(destDir);
         action.setEncoding(encoding);
         action.setMakePairs(makepairs);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/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 bf981ee..3ff9278 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
@@ -110,7 +110,8 @@ public class DbImportAction {
             List<MergerToken> mergeTokens = new DbMerger(mergerFactory)
                     .createMergeTokens(existing, loadedFomDb, config.getDbLoaderConfig());
             if (mergeTokens.isEmpty()) {
-                logger.info("No changes to import.");
+                logger.info("");
+                logger.info("Detected changes: No changes to import.");
                 return;
             }
 
@@ -122,6 +123,7 @@ public class DbImportAction {
     }
 
     private Collection<MergerToken> log(List<MergerToken> tokens) {
+        logger.info("");
         logger.info("Detected changes: ");
         for (MergerToken token : tokens) {
             logger.info(String.format("    %-20s %s", token.getTokenName(), token.getTokenValue()));
@@ -154,7 +156,7 @@ public class DbImportAction {
     /**
      * Performs configured schema operations via DbGenerator.
      */
-    public DataMap execute(ModelMergeDelegate mergeDelegate, DataMap dataMap, Collection<MergerToken>
tokens) {
+    private DataMap execute(ModelMergeDelegate mergeDelegate, DataMap dataMap, Collection<MergerToken>
tokens) {
         MergerContext mergerContext = new ExecutingMergerContext(
                 dataMap, null, null, mergeDelegate);
 
@@ -190,18 +192,18 @@ public class DbImportAction {
         projectSaver.save(project);
     }
 
-	private DataMap load(DbImportConfiguration config, DbAdapter adapter, Connection connection)
throws Exception {
-		DataMap dataMap = config.createDataMap();
+    private DataMap load(DbImportConfiguration config, DbAdapter adapter, Connection connection)
throws Exception {
+        DataMap dataMap = config.createDataMap();
 
-		try {
-			DbLoader loader = config.createLoader(adapter, connection, config.createLoaderDelegate());
-			loader.load(dataMap, config.getDbLoaderConfig());
-		} finally {
-			if (connection != null) {
-				connection.close();
-			}
-		}
+        try {
+            DbLoader loader = config.createLoader(adapter, connection, config.createLoaderDelegate());
+            loader.load(dataMap, config.getDbLoaderConfig());
+        } finally {
+            if (connection != null) {
+                connection.close();
+            }
+        }
 
-		return dataMap;
-	}
+        return dataMap;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegate.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegate.java
b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegate.java
index a97fd03..e3fbc01 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegate.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportDbLoaderDelegate.java
@@ -19,7 +19,6 @@
 
 package org.apache.cayenne.tools.dbimport;
 
-import org.apache.cayenne.access.DbLoaderDelegate;
 import org.apache.cayenne.access.loader.DefaultDbLoaderDelegate;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.ObjEntity;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/cayenne-tools/src/main/resources/reverseEngineering.xsd
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/resources/reverseEngineering.xsd b/cayenne-tools/src/main/resources/reverseEngineering.xsd
new file mode 100644
index 0000000..6905386
--- /dev/null
+++ b/cayenne-tools/src/main/resources/reverseEngineering.xsd
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+<xs:schema attributeFormDefault="unqualified"
+           elementFormDefault="qualified"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+    <xs:complexType name="PatternParamType" mixed="true">
+        <xs:annotation>
+            <xs:documentation>
+                At least one of 3 options ot fill pattern information should be used
+                1) &lt;tag>pattarn&lt;tag>
+                2) &lt;tag pattern="pattern" />
+                3) &lt;tag>
+                      &lt;pattern>pattern&lt;/pattern>
+                   &lt;/tag>
+            </xs:documentation>
+        </xs:annotation>
+        <xs:sequence>
+            <xs:element type="xs:string" name="pattern" minOccurs="0"/>
+        </xs:sequence>
+        <xs:attribute type="xs:string" name="pattern" use="optional"/>
+    </xs:complexType>
+
+    <xs:complexType name="IncludeTableType" mixed="true">
+        <xs:complexContent>
+            <xs:extension base="PatternParamType">
+                <xs:sequence>
+                    <xs:choice minOccurs="0" maxOccurs="unbounded">
+                        <xs:element name="includeColumn" type="PatternParamType" />
+                        <xs:element name="excludeColumn" type="PatternParamType" />
+                    </xs:choice>
+                </xs:sequence>
+            </xs:extension>
+        </xs:complexContent>
+    </xs:complexType>
+
+    <xs:complexType name="FilterContainerType">
+        <xs:sequence>
+            <xs:choice minOccurs="1" maxOccurs="unbounded">
+                <xs:element name="includeTable" type="IncludeTableType" />
+                <xs:element name="excludeTable" type="PatternParamType" />
+                <xs:element name="includeColumn" type="PatternParamType" />
+                <xs:element name="excludeColumn" type="PatternParamType" />
+                <xs:element name="includeProcedure" type="PatternParamType" />
+                <xs:element name="excludeProcedure" type="PatternParamType" />
+            </xs:choice>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="SchemaType" mixed="true">
+        <xs:annotation>
+            <xs:documentation>
+                At least one of 3 options to provide schema name can be used:
+                1) &lt;schema>name&lt;schema>
+                2) &lt;schema name="name" />
+                3) &lt;schema>
+                &lt;name>name&lt;/name>
+                &lt;/schema>
+            </xs:documentation>
+        </xs:annotation>
+        <xs:complexContent>
+            <xs:extension base="FilterContainerType">
+                <xs:sequence>
+                    <xs:element name="name" type="xs:string" minOccurs="0" maxOccurs="1"
/>
+                </xs:sequence>
+                <xs:attribute type="xs:string" name="name" use="optional" />
+            </xs:extension>
+        </xs:complexContent>
+    </xs:complexType>
+
+    <xs:complexType name="CatalogType" mixed="true">
+        <xs:annotation>
+            <xs:documentation>
+                At least one of 3 options to provide schema name can be used:
+                1) &lt;catalog>name&lt;catalog>
+                2) &lt;catalog name="name" />
+                3) &lt;catalog>
+                &lt;name>name&lt;/name>
+                &lt;/catalog>
+            </xs:documentation>
+        </xs:annotation>
+        <xs:complexContent>
+            <xs:extension base="FilterContainerType">
+                <xs:sequence>
+                    <xs:element name="name" type="xs:string" minOccurs="0" maxOccurs="1"
/>
+                    <xs:choice minOccurs="0" maxOccurs="unbounded">
+                        <xs:element name="schema" type="SchemaType" />
+                    </xs:choice>
+                </xs:sequence>
+                <xs:attribute type="xs:string" name="name" use="optional" />
+            </xs:extension>
+        </xs:complexContent>
+    </xs:complexType>
+
+    <xs:complexType name="ReverseEngineeringType">
+        <xs:annotation>
+            <xs:documentation>
+                <!-- TODO -->
+            </xs:documentation>
+        </xs:annotation>
+        <xs:complexContent>
+            <xs:extension base="FilterContainerType">
+                <xs:sequence>
+                    <xs:element name="name" type="xs:string" minOccurs="0" maxOccurs="1"
/>
+                    <xs:choice minOccurs="0" maxOccurs="unbounded">
+                        <xs:element name="catalog" type="CatalogType" />
+                        <xs:element name="schema" type="SchemaType" />
+                    </xs:choice>
+                </xs:sequence>
+                <xs:attribute type="xs:string" name="name" use="optional" />
+            </xs:extension>
+        </xs:complexContent>
+    </xs:complexType>
+
+    <xs:element name="reverseEngineering" type="ReverseEngineeringType">
+        <xs:annotation>
+            <!-- TODO -->
+            <xs:documentation> </xs:documentation>
+        </xs:annotation>
+    </xs:element>
+
+</xs:schema>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java
b/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java
index cf17a84..e7fc592 100644
--- a/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java
+++ b/plugins/maven-cayenne-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java
@@ -153,6 +153,10 @@ public class DbImporterMojoTest extends AbstractMojoTestCase {
 		test("testSkipPrimaryKeyLoading");
 	}
 
+	public void testOneToOne() throws Exception {
+		test("testOneToOne");
+	}
+
     /**
      * Q: what happens if a relationship existed over a column that was later deleted? and
‘skipRelLoading’ is true
      * A: it should remove relationship and column

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne-pom.xml
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne-pom.xml
b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne-pom.xml
new file mode 100644
index 0000000..bee8671
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne-pom.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+	http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+	<name>DbImporterMojo Test1</name>	
+
+	<build>
+		<plugins>
+			<plugin>
+				<artifactId>maven-cayenne-plugin</artifactId>
+				<configuration>
+					<map>target/test-classes/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml</map>
+                    <driver>org.apache.derby.jdbc.EmbeddedDriver</driver>
+                    <url>jdbc:derby:memory:DbImporterMojoTest;create=true</url>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml-result
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml-result
b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml-result
new file mode 100644
index 0000000..557423d
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.map.xml-result
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+	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.
+-->
+<data-map xmlns="http://cayenne.apache.org/schema/7/modelMap"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://cayenne.apache.org/schema/7/modelMap http://cayenne.apache.org/schema/7/modelMap.xsd"
+          project-version="7">
+	<db-entity name="PICK_SCHEDULE" schema="APP">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
+		<db-attribute name="OWNER_ID" type="INTEGER" length="10"/>
+		<db-attribute name="SELECTED_PLAYER_ID" type="INTEGER" length="10"/>
+	</db-entity>
+	<db-entity name="PLAYER" schema="APP">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true" length="10"/>
+	</db-entity>
+	<db-entity name="PLAYER_INFO" schema="APP">
+		<db-attribute name="PLAYER_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"
length="10"/>
+	</db-entity>
+	<obj-entity name="PickSchedule" className="PickSchedule" dbEntityName="PICK_SCHEDULE">
+		<obj-attribute name="ownerId" type="java.lang.Integer" db-attribute-path="OWNER_ID"/>
+	</obj-entity>
+	<obj-entity name="Player" className="Player" dbEntityName="PLAYER">
+	</obj-entity>
+	<obj-entity name="PlayerInfo" className="PlayerInfo" dbEntityName="PLAYER_INFO">
+	</obj-entity>
+	<db-relationship name="toPlayer" source="PICK_SCHEDULE" target="PLAYER" toMany="false">
+		<db-attribute-pair source="SELECTED_PLAYER_ID" target="ID"/>
+	</db-relationship>
+	<db-relationship name="pickScheduleArray" source="PLAYER" target="PICK_SCHEDULE" toMany="true">
+		<db-attribute-pair source="ID" target="SELECTED_PLAYER_ID"/>
+	</db-relationship>
+	<db-relationship name="toPlayer" source="PLAYER" target="PLAYER_INFO" toDependentPK="true"
toMany="false">
+		<db-attribute-pair source="ID" target="PLAYER_ID"/>
+	</db-relationship>
+	<db-relationship name="toPlayer" source="PLAYER_INFO" target="PLAYER" toMany="false">
+		<db-attribute-pair source="PLAYER_ID" target="ID"/>
+	</db-relationship>
+	<obj-relationship name="toPlayer" source="PickSchedule" target="Player" deleteRule="Nullify"
db-relationship-path="toPlayer"/>
+	<obj-relationship name="pickScheduleArray" source="Player" target="PickSchedule" deleteRule="Deny"
db-relationship-path="pickScheduleArray"/>
+	<obj-relationship name="toPlayer" source="Player" target="PlayerInfo" deleteRule="Nullify"
db-relationship-path="toPlayer"/>
+	<obj-relationship name="toPlayer" source="PlayerInfo" target="Player" deleteRule="Nullify"
db-relationship-path="toPlayer"/>
+</data-map>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/aaafe117/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.sql
----------------------------------------------------------------------
diff --git a/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.sql
b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.sql
new file mode 100644
index 0000000..a279c65
--- /dev/null
+++ b/plugins/maven-cayenne-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testOneToOne.sql
@@ -0,0 +1,24 @@
+CREATE TABLE player (
+  id INTEGER NOT NULL,
+
+  PRIMARY KEY (id)
+);
+
+
+-- one-to-one relationship
+CREATE TABLE player_info (
+  player_id INTEGER NOT NULL,
+
+  PRIMARY KEY (player_id),
+  CONSTRAINT fk_player_info FOREIGN KEY (player_id) REFERENCES player (id)
+);
+
+-- one-to-many relationship
+CREATE TABLE pick_schedule (
+  id INTEGER NOT NULL,
+  owner_id INTEGER,
+  selected_player_id INTEGER,
+  PRIMARY KEY (id),
+
+  CONSTRAINT fk_pick_schedule_player1 FOREIGN KEY (selected_player_id) REFERENCES player
(id)
+)


Mime
View raw message