Author: aadamchik
Date: Sun May 7 18:25:13 2006
New Revision: 404890
URL: http://svn.apache.org/viewcvs?rev=404890&view=rev
Log:
CAY-207 - finished
improved the algorithm to prevent using a randomly registered ExtendedType in
case when there are multiple overlapping ObjAttributes that map to the same
column. Introduced "void" ExtendedType used to mask a ResultSet postprocessor
Added:
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/types/VoidType.java
Modified:
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/jdbc/DataRowPostProcessor.java
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/trans/SelectTranslator.java
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/types/ExtendedTypeMap.java
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/objectstyle/cayenne/unit/jira/CAY_207String1.java
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/objectstyle/cayenne/unit/jira/CAY_207String2.java
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/objectstyle/cayenne/unit/jira/CAY_207Tst.java
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/resources/dml/unit.jira.CAY_207Tst.xml
Modified:
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=404890&r1=404889&r2=404890&view=diff
==============================================================================
---
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/jdbc/DataRowPostProcessor.java
(original)
+++
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/jdbc/DataRowPostProcessor.java
Sun May 7 18:25:13 2006
@@ -81,20 +81,15 @@
private EntityInheritanceTree inheritanceTree;
private Map columnOverrides;
+ private Collection defaultOverrides;
// 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);
@@ -131,7 +126,7 @@
ExtendedType converter = translator
.getAdapter()
.getExtendedTypes()
- .getRegisteredType(attribute.getJavaClass());
+ .getRegisteredType(attribute.getType());
Collection overrides = null;
@@ -150,35 +145,55 @@
overrides.add(new ColumnOverride(index, key, converter, jdbcType));
}
- return columnOverrides != null ? new DataRowPostProcessor(
- inheritanceTree,
- columnOverrides) : null;
+ // inject null post-processor
+ return columnOverrides != null ? new DataRowPostProcessor(translator
+ .getRootInheritanceTree(), columnOverrides) : null;
}
- private DataRowPostProcessor(EntityInheritanceTree inheritanceTree, Map
columnOverides) {
+ private DataRowPostProcessor(EntityInheritanceTree inheritanceTree,
+ Map columnOverrides) {
+
+ if (inheritanceTree != null && inheritanceTree.getChildren().size() >
0) {
+ this.inheritanceTree = inheritanceTree;
+ this.columnOverrides = columnOverrides;
+ }
+ else {
+ if (columnOverrides.size() != 1) {
+ throw new IllegalArgumentException(
+ "No inheritance - there must be only one override
set");
+ }
- this.inheritanceTree = inheritanceTree;
- this.columnOverrides = columnOverides;
+ defaultOverrides = (Collection)
columnOverrides.values().iterator().next();
+ }
}
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);
- }
+ Collection overrides = getOverrides(row);
+
+ 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);
}
+ }
+ }
+
+ private final Collection getOverrides(DataRow row) {
+ if (defaultOverrides != null) {
+ return defaultOverrides;
+ }
+ else {
+ ObjEntity entity = inheritanceTree.entityMatchingRow(row);
+ return entity != null
+ ? (Collection) columnOverrides.get(entity.getName())
+ : null;
}
}
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=404890&r1=404889&r2=404890&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 18:25:13 2006
@@ -331,7 +331,7 @@
*/
protected Map readIdRow() throws CayenneException {
try {
- Map idRow = new DataRow(2);
+ DataRow idRow = new DataRow(2);
ExtendedType[] converters = rowDescriptor.getConverters();
ColumnDescriptor[] columns = rowDescriptor.getColumns();
int len = pkIndices.length;
@@ -347,6 +347,10 @@
index + 1,
columns[index].getJdbcType());
idRow.put(columns[index].getLabel(), val);
+ }
+
+ if(postProcessor != null) {
+ postProcessor.postprocessRow(resultSet, idRow);
}
return idRow;
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=404890&r1=404889&r2=404890&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 18:25:13 2006
@@ -114,6 +114,7 @@
List resultColumns;
List groupByList;
Map attributeOverrides;
+ Map defaultAttributesByColumn;
int aliasCounter;
@@ -357,6 +358,8 @@
List buildResultColumns() {
+ this.defaultAttributesByColumn = new HashMap();
+
// create alias for root table
newAliasForTable(getRootDbEntity());
@@ -419,21 +422,7 @@
"ObjAttribute has no DbAttribute: " +
oa.getName());
}
- 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;
- }
- }
- }
+ appendColumn(columns, oa, dbAttr, attributes, null);
}
}
}
@@ -659,7 +648,7 @@
return columns;
}
- private boolean appendColumn(
+ private void appendColumn(
List columns,
ObjAttribute objAttribute,
DbAttribute attribute,
@@ -678,10 +667,36 @@
}
columns.add(column);
- return true;
- }
- else {
- return false;
+
+ // TODO: andrus, 5/7/2006 - replace 'columns' collection with this
map, as it
+ // is redundant
+ defaultAttributesByColumn.put(column, objAttribute);
+ }
+ else if (objAttribute != null) {
+
+ // record ObjAttribute override
+ for (int i = 0; i < columns.size(); i++) {
+ ColumnDescriptor column = (ColumnDescriptor) columns.get(i);
+ if (attribute.getName().equals(column.getName())) {
+
+ if (attributeOverrides == null) {
+ attributeOverrides = new HashMap();
+ }
+
+ attributeOverrides.put(objAttribute, column);
+
+ // kick out the original attribute
+ ObjAttribute original = (ObjAttribute)
defaultAttributesByColumn
+ .remove(column);
+
+ if (original != null) {
+ attributeOverrides.put(original, column);
+ column.setJavaClass(Void.TYPE.getName());
+ }
+
+ break;
+ }
+ }
}
}
Modified:
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/types/ExtendedTypeMap.java
URL:
http://svn.apache.org/viewcvs/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/types/ExtendedTypeMap.java?rev=404890&r1=404889&r2=404890&view=diff
==============================================================================
---
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/types/ExtendedTypeMap.java
(original)
+++
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/types/ExtendedTypeMap.java
Sun May 7 18:25:13 2006
@@ -112,6 +112,9 @@
* Registers default extended types. This method is called from
constructor.
*/
protected void initDefaultTypes() {
+ // void placeholder
+ registerType(new VoidType());
+
// register default types
Iterator it = DefaultType.defaultTypes();
while (it.hasNext()) {
Added:
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/types/VoidType.java
URL:
http://svn.apache.org/viewcvs/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/types/VoidType.java?rev=404890&view=auto
==============================================================================
---
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/types/VoidType.java
(added)
+++
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/access/types/VoidType.java
Sun May 7 18:25:13 2006
@@ -0,0 +1,104 @@
+/* ====================================================================
+ *
+ * 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.types;
+
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+
+import org.objectstyle.cayenne.map.DbAttribute;
+import org.objectstyle.cayenne.validation.ValidationResult;
+
+/**
+ * A noop type that is sometimes useful to suppress extended types operations.
It will set
+ * and get null values.
+ *
+ * @since 1.2
+ * @author Andrus Adamchik
+ */
+class VoidType implements ExtendedType {
+
+ public String getClassName() {
+ return Void.TYPE.getName();
+ }
+
+ public boolean validateProperty(
+ Object source,
+ String property,
+ Object value,
+ DbAttribute dbAttribute,
+ ValidationResult validationResult) {
+ return true;
+ }
+
+ public void setJdbcObject(
+ PreparedStatement statement,
+ Object value,
+ int pos,
+ int type,
+ int precision) throws Exception {
+ statement.setNull(pos, type);
+ }
+
+ public Object materializeObject(ResultSet rs, int index, int type) throws
Exception {
+ return null;
+ }
+
+ public Object materializeObject(CallableStatement rs, int index, int type)
+ throws Exception {
+ return null;
+ }
+}
Modified:
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/objectstyle/cayenne/unit/jira/CAY_207String1.java
URL:
http://svn.apache.org/viewcvs/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/objectstyle/cayenne/unit/jira/CAY_207String1.java?rev=404890&r1=404889&r2=404890&view=diff
==============================================================================
---
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/objectstyle/cayenne/unit/jira/CAY_207String1.java
(original)
+++
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/objectstyle/cayenne/unit/jira/CAY_207String1.java
Sun May 7 18:25:13 2006
@@ -63,6 +63,12 @@
protected String string;
public CAY_207String1(String string) {
+ // mock deserialization behavior... if the raw data is invalid, an
exception
+ // should be thrown
+ if (string != null && !string.startsWith("T1")) {
+ throw new IllegalArgumentException(string);
+ }
+
this.string = string;
}
Modified:
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/objectstyle/cayenne/unit/jira/CAY_207String2.java
URL:
http://svn.apache.org/viewcvs/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/objectstyle/cayenne/unit/jira/CAY_207String2.java?rev=404890&r1=404889&r2=404890&view=diff
==============================================================================
---
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/objectstyle/cayenne/unit/jira/CAY_207String2.java
(original)
+++
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/objectstyle/cayenne/unit/jira/CAY_207String2.java
Sun May 7 18:25:13 2006
@@ -63,6 +63,12 @@
protected String string;
public CAY_207String2(String string) {
+ // mock deserialization behavior... if the raw data is invalid, an
exception
+ // should be thrown
+ if (string != null && !string.startsWith("T2")) {
+ throw new IllegalArgumentException(string);
+ }
+
this.string = string;
}
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=404890&r1=404889&r2=404890&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 18:25:13 2006
@@ -186,7 +186,7 @@
.createAndRegisterNewObject(CAY_207Manager2.class);
o2.setPersonType("M2");
o2.setName("aaaa");
- o2.setClientContactType(new CAY_207String1("AAAAA"));
+ o2.setClientContactType(new CAY_207String1("T1:AAAAA"));
// should succeed...
context.commitChanges();
@@ -201,7 +201,7 @@
assertEquals(1, rows.size());
Map map = (Map) rows.get(0);
- assertEquals("AAAAA", map.get("CLIENT_CONTACT_TYPE"));
+ assertEquals("T1:AAAAA", map.get("CLIENT_CONTACT_TYPE"));
}
finally {
cleanup(context);
Modified:
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/resources/dml/unit.jira.CAY_207Tst.xml
URL:
http://svn.apache.org/viewcvs/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/resources/dml/unit.jira.CAY_207Tst.xml?rev=404890&r1=404889&r2=404890&view=diff
==============================================================================
---
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/resources/dml/unit.jira.CAY_207Tst.xml
(original)
+++
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/resources/dml/unit.jira.CAY_207Tst.xml
Sun May 7 18:25:13 2006
@@ -8,13 +8,13 @@
<bean id="M1"
class="org.objectstyle.cayenne.unit.util.UpdatingSQLTemplate">
<constructor-arg
type="java.lang.Class"><value>org.objectstyle.cayenne.testdo.inherit.AbstractPerson</value></constructor-arg>
<constructor-arg><value>
- insert into PERSON (CLIENT_COMPANY_ID, CLIENT_CONTACT_TYPE,
DEPARTMENT_ID, NAME, PERSON_ID, PERSON_TYPE, SALARY) values (null, 'T1', null,
'Manager Type 1', 1, 'M1', 50000)
+ insert into PERSON (CLIENT_COMPANY_ID, CLIENT_CONTACT_TYPE,
DEPARTMENT_ID, NAME, PERSON_ID, PERSON_TYPE, SALARY) values (null, 'T1:a',
null, 'Manager Type 1', 1, 'M1', 50000)
</value></constructor-arg>
</bean>
<bean id="M2" class="org.objectstyle.cayenne.unit.util.UpdatingSQLTemplate">
<constructor-arg
type="java.lang.Class"><value>org.objectstyle.cayenne.testdo.inherit.AbstractPerson</value></constructor-arg>
<constructor-arg><value>
- insert into PERSON (CLIENT_COMPANY_ID, CLIENT_CONTACT_TYPE,
DEPARTMENT_ID, NAME, PERSON_ID, PERSON_TYPE, SALARY) values (null, 'T2', null,
'Manager Type 2', 2, 'M2', 60000)
+ insert into PERSON (CLIENT_COMPANY_ID, CLIENT_CONTACT_TYPE,
DEPARTMENT_ID, NAME, PERSON_ID, PERSON_TYPE, SALARY) values (null, 'T2:b',
null, 'Manager Type 2', 2, 'M2', 60000)
</value></constructor-arg>
</bean>
<bean id="M3" class="org.objectstyle.cayenne.unit.util.UpdatingSQLTemplate">