You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by ar...@apache.org on 2006/08/05 14:18:15 UTC

svn commit: r428990 [1/5] - in /db/ojb/trunk/proposals/otm: ./ java/ java/org/ java/org/apache/ java/org/apache/ojb/ java/org/apache/ojb/otm/ java/org/apache/ojb/otm/copy/ java/org/apache/ojb/otm/core/ java/org/apache/ojb/otm/kit/ java/org/apache/ojb/o...

Author: arminw
Date: Sat Aug  5 05:18:12 2006
New Revision: 428990

URL: http://svn.apache.org/viewvc?rev=428990&view=rev
Log:
move OTM layer to archive

Added:
    db/ojb/trunk/proposals/otm/
    db/ojb/trunk/proposals/otm/java/
    db/ojb/trunk/proposals/otm/java/org/
    db/ojb/trunk/proposals/otm/java/org/apache/
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/EditingContext.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/Kit.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/OTMConnection.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/OTMKit.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/CloneableObjectCopyStrategy.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/MetadataObjectCopyStrategy.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/NoOpObjectCopyStrategy.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/ObjectCopyException.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/ObjectCopyStrategy.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/OjbCloneable.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/ReflectiveObjectCopyStrategy.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/SerializeObjectCopyStrategy.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/core/
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/core/BaseConnection.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/core/ConcreteEditingContext.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/core/ConnectionException.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/core/LockingPassthruException.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/core/OTMGenericException.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/core/QueryPreparationRuntimeException.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/core/Transaction.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/core/TransactionAbortedException.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/core/TransactionException.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/core/TransactionInProgressException.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/core/TransactionListener.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/core/TransactionNotInProgressException.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/kit/
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/kit/SimpleKit.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/IsolationFactory.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/LockListener.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/LockManager.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/LockType.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/LockingException.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/ObjectLock.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/UnknownIsolationException.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/isolation/
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/isolation/AbstractIsolation.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/isolation/ReadCommittedIsolation.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/isolation/ReadUncommittedIsolation.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/isolation/RepeatableReadIsolation.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/isolation/SerializableIsolation.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/isolation/TransactionIsolation.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/map/
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/map/InMemoryLockMap.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/map/LockMap.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/wait/
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/wait/ConcurrentModificationException.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/wait/DeadlockException.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/wait/LockWaitStrategy.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/wait/NoWaitStrategy.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/lock/wait/TimeoutStrategy.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/states/
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/states/Hollow.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/states/IllegalObjectStateException.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/states/PersistentClean.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/states/PersistentDeleted.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/states/PersistentDirty.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/states/PersistentNew.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/states/PersistentNewDeleted.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/states/State.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/states/Transient.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/swizzle/
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/swizzle/CopySwizzling.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/swizzle/NoSwizzling.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/swizzle/Swizzling.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/transaction/
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/transaction/LocalTransactionFactory.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/transaction/ManagedTransactionFactory.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/transaction/TransactionFactory.java
    db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/transaction/TransactionFactoryException.java
    db/ojb/trunk/proposals/otm/repository_junit_otm.xml
    db/ojb/trunk/proposals/otm/test/
    db/ojb/trunk/proposals/otm/test/org/
    db/ojb/trunk/proposals/otm/test/org/apache/
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/AbstractPerson.java
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/Address.java
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/Address2.java
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/AddressDesc.java
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/AllTests.java
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/CopyTest.java
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/Debitor.java
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/DependentTests.java
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/LegalPerson.java
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/LockTestBase.java
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/LockTestCommittedReads.java
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/LockTestRepeatableReads.java
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/LockTestSerializable.java
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/LockTestUncommittedReads.java
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/MtoNTest.java
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/MultipleConnectionsTest.java
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/NaturalPerson.java
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/OtmExamples.java
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/Person.java
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/SwizzleTests.java
    db/ojb/trunk/proposals/otm/test/org/apache/ojb/otm/TestKit.java

Added: db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/EditingContext.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/EditingContext.java?rev=428990&view=auto
==============================================================================
--- db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/EditingContext.java (added)
+++ db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/EditingContext.java Sat Aug  5 05:18:12 2006
@@ -0,0 +1,88 @@
+package org.apache.ojb.otm;
+
+/* 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 org.apache.ojb.broker.Identity;
+import org.apache.ojb.otm.lock.LockingException;
+import org.apache.ojb.otm.states.State;
+
+import java.util.Collection;
+
+/**
+ *
+ * The EditingContext contains and manages the set of object read/edited within the context of a
+ * transaction. Logically, this could be considered similar to a document that is being edited.
+ * During commit, all objects within this transaction that are marked as being written to (ones
+ * with a write lock) are written back to the persistent store.
+ *
+ * @author <a href="mailto:rraghuram@hotmail.com">Raghu Rajah</a>
+ *
+ */
+public interface EditingContext
+{
+
+    /**
+     *
+     * Insert the given object into the EditingContext, acquiring the specified lock.
+     *
+     * @param oid                   the identity of the object to be inserted
+     * @param userObject            the object to insert, for user operations
+     * @param lock                  the lock to be acquired.
+     * @throws LockingException     thrown by the Lock Manager to avoid deadlocks. The insertion
+     *                              could be re-attempted if the lock fails.
+     *
+     */
+    public void insert (Identity oid, Object userObject, int lock)
+            throws LockingException;
+
+    /**
+     *
+     * Remove a managed object from the management of this EditingContext. All edits on the object
+     * will be lost. All locks kept by this object will be released.
+     *
+     * @param oid                   the Identity of the object to be removed from this context.
+     *
+     */
+    public void remove (Identity oid);
+
+    /**
+     *
+     * Lookup object with the given oid in the Context.
+     *
+     * @param oid           the oid of the object to lookup
+     *
+     */
+    public Object lookup (Identity oid)
+            throws LockingException;
+
+	/**
+	 * lookup the state of an object, given the oid, in the context
+	 * @param oid
+	 * @return the state of that object in the context, null if the object is not in the context
+	 * @throws LockingException
+	 */
+	State lookupState(Identity oid)
+			throws LockingException;
+
+	void setState(Identity oid, State state);
+
+	Collection getAllObjectsInContext();
+
+    /**
+     *  Rollback all changes made during this transaction to the given object.
+     */
+    public void refresh(Identity oid, Object object);
+}

Added: db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/Kit.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/Kit.java?rev=428990&view=auto
==============================================================================
--- db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/Kit.java (added)
+++ db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/Kit.java Sat Aug  5 05:18:12 2006
@@ -0,0 +1,71 @@
+package org.apache.ojb.otm;
+
+/* 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 org.apache.ojb.broker.Identity;
+import org.apache.ojb.broker.PersistenceConfiguration;
+import org.apache.ojb.otm.copy.ObjectCopyStrategy;
+import org.apache.ojb.otm.core.Transaction;
+import org.apache.ojb.otm.lock.map.LockMap;
+import org.apache.ojb.otm.lock.wait.LockWaitStrategy;
+import org.apache.ojb.otm.swizzle.Swizzling;
+
+/**
+ *  The Kit provides the point of entry for any OTM client
+ *
+ *  @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird</a>
+ */
+public interface Kit
+{
+    /**
+     * Acquire an open OTMConnection
+     *
+     * @param persistenceConf
+     * @return
+     */
+	OTMConnection acquireConnection(PersistenceConfiguration persistenceConf);
+
+    /**
+     * Obtain the transaction this connection is bound to
+     */
+	Transaction getTransaction(OTMConnection conn);
+
+    /**
+     * @todo document
+     */
+	Swizzling getSwizzlingStrategy();
+
+    /**
+     * @todo document
+     */
+	LockWaitStrategy getLockWaitStrategy();
+
+    /**
+     * @todo document
+     */
+	LockMap getLockMap();
+
+    /**
+     * @todo document
+     */
+	ObjectCopyStrategy getCopyStrategy(Identity oid);
+
+    /**
+     * @todo document
+     */
+	boolean isImplicitLockingUsed();
+
+}

Added: db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/OTMConnection.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/OTMConnection.java?rev=428990&view=auto
==============================================================================
--- db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/OTMConnection.java (added)
+++ db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/OTMConnection.java Sat Aug  5 05:18:12 2006
@@ -0,0 +1,266 @@
+package org.apache.ojb.otm;
+
+/* 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.util.Collection;
+import java.util.Iterator;
+import org.apache.ojb.broker.Identity;
+import org.apache.ojb.broker.cache.ObjectCache;
+import org.apache.ojb.broker.metadata.ClassDescriptor;
+import org.apache.ojb.broker.query.Query;
+import org.apache.ojb.otm.lock.LockingException;
+import org.apache.ojb.otm.core.Transaction;
+import org.apache.ojb.odmg.oql.EnhancedOQLQuery;
+import org.odmg.OQLQuery;
+
+/**
+ *
+ *  A OTMConnection within the given Environment
+ *
+ *  @author <a href="mailto:rraghuram@hotmail.com">Raghu Rajah</a>
+ */
+public interface OTMConnection
+{
+
+    /**
+     *
+     * Make the given object persistent by inserting it into the database.
+     * Also read locks the object (OTM will automatically lock
+     * it for write on transaction commit if the object will appear
+     * to be modified).
+     *
+     * @param object       the object to be made persistent
+     *
+     */
+    public void makePersistent(Object object)
+            throws LockingException;
+
+    /**
+     * Obtain the Transaction this connection is associated with
+     */
+    public Transaction getTransaction();
+
+    /**
+     * Associate this connection with a given transaction.
+     */
+    public void setTransaction(Transaction tx);
+
+    /**
+     *
+     *  Mark the given object for deletion from the persistent store. The object would then become
+     *  a transient object, rather than a persistent one.
+     *
+     *  @param obj      the object to delete
+     *
+     */
+    public void deletePersistent(Object obj)
+            throws LockingException;
+
+    /**
+     *
+     *  Lock the given object for Write. Only write locked objects are persisted back to the
+     *  database. Changes to read objects are not inserted back into the database.
+     *
+     *  @param object       the object to be locked for write.
+     *
+     */
+    public void lockForWrite(Object object)
+            throws LockingException;
+
+    /**
+     *
+     *  Get the object with the given Identity from the persistent store. By default, the fetch is
+     *  for read. (OTM will automatically lock it for write on transaction commit
+     * if the object will appear to be modified).
+     *
+     *  @param oid                  the Identity of the object to fetch
+     *  @return                     the object from the persistent store.
+     *  @throws LockingException    thrown by the LockManager to avoid deadlocks. The fetch could be
+     *                              re-submitted.
+     *
+     */
+    public Object getObjectByIdentity(Identity oid)
+            throws LockingException;
+
+    /**
+     *
+     * Get the object with the given Identity from the persistent store with the given lock value.
+     *
+     * @param oid                   the Identity of the object to fetch
+     * @param lock                  the lock that need to be acquired on the object
+     * Possible values are:
+     * LockType.NO_LOCK (aka read only) - changes to the object will not be written to database;
+     * LockType.READ_LOCK (aka optimistic lock) - changes to the object will be written to the database,
+     * in this case the lock will be automatically upgraded to the write lock on transaction commit;
+     * LockType.WRITE_LOCK (aka pessimistic lock) - changes to the object will be written to the database.
+     *
+     * @return                     the object from the persistent store.
+     * @throws LockingException     thrown by the LockManager to avoid a deadlock.
+     *
+     */
+    public Object getObjectByIdentity(Identity oid, int lock)
+            throws LockingException;
+
+    /**
+     * @param query The query to execute
+     * @return an Iterator that iterates Objects of class c if calling the .next()
+     * method. The returned objects are locked for read.
+     */
+    public Iterator getIteratorByQuery(Query query);
+
+    /**
+     * @param query The query to execute
+     * @param lock the lock that need to be acquired on the object
+     * Possible values are:
+     * LockType.NO_LOCK (aka read only) - changes to the object will not be written to database;
+     * LockType.READ_LOCK (aka optimistic lock) - changes to the object will be written to the database,
+     * in this case the lock will be automatically upgraded to the write lock on transaction commit;
+     * LockType.WRITE_LOCK (aka pessimistic lock) - changes to the object will be written to the database.
+     * @return an Iterator that iterates Objects of class c if calling the .next()
+     * method. The returned objects are locked with the given lock value.
+     */
+    public Iterator getIteratorByQuery(Query query, int lock);
+
+    /**
+     * @param query The OQL query to execute
+     * @return an Iterator that iterates Objects of class c if calling the .next()
+     * method. The returned objects are locked for read.
+     */
+    public Iterator getIteratorByOQLQuery(OQLQuery query);
+
+    /**
+     * @param query The OQL query to execute
+     * @param lock the lock that need to be acquired on the object
+     * Possible values are:
+     * LockType.NO_LOCK (aka read only) - changes to the object will not be written to database;
+     * LockType.READ_LOCK (aka optimistic lock) - changes to the object will be written to the database,
+     * in this case the lock will be automatically upgraded to the write lock on transaction commit;
+     * LockType.WRITE_LOCK (aka pessimistic lock) - changes to the object will be written to the database.
+     * @return an Iterator that iterates Objects of class c if calling the .next()
+     * method. The returned objects are locked for read.
+     */
+    public Iterator getIteratorByOQLQuery(OQLQuery query, int lock);
+
+    /**
+     * @param query The query to execute
+     * @param lock the lock that need to be acquired on the object
+     * Possible values are:
+     * LockType.NO_LOCK (aka read only) - changes to the object will not be written to database;
+     * LockType.READ_LOCK (aka optimistic lock) - changes to the object will be written to the database,
+     * in this case the lock will be automatically upgraded to the write lock on transaction commit;
+     * LockType.WRITE_LOCK (aka pessimistic lock) - changes to the object will be written to the database.
+     * @return an Iterator that iterates Objects of class c if calling the .next()
+     * method. The returned objects are locked with the given lock value.
+     */
+    public Collection getCollectionByQuery(Query query, int lock);
+
+    /**
+     * @param query The query to execute
+     * @return an Iterator that iterates Objects of class c if calling the .next()
+     * method. The returned objects are locked for read.
+     */
+    public Collection getCollectionByQuery(Query query);
+
+    /**
+     * Get the identity of the object
+     * @param object The object
+     * @return the identity of the object
+     */
+    public Identity getIdentity(Object object);
+
+    public ClassDescriptor getDescriptorFor(Class clazz);
+
+    /**
+     *
+     *  Get the EditingContext associated with the transaction to which this connection belongs.
+     *  EditingContext contains and manages the set of objects read/edited within the current
+     *  transaction.
+     *
+     *  @return                     EditingContext associated with current Transaction
+     *
+     */
+    public EditingContext getEditingContext();
+
+    /**
+     * In the case if the program need to change the objects
+     * via direct JDBC call, it should first call invalidate()
+     * for the object, which will lock the object for write
+     * and tell OJB OTM that it must be re-read from the database,
+     * only after that you shold perform JDBC operation.
+     * NOTE: it is not recommended to use read-uncommitted isolation
+     * if you want this feature to work correctly.
+     */
+    public void invalidate(Identity oid)
+            throws LockingException;
+
+    /**
+     * clear the underlying caches
+     */
+    public void invalidateAll()
+            throws LockingException;
+
+    /**
+     * returns a new OQL Query. This OQL query is Enhanced, meaning it does
+     * the ODMG functionality as well as some additional OJB specific, non
+     * portable functionality.
+     * @return the new OQLQuery
+     */
+    public EnhancedOQLQuery newOQLQuery();
+
+    /**
+     * returns a new OQL Query. This OQL query is Enhanced, meaning it does
+     * the ODMG functionality as well as some additional OJB specific, non
+     * portable functionality.
+     * @param lock the lock that need to be acquired on the object
+     * Possible values are:
+     * LockType.NO_LOCK (aka read only) - changes to the object will not be written to database;
+     * LockType.READ_LOCK (aka optimistic lock) - changes to the object will be written to the database,
+     * in this case the lock will be automatically upgraded to the write lock on transaction commit;
+     * LockType.WRITE_LOCK (aka pessimistic lock) - changes to the object will be written to the database.
+     * @return the new OQLQuery
+     */
+    public EnhancedOQLQuery newOQLQuery(int lock);
+
+    /**
+     * return the number of objects that would be returned from this query
+     * @param query
+     * @return the number of objects that would be returned from this query
+     */
+    int getCount(Query query);
+
+    /**
+     * Close the OTMConnection
+     */
+    void close();
+
+    /**
+     * check if the OTMConnection is closed
+     */
+
+    boolean isClosed();
+
+    /**
+     * get the global cache
+     * @return
+     */
+    ObjectCache serviceObjectCache();
+
+    /**
+     * Updates the values in the object from the data in data store.
+     * The state of the object becomes "Persistent-clean".
+     */
+    void refresh(Object object);
+}

Added: db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/OTMKit.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/OTMKit.java?rev=428990&view=auto
==============================================================================
--- db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/OTMKit.java (added)
+++ db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/OTMKit.java Sat Aug  5 05:18:12 2006
@@ -0,0 +1,91 @@
+package org.apache.ojb.otm;
+
+/* 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 org.apache.ojb.broker.Identity;
+import org.apache.ojb.broker.PersistenceConfiguration;
+import org.apache.ojb.otm.copy.ObjectCopyStrategy;
+import org.apache.ojb.otm.core.Transaction;
+import org.apache.ojb.otm.lock.map.LockMap;
+import org.apache.ojb.otm.lock.wait.LockWaitStrategy;
+import org.apache.ojb.otm.swizzle.Swizzling;
+import org.apache.ojb.otm.transaction.TransactionFactory;
+
+/**
+ *
+ * OTMKit implementations provide the initial point of entry
+ * into the OTM layer.
+ *
+ * @author <a href="mailto:rraghuram@hotmail.com">Raghu Rajah</a>
+ *
+ */
+public abstract class OTMKit implements Kit
+{
+    /**
+     * Obtain an OTMConnection for the given persistence broker key
+     */
+    public OTMConnection acquireConnection(PersistenceConfiguration persistenceConf)
+    {
+        TransactionFactory txFactory = getTransactionFactory();
+
+        return txFactory.acquireConnection(persistenceConf);
+    }
+
+    /**
+     * Obtain the transaction which <code>conn</code> is currently
+     * bound to.
+     */
+    public Transaction getTransaction(OTMConnection conn)
+    {
+        TransactionFactory txFactory = getTransactionFactory();
+        Transaction tx = txFactory.getTransactionForConnection(conn);
+        tx.setKit(this);
+        return tx;
+    }
+
+    ////////////////////////////
+    // Abstract Methods
+    ////////////////////////////
+
+    protected abstract TransactionFactory getTransactionFactory();
+
+    public abstract Swizzling getSwizzlingStrategy();
+
+    public abstract LockWaitStrategy getLockWaitStrategy();
+
+    public abstract LockMap getLockMap();
+
+    public abstract ObjectCopyStrategy getCopyStrategy(Identity oid);
+
+    /**
+     * Should OTM implicitely read lock all objects that are reachable
+     * from the explicitely locked object? The updates to the read locked
+     * objects are automatically stored to the database at the end
+     * of transaction.
+     **/
+    public abstract boolean isImplicitLockingUsed();
+
+    /**
+     * Should OTM verify each inserted object for presence in the database?
+     **/
+    public abstract boolean isInsertVerified();
+
+    /**
+     * Should OTM perform INSERTs for the given object eagerly or during commit?
+     **/
+    public abstract boolean isEagerInsert(Object obj);
+
+}

Added: db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/CloneableObjectCopyStrategy.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/CloneableObjectCopyStrategy.java?rev=428990&view=auto
==============================================================================
--- db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/CloneableObjectCopyStrategy.java (added)
+++ db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/CloneableObjectCopyStrategy.java Sat Aug  5 05:18:12 2006
@@ -0,0 +1,57 @@
+package org.apache.ojb.otm.copy;
+
+/* 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 org.apache.ojb.broker.PersistenceBroker;
+
+
+/**
+ * @author matthew.baird
+ */
+public class CloneableObjectCopyStrategy implements ObjectCopyStrategy
+{
+	/**
+	 * If users want to implement clone on all their objects, we can use this
+	 * to make copies. This is hazardous as user may mess it up, but it is also
+	 * potentially the fastest way of making a copy.
+	 *
+	 * Usually the OjbCloneable interface should just be delegating to the clone()
+	 * operation that the user has implemented.
+	 *
+	 * @see org.apache.ojb.otm.copy.ObjectCopyStrategy#copy(Object)
+	 *
+	 */
+	public Object copy(Object obj, PersistenceBroker broker)
+			throws ObjectCopyException
+	{
+		if (obj instanceof OjbCloneable)
+		{
+			try
+			{
+				return ((OjbCloneable) obj).ojbClone();
+			}
+			catch (Exception e)
+			{
+				throw new ObjectCopyException(e);
+			}
+		}
+		else
+		{
+			throw new ObjectCopyException("Object must implement OjbCloneable in order to use the"
+										  + " CloneableObjectCopyStrategy");
+		}
+	}
+}

Added: db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/MetadataObjectCopyStrategy.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/MetadataObjectCopyStrategy.java?rev=428990&view=auto
==============================================================================
--- db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/MetadataObjectCopyStrategy.java (added)
+++ db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/MetadataObjectCopyStrategy.java Sat Aug  5 05:18:12 2006
@@ -0,0 +1,216 @@
+package org.apache.ojb.otm.copy;
+
+/* 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.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.ojb.broker.PersistenceBroker;
+import org.apache.ojb.broker.core.proxy.CollectionProxy;
+import org.apache.ojb.broker.core.proxy.ProxyFactory;
+import org.apache.ojb.broker.metadata.ClassDescriptor;
+import org.apache.ojb.broker.metadata.CollectionDescriptor;
+import org.apache.ojb.broker.metadata.FieldDescriptor;
+import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
+import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
+import org.apache.ojb.broker.util.IdentityMapFactory;
+
+/**
+ * recursively copies an object based on the ClassDescriptor
+ * User: matthew.baird
+ * Date: Jul 7, 2003
+ * Time: 1:41:58 PM
+ */
+public final class MetadataObjectCopyStrategy implements ObjectCopyStrategy
+{
+    private static final ReflectiveObjectCopyStrategy _reflective = new ReflectiveObjectCopyStrategy();
+    private static final SerializeObjectCopyStrategy _serialize = new SerializeObjectCopyStrategy();
+
+    /**
+     * Uses an IdentityMap to make sure we don't recurse infinitely on the same object in a cyclic object model.
+     * Proxies
+     * @param obj
+     * @return
+     */
+    public Object copy(final Object obj, final PersistenceBroker broker)
+    {
+        return clone(obj, IdentityMapFactory.getIdentityMap(), broker);
+    }
+
+    private static Object clone(final Object toCopy, final Map objMap, final PersistenceBroker broker)
+    {
+        /**
+         * first, check to make sure we aren't recursing to some object that we've already copied.
+         * if the toCopy is in the objMap, just return it.
+         */
+        if (objMap.containsKey(toCopy)) return objMap.get(toCopy);
+        /**
+         * if null, return null, duh
+         */
+        if (toCopy == null)
+            return null;
+
+        /**
+         * if this is a proxy, just copy the proxy, don't materialize it, and stop recursing
+         */
+        ProxyFactory proxyFactory = broker.getConfiguration().getOjb().getProxyFactory();
+        if (proxyFactory.isVirtualOjbProxy(toCopy))
+        {
+            return _reflective.copy(toCopy, null);
+        }
+        else if (proxyFactory.isNormalOjbProxy(toCopy))
+        {
+            return _serialize.copy(toCopy, null);
+        }
+
+        /**
+         * if no classdescriptor exists for this object, just return this object, we
+         * can't copy it.
+         */
+        final ClassDescriptor cld = broker.getClassDescriptor(toCopy.getClass());
+        if (cld == null)
+        {
+            return _reflective.copy(toCopy, null);
+        }
+
+        final Object retval;
+        try
+        {
+            FieldDescriptor[] argFields = cld.getCreationArgumentFields();
+            Object[]          args      = new Object[argFields.length];
+
+            for (int idx = 0; idx < argFields.length; idx++)
+            {
+                args[idx] = _serialize.copy(argFields[idx].getPersistentField().get(toCopy), null);
+            }
+            retval = broker.getConfiguration().getObjectFactory().newInstance(cld, args, null);
+            objMap.put(toCopy,retval);
+        }
+        catch (Exception e)
+        {
+            throw new ObjectCopyException("InstantiationException", e);
+        }
+
+        /**
+         * first copy all the fields
+         * fields are not mapped objects (ie ObjectReferenceDescriptors)
+         */
+        final FieldDescriptor[] fieldDescs = cld.getFieldDescriptions();
+//        final BrokerHelper brokerHelper = broker.serviceBrokerHelper();
+        for (int i = 0; i < fieldDescs.length; i++)
+        {
+            final FieldDescriptor fd = fieldDescs[i];
+            final PersistentField f = fd.getPersistentField();
+            Object fieldValue = f.get(toCopy);
+/*
+arminw:
+TODO: ensure that the autoincrement values be assigned before the copy was done
+If possible we should avoid to declare BrokerHelper#getAutoIncrementValue public and
+if we copy an object user don't expect the change of fields.
+*/
+//            // If the field is auto increment, assign its value before copying!
+//            if (fd.isAutoIncrement())
+//            {
+//                fieldValue = brokerHelper.getAutoIncrementValue(fd, toCopy, fieldValue);
+//            }
+
+            f.set(retval, fieldValue);
+        }
+
+        /**
+         * then copy all the 1:1 references
+         */
+        final Collection refDescsCol = cld.getObjectReferenceDescriptors();
+        final ObjectReferenceDescriptor[] rds = (ObjectReferenceDescriptor[]) refDescsCol.toArray(new ObjectReferenceDescriptor[refDescsCol.size()]);
+        for (int i = 0; i < rds.length; i++)
+        {
+            final ObjectReferenceDescriptor rd = rds[i];
+            final PersistentField f = rd.getPersistentField();
+            /**
+             * recursively copy the referenced objects
+             * register in the objMap first
+             */
+            final Object object = f.get(toCopy);
+            final Object clone = clone(object, objMap, broker);
+            objMap.put(object, clone);
+            f.set(retval, clone);
+        }
+        /**
+         * then copy all the 1:M and M:N references
+         */
+        final Collection colDescsCol = cld.getCollectionDescriptors();
+        final Iterator it = colDescsCol.iterator();
+        while (it.hasNext())
+        {
+            final CollectionDescriptor cd = (CollectionDescriptor) it.next();
+            final PersistentField f = cd.getPersistentField();
+            final Object collection = f.get(toCopy);
+            /**
+             * handle collection proxies where the entire Collection is a big proxy
+             * (vs all the elements in the collection are proxies
+             */
+            if (collection == null)
+            {
+                f.set(retval, null);
+            }
+            else if (collection instanceof CollectionProxy)
+            {
+                f.set(retval, _reflective.copy(collection, null));
+            }
+            else if (collection instanceof Collection)
+            {
+                try
+                {
+                    final Collection newCollection = (Collection) collection.getClass().newInstance();
+                    final Iterator tempIter = ((Collection) collection).iterator();
+                    Object obj;
+                    while (tempIter.hasNext())
+                    {
+                        obj = tempIter.next();
+                        /**
+                        * if this is a proxy, just copy the proxy, don't materialize it, and stop recursing
+                        */
+                        if (proxyFactory.isNormalOjbProxy(obj))  // tomdz: what about VirtualProxy ?
+                        {
+                            newCollection.add(obj);
+                        }
+                        else
+                        {
+                            final Object clone = clone(obj, objMap, broker);
+                            objMap.put(obj, clone);
+                            newCollection.add(clone);
+                        }
+                    }
+                    f.set(retval, newCollection);
+                }
+                catch (InstantiationException e)
+                {
+                    throw new ObjectCopyException("InstantiationException", e);
+                }
+                catch (IllegalAccessException e)
+                {
+                    throw new ObjectCopyException("IllegalAccessException", e);
+                }
+            }
+            else
+            {
+                throw new java.lang.UnsupportedOperationException("MetadataObjectCopyStrategy cannot handle Collection of type: " + collection.getClass().getName());
+            }
+        }
+        return retval;
+    }
+}

Added: db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/NoOpObjectCopyStrategy.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/NoOpObjectCopyStrategy.java?rev=428990&view=auto
==============================================================================
--- db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/NoOpObjectCopyStrategy.java (added)
+++ db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/NoOpObjectCopyStrategy.java Sat Aug  5 05:18:12 2006
@@ -0,0 +1,42 @@
+package org.apache.ojb.otm.copy;
+
+
+/* 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 org.apache.ojb.broker.PersistenceBroker;
+
+/**
+ * The NoOpObjectCopyStrategy does not make a copy. It merely returns the same object.
+ *
+ * For backwards compatability with OJB 0.9, we include a way to no-op copy
+ * the object into the transactional context. This means that we are operating
+ * on a live object, and can potentially mess stuff up. This is essentially
+ * supporting a uncommitted-read only strategy.
+ *
+ * @author matthew.baird
+ */
+public class NoOpObjectCopyStrategy implements ObjectCopyStrategy
+{
+	/**
+	 * @see org.apache.ojb.otm.copy.ObjectCopyStrategy#copy(Object)
+	 *
+	 */
+	public Object copy(Object obj, PersistenceBroker broker)
+			throws ObjectCopyException
+	{
+		return obj;
+	}
+}

Added: db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/ObjectCopyException.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/ObjectCopyException.java?rev=428990&view=auto
==============================================================================
--- db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/ObjectCopyException.java (added)
+++ db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/ObjectCopyException.java Sat Aug  5 05:18:12 2006
@@ -0,0 +1,58 @@
+package org.apache.ojb.otm.copy;
+
+import org.apache.ojb.otm.core.OTMGenericException;
+
+/* 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.
+ */
+public class ObjectCopyException extends OTMGenericException
+{
+
+	/**
+	 * Constructor for ObjectCopyException.
+	 */
+	public ObjectCopyException()
+	{
+		super();
+	}
+
+	/**
+	 * Constructor for ObjectCopyException.
+	 * @param msg
+	 */
+	public ObjectCopyException(String msg)
+	{
+		super(msg);
+	}
+
+	/**
+	 * Constructor for ObjectCopyException.
+	 * @param cause
+	 */
+	public ObjectCopyException(Throwable cause)
+	{
+		super(cause);
+	}
+
+	/**
+	 * Constructor for ObjectCopyException.
+	 * @param msg
+	 * @param cause
+	 */
+	public ObjectCopyException(String msg, Throwable cause)
+	{
+		super(msg, cause);
+	}
+
+}

Added: db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/ObjectCopyStrategy.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/ObjectCopyStrategy.java?rev=428990&view=auto
==============================================================================
--- db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/ObjectCopyStrategy.java (added)
+++ db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/ObjectCopyStrategy.java Sat Aug  5 05:18:12 2006
@@ -0,0 +1,33 @@
+package org.apache.ojb.otm.copy;
+
+
+/* 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 org.apache.ojb.broker.PersistenceBroker;
+
+public interface ObjectCopyStrategy
+{
+
+    /**
+     *
+     * Make a copy of the given object
+     *
+     * @param obj object to be copied
+     * @return Object the copy of the object
+     */
+    public Object copy(Object obj, PersistenceBroker broker);
+
+}

Added: db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/OjbCloneable.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/OjbCloneable.java?rev=428990&view=auto
==============================================================================
--- db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/OjbCloneable.java (added)
+++ db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/OjbCloneable.java Sat Aug  5 05:18:12 2006
@@ -0,0 +1,28 @@
+package org.apache.ojb.otm.copy;
+
+/* 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.
+ */
+
+/**
+ * @author matthew.baird
+ */
+
+public interface OjbCloneable
+{
+	/**
+	 * Probably just a delegation to the clone() method of object.
+	 */
+	Object ojbClone();
+}

Added: db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/ReflectiveObjectCopyStrategy.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/ReflectiveObjectCopyStrategy.java?rev=428990&view=auto
==============================================================================
--- db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/ReflectiveObjectCopyStrategy.java (added)
+++ db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/ReflectiveObjectCopyStrategy.java Sat Aug  5 05:18:12 2006
@@ -0,0 +1,297 @@
+package org.apache.ojb.otm.copy;
+
+/* 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.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ojb.broker.PersistenceBroker;
+import org.apache.ojb.broker.util.IdentityMapFactory;
+
+/**
+ * User: matthew.baird
+ * Date: Jul 7, 2003
+ * Time: 3:05:22 PM
+ */
+public final class ReflectiveObjectCopyStrategy implements ObjectCopyStrategy
+{
+	private static final Set FINAL_IMMUTABLE_CLASSES;
+	private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
+	private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
+    private static final SerializeObjectCopyStrategy _serialize = new SerializeObjectCopyStrategy();
+
+	static
+	{
+		FINAL_IMMUTABLE_CLASSES = new HashSet(17);
+		FINAL_IMMUTABLE_CLASSES.add(String.class);
+		FINAL_IMMUTABLE_CLASSES.add(Byte.class);
+		FINAL_IMMUTABLE_CLASSES.add(Short.class);
+		FINAL_IMMUTABLE_CLASSES.add(Integer.class);
+		FINAL_IMMUTABLE_CLASSES.add(Long.class);
+		FINAL_IMMUTABLE_CLASSES.add(Float.class);
+		FINAL_IMMUTABLE_CLASSES.add(Double.class);
+		FINAL_IMMUTABLE_CLASSES.add(Character.class);
+		FINAL_IMMUTABLE_CLASSES.add(Boolean.class);
+	}
+
+	/**
+	 * makes a deep clone of the object, using reflection.
+	 * @param toCopy the object you want to copy
+	 * @return
+	 */
+	public final Object copy(final Object toCopy, PersistenceBroker broker)
+	{
+		return clone(toCopy, IdentityMapFactory.getIdentityMap(), new HashMap());
+	}
+
+	/*
+	 * class used to cache class metadata info
+	 */
+	private static final class ClassMetadata
+	{
+		Constructor m_noArgConstructor;
+		Field[] m_declaredFields;
+		boolean m_noArgConstructorAccessible;
+		boolean m_fieldsAccessible;
+		boolean m_hasNoArgConstructor = true;
+	}
+
+	private static Object clone(final Object toCopy, final Map objMap, final Map metadataMap)
+	{
+		/**
+		 * first, check to make sure we aren't recursing to some object that we've already copied.
+		 * if the toCopy is in the objMap, just return it.
+		 */
+		if (objMap.containsKey(toCopy)) return objMap.get(toCopy);
+		final Class objClass = toCopy.getClass();
+		final Object retval;
+		if (objClass.isArray())
+		{
+			retval = handleArray(toCopy, objMap, objClass, metadataMap);
+		}
+		else if (FINAL_IMMUTABLE_CLASSES.contains(objClass))
+		{
+			objMap.put(toCopy, toCopy);
+			retval = toCopy;
+		}
+		else
+		{
+			retval = handleObjectWithNoArgsConstructor(metadataMap, objClass, objMap, toCopy);
+		}
+		return retval;
+	}
+
+	private static Object handleObjectWithNoArgsConstructor(final Map metadataMap, final Class objClass, final Map objMap, final Object toCopy)
+	{
+		Object retval = null;
+		ClassMetadata metadata = (ClassMetadata) metadataMap.get(objClass);
+		if (metadata == null)
+		{
+			metadata = new ClassMetadata();
+			metadataMap.put(objClass, metadata);
+		}
+		Constructor noArg = metadata.m_noArgConstructor;
+		if (metadata.m_hasNoArgConstructor)
+		{
+			if (noArg == null)
+			{
+				try
+				{
+					noArg = objClass.getDeclaredConstructor(EMPTY_CLASS_ARRAY);
+					metadata.m_noArgConstructor = noArg;
+				}
+				catch (Exception e)
+				{
+					metadata.m_hasNoArgConstructor = false;
+	//				throw new ObjectCopyException("class [" + objClass.getName() + "] has no noArg constructor: " + e.toString(), e);
+				}
+			}
+		}
+		if (metadata.m_hasNoArgConstructor)
+		{
+			if (!metadata.m_noArgConstructorAccessible && (Modifier.PUBLIC & noArg.getModifiers()) == 0)
+			{
+				try
+				{
+					noArg.setAccessible(true);
+				}
+				catch (SecurityException e)
+				{
+					throw new ObjectCopyException("cannot access noArg constructor [" + noArg + "] of class [" + objClass.getName() + "]: " + e.toString(), e);
+				}
+				metadata.m_noArgConstructorAccessible = true;
+			}
+			try
+			{
+				/**
+				 * create the return value via the default no argument constructor
+				 */
+				retval = noArg.newInstance(EMPTY_OBJECT_ARRAY);
+				objMap.put(toCopy, retval);
+			}
+			catch (Exception e)
+			{
+				throw new ObjectCopyException("cannot instantiate class [" + objClass.getName() + "] using noArg constructor: " + e.toString(), e);
+			}
+			for (Class c = objClass; c != Object.class; c = c.getSuperclass())
+			{
+				copyClass(metadataMap, c, toCopy, retval, objMap);
+			}
+		}
+        else
+        {
+            retval = _serialize.copy(toCopy, null);
+        }
+		return retval;
+	}
+
+	private static void copyClass(final Map metadataMap, final Class c, final Object obj, final Object retval, final Map objMap)
+	{
+		ClassMetadata metadata;
+		metadata = (ClassMetadata) metadataMap.get(c);
+		if (metadata == null)
+		{
+			metadata = new ClassMetadata();
+			metadataMap.put(c, metadata);
+		}
+		Field[] declaredFields = metadata.m_declaredFields;
+		if (declaredFields == null)
+		{
+			declaredFields = c.getDeclaredFields();
+			metadata.m_declaredFields = declaredFields;
+		}
+		setFields(obj, retval, declaredFields, metadata.m_fieldsAccessible, objMap, metadataMap);
+		metadata.m_fieldsAccessible = true;
+	}
+
+	private static Object handleArray(final Object obj, final Map objMap, final Class objClass, final Map metadataMap)
+	{
+		final Object retval;
+		final int arrayLength = Array.getLength(obj);
+		/**
+		 * immutable
+		 */
+		if (arrayLength == 0)
+		{
+			objMap.put(obj, obj);
+			retval = obj;
+		}
+		else
+		{
+			final Class componentType = objClass.getComponentType();
+			/**
+			 * even though arrays implicitly have a public clone(), it
+			 * cannot be invoked reflectively, so need to do copy construction
+			 */
+			retval = Array.newInstance(componentType, arrayLength);
+			objMap.put(obj, retval);
+			if (componentType.isPrimitive() || FINAL_IMMUTABLE_CLASSES.contains(componentType))
+			{
+				System.arraycopy(obj, 0, retval, 0, arrayLength);
+			}
+			else
+			{
+				for (int i = 0; i < arrayLength; ++i)
+				{
+					/**
+					 * recursively clone each array slot:
+					 */
+					final Object slot = Array.get(obj, i);
+					if (slot != null)
+					{
+						final Object slotClone = clone(slot, objMap, metadataMap);
+						Array.set(retval, i, slotClone);
+					}
+				}
+			}
+		}
+		return retval;
+	}
+
+	/**
+	 * copy all fields from the "from" object to the "to" object.
+	 *
+	 * @param from source object
+	 * @param to from's clone
+	 * @param fields fields to be populated
+	 * @param accessible 'true' if all 'fields' have been made accessible during
+	 * traversal
+	 */
+	private static void setFields(final Object from, final Object to,
+	                              final Field[] fields, final boolean accessible,
+	                              final Map objMap, final Map metadataMap)
+	{
+		for (int f = 0, fieldsLength = fields.length; f < fieldsLength; ++f)
+		{
+			final Field field = fields[f];
+			final int modifiers = field.getModifiers();
+			if ((Modifier.STATIC & modifiers) != 0) continue;
+			if ((Modifier.FINAL & modifiers) != 0)
+				throw new ObjectCopyException("cannot set final field [" + field.getName() + "] of class [" + from.getClass().getName() + "]");
+			if (!accessible && ((Modifier.PUBLIC & modifiers) == 0))
+			{
+				try
+				{
+					field.setAccessible(true);
+				}
+				catch (SecurityException e)
+				{
+					throw new ObjectCopyException("cannot access field [" + field.getName() + "] of class [" + from.getClass().getName() + "]: " + e.toString(), e);
+				}
+			}
+			try
+			{
+				cloneAndSetFieldValue(field, from, to, objMap, metadataMap);
+			}
+			catch (Exception e)
+			{
+				throw new ObjectCopyException("cannot set field [" + field.getName() + "] of class [" + from.getClass().getName() + "]: " + e.toString(), e);
+			}
+		}
+	}
+
+	private static void cloneAndSetFieldValue(final Field field, final Object src, final Object dest, final Map objMap, final Map metadataMap) throws IllegalAccessException
+	{
+		Object value = field.get(src);
+		if (value == null)
+		{
+			/**
+			 *  null is a valid type, ie the object may initialize this field to a different value,
+			 * so we must explicitely set all null fields.
+			 */
+			field.set(dest, null);
+		}
+		else
+		{
+			final Class valueType = value.getClass();
+			if (!valueType.isPrimitive() && !FINAL_IMMUTABLE_CLASSES.contains(valueType))
+			{
+				/**
+				 * recursively call clone on value as it could be an object reference, an array,
+				 * or some mutable type
+				 */
+				value = clone(value, objMap, metadataMap);
+			}
+			field.set(dest, value);
+		}
+	}
+}

Added: db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/SerializeObjectCopyStrategy.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/SerializeObjectCopyStrategy.java?rev=428990&view=auto
==============================================================================
--- db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/SerializeObjectCopyStrategy.java (added)
+++ db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/copy/SerializeObjectCopyStrategy.java Sat Aug  5 05:18:12 2006
@@ -0,0 +1,75 @@
+package org.apache.ojb.otm.copy;
+
+/* 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.io.*;
+import org.apache.ojb.broker.PersistenceBroker;
+
+/**
+ * Does in-memory serialization to achieve a copy of the object graph.
+ *
+ * @author matthew.baird
+ * @see ObjectCopyStrategy
+ */
+public final class SerializeObjectCopyStrategy implements ObjectCopyStrategy
+{
+	/**
+	 * This implementation will probably be slower than the metadata
+	 * object copy, but this was easier to implement.
+	 * @see org.apache.ojb.otm.copy.ObjectCopyStrategy#copy(Object)
+	 */
+	public Object copy(final Object obj, PersistenceBroker broker)
+			throws ObjectCopyException
+	{
+		ObjectOutputStream oos = null;
+		ObjectInputStream ois = null;
+		try
+		{
+			final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+			oos = new ObjectOutputStream(bos);
+			// serialize and pass the object
+			oos.writeObject(obj);
+			oos.flush();
+			final ByteArrayInputStream bin =
+					new ByteArrayInputStream(bos.toByteArray());
+			ois = new ObjectInputStream(bin);
+			// return the new object
+			return ois.readObject();
+		}
+		catch (Exception e)
+		{
+			throw new ObjectCopyException(e);
+		}
+		finally
+		{
+			try
+			{
+				if (oos != null)
+				{
+					oos.close();
+				}
+				if (ois != null)
+				{
+					ois.close();
+				}
+			}
+			catch (IOException ioe)
+			{
+				// ignore
+			}
+		}
+	}
+}

Added: db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/core/BaseConnection.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/core/BaseConnection.java?rev=428990&view=auto
==============================================================================
--- db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/core/BaseConnection.java (added)
+++ db/ojb/trunk/proposals/otm/java/org/apache/ojb/otm/core/BaseConnection.java Sat Aug  5 05:18:12 2006
@@ -0,0 +1,701 @@
+package org.apache.ojb.otm.core;
+
+/* 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.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.ListIterator;
+
+import org.apache.ojb.broker.Identity;
+import org.apache.ojb.broker.PersistenceBroker;
+import org.apache.ojb.broker.PersistenceBrokerException;
+import org.apache.ojb.broker.PersistenceBrokerInternal;
+import org.apache.ojb.broker.PersistenceConfiguration;
+import org.apache.ojb.broker.accesslayer.OJBIterator;
+import org.apache.ojb.broker.cache.ObjectCache;
+import org.apache.ojb.broker.metadata.ClassDescriptor;
+import org.apache.ojb.broker.query.Query;
+import org.apache.ojb.broker.query.ReportQuery;
+import org.apache.ojb.odmg.collections.DListImpl;
+import org.apache.ojb.odmg.oql.EnhancedOQLQuery;
+import org.apache.ojb.odmg.oql.OQLQueryImpl;
+import org.apache.ojb.otm.EditingContext;
+import org.apache.ojb.otm.OTMConnection;
+import org.apache.ojb.otm.copy.ObjectCopyStrategy;
+import org.apache.ojb.otm.lock.LockType;
+import org.apache.ojb.otm.lock.LockingException;
+import org.odmg.OQLQuery;
+
+/**
+ *
+ * <javadoc>
+ *
+ * @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird </a>
+ * @author <a href="mailto:rraghuram@hotmail.com">Raghu Rajah </a>
+ * @version $Id: BaseConnection.java 364932 2005-08-27 14:29:03 +0200 (Sa, 27 Aug 2005) arminw $
+ *
+ */
+public abstract class BaseConnection implements OTMConnection
+{
+
+    private PersistenceBrokerInternal _pb;
+    private Transaction _tx;
+    private ConcreteEditingContext _editingContext;
+
+    /**
+     * Constructor for BaseConnection.
+     *
+     */
+    public BaseConnection(PersistenceConfiguration persistenceConf)
+    {
+        _pb = (PersistenceBrokerInternal)persistenceConf.createPersistenceBroker();
+    }
+
+    public void close()
+    {
+        _pb.close();
+        _pb = null;
+    }
+
+    public boolean isClosed()
+    {
+        if (_pb == null)
+            return true;
+        else
+            return _pb.isClosed();
+    }
+
+    public PersistenceBroker getKernelBroker()
+    {
+        return _pb;
+    }
+
+    public void setTransaction(Transaction transaction)
+    {
+        if (transaction == null)
+        {
+            _editingContext = null;
+        }
+        else if (_tx != null)
+        {
+            throw new IllegalStateException("OTMConnection is already bound to the transacaction "
+                    + _tx);
+        }
+        else
+        {
+            _editingContext = new ConcreteEditingContext(transaction, _pb);
+        }
+        _tx = transaction;
+    }
+
+    public Transaction getTransaction()
+    {
+        return _tx;
+    }
+
+    //////////////////////////////////////
+    // OTMConnection protocol
+    //////////////////////////////////////
+
+    /**
+     * @see org.apache.ojb.otm.OTMConnection#getObjectByIdentity(Identity, int)
+     */
+    public Object getObjectByIdentity(Identity oid, int lock) throws LockingException
+    {
+        checkTransaction("getObjectByIdentity");
+        Object userObject;
+        Object cacheObject;
+
+        cacheObject = _pb.getObjectByIdentity(oid);
+        if (cacheObject == null)
+        {
+            // Possibly the object was inserted in this transaction
+            // and was not stored to database yet
+            userObject = _editingContext.lookup(oid);
+        }
+        else
+        {
+            userObject = getUserObject(oid, cacheObject);
+            // userObject from editing context may be proxy
+            userObject = _pb.getProxyFactory().getRealObject(userObject);
+            _editingContext.insert(oid, userObject, lock);
+        }
+        return userObject;
+    }
+
+    private void checkTransaction(String methodBeingCalled)
+    {
+        if (null == _tx)
+        {
+            throw new TransactionNotInProgressException(
+                    methodBeingCalled
+                            + " requires a valid transaction. Please make sure you have created a new transaction, and called begin() on it.");
+        }
+        if (!_tx.isInProgress())
+        {
+            throw new TransactionNotInProgressException(methodBeingCalled
+                    + " cannot be called before transaction begin() is called");
+        }
+    }
+
+    /**
+     * @see org.apache.ojb.otm.OTMConnection#getObjectByIdentity(Identity)
+     */
+    public Object getObjectByIdentity(Identity oid) throws LockingException
+    {
+        return getObjectByIdentity(oid, LockType.READ_LOCK);
+    }
+
+    /**
+     * @param query The query to execute
+     * @return an Iterator that iterates Objects. The returned objects are locked for read.
+     */
+    public Iterator getIteratorByQuery(Query query)
+    {
+        return getIteratorByQuery(query, LockType.READ_LOCK);
+    }
+
+    /**
+     * @param query The query to execute
+     * @param lock the lock that need to be acquired on the object Possible values are:
+     *            LockType.NO_LOCK (aka read only) - changes to the object will not be written to
+     *            database; LockType.READ_LOCK (aka optimistic lock) - changes to the object will
+     *            be written to the database, in this case the lock will be automatically upgraded
+     *            to the write lock on transaction commit; LockType.WRITE_LOCK (aka pessimistic
+     *            lock) - changes to the object will be written to the database.
+     * @return an Iterator that iterates Objects of class c if calling the .next() method. The
+     *         returned objects are locked with the given lock value.
+     */
+    public Iterator getIteratorByQuery(Query query, int lock)
+    {
+        checkTransaction("getIteratorByQuery");
+        return new OTMIterator( _pb.getIteratorByQuery(query), lock, null);
+    }
+
+    /**
+     * @param query The OQL query to execute. Use this method if you don't want to load all the
+     *            collection at once as OQLQuery.execute() does.
+     * @return an Iterator that iterates Objects. The returned objects are locked for read.
+     */
+    public Iterator getIteratorByOQLQuery(OQLQuery query)
+    {
+        return getIteratorByOQLQuery(query, LockType.READ_LOCK);
+    }
+
+    /**
+     * @param query The OQL query to execute. Use this method if you don't want to load all the
+     *            collection at once as OQLQuery.execute() does.
+     * @return an Iterator that iterates Objects. The returned objects are locked for read.
+     */
+    public Iterator getIteratorByOQLQuery(OQLQuery query, int lock)
+    {
+        checkTransaction("getIteratorByOQLQuery");
+        if (query instanceof OTMOQLQueryImpl)
+        {
+            OTMOQLQueryImpl q = (OTMOQLQueryImpl) query;
+            return new OTMIterator(_pb.getIteratorByQuery(q.getQuery()), lock, q);
+        }
+        else
+        {
+            throw new IllegalArgumentException("The OQLQuery where created not via OTM API");
+        }
+    }
+
+    /**
+     * @param query The query to execute
+     * @param lock the lock that need to be acquired on the object Possible values are:
+     *            LockType.NO_LOCK (aka read only) - changes to the object will not be written to
+     *            database; LockType.READ_LOCK (aka optimistic lock) - changes to the object will
+     *            be written to the database, in this case the lock will be automatically upgraded
+     *            to the write lock on transaction commit; LockType.WRITE_LOCK (aka pessimistic
+     *            lock) - changes to the object will be written to the database.
+     * @return an Iterator that iterates Objects of class c if calling the .next() method. The
+     *         returned objects are locked with the given lock value.
+     */
+    public Collection getCollectionByQuery(Query query, int lock)
+    {
+        checkTransaction("getCollectionByQuery");
+        Collection col = _pb.getCollectionByQuery(query);
+        Collection result = createCollectionOfTheSameClass(col);
+        for (Iterator it = col.iterator(); it.hasNext();)
+        {
+            result.add(insertObject(it.next(), lock));
+        }
+        return result;
+    }
+
+    /**
+     * @param query The query to execute
+     * @return an Iterator that iterates Objects of class c if calling the .next() method. The
+     *         returned objects are locked for read.
+     */
+    public Collection getCollectionByQuery(Query query)
+    {
+        return getCollectionByQuery(query, LockType.READ_LOCK);
+    }
+
+    /**
+     * Get the identity of the object
+     *
+     * @param object The object
+     * @return the identity of the object
+     */
+    public Identity getIdentity(Object object)
+    {
+        return new Identity(object, _pb);
+    }
+
+    /**
+     * Get the class descriptor
+     *
+     * @param clazz The class
+     * @return the descriptor of the class
+     */
+    public ClassDescriptor getDescriptorFor(Class clazz)
+    {
+        return _pb.getClassDescriptor(clazz);
+    }
+
+    /**
+     * @see org.apache.ojb.otm.OTMConnection#invalidate(Identity)
+     */
+    public void invalidate(Identity oid) throws LockingException
+    {
+        if (null == _tx)
+        {
+            throw new TransactionNotInProgressException(
+                    "invalidate requires a valid transaction. Please make sure you have created a new transaction, and called begin() on it.");
+        }
+        // mark as invalidated in the editing context, if it's found there
+        _editingContext.insert(oid, null, LockType.READ_LOCK);
+
+        // remove from the cache
+        _pb.serviceObjectCache().remove(oid);
+
+    }
+
+    /**
+     * @see org.apache.ojb.otm.OTMConnection#serviceObjectCache()
+     */
+    public ObjectCache serviceObjectCache()
+    {
+        return _pb.serviceObjectCache();
+    }
+
+    /**
+     * TODO remove all from editing context.
+     *
+     * @throws LockingException
+     */
+    public void invalidateAll() throws LockingException
+    {
+        _pb.serviceObjectCache().clear();
+    }
+
+    /**
+     * @see org.apache.ojb.otm.OTMConnection#lockForWrite(Object)
+     */
+    public void lockForWrite(Object object) throws LockingException
+    {
+        checkTransaction("lockForWrite");
+        makePersistent(object);
+    }
+
+    /**
+     * @see org.apache.ojb.otm.OTMConnection#makePersistent(Object)
+     */
+    public void makePersistent(Object userObject) throws LockingException
+    {
+        checkTransaction("makePersistent");
+        Identity oid = new Identity(userObject, _pb);
+        Object cacheObject = _pb.getObjectByIdentity(oid);
+
+        if ((cacheObject != null) && (_editingContext.lookup(oid) == null))
+        {
+            // The object exists in the database, but is not yet in the editing
+            // context, so we need to put it to the editing context in its
+            // old state, then we will put the modified userObject.
+            // This will allow the editing context to find changes
+            ObjectCopyStrategy copyStrategy = _tx.getKit().getCopyStrategy(oid);
+            Object origUserObject = copyStrategy.copy(cacheObject, _pb);
+            _editingContext.insert(oid, origUserObject, LockType.WRITE_LOCK);
+        }
+        _editingContext.insert(oid, userObject, LockType.WRITE_LOCK);
+    }
+
+    /**
+     * @see org.apache.ojb.otm.OTMConnection#deletePersistent(Object)
+     */
+    public void deletePersistent(Object userObject) throws LockingException
+    {
+        checkTransaction("deletePersistent");
+        Identity oid = new Identity(userObject, _pb);
+        Object cacheObject = _pb.getObjectByIdentity(oid);
+        if (cacheObject == null)
+        {
+            // Possibly the object was inserted in this transaction
+            // and was not stored to database yet, so we simply remove it
+            // from editing context.
+            _editingContext.remove(oid);
+        }
+        else
+        {
+            if (_editingContext.lookup(oid) == null)
+            {
+                // The object exists in the database, but is not yet in the editing
+                // context, so we need to put it to the editing context
+                ObjectCopyStrategy copyStrategy = _tx.getKit().getCopyStrategy(oid);
+                Object origUserObject = copyStrategy.copy(cacheObject, _pb);
+                _editingContext.insert(oid, origUserObject, LockType.WRITE_LOCK);
+            }
+            _editingContext.deletePersistent(oid, userObject);
+        }
+    }
+
+    /**
+     * @see org.apache.ojb.otm.OTMConnection#refresh(Object)
+     */
+    public void refresh(Object userObject)
+    {
+        checkTransaction("refresh");
+        Identity oid = new Identity(userObject, _pb);
+        _editingContext.refresh(oid, userObject);
+    }
+
+    public EditingContext getEditingContext()
+    {
+        return _editingContext;
+    }
+
+    public EnhancedOQLQuery newOQLQuery()
+    {
+        return newOQLQuery(LockType.READ_LOCK);
+    }
+
+    public EnhancedOQLQuery newOQLQuery(int lock)
+    {
+        checkTransaction("newOQLQuery");
+
+        // TODO: How do we get the oqlCollectionClass value
+        return new OTMOQLQueryImpl(_pb.getConfiguration(), DListImpl.class, lock);
+    }
+
+    public int getCount(Query query)
+    {
+        checkTransaction("getCount");
+        return _pb.getCount(query);
+    }
+
+    private Object insertObject(Object cacheObject, int lock)
+    {
+        Object ctxObject;
+        Identity oid;
+        Object userObject;
+
+
+        oid = getIdentity(cacheObject);
+        userObject = getUserObject(oid, cacheObject);
+        try
+        {
+            _editingContext.insert(oid, userObject, lock);
+        }
+        catch (LockingException ex)
+        {
+            throw new LockingPassthruException(ex);
+        }
+
+        return userObject;
+    }
+
+    /**
+     * Get user object (from the editing context) with the given oid.
+     * If not found, then create it as a copy of cacheObject.
+     * User object and cache object must be separate.
+     * @param oid The identity
+     * @param cacheObject the object for user
+     */
+    private Object getUserObject(Identity oid, Object cacheObject)
+    {
+        Object userObject = _editingContext.lookup(oid);
+
+        if (userObject == null)
+        {
+            ObjectCopyStrategy copyStrategy = _tx.getKit().getCopyStrategy(oid);
+            userObject = copyStrategy.copy(cacheObject, _pb);
+        }
+        return userObject;
+    }
+
+    private Collection createCollectionOfTheSameClass(Collection col)
+    {
+        try
+        {
+            return (Collection) col.getClass().newInstance();
+        }
+        catch (Throwable ex)
+        {
+            return new ArrayList();
+        }
+    }
+
+    ///////////////////////////////////////
+    // Transaction Notifications
+    ///////////////////////////////////////
+
+    /**
+     *
+     * Notification issued by the driving transaction to begin this transaction
+     *
+     */
+    public abstract void transactionBegin() throws TransactionException;
+
+    /**
+     *
+     * Prepare for a commit. As part of a two phase commit protocol of the transaction.
+     *
+     */
+    public abstract void transactionPrepare() throws TransactionException;
+
+    /**
+     *
+     * Notification issued by the driving transaction to commit resources held by this connection.
+     *
+     */
+    public abstract void transactionCommit() throws TransactionException;
+
+    /**
+     *
+     * Notification issued by the driving transaction to rollback resources held by this
+     * connection.
+     *
+     */
+    public abstract void transactionRollback() throws TransactionException;
+
+    ///////////////////////////////////////
+    // Inner classes
+    ///////////////////////////////////////
+
+    private class OTMIterator implements OJBIterator
+    {
+        private final OJBIterator _it;
+        private final int _lock;
+        private final OTMOQLQueryImpl _oqlQuery;
+
+        OTMIterator(OJBIterator it, int lock, OTMOQLQueryImpl oqlQuery)
+        {
+            _it = it;
+            _lock = lock;
+            _oqlQuery = oqlQuery;
+        }
+
+        public void setAutoRelease(boolean autoRelease)
+        {
+            _it.setAutoRelease(autoRelease);
+        }
+
+        public boolean hasNext()
+        {
+            boolean res = _it.hasNext();
+
+            // once the result set is finished, close it
+            if (!res)
+            {
+                done();
+            }
+
+            return res;
+        }
+
+        public Object next()
+        {
+            Object object = _it.next();
+            object = insertObject(object, _lock);
+            return object;
+        }
+
+        public void remove()
+        {
+            throw new UnsupportedOperationException();
+        }
+
+        public void done()
+        {
+            releaseDbResources();
+            if (_oqlQuery != null)
+            {
+                _oqlQuery.resetBindIterator();
+            }
+        }
+
+        protected void finalize()
+        {
+            done();
+        }
+
+        /**
+         * @see org.apache.ojb.broker.accesslayer.OJBIterator#absolute(int)
+         */
+        public boolean absolute(int row) throws PersistenceBrokerException
+        {
+            return _it.absolute(row);
+        }
+
+        /**
+         * @see org.apache.ojb.broker.accesslayer.OJBIterator#fullSize()
+         */
+        public int fullSize() throws PersistenceBrokerException
+        {
+            return _it.fullSize();
+        }
+
+        /**
+         * @see org.apache.ojb.broker.accesslayer.OJBIterator#relative(int)
+         */
+        public boolean relative(int row) throws PersistenceBrokerException
+        {
+            return _it.relative(row);
+        }
+
+        /**
+         * @see org.apache.ojb.broker.accesslayer.OJBIterator#releaseDbResources()
+         */
+        public void releaseDbResources()
+        {
+            _it.releaseDbResources();
+        }
+
+        public boolean isClosed()
+        {
+            return _it.isClosed();
+        }
+
+        /**
+         * @see org.apache.ojb.broker.accesslayer.OJBIterator#size()
+         */
+        public int size() throws PersistenceBrokerException
+        {
+            return _it.size();
+        }
+
+        /**
+         * @see org.apache.ojb.broker.accesslayer.OJBIterator#disableLifeCycleEvents()
+         */
+        public void disableLifeCycleEvents()
+        {
+            _it.disableLifeCycleEvents();
+    }
+
+    }
+
+    private class OTMOQLQueryImpl extends OQLQueryImpl
+    {
+        int _lock;
+        Class collectionClass;
+
+        public OTMOQLQueryImpl(PersistenceConfiguration persistenceConf, Class collectionClass, int lock)
+        {
+            // no transaction manager because we override the execute method anyway
+            super(null);
+            this.collectionClass = collectionClass;
+            _lock = lock;
+        }
+
+        public Class getCollectionClass()
+        {
+            return this.collectionClass;
+        }
+
+        /**
+         * Execute the query. After executing a query, the parameter list is reset.
+         *
+         * @return The object that represents the result of the query. The returned data, whatever
+         *         its OQL type, is encapsulated into an object. For instance, when OQL returns an
+         *         integer, the result is put into an <code>Integer</code> object. When OQL
+         *         returns a collection (literal or object), the result is always a Java collection
+         *         object of the same kind (for instance, a <code>DList</code>).
+         * @exception org.odmg.QueryException An exception has occurred while executing the query.
+         */
+        public Object execute() throws org.odmg.QueryException
+        {
+            Collection result;
+            Iterator iter = null;
+            Query query = getQuery();
+
+            try
+            {
+                if (!(query instanceof ReportQuery))
+                {
+                    Collection res0 = _pb.getCollectionByQuery(query);
+                    result = createCollectionOfTheSameClass(res0);
+                    for (iter = res0.iterator(); iter.hasNext();)
+                    {
+                        result.add(insertObject(iter.next(), _lock));
+                    }
+                }
+                else
+                {
+                    result = new ArrayList();
+                    iter = _pb.getReportQueryIteratorByQuery(query);
+                    while (iter.hasNext())
+                    {
+                        Object[] res = (Object[]) iter.next();
+
+                        if (res.length == 1)
+                        {
+                            if (res[0] != null) // skip null values
+                            {
+                                result.add(res[0]);
+                            }
+                        }
+                        else
+                        {
+                            // skip null tuples
+                            for (int i = 0; i < res.length; i++)
+                            {
+                                if (res[i] != null)
+                                {
+                                    result.add(res);
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+                resetBindIterator();
+            }
+            finally
+            {
+                if ((iter != null) && (iter instanceof OJBIterator))
+                {
+                    ((OJBIterator) iter).releaseDbResources();
+                }
+            }
+            return result;
+        }
+
+        void resetBindIterator()
+        {
+            // reset iterator to start of list so we can reuse this query
+            ListIterator it = getBindIterator();
+            while (it.hasPrevious())
+            {
+                it.previous();
+            }
+        }
+    }
+
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org