tomdz 2005/09/30 14:45:15
Modified: src/java/org/apache/ojb/broker/core
PersistenceBrokerImpl.java
DelegatingPersistenceBroker.java
src/java/org/apache/ojb/broker/util ClassHelper.java
src/java/org/apache/ojb/otm/copy
MetadataObjectCopyStrategy.java
src/java/org/apache/ojb/broker PersistenceBroker.java
PersistenceBrokerInternal.java Identity.java
src/java/org/apache/ojb/broker/accesslayer
JdbcAccessImpl.java RowReaderDefaultImpl.java
RowReader.java RsIterator.java
src/java/org/apache/ojb/broker/core/factory
ObjectCreator.java ObjectFactoryDefaultImpl.java
src/java/org/apache/ojb/broker/metadata ClassDescriptor.java
RepositoryXmlHandler.java CreationDescriptor.java
src/java/org/apache/ojb/broker/cache
CachingStrategyTwoLevelImpl.java
Added: src/java/org/apache/ojb/broker/metadata
EnclosingClassReferenceDescriptor.java
Removed: src/java/org/apache/ojb/broker/accesslayer
PkEnumeration.java
Log:
* Added initial support for mapping inner classes using a special reference
descriptor for the corresponding this-reference
* Removed PKEnumeration
Revision Changes Path
1.121 +115 -42
db-ojb/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java
Index: PersistenceBrokerImpl.java
===================================================================
RCS file:
/home/cvs/db-ojb/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java,v
retrieving revision 1.120
retrieving revision 1.121
diff -u -r1.120 -r1.121
--- PersistenceBrokerImpl.java 6 Sep 2005 22:19:19 -0000 1.120
+++ PersistenceBrokerImpl.java 30 Sep 2005 21:45:14 -0000 1.121
@@ -20,10 +20,10 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
-import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.apache.commons.collections.ListUtils;
@@ -46,7 +46,6 @@
import org.apache.ojb.broker.accesslayer.JdbcAccess;
import org.apache.ojb.broker.accesslayer.OJBIterator;
import org.apache.ojb.broker.accesslayer.PagingIterator;
-import org.apache.ojb.broker.accesslayer.PkEnumeration;
import org.apache.ojb.broker.accesslayer.RelationshipPrefetcherFactory;
import org.apache.ojb.broker.accesslayer.RowReader;
import org.apache.ojb.broker.accesslayer.RsIteratorFactory;
@@ -67,8 +66,10 @@
import org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException;
import org.apache.ojb.broker.metadata.CollectionDescriptor;
import org.apache.ojb.broker.metadata.DescriptorRepository;
+import org.apache.ojb.broker.metadata.EnclosingClassReferenceDescriptor;
import org.apache.ojb.broker.metadata.FieldDescriptor;
import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
+import org.apache.ojb.broker.metadata.MetadataException;
import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
import org.apache.ojb.broker.metadata.SequenceDescriptor;
import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
@@ -78,6 +79,7 @@
import org.apache.ojb.broker.query.QueryBySQL;
import org.apache.ojb.broker.query.QueryFactoryNew;
import org.apache.ojb.broker.util.BrokerHelper;
+import org.apache.ojb.broker.util.ClassHelper;
import org.apache.ojb.broker.util.IdentityArrayList;
import org.apache.ojb.broker.util.ObjectModification;
import org.apache.ojb.broker.util.collections.TrackingCollection;
@@ -794,14 +796,15 @@
private void deleteReferences(Object obj, List listRds, boolean
ignoreReferences) throws PersistenceBrokerException
{
// get all members of obj that are references and delete them
- Iterator i = listRds.iterator();
- while (i.hasNext())
+ for (Iterator i = listRds.iterator(); i.hasNext();)
{
- ObjectReferenceDescriptor rds = (ObjectReferenceDescriptor)
i.next();
- if ((!ignoreReferences && rds.getCascadingDelete() ==
ObjectReferenceDescriptor.CASCADE_OBJECT)
+ ObjectReferenceDescriptor rds =
(ObjectReferenceDescriptor)i.next();
+
+ if ((!ignoreReferences && (rds.getCascadingDelete() ==
ObjectReferenceDescriptor.CASCADE_OBJECT))
|| rds.isSuperReferenceDescriptor())
{
Object referencedObject = rds.getPersistentField().get(obj);
+
if (referencedObject != null)
{
doDelete(referencedObject, ignoreReferences);
@@ -1028,24 +1031,23 @@
{
// get all members of obj that are references and store them
Collection listRds = cld.getObjectReferenceDescriptors();
- // return if nothing to do
- if(listRds == null || listRds.size() == 0)
- {
- return;
- }
- Iterator i = listRds.iterator();
- while (i.hasNext())
+
+ if ((listRds != null) && (listRds.size() > 0))
{
- ObjectReferenceDescriptor rds = (ObjectReferenceDescriptor)
i.next();
- /*
- arminw: the super-references (used for table per subclass
inheritance) must
- be performed in any case. The "normal" 1:1 references can be
ignored when
- flag "ignoreReferences" is set
- */
- if((!ignoreReferences && rds.getCascadingStore() !=
ObjectReferenceDescriptor.CASCADE_NONE)
- || rds.isSuperReferenceDescriptor())
+ for (Iterator i = listRds.iterator(); i.hasNext();)
{
- storeAndLinkOneToOne(false, obj, cld, rds, insert);
+ ObjectReferenceDescriptor rds = (ObjectReferenceDescriptor)
i.next();
+ /*
+ arminw: the special references (eg. super-references used
for table per subclass
+ inheritance) must be performed in any case. The "normal" 1:1
references can be
+ ignored when flag "ignoreReferences" is set
+ */
+ if((!ignoreReferences && rds.getCascadingStore() !=
ObjectReferenceDescriptor.CASCADE_NONE)
+ || rds.isSuperReferenceDescriptor()
+ || (rds instanceof EnclosingClassReferenceDescriptor))
+ {
+ storeAndLinkOneToOne(false, obj, cld, rds, insert);
+ }
}
}
}
@@ -1068,7 +1070,10 @@
Identity oid = serviceIdentity().buildIdentity(superCld,
ref);
storeToDb(ref, superCld, oid, insert);
}
- else store(ref);
+ else
+ {
+ store(ref);
+ }
}
link(obj, cld, rds, ref, insert);
}
@@ -1415,6 +1420,92 @@
}
/**
+ * [EMAIL PROTECTED]
+ */
+ public Object materializeEnclosingClassReference(ClassDescriptor
classDesc, Map rowForInnerObj)
+ {
+ Class targetClass = classDesc.getClassOfObject();
+
+ if (!ClassHelper.isNonStaticInnerClass(targetClass))
+ {
+ return null;
+ }
+
+ EnclosingClassReferenceDescriptor outerClassRef =
classDesc.getEnclosingClassReferenceDescriptor();
+ Class outerClass = null;
+ Object outerObj = null;
+
+ if (outerClassRef != null)
+ {
+ ClassDescriptor outerClassDesc =
outerClassRef.getItemClassDescriptor();
+
+ outerClass = outerClassDesc.getClassOfObject();
+
+ Identity outerId = new Identity(outerClassDesc,
+ getTopLevelClass(outerClass),
+
outerClassRef.getForeignKeyFieldDescriptors(classDesc),
+ rowForInnerObj);
+
+ // TODO: this doGetObjectByIdentity call might lead to problems
when the outer
+ // objects references its inner object;
+ // solution: put a unmaterialized proxy for the inner
object into
+ // the materializion cache prior to getting the outer
object
+ outerObj = doGetObjectByIdentity(outerId);
+
+ }
+ // there might be non-persistent outer classes in-between which we
simply
+ // create via reflection
+ return createDirectEnclosingObject(targetClass, outerClass,
outerObj);
+ }
+
+ /**
+ * Creates the hierarchy of enclosing objects between the target class
and the given persistent outer class
+ *
+ * @param targetClass The target inner class (is not
instantiated)
+ * @param directPersistentOuterClass The nearest persistent enclosing
class
+ * @param directPersistentOuterObject The instance of the nearest
persistent enclosing class to use
+ * @return The instance of the direct enclosing class of the target class
+ */
+ private Object createDirectEnclosingObject(Class targetClass, Class
directPersistentOuterClass, Object directPersistentOuterObject)
+ {
+ Class directEnclosingClass = targetClass.getEnclosingClass();
+
+ if ((directPersistentOuterClass != null) &&
directPersistentOuterClass.equals(directEnclosingClass))
+ {
+ return directPersistentOuterObject;
+ }
+ else if (directEnclosingClass.getEnclosingClass() != null)
+ {
+ // recursively create the direct enclosing object of the direct
enclosing class
+ Object oneLevelAboveOuterObj =
createDirectEnclosingObject(directEnclosingClass, directPersistentOuterClass,
directPersistentOuterObject);
+
+ try
+ {
+ return ClassHelper.newInstance(directEnclosingClass,
+ new Class[] {
directEnclosingClass.getEnclosingClass() },
+ new Object[] {
oneLevelAboveOuterObj },
+ true);
+ }
+ catch (Exception ex)
+ {
+ throw new MetadataException("Cannot create instance of class
"+directEnclosingClass.getName()+" because there is no no-arg constructor", ex);
+ }
+ }
+ else
+ {
+ // the direct enclosing class is no inner class itself -> create
with no-arg constructor
+ try
+ {
+ return ClassHelper.newInstance(directEnclosingClass, true);
+ }
+ catch (Exception ex)
+ {
+ throw new MetadataException("Cannot create instance of class
"+directEnclosingClass.getName()+" because there is no no-arg constructor", ex);
+ }
+ }
+ }
+
+ /**
* Retrieve all References (also Collection-attributes) of a given
instance.
* Loading is forced, even if the collection- and reference-descriptors
differ.
* @param pInstance the persistent instance to work with
@@ -1885,24 +1976,6 @@
}
/**
- * Returns an Enumeration of PrimaryKey Objects for objects of class
DataClass.
- * The Elements returned come from a SELECT ... WHERE Statement
- * that is defined by the fields and their coresponding values of
listFields
- * and listValues.
- * Useful for EJB Finder Methods...
- * @param primaryKeyClass the pk class for the searched objects
- * @param query the query
- */
- public Enumeration getPKEnumerationByQuery(Class primaryKeyClass, Query
query) throws PersistenceBrokerException
- {
- if (logger.isDebugEnabled()) logger.debug("getPKEnumerationByQuery "
+ query);
-
- query.setFetchSize(1);
- ClassDescriptor cld = getClassDescriptor(query.getSearchClass());
- return new PkEnumeration(query, cld, primaryKeyClass, this);
- }
-
- /**
* @see org.apache.ojb.broker.PersistenceBroker#update(Object, String[])
*/
public void update(Object obj, String[] fields)
1.25 +8 -9
db-ojb/src/java/org/apache/ojb/broker/core/DelegatingPersistenceBroker.java
Index: DelegatingPersistenceBroker.java
===================================================================
RCS file:
/home/cvs/db-ojb/src/java/org/apache/ojb/broker/core/DelegatingPersistenceBroker.java,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -r1.24 -r1.25
--- DelegatingPersistenceBroker.java 6 Sep 2005 22:19:19 -0000 1.24
+++ DelegatingPersistenceBroker.java 30 Sep 2005 21:45:14 -0000 1.25
@@ -16,7 +16,7 @@
*/
import java.util.Collection;
-import java.util.Enumeration;
+import java.util.Map;
import org.apache.ojb.broker.Identity;
import org.apache.ojb.broker.IdentityFactory;
@@ -325,7 +325,12 @@
getBroker().retrieveReference(pInstance, pAttributeName);
}
- public void retrieveAllReferences(Object pInstance) throws
PersistenceBrokerException
+ public Object materializeEnclosingClassReference(ClassDescriptor
classDesc, Map rowForInnerObj)
+ {
+ return getBroker().materializeEnclosingClassReference(classDesc,
rowForInnerObj);
+ }
+
+ public void retrieveAllReferences(Object pInstance) throws
PersistenceBrokerException
{
getBroker().retrieveAllReferences(pInstance);
}
@@ -405,12 +410,6 @@
return getBroker().getClassDescriptor(clazz);
}
- public Enumeration getPKEnumerationByQuery(Class primaryKeyClass,
-
Query query) throws PersistenceBrokerException
- {
- return getBroker().getPKEnumerationByQuery(primaryKeyClass,
query);
- }
-
public Object getObjectByQuery(Query query) throws
PersistenceBrokerException
{
return getBroker().getObjectByQuery(query);
1.16 +35 -4
db-ojb/src/java/org/apache/ojb/broker/util/ClassHelper.java
Index: ClassHelper.java
===================================================================
RCS file:
/home/cvs/db-ojb/src/java/org/apache/ojb/broker/util/ClassHelper.java,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- ClassHelper.java 3 Sep 2005 15:28:14 -0000 1.15
+++ ClassHelper.java 30 Sep 2005 21:45:14 -0000 1.16
@@ -150,6 +150,17 @@
}
/**
+ * Determines whether the given class is a non-static inner class.
+ *
+ * @param clazz The class
+ * @return <code>true</code> if the class is a non-static inner class
+ */
+ public static boolean isNonStaticInnerClass(Class clazz)
+ {
+ return (clazz.getEnclosingClass() != null) &&
!Modifier.isStatic(clazz.getModifiers());
+ }
+
+ /**
* Returns a new instance of the given class, using the default or a
no-arg constructor.
*
* @param target The class to instantiate
@@ -409,10 +420,12 @@
/**
* Builds a new instance for the class represented by the given class
descriptor.
*
- * @param cld The class descriptor
+ * @param cld The class descriptor
+ * @param args The arguments to the constructor or factory method
+ * @param enclosingObj The enclosing class instance if any
* @return The instance
*/
- public static Object buildNewObjectInstance(ClassDescriptor cld,
Object[] args)
+ public static Object buildNewObjectInstance(ClassDescriptor cld,
Object[] args, Object enclosingObj)
{
Object result = null;
@@ -432,7 +445,25 @@
throw new ClassNotPersistenceCapableException(
"No useable constructor was found in class '" +
cld.getClassNameOfObject() + "'");
}
- result = ConstructorHelper.instantiate(con, args);
+
+ // if we have an enclosing object, we have to add it as the
first argument
+ Object[] realArgs = args;
+
+ if
(ClassHelper.isNonStaticInnerClass(cld.getClassOfObject()))
+ {
+ if ((args == null) || (args.length == 0))
+ {
+ realArgs = new Object[1];
+ }
+ else
+ {
+ realArgs = new Object[args.length + 1];
+ System.arraycopy(args, 0, realArgs, 1, args.length);
+ }
+ realArgs[0] = enclosingObj;
+ }
+
+ result = ConstructorHelper.instantiate(con, realArgs);
}
catch (InstantiationException e)
{
1.26 +1 -1
db-ojb/src/java/org/apache/ojb/otm/copy/MetadataObjectCopyStrategy.java
Index: MetadataObjectCopyStrategy.java
===================================================================
RCS file:
/home/cvs/db-ojb/src/java/org/apache/ojb/otm/copy/MetadataObjectCopyStrategy.java,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- MetadataObjectCopyStrategy.java 3 Sep 2005 15:28:14 -0000 1.25
+++ MetadataObjectCopyStrategy.java 30 Sep 2005 21:45:14 -0000 1.26
@@ -97,7 +97,7 @@
{
args[idx] =
_serialize.copy(argFields[idx].getPersistentField().get(toCopy), null);
}
- retval =
broker.getConfiguration().getObjectFactory().newInstance(cld, args);
+ retval =
broker.getConfiguration().getObjectFactory().newInstance(cld, args, null);
objMap.put(toCopy,retval);
}
catch (Exception e)
1.39 +1 -15
db-ojb/src/java/org/apache/ojb/broker/PersistenceBroker.java
Index: PersistenceBroker.java
===================================================================
RCS file:
/home/cvs/db-ojb/src/java/org/apache/ojb/broker/PersistenceBroker.java,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -r1.38 -r1.39
--- PersistenceBroker.java 6 Sep 2005 22:19:20 -0000 1.38
+++ PersistenceBroker.java 30 Sep 2005 21:45:14 -0000 1.39
@@ -16,7 +16,6 @@
*/
import java.util.Collection;
-import java.util.Enumeration;
import org.apache.ojb.broker.accesslayer.ConnectionManagerIF;
import org.apache.ojb.broker.accesslayer.JdbcAccess;
@@ -444,17 +443,4 @@
* I.e perform a SELECT ... FROM ... WHERE ... in an RDBMS
*/
public Object getObjectByQuery(Query query) throws
PersistenceBrokerException;
-
- /**
- * Returns an Enumeration of PrimaryKey Objects for objects of class
DataClass.
- * The Elements returned come from a SELECT ... WHERE Statement
- * that is defined by the fields and their coresponding values of
vecFields
- * and vecValues.
- * Useful for EJB Finder Methods...
- * NOT YET AWARE OF EXTENTS !
- * @param PrimaryKeyClass the pk class for the searched objects
- * @param query the query
- */
- public Enumeration getPKEnumerationByQuery(Class PrimaryKeyClass, Query
query)
- throws PersistenceBrokerException;
}
1.10 +14 -2
db-ojb/src/java/org/apache/ojb/broker/PersistenceBrokerInternal.java
Index: PersistenceBrokerInternal.java
===================================================================
RCS file:
/home/cvs/db-ojb/src/java/org/apache/ojb/broker/PersistenceBrokerInternal.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- PersistenceBrokerInternal.java 27 Aug 2005 12:23:16 -0000 1.9
+++ PersistenceBrokerInternal.java 30 Sep 2005 21:45:14 -0000 1.10
@@ -1,5 +1,7 @@
package org.apache.ojb.broker;
+import java.util.Map;
+
import org.apache.ojb.broker.accesslayer.CollectionCreationContext;
import org.apache.ojb.broker.accesslayer.RowReader;
import org.apache.ojb.broker.accesslayer.RelationshipPrefetcherFactory;
@@ -108,7 +110,17 @@
* @return QueryReferenceBroker
*/
public QueryReferenceBroker getReferenceBroker();
-
+
+ /**
+ * Creates the enclosing class instance (hierarchy) by retrieving the
necessary data from the database
+ * (for mapped enclosing classes) or by creating them (for non-mapped
enclosing classes).
+ *
+ * @param classDesc The class descriptor
+ * @return The enclosing class instance or <code>null</code> if the
target class is
+ * not a non-static inner class
+ */
+ public Object materializeEnclosingClassReference(ClassDescriptor
classDesc, Map rowForInnerObj);
+
/**
* Refresh the references of the specified object if they have enabled
* the <em>refresh</em> attribute.
1.45 +27 -1 db-ojb/src/java/org/apache/ojb/broker/Identity.java
Index: Identity.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/Identity.java,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -r1.44 -r1.45
--- Identity.java 5 Sep 2005 22:46:15 -0000 1.44
+++ Identity.java 30 Sep 2005 21:45:14 -0000 1.45
@@ -21,6 +21,7 @@
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Arrays;
+import java.util.Map;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
@@ -30,6 +31,7 @@
import org.apache.ojb.broker.core.proxy.IndirectionHandler;
import org.apache.ojb.broker.metadata.ClassDescriptor;
import org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException;
+import org.apache.ojb.broker.metadata.FieldDescriptor;
import org.apache.ojb.broker.util.BrokerHelper;
/**
@@ -116,6 +118,30 @@
checkForPrimaryKeys(null);
}
+ /**
+ * Creates an identity object for the given class descriptor by reading
the field values from
+ * the given map.
+ *
+ * @param targetClass The target class descriptor
+ * @param topLevel The highest persistence-capable class
+ * @param fields The fields to use for building the identity
+ * @param fieldValues The field values keyed by the field names
+ */
+ public Identity(final ClassDescriptor targetClass, final Class topLevel,
final FieldDescriptor[] fields, final Map fieldValues)
+ {
+ Object[] values = new Object[fields.length];
+
+ for (int idx = 0; idx < fields.length; idx++)
+ {
+ values[idx] = fieldValues.get(fields[idx].getColumnName());
+ }
+
+ m_objectsTopLevelClass = topLevel;
+ m_objectsRealClass = targetClass.getClassOfObject();
+ m_pkValues = values;
+ checkForPrimaryKeys(null);
+ }
+
public Identity(final Object objectToIdentitify, final PersistenceBroker
targetBroker)
{
init(objectToIdentitify, targetBroker, null);
1.37 +7 -2
db-ojb/src/java/org/apache/ojb/broker/accesslayer/JdbcAccessImpl.java
Index: JdbcAccessImpl.java
===================================================================
RCS file:
/home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/JdbcAccessImpl.java,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -r1.36 -r1.37
--- JdbcAccessImpl.java 30 Sep 2005 01:46:44 -0000 1.36
+++ JdbcAccessImpl.java 30 Sep 2005 21:45:15 -0000 1.37
@@ -696,9 +696,14 @@
{
Map row = new HashMap();
RowReader rowReader = broker.getRowReaderFor(cld);
+
rs_stmt = new
ResultSetAndStatement(broker.serviceStatementManager(), stmt, rs, sql);
rowReader.readObjectArrayFrom(rs_stmt, row);
- return rowReader.readObjectFrom(row);
+
+ // read enclosing class reference first
+ Object enclosingObj =
broker.materializeEnclosingClassReference(cld, row);
+
+ return rowReader.readObjectFrom(row, enclosingObj);
}
else
{
1.41 +21 -17
db-ojb/src/java/org/apache/ojb/broker/accesslayer/RowReaderDefaultImpl.java
Index: RowReaderDefaultImpl.java
===================================================================
RCS file:
/home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/RowReaderDefaultImpl.java,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -r1.40 -r1.41
--- RowReaderDefaultImpl.java 30 Sep 2005 01:46:44 -0000 1.40
+++ RowReaderDefaultImpl.java 30 Sep 2005 21:45:15 -0000 1.41
@@ -30,9 +30,12 @@
import org.apache.ojb.broker.metadata.ClassDescriptor;
import org.apache.ojb.broker.metadata.CreationDescriptor;
import org.apache.ojb.broker.metadata.CreationParameter;
+import org.apache.ojb.broker.metadata.EnclosingClassReferenceDescriptor;
import org.apache.ojb.broker.metadata.FieldDescriptor;
import org.apache.ojb.broker.metadata.JdbcType;
import org.apache.ojb.broker.metadata.MetadataException;
+import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
+import org.apache.ojb.broker.util.ClassHelper;
import org.apache.ojb.broker.util.SqlHelper;
/**
@@ -92,11 +95,11 @@
* same table.
*
*/
- public Object readObjectFrom(Map row) throws PersistenceBrokerException
+ public Object readObjectFrom(Map row, Object enclosingObj) throws
PersistenceBrokerException
{
// allow to select a specific classdescriptor
ClassDescriptor cld = selectClassDescriptor(row);
- return buildOrRefreshObject(row, cld, null);
+ return buildOrRefreshObject(row, cld, null, enclosingObj);
}
/**
@@ -107,7 +110,7 @@
// 1. select target ClassDescriptor
ClassDescriptor targetClassDescriptor = selectClassDescriptor(row);
// 2. fill all scalar attributes of the existing object
- buildOrRefreshObject(row, targetClassDescriptor, instance);
+ buildOrRefreshObject(row, targetClassDescriptor, instance, null);
}
/**
@@ -120,7 +123,7 @@
* be refreshed.
* @throws PersistenceBrokerException if there ewas an error creating
the new object
*/
- protected Object buildOrRefreshObject(Map row, ClassDescriptor
targetClassDescriptor, Object targetObject)
+ protected Object buildOrRefreshObject(Map row, ClassDescriptor
targetClassDescriptor, Object targetObject, Object enclosingObj)
{
Object result = targetObject;
FieldDescriptor[] fields =
targetClassDescriptor.getFieldDescriptor(true);
@@ -129,7 +132,7 @@
// 1. create new object instance if needed
if (targetObject == null)
{
- result = createInstance(row, targetClassDescriptor);
+ result = createInstance(row, targetClassDescriptor,
enclosingObj);
if
(targetClassDescriptor.getCreationDescriptor().hasParameters())
{
fields = filterFieldDescriptors(fields,
targetClassDescriptor.getCreationDescriptor());
@@ -165,12 +168,13 @@
/**
* Creates a new instance for the given class dscriptor.
- *
- * @param row The row to get parameter values for the construction
- * @param classDesc The class descriptor
+ *
+ * @param row The row to get parameter values for the
construction
+ * @param classDesc The class descriptor
+ * @param enclosingObj The enclosing class instance if any
* @return The new instance
*/
- protected Object createInstance(Map row, ClassDescriptor classDesc)
+ protected Object createInstance(Map row, ClassDescriptor classDesc,
Object enclosingObj)
{
// determine fields to use in the constructor
// remove them from the fields array
@@ -204,12 +208,12 @@
}
}
}
- return factory.newInstance(classDesc, args);
+ return factory.newInstance(classDesc, args, enclosingObj);
}
/**
* Filters the field descriptors so that the fields used as creation
parameters are not in the array.
- *
+ *
* @param fieldDescs The original field descriptors
* @param creationDesc The creation descriptor
* @return The filtered list
@@ -293,7 +297,7 @@
else
{
fields = classDescriptor.getFieldDescriptor(true);
- }
+ }
}
}
readValuesFrom(rs_stmt, row, fields);
@@ -304,10 +308,10 @@
* @throws PersistenceBrokerException if there is an error accessing the
access layer
*/
public void readPkValuesFrom(ResultSetAndStatement rs_stmt, Map row)
- {
+ {
String ojbClass = SqlHelper.getOjbClassName(rs_stmt.m_rs);
ClassDescriptor cld;
-
+
if (ojbClass != null)
{
cld = classDescriptor.getRepository().getDescriptorFor(ojbClass);
@@ -324,12 +328,12 @@
private int getColumnIndex(SelectStatementWrapper statementWrapper,
FieldDescriptor fld)
{
int index = JdbcType.MIN_INT;
-
+
if (statementWrapper != null)
{
index = statementWrapper.getColumnIndex(fld);
}
-
+
return index;
}
1.13 +6 -6
db-ojb/src/java/org/apache/ojb/broker/accesslayer/RowReader.java
Index: RowReader.java
===================================================================
RCS file:
/home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/RowReader.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- RowReader.java 30 Sep 2005 01:46:44 -0000 1.12
+++ RowReader.java 30 Sep 2005 21:45:15 -0000 1.13
@@ -23,16 +23,16 @@
*/
public interface RowReader extends Serializable
{
-// static final long serialVersionUID = -1283322922537162249L;
-
/**
* Materialize a single object from the values of the Map row.
* the implementor of this class must not care for materializing
* references or collection attributes, this is done later!
- * @param row the Map containing the new values
- * @return a properly created instance.
+ *
+ * @param row The map containing the new values
+ * @param enclosingObj The enclosing object for inner classes
+ * @return A properly created instance.
*/
- public Object readObjectFrom(Map row);
+ public Object readObjectFrom(Map row, Object enclosingObj);
/**
* refresh an existing instance from the values of the Map row.
1.80 +8 -15
db-ojb/src/java/org/apache/ojb/broker/accesslayer/RsIterator.java
Index: RsIterator.java
===================================================================
RCS file:
/home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/RsIterator.java,v
retrieving revision 1.79
retrieving revision 1.80
diff -u -r1.79 -r1.80
--- RsIterator.java 30 Sep 2005 01:46:44 -0000 1.79
+++ RsIterator.java 30 Sep 2005 21:45:15 -0000 1.80
@@ -36,7 +36,6 @@
import org.apache.ojb.broker.cache.SessionCache;
import org.apache.ojb.broker.metadata.ClassDescriptor;
import org.apache.ojb.broker.metadata.DescriptorRepository;
-import org.apache.ojb.broker.metadata.FieldDescriptor;
import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
import org.apache.ojb.broker.query.Query;
import org.apache.ojb.broker.query.QueryByCriteria;
@@ -381,19 +380,9 @@
*/
protected Identity getIdentityFromResultSet() throws
PersistenceBrokerException
{
- // fill primary key values from Resultset
- FieldDescriptor fld;
- FieldDescriptor[] pkFields =
getQueryObject().getClassDescriptor().getPkFields();
- Object[] pkValues = new Object[pkFields.length];
+ ClassDescriptor classDesc = getQueryObject().getClassDescriptor();
- for (int i = 0; i < pkFields.length; i++)
- {
- fld = pkFields[i];
- pkValues[i] = getRow().get(fld.getColumnName());
- }
-
- // return identity object build up from primary keys
- return new
Identity(getQueryObject().getClassDescriptor().getClassOfObject(),
getTopLevelClass(), pkValues);
+ return new Identity(classDesc, getTopLevelClass(),
classDesc.getPkFields(), getRow());
}
/**
@@ -422,9 +411,13 @@
// map all field values from the current result set
reader.readObjectArrayFrom(getRsAndStmt(), getRow());
+
// 3. If Object is not in cache
// materialize Object with primitive attributes filled from
current row
- result = reader.readObjectFrom(getRow());
+ // we however have to first retrieve an enclosing class
reference if one exists
+ Object enclosingObj =
getBroker().materializeEnclosingClassReference(getQueryObject().getClassDescriptor(),
getRow());
+
+ result = reader.readObjectFrom(getRow(), enclosingObj);
// result may still be null!
if (result != null)
{
1.3 +8 -6
db-ojb/src/java/org/apache/ojb/broker/core/factory/ObjectCreator.java
Index: ObjectCreator.java
===================================================================
RCS file:
/home/cvs/db-ojb/src/java/org/apache/ojb/broker/core/factory/ObjectCreator.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ObjectCreator.java 3 Sep 2005 15:28:15 -0000 1.2
+++ ObjectCreator.java 30 Sep 2005 21:45:15 -0000 1.3
@@ -28,21 +28,23 @@
/**
* Creates a new instance of the type described by the given class
descriptor.
*
- * @param classDesc The class descriptor
- * @param args The arguments
+ * @param classDesc The class descriptor
+ * @param args The arguments
+ * @param enclosingObj The enclosing class instance
* @return The new instance
* @throws ObjectFactoryException If no new instance could be created
*/
- public Object newInstance(ClassDescriptor classDesc, Object[] args)
throws ObjectFactoryException;
+ public Object newInstance(ClassDescriptor classDesc, Object[] args,
Object enclosingObj) throws ObjectFactoryException;
/**
* Creates a new instance of the type described by the given class
descriptor, that is meant to
* be used as an identity object.
*
- * @param classDesc The class descriptor
- * @param args The arguments
+ * @param classDesc The class descriptor
+ * @param args The arguments
+ * @param enclosingObj The enclosing class instance
* @return The new instance
* @throws ObjectFactoryException If no new instance could be created
*/
- public Object newIdentityInstance(ClassDescriptor classDesc, Object[]
args) throws ObjectFactoryException;
+ public Object newIdentityInstance(ClassDescriptor classDesc, Object[]
args, Object enclosingObj) throws ObjectFactoryException;
}
1.4 +13 -13
db-ojb/src/java/org/apache/ojb/broker/core/factory/ObjectFactoryDefaultImpl.java
Index: ObjectFactoryDefaultImpl.java
===================================================================
RCS file:
/home/cvs/db-ojb/src/java/org/apache/ojb/broker/core/factory/ObjectFactoryDefaultImpl.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- ObjectFactoryDefaultImpl.java 3 Sep 2005 15:28:15 -0000 1.3
+++ ObjectFactoryDefaultImpl.java 30 Sep 2005 21:45:15 -0000 1.4
@@ -33,8 +33,8 @@
/** The registered creators */
private HashMap creators = new HashMap();
- /* (non-Javadoc)
- * @see
org.apache.ojb.broker.core.factory.ObjectFactory#registerCreator(org.apache.ojb.broker.core.factory.ObjectCreator,
java.lang.String)
+ /**
+ * [EMAIL PROTECTED]
*/
public void registerCreator(ObjectCreator creator, String type)
{
@@ -52,8 +52,8 @@
}
}
- /* (non-Javadoc)
- * @see
org.apache.ojb.broker.core.factory.ObjectFactory#registerCreator(org.apache.ojb.broker.core.factory.ObjectCreator,
java.lang.String[])
+ /**
+ * [EMAIL PROTECTED]
*/
public void registerCreator(ObjectCreator creator, String[] types)
{
@@ -67,10 +67,10 @@
}
}
- /* (non-Javadoc)
- * @see
org.apache.ojb.broker.core.factory.ObjectCreator#newInstance(org.apache.ojb.broker.metadata.ClassDescriptor,
java.lang.Object[])
+ /**
+ * [EMAIL PROTECTED]
*/
- public Object newInstance(ClassDescriptor classDesc, Object[] args)
throws ObjectFactoryException
+ public Object newInstance(ClassDescriptor classDesc, Object[] args,
Object enclosingObj) throws ObjectFactoryException
{
try
{
@@ -79,11 +79,11 @@
if (creator != null)
{
- obj = creator.newInstance(classDesc, args);
+ obj = creator.newInstance(classDesc, args, enclosingObj);
}
else
{
- obj = ClassHelper.buildNewObjectInstance(classDesc, args);
+ obj = ClassHelper.buildNewObjectInstance(classDesc, args,
enclosingObj);
}
if (obj instanceof Initializable)
@@ -105,11 +105,11 @@
}
}
- /* (non-Javadoc)
- * @see
org.apache.ojb.broker.core.factory.ObjectCreator#newIdentityInstance(org.apache.ojb.broker.metadata.ClassDescriptor,
java.lang.Object[])
+ /**
+ * [EMAIL PROTECTED]
*/
- public Object newIdentityInstance(ClassDescriptor classDesc, Object[]
args) throws ObjectFactoryException
+ public Object newIdentityInstance(ClassDescriptor classDesc, Object[]
args, Object enclosingObj) throws ObjectFactoryException
{
- return newInstance(classDesc, args);
+ return newInstance(classDesc, args, enclosingObj);
}
}
1.112 +19 -1
db-ojb/src/java/org/apache/ojb/broker/metadata/ClassDescriptor.java
Index: ClassDescriptor.java
===================================================================
RCS file:
/home/cvs/db-ojb/src/java/org/apache/ojb/broker/metadata/ClassDescriptor.java,v
retrieving revision 1.111
retrieving revision 1.112
diff -u -r1.111 -r1.112
--- ClassDescriptor.java 25 Sep 2005 01:55:44 -0000 1.111
+++ ClassDescriptor.java 30 Sep 2005 21:45:15 -0000 1.112
@@ -28,6 +28,8 @@
import java.util.Map;
import java.util.Vector;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.Predicate;
import org.apache.commons.collections.set.ListOrderedSet;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.SystemUtils;
@@ -480,6 +482,22 @@
return m_objectReferenceDescriptorsNameMap;
}
+
+ /**
+ * Returns the reference to the enclosing persistent class if any.
+ *
+ * @return The reference or <code>null</code> if there is no such
reference
+ */
+ public EnclosingClassReferenceDescriptor
getEnclosingClassReferenceDescriptor()
+ {
+ return
(EnclosingClassReferenceDescriptor)CollectionUtils.find(m_ObjectReferenceDescriptors,
+ new
Predicate() {
+ public boolean evaluate(Object input)
+ {
+ return input instanceof EnclosingClassReferenceDescriptor;
+ }
+ });
+ }
/**
* Get an CollectionDescriptor by name BRJ
1.75 +5 -1
db-ojb/src/java/org/apache/ojb/broker/metadata/RepositoryXmlHandler.java
Index: RepositoryXmlHandler.java
===================================================================
RCS file:
/home/cvs/db-ojb/src/java/org/apache/ojb/broker/metadata/RepositoryXmlHandler.java,v
retrieving revision 1.74
retrieving revision 1.75
diff -u -r1.74 -r1.75
--- RepositoryXmlHandler.java 6 Sep 2005 22:19:19 -0000 1.74
+++ RepositoryXmlHandler.java 30 Sep 2005 21:45:15 -0000 1.75
@@ -589,6 +589,10 @@
ord = new SuperReferenceDescriptor(m_CurrentCLD);
}
+ else if (name.endsWith(".this"))
+ {
+ ord = new
EnclosingClassReferenceDescriptor(m_CurrentCLD, name);
+ }
else
{
ord = new
ObjectReferenceDescriptor(m_CurrentCLD);
1.3 +26 -10
db-ojb/src/java/org/apache/ojb/broker/metadata/CreationDescriptor.java
Index: CreationDescriptor.java
===================================================================
RCS file:
/home/cvs/db-ojb/src/java/org/apache/ojb/broker/metadata/CreationDescriptor.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- CreationDescriptor.java 5 Sep 2005 21:35:22 -0000 1.2
+++ CreationDescriptor.java 30 Sep 2005 21:45:15 -0000 1.3
@@ -160,7 +160,7 @@
// we're determining the constructor object lazily
if ((constructor == null) && TYPE_CONSTRUCTOR.equals(getType()))
{
- if (!hasParameters())
+ if (!hasParameters() &&
!ClassHelper.isNonStaticInnerClass(getTargetClass()))
{
try
{
@@ -178,7 +178,7 @@
for (int idx = 0; idx < constructors.length; idx++)
{
- if
(fitsCreationParameters(constructors[idx].getParameterTypes()))
+ if
(fitsCreationParameters(constructors[idx].getParameterTypes(),
getTargetClass().getEnclosingClass()))
{
constructor = constructors[idx];
break;
@@ -276,7 +276,7 @@
for (int idx = 0; idx < methods.length; idx++)
{
if (methods[idx].getName().equals(factoryMethodName) &&
- fitsCreationParameters(methods[idx].getParameterTypes()))
+ fitsCreationParameters(methods[idx].getParameterTypes(),
null))
{
factoryMethod = methods[idx];
break;
@@ -294,24 +294,40 @@
* Determines whether the given method/constructor parameter types fit
the
* creation parameters.
*
- * @param paramTypes
+ * @param paramTypes The parameter types of the constructor/method
to check
+ * @param enclosingClass The optional enclosing instance for non-static
inner classes
+ * which is used as the first parameter for
constructors
* @return <code>true</code> if the given param types fit
*/
- private boolean fitsCreationParameters(Class[] paramTypes)
+ private boolean fitsCreationParameters(Class[] paramTypes, Class
enclosingClass)
{
- if ((paramTypes == null) || (paramTypes.length == 0))
+ int numParamTypes = (paramTypes == null ? 0 : paramTypes.length);
+ int numExpectedParams = parameters.size();
+
+ if (enclosingClass != null)
{
- return parameters.isEmpty();
+ // first param is the enclosing class
+ numExpectedParams++;
}
- else if (paramTypes.length != parameters.size())
+ if (numParamTypes != numExpectedParams)
{
return false;
}
else
{
- for (int idx = 0; idx < paramTypes.length; idx++)
+ int paramOfs = 0;
+
+ if (enclosingClass != null)
+ {
+ if (!enclosingClass.equals(paramTypes[0]))
+ {
+ return false;
+ }
+ paramOfs++;
+ }
+ for (int idx = paramOfs; idx < numParamTypes; idx++)
{
- CreationParameter param =
(CreationParameter)parameters.get(idx);
+ CreationParameter param =
(CreationParameter)parameters.get(idx - paramOfs);
if ((param.getType() != null) &&
!param.getType().equals(paramTypes[idx]))
1.1
db-ojb/src/java/org/apache/ojb/broker/metadata/EnclosingClassReferenceDescriptor.java
Index: EnclosingClassReferenceDescriptor.java
===================================================================
package org.apache.ojb.broker.metadata;
/* Copyright 2003-2004 The Apache Software Foundation
*
* Licensed 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.
*/
import java.lang.reflect.Field;
import org.apache.ojb.broker.metadata.fieldaccess.AnonymousPersistentField;
import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
import org.apache.ojb.broker.util.logging.Logger;
import org.apache.ojb.broker.util.logging.LoggerFactory;
/**
* Specialized reference that handles references from an inner class
(non-static) to an
* enclosing class instance which are necessary to create an inner class
instance.
*
* @version $Id: EnclosingClassReferenceDescriptor.java,v 1.1 2005/09/30
21:45:15 tomdz Exp $
*/
public class EnclosingClassReferenceDescriptor extends
ObjectReferenceDescriptor
{
/** Unique id for serialization */
private static final long serialVersionUID = -6710982246416814483L;
private transient Logger log;
public EnclosingClassReferenceDescriptor(ClassDescriptor descriptor,
String fieldName)
{
super(descriptor);
super.setPersistentField(new EnclosingReferenceField(this,
fieldName));
// needed immutable settings
super.setLazy(false);
super.setCascadeRetrieve(true);
super.setCascadingStore(CASCADE_OBJECT);
// we cannot simply delete the enclosing object because it might have
other inner objects
super.setCascadingDelete(CASCADE_LINK);
}
/**
* [EMAIL PROTECTED]
*/
public void setItemClass(Class c)
{
Class curClass =
getClassDescriptor().getClassOfObject().getEnclosingClass();
while (curClass != null)
{
if (curClass.equals(c))
{
break;
}
else
{
curClass = curClass.getEnclosingClass();
}
}
if (curClass == null)
{
throw new MetadataException("Class "+c.getName()+" is not an
enclosing class of "+getClassDescriptor().getClassNameOfObject());
}
super.setItemClass(c);
// TODO: we should check that the attribute name matches the
respective this reference
}
/**
* [EMAIL PROTECTED]
*/
public void setPersistentField(Class c, String fieldname)
{
// noop
}
/**
* [EMAIL PROTECTED]
*/
public void setPersistentField(PersistentField pf)
{
// noop
}
/**
* [EMAIL PROTECTED]
*/
public void setLazy(boolean lazy)
{
getLog().info("Not allowed to change the lazy property, will ignore
setting");
}
/**
* [EMAIL PROTECTED]
*/
public void setCascadeRetrieve(boolean b)
{
getLog().info("Not allowed to change the auto-retrieve property, will
ignore setting");
}
/**
* [EMAIL PROTECTED]
*/
public void setCascadeStore(boolean cascade)
{
getLog().info("Not allowed to change the auto-update property, will
ignore setting");
}
/**
* [EMAIL PROTECTED]
*/
public void setCascadingStore(int cascade)
{
getLog().info("Not allowed to change the auto-update property, will
ignore setting");
}
/**
* [EMAIL PROTECTED]
*/
public void setCascadingStore(String value)
{
getLog().info("Not allowed to change the auto-update property, will
ignore setting");
}
/**
* [EMAIL PROTECTED]
*/
public void setCascadeDelete(boolean cascade)
{
getLog().info("Not allowed to change the auto-delete property, will
ignore setting");
}
/**
* [EMAIL PROTECTED]
*/
public void setCascadingDelete(int cascade)
{
// TODO: Setting this to CASCADE_OBJECT could be interpreted as:
// "Delete enclosing instance if there are no other inner class
instances
// referencing it"
// However this is not simple because there might be different
(unrelated)
// inner classes, so multiple SELECTs would be necessary
getLog().info("Not allowed to change the auto-delete property, will
ignore setting");
}
/**
* [EMAIL PROTECTED]
*/
public void setCascadingDelete(String value)
{
getLog().info("Not allowed to change the auto-delete property, will
ignore setting");
}
private Logger getLog()
{
if (log == null)
{
log =
LoggerFactory.getLogger(EnclosingClassReferenceDescriptor.class);
}
return log;
}
private static final class EnclosingReferenceField extends
AnonymousPersistentField
{
private static final long serialVersionUID = 6096992757214847399L;
private EnclosingClassReferenceDescriptor enclosingRef;
public EnclosingReferenceField(EnclosingClassReferenceDescriptor
enclosingRef, String name)
{
super(name);
this.enclosingRef = enclosingRef;
}
public synchronized Object get(Object anObject) throws
MetadataException
{
// we have to get outwards the enclosing class hierarchy
Class targetClass = enclosingRef.getItemClass();
Class curClass = anObject.getClass();
Object curObject = anObject;
try
{
do
{
// TODO: This actually returns the this reference to the
outermost class
Field[] declaredFields = curClass.getDeclaredFields();
Field enclosingThisField = null;
// we have to find the field this${n} where {n} is the
depth of the
// enclosing class
for (int idx = 0; idx < declaredFields.length; idx++)
{
if (declaredFields[idx].getName().startsWith("this$"))
{
enclosingThisField = declaredFields[idx];
break;
}
}
enclosingThisField.setAccessible(true);
curObject = enclosingThisField.get(curObject);
curClass = curClass.getEnclosingClass();
}
while ((curClass != null) && !curClass.equals(targetClass));
}
catch (Exception ex)
{
throw new MetadataException(ex);
}
return curObject;
}
public synchronized void set(Object obj, Object value) throws
MetadataException
{
// noop
}
}
}
1.4 +2 -2
db-ojb/src/java/org/apache/ojb/broker/cache/CachingStrategyTwoLevelImpl.java
Index: CachingStrategyTwoLevelImpl.java
===================================================================
RCS file:
/home/cvs/db-ojb/src/java/org/apache/ojb/broker/cache/CachingStrategyTwoLevelImpl.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- CachingStrategyTwoLevelImpl.java 25 Sep 2005 01:44:39 -0000 1.3
+++ CachingStrategyTwoLevelImpl.java 30 Sep 2005 21:45:15 -0000 1.4
@@ -158,7 +158,7 @@
ObjectFactory factory =
getBroker().getConfiguration().getObjectFactory();
FieldDescriptor[] creationFields =
cld.getCreationArgumentFields();
FieldDescriptor[] nonCreationFields =
cld.getNonCreationArgumentFields(true);
- Object target = factory.newInstance(cld,
getFieldValues(source, creationFields));
+ Object target = factory.newInstance(cld,
getFieldValues(source, creationFields), null);
Object[] fieldValues = getFieldValues(source,
nonCreationFields);
// copy main object values
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]