svn commit: r495677 [5/9] - in /db/ojb/trunk: ./ profile/ src/java/org/apache/ojb/broker/ src/java/org/apache/ojb/broker/accesslayer/ src/java/org/apache/ojb/broker/accesslayer/batch/ src/java/org/apache/ojb/broker/accesslayer/sql/ src/java/org/apache/...

[email protected]
Newsgroups gmane.comp.jakarta.ojb.devel
Message-ID <[email protected]>
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java Fri Jan 12 10:19:39 2007
@@ -33,7 +33,6 @@
 import org.apache.ojb.broker.Identity;
 import org.apache.ojb.broker.IdentityFactory;
 import org.apache.ojb.broker.ManageableCollection;
-import org.apache.ojb.broker.MtoNImplementor;
 import org.apache.ojb.broker.OptimisticLockException;
 import org.apache.ojb.broker.PBKey;
 import org.apache.ojb.broker.PBState;
@@ -43,7 +42,6 @@
 import org.apache.ojb.broker.TransactionInProgressException;
 import org.apache.ojb.broker.TransactionNotInProgressException;
 import org.apache.ojb.broker.TransientObjectException;
-import org.apache.ojb.broker.lob.LobHelper;
 import org.apache.ojb.broker.accesslayer.ChainingIterator;
 import org.apache.ojb.broker.accesslayer.CollectionCreationContext;
 import org.apache.ojb.broker.accesslayer.ConnectionManagerIF;
@@ -66,6 +64,7 @@
 import org.apache.ojb.broker.core.proxy.IndirectionHandler;
 import org.apache.ojb.broker.core.proxy.ProxyFactory;
 import org.apache.ojb.broker.core.proxy.VirtualProxy;
+import org.apache.ojb.broker.lob.LobHelper;
 import org.apache.ojb.broker.metadata.BatchDescriptor;
 import org.apache.ojb.broker.metadata.ClassDescriptor;
 import org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException;
@@ -76,7 +75,6 @@
 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;
 import org.apache.ojb.broker.query.Query;
 import org.apache.ojb.broker.query.QueryByCriteria;
@@ -99,11 +97,6 @@
  * and allows to store and retrieve arbitrary objects in/from relational
  * databases accessed by JDBC.
  *
- * @author <a href="mailto:[email protected]">Thomas Mahler<a>
- * @author <a href="mailto:[email protected]">Leandro Rodrigo Saad Cruz<a>
- * @author <a href="mailto:[email protected]">Matthew Baird<a>
- * @author <a href="mailto:[email protected]">Jakob Braeuchi</a>
- *
  * @version $Id$
  */
 public class PersistenceBrokerImpl extends PersistenceBrokerAbstractImpl implements PBState
@@ -121,7 +114,7 @@
     protected boolean brokerLeakDetection;
     protected PersistenceConfiguration persistenceConfiguration;
     protected BrokerHelper brokerHelper;
-    protected MtoNBroker mtoNBroker;
+    public MtoNBroker mtoNBroker;
     protected QueryReferenceBroker referencesBroker;
     /** The proxy factory */
     private ProxyFactory proxyFactory;
@@ -164,7 +157,6 @@
     private IdentityFactory identityFactory;
     private RelationshipPrefetcherFactory relationshipPrefetcherFactory;
     private LobHelper lobHelper;
-    private PBKey pbKey;
 
     /**
      * List of objects being stored now, allows to avoid infinite
@@ -225,23 +217,10 @@
         subContainer             = container.createChildContainer();
 
         JdbcConnectionDescriptor    jcd         = pc.getJdbcConnectionDescriptor();
-        SequenceDescriptor          seqDesc     = jcd.getSequenceDescriptor();
         BatchDescriptor             batchDesc   = jcd.getBatchDescriptor();
 
         subContainer.setSingletonInstance(this);
 
-        // we check whether the sequence descriptor declares different managers/factories
-        if ((seqDesc != null) && (seqDesc.getSequenceManagerClass() != null))
-        {
-            // if a seqMan was defined in repository, use that
-            Class seqManClass = seqDesc.getSequenceManagerClass();
-
-            subContainer.setImplementationClass(SequenceManager.class, seqManClass);
-            if (logger.isDebugEnabled())
-            {
-                logger.debug("Jdbc-Connection-Descriptor '" + jcd.getJcdAlias() + "' use sequence manager: " + seqManClass);
-            }
-        }
         if (batchDesc != null)
         {
             if (batchDesc.getBatchManager() != null)
@@ -258,6 +237,7 @@
             }
         }
 
+        proxyFactory      = (ProxyFactory)subContainer.getSingletonInstance(ProxyFactory.class);
         brokerHelper = new BrokerHelper(this);
         connectionManager = (ConnectionManagerIF)subContainer.getSingletonInstance(ConnectionManagerIF.class);
         identityFactory   = (IdentityFactory)subContainer.getSingletonInstance(IdentityFactory.class);
@@ -265,13 +245,12 @@
         // we're registering the sql generator instance as a singleton so that any pb instance
         // created in the context of this pc will get the same sql generator instance
         sqlGenerator      = (SqlGenerator)subContainer.getSingletonInstance(SqlGenerator.class);
-        dbAccess     = (JdbcAccess) subContainer.getSingletonInstance(JdbcAccess.class);
         batchManager     = (BatchManager) subContainer.getSingletonInstance(BatchManager.class);
         batchManager.setStrategy((BatchStrategy)subContainer.getInstance(BatchStrategy.class));
+        dbAccess     = (JdbcAccess) subContainer.getSingletonInstance(JdbcAccess.class);
         mtoNBroker        = new MtoNBroker(this);
         referencesBroker  = new QueryReferenceBroker(this);
         sessionCache        = (SessionCache)subContainer.getSingletonInstance(SessionCache.class);
-        proxyFactory      = (ProxyFactory)subContainer.getSingletonInstance(ProxyFactory.class);
         queryFactory      = (QueryFactoryNew)subContainer.getSingletonInstance(QueryFactoryNew.class);
         relationshipPrefetcherFactory = new RelationshipPrefetcherFactory(this);
         lobHelper   = (LobHelper)subContainer.getSingletonInstance(LobHelper.class);
@@ -316,7 +295,7 @@
     {
         if (sequenceManager == null)
         {
-            sequenceManager = (SequenceManager)subContainer.getSingletonInstance(SequenceManager.class);
+            sequenceManager = (SequenceManager) subContainer.getSingletonInstance(SequenceManager.class);
         }
         return sequenceManager;
     }
@@ -326,11 +305,6 @@
         return brokerHelper;
     }
 
-    public ObjectCache serviceObjectCache()
-    {
-        return sessionCache.getCachingStrategy(null).getObjectCache();
-    }
-
     public SessionCache serviceSessionCache()
     {
         return sessionCache;
@@ -573,6 +547,10 @@
     {
         if(isInTransaction())
         {
+            if(logger.isEnabledFor(Logger.INFO))
+            {
+                logger.info("Abort transaction for " + this);
+            }
             fireBrokerEvent(BEFORE_ROLLBACK_EVENT);
             setInTransaction(false);
             refreshRegistrationLists();
@@ -601,6 +579,10 @@
         {
             throw new TransactionInProgressException("PersistenceBroker is already in transaction");
         }
+        if(logger.isEnabledFor(Logger.INFO))
+            {
+                logger.info("Begin transaction for " + this);
+            }
         fireBrokerEvent(BEFORE_BEGIN_EVENT);
         setInTransaction(true);
         this.connectionManager.localBegin();
@@ -622,6 +604,10 @@
         {
             throw new TransactionNotInProgressException("PersistenceBroker is NOT in transaction, can't commit");
         }
+        if(logger.isEnabledFor(Logger.INFO))
+            {
+                logger.info("Commit transaction for " + this);
+            }
         fireBrokerEvent(BEFORE_COMMIT_EVENT);
         setInTransaction(false);
         refreshRegistrationLists();
@@ -655,25 +641,37 @@
      */
     public void delete(Object obj, boolean ignoreReferences) throws PersistenceBrokerException
     {
-        if(isTxCheck() && !isInTransaction())
+        if(obj == null)
         {
-            if(logger.isEnabledFor(Logger.ERROR))
-            {
-                String msg = "No running PB-tx found. Please, only delete objects in context of a PB-transaction" +
-                    " to avoid side-effects - e.g. when rollback of complex objects.";
-                try
-                {
-                    throw new Exception("** Delete object without active PersistenceBroker transaction **");
-                }
-                catch(Exception e)
-                {
-                    logger.error(msg, e);
-                }
-            }
+            logger.warn("Specified object to delete is 'null' --> return immediately");
+            return;
+        }
+        // check for tx
+        doTxCheck();
+        try
+        {
+            ClassDescriptor cld = getClassDescriptor(getProxyFactory().getRealClass(obj));
+            Identity oid = serviceIdentity().buildIdentity(cld, obj);
+            doDelete(obj, oid, cld, ignoreReferences);
+        }
+        finally
+        {
+            markedForDelete.clear();
+        }
+    }
+
+    public void delete(Object obj, Identity oid, ClassDescriptor cld, boolean ignoreReferences)
+            throws PersistenceBrokerException
+    {
+        if(obj == null)
+        {
+            logger.warn("Specified object to delete is 'null' --> return immediately");
+            return;
         }
+        doTxCheck();
         try
         {
-            doDelete(obj, ignoreReferences);
+            doDelete(obj, oid, cld, ignoreReferences);
         }
         finally
         {
@@ -693,59 +691,54 @@
      * do delete given object. Should be used by all intern classes to delete
      * objects.
      */
-    private void doDelete(Object obj, boolean ignoreReferences) throws PersistenceBrokerException
+    private void doDelete(Object obj, Identity oid, ClassDescriptor cld, boolean ignoreReferences)
+            throws PersistenceBrokerException
     {
-        //logger.info("DELETING " + obj);
-        // only delete if object is not null
-        if (obj != null)
+        // replace specified object with the real one
+        obj = getProxyFactory().getRealObject(obj);
+        if(cld == null) cld = getClassDescriptor(obj.getClass());
+        if(oid == null) oid = serviceIdentity().buildIdentity(cld, obj);
+
+        /*
+        MBAIRD
+        1. if we are marked for delete already, avoid recursing on this object
+        arminw:
+        use object identity based list, because using objects we get a
+        better performance. I can't find side-effects in doing so.
+         */
+        if (markedForDelete.contains(obj))
         {
-            // replace specified object with the real one
-            obj = getProxyFactory().getRealObject(obj);
+            return;
+        }
 
-            /*
-            MBAIRD
-            1. if we are marked for delete already, avoid recursing on this object
-            arminw:
-            use object identity based list, because using objects we get a
-            better performance. I can't find side-effects in doing so.
-             */
-            if (markedForDelete.contains(obj))
-            {
-                return;
-            }
+        //BRJ: check for valid pk
+        //if (!serviceBrokerHelper().assertValidPkForDelete(cld, obj))
+        // TODO: arminw: this simple check should do the same - verify
+        if (oid.isTransient())
+        {
+            String msg = "Transient object detected. Cannot delete object without valid PK's: " + obj;
+            logger.error(msg);
+            return;
+        }
 
-            ClassDescriptor cld = getClassDescriptor(obj.getClass());
-            Identity oid = serviceIdentity().buildIdentity(cld, obj);
+        /**
+         * MBAIRD
+         * 2. register object in markedForDelete map.
+         */
+        markedForDelete.add(obj);
 
-            //BRJ: check for valid pk
-            //if (!serviceBrokerHelper().assertValidPkForDelete(cld, obj))
-            // TODO: arminw: this simple check should do the same - verify
-            if (oid.isTransient())
-            {
-                String msg = "Cannot delete object without valid PKs: " + obj;
-                logger.error(msg);
-                return;
-            }
-
-            /**
-             * MBAIRD
-             * 2. register object in markedForDelete map.
-             */
-            markedForDelete.add(obj);
-
-            // Invoke events on PersistenceBrokerAware instances and listeners
-            BEFORE_DELETE_EVENT.setTarget(obj);
-            fireBrokerEvent(BEFORE_DELETE_EVENT);
-            BEFORE_DELETE_EVENT.setTarget(null);
-
-            // now perform deletion
-            performDeletion(cld, obj, oid, ignoreReferences);
-
-            // Invoke events on PersistenceBrokerAware instances and listeners
-            AFTER_DELETE_EVENT.setTarget(obj);
-            fireBrokerEvent(AFTER_DELETE_EVENT);
-            AFTER_DELETE_EVENT.setTarget(null);
-        }
+        // Invoke events on PersistenceBrokerAware instances and listeners
+        BEFORE_DELETE_EVENT.setTarget(obj);
+        fireBrokerEvent(BEFORE_DELETE_EVENT);
+        BEFORE_DELETE_EVENT.setTarget(null);
+
+        // now perform deletion
+        performDeletion(cld, obj, oid, ignoreReferences);
+
+        // Invoke events on PersistenceBrokerAware instances and listeners
+        AFTER_DELETE_EVENT.setTarget(obj);
+        fireBrokerEvent(AFTER_DELETE_EVENT);
+        AFTER_DELETE_EVENT.setTarget(null);
     }
 
     /**
@@ -898,7 +891,7 @@
                     }
                     else
                     {
-                        doDelete(referencedObject, ignoreReferences);
+                        doDelete(referencedObject, null, null, ignoreReferences);
                     }
                 }
             }
@@ -928,7 +921,7 @@
                 if(cds.isMtoNRelation())
                 {
                     // if this is a m:n mapped table, remove entries from indirection table
-                    mtoNBroker.deleteMtoNImplementor(cds, obj);
+                    mtoNBroker.deleteAllIndirectionTableEntries(cds.getIndirectionTableDescriptor(), obj);
                 }
                 /*
                 if cascading delete is on, delete all referenced objects.
@@ -943,7 +936,7 @@
                         Iterator colIterator = BrokerHelper.getCollectionIterator(this, col);
                         while (colIterator.hasNext())
                         {
-                            doDelete(colIterator.next(), false);
+                            doDelete(colIterator.next(), null, null, false);
                         }
                     }
                 }
@@ -1039,22 +1032,9 @@
         }
 
         //************************************************
+        // check for runnin tx
+        doTxCheck();
         // now store it:
-        if(isTxCheck() && !isInTransaction())
-        {
-            if(logger.isEnabledFor(Logger.ERROR))
-            {
-                try
-                {
-                    throw new Exception("** Try to store object without active PersistenceBroker transaction **");
-                }
-                catch(Exception e)
-                {
-                    logger.error("No running tx found, please only store in context of an PB-transaction" +
-                    ", to avoid side-effects - e.g. when rollback of complex objects", e);
-                }
-            }
-        }
         // Invoke events on PersistenceBrokerAware instances and listeners
         if (insert)
         {
@@ -1153,7 +1133,7 @@
      * @param rds {@link ObjectReferenceDescriptor} of the real object
      * @param insert flag for insert operation
      */
-    private void storeAndLinkOneToOne(boolean onlyLink, Object obj, ClassDescriptor cld, ObjectReferenceDescriptor rds, boolean insert)
+    void storeAndLinkOneToOne(boolean onlyLink, Object obj, ClassDescriptor cld, ObjectReferenceDescriptor rds, boolean insert)
     {
         Object ref = rds.getPersistentField().get(obj);
         if (!onlyLink && rds.getCascadingStore() == ObjectReferenceDescriptor.CASCADE_OBJECT)
@@ -1241,7 +1221,7 @@
      * @param referencedObjects the referenced objects ({@link ManageableCollection} or Collection or Array) or null
      * @param insert flag for insert operation
      */
-    private void storeAndLinkMtoN(boolean onlyLink, Object obj, CollectionDescriptor cod, Object referencedObjects, boolean insert)
+    void storeAndLinkMtoN(boolean onlyLink, Object obj, CollectionDescriptor cod, Object referencedObjects, boolean insert)
     {
         /*
         - if the collection is a collectionproxy and it's not already loaded
@@ -1279,11 +1259,14 @@
             List existingMtoNKeys;
             if(!insert)
             {
-                existingMtoNKeys = mtoNBroker.getMtoNImplementor(cod, obj);
+                // perform batch to guarantee all indirection table entries
+                serviceBatchManager().executeBatch();
+                existingMtoNKeys = mtoNBroker.getAllIndirectionTableEntries(cod.getIndirectionTableDescriptor(), obj);
                 // we can't reuse iterator
                 referencedObjectsIterator = BrokerHelper.getCollectionIterator(this, referencedObjects);
                 // remove all entries in indirection table which not be part of referenced objects
-                mtoNBroker.deleteMtoNImplementor(cod, obj, referencedObjectsIterator, existingMtoNKeys);
+                mtoNBroker.deleteAllNotMatchedIndirectionTableEntries(
+                        cod.getIndirectionTableDescriptor(), obj, referencedObjectsIterator, existingMtoNKeys);
             }
             else
             {
@@ -1297,7 +1280,8 @@
                 // Now store indirection record
                 // BRJ: this could cause integrity problems because
                 // obj may not be stored depending on auto-update
-                mtoNBroker.storeMtoNImplementor(cod, obj, refObj, existingMtoNKeys);
+                mtoNBroker.storeIndirectionTableEntry(
+                        cod.getIndirectionTableDescriptor(), obj, refObj, existingMtoNKeys);
             }
         }
     }
@@ -1312,7 +1296,7 @@
      * @param referencedObjects the referenced objects ({@link ManageableCollection} or Collection or Array) or null
      * @param insert flag for insert operation
      */
-    private void storeAndLinkOneToMany(boolean linkOnly, Object obj, CollectionDescriptor cod, Object referencedObjects, boolean insert)
+    void storeAndLinkOneToMany(boolean linkOnly, Object obj, CollectionDescriptor cod, Object referencedObjects, boolean insert)
     {
         if(referencedObjects == null)
         {
@@ -1503,7 +1487,7 @@
         if(col.isMtoNRelation())
         {
             // if this is a m:n mapped table, remove entries from indirection table
-            mtoNBroker.deleteMtoNImplementor(col, obj);
+            mtoNBroker.deleteAllIndirectionTableEntries(col.getIndirectionTableDescriptor(), obj);
         }
         else
         {
@@ -1629,7 +1613,7 @@
     {
         if (logger.isDebugEnabled())
         {
-        	logger.debug("Manually retrieving all references for object " + serviceIdentity().buildIdentity(obj));
+            logger.debug("Manually retrieving all references for object " + serviceIdentity().buildIdentity(obj));
         }
         ClassDescriptor cld = getClassDescriptor(obj.getClass());
         try
@@ -1669,7 +1653,7 @@
         if(logger.isDebugEnabled())
         {
             logger.debug("Retrieving reference named ["+pAttributeName+"] on ["+
-        	            pInstance.getClass().getName()+"]");
+                        pInstance.getClass().getName()+"]");
         }
         ClassDescriptor cld = getClassDescriptor(pInstance.getClass());
         CollectionDescriptor cod = cld.getCollectionDescriptorByName(pAttributeName);
@@ -2149,7 +2133,7 @@
             return;
         }
         // check for running tx and unmaterialized proxy
-        if(!perpareForUpdate(obj))
+        if(!checkUpdatePossible(obj))
         {
             return;
         }
@@ -2211,7 +2195,7 @@
             return;
         }
         // check for running tx and unmaterialized proxy
-        if(!perpareForUpdate(obj))
+        if(!checkUpdatePossible(obj))
         {
             return;
         }
@@ -2269,39 +2253,24 @@
 
         dbAccess.executeUpdate(cld, fields, realObject);
         Identity oid = serviceIdentity().buildIdentity(cld, realObject);
-        serviceSessionCache().cache(oid, realObject, SessionCache.TYPE_WRITE, SessionCache.LEVEL_DEEP);
+        serviceSessionCache().cache(oid, realObject, SessionCache.TYPE_UPDATE, SessionCache.LEVEL_DEEP);
 
         AFTER_UPDATE_EVENT.setTarget(realObject);
         fireBrokerEvent(AFTER_UPDATE_EVENT);
         AFTER_UPDATE_EVENT.setTarget(null);
     }
 
-    private boolean perpareForUpdate(Object obj)
+    private boolean checkUpdatePossible(Object obj)
     {
+        doTxCheck();
         boolean result = true;
-        if(isTxCheck() && !isInTransaction())
-        {
-            if(logger.isEnabledFor(Logger.ERROR))
-            {
-                String msg = "No running PB-tx found. Please, only update objects in context of a PB-transaction" +
-                    " to avoid side-effects - e.g. when rollback of complex objects.";
-                try
-                {
-                    throw new Exception("** Update object without active PersistenceBroker transaction **");
-                }
-                catch(Exception e)
-                {
-                    logger.error(msg, e);
-                }
-            }
-        }
         obj = getProxyFactory().getRealObjectIfMaterialized(obj);
         if (obj == null)    // null for unmaterialized Proxy
         {
             result = false;
             if(logger.isEnabledFor(Logger.INFO))
             {
-                logger.info("Skip update, because object is a unmaterialized proxy object: "
+                logger.info("Skip update, because object is an unmaterialized proxy object: "
                 + getProxyFactory().getIndirectionHandler(obj).getIdentity());
             }
         }
@@ -2373,7 +2342,7 @@
         {
             // BRJ: fk values may be part of pk, but the are not known during
             // creation of Identity. so we have to get them here
-            pkValues = serviceBrokerHelper().getKeyValues(cld, obj);
+            pkValues = serviceBrokerHelper().extractValueArray(serviceBrokerHelper().getKeyValues(cld, obj, false));
             if (!serviceBrokerHelper().assertValidPksForStore(cld.getPkFields(), pkValues))
             {
                 String append = insert ? " on insert" : " on update" ;
@@ -2381,26 +2350,6 @@
             }
         }
 
-        // get super class cld then store it with the object
-        /*
-        now for multiple table inheritance
-        1. store super classes, topmost parent first
-        2. go down through heirarchy until current class
-        3. todo: store to full extent?
-
-// arminw: TODO: The extend-attribute feature dosn't work, should we remove this stuff?
-        This if-clause will go up the inheritance heirarchy to store all the super classes.
-        The id for the top most super class will be the id for all the subclasses too
-         */
-        if(cld.getSuperClass() != null)
-        {
-
-            ClassDescriptor superCld = getDescriptorRepository().getDescriptorFor(cld.getSuperClass());
-            storeToDb(obj, superCld, oid, insert);
-            // arminw: why this?? I comment out this section
-            // storeCollections(obj, cld.getCollectionDescriptors(), insert);
-        }
-
         // 2. store primitive typed attributes (Or is THIS step 3 ?)
         // if obj not present in db use INSERT
         if (insert)
@@ -2412,6 +2361,8 @@
             PK values of the object can be changed by the database (use of database identity columns)
             */
             oid = serviceIdentity().buildIdentity(cld, obj);
+            // Add the object to the cache.
+            serviceSessionCache().cache(oid, obj, SessionCache.TYPE_INSERT, SessionCache.LEVEL_DEEP);
         }
         // else use UPDATE
         else
@@ -2426,10 +2377,9 @@
                 serviceSessionCache().evict(oid, SessionCache.LEVEL_DEEP);
                 throw e;
             }
+            // Add the object to the cache.
+            serviceSessionCache().cache(oid, obj, SessionCache.TYPE_UPDATE, SessionCache.LEVEL_DEEP);
         }
-        // cache object for symmetry with getObjectByXXX()
-        // Add the object to the cache.
-        serviceSessionCache().cache(oid, obj, SessionCache.TYPE_WRITE, SessionCache.LEVEL_DEEP);
         // 3. store 1:n and m:n associations except if we have to skip
         if(!ignoreReferences) storeCollections(obj, cld, insert);
     }
@@ -2691,21 +2641,21 @@
         mtoNBroker.reset();
     }
 
-    /**
-     * @see org.apache.ojb.broker.PersistenceBroker#deleteMtoNImplementor
-     */
-    public void deleteMtoNImplementor(MtoNImplementor m2nImpl) throws PersistenceBrokerException
-    {
-        mtoNBroker.deleteMtoNImplementor(m2nImpl);
-    }
-
-    /**
-     * @see org.apache.ojb.broker.PersistenceBroker#addMtoNImplementor
-     */
-    public void addMtoNImplementor(MtoNImplementor m2n) throws PersistenceBrokerException
-    {
-		mtoNBroker.storeMtoNImplementor(m2n);
-    }
+//    /**
+//     * @see org.apache.ojb.broker.PersistenceBroker#deleteMtoNImplementor
+//     */
+//    public void deleteMtoNImplementor(MtoNImplementor m2nImpl) throws PersistenceBrokerException
+//    {
+//        mtoNBroker.deleteMtoNImplementor(m2nImpl);
+//    }
+//
+//    /**
+//     * @see org.apache.ojb.broker.PersistenceBroker#addMtoNImplementor
+//     */
+//    public void addMtoNImplementor(MtoNImplementor m2n) throws PersistenceBrokerException
+//    {
+//		mtoNBroker.storeMtoNImplementor(m2n);
+//    }
 
     /**
      * Get the Identity out of the Query.
@@ -2739,5 +2689,18 @@
     public QueryFactoryNew getQueryFactory()
     {
         return queryFactory;
+    }
+
+    /**
+     * Check if store/delete operation is allowed.
+     */
+    protected void doTxCheck()
+    {
+        if(isTxCheck() && !isInTransaction())
+        {
+            String msg = "No running PB-tx found. Please, only insert/update/delete objects in context" +
+                    " of a PB-transaction to avoid side-effects - e.g. when rollback of complex objects.";
+            throw new PersistenceBrokerException(msg);
+        }
     }
 }

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/core/QueryReferenceBroker.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/core/QueryReferenceBroker.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/core/QueryReferenceBroker.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/core/QueryReferenceBroker.java Fri Jan 12 10:19:39 2007
@@ -65,8 +65,7 @@
     private PersistenceBrokerImpl pb;
     private HashMap m_retrievalTasks;
     private ArrayList prefetchingListeners;
-    private final boolean batchRetrieval = true;
-    private final boolean prefetchProxies = true;
+    private boolean prefetchProxies = true;
     private Class classToPrefetch;
     private PBLifeCycleEvent afterLookupEvent;
 
@@ -77,6 +76,24 @@
     }
 
     /**
+     * Return <em>true</em> if proxy object reference pre-fetching is enabled,
+     * <em>false</em> if disabled.
+     */
+    public boolean isPrefetchProxies()
+    {
+        return prefetchProxies;
+    }
+
+    /**
+     * Enable or disable proxy object reference pre-fetching. By default it's enabled.
+     * @param prefetchProxies If set <em>true</em>, reference pre-fetching will be enabled.
+     */
+    public void setPrefetchProxies(boolean prefetchProxies)
+    {
+        this.prefetchProxies = prefetchProxies;
+    }
+
+    /**
      * Retrieves the collection specified by the given context directly, i.e.
      * the laziness of the context is ignored.
      *
@@ -106,7 +123,7 @@
         int fullSize = -1;
         int size = 0;
 
-        final boolean isRetrievalTasksCreated = batchRetrieval && m_retrievalTasks == null;
+        final boolean isRetrievalTasksCreated = m_retrievalTasks == null;
         if (isRetrievalTasksCreated)
         {
             // Maps ReferenceDescriptors to HashSets of owners
@@ -164,8 +181,9 @@
                             && (cld.getProxyPrefetchingLimit() > 0)
                             && addRetrievalTask(candidate, this))
                     {
-                        new PBMaterializationListener(candidate, m_retrievalTasks,
-                                this, cld.getProxyPrefetchingLimit(), pb.getProxyFactory());
+                        if(log.isDebugEnabled()) log.debug("Add proxy prefetch listener for result candidate of query " + query);
+                        new PBMaterializationListener(candidate, m_retrievalTasks, this,
+                        cld.getProxyPrefetchingLimit(), pb.getProxyFactory());
                     }
                 }
             }
@@ -207,6 +225,13 @@
             log.error(e);
             throw e;
         }
+        catch (Exception ex)
+        {
+            // ==> clear materialization cache
+            pb.serviceSessionCache().clearMaterializationCache();
+            log.error(ex);
+            throw new PersistenceBrokerException(ex);
+        }
         finally
         {
             if (iter != null)
@@ -324,23 +349,18 @@
                 Map.Entry entry = (Map.Entry) it.next();
                 Object key = entry.getKey();
 
-                if (!(key instanceof ObjectReferenceDescriptor))
+                if (key instanceof ObjectReferenceDescriptor)
                 {
-                    continue;
-                }
+                    ObjectReferenceDescriptor ord = (ObjectReferenceDescriptor) key;
+                    ArrayList owners = (ArrayList) entry.getValue();
 
-                ObjectReferenceDescriptor ord = (ObjectReferenceDescriptor) key;
-//                if (ord.isSuperReferenceDescriptor() || ord.isLazy() || (ord.getItemProxyClass() != null))
-                if (ord.isLazy() || (ord.getItemProxyClass() != null))
-                {
-                    continue;
+                    if(!ord.isLazy() && (ord.getItemProxyClass() == null))
+                    {
+                        RelationshipPrefetcher prefetcher = pb.getRelationshipPrefetcherFactory().createRelationshipPrefetcher(ord);
+                        prefetcher.prefetchRelationship(owners);
+                        it.remove();
+                    }
                 }
-
-                RelationshipPrefetcher prefetcher;
-                ArrayList owners = (ArrayList) entry.getValue();
-                prefetcher = pb.getRelationshipPrefetcherFactory().createRelationshipPrefetcher(ord);
-                prefetcher.prefetchRelationship(owners);
-                it.remove();
             }
         }
     }
@@ -348,26 +368,26 @@
     /**
      * Retrieve a single Reference.
      * This implementation retrieves a referenced object from the data backend
-     * if <b>cascade-retrieve</b> is true or if <b>forced</b> is true.
+     * if <b>cascade-retrieve</b> is true or if <b>forceReference</b> is true.
      *
      * @param obj - object that will have it's field set with a referenced object.
      * @param cld - the ClassDescriptor describring obj
      * @param rds - the ObjectReferenceDescriptor of the reference attribute to be loaded
-     * @param forced - if set to true, the reference is loaded even if the rds differs.
+     * @param forceReference if set to true, loading of reference is forced even if cld
+     * auto/cascade retrieve setting differs
      */
-    public void retrieveReference(Object obj, ClassDescriptor cld, ObjectReferenceDescriptor rds, boolean forced)
+    public void retrieveReference(Object obj, ClassDescriptor cld, ObjectReferenceDescriptor rds, boolean forceReference)
     {
         PersistentField refField;
         Object refObj = null;
 
-        if (forced || rds.getCascadeRetrieve())
+        if (forceReference || rds.getCascadeRetrieve())
         {
             pb.serviceSessionCache().enableMaterializationCache();
             try
             {
                 Identity id = getReferencedObjectIdentity(obj, rds, cld);
                 boolean isRefObjDefined = true;
-
                 if (id == null)
                 {
                     refObj = null;
@@ -378,7 +398,7 @@
                     if (rds.isSuperReferenceDescriptor())
                     {
                         // walk the super-references
-                        ClassDescriptor superCld = cld.getRepository().getDescriptorFor(rds.getItemClass());
+                        ClassDescriptor superCld = cld.getSuperClassDescriptor();
                         retrieveReferences(refObj, superCld, false);
                         retrieveCollections(refObj, superCld, false);
                     }
@@ -386,7 +406,7 @@
                 else if ((m_retrievalTasks != null)
                         && !rds.isLazy()
                         && (rds.getItemProxyClass() == null)
-                        && (pb.getClassDescriptor(rds.getItemClass()).getSelectByFKProcedure() == null))
+                        && (rds.getItemClassDescriptor().getSelectByFKProcedure() == null))
                 {
                     addRetrievalTask(obj, rds);
                     isRefObjDefined = false;
@@ -394,6 +414,7 @@
                 else
                 {
                     refObj = getReferencedObject(id, rds);
+                    if(refObj == null) isRefObjDefined = false;
                 }
 
                 if (isRefObjDefined)
@@ -410,6 +431,7 @@
                         if ((handler != null)
                                 && addRetrievalTask(obj, rds))
                         {
+                            if(log.isDebugEnabled()) log.debug("Add proxy prefetch listener for reference " + rds);
                             new PBMaterializationListener(obj, m_retrievalTasks,
                                     rds, rds.getProxyPrefetchingLimit(), pb.getProxyFactory());
                         }
@@ -430,14 +452,15 @@
     /**
      * Retrieve a single Reference.
      * This implementation retrieves a referenced object from the data backend
-     * if <b>cascade-retrieve</b> is true or if <b>forced</b> is true.
+     * if <b>cascade-retrieve</b> is true or if <b>forceReference</b> is true.
      *
      * @param obj - object that will have it's field set with a referenced object.
      * @param cld - the ClassDescriptor describring obj
      * @param rds - the ObjectReferenceDescriptor of the reference attribute to be loaded
-     * @param forced - if set to true, the reference is loaded even if the rds differs.
+     * @param forceReference if set to true, loading of reference is forced even if cld
+     * auto/cascade retrieve setting differs
      */
-    public void retrieveProxyReference(Object obj, ClassDescriptor cld, ObjectReferenceDescriptor rds, boolean forced)
+    public void retrieveProxyReference(Object obj, ClassDescriptor cld, ObjectReferenceDescriptor rds, boolean forceReference)
     {
         PersistentField refField;
         Object refObj = null;
@@ -457,9 +480,9 @@
                         && (rds.getProxyPrefetchingLimit() > 0))
                 {
                     IndirectionHandler handler = pb.getProxyFactory().getIndirectionHandler(refObj);
-
                     if ((handler != null) && addRetrievalTask(obj, rds))
                     {
+                        if(log.isDebugEnabled()) log.debug("Add proxy prefetch listener for reference " + rds);
                         new PBMaterializationListener(obj, m_retrievalTasks, rds, rds.getProxyPrefetchingLimit(), pb.getProxyFactory());
                     }
                 }
@@ -478,12 +501,12 @@
      *
      * @param newObj the instance to be loaded or refreshed
      * @param cld the ClassDescriptor of the instance
-     * @param forced if set to true loading is forced even if cld differs.
+     * @param forceReference if set to true, loading of reference is forced even if cld
+     * auto/cascade retrieve setting differs
      */
-    public void retrieveReferences(Object newObj, ClassDescriptor cld, boolean forced) throws PersistenceBrokerException
+    public void retrieveReferences(Object newObj, ClassDescriptor cld, boolean forceReference) throws PersistenceBrokerException
     {
         Iterator i = cld.getObjectReferenceDescriptors().iterator();
-
         // turn off auto prefetching for related proxies
         final Class saveClassToPrefetch = classToPrefetch;
         classToPrefetch = null;
@@ -494,9 +517,8 @@
             while (i.hasNext())
             {
                 ObjectReferenceDescriptor rds = (ObjectReferenceDescriptor) i.next();
-                retrieveReference(newObj, cld, rds, forced);
+                retrieveReference(newObj, cld, rds, forceReference);
             }
-
             pb.serviceSessionCache().disableMaterializationCache();
         }
         catch(RuntimeException e)
@@ -516,12 +538,12 @@
      *
      * @param newObj the instance to be loaded or refreshed
      * @param cld the ClassDescriptor of the instance
-     * @param forced if set to true loading is forced even if cld differs.
+     * @param forceReference if set to true, loading of reference is forced even if cld
+     * auto/cascade retrieve setting differs
      */
-    public void retrieveProxyReferences(Object newObj, ClassDescriptor cld, boolean forced) throws PersistenceBrokerException
+    public void retrieveProxyReferences(Object newObj, ClassDescriptor cld, boolean forceReference) throws PersistenceBrokerException
     {
         Iterator i = cld.getObjectReferenceDescriptors().iterator();
-
         // turn off auto prefetching for related proxies
         final Class saveClassToPrefetch = classToPrefetch;
         classToPrefetch = null;
@@ -532,7 +554,7 @@
             while (i.hasNext())
             {
                 ObjectReferenceDescriptor rds = (ObjectReferenceDescriptor) i.next();
-                retrieveProxyReference(newObj, cld, rds, forced);
+                retrieveProxyReference(newObj, cld, rds, forceReference);
             }
 
             pb.serviceSessionCache().disableMaterializationCache();
@@ -580,7 +602,7 @@
         else
         {
             // ensure that top-level extents are used for Identities
-            return pb.serviceIdentity().buildIdentity(rds.getItemClass(), pb.getTopLevelClass(rds.getItemClass()), fkValues);
+            return pb.serviceIdentity().buildIdentity(rds.getItemClass(), rds.getItemClassDescriptor().getTopLevelClass(), fkValues);
         }
         return null;
     }
@@ -617,14 +639,6 @@
         if (rds.isLazy())
         {
             /*
-            arminw:
-            use real reference class instead of the top-level class,
-            because we want to use a proxy representing the real class
-            not only the top-level class - right?
-            */
-            //referencedProxy = rds.getItemClassDescriptor().getDynamicProxyClass();
-
-            /*
              * andrew.clute:
              * With proxy generation now handled by the ProxyFactory implementations, the class of the Item
              * is now the nessecary parameter to generate a proxy.
@@ -668,43 +682,43 @@
     /**
      * Retrieve a single Collection on behalf of <b>obj</b>.
      * The Collection is retrieved only if <b>cascade.retrieve is true</b>
-     * or if <b>forced</b> is set to true.     *
+     * or if <b>forceReference</b> is set to true.     *
      *
      * @param obj - the object to be updated
      * @param cld - the ClassDescriptor describing obj
      * @param cds - the CollectionDescriptor describing the collection attribute to be loaded
-     * @param forced - if set to true loading is forced, even if cds differs.
+     * @param forceReference - if set to true loading is forced, even if cds differs.
      *
      */
-    public void retrieveCollection(Object obj, ClassDescriptor cld, CollectionDescriptor cds, boolean forced)
+    public void retrieveCollection(Object obj, ClassDescriptor cld, CollectionDescriptor cds, boolean forceReference)
     {
-        doRetrieveCollection(obj, cds, forced);
+        doRetrieveCollection(obj, cds, forceReference, cds.isLazy());
     }
 
     /**
      * Retrieve a single Proxied Collection on behalf of <b>obj</b>.
      * The Collection is retrieved only if <b>cascade.retrieve is true</b>
-     * or if <b>forced</b> is set to true.     *
+     * or if <b>forceReference</b> is set to true.     *
      *
      * @param obj - the object to be updated
      * @param cld - the ClassDescriptor describing obj
      * @param cds - the CollectionDescriptor describing the collection attribute to be loaded
-     * @param forced - if set to true a proxy will be placed, even if cds differs.
+     * @param forceReference if set to true, loading of reference is forced even if cld
+     * auto/cascade retrieve setting differs
      *
      */
-    public void retrieveProxyCollection(Object obj, ClassDescriptor cld, CollectionDescriptor cds, boolean forced)
+    public void retrieveProxyCollection(Object obj, ClassDescriptor cld, CollectionDescriptor cds, boolean forceReference)
     {
-        doRetrieveCollection(obj, cds, forced);
+        doRetrieveCollection(obj, cds, forceReference, true);
     }
 
-    private void doRetrieveCollection(Object obj, CollectionDescriptor cds, boolean forced)
+    private void doRetrieveCollection(Object obj, CollectionDescriptor cds, boolean forced, boolean lazyLoad)
     {
         if (forced || cds.getCascadeRetrieve())
         {
             if ((m_retrievalTasks != null) && !cds.isLazy()
-                    && !cds.hasProxyItems()
-                    && (cds.getQueryCustomizer() == null)
-                    && (pb.getClassDescriptor(cds.getItemClass()).getSelectByFKProcedure() == null))
+                    && !cds.hasProxyItems() && (cds.getQueryCustomizer() == null)
+                    && (cds.getItemClassDescriptor().getSelectByFKProcedure() == null))
             {
                 addRetrievalTask(obj, cds);
             }
@@ -712,22 +726,22 @@
             {
                 // this collection type will be used:
                 PersistentField collectionField = cds.getPersistentField();
-                Query           fkQuery         = getFKQuery(obj, cds);
-                Object          value;
+                Query fkQuery = getFKQuery(obj, cds);
+                Object value;
 
                 pb.serviceSessionCache().enableMaterializationCache();
                 try
                 {
                     ManageableCollection result = getCollectionByQuery(obj, cds, fkQuery);
-
                     // assign collection to objects attribute
                     // if attribute has an array type build an array, else assign collection directly
                     if (collectionField.getType().isArray() && (result instanceof Collection))
                     {
-                        Collection coll     = (Collection)result;
-                        int        length   = coll.size();
-                        Class      itemtype = collectionField.getType().getComponentType();
-                        int        j        = 0;
+                        // if an array is used we expect a Collection result
+                        Collection coll = (Collection) result;
+                        int length = coll.size();
+                        Class itemtype = collectionField.getType().getComponentType();
+                        int j = 0;
 
                         value = Array.newInstance(itemtype, length);
                         for (Iterator iter = coll.iterator(); iter.hasNext();j++)
@@ -749,6 +763,7 @@
                     {
                         if (addRetrievalTask(obj, cds))
                         {
+                            if(log.isDebugEnabled()) log.debug("Add proxy prefetch listener for collection reference " + cds);
                             new PBCollectionProxyListener(obj,
                                     m_retrievalTasks, cds, cds.getProxyPrefetchingLimit(), pb.getProxyFactory());
                         }
@@ -812,12 +827,12 @@
     }
 
     /**
-     * Get Foreign key query for m:n relationship <br>
+     * Get Foreign key query for m:n relationship
      * supports UNIDIRECTIONAL m:n using QueryByMtoNCriteria.
      *
      * @param obj the owner of the relationship
      * @param cod the CollectionDescriptor
-     * @return org.apache.ojb.broker.query.QueryByCriteria
+     * @return A Query object
      */
     private QueryByCriteria getFKQueryMtoN(Object obj, CollectionDescriptor cod)
     {
@@ -834,7 +849,7 @@
         for (int i = 0; i < itemClassFks.length; i++)
         {
             criteria.addEqualToField(
-                cod.getIndirectionTable() + "." + itemClassFks[i].toString(),
+                cod.getIndirectionTable() + "." + itemClassFks[i],
                 refCld.getPkFields()[i].getAttributeName());
         }
 
@@ -870,12 +885,10 @@
         else
         {
             Criteria criteria = new Criteria();
-
-            for (int idx = 0; idx < fields.length; idx++)
+            for (int i = 0; i < fields.length; i++)
             {
-                criteria.addEqualTo(fields[idx].getAttributeName(), container[idx].getValue());
+                criteria.addEqualTo(fields[i].getAttributeName(), container[i].getValue());
             }
-
             return pb.getQueryFactory().newQuery(refCld.getClassOfObject(), criteria);
         }
     }
@@ -913,12 +926,13 @@
      *
      * @param newObj the instance to be loaded or refreshed
      * @param cld the ClassDescriptor of the instance
-     * @param forced if set to true, loading is forced even if cld differs
+     * @param forceReference if set to true, loading of reference is forced even if cld
+     * auto/cascade retrieve setting differs
      *
      */
-    public void retrieveCollections(Object newObj, ClassDescriptor cld, boolean forced) throws PersistenceBrokerException
+    public void retrieveCollections(Object newObj, ClassDescriptor cld, boolean forceReference) throws PersistenceBrokerException
     {
-        doRetrieveCollections(newObj, cld, forced, false);
+        doRetrieveCollections(newObj, cld, forceReference, false);
     }
 
     /**
@@ -926,15 +940,16 @@
      *
      * @param newObj the instance to be loaded or refreshed
      * @param cld the ClassDescriptor of the instance
-     * @param forced if set to true, loading is forced even if cld differs
+     * @param forceReference if set to true, loading of reference is forced even if cld
+     * auto/cascade retrieve setting differs
      *
      */
-    public void retrieveProxyCollections(Object newObj, ClassDescriptor cld, boolean forced) throws PersistenceBrokerException
+    public void retrieveProxyCollections(Object newObj, ClassDescriptor cld, boolean forceReference) throws PersistenceBrokerException
     {
-        doRetrieveCollections(newObj, cld, forced, true);
+        doRetrieveCollections(newObj, cld, forceReference, true);
     }
 
-    private void doRetrieveCollections(Object newObj, ClassDescriptor cld, boolean forced, boolean forceProxyCollection) throws PersistenceBrokerException
+    private void doRetrieveCollections(Object newObj, ClassDescriptor cld, boolean forceReference, boolean forceProxyCollection) throws PersistenceBrokerException
     {
         Iterator i = cld.getCollectionDescriptors().iterator();
 
@@ -950,11 +965,11 @@
                 CollectionDescriptor cds = (CollectionDescriptor) i.next();
                 if(forceProxyCollection)
                 {
-                    retrieveProxyCollection(newObj, cld, cds, forced);
+                    retrieveProxyCollection(newObj, cld, cds, forceReference);
                 }
                 else
                 {
-                    retrieveCollection(newObj, cld, cds, forced);
+                    retrieveCollection(newObj, cld, cds, forceReference);
                 }
             }
             pb.serviceSessionCache().disableMaterializationCache();
@@ -1110,6 +1125,7 @@
             }
             else
             {
+                if(log.isDebugEnabled()) log.debug("Prefetch limit of " + _limit + " entries rearched");
                 toPrefetch = owners.subList(0, _limit);
                 prefetchingAll = false;
             }
@@ -1118,6 +1134,7 @@
             classToPrefetch = prefetcher.getItemClassDescriptor().getClassOfObject();
             try
             {
+                if(log.isDebugEnabled()) log.debug("Start prefetching of objects for " + prefetcher);
                 prefetcher.prefetchRelationship(toPrefetch);
             }
             finally
@@ -1127,10 +1144,12 @@
 
             if (prefetchingAll)
             {
+                if(log.isDebugEnabled()) log.debug("All objects for key " + _key + " prefetched");
                 _retrievalTasks.remove(_key);
             }
             else
             {
+                if(log.isDebugEnabled()) log.debug("Only objects till limit prefetched for key " + _key);
                 // ArrayList documented trick:
                 // "the following idiom removes a range of elements from a list:
                 // list.subList(from, to).clear();

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/core/ValueContainer.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/core/ValueContainer.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/core/ValueContainer.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/core/ValueContainer.java Fri Jan 12 10:19:39 2007
@@ -18,7 +18,6 @@
 import java.io.Serializable;
 
 import org.apache.commons.lang.ClassUtils;
-import org.apache.commons.lang.builder.EqualsBuilder;
 import org.apache.commons.lang.builder.HashCodeBuilder;
 import org.apache.ojb.broker.metadata.JdbcType;
 
@@ -39,19 +38,22 @@
     private final JdbcType jdbcType;
     private final Object value;
     private final boolean procedureOutParameter;
+    private final boolean procedureInParameter;
     private int hc;
 
-    public ValueContainer(Object value, JdbcType jdbcType)
+    public ValueContainer(final Object value, final JdbcType jdbcType)
     {
         this.jdbcType = jdbcType;
         this.value = value;
         this.procedureOutParameter = false;
+        this.procedureInParameter = false;
     }
 
-    public ValueContainer(Object value, JdbcType jdbcType, boolean procedureOutParameter)
+    public ValueContainer(final Object value, final JdbcType jdbcType, final boolean procedureInParameter, final boolean procedureOutParameter)
     {
         this.value = value;
         this.jdbcType = jdbcType;
+        this.procedureInParameter = procedureInParameter;
         this.procedureOutParameter = procedureOutParameter;
     }
 
@@ -70,6 +72,11 @@
         return procedureOutParameter;
     }
 
+    public boolean isProcedureInParameter()
+    {
+        return procedureInParameter;
+    }
+
     public boolean equals(Object obj)
     {
         if(obj == this) return true;
@@ -80,12 +87,11 @@
             // if jdbcType was null, we can't compare
             result = this.jdbcType != null
                     && this.jdbcType.equals(container.jdbcType)
-                    && this.procedureOutParameter == container.procedureOutParameter;
+                    && this.procedureOutParameter == container.procedureOutParameter
+                    && this.procedureInParameter == container.procedureInParameter;
             if(result)
             {
-                result = new EqualsBuilder()
-                        .append(this.value, container.value)
-                        .isEquals();
+                result = this.value != null ? this.value.equals(container.value) : container.value == null;
             }
         }
         return result;
@@ -93,9 +99,6 @@
 
     public int hashCode()
     {
-//        int hash =  value != null ? value.hashCode() : 0;
-//        hash += jdbcType != null ? jdbcType.hashCode() : 0;
-//        return hash;
         if(hc == 0) hc = new HashCodeBuilder().append(jdbcType).append(value).toHashCode();
         return hc;
     }

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/core/proxy/AbstractIndirectionHandler.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/core/proxy/AbstractIndirectionHandler.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/core/proxy/AbstractIndirectionHandler.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/core/proxy/AbstractIndirectionHandler.java Fri Jan 12 10:19:39 2007
@@ -26,6 +26,7 @@
 import org.apache.ojb.broker.PersistenceBrokerInternal;
 import org.apache.ojb.broker.PersistenceConfiguration;
 import org.apache.ojb.broker.core.PersistenceBrokerThreadMapping;
+import org.apache.ojb.broker.util.logging.Logger;
 import org.apache.ojb.broker.util.logging.LoggerFactory;
 
 /**
@@ -35,17 +36,19 @@
  */
 public abstract class AbstractIndirectionHandler implements IndirectionHandler
 {
-	static final long serialVersionUID = -1993879565033755826L;
+    private static Logger log = LoggerFactory.getLogger(AbstractIndirectionHandler.class);
+
+    static final long serialVersionUID = -1993879565033755826L;
 
     /** The persistence configuration that this indirection handler is bound to */
-	private transient PersistenceConfiguration persistenceConf;
+    private transient PersistenceConfiguration persistenceConf;
     /** The real subject which this is hidden by the proxy */
-    private Object realSubject = null;
+    private Object _realSubject = null;
     /** Represents the identity of the real subject. When the real subject is not
      *  yet materialized, it can be loaded from the underlying db by this identity object */
-    private Identity id = null;
+    private Identity _id = null;
     /** The materialization listeners */
-    private transient ArrayList listeners;
+    private transient ArrayList _listeners;
 
     /**
      * Creates a new indirection handler for the indicated object.
@@ -66,7 +69,7 @@
      */
     public Identity getIdentity()
     {
-        return id;
+        return _id;
     }
 
     /**
@@ -76,11 +79,12 @@
      */
     protected void setIdentity(Identity identity)
     {
-        id = identity;
+        _id = identity;
     }
 
     /**
-     * Returns the key of the persistence broker used by this indirection handler.
+     * Returns the key of the persistence broker used by this indirection
+     * handler.
      * 
      * @return The broker key
      */
@@ -96,14 +100,14 @@
      */
     public synchronized void addListener(MaterializationListener listener)
     {
-        if (listeners == null)
+        if (_listeners == null)
         {
-            listeners = new ArrayList();
+            _listeners = new ArrayList();
         }
         // to avoid multi-add of same listener, do check
-        if(!listeners.contains(listener))
+        if(!_listeners.contains(listener))
         {
-            listeners.add(listener);
+            _listeners.add(listener);
         }
     }
 
@@ -114,9 +118,9 @@
      */
     public synchronized void removeListener(MaterializationListener listener)
     {
-        if (listeners != null)
+        if (_listeners != null)
         {
-            listeners.remove(listener);
+            _listeners.remove(listener);
         }
     }
 
@@ -126,40 +130,40 @@
      */
     protected void beforeMaterialization()
     {
-        if (listeners != null)
+        if (_listeners != null)
         {
             MaterializationListener listener;
 
-            for (int idx = listeners.size() - 1; idx >= 0; idx--)
+            for (int idx = _listeners.size() - 1; idx >= 0; idx--)
             {
-                listener = (MaterializationListener)listeners.get(idx);
-                listener.beforeMaterialization(this, id);
+                listener = (MaterializationListener)_listeners.get(idx);
+                listener.beforeMaterialization(this, _id);
             }
         }
     }
 
     /**
-     * Calls afterMaterialization on all registered listeners in the reverse order
-     * of registration.
+     * Calls afterMaterialization on all registered listeners in the reverse
+     * order of registration.
      */
     protected void afterMaterialization()
     {
-        if (listeners != null)
+        if (_listeners != null)
         {
             MaterializationListener listener;
 
             // listeners may remove themselves during the afterMaterialization callback.
             // thus we must iterate through the listeners vector from back to front
             // to avoid index problems.
-            for (int idx = listeners.size() - 1; idx >= 0; idx--)
+            for (int idx = _listeners.size() - 1; idx >= 0; idx--)
             {
-                listener = (MaterializationListener)listeners.get(idx);
-                listener.afterMaterialization(this, realSubject);
+                listener = (MaterializationListener)_listeners.get(idx);
+                listener.afterMaterialization(this, _realSubject);
             }
         }
     }
 
-	/**
+    /**
      * Gets the persistence broker used by this indirection handler.
      * If no PBKey is available a runtime exception will be thrown.
      * 
@@ -177,7 +181,7 @@
             if no PBKey is set we throw an exception, because we don't
             know which PB (connection) should be used.
             */
-            throw new OJBRuntimeException("Can't find associated PBKey. Need PBKey to obtain a valid" +
+            throw new OJBRuntimeException("Can't find associated PBKey. Need PBKey to obtain a valid " +
                                           "PersistenceBroker instance from intern resources.");
         }
         // first try to use the current threaded broker to avoid blocking
@@ -253,11 +257,11 @@
             // [andrew clute]
             // short-circuit any calls to a finalize methjod if the subject
             // has not been retrieved yet
-            if ("finalize".equals(methodName) && realSubject == null)
+            if ("finalize".equals(methodName) && _realSubject == null)
             {
                 return null;
             }
-            
+
             // [tomdz]
             // Previously the hashcode of the identity would have been used
             // but this requires a compatible hashCode implementation in the
@@ -280,9 +284,9 @@
             // if this is not desired, then the ProxyHandler.toString(Object) method
             // should be used instead (e.g. for logging within OJB)
             /*
-            if ((realSubject == null) && "toString".equals(methodName))
+            if ((_realSubject == null) && "toString".equals(methodName))
             {
-                return "unmaterialized proxy for " + id;
+                return "unmaterialized proxy for " + _id;
             }
             */
 
@@ -293,13 +297,33 @@
                 args[0] = persistenceConf.getOjb().getProxyFactory().getRealObject(args[0]);
             }
 
+            if ("getIndirectionHandler".equals(methodName) && args[0] != null)
+            {
+                return this;
+            }
+
             subject = getRealSubject();
-            return method.invoke(subject, args);
-            // [olegnitz] I've changed the following strange lines
-            // to the above one. Why was this done in such complicated way?
-            // Is it possible that subject doesn't implement the method's interface?
-            // Method m = subject.getClass().getMethod(method.getName(), method.getParameterTypes());
-            // return m.invoke(subject, args);
+            if("toString".equals(methodName) && subject == null)
+            {
+                return null;
+            }
+            /*
+            arminw: If the real subject doesn't exist, return 'null' for all
+            method calls. This could happen e.g. when the FK of a 1:1 reference
+            is the PK of main object. In this case the reference can be null but
+            the FK to the referenced object always exists (because it's the PK of the
+            main object)
+            TODO: Should we log a warn message to indicate abnormal Proxy object behavior?
+            */
+            if(subject == null)
+            {
+                log.warn("Real object of this proxy object doesn't exist, all method will return 'null': " + getIdentity());
+                return null;
+            }
+            else
+            {
+                return method.invoke(subject, args);
+            }
         }
         catch (Exception ex)
         {
@@ -314,13 +338,13 @@
      */
     public Object getRealSubject() throws PersistenceBrokerException
     {
-        if (realSubject == null)
+        if (_realSubject == null)
         {
             beforeMaterialization();
-            realSubject = materializeSubject();
+            _realSubject = materializeSubject();
             afterMaterialization();
         }
-        return realSubject;
+        return _realSubject;
     }
 
     /**
@@ -331,7 +355,7 @@
      */
     public void setRealSubject(Object object)
     {
-        realSubject = object;
+        _realSubject = object;
     }
 
     /**
@@ -345,11 +369,10 @@
         TemporaryBrokerWrapper tmp = getBroker();
         try
         {
-            Object realSubject = tmp.broker.getObjectByIdentity(id);
-
+            Object realSubject = tmp.broker.getObjectByIdentity(_id);
             if (realSubject == null)
             {
-                LoggerFactory.getLogger(IndirectionHandler.class).warn("Can not materialize object for Identity " + id + " - using PBKey " + getBrokerKey());
+                LoggerFactory.getLogger(IndirectionHandler.class).warn("Can not materialize object for Identity " + _id + " - using PBKey " + getBrokerKey());
             }
             return realSubject;
         }
@@ -359,7 +382,7 @@
         }
         finally
         {
-			tmp.close();
+            tmp.close();
         }
     }
 
@@ -370,7 +393,7 @@
      */
     public boolean alreadyMaterialized()
     {
-        return realSubject != null;
+        return _realSubject != null;
     }
 
 

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/core/proxy/ProxyFactory.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/core/proxy/ProxyFactory.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/core/proxy/ProxyFactory.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/core/proxy/ProxyFactory.java Fri Jan 12 10:19:39 2007
@@ -210,4 +210,10 @@
      * @return The string representation
      */
     public String toString(Object proxy);
+
+    /**
+     * Method that returns whether or not this ProxyFactory can generate reference Proxies
+     * for classes regardless if they extend an interface or not.
+     */
+    boolean interfaceRequiredForProxyGeneration();
 }

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/core/proxy/ProxyFactoryCGLIBImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/core/proxy/ProxyFactoryCGLIBImpl.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/core/proxy/ProxyFactoryCGLIBImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/core/proxy/ProxyFactoryCGLIBImpl.java Fri Jan 12 10:19:39 2007
@@ -16,28 +16,28 @@
  */
 
 import java.util.HashMap;
+
 import net.sf.cglib.proxy.Callback;
 import net.sf.cglib.proxy.Enhancer;
 import net.sf.cglib.proxy.Factory;
 
 /**
  * @author andrew.clute
- *
  */
-public class ProxyFactoryCGLIBImpl extends AbstractProxyFactory {
+public class ProxyFactoryCGLIBImpl extends AbstractProxyFactory
+{
 
     private transient HashMap proxyFactories = new HashMap();
-    
-    
+
+
     public Class getDefaultIndirectionHandlerClass()
     {
         return IndirectionHandlerCGLIBImpl.class;
     }
-    
-    
+
+
     /**
      * Returns the class of the base class that the given IndirectionHandler must extend/implement
-     * 
      */
     public Class getIndirectionHandlerBaseClass()
     {
@@ -46,39 +46,46 @@
 
     public OJBProxy createProxy(Class baseClass, IndirectionHandler handler) throws Exception
     {
-        Factory factory = (Factory)proxyFactories.get(baseClass);
-        Object  result  = null;
+        Factory factory = (Factory) proxyFactories.get(baseClass);
+        Object result;
 
-        if (factory == null)
+        if(factory == null)
         {
             Class[] interfaces;
 
-            if (baseClass.isInterface())
+            if(baseClass.isInterface())
             {
-                interfaces = new Class[]{ baseClass, OJBProxy.class };
+                interfaces = new Class[]{baseClass, OJBProxy.class};
             }
             else
             {
-                interfaces = new Class[]{ OJBProxy.class };
+                interfaces = new Class[]{OJBProxy.class};
             }
-            
-            result = (Factory)Enhancer.create(baseClass, interfaces, (Callback)handler);
+
+            result = Enhancer.create(baseClass, interfaces, (Callback) handler);
             proxyFactories.put(baseClass, result);
         }
         else
         {
-            result = factory.newInstance((Callback)handler);
+            result = factory.newInstance((Callback) handler);
         }
-        return (OJBProxy)result;
+        return (OJBProxy) result;
     }
 
-    public boolean isNormalOjbProxy(Object proxyOrObject) {
+    public boolean isNormalOjbProxy(Object proxyOrObject)
+    {
         return super.isNormalOjbProxy(proxyOrObject) && (proxyOrObject instanceof Factory);
     }
 
-    public IndirectionHandler getDynamicIndirectionHandler(Object obj) {
-        return (IndirectionHandler)((Factory)obj).getCallbacks()[0];
+    public IndirectionHandler getDynamicIndirectionHandler(Object obj)
+    {
+        return (IndirectionHandler) ((Factory) obj).getCallbacks()[0];
 
+    }
+
+    public boolean interfaceRequiredForProxyGeneration()
+    {
+        return false;
     }
 
 }

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/core/proxy/ProxyFactoryJDKImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/core/proxy/ProxyFactoryJDKImpl.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/core/proxy/ProxyFactoryJDKImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/core/proxy/ProxyFactoryJDKImpl.java Fri Jan 12 10:19:39 2007
@@ -97,9 +97,6 @@
 
     /**
      * Get interfaces implemented by clazz
-     *
-     * @param clazz
-     * @return
      */
     private Class[] getInterfaces(Class clazz)
     {
@@ -144,6 +141,11 @@
         unique.put(OJBProxy.class.getName(), OJBProxy.class);
 
         return  (Class[])unique.values().toArray(new Class[unique.size()]);
+    }
+
+    public boolean interfaceRequiredForProxyGeneration()
+    {
+        return true;
     }
 
 }

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/locking/IsolationLevels.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/locking/IsolationLevels.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/locking/IsolationLevels.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/locking/IsolationLevels.java Fri Jan 12 10:19:39 2007
@@ -1,11 +1,5 @@
 package org.apache.ojb.broker.locking;
 
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.lang.enums.ValuedEnum;
-
 /* Copyright 2002-2004 The Apache Software Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,6 +14,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang.enums.ValuedEnum;
 
 /**
  * This class defines the lock isolation level constants used by

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/locking/LockManagerInMemoryImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/locking/LockManagerInMemoryImpl.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/locking/LockManagerInMemoryImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/locking/LockManagerInMemoryImpl.java Fri Jan 12 10:19:39 2007
@@ -16,13 +16,13 @@
  */
 
 import java.io.Serializable;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.apache.commons.collections.list.TreeList;
+import org.apache.commons.collections.map.LinkedMap;
 import org.apache.commons.lang.SystemUtils;
 import org.apache.ojb.broker.util.logging.Logger;
 import org.apache.ojb.broker.util.logging.LoggerFactory;
@@ -45,7 +45,7 @@
      * while still maintaining an O(1) lookup like a normal hashmap. We can then
      * use this to get the oldest entries very quickly, makes cleanup a breeze.
      */
-    private final Map resourceLockMap = new LinkedHashMap(70);
+    private final Map resourceLockMap = new LinkedMap(70);
     private final Map keyLockMap = new HashMap();
     private final LockIsolationManager lockStrategyManager = new LockIsolationManager();
     private long m_lastCleanupAt = System.currentTimeMillis();
@@ -274,13 +274,17 @@
         return false;
     }
 
-    /** The number of locked objects. */
+    /**
+     * The number of locked objects.
+     */
     public int lockedObjects()
     {
         return resourceLockMap.size();
     }
 
-    /** Internal method to detect and remove timed out locks. */
+    /**
+     * Internal method to detect and remove timed out locks.
+     */
     private void checkTimedOutLocks()
     {
         if(System.currentTimeMillis() - m_lastCleanupAt > cleanupFrequency)
@@ -290,7 +294,9 @@
         }
     }
 
-    /** removes all timed out lock entries from the persistent storage. */
+    /**
+     * removes all timed out lock entries from the persistent storage.
+     */
     private void removeTimedOutLocks(long timeout)
     {
         int count = 0;
@@ -377,7 +383,7 @@
         List list = (List) keyLockMap.get(key);
         if(list == null)
         {
-            list = new TreeList();
+            list = new ArrayList();
             keyLockMap.put(key, list);
         }
         if(!list.contains(lock)) list.add(lock);

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/ArgumentDescriptor.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/ArgumentDescriptor.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/ArgumentDescriptor.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/ArgumentDescriptor.java Fri Jan 12 10:19:39 2007
@@ -15,11 +15,10 @@
  * limitations under the License.
  */
 
-import org.apache.commons.lang.builder.ToStringBuilder;
-import org.apache.commons.lang.builder.ToStringStyle;
-import org.apache.ojb.broker.accesslayer.conversions.FieldConversion;
 import java.io.Serializable;
 
+import org.apache.ojb.broker.accesslayer.conversions.FieldConversion;
+
 /**
  * An ArgumentDescriptor contains information that defines a single argument
  * that is passed to a procedure/function.
@@ -41,7 +40,8 @@
     private int fieldSource = SOURCE_NULL;
     private String constantValue = null;
     private String fieldRefName = null;
-    private boolean returnedByProcedure = false;
+    private boolean inParameter = true;
+    private boolean outParameter = false;
 
     //---------------------------------------------------------------
     /**
@@ -70,9 +70,12 @@
      */
     public void setValue()
     {
+        verifyValueSetting();
+
         this.fieldSource = SOURCE_NULL;
         this.fieldRefName = null;
-        this.returnedByProcedure = false;
+        this.inParameter = true;
+        this.outParameter = false;
         this.constantValue = null;
     }
 
@@ -81,10 +84,7 @@
      * in the corresponding class-descriptor.
      * <p>
      * If the value of <code>fieldRefName</code> is blank or refers to an
-     * invalid field reference, then the value of the corresponding argument
-     * will be set to null. In this case, {@link #getIsReturnedByProcedure}
-     * will be set to <code>false</code>, regardless of the value of the
-     * <code>returnedByProcedure</code> argument.
+     * invalid field reference a runtime exception will be thrown..
      *
      * @param fieldRefName the name of the field reference that provides the
      *          value of this argument.
@@ -93,23 +93,21 @@
      */
     public void setValue(String fieldRefName, boolean returnedByProcedure)
     {
+        verifyValueSetting();
+
         this.fieldSource = SOURCE_FIELD;
         this.fieldRefName = fieldRefName;
-        this.returnedByProcedure = returnedByProcedure;
+        this.inParameter = !returnedByProcedure;
+        this.outParameter = returnedByProcedure;
         this.constantValue = null;
 
         // If the field reference is not valid, then disregard the value
         // of the returnedByProcedure argument.
         if (this.getFieldRef() == null)
         {
-            this.returnedByProcedure = false;
-        }
-
-        // If the field reference is not valid, then disregard the value
-        // of the returnedByProcedure argument.
-        if (this.getFieldRef() == null)
-        {
-            this.returnedByProcedure = false;
+            throw new MetadataException("Can't resolve field name '" + fieldRefName
+                    + "' for " + getProcedureDescriptor().getClassDescriptor().getClassOfObject()
+                    + " in this argument descriptor");
         }
     }
 
@@ -121,20 +119,18 @@
      */
     public void setValue(String constantValue)
     {
+        verifyValueSetting();
+
         this.fieldSource = SOURCE_VALUE;
         this.fieldRefName = null;
-        this.returnedByProcedure = false;
+        this.inParameter = true;
+        this.outParameter = false;
         this.constantValue = constantValue;
     }
 
-    public boolean getIsReturnedByProcedure()
-    {
-        return this.returnedByProcedure;
-    }
-
     public Object getValue(Object objekt)
     {
-        switch (this.fieldSource)
+        switch (fieldSource)
         {
             case SOURCE_FIELD :
                 if (objekt == null)
@@ -166,26 +162,26 @@
         }
     }
 
-    public void saveValue(Object objekt, Object value)
-    {
-        if ((this.fieldSource == SOURCE_FIELD) && (this.returnedByProcedure))
-        {
-            FieldDescriptor fd = this.getFieldRef();
-            FieldConversion conversion;
-            if (fd != null)
-            {
-                conversion = fd.getFieldConversion();
-                if (conversion == null)
-                {
-                    fd.getPersistentField().set(objekt, value);
-                }
-                else
-                {
-                    fd.getPersistentField().set(objekt, conversion.sqlToJava(value));
-                }
-            }
-        }
-    }
+//    public void saveValue(Object objekt, Object value)
+//    {
+//        if ((this.fieldSource == SOURCE_FIELD) && (this.returnedByProcedure))
+//        {
+//            FieldDescriptor fd = this.getFieldRef();
+//            FieldConversion conversion;
+//            if (fd != null)
+//            {
+//                conversion = fd.getFieldConversion();
+//                if (conversion == null)
+//                {
+//                    fd.getPersistentField().set(objekt, value);
+//                }
+//                else
+//                {
+//                    fd.getPersistentField().set(objekt, conversion.sqlToJava(value));
+//                }
+//            }
+//        }
+//    }
 
     /**
      * Retrieve the field name that this argument is related to.
@@ -221,18 +217,18 @@
      * Retrieve the jdbc type for the field descriptor that is related
      * to this argument.
      */
-    public final int getJdbcType()
+    public final JdbcType getJdbcType()
     {
         switch (this.fieldSource)
         {
             case SOURCE_FIELD :
-                return this.getFieldRef().getJdbcType().getType();
+                return this.getFieldRef().getJdbcType();
             case SOURCE_NULL :
-                return java.sql.Types.NULL;
+                return new JdbcTypes.T_Null();
             case SOURCE_VALUE :
-                return java.sql.Types.VARCHAR;
+                return new JdbcTypes.T_Varchar();
             default :
-                return java.sql.Types.NULL;
+                throw new MetadataException("Can't determine jdbc field type, please check metadata setting");
         }
     }
 
@@ -247,6 +243,29 @@
         return this.procedureDescriptor;
     }
 
+    public boolean isInParameter()
+    {
+        return inParameter;
+    }
+
+    public boolean isOutParameter()
+    {
+        return outParameter;
+    }
+
+    public boolean isConstant()
+    {
+        return constantValue != null;
+    }
+
+    private void verifyValueSetting()
+    {
+        if(isConstant())
+        {
+            throw new MetadataException("It's not allwed to change the type/value of an argument");
+        }
+    }
+
     /*
      * @see XmlCapable#toXML()
      */
@@ -262,7 +281,7 @@
             case SOURCE_FIELD :
                 result += " " + RepositoryTags.getOpeningTagNonClosingById(RUNTIME_ARGUMENT);
                 result += " " + RepositoryTags.getAttribute(FIELD_REF, this.fieldRefName);
-                result += " " + RepositoryTags.getAttribute(RETURN, String.valueOf(this.returnedByProcedure));
+                result += " " + RepositoryTags.getAttribute(RETURN, String.valueOf(this.outParameter));
                 result += "/>";
                 break;
             case SOURCE_VALUE :
@@ -290,25 +309,29 @@
      */
     public String toString()
     {
-        ToStringBuilder buf = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE);
+        StringBuffer buf = new StringBuffer();
+        buf.append("arg[");
         switch (this.fieldSource)
         {
             case SOURCE_FIELD :
                 {
-                    buf.append("fieldRefName", this.fieldRefName);
-                    buf.append("returnedByProcedure", this.returnedByProcedure);
+                    buf.append("fieldRefName=").append(this.fieldRefName);
+                    buf.append(", inParameter=").append(this.inParameter);
+                    buf.append(", outParameter=").append(this.outParameter);
                     break;
                 }
             case SOURCE_NULL :
                 {
+                    buf.append("null");
                     break;
                 }
             case SOURCE_VALUE :
                 {
-                    buf.append("constantValue", this.constantValue);
+                    buf.append("constant=").append(this.constantValue);
                     break;
                 }
         }
+        buf.append("]");
         return buf.toString();
     }
 }

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/AttributeContainer.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/AttributeContainer.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/AttributeContainer.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/AttributeContainer.java Fri Jan 12 10:19:39 2007
@@ -53,8 +53,13 @@
     public Properties getAttributes();
 
     /**
-     * Add map of attributes.
+     * Set attributes.
      */
-    public void addAttributes(Map attributes);
+    public void setAttributes(Properties attributes);
+
+    /**
+     * Add attributes.
+     */
+    public void addAttributes(Properties attributes);
 }
 

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/AttributeDescriptorBase.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/AttributeDescriptorBase.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/AttributeDescriptorBase.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/AttributeDescriptorBase.java Fri Jan 12 10:19:39 2007
@@ -70,11 +70,6 @@
     {
         return m_ClassDescriptor;
     }
-
-    protected ClassDescriptor getDescriptorFor(Class aClass)
-    {
-        return getClassDescriptor().getRepository().getDescriptorFor(aClass);
-    }
     
     /**
      * Sets the classDescriptor.

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/BatchDescriptor.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/BatchDescriptor.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/BatchDescriptor.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/BatchDescriptor.java Fri Jan 12 10:19:39 2007
@@ -5,6 +5,7 @@
 import org.apache.ojb.broker.accesslayer.batch.BatchManagerImpl;
 import org.apache.ojb.broker.accesslayer.batch.BatchStrategyDefaultImpl;
 import org.apache.ojb.broker.accesslayer.batch.ReturnValueValidatorImpl;
+import org.apache.ojb.broker.util.XmlHelper;
 
 /* Copyright 2002-2004 The Apache Software Foundation
  *
@@ -127,11 +128,12 @@
         buf.append(eol);
         buf.append("         Add sequence manger properties here, using custom attributes");
         buf.append(eol);
-        buf.append("         e.g. <attribute attribute-name=\"grabSize\" attribute-value=\"20\"/>");
+        buf.append("         e.g. <attribute attribute-name=\"aKey\" attribute-value=\"aValue\"/>");
         buf.append(eol);
         buf.append("         -->");
         buf.append(eol);
-        buf.append(super.toXML("         "));
+        // custom attributes
+        XmlHelper.appendSerializedAttributes(buf, "        ", getAttributes());
         buf.append("      ");
         buf.append(RepositoryTags.getClosingTagById(BATCH));
         buf.append(eol);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.