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 2006/05/08 02:31:40 UTC

svn commit: r404884 - in /incubator/cayenne/main/trunk/cayenne/cayenne-java/src: cayenne/java/org/objectstyle/cayenne/access/jdbc/ cayenne/java/org/objectstyle/cayenne/access/trans/ tests/java/org/objectstyle/cayenne/unit/jira/

Author: aadamchik
Date: Sun May  7 17:31:39 2006
New Revision: 404884

URL: http://svn.apache.org/viewcvs?rev=404884&view=rev
Log:
CAY-207. Had to introuce a new public method in SelectTranslator, but I guess this 
does not really compromize our API freeze...

Added:
    incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/jdbc/DataRowPostProcessor.java
Modified:
    incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/jdbc/JDBCResultIterator.java
    incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/jdbc/SelectAction.java
    incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/trans/SelectTranslator.java
    incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/objectstyle/cayenne/unit/jira/CAY_207Tst.java

Added: incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/jdbc/DataRowPostProcessor.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/jdbc/DataRowPostProcessor.java?rev=404884&view=auto
==============================================================================
--- incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/jdbc/DataRowPostProcessor.java (added)
+++ incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/jdbc/DataRowPostProcessor.java Sun May  7 17:31:39 2006
@@ -0,0 +1,199 @@
+/* ====================================================================
+ * 
+ * The ObjectStyle Group Software License, version 1.1
+ * ObjectStyle Group - http://objectstyle.org/
+ * 
+ * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
+ * of the software. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 
+ * 3. The end-user documentation included with the redistribution, if any,
+ *    must include the following acknowlegement:
+ *    "This product includes software developed by independent contributors
+ *    and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ * 
+ * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
+ *    or promote products derived from this software without prior written
+ *    permission. For written permission, email
+ *    "andrus at objectstyle dot org".
+ * 
+ * 5. Products derived from this software may not be called "ObjectStyle"
+ *    or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
+ *    names without prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ * 
+ * This software consists of voluntary contributions made by many
+ * individuals and hosted on ObjectStyle Group web site.  For more
+ * information on the ObjectStyle Group, please see
+ * <http://objectstyle.org/>.
+ */
+package org.objectstyle.cayenne.access.jdbc;
+
+import java.sql.ResultSet;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.objectstyle.cayenne.DataRow;
+import org.objectstyle.cayenne.access.trans.SelectTranslator;
+import org.objectstyle.cayenne.access.types.ExtendedType;
+import org.objectstyle.cayenne.dba.TypesMapping;
+import org.objectstyle.cayenne.map.Entity;
+import org.objectstyle.cayenne.map.EntityInheritanceTree;
+import org.objectstyle.cayenne.map.ObjAttribute;
+import org.objectstyle.cayenne.map.ObjEntity;
+
+/**
+ * Deals with DataRow type conversion in inheritance situations.
+ * 
+ * @since 1.2
+ * @author Andrus Adamchik
+ */
+class DataRowPostProcessor {
+
+    private EntityInheritanceTree inheritanceTree;
+    private Map columnOverrides;
+
+    // factory method
+    static DataRowPostProcessor createPostProcessor(SelectTranslator translator) {
+        Map attributeOverrides = translator.getAttributeOverrides();
+
+        if (attributeOverrides.isEmpty()) {
+            return null;
+        }
+
+        EntityInheritanceTree inheritanceTree = translator.getRootInheritanceTree();
+        if (inheritanceTree == null || inheritanceTree.getChildrenCount() == 0) {
+            return null;
+        }
+
+        ColumnDescriptor[] columns = translator.getResultColumns();
+
+        Map columnOverrides = new HashMap(2);
+
+        Iterator it = attributeOverrides.entrySet().iterator();
+        while (it.hasNext()) {
+            Map.Entry entry = (Map.Entry) it.next();
+
+            ObjAttribute attribute = (ObjAttribute) entry.getKey();
+            Entity entity = attribute.getEntity();
+
+            String key = null;
+            int jdbcType = TypesMapping.NOT_DEFINED;
+            int index = -1;
+            for (int i = 0; i < columns.length; i++) {
+                if (columns[i] == entry.getValue()) {
+
+                    // if attribute type is the same as column, there is no conflict
+                    if (!attribute.getType().equals(columns[i].getJavaClass())) {
+                        // note that JDBC index is "1" based
+                        index = i + 1;
+                        jdbcType = columns[i].getJdbcType();
+                        key = columns[i].getLabel();
+                    }
+
+                    break;
+                }
+            }
+
+            if (index < 1) {
+                continue;
+            }
+
+            ExtendedType converter = translator
+                    .getAdapter()
+                    .getExtendedTypes()
+                    .getRegisteredType(attribute.getJavaClass());
+
+            Collection overrides = null;
+
+            if (columnOverrides == null) {
+                columnOverrides = new HashMap(2);
+            }
+            else {
+                overrides = (Collection) columnOverrides.get(entity.getName());
+            }
+
+            if (overrides == null) {
+                overrides = new ArrayList(3);
+                columnOverrides.put(entity.getName(), overrides);
+            }
+
+            overrides.add(new ColumnOverride(index, key, converter, jdbcType));
+        }
+
+        return columnOverrides != null ? new DataRowPostProcessor(
+                inheritanceTree,
+                columnOverrides) : null;
+    }
+
+    private DataRowPostProcessor(EntityInheritanceTree inheritanceTree, Map columnOverides) {
+
+        this.inheritanceTree = inheritanceTree;
+        this.columnOverrides = columnOverides;
+    }
+
+    void postprocessRow(ResultSet resultSet, DataRow row) throws Exception {
+
+        ObjEntity entity = inheritanceTree.entityMatchingRow(row);
+        if (entity != null) {
+            Collection overrides = (Collection) columnOverrides.get(entity.getName());
+
+            if (overrides != null) {
+                Iterator it = overrides.iterator();
+                while (it.hasNext()) {
+                    ColumnOverride override = (ColumnOverride) it.next();
+
+                    Object newValue = override.converter.materializeObject(
+                            resultSet,
+                            override.index,
+                            override.jdbcType);
+                    row.put(override.key, newValue);
+                }
+            }
+        }
+    }
+
+    static final class ColumnOverride {
+
+        int index;
+        int jdbcType;
+        String key;
+        ExtendedType converter;
+
+        ColumnOverride(int index, String key, ExtendedType converter, int jdbcType) {
+            this.index = index;
+            this.key = key;
+            this.converter = converter;
+            this.jdbcType = jdbcType;
+        }
+    }
+}

Modified: incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/jdbc/JDBCResultIterator.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/jdbc/JDBCResultIterator.java?rev=404884&r1=404883&r2=404884&view=diff
==============================================================================
--- incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/jdbc/JDBCResultIterator.java (original)
+++ incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/jdbc/JDBCResultIterator.java Sun May  7 17:31:39 2006
@@ -79,7 +79,7 @@
  * A ResultIterator over the underlying JDBC ResultSet.
  * 
  * @since 1.2
- * @author Andrei Adamchik
+ * @author Andrus Adamchik
  */
 // Replaces DefaultResultIterator
 public class JDBCResultIterator implements ResultIterator {
@@ -91,6 +91,8 @@
 
     protected RowDescriptor rowDescriptor;
 
+    DataRowPostProcessor postProcessor;
+
     // last indexed PK
     protected DbEntity rootEntity;
     protected int[] pkIndices;
@@ -294,7 +296,7 @@
      */
     protected Map readDataRow() throws CayenneException {
         try {
-            Map dataRow = new DataRow(mapCapacity);
+            DataRow dataRow = new DataRow(mapCapacity);
             ExtendedType[] converters = rowDescriptor.getConverters();
             ColumnDescriptor[] columns = rowDescriptor.getColumns();
             int resultWidth = rowDescriptor.getWidth();
@@ -306,6 +308,10 @@
                         .getJdbcType());
                 dataRow.put(columns[i].getLabel(), val);
             }
+            
+            if(postProcessor != null) {
+                postProcessor.postprocessRow(resultSet, dataRow);
+            }
 
             return dataRow;
         }
@@ -401,5 +407,9 @@
 
     public RowDescriptor getRowDescriptor() {
         return rowDescriptor;
+    }
+
+    void setPostProcessor(DataRowPostProcessor postProcessor) {
+        this.postProcessor = postProcessor;
     }
 }

Modified: incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/jdbc/SelectAction.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/jdbc/SelectAction.java?rev=404884&r1=404883&r2=404884&view=diff
==============================================================================
--- incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/jdbc/SelectAction.java (original)
+++ incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/jdbc/SelectAction.java Sun May  7 17:31:39 2006
@@ -117,6 +117,9 @@
                 descriptor,
                 query.getFetchLimit());
 
+        workerIterator.setPostProcessor(DataRowPostProcessor
+                .createPostProcessor(translator));
+
         ResultIterator it = workerIterator;
 
         // wrap result iterator if distinct has to be suppressed
@@ -128,7 +131,7 @@
 
             QueryMetadata md = query.getMetaData(getEntityResolver());
             final PrefetchTreeNode rootPrefetch = md.getPrefetchTree();
-            
+
             if (rootPrefetch != null) {
                 rootPrefetch.traverse(new PrefetchProcessor() {
 

Modified: incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/trans/SelectTranslator.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/trans/SelectTranslator.java?rev=404884&r1=404883&r2=404884&view=diff
==============================================================================
--- incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/trans/SelectTranslator.java (original)
+++ incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/trans/SelectTranslator.java Sun May  7 17:31:39 2006
@@ -113,6 +113,7 @@
 
     List resultColumns;
     List groupByList;
+    Map attributeOverrides;
 
     int aliasCounter;
 
@@ -320,6 +321,17 @@
     }
 
     /**
+     * Returns a map of ColumnDescriptors keyed by ObjAttribute for columns that may need
+     * to be reprocessed manually due to incompatible mappings along the inheritance
+     * hierarchy.
+     * 
+     * @since 1.2
+     */
+    public Map getAttributeOverrides() {
+        return attributeOverrides != null ? attributeOverrides : Collections.EMPTY_MAP;
+    }
+
+    /**
      * Returns true if SelectTranslator determined that a query requiring DISTINCT can't
      * be run with DISTINCT keyword for internal reasons. If this method returns true,
      * DataNode may need to do in-memory distinct filtering.
@@ -407,7 +419,21 @@
                                 "ObjAttribute has no DbAttribute: " + oa.getName());
                     }
 
-                    appendColumn(columns, oa, dbAttr, attributes, null);
+                    if (!appendColumn(columns, oa, dbAttr, attributes, null)) {
+
+                        for (int i = 0; i < columns.size(); i++) {
+                            ColumnDescriptor column = (ColumnDescriptor) columns.get(i);
+                            if (dbAttr.getName().equals(column.getName())) {
+
+                                if (attributeOverrides == null) {
+                                    attributeOverrides = new HashMap();
+                                }
+
+                                attributeOverrides.put(oa, column);
+                                break;
+                            }
+                        }
+                    }
                 }
             }
         }
@@ -500,7 +526,8 @@
 
                         // note that we my select a source attribute, but label it as
                         // target for simplified snapshot processing
-                        appendColumn(columns, null, attribute, attributes, labelPrefix + '.'
+                        appendColumn(columns, null, attribute, attributes, labelPrefix
+                                + '.'
                                 + j.getTargetName());
                     }
                 }
@@ -632,7 +659,7 @@
         return columns;
     }
 
-    private void appendColumn(
+    private boolean appendColumn(
             List columns,
             ObjAttribute objAttribute,
             DbAttribute attribute,
@@ -651,6 +678,10 @@
             }
 
             columns.add(column);
+            return true;
+        }
+        else {
+            return false;
         }
     }
 

Modified: incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/objectstyle/cayenne/unit/jira/CAY_207Tst.java
URL: http://svn.apache.org/viewcvs/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/objectstyle/cayenne/unit/jira/CAY_207Tst.java?rev=404884&r1=404883&r2=404884&view=diff
==============================================================================
--- incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/objectstyle/cayenne/unit/jira/CAY_207Tst.java (original)
+++ incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/objectstyle/cayenne/unit/jira/CAY_207Tst.java Sun May  7 17:31:39 2006
@@ -98,11 +98,10 @@
             Object p1 = o1.readProperty("clientContactType");
             assertNotNull(p1);
 
-            // ***** The next assertion fails - uncomment to test
-            //assertTrue(
-            //        "Invalid property class: " + p1.getClass().getName(),
-            //        p1 instanceof CAY_207String1);
-
+           
+             assertTrue(
+                    "Invalid property class: " + p1.getClass().getName(),
+                    p1 instanceof CAY_207String1);
         }
         finally {
             cleanup(context);
@@ -121,12 +120,9 @@
 
             Object p2 = o2.readProperty("clientContactType");
             assertNotNull(p2);
-
-            // ***** The next assertion fails - uncomment to test
-            // assertTrue(
-            //        "Invalid property class: " + p2.getClass().getName(),
-            //        p2 instanceof CAY_207String2);
-
+            assertTrue(
+                    "Invalid property class: " + p2.getClass().getName(),
+                    p2 instanceof CAY_207String2);
         }
         finally {
             cleanup(context);